I have a line plot and 2 hlines, all using different colors, and I'm filling the areas where the main line crosses the hlines with the color of the hline. In addition to that, I'd like to use the same color for the main line in those areas. In a nutshell, current output:
Desired output:
And the relevant code I'm currently using:
lower, upper = 20, 80
self.indicatorPlot.axhline(lower, color="red")
self.indicatorPlot.axhline(upper, color="green")
self.indicatorPlot.plot(self.chartTimes, self.indicatorData, color="blue")
self.indicatorPlot.fill_between(self.chartTimes, self.indicatorData, lower, where=(self.indicatorData <= lower), facecolor="red", interpolate=True)
self.indicatorPlot.fill_between(self.chartTimes, self.indicatorData, upper, where=(self.indicatorData >= upper), facecolor="green", interpolate=True)
In principle you may split up your plot into three parts, the values above upper
, the values below lower
and the values in the middle. In that sense this question has already been asked and answered, e.g.
Those solutions work great if your point density is high enough, such that the lines end up close enough to the threshold line.
In the case where you have larger gaps they are probably not well suited. I will hence give a solution here, which interpolates the gaps such that the lines end exactly at the threshold line.
import numpy as np; np.random.seed(43)
import matplotlib.pyplot as plt
t = np.linspace(0,100,301)
x = np.cumsum(np.random.randn(len(t)))
lower,upper = 0,8
fig, ax=plt.subplots()
ax.axhline(lower, color="crimson")
ax.axhline(upper, color="limegreen")
def insertzeros(t, x, zero=0):
ta = []
positive = (x-zero) > 0
ti = np.where(np.bitwise_xor(positive[1:], positive[:-1]))[0]
for i in ti:
y_ = np.sort(x[i:i+2])
z_ = t[i:i+2][np.argsort(x[i:i+2])]
t_ = np.interp(zero, y_, z_)
ta.append( t_ )
tnew = np.append( t, np.array(ta) )
xnew = np.append( x, np.ones(len(ta))*zero )
xnew = xnew[tnew.argsort()]
tnew = np.sort(tnew)
return tnew, xnew
t1,x1 = insertzeros(t,x, zero=lower)
t1,x1 = insertzeros(t1,x1, zero=upper)
xm = np.copy(x1)
xm[(x1 < lower) | (x1 > upper)] = np.nan
ax.plot(t1,xm, color="C0")
xl = np.copy(x1)
xl[(x1 > lower)] = np.nan
ax.plot(t1,xl, color="crimson")
#
xu = np.copy(x1)
xu[(xu < upper)] = np.nan
ax.plot(t1,xu, color="limegreen")
ax.fill_between(t, x, lower, where=(x <= lower), facecolor="crimson", interpolate=True, alpha=0.5)
ax.fill_between(t, x, upper, where=(x >= upper), facecolor="limegreen", interpolate=True, alpha=0.5)
plt.show()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With