Matplotlib fill_between edge effect with `where` argument -


i want plot region between 2 curves different colors whether 1 of line positive or negative. got edge effect non-continuous coloring of region when curve changes of sign. setting interpolate=true not help. edge effect related resolution (voluntarily coarse in basic example below) - enhancing not want. better solution make smooth transitions? thanks.

import matplotlib.pyplot plt import numpy  plt.figure() x=numpy.arange(0.,1.05,0.05) y1=numpy.sin(2*numpy.pi*x) y2=y1+0.2 y1positive=y1>0 y1negative=y1<=0 plt.plot(x,y1,'r',label='y1') plt.plot(x,y2,'g',label='y2') plt.plot(x,x*0,'--k') plt.fill_between(x,y2,y1,where=y1positive,color='green',alpha=0.5) plt.fill_between(x,y2,y1,where=y1negative,color='red',alpha=0.5,interpolate=true) plt.legend() 

enter image description here http://i.stack.imgur.com/9q9ff.png

** edit ** based on pyhazard's answer addressing problem above, still encounter difficulties:

revised case (see code) - need fill area between 2 summed curves if have same sign, , between 1 of them , 0 otherwize. filled area must continuous when where= condition changes. including tiny margin indeed helps, not totally resolve problem (filled surface still interrupted). needed there fill_between y1=0, condition no width... need kind of condition where y1-eta<=0<=y1+eta foolishly blocked there now. idea make filled area totally continuous? thanks!

plt.figure() x=numpy.arange(0.,3.05,0.05) y1=numpy.sin(2*numpy.pi*x) y2=[2.]*len(y1) y3=[-2.]*len(y1)  eta=1e-6 y1positive=y1+eta>=0 y1negative=y1-eta<=0  plt.plot(x,x*0,'--k') plt.plot(x,y1,'.-k',label='y1') plt.plot(x,y2,'.-g',label='y2') plt.plot(x,y3,'.-r',label='y3')  plt.fill_between(x,y2+y1,y1,where=y1positive,color='green',alpha=0.5,linewidth=0) plt.fill_between(x,y2,0,where=y1negative,color='green',alpha=0.5,linewidth=0) plt.fill_between(x,y3+y1,y1,where=y1negative,color='red',alpha=0.5,linewidth=0)  plt.fill_between(x,y3,0,where=y1positive,color='red',alpha=0.5,linewidth=0)   plt.legend() 

fill_between_2

to make clearer, here original plot (with eta=0. in code above). fine there, except vertical interruptions in green , red areas. blank areas between sine curve , 0 fine. problematic vertical interruptions come definition of filled areas: between sine , horizontal curve if have same sign, or between horizontal curve , 0 if sine , horizontal curve have opposite signs. there switch in conditions filled areas, blank vertical zones undesirable edge effects...

fill_between_3

* final edit * [with solution]

because cannot find solution within fill_between, 1 solution (based on pyhazard's answer) recalculate upper , lower limit of filled areas make sure have them continuous (no more swith in fill_between condition).

plt.figure() x=numpy.arange(0.,3.05,0.05) y1=numpy.sin(2*numpy.pi*x) y2=[2.]*len(y1) y3=[-2.]*len(y1)  y1positive=y1>=0 y1negative=y1<=0  plt.plot(x,x*0,'--k') plt.plot(x,y1,'.-k',label='y1') plt.plot(x,y2,'.-g',label='y2') plt.plot(x,y3,'.-r',label='y3')  #solution: recalculate upper , lower limit of filled areas #  have each of them 1 continuous line y0=[0.]*len(y1) y1pos=numpy.amax(numpy.vstack((y1,y0)),axis=0.) y1neg=numpy.amin(numpy.vstack((y1,y0)),axis=0.) y21=y2+y1pos y31=y3+y1neg  plt.fill_between(x,y21,y1pos,color='green',alpha=0.5,linewidth=0) plt.fill_between(x,y31,y1neg,color='red',alpha=0.5,linewidth=0)   plt.legend() 

fill_between_4

as long concerned 1 line or other suggest looking @ comparison. following produces more pleasing plot. (note plotting style changed make data points clear.)

if had intended of area on negative side red , positive side green need add additional data-points series that lie on axis.

import matplotlib.pyplot plt import numpy  plt.figure() x=numpy.arange(0.,1.05,0.05) y1=numpy.sin(2*numpy.pi*x) y2=y1+0.2  eta=1e-6 y1positive=(y1+eta)>=0 y1negative=(y1-eta)<=0  plt.plot(x,y1,'-r',label='y1') plt.plot(x,y2,'-g',label='y2') plt.plot(x,x*0,'--k') plt.fill_between(x,y2,y1,where=y1positive,color='green',alpha=0.5,interpolate=false) plt.fill_between(x,y2,y1,where=y1negative,color='red',alpha=0.5,interpolate=false) plt.legend() plt.show() 

enter image description here

** edit ** cannot yet comment i'm adding edit. i'm new forum scene i'm not sure if considered proper etiquette.

i'm not sure understand revised situation. trying fill white areas in red , green? if don't need conditionals , need to fill between in simplest way shown below.

plt.figure() x=numpy.arange(0.,3.05,0.05) y1=numpy.sin(2*numpy.pi*x) y2=[ 2.]*len(y1) y3=[-2.]*len(y1)  y21 = numpy.amax(numpy.vstack((y2,y2+y1)), axis=0) y31 = numpy.amin(numpy.vstack((y3,y3+y1)), axis=0)  plt.plot(x,x*0,'--k') plt.fill_between(x,y21,y1,color='green',alpha=0.5,linewidth=0) plt.fill_between(x,y31,y1,color='red',alpha=0.5,linewidth=0)   plt.show() 

enter image description here


Comments

Popular posts from this blog

java.util.scanner - How to read and add only numbers to array from a text file -

rewrite - Trouble with Wordpress multiple custom querystrings -