User Tools

Site Tools


pylabrecipes

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
pylabrecipes [2015/08/04 13:35]
mantis [Selecting color from colormaps]
pylabrecipes [2015/08/04 13:36] (current)
mantis [Selecting color from colormaps]
Line 1: Line 1:
 +Pylab is a procedural interface to the matplotlib object-oriented plotting library. It can be installed via apt:
  
 +<code bash>
 +sudo apt-get install python-matplotlib python-gtk2
 +</​code>​
 +
 +To find out what you can do with it have a look at the [[http://​matplotlib.sourceforge.net/​pylab_commands.html|Pylab Command Overview]] or the [[http://​matplotlib.sourceforge.net/​|Matplotlib Site]]
 +
 +====== Control axis ticks ======
 +
 +by setting tick locations and tick labels ​
 +
 +It is also possible to rotate long labels:
 +<code python>
 +pylab.xticks( arange(12), calendar.month_name[1:​13],​ rotation=17 )
 +</​code>​
 +
 +====== Plots with date axes ======
 +Use pylab.plot_date and the boolean parameters xdate and ydate date2num takes datetime instance or a sequence of datetimes as parameter and converts it/them to float(s).
 +
 +<code python>
 +pylab.plot_date(dates,​values,​ xdate=True, ydate=False)
 +</​code>​
 +
 +====== Format Date Axes ======
 +
 +To show hours on the X-Axis:
 +
 +<code python>
 +import pylab
 +from matplotlib.dates import DateFormatter,​HourLocator
 +
 +pylab.plot_date(pylab.date2num(times),​ values, "​b-", ​ xdate=True, ydate=False,​ label="​memory use" )
 +axes=pylab.gca()
 +
 +# Display the time of day every 2 hours
 +axes.xaxis.set_major_locator(HourLocator(interval=2))
 +axes.xaxis.set_major_formatter(DateFormatter('​%H:​%M'​))
 +
 +# Display a small tick every hour
 +axes.xaxis.set_minor_locator(HourLocator())
 +</​code>​
 +
 +
 +To show days on the X-Axis.
 +
 +<code python>
 +import pylab
 +from matplotlib.dates import DateFormatter,​DayLocator,​ HourLocator
 +
 +
 +pylab.plot_date(times,​values) # plot data
 +
 +# Display date at beginning of each day
 +pylab.gca().xaxis.set_major_locator(DayLocator()) ​
 +pylab.gca().xaxis.set_major_formatter(DateFormatter('​%d.%b %Y'​)) ​
 +
 + # display a small tick every 6 hours
 +pylab.gca().xaxis.set_minor_locator(HourLocator(byhour=(0,​6,​12,​18)))
 +
 +</​code>​
 +
 +====== Set Axis Min/Max ======
 +<code python>
 +pylab.plot(values)
 +pylab.axis(ymax=100) # or ymin|xmax|xmin ​ ( Note: its important to call pylab.axis() AFTER the plot command! ) pylab.show()
 +</​code>​
 +
 +====== Change Font Size of Axis Labels ======
 +<code python>
 +fontsize = 8
 +for tick in pylab.gca().xaxis.get_major_ticks():​
 +    tick.label1.set_fontsize(fontsize)
 +</​code> ​   ​
 +    ​
 +====== Plot lines ======
 +Draw a horizontal line at y=60 from xmin to xmax
 +
 +<code python>
 +pylab.axhline(60,​color="​g",​ linestyle="​--",​ label="​free speed"​)
 +</​code>​
 +====== Plot Histograms ======
 +<code python>
 +n,​bins,​patches = pylab.hist(values,​ noOfBins)
 +</​code>​
 +
 +====== Kernel Density ======
 +<code python>
 +import pylab
 +import scipy
 +import numpy
 +
 +# get data from somewhere
 +data = numpy.random.normal(0,​1,​1000)
 +
 +# Important Note: Make sure your data is float. If your data is int it does not work for some reason!
 +
 +
 +# histogram of data
 +pylab.hist(data,​50,​ normed=True) ​
 +
 +# add kernel density plot with gaussian kernel
 +kernel = scipy.stats.kde.gaussian_kde(data)
 +ind = numpy.linspace(-5,​5,​100)
 +kdepdf = kernel.evaluate(ind)
 +pylab.plot(ind,​ kdepdf,'​r',​linewidth=2)
 +</​code>​
 +
 +see 
 +  * http://​jpktd.blogspot.com/​2009/​03/​using-gaussian-kernel-density.html
 +  * http://​www.scipy.org/​SciPyPackages/​Stats
 +
 +====== ECDF ======
 +<code python>
 +import numpy
 +import statsmodels.distributions
 +
 +ecdf = statsmodels.distributions.ECDF(data)
 +
 +x = numpy.linspace(min(data),​ max(data))
 +y = ecdf(x)
 +pylab.plot(x,​y) # or pylab.step(x,​ y)
 +</​code>​
 +
 +====== Donut plot ======
 +
 +Is (unsurprisingly) made from pie plots.
 +
 +A very good example is here http://​matplotlib.1069221.n5.nabble.com/​how-to-draw-concentric-donuts-chart-tp43408p43412.html
 +
 +I needed just a clean, simple "​binary"​ donut, so I simplified that code.
 +
 +{{:​data.png?​300|}}
 +
 +<code python>
 +# thanks to Joe Kington http://​matplotlib.1069221.n5.nabble.com/​how-to-draw-concentric-donuts-chart-tp43408p43412.html
 +def make_pie(percent,​ text):
 +    import matplotlib.pyplot as plt
 +    import numpy as np
 +    c1 = '#​9999FF'​
 +    c2 = '#​FF9999'​
 +
 +    fig, ax = plt.subplots()
 +    ax.axis('​equal'​)
 +    width = 0.15
 +    kwargs = dict(colors=[c1,​ c2], startangle=180,​ counterclock=False)
 +    outside, _ = ax.pie([percent,​ 1-percent], radius=1, pctdistance=1-width/​2,​ **kwargs)
 +    plt.setp( outside, width=width,​ edgecolor='​white'​)
 +
 +    kwargs = dict(size=20,​ fontweight='​bold',​ va='​center',​ color=c1)
 +    ax.text(0, 0, "{0}% {1}"​.format(percent*100,​ text), ha='​center',​ **kwargs)
 +    plt.show()
 +
 +make_pie(0.95,​ "of your data\n is made up")
 +
 +</​code>​
 +
 +
 +
 +====== Plot (stack) bars ======
 +Use pylab.bar to plot (stack) bars:
 +
 +<code python>
 +bar(left, height, width=0.8, bottom=0, color=None, edgecolor=None,​ linewidth=None,​ yerr=None, xerr=None, ecolor=None,​ capsize=3, align='​edge',​ orientation='​vertical',​ log=False)
 +  #left - the x coordinates of the left sides of the bars
 +  #height - the heights of the bars
 +  #bottom - the y coordinates of the bottom edges of the bars
 +  #xerr, yerr - use to generate errorbars on the bar chart
 +</​code>​
 +To plot stack bars use the argument "​bottom",​ for example:
 +
 +<code python>
 +width=0.8 heights1 = (20, 35, 30, 35, 27) #heights of bar1
 +heights2 = (25, 32, 34, 20, 25)  #heights of bar2
 +bar1 = pylab.bar(arange(5),​ heights1, ​  ​width,​ color='​r'​)
 +bar2 = pylab.bar(arange(5),​ heights2, width, color='​y',​ bottom=heights1)
 +</​code>​
 +
 +====== Rotate xticklabels to vertical ======
 +<code python>
 +labels = pylab.getp(pylab.gca(),'​xticklabels'​) # getproperty xticklabels from current axes
 +pylab.setp(labels,​ rotation='​vertical'​)
 +</​code>​
 +
 +====== Add text ======
 +Add text in string s to axis at location x,y (default: data coords). It is also possible to specify text in axis coords (0,0 lower left and 1,1 upper right).
 +
 +<code python>
 +text(x, y, s, fontsize=12)
 +</​code>​
 +
 +====== Add text with Umlauts ======
 +<code python>
 +text(x, y, unicode('​hübsche Umlaute: ä ü ö', '​latin-1'​))
 +</​code>​
 +
 +====== Draw colored area / belt ("​band"​) ======
 +To draw a belt do: 
 +<code python>
 +pylab.fill_between(x,​ylower,​ yupper, color='​blue',​ alpha=0.1)
 +</​code>​
 +
 +====== Mark/​colour/​paint areas ======
 +check [[http://​matplotlib.sourceforge.net/​examples/​pylab_examples/​axhspan_demo.html this example]] to see how it looks like.
 +
 +eg. to mark months in a plot:
 +
 +<code python>
 +# get day of the year
 +aug=int(datetime(2008,​8,​1).strftime("​%j"​))
 +sept=int(datetime(2008,​9,​1).strftime("​%j"​))
 +okt=int(datetime(2008,​10,​1).strftime("​%j"​))
 +nov=int(datetime(2008,​11,​1).strftime("​%j"​))
 +
 +# plot areas
 +subplot.axvspan(aug-0.5,​ sept-0.5, facecolor='​0.5',​ alpha=0.2)
 +subplot.axvspan(okt-0.5,​ nov-0.5, facecolor='​0.5',​ alpha=0.2) # add descriptive text
 +subplot.text( aug, 13500, '​August'​)
 +subplot.text( sept, 13500, '​September'​)
 +subplot.text( okt, 13500, '​October'​) ''​
 +</​code>​
 +also works horizontally using:
 +
 +<code python>
 +subplot.axhspan(ymin,​ymax)
 +</​code>​
 +
 +
 +
 +
 +
 +====== Legends ======
 +
 +
 +===== Add legend =====
 +In order to display a lagend you need to label your plots. For example
 +
 +<code python>
 +pylab.plot_date(pylab.date2num(dates),​speeds,"​b-", ​ xdate=True, ydate=False,​ label="​taxi speeds"​) # the plot should be named "taxi speeds"​ in the legend
 +pylab.legend() # add the legend to the plot pylab.show() ''​
 +</​code>​
 +
 +===== Legends outside of plot =====
 +
 +Often there simply is no room to put the legend inside a plot. There are several approaches to put it partly or completely outside the plot.
 +This [[http://​stackoverflow.com/​questions/​4700614/​how-to-put-the-legend-out-of-the-plot|stackoverflow]] thread shows how to use the bbox_to_anchor keyword to move the legend partly outside the plot:
 +
 +<code python>
 +ax = plt.subplot(111)
 +#​ax.plot(something)
 +ax.legend(bbox_to_anchor=(1.1,​ 1.05))
 +</​code>​
 +
 +Alternatively the thread show how to shrink the current plot's width: this gains some space outside the plot where the legend can be put.
 +
 +<code python>
 +ax = plt.subplot(111)
 +#​ax.plot(plot something)
 +
 +# Shink current axis by 20%
 +box = ax.get_position()
 +ax.set_position([box.x0,​ box.y0, box.width * 0.8, box.height])
 +
 +# Put a legend to the right of the current axis
 +ax.legend(loc='​center left', bbox_to_anchor=(1,​ 0.5))
 +</​code>​
 +
 +===== Font properties of legends =====
 +
 +Sometimes simply shrinking the legend font helps to improve the visibility of data in a plot:
 +
 +<code python>
 +from matplotlib.font_manager import FontProperties
 +
 +fontP = FontProperties()
 +fontP.set_size('​xx-small'​)
 +legend([plot1],​ "​title",​ prop = fontP)
 +</​code>​
 +
 +====== Save Figure ======
 +<code python>
 +
 +pylab.plot(...)
 +pylab.savefig("​my_figure.png",​ format="​png"​)
 +</​code>​
 +
 +====== Subplots ======
 +To create a subplot with 2 lines, and 1 Column, and switch to the first image:
 +
 +<code python>
 +
 +pylab.subplot(211)
 +# plot first chart...
 +
 +# now switch to the second image
 +pylab.subplot(212)
 +# plot second chart
 +</​code>​
 +
 +====== Using Pylab in CGI Scripts ======
 +Its necessary to do a few things before importing the pylab module:
 +
 +<code python>
 +import os os.environ[ '​HOME'​ ] = '/​tmp/'#​set HOME environment variable to a directory the httpd server can write to
 +import matplotlib
 +matplotlib.use( '​Agg'​ )#use a non-gui backend.
 +
 +# Now pylab can be imported without errors
 +import pylab
 +import sys
 +
 +#Create your plot like you normally would, then return it to the browser by doing the following:
 +print "​Content-Type:​ image/​png\n" ​
 +pylab.savefig(sys.stdout,​ format='​png'​ )
 +</​code>​
 +
 +====== Adding color to plots ======
 +<code python>
 +from random import choice
 +colors = ['#​FFFFCC','#​FFFF99','#​FFFF66','#​FFFF33','#​FFFF00','#​FFCCFF','#​FFCCCC','#​FFCC99','#​FFCC66','#​FFCC33','#​FFCC00','#​FF99FF','#​FF99CC','#​FF9999','#​FF9966','#​FF9933','#​FF9900','#​FF66FF','#​FF66CC','#​FF6699','#​FF6666','#​FF6633','#​FF6600','#​FF33FF','#​FF33CC','#​FF3399','#​FF3366','#​FF3333','#​FF3300','#​FF00FF','#​FF00CC','#​FF0099','#​FF0066','#​FF0033','#​FF0000','#​CCFFFF','#​CCFFCC','#​CCFF99','#​CCFF66','#​CCFF33','#​CCFF00','#​CCCCFF','#​CCCCCC','#​CCCC99','#​CCCC66','#​CCCC33','#​CCCC00','#​CC99FF','#​CC99CC','#​CC9999','#​CC9966','#​CC9933','#​CC9900','#​CC66FF','#​CC66CC','#​CC6699','#​CC6666','#​CC6633','#​CC6600','#​CC33FF','#​CC33CC','#​CC3399','#​CC3366','#​CC3333','#​CC3300','#​CC00FF','#​CC00CC','#​CC0099','#​CC0066','#​CC0033','#​CC0000','#​99FFFF','#​99FFCC','#​99FF99','#​99FF66','#​99FF33','#​99FF00','#​99CCFF','#​99CCCC','#​99CC99','#​99CC66','#​99CC33','#​99CC00','#​9999FF','#​9999CC','#​999999','#​999966','#​999933','#​999900','#​9966FF','#​9966CC','#​996699','#​996666','#​996633','#​996600','#​9933FF','#​9933CC','#​993399','#​993366','#​993333','#​993300','#​9900FF','#​9900CC','#​990099','#​990066','#​990033','#​990000','#​66FFFF','#​66FFCC','#​66FF99','#​66FF66','#​66FF33','#​66FF00','#​66CCFF','#​66CCCC','#​66CC99','#​66CC66','#​66CC33','#​66CC00','#​6699FF','#​6699CC','#​669999','#​669966','#​669933','#​669900','#​6666FF','#​6666CC','#​666699','#​666666','#​666633','#​666600','#​6633FF','#​6633CC','#​663399','#​663366','#​663333','#​663300','#​6600FF','#​6600CC','#​660099','#​660066','#​660033','#​660000','#​33FFFF','#​33FFCC','#​33FF99','#​33FF66','#​33FF33','#​33FF00','#​33CCFF','#​33CCCC','#​33CC99','#​33CC66','#​33CC33','#​33CC00','#​3399FF','#​3399CC','#​339999','#​339966','#​339933','#​339900','#​3366FF','#​3366CC','#​336699','#​336666','#​336633','#​336600','#​3333FF','#​3333CC','#​333399','#​333366','#​333333','#​333300','#​3300FF','#​3300CC','#​330099','#​330066','#​330033','#​330000','#​00FFFF','#​00FFCC','#​00FF99','#​00FF66','#​00FF33','#​00FF00','#​00CCFF','#​00CCCC','#​00CC99','#​00CC66','#​00CC33','#​00CC00','#​0099FF','#​0099CC','#​009999','#​009966','#​009933','#​009900','#​0066FF','#​0066CC','#​006699','#​006666','#​006633','#​006600','#​0033FF','#​0033CC','#​003399','#​003366','#​003333','#​003300','#​0000FF','#​0000CC','#​000099','#​000066','#​000033','#​000000'​]
 +
 +pylab.bar(h,​ prev, width,​color=choice(colors))
 +</​code>​
 +
 +
 +====== Selecting color from colormaps ======
 +
 +Found [[https://​geetduggal.wordpress.com/​2011/​08/​22/​grabbing-individual-colors-from-color-maps-in-matplotlib/​|here]]
 +
 +Choose good colormap ([[http://​matplotlib.org/​examples/​color/​colormaps_reference.html|reference]]) and call it as function with a parameter between 0 and 1
 +<code python>
 +import pylab as p
 +c1 = p.cm.gnuplot2(0.3)
 +c2 = p.cm.gnuplot2(0.7)
 +
 +p.plot(range(0,​ 5), color=c1)
 +p.plot(range(4,​ 9), color=c2)
 +p.show()
 +</​code>​
 +
 +====== Make "​customised"​ legends ======
 +Not very elegant but googling helped me doing the job: these lines are never plotted, only used for building a legend.
 +
 +<code python>
 +from matplotlib.lines
 +import Line2D
 +line0 = Line2D(range(1),​ range(1), lw=4,​color='​darkgreen'​ )
 +line1 = Line2D(range(1),​ range(1), lw=4,​color='​skyblue'​ )
 +pylab.legend((line0,​line1),​('​weekdays','​weekends'​),​loc='​best'​)
 +</​code>​
 +
 +====== Show legend outside plot ======
 +<code python>
 +import pylab
 +pylab.figure()
 +pylab.subplot(111)
 +pylab.subplots_adjust(right=0.7)
 +pylab.plot([1,​6,​11],​label="​1) ​ label very long")
 +pylab.plot([2,​6,​10],​label="​2) ​ label"​) #Legende 1,1: ausrichtung rechts neben der Grafik; 0,1 unten neben der Grafik beginnen
 +pylab.legend(loc=(1.1,​0.1)) #show legend on the right side of the chart
 +pylab.show()
 +</​code>​
 +
 +====== Axis Labels ======
 +<code python>
 +import pylab
 +pylab.plot(....)
 +pylab.axes().set_xlabel("​hour"​)
 +pylab.axes().set_ylabel("​speed"​)
 +</​code>​
 +
 +====== Format axes ======
 +<code python>
 +import pylab
 +pylab.figure()
 +pylab.axes([0.1,​0.1,​0.71,​0.8])
 +pylab.plot([0,​1],​[0,​1],​label="​line 1")
 +pylab.hold(1) pylab.plot([0,​1],​[1,​0.5],​label="​line 2")
 +pylab.legend(loc=(1.03,​0.2))
 +pylab.show()
 +</​code>​
 +
 +====== Overwrite Legend Function ======
 +Function for overwriting:​
 +
 +<code python>
 +
 +def legend(*args,​ **kwargs):
 +  """​ Overwrites the pylab legend function. It adds another location identfier 'outer right' which locates the legend on the right side of the plot The args and kwargs are forwarded to the pylab legend function """​
 +  if kwargs.has_key('​loc'​):​
 +    loc = kwargs['​loc'​]
 +    loc = loc.split()
 +    if loc[0] == '​outer':​
 +      # make a legend with out the location
 +      kwargs.pop('​loc'​) # remove the location setting from the kwargs
 +      leg = pylab.legend(loc=(0,​0),​ *args, **kwargs)
 +      frame = leg.get_frame()
 +      currentAxes = pylab.gca()
 +      currentAxesPos = currentAxes.get_position() # scale plot by the part which is taken by the legend
 +      plotScaling = frame.get_width()/​currentAxesPos[2]
 +      if loc[1] == '​right':​
 +        # scale the plot
 +        currentAxes.set_position((currentAxesPos[0],​currentAxesPos[1],​currentAxesPos[2]*(1-plotScaling),​currentAxesPos[3])) # set x and y coordinates of legend.
 +        leg._loc = (1 + leg.axespad,​ 1 - frame.get_height())
 +
 +      pylab.draw_if_interactive()
 +      return leg
 +
 +    return pylab.legend(*args,​ **kwargs) ''​
 +</​code>​
 +Test the function:
 +
 +<code python>
 +pylab.plot([1,​6,​11],​label="​1) ​ label"​)
 +pylab.plot([2,​6,​10],​label="​2) ​ label"​)
 +pylab.plot([3,​6,​9],​label ="​3) ​ label"​)
 +pylab.plot([4,​6,​8],​label ="​4) ​ label"​)
 +pylab.title("​Legend override (outer right)"​)
 +pylab.grid() ​
 +legend(loc='​outer right'​)
 +pylab.show()
 +</​code>​
 +source: : http://​www.mail-archive.com/​matplotlib-users@lists.sourceforge.net/​msg04256.html
 +
 +====== Annotations ======
 +Use [[http://​matplotlib.sourceforge.net/​api/​pyplot_api.html#​matplotlib.pyplot.annotate|annotations]] to enrich your plots with additional information. More Code Samples [[http://​matplotlib.sourceforge.net/​examples/​pylab_examples/​annotation_demo2.html|here]]]
 +
 +====== Continuously updating a plot ======
 +The easy (but grossly inefficient) way:
 +
 +<code python>
 +import pylab
 +import time
 +import random
 +x=[]
 +pylab.figure(1)
 +pylab.subplot(111)
 +for i in range (50):
 +  x.append(random.randint(0,​100))
 +  pylab.cla()
 +  pylab.plot(x)
 +  time.sleep(1)
 +</​code>​
 +
 +====== Contour Plot ======
 +
 +===== Save Contour Plot as MIF =====
 +Here is a small function to save a contour plot as a MIF File (so it can be displayed in QGis etc.)
 +
 +<code python>
 +import numpy.random
 +import pylab
 +
 +def saveAsMIF(contour_plot,​ filename): ​       ​
 +    coll = contour_plot.collections
 +    ​
 +    mid=file("​%s.mid"​ %filename, "​w"​) ​
 +    mif=file("​%s.mif"​%filename,​ "​w"​)
 +    mif.write("""​Version 300\nCharset "​WindowsLatin1"​\nDelimiter ","​\nCOLUMNS 1\nLevel Integer\n"""​)
 +    mif.write("""​DATA\n"""​)
 +
 +    for level in range(0,​len(coll)):​
 +        for path in coll[level].get_paths():​
 +            polygon = path.to_polygons()[0]
 +    ​
 +            mif.write("​PLINE %d\n" % len(polygon))
 +            for c in polygon: ​
 +                mif.write("​%f %f\n" % (c[0], c[1]) )
 +            ​
 +            mid.write('"​%d""​\n'​ % level )                ​
 +    mid.close()
 +    mif.close()
 +
 +
 +# example
 +x=numpy.arange(100)/​100.0 + 16.0
 +y=numpy.arange(100)/​100.0 + 48.0
 +z= numpy.random.rand(100,​100)
 +C=pylab.contour(x,​y,​z)
 +saveAsMIF(C,"​test"​)
 +</​code>​
 +
 +
 +======= 3D plotting =======
 +3D support was dropped by matplotlib but there are alternatives. One is [[http://​code.enthought.com/​projects/​mayavi/​docs/​development/​html/​mayavi/​mlab.html Mayavi2'​s mlab API]].
 +
 +<​code>​sudo apt-get install mayavi2 </​code>​
 +
 +Then you can use it in your python scripts
 +
 +<code python>
 +from enthought.mayavi
 +import mlab
 +</​code>​
 +
 +
 +======= Resize Figure =======
 +<code python>
 +fig.set_size_inches(20,​15,​forward=True)
 +</​code>​
 +
 +
 +
 +====== Multiple Y-Axes ======
 +
 +<code python>
 +fig = pylab.figure()
 +ax1 = fig.add_subplot(111)
 +
 +# plot something on the first pair
 +ax1.plot(range(100))
 +ax1.axis(ymin=0,​ ymax=100) # set scale
 +
 +# get a second pair of axes and plot something else
 +ax2 = ax1.twinx()
 +ax2.plot(range(100))
 +ax2.axis(ymin=0,​ ymax=1000)
 +
 +</​code>​
 +
 +====== ggplot ======
 +
 +Pretty plots ahead - [[https://​github.com/​yhat/​ggplot|ggplot]] is a port of R's ggplot2, has tight integration with pandas and is easy to install.
 +
 +
 +<​code>​pip install ggplot</​code>​
 +
 +
 +You can also use it to switch plot styles in [[http://​matplotlib.org/​users/​style_sheets.html|matplotlib]]:​
 +
 +<​code>​
 +import matplotlib.pyplot as plt
 +plt.style.use('​ggplot'​)
 +</​code>​
 +
 +You need at least matplotlib 1.4.x, which might not be what your package provider offers. You can upgrade matplotlib with pip, but I ran into a quirk on Ubuntu 14.04 during installation. Here's a [[https://​mlbernauer.wordpress.com/​2014/​12/​06/​upgrading-from-matplotlib-1-3-1-to-1-4-1-in-ubuntu-14-04/​|quick fix]].
pylabrecipes.txt · Last modified: 2015/08/04 13:36 by mantis