Search code examples
pythonmatplotlibplot

Plotting a curve with different background colors


I am trying to plot a curve after reading a data file. The background above the curve and below the curve should be different (say, red and green). This is like a phase diagram showing two different phases above and below a boundary line. Is it possible using matplotlib in python? My code is

#!/usr/bin/env python

import numpy as np
import pylab as pl
import matplotlib.pyplot as plt

# Use numpy to load the data contained in the file
# 'data.txt' into a 2-D array called data
data = np.loadtxt('data.txt')
# plot the first column as x, and second column as y
x=data[:,0]
y=data[:,1]
pl.plot(x,y, '-r')
pl.xlabel('x')
pl.ylabel('y')
pl.show()

The 'data.txt' file contains :

0 0
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81

So it should plot a parabola.

There is a possible duplicate here. However, that doesn't seem to work in my case.

Also I would like enter texts in the middle of the differently colored patches.

So my plot should look like:

enter image description here


Solution

  • Yes, this is possible using matplotlib's fill_between. You can fill below the line simply with plt.fill_between(x,y,color="whatever"). To be more complete, you can set the lower bound of the fill with plt.fill_between(x,0,y,color="whatever")

    To fill the whole area above the curve, you can use plt.fill_between(x,y,plt.ylim()[1],color="whatever")

    Here is some demo code that works to fill both above and below the curve:

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(0,9,10)
    y = x ** 2
    plt.plot(x,y,"b-")
    plt.fill_between(x,y,color="red")
    maxy = plt.ylim()[1]
    plt.fill_between(x,y,maxy,color="green")
    plt.show()
    

    You can set x and y however you want.

    Hope this helps!

    EDIT: You can add text with matplotlib's text. You need to specify the coordinates, but you could do something like

    xtextplace = x[7]
    ytextplace = y[7] / 2
    plt.text(xtextplace,ytextplace,"Some Text")
    

    I'd do something like:

    xcoord = x[int((x.size/3)*2)]
    ycoord = y[int((x.size/3)*2)] / 2
    plt.text(xcoord,ycoord,"Text")
    

    This would make the text appear 2/3 of the way along the x-axis and 1/2 way up under the curve at that point.