Matplotlib fill_between invert?

Question:

I am trying to fill the regions below two intersecting lines and above both lines, using matplotlib. I can fill between both lines, but haven’t found a simple way to invert the region obtained previously. The only workaround I have is to created some extra functions (a low one and a min one for the bottom, and the equivalents for the top), which is a bit cumbersome and requires manual inputs (see below). Any better solutions?

Illustration

import numpy as np
import matplotlib.pyplot as plt

# Doesn't work
def f1(x): return 32.0 * x + 2.0
def f2(x): return -55.0 * x
xRng=[-1, 1]
plt.plot(xRng, [f1(x) for x in xRng], 'b-')
plt.plot(xRng, [f2(x) for x in xRng], 'r-')
plt.fill_between(xRng, [f1(x) for x in xRng], [f2(x) for x in xRng], color='g') # Would like the fill inverted
plt.title('Not good'); plt.show()

# Works, but clumsy
def fLo(x): return -100
def fHi(x): return 100
def fMin(x): return min(f1(x), f2(x))
def fMax(x): return max(f1(x), f2(x))
xRng=np.linspace(-1, 1, 100)
plt.plot(xRng, [f1(x) for x in xRng], 'b-')
plt.plot(xRng, [f2(x) for x in xRng], 'r-')
plt.fill_between(xRng, [fMin(x) for x in xRng], [fLo(x) for x in xRng], color='g')
plt.fill_between(xRng, [fMax(x) for x in xRng], [fHi(x) for x in xRng], color='g')
plt.title('Complicated'); plt.show()

EDIT: swapping BG and FG colors as suggested by @Mad Physicist will work if basic case, but not if there are several such areas to overlay

Asked By: Mister Mak

||

Answers:

It appears that fill_between does not do well with infinite values (e.g. Fill area under curve in matlibplot python on log scale). However, if you’re only trying to plot those specific lines, you could just invert the colors of the plot:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-1, 1, 100)
y1 = 32.0 * x + 2.0
y2 = -55.0 * x

fig, ax = plt.subplots()
ax.set_facecolor('g')
ax.plot(x, y1, 'b-')
ax.plot(x, y2, 'r-')
ax.fill_between(x, y1, y2, color='w')
ax.set_xlim(x.min(), x.max())
plt.show()

enter image description here

This is very hacky and won’t work well with interactive plots, but it will display the plot you want, hopefully fairly painlessly.

enter image description here

A slightly better approach might be to set the background of only the region covered by x to a green patch:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-1, 1, 100)
y1 = 32.0 * x + 2.0
y2 = -55.0 * x

fig, ax = plt.subplots()
ax.plot(x, y1, 'b-')
ax.plot(x, y2, 'r-')
ax.axvspan(x.min(), x.max(), color='g')
ax.fill_between(x, y1, y2, color='w')
ax.set_xlim(x.min(), x.max())
plt.show()

enter image description here

Answered By: Mad Physicist
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.