Difference between revisions of "MatPlotLib Tutorial 1"
(→Bar-Graphs) |
(→Other Sources of Information) |
||
(50 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
--[[User:Thiebaut|D. Thiebaut]] 10:27, 25 April 2011 (EDT) | --[[User:Thiebaut|D. Thiebaut]] 10:27, 25 April 2011 (EDT) | ||
---- | ---- | ||
+ | <div style="text-align:right;"> | ||
+ | <google1 style="2"></google1> | ||
+ | </div> | ||
+ | |||
{| | {| | ||
| width="40%" | __TOC__ | | width="40%" | __TOC__ | ||
− | | | + | |valign="top"| |
− | |||
<bluebox> | <bluebox> | ||
[[File:MatPlotLib.png | right | 80px]] | [[File:MatPlotLib.png | right | 80px]] | ||
Line 17: | Line 20: | ||
|} | |} | ||
+ | =What is MatPlotLib?= | ||
+ | |||
+ | From the [http://matplotlib.sourceforge.net/users/intro.html MatPlotLib Website (matplotlib.sourceforge.net)]: | ||
+ | :::The matplotlib code is conceptually divided into three parts: the pylab interface is the set of functions provided by matplotlib.pylab which allow the user to create plots with code quite similar to MATLAB figure generating code ([http://matplotlib.sourceforge.net/users/pyplot_tutorial.html#pyplot-tutorial Pyplot tutorial]). The matplotlib frontend or matplotlib API is the set of classes that do the heavy lifting, creating and managing figures, text, lines, plots and so on ([http://matplotlib.sourceforge.net/users/artists.html#artist-tutorial Artist tutorial]). This is an abstract interface that knows nothing about output. The backends are device dependent drawing devices, aka renderers, that transform the frontend representation to hardcopy or a display device ([http://matplotlib.sourceforge.net/faq/installing_faq.html#what-is-a-backend What is a backend?]). Example backends: PS creates PostScript® hardcopy, SVG creates Scalable Vector Graphics hardcopy, Agg creates PNG output using the high quality [http://www.antigrain.com/ Anti-Grain Geometry] library that ships with matplotlib, GTK embeds matplotlib in a Gtk+ application, GTKAgg uses the Anti-Grain renderer to create a figure and embed it a Gtk+ application, and so on for PDF, WxWidgets, Tkinter etc. | ||
=Other Sources of Information= | =Other Sources of Information= | ||
* MatPlotLib's tutorials, at http://matplotlib.sourceforge.net/users/pyplot_tutorial.html | * MatPlotLib's tutorials, at http://matplotlib.sourceforge.net/users/pyplot_tutorial.html | ||
+ | * J.R. Johansson has a nice tutorial on MatPlotLib at [http://nbviewer.ipython.org/urls/raw.github.com/jrjohansson/scientific-python-lectures/master/Lecture-4-Matplotlib.ipynb nbviewer.jpython.org]. | ||
=Setup= | =Setup= | ||
Line 30: | Line 38: | ||
# EDP from Enthought: https://www.enthought.com/products/. It contains all you need to run MatPlotLib. | # EDP from Enthought: https://www.enthought.com/products/. It contains all you need to run MatPlotLib. | ||
− | ==Default Python== | + | ==Default Python Interpreter== |
* You should make the Python version installed by EDP as the default Python interpreter for Eclipse/PyDev. | * You should make the Python version installed by EDP as the default Python interpreter for Eclipse/PyDev. | ||
* First open a Terminal window and type: | * First open a Terminal window and type: | ||
Line 41: | Line 49: | ||
<br /><center>[[Image:EclipsePyDevDefaultPythonInterpreter.png|700px]]</center><br /> | <br /><center>[[Image:EclipsePyDevDefaultPythonInterpreter.png|700px]]</center><br /> | ||
− | ==Testing== | + | ==Testing the Installation== |
* To test that your installation is ready to go, load up the code from this URL http://matplotlib.sourceforge.net/examples/api/unicode_minus.html and run it. You should get a plot, as shown below: | * To test that your installation is ready to go, load up the code from this URL http://matplotlib.sourceforge.net/examples/api/unicode_minus.html and run it. You should get a plot, as shown below: | ||
Line 54: | Line 62: | ||
==The Simplest Approach== | ==The Simplest Approach== | ||
[[Image:MatPlotLib_SimplestApproach.png|300px|right]] | [[Image:MatPlotLib_SimplestApproach.png|300px|right]] | ||
− | + | ||
+ | We have an array of ''N'' Y-values, and you want to display them at X-values ranging from 0 to ''N''-1. By default if only one series is specified, it is assumed to be the Y-values, and the X-values automatically become ''range(N)''. | ||
<br /> | <br /> | ||
<source lang="python"> | <source lang="python"> | ||
+ | |||
+ | import numpy as np | ||
+ | import matplotlib.pyplot as plt | ||
def plot2(): | def plot2(): | ||
Line 63: | Line 75: | ||
plt.ylabel('Intensity') | plt.ylabel('Intensity') | ||
plt.show() | plt.show() | ||
− | + | ||
+ | plot2() | ||
</source> | </source> | ||
<br /> | <br /> | ||
Line 75: | Line 88: | ||
<br /> | <br /> | ||
+ | |||
==Changing Colors and Adding Markers== | ==Changing Colors and Adding Markers== | ||
[[Image:MatPlotLib_SimplestApproachColorMarkers.png|300px|right]] | [[Image:MatPlotLib_SimplestApproachColorMarkers.png|300px|right]] | ||
<br /> | <br /> | ||
<source lang="python"> | <source lang="python"> | ||
+ | import numpy as np | ||
+ | import matplotlib.pyplot as plt | ||
+ | |||
def plot3(): | def plot3(): | ||
plt.plot([1,3,2,4], 'ro-' ) | plt.plot([1,3,2,4], 'ro-' ) | ||
plt.ylabel('Intensity') | plt.ylabel('Intensity') | ||
plt.show() | plt.show() | ||
+ | |||
+ | plot3() | ||
</source> | </source> | ||
<br /> | <br /> | ||
Line 94: | Line 113: | ||
<br /> | <br /> | ||
− | ==Two | + | ==Two lists of coordinates== |
[[Image:MatPlotLib_XYListsCoords.png|300px|right]] | [[Image:MatPlotLib_XYListsCoords.png|300px|right]] | ||
<br /> | <br /> | ||
<source lang="python"> | <source lang="python"> | ||
+ | import numpy as np | ||
+ | import matplotlib.pyplot as plt | ||
def plot4(): | def plot4(): | ||
Line 108: | Line 129: | ||
plt.show() | plt.show() | ||
− | + | plot4() | |
</source> | </source> | ||
<br /> | <br /> | ||
Line 140: | Line 161: | ||
</source> | </source> | ||
<br /> | <br /> | ||
− | We just use Python to break the list of pairs into two lists of numbers, one for ''x'', one for ''y''. | + | We just use Python to break the list of pairs into two lists of numbers, one for ''x'', one for ''y''. |
+ | |||
+ | The ''axis( [minX, maxX, minY, maxY] ) '' function is used to define the bounds of the two axes. | ||
<br /> | <br /> | ||
<br /> | <br /> | ||
<br /> | <br /> | ||
+ | |||
==Plotting Two Different Curves== | ==Plotting Two Different Curves== | ||
[[Image:MatPlotLibTwoCurves.png|right|300px]] | [[Image:MatPlotLibTwoCurves.png|right|300px]] | ||
Line 193: | Line 217: | ||
=Line Graph with String X-Values= | =Line Graph with String X-Values= | ||
− | ==A Simple Line of (label, y) Points== | + | ==A Simple Line of a series of (label, y) Points== |
[[Image:LineGraphWithStringXValues.png|300px|right]] | [[Image:LineGraphWithStringXValues.png|300px|right]] | ||
<br /> | <br /> | ||
Line 212: | Line 236: | ||
plt.show() | plt.show() | ||
</source> | </source> | ||
+ | <br /> | ||
+ | We use some random points with y-values in the range 0 to 200, and x-values of the form "data1", "data2", "data3", etc. The values on the X-axis are printed every fifth of the axis length. | ||
+ | |||
+ | =Area-Curve= | ||
+ | |||
+ | ==One Curve, Colored Area Under the Curve== | ||
+ | [[Image:MatPlotLib_AreaCurve.png|300px|right]] | ||
+ | <br /> | ||
+ | <source lang="python"> | ||
+ | def plot12(): | ||
+ | t = np.arange( 0, 200, 1) | ||
+ | N = len( t ) | ||
+ | y = np.random.rand( N ) | ||
+ | x = np.arange( 1, N+1 ) | ||
+ | labels = [ "data"+str(k) for k in range(1, N+1) ] | ||
+ | samples = [ '' ] * N | ||
+ | for i in range( 0, N, N/5 ): | ||
+ | samples[i] = labels[i] | ||
+ | width = 1.0 | ||
+ | plt.fill_between( x, 0, y, color='y' ) | ||
+ | plt.ylabel( 'Intensity' ) | ||
+ | plt.xticks(x + width/2.0, samples ) | ||
+ | plt.show() | ||
+ | </source> | ||
+ | <br /> | ||
+ | |||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | ==One Curve, Colored Area Above the Curve== | ||
+ | [[Image:MatPlotLib_AreaCurve2.png|300px|right]] | ||
+ | <br /> | ||
+ | <source lang="python"> | ||
+ | def plot12(): | ||
+ | t = np.arange( 0, 200, 1) | ||
+ | N = len( t ) | ||
+ | y = np.random.rand( N ) | ||
+ | x = np.arange( 1, N+1 ) | ||
+ | labels = [ "data"+str(k) for k in range(1, N+1) ] | ||
+ | samples = [ '' ] * N | ||
+ | for i in range( 0, N, N/5 ): | ||
+ | samples[i] = labels[i] | ||
+ | width = 1.0 | ||
+ | '''plt.fill_between( x, y, 1, color='m' )''' | ||
+ | plt.ylabel( 'Intensity' ) | ||
+ | plt.xticks(x + width/2.0, samples ) | ||
+ | plt.show() | ||
+ | </source> | ||
+ | <br /> | ||
+ | |||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | ==Two Curves, Stacked, Color under the Curves== | ||
+ | [[Image:MatPlotLibTwoCurvesColoredUnder.png|300px|right]] | ||
+ | <br /> | ||
+ | <source lang="python"> | ||
+ | def plot13(): | ||
+ | t = np.arange( 0, 200, 1) | ||
+ | N = len( t ) | ||
+ | y1 = np.random.rand( N) | ||
+ | delta = np.random.rand( N ) | ||
+ | y2 = y1 + delta/2 | ||
+ | x = np.arange( 1, N+1 ) | ||
+ | labels = [ "data"+str(k) for k in range(1, N+1) ] | ||
+ | samples = [ '' ] * N | ||
+ | for i in range( 0, N, N/5 ): | ||
+ | samples[i] = labels[i] | ||
+ | width = 1.0 | ||
+ | plt.fill_between( x, 0, y1, color='m' ) | ||
+ | plt.fill_between( x, y1, y2, color='y' ) | ||
+ | plt.axis( [0, N, 0, max(y2)] ) | ||
+ | plt.ylabel( 'Intensity' ) | ||
+ | #plt.xticks(x + width/2.0, samples ) | ||
+ | plt.show() | ||
+ | |||
+ | </source> | ||
+ | <br /> | ||
<br /> | <br /> | ||
Line 239: | Line 346: | ||
<br /> | <br /> | ||
<br /> | <br /> | ||
+ | |||
==Adding String Labels for X Values== | ==Adding String Labels for X Values== | ||
[[Image:MatPlotLib_BarGraphWithStringXValues.png|300px|right]] | [[Image:MatPlotLib_BarGraphWithStringXValues.png|300px|right]] | ||
Line 256: | Line 364: | ||
plt.ylabel( 'Intensity' ) | plt.ylabel( 'Intensity' ) | ||
plt.xticks(x + width/2.0, labels ) | plt.xticks(x + width/2.0, labels ) | ||
− | plt.show()</source> | + | plt.show() |
+ | </source> | ||
<br /> | <br /> | ||
+ | Here we set the '''width''' to '''1''' to make the bars fill the space. | ||
<br /> | <br /> | ||
<br /> | <br /> | ||
<br /> | <br /> | ||
<br /> | <br /> | ||
+ | |||
==Adding Sampled String Labels for X Values== | ==Adding Sampled String Labels for X Values== | ||
[[Image:MatPlotLib_BarGraphWithSampledStringXValues.png|300px|right]] | [[Image:MatPlotLib_BarGraphWithSampledStringXValues.png|300px|right]] | ||
Line 283: | Line 394: | ||
</source> | </source> | ||
<br /> | <br /> | ||
+ | |||
+ | =Histograms= | ||
+ | |||
+ | More good information on [http://matplotlib.sourceforge.net/examples/pylab_examples/histogram_demo_extended.html MatPlotLib's site]. | ||
+ | |||
+ | ==Basic Histogram== | ||
+ | [[Image:MatPlotLibBasicHistogram.png|300px|right]] | ||
<br /> | <br /> | ||
+ | <source lang="python"> | ||
+ | def plot14(): | ||
+ | # the number of bins | ||
+ | N = 12 | ||
+ | |||
+ | # the samples | ||
+ | samples = np.array([1, 1, 1, 3, 2, 5, 1, 10, 10, 8]) | ||
+ | |||
+ | n, bins, patches = plt.hist( samples, N, facecolor="magenta", | ||
+ | range=[1,N], normed=True ) | ||
+ | plt.xlabel( 'bins' ) | ||
+ | plt.ylabel( 'Probability' ) | ||
+ | plt.show() | ||
+ | </source> | ||
<br /> | <br /> | ||
+ | * Change '''normed''' to ''False'' to get the counts instead of the percentage or probability. | ||
+ | * Add '''cumulative'''=''True'' to get a probability distribution. | ||
<br /> | <br /> | ||
<br /> | <br /> | ||
<br /> | <br /> | ||
+ | ==Stacked Histograms in the same graph== | ||
+ | [[Image:MaptPlotLibStackedHistograms.png|300px|right]] | ||
<br /> | <br /> | ||
+ | There is very likely a more "MapPlotLib" way to do this, but until somebody points out a more elegant way to do this, we simply create the distribution in the bins ourselves and display the stacked histograms as two bar-graphs in the same system of axes, one on top of the other. | ||
<br /> | <br /> | ||
+ | <source lang="python"> | ||
+ | def plot17(): | ||
+ | #--- the two samples --- | ||
+ | samples1 = np.array([1, 1, 1, 3, 2, 5, 1, 10, 10, 8]) | ||
+ | samples2 = np.array([6, 6, 6, 1, 2, 3, 9, 12 ] ) | ||
+ | |||
+ | N = 12 # number of bins | ||
+ | hist1 = [0] * (N) | ||
+ | hist2 = [0] * (N) | ||
+ | |||
+ | #--- create two histogram. Values of 1 go in Bin 0 --- | ||
+ | for x in samples1: | ||
+ | hist1[x-1] += 1 | ||
+ | for x in samples2: | ||
+ | hist2[x-1] += 1 | ||
+ | #--- display the bar-graph --- | ||
+ | width = 1 | ||
+ | p1 = plt.bar( np.arange(0,N)+0.5, hist1, width, color='y' ) | ||
+ | p2 = plt.bar( np.arange(0,N)+0.5, hist2, width, color='m', bottom=hist1 ) | ||
+ | plt.legend( (p1[0], p2[0]), ( 'hist1', 'hist2' ) ) | ||
+ | plt.xlabel( 'Bins' ) | ||
+ | plt.ylabel( 'Count' ) | ||
+ | plt.xticks( np.arange( 1,N+1 ) ) | ||
+ | plt.show() | ||
+ | |||
+ | |||
+ | </source> | ||
<br /> | <br /> | ||
+ | ==Stacked histogram X 3== | ||
+ | [[Image:MatPlotLibStackedHistogramX3.png|300px|right]] | ||
<br /> | <br /> | ||
+ | Just an improved version of the previous histogram with 3 sets of sample values. | ||
<br /> | <br /> | ||
+ | <source lang="python"> | ||
+ | def plot17(): | ||
+ | #--- the two samples --- | ||
+ | samples1 = [1, 1, 1, 3, 2, 5, 1, 10, 10, 8] | ||
+ | samples2 = [6, 6, 6, 1, 2, 3, 9, 12 ] | ||
+ | samples3 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 11, 12] | ||
+ | |||
+ | N = 12 # number of bins | ||
+ | hist1 = np.array([0] * N ) | ||
+ | hist2 = np.array([0] * N ) | ||
+ | hist3 = np.array([0] * N ) | ||
+ | |||
+ | #--- create two histogram. Values of 1 go in Bin 0 --- | ||
+ | for x in samples1: | ||
+ | hist1[x-1] += 1 | ||
+ | for x in samples2: | ||
+ | hist2[x-1] += 1 | ||
+ | for x in samples3: | ||
+ | hist3[x-1] += 1 | ||
+ | |||
+ | #--- display the bar-graph --- | ||
+ | width = 1 | ||
+ | p1 = plt.bar( np.arange(0,N)+0.5, hist1, width, color='#9932cc' ) | ||
+ | p2 = plt.bar( np.arange(0,N)+0.5, hist2, width, color='#ffa500', bottom=hist1 ) | ||
+ | p3 = plt.bar( np.arange(0,N)+0.5, hist3, width, color='#d2691e', bottom=hist1+hist2 ) | ||
+ | plt.legend( (p1[0], p2[0], p3[0]), ( 'hist1', 'hist2', 'hist3' ) ) | ||
+ | plt.xlabel( 'Bins' ) | ||
+ | plt.ylabel( 'Count' ) | ||
+ | #plt.axis([1, 46, 0, 6]) | ||
+ | plt.xticks( np.arange( 1,N+1 ) ) | ||
+ | plt.axis( [width/2.0, N+width/2.0, 0, max( hist1+hist2+hist3)] ) | ||
+ | plt.show() | ||
+ | |||
+ | |||
+ | </source> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | |||
+ | ==Two Histograms One Above the Other== | ||
+ | [[Image:MatPlotLibTwoHistSideBySide.png|300px|right]] | ||
+ | <br /> | ||
+ | <source lang="python"> | ||
+ | def plot15(): | ||
+ | N = 12 | ||
+ | samples1 = np.array([1, 1, 1, 3, 2, 5, 1, 10, 10, 8]) | ||
+ | samples2 = np.array([5,5,5,5,6,7,1,1,2,12,12,12,9,3,4]) | ||
+ | |||
+ | plt.figure( 1 ) | ||
+ | plt.subplot( 2, 1, 1 ) # 2 rows, 1 column, figure 1 | ||
+ | n1, bins1, patches1 = plt.hist( samples1, N, facecolor="m", | ||
+ | range=[1,N], normed=True ) | ||
+ | plt.xlabel( 'Bins' ) | ||
+ | plt.ylabel( 'Probability (magenta)' ) | ||
+ | |||
+ | plt.subplot( 2, 1, 2 ) | ||
+ | n2, bins2, patches2 = plt.hist( samples2, N, facecolor="y", | ||
+ | range=[1,N], normed=True ) | ||
+ | plt.xlabel( 'Bins' ) | ||
+ | plt.ylabel( 'Probability (yellow)' ) | ||
+ | plt.show() | ||
+ | </source> | ||
<br /> | <br /> | ||
+ | * A good reference: [http://matplotlib.sourceforge.net/users/pyplot_tutorial.html#working-with-multiple-figures-and-axes PyPlot Tutorial] | ||
+ | <br /> | ||
+ | ==Four Histograms, in a Quadrant System== | ||
+ | [[Image:MatPlotLibQuadrantHistograms.png|300px|right]] | ||
+ | Note that this method does scale the vertical axes individually. In other words the histograms' vertical axes are '''not''' scaled relative to each. | ||
+ | <br /> | ||
+ | <source lang="python"> | ||
+ | def plot16(): | ||
+ | N = 12 # the number of bins | ||
+ | samples1 = np.array([1, 1, 1, 3, 2, 5, 1, 10, 10, 8]) | ||
+ | samples2 = np.array([5,5,5,5,6,7,1,1,2,12,12,12,9,3,4]) | ||
+ | samples3 = np.array([1,2,3,4,5,6,6,7,8,9,10,10,11,12]) | ||
+ | samples4 = np.array([1,2,2,2,2,2,2,2,2,10,11,12]) | ||
+ | plt.figure( 1 ) | ||
+ | #--- top left --- | ||
+ | plt.subplot( 2, 2, 1 ) | ||
+ | n1, bins1, patches1 = plt.hist( samples1, N, facecolor="m", | ||
+ | range=[1,N], normed=True ) | ||
+ | plt.xlabel( 'Bins' ) | ||
+ | plt.ylabel( 'Probability (magenta)' ) | ||
+ | plt.title( "Sample 1 Frequencies") | ||
+ | |||
+ | #--- top right --- | ||
+ | plt.subplot( 2, 2, 2 ) | ||
+ | n2, bins2, patches2 = plt.hist( samples2, N, facecolor="y", | ||
+ | range=[1,N], normed=True ) | ||
+ | plt.xlabel( 'Bins' ) | ||
+ | plt.ylabel( 'Probability (yellow)' ) | ||
+ | plt.title( "Sample 2 Frequencies") | ||
+ | |||
+ | #--- bottom left --- | ||
+ | plt.subplot( 2, 2, 3 ) | ||
+ | n3, bins3, patches3 = plt.hist( samples3, N, facecolor="grey", | ||
+ | range=[1,N], normed=False ) | ||
+ | plt.title( "Sample 3 Counts") | ||
+ | plt.xlabel( 'Bins' ) | ||
+ | plt.ylabel( 'Count (grey)' ) | ||
+ | |||
+ | #--- bottom right --- | ||
+ | plt.subplot( 2, 2, 4 ) | ||
+ | n4, bins4, patches4 = plt.hist( samples4, N, facecolor="r", | ||
+ | range=[1,N], normed=False ) | ||
+ | plt.title( "Sample 4 Counts") | ||
+ | plt.xlabel( 'Bins' ) | ||
+ | plt.ylabel( 'Count (red)' ) | ||
+ | |||
+ | plt.show() | ||
+ | |||
+ | </source> | ||
+ | |||
+ | <br /> | ||
+ | |||
+ | ==Adjusting the Placement of Sub-Plots== | ||
+ | {| | ||
+ | | | ||
+ | When generating several sub-plots in a plot, the labels may overlap graphics elements, as shown in the picture to the right, where the titles and the Y-axis labels overlap elements of the neighboring plots. To remedy this problem, use the spacing controls to move the graphics elements of the plot. | ||
+ | | | ||
+ | [[Image:MapPlotLibAdjustPlacement1.png|300px|right]] | ||
+ | |- | ||
+ | | | ||
+ | In the Controls window move the wspace and hspace sliders to control the horizontal and vertical spacing separating the sub-plots. You may use the other controls to get the desired esthetics. | ||
+ | | | ||
+ | [[Image:MapPlotLibAdjustPlacementControls.png|300px|right]] | ||
+ | |- | ||
+ | | | ||
+ | The resulting graph shows non-overlapping sub-plots and can then be safely saved to file. | ||
+ | | | ||
+ | [[Image:MapPlotLibAdjustPlacement2.png|300px|right]] | ||
+ | |} | ||
+ | |||
+ | <br /> | ||
+ | <br /> | ||
+ | |||
+ | =Saving Your Plot to File= | ||
+ | [[Image:MatPlotLibSaveFile.png|400px|right]] | ||
+ | * Adjust the geometry of your plot and sub-plots if any. | ||
+ | * Click on the Save icon in the display window, | ||
+ | * In the "Save As" menu, pick the graphic file format. The fomats supported in the version used for this tutorial are | ||
+ | ** eps | ||
+ | ** emp | ||
+ | ** pdf | ||
+ | ** png | ||
+ | ** ps | ||
+ | ** raw | ||
+ | ** svg | ||
+ | |||
+ | |||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | *Alternatively, you can save your file from within your program: | ||
+ | |||
+ | import numpy as np | ||
+ | import matplotlib.pyplot as plt | ||
+ | |||
+ | plt.plot( Y0m[i], '.', color="#4169e1" ) | ||
+ | fileName = "~/Desktop/myPlot.png" | ||
+ | plt.savefig( fileName, format="png" ) | ||
+ | |||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
[[Category:Tutorials]][[Category:MatPlotLib]][[Category:Python]] | [[Category:Tutorials]][[Category:MatPlotLib]][[Category:Python]] |
Latest revision as of 16:28, 27 March 2013
--D. Thiebaut 10:27, 25 April 2011 (EDT)
What is MatPlotLib?
From the MatPlotLib Website (matplotlib.sourceforge.net):
- The matplotlib code is conceptually divided into three parts: the pylab interface is the set of functions provided by matplotlib.pylab which allow the user to create plots with code quite similar to MATLAB figure generating code (Pyplot tutorial). The matplotlib frontend or matplotlib API is the set of classes that do the heavy lifting, creating and managing figures, text, lines, plots and so on (Artist tutorial). This is an abstract interface that knows nothing about output. The backends are device dependent drawing devices, aka renderers, that transform the frontend representation to hardcopy or a display device (What is a backend?). Example backends: PS creates PostScript® hardcopy, SVG creates Scalable Vector Graphics hardcopy, Agg creates PNG output using the high quality Anti-Grain Geometry library that ships with matplotlib, GTK embeds matplotlib in a Gtk+ application, GTKAgg uses the Anti-Grain renderer to create a figure and embed it a Gtk+ application, and so on for PDF, WxWidgets, Tkinter etc.
Other Sources of Information
- MatPlotLib's tutorials, at http://matplotlib.sourceforge.net/users/pyplot_tutorial.html
- J.R. Johansson has a nice tutorial on MatPlotLib at nbviewer.jpython.org.
Setup
We use the Eclipse IDE and PyDev to develop Python packages. If you want to setup your environment to match the one used here you will need to install:
- Eclipse: http://www.eclipse.org/downloads/
- Python: http://www.python.org/download/
- PyDev: http://pydev.org/download.html
- EDP from Enthought: https://www.enthought.com/products/. It contains all you need to run MatPlotLib.
Default Python Interpreter
- You should make the Python version installed by EDP as the default Python interpreter for Eclipse/PyDev.
- First open a Terminal window and type:
which python /Library/Frameworks/Python.framework/Versions/Current/bin/python
- Record the answer to the command and enter it in Eclipse's Preference window for PyDev:
Testing the Installation
- To test that your installation is ready to go, load up the code from this URL http://matplotlib.sourceforge.net/examples/api/unicode_minus.html and run it. You should get a plot, as shown below:
Scatter Plot of (X, Y) points
The Simplest Approach
We have an array of N Y-values, and you want to display them at X-values ranging from 0 to N-1. By default if only one series is specified, it is assumed to be the Y-values, and the X-values automatically become range(N).
import numpy as np
import matplotlib.pyplot as plt
def plot2():
plt.plot([1,3,2,4])
plt.ylabel('Intensity')
plt.show()
plot2()
Changing Colors and Adding Markers
import numpy as np
import matplotlib.pyplot as plt
def plot3():
plt.plot([1,3,2,4], 'ro-' )
plt.ylabel('Intensity')
plt.show()
plot3()
To change the color, simply use a string at the last parameter of the plot() function and define the color, 'r' for red, for example, and the type of marker, 'o' for circle. 'ro' would display red circles only. 'ro-' would display red circles linked by a line. This is similar to the Matlab syntax. '--rs' would display a dash line between red squares. ':bs' would display a dotted line between blue squares.
Two lists of coordinates
import numpy as np
import matplotlib.pyplot as plt
def plot4():
x = [1, 2, 3, 4, 5, 6]
y = [1, 2, 4, 3, 6, 5]
plt.plot( x, y, ':rs' )
plt.axis( [0, 10, 0, 6])
plt.xlabel( "X values" )
plt.ylabel( "Y values" )
plt.show()
plot4()
Here we present the plot with two arrays, one for the X values, one for the Y values. We also define the range of values for the X-axis and the range of values for the Y-axis, and provide labels for each one.
The line and marker styles are defined by ':rs' , meaning dotted line, red square.
What if the List is a List of Pairs of Coordinates?
def plot5():
data = [ (1, 0), (2, 0.1 ), (3, 1.1), (4, 1.2), (5, 2.3),
(6, 3.5), (7, 5.8) ]
X = [ x for (x,y) in data ]
Y = [ y for (x,y) in data ]
#print X
#print Y
plt.plot( X, Y, ':rs' )
plt.axis( [0, 8, 0, 6])
plt.xlabel( "X values" )
plt.ylabel( "Y values" )
plt.show()
We just use Python to break the list of pairs into two lists of numbers, one for x, one for y.
The axis( [minX, maxX, minY, maxY] ) function is used to define the bounds of the two axes.
Plotting Two Different Curves
import numpy as np
def plot6():
t = np.arange(1, 10, 0.5)
plt.plot( t, t**2, 'r^--', t, 3*(t**2)-3, 'bs-' )
plt.show()
Here we plot two functions, one is y = x^2, in red with triangular markers, and dashed line. Then we print y = 3*x^2 -3, with blue squares and a solid line.
Plotting Two Different Curves defined as Lists
def plot7():
x1 =[ 1, 2, 5, 10, 15, 20]
y1 =[ 1.5 * x**2 for x in x1 ]
x2 = range( 5, 30)
y2 = [ 0.3 * x**2 -5 for x in x2 ]
plt.plot( x1, y1, "rs--", x2, y2, ":b^")
plt.show()
Note that the X-range for the first curve and for the second curve are not the same, but overlap. PyPlot adjusts the display and plots both curves correctly.
Line Graph with String X-Values
A Simple Line of a series of (label, y) Points
def plot11():
t = np.arange( 0, 200, 1)
N = len( t )
y = np.random.rand( N )
x = np.arange( 1, N+1 )
labels = [ "data"+str(k) for k in range(1, N+1) ]
samples = [ '' ] * N
for i in range( 0, N, N/5 ):
samples[i] = labels[i]
width = 1.0
plt.plot( x, y )
plt.ylabel( 'Intensity' )
plt.xticks(x + width/2.0, samples )
plt.show()
We use some random points with y-values in the range 0 to 200, and x-values of the form "data1", "data2", "data3", etc. The values on the X-axis are printed every fifth of the axis length.
Area-Curve
One Curve, Colored Area Under the Curve
def plot12():
t = np.arange( 0, 200, 1)
N = len( t )
y = np.random.rand( N )
x = np.arange( 1, N+1 )
labels = [ "data"+str(k) for k in range(1, N+1) ]
samples = [ '' ] * N
for i in range( 0, N, N/5 ):
samples[i] = labels[i]
width = 1.0
plt.fill_between( x, 0, y, color='y' )
plt.ylabel( 'Intensity' )
plt.xticks(x + width/2.0, samples )
plt.show()
One Curve, Colored Area Above the Curve
def plot12():
t = np.arange( 0, 200, 1)
N = len( t )
y = np.random.rand( N )
x = np.arange( 1, N+1 )
labels = [ "data"+str(k) for k in range(1, N+1) ]
samples = [ '' ] * N
for i in range( 0, N, N/5 ):
samples[i] = labels[i]
width = 1.0
'''plt.fill_between( x, y, 1, color='m' )'''
plt.ylabel( 'Intensity' )
plt.xticks(x + width/2.0, samples )
plt.show()
Two Curves, Stacked, Color under the Curves
def plot13():
t = np.arange( 0, 200, 1)
N = len( t )
y1 = np.random.rand( N)
delta = np.random.rand( N )
y2 = y1 + delta/2
x = np.arange( 1, N+1 )
labels = [ "data"+str(k) for k in range(1, N+1) ]
samples = [ '' ] * N
for i in range( 0, N, N/5 ):
samples[i] = labels[i]
width = 1.0
plt.fill_between( x, 0, y1, color='m' )
plt.fill_between( x, y1, y2, color='y' )
plt.axis( [0, N, 0, max(y2)] )
plt.ylabel( 'Intensity' )
#plt.xticks(x + width/2.0, samples )
plt.show()
Bar-Graphs
A Simple Bar-Graph
def plot8():
y = [ 3, 10, 7, 5, -3, 4.5, 6, 8.1]
N = len( y )
x = range( N )
width = 1/1.5
plt.bar( x, y, width, color="magenta" )
plt.show()
Adding String Labels for X Values
def plot9():
data = [ ("data1", 34), ("data2", 22),
("data3", 11), ( "data4", 28),
("data5", 57), ( "data6", 39),
("data7", 23), ( "data8", 98)]
N = len( data )
x = np.arange(1, N+1)
y = [ num for (s, num) in data ]
labels = [ s for (s, num) in data ]
width = 1
bar1 = plt.bar( x, y, width, color="y" )
plt.ylabel( 'Intensity' )
plt.xticks(x + width/2.0, labels )
plt.show()
Here we set the width to 1 to make the bars fill the space.
Adding Sampled String Labels for X Values
def plot10():
t = np.arange( 0, 200, 1)
N = len( t )
y = np.random.rand( N )
x = np.arange( 1, N+1 )
labels = [ "data"+str(k) for k in range(1, N+1) ]
samples = [ '' ] * N
for i in range( 0, N, N/5 ):
samples[i] = labels[i]
width = 1.0
bar1 = plt.bar( x, y, width, color="y" )
plt.ylabel( 'Intensity' )
plt.xticks(x + width/2.0, samples )
plt.show()
Histograms
More good information on MatPlotLib's site.
Basic Histogram
def plot14():
# the number of bins
N = 12
# the samples
samples = np.array([1, 1, 1, 3, 2, 5, 1, 10, 10, 8])
n, bins, patches = plt.hist( samples, N, facecolor="magenta",
range=[1,N], normed=True )
plt.xlabel( 'bins' )
plt.ylabel( 'Probability' )
plt.show()
- Change normed to False to get the counts instead of the percentage or probability.
- Add cumulative=True to get a probability distribution.
Stacked Histograms in the same graph
There is very likely a more "MapPlotLib" way to do this, but until somebody points out a more elegant way to do this, we simply create the distribution in the bins ourselves and display the stacked histograms as two bar-graphs in the same system of axes, one on top of the other.
def plot17():
#--- the two samples ---
samples1 = np.array([1, 1, 1, 3, 2, 5, 1, 10, 10, 8])
samples2 = np.array([6, 6, 6, 1, 2, 3, 9, 12 ] )
N = 12 # number of bins
hist1 = [0] * (N)
hist2 = [0] * (N)
#--- create two histogram. Values of 1 go in Bin 0 ---
for x in samples1:
hist1[x-1] += 1
for x in samples2:
hist2[x-1] += 1
#--- display the bar-graph ---
width = 1
p1 = plt.bar( np.arange(0,N)+0.5, hist1, width, color='y' )
p2 = plt.bar( np.arange(0,N)+0.5, hist2, width, color='m', bottom=hist1 )
plt.legend( (p1[0], p2[0]), ( 'hist1', 'hist2' ) )
plt.xlabel( 'Bins' )
plt.ylabel( 'Count' )
plt.xticks( np.arange( 1,N+1 ) )
plt.show()
Stacked histogram X 3
Just an improved version of the previous histogram with 3 sets of sample values.
def plot17():
#--- the two samples ---
samples1 = [1, 1, 1, 3, 2, 5, 1, 10, 10, 8]
samples2 = [6, 6, 6, 1, 2, 3, 9, 12 ]
samples3 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 11, 12]
N = 12 # number of bins
hist1 = np.array([0] * N )
hist2 = np.array([0] * N )
hist3 = np.array([0] * N )
#--- create two histogram. Values of 1 go in Bin 0 ---
for x in samples1:
hist1[x-1] += 1
for x in samples2:
hist2[x-1] += 1
for x in samples3:
hist3[x-1] += 1
#--- display the bar-graph ---
width = 1
p1 = plt.bar( np.arange(0,N)+0.5, hist1, width, color='#9932cc' )
p2 = plt.bar( np.arange(0,N)+0.5, hist2, width, color='#ffa500', bottom=hist1 )
p3 = plt.bar( np.arange(0,N)+0.5, hist3, width, color='#d2691e', bottom=hist1+hist2 )
plt.legend( (p1[0], p2[0], p3[0]), ( 'hist1', 'hist2', 'hist3' ) )
plt.xlabel( 'Bins' )
plt.ylabel( 'Count' )
#plt.axis([1, 46, 0, 6])
plt.xticks( np.arange( 1,N+1 ) )
plt.axis( [width/2.0, N+width/2.0, 0, max( hist1+hist2+hist3)] )
plt.show()
Two Histograms One Above the Other
def plot15():
N = 12
samples1 = np.array([1, 1, 1, 3, 2, 5, 1, 10, 10, 8])
samples2 = np.array([5,5,5,5,6,7,1,1,2,12,12,12,9,3,4])
plt.figure( 1 )
plt.subplot( 2, 1, 1 ) # 2 rows, 1 column, figure 1
n1, bins1, patches1 = plt.hist( samples1, N, facecolor="m",
range=[1,N], normed=True )
plt.xlabel( 'Bins' )
plt.ylabel( 'Probability (magenta)' )
plt.subplot( 2, 1, 2 )
n2, bins2, patches2 = plt.hist( samples2, N, facecolor="y",
range=[1,N], normed=True )
plt.xlabel( 'Bins' )
plt.ylabel( 'Probability (yellow)' )
plt.show()
- A good reference: PyPlot Tutorial
Four Histograms, in a Quadrant System
Note that this method does scale the vertical axes individually. In other words the histograms' vertical axes are not scaled relative to each.
def plot16():
N = 12 # the number of bins
samples1 = np.array([1, 1, 1, 3, 2, 5, 1, 10, 10, 8])
samples2 = np.array([5,5,5,5,6,7,1,1,2,12,12,12,9,3,4])
samples3 = np.array([1,2,3,4,5,6,6,7,8,9,10,10,11,12])
samples4 = np.array([1,2,2,2,2,2,2,2,2,10,11,12])
plt.figure( 1 )
#--- top left ---
plt.subplot( 2, 2, 1 )
n1, bins1, patches1 = plt.hist( samples1, N, facecolor="m",
range=[1,N], normed=True )
plt.xlabel( 'Bins' )
plt.ylabel( 'Probability (magenta)' )
plt.title( "Sample 1 Frequencies")
#--- top right ---
plt.subplot( 2, 2, 2 )
n2, bins2, patches2 = plt.hist( samples2, N, facecolor="y",
range=[1,N], normed=True )
plt.xlabel( 'Bins' )
plt.ylabel( 'Probability (yellow)' )
plt.title( "Sample 2 Frequencies")
#--- bottom left ---
plt.subplot( 2, 2, 3 )
n3, bins3, patches3 = plt.hist( samples3, N, facecolor="grey",
range=[1,N], normed=False )
plt.title( "Sample 3 Counts")
plt.xlabel( 'Bins' )
plt.ylabel( 'Count (grey)' )
#--- bottom right ---
plt.subplot( 2, 2, 4 )
n4, bins4, patches4 = plt.hist( samples4, N, facecolor="r",
range=[1,N], normed=False )
plt.title( "Sample 4 Counts")
plt.xlabel( 'Bins' )
plt.ylabel( 'Count (red)' )
plt.show()
Adjusting the Placement of Sub-Plots
When generating several sub-plots in a plot, the labels may overlap graphics elements, as shown in the picture to the right, where the titles and the Y-axis labels overlap elements of the neighboring plots. To remedy this problem, use the spacing controls to move the graphics elements of the plot. |
|
In the Controls window move the wspace and hspace sliders to control the horizontal and vertical spacing separating the sub-plots. You may use the other controls to get the desired esthetics. |
|
The resulting graph shows non-overlapping sub-plots and can then be safely saved to file. |
Saving Your Plot to File
- Adjust the geometry of your plot and sub-plots if any.
- Click on the Save icon in the display window,
- In the "Save As" menu, pick the graphic file format. The fomats supported in the version used for this tutorial are
- eps
- emp
- png
- ps
- raw
- svg
- Alternatively, you can save your file from within your program:
import numpy as np import matplotlib.pyplot as plt plt.plot( Y0m[i], '.', color="#4169e1" ) fileName = "~/Desktop/myPlot.png" plt.savefig( fileName, format="png" )