Revision: 5014
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5014&view=rev
Author: jdh2358
Date: 2008-03-21 10:51:06 -0700 (Fri, 21 Mar 2008)
Log Message:
-----------
added api and event tutorials
Added Paths:
-----------
trunk/matplotlib/doc/artist_api_tut.txt
trunk/matplotlib/doc/event_handling_tut.txt
trunk/matplotlib/doc/figures/
trunk/matplotlib/doc/figures/dollar_ticks.py
trunk/matplotlib/doc/figures/fig_axes_customize_simple.py
trunk/matplotlib/doc/figures/fig_axes_labels_simple.py
trunk/matplotlib/doc/figures/make.py
trunk/matplotlib/doc/make.py
Added: trunk/matplotlib/doc/artist_api_tut.txt
===================================================================
--- trunk/matplotlib/doc/artist_api_tut.txt (rev 0)
+++ trunk/matplotlib/doc/artist_api_tut.txt 2008-03-21 17:51:06 UTC (rev
5014)
@@ -0,0 +1,597 @@
+The matplotlib Artist API tutorial
+==================================
+
+There are three layers to the matplotlib API. The FigureCanvas is the
+area onto which the figure is drawn, the Renderer is the object which
+knows how to draw on the FigureCanvas, and the Artist is the object
+that knows how to use a renderer to paint onto the canvas. The
+FigureCanvas and Renderer handle all the details of talking to user
+interface toolkits like wxpython or drawing languages like postscript,
+and the Artist handles all the high level constructs like
+representing and laying out the figure, text, and lines. The typical
+user will spend 95% of his time working with the Artists.
+
+There are two types Artists: primitives and containers. The
+primitives represent the standard graphical objects we want to paint
+onto our canvas: Line2D, Rectangle, Text, AxesImage, etc, and the
+containers are places to put them (Axis, Axes and Figure). The
+standard use is to create a Figure instance, use the Figure to create
+one or more Axes or Subplot instances, and use the Axes instance
+helper methods to create the primitives. In the example below, we
+create a Figure instance using pyplot.figure, which is a convenience
+method for instantiating Figure instances and connecting them with
+your user interface or drawing toolkit FigureCanvas. As we will
+discuss below, this is not necessary, and you can work directly with
+postscript, pdf gtk, or wxpython FigureCanvas es, instantiate your
+Figures directly and connect them yourselves, but since we are
+focusing here on the Artist API we'll let pyplot handle some of those
+details for us::
+
+ import matplotlib.pyplot as plt
+ fig = plt.figure()
+ ax = fig.add_subplot(2,1,1) # two rows, one column, first plot
+
+The Axes is probably the most important class in the matplotlib API,
+and the one you will be working with most of the time. This is
+because the Axes is the plotting area into which most of the objects
+go, and the Axes has many special helper methods (ax.plot, ax.text,
+ax.hist, ax.imshow) to create the most common graphics primitives
+(Line2D, Text, Rectangle, Image, respectively). These helper methods
+will take your data (eg numpy arrays and strings) create primitive
+Artist instances as needed (eg Line2D), add them to the relevant
+containers, and draw them when requested. Most of you are probably
+familiar with the Subplot, which is just a special case of an Axes
+that lives on a regular rows by columns grid of Subplot instances. If
+you want to create an Axes at an arbitrary location, simply use the
+add_axes method which takes a list of [left, bottom, width, height]
+values in 0-1 relative figure coordinates::
+
+ ax2 = fig.add_axes([0.15, 0.1, 0.7, 0.3])
+
+Continuing with our example::
+
+ import numpy as np
+ t = np.arange(0.0, 1.0, 0.01)
+ s = np.sin(2*np.pi*t)
+ line, = ax1.plot(t, s, color='blue', lw=2)
+
+In this example, ax is the Axes instance created by the
+fig.add_subplot call above (remember Subplot is just a subclass of
+Axes) and when you call ax.plot, it creates a Line2D instance and adds
+it the the Axes.lines list. In the interactive ipython session below,
+you can see that Axes.lines list is length one and contains the same
+line that was returned by the "line, ax.plot(x, y, 'o')" call::
+
+ In [101]: ax.lines[0]
+ Out[101]: <matplotlib.lines.Line2D instance at 0x19a95710>
+
+ In [102]: line
+ Out[102]: <matplotlib.lines.Line2D instance at 0x19a95710>
+
+If you make subsequent calls to ax.plot (and the hold state is "on"
+which is the default) then additional lines will be added to the list.
+You can remove lines later simply by calling the list methods; either
+of these will work::
+
+ del ax.lines[0]
+ ax.lines.remove(line) # one or the other, not both!
+
+The Axes also has helper methods to configure and decorate the xaxis
+and yaxis tick, ticklabels and axis labels::
+
+ xtext = ax.set_xlabel('my xdata') # returns a Text instance
+ ytext = ax.set_ylabel('my xdata')
+
+When you call ax.set_xlabel, it passes the information on the Text
+instance of the XAxis. Each Axes instance contains an xaxis and a
+yaxis instance, which handle the layout and drawing of the ticks, tick
+labels and axis labels.
+
+Here are the most important matplotlib modules that contain the
+classes referenced above
+
+=============== ==================
+Artist Module
+=============== ==================
+Artist matplotlib.artist
+Rectangle matplotlib.patches
+Line2D matplotlib.lines
+Axes matplotlib.axes
+XAxis and YAxis matplotlib.axis
+Figure matplotlib.figure
+Text matplotlib.text
+=============== ==================
+
+Try creating the figure below
+
+.. image:: figures/fig_axes_labels_simple.png
+ :scale: 75
+
+Customizing your objects
+========================
+
+Every element in the figure is represented by a matplotlib Artist, and
+each has an extensive list of properties to configure its appearance.
+The figure itself contains a Rectangle exactly the size of the figure,
+which you can use to set the background color and transparency of the
+figures. Likewise, each Axes bounding box (the standard white box
+with black edges in the typical matplotlib plot, has a Rectangle
+instance that determines the color, transparency, and other properties
+of the Axes. These instances are stored as member variables
+Figure.figurePatch and Axes.axesPatch ("Patch" is a name inherited
+from Matlab, and is a 2D "patch" of color on the figure, eg
+rectangles, circles and polygons). Every matplotlib Artist has the
+following properties
+
+==========
======================================================================
+Property Description
+==========
======================================================================
+alpha The transparency - a scalar from 0-1
+animated A boolean that is used to facilitate animated drawing
+axes The axes that the Artist lives in, possibly None
+clip_box The bounding box that clips the Artist
+clip_on Whether clipping is enabled
+clip_path The path the artist is clipped to
+contains A picking function to test whether the artist contains the pick
point
+figure The figure instance the aritst lives in, possibly None
+label A text label (eg for auto-labeling)
+picker A python object that controls object picking
+transform The transformation
+visible A boolean whether the artist should be drawn
+zorder A number which determines the drawing order
+==========
======================================================================
+
+Each of the properties is accessed with an old-fashioned setter or
+getter (yes we know this irritates pythonistas and we plan to support
+direct access via properties or traits but it hasn't been done yet).
+For example, to multiply the current alpha by a half::
+
+ a = o.get_alpha()
+ o.set_alpha(0.5*a)
+
+If you want to set a number of properties at once, you can also use
+the "set" method with keyword arguments. For example::
+
+ o.set(alpha=0.5, zorder=2)
+
+If you are working interactively at the python shell, a handy way to
+inspect the artist properties is to use the matplotlib.artist.getp
+method, which lists the properties and their values (simply "getp") in
+pylab. This works for classes derived from Artist as well, eg Figure
+and Rectangle. Here are the Figure rectangle properties mentioned above::
+
+
+ In [149]: matplotlib.artist.getp(fig.figurePatch)
+ alpha = 1.0
+ animated = False
+ antialiased or aa = True
+ axes = None
+ clip_box = None
+ clip_on = False
+ clip_path = None
+ contains = None
+ edgecolor or ec = w
+ facecolor or fc = 0.75
+ figure = Figure(8.125x6.125)
+ fill = 1
+ hatch = None
+ height = 1
+ label =
+ linewidth or lw = 1.0
+ picker = None
+ transform = <Affine object at 0x134cca84>
+ verts = ((0, 0), (0, 1), (1, 1), (1, 0))
+ visible = True
+ width = 1
+ window_extent = <Bbox object at 0x134acbcc>
+ x = 0
+ y = 0
+ zorder = 1
+
+The docstrings for all of the classes also contain the artist
+properties, so you can consult the interactive "help", the online html
+docs at http://matplotlib.sourceforge.net/classdocs.html or PDF documentation
+at http://matplotlib.sourceforge.net/api.pdf for a listing of
+properties for a give object.
+
+Getting at the objects to customize them
+========================================
+
+Now that we know how to inspect set the properties of a given
+object we want to configure, we need to now how to get at that
+object. As mentioned in the introduction, there are two kinds of
+objects: primitives and containers. The primitives are usually the
+things you want to configure (the font of a Text instance, the width
+of a Line2D) although the containers also have some properties as
+well -- for example the Axes Artist is a container that contains many
+of the primitives in your plot, but it also has properties like the
+xscale to control whether the xaxis is 'linear' or 'log'. In this
+section we'll review where the various container objects store the
+Artists that you want to get at.
+
+The Figure container
+--------------------
+
+The top level container Artist is the matplotlib.figure.Figure, and it
+contains everything in the figure. The background of the figure is a
+Rectangle which is stored in fig.figurePatch (where fig is your Figure
+instance). As you add subplots (fig.add_subplot) and axes
+(ax.add_axes)to the figure these will be appended to the fig.axes
+list. These are also returned by the methods that create them::
+
+ In [156]: fig = plt.figure()
+
+ In [157]: ax1 = fig.add_subplot(211)
+
+ In [158]: ax2 = fig.add_axes([0.1, 0.1, 0.7, 0.3])
+
+ In [159]: ax1
+ Out[159]: <matplotlib.axes.Subplot instance at 0xd54b26c>
+
+ In [160]: print fig.axes
+ [<matplotlib.axes.Subplot instance at 0xd54b26c>, <matplotlib.axes.Axes
instance at 0xd3f0b2c>]
+
+
+Because the figure maintains the concept of the "current axes" (see
+Figure.gca and Figure.sca) to support the pylab/pyplot state machine,
+you should not insert or remove axes directly from the axes list, but
+rather use the Figure.add_axes and Figure.add_subplot method to
+insert, and the Figure.delaxes methods to delete. You are free
+however, to iterate over the list of axes or index into it to get
+access to Axes instances you want to customize. Here is an example
+which turns all the axes grids on::
+
+ for ax in fig.axes:
+ ax.grid(True)
+
+
+The figure also has its own text, lines, patches and images, which you
+can use to add primitives directly. The default coordinate system for
+the Figure will simply be in pixels (which is not usually what you
+want) but you can control this by setting the transform property of
+the Artist you are adding to the figure. More useful is "figure
+coordinates" where 0,0 is the bottom, left of the figure and 1,1 is
+the top, right of the figure which you can obtain by setting the
+Artist transform to fig.transFigure::
+
+ In [191]: fig = plt.figure()
+
+ In [192]: l1 = matplotlib.lines.Line2D([0, 1], [0, 1],
transform=fig.transFigure, figure=fig)
+
+ In [193]: l2 = matplotlib.lines.Line2D([0, 1], [1, 0],
transform=fig.transFigure, figure=fig)
+
+ In [194]: fig.lines.extend([l1, l2])
+
+ In [195]: fig.canvas.draw()
+
+.. image:: figures/fig_x.png
+ :scale: 75
+
+
+Here is a summary of the Artists the figure contains
+
+================
===============================================================
+Figure attribute Description
+================
===============================================================
+axes A list of Axes instances (includes Subplot)
+figurePatch The Rectangle background
+images A list of FigureImages patches - useful for raw pixel
display
+legends A list of Figure Legend instances (different from
Axes.legends)
+lines A list of Figure Line2D instances (rarely used, see
Axes.lines)
+patches A list of Figure patches (rarely used, see Axes.patches)
+texts A list Figure Text instances
+================
===============================================================
+
+
+The Axes container
+------------------
+
+The matplotlib.axes.Axes is the center of the matplotlib universe --
+it contains the vast majority of all the Artists used in a figure with
+many helper methods to create and these Artists to itself, as well as
+helper methods to access and customize the Artists it contains. Like
+the Figure, it contains a Patch ax.axesPatch which is Rectangle for
+Cartesian coordinates and a Circle for polar coordinates; this patch
+determines the shape, background and border of the plotting region::
+
+ ax = fig.add_subplot(111)
+ rect = ax.axesPatch # a Rectangle instance
+ rect.set_facecolor('green')
+
+When you call a plotting method, eg the canonical "ax.plot" and pass
+in arrays or list of values, the method will a matplotlib.lines.Line2D
+instance, update the line with all the Line2D properties passed as
+keyword arguments, add the line to the Axes.lines container, and
+returns it to you::
+
+ In [213]: x, y = np.random.rand(2, 100)
+
+ In [214]: line, = ax.plot(x, y, '-', color='blue', linewidth=2)
+
+ax.plot returns a list of lines because you can pass in multiple x, y
+pairs to plot, and we are unpacking the first element of the length
+one list into the line variable. The line has been added to the
+ax.lines list::
+
+
+ In [229]: print ax.lines
+ [<matplotlib.lines.Line2D instance at 0xd378b0c>]
+
+Similarly, methods that create patches, like ax.bar creates a list of
+rectangles, will add the patches to the ax.patches list::
+
+ In [233]: n, bins, rectangles = ax.hist(np.random.randn(1000), 50,
facecolor='yellow')
+
+ In [234]: rectangles
+ Out[234]: <a list of 50 Patch objects>
+
+ In [235]: print len(ax.patches)
+
+You should not add objects directly to the ax.lines or ax.patches
+unless you know exactly what you are doing, because the Axes needs to
+do a few things when it creates and adds an object. It sets the figure
+and axes property of the Artist, as well as the default Axes
+transformation (unless a transformation is set). It also inspects the
+data contained in the Artist to update the data structures controlling
+auto-scaling, so that the view limits can be adjusted to contain the
+plotted data. You can, nonetheless, create objects yourself and add
+them directly to the Axes using helper methods like ax.add_line and
+ax.add_patch. Here is an annotated interactive session illustrating
+what is going on::
+
+ In [261]: fig = plt.figure()
+
+ In [262]: ax = fig.add_subplot(111)
+
+ # create a rectangle instance
+ In [263]: rect = matplotlib.patches.Rectangle( (1,1), width=5, height=12)
+
+ # by default the axes instance is None
+ In [264]: print rect.get_axes()
+ None
+
+ # and the transformation instance is set to the "identity transform"
+ In [265]: print rect.get_transform()
+ <Affine object at 0x13695544>
+
+ # now we add the Rectangle to the Axes
+ In [266]: ax.add_patch(rect)
+
+ # and notice that the ax.add_patch method has set the axes
+ # instance
+ In [267]: print rect.get_axes()
+ Subplot(49,81.25)
+
+ # and the transformation has been set too
+ In [268]: print rect.get_transform()
+ <Affine object at 0x15009ca4>
+
+ # the default axes transformation is ax.transData
+ In [269]: print ax.transData
+ <Affine object at 0x15009ca4>
+
+ # notice that the xlimits of the Axes have not been changed
+ In [270]: print ax.get_xlim()
+ (0.0, 1.0)
+
+ # but the data limits have been updated to encompass the rectangle
+ In [271]: print ax.dataLim.get_bounds()
+ (1.0, 1.0, 5.0, 12.0)
+
+ # we can manually invoke the auto-scaling machinery
+ In [272]: ax.autoscale_view()
+
+ # and now the xlim are updated to encompass the rectangle
+ In [273]: print ax.get_xlim()
+ (1.0, 6.0)
+
+ # we have to manually force a figure draw
+ In [274]: ax.figure.canvas.draw()
+
+
+There are many, many Axes helper methods for creating primitive
+Artists and adding them to their respective containers. The table
+below summarizes a small sampling of them, the kinds of Artist they
+create, and where they store them
+
+============================== ==================== =======================
+Helper method Artist Container
+============================== ==================== =======================
+ax.annotate - text annotations Annotate ax.texts
+ax.bar - bar charts Rectangle ax.patches
+ax.errorbar - error bar plots Line2D and Rectangle ax.lines and ax.patches
+ax.fill - shared area Polygon ax.patches
+ax.hist - histograms Rectangle ax.patches
+ax.imshow - image data AxesImage ax.images
+ax.legend - axes legends Legend ax.legends
+ax.plot - xy plots Line2D ax.lines
+ax.scatter - scatter charts PolygonCollection ax.collections
+ax.text - text Text ax.texts
+============================== ==================== =======================
+
+
+In addition to all of these Artists, the Axes contains two important
+Artist containers: the XAxis and YAxis, which handle the drawing of
+the ticks and labels. These are stored as instance variables xaxis
+and yaxis. The XAxis and YAxis containers will be detailed below, but
+note that the Axes contains many helper methods which forward calls on
+to the Axis instances so you often do not need to work with them
+directly unless you want to. For example, you can set the fontsize of
+the XAxis ticklabels using the Axes helper method::
+
+ for label in ax.get_xticklabels():
+ label.set_color('orange')
+
+Below is a summary of the Artists that the Axes contains
+
+============== ======================================
+Axes attribute Description
+============== ======================================
+artists A list of Artist instances
+axesPatch Rectangle instance for Axes background
+collections A list of Collection instances
+images A list of AxesImage
+legends A list of Legend instances
+lines A list of Line2D instances
+patches A list of Patch instances
+texts A list of Text instances
+xaxis matplotlib.axis.XAxis instance
+yaxis matplotlib.axis.YAxis instance
+============== ======================================
+
+The Axis containers
+-------------------
+
+The matplotlib.axis.Axis instances handle the drawing of the tick lines, the
grid
+lines, the tick labels and the axis label. You can configure the left
+and right ticks separately for the y axis, and the upper and lower
+ticks separately for the x axis. The axis also stores the data and view
+intervals used in auto-scaling, panning and zooming, as well as the
+locator and formatter instances which control where the ticks are
+placed and how they are represented as strings.
+
+Each axis object contains a label attribute (this is what the pylab
+calls to xlabel and ylabel set) as well as a list of major and minor
+ticks. The ticks are XTick and YTick instances, which contain the
+actual line and text primitives that render the ticks and ticklabels.
+Because the ticks are dynamically created as needed (eg when panning
+and zooming), you should access the lists of major and minor ticks
+through their accessor methods axis.get_major_ticks() and
+axis.get_minor_ticks(). Although the ticks contain all the primitives
+and will be covered below, the Axis methods contain accessor methods
+to return the tick lines, tick labels, tick locations etc....::
+
+ In [285]: axis = ax.xaxis
+
+ In [286]: axis.get_ticklocs()
+ Out[286]: array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
+
+ In [287]: axis.get_ticklabels()
+ Out[287]: <a list of 10 Text major ticklabel objects>
+
+ # note there are twice as many ticklines as labels because by
+ # default there are tick lines at the top and bottom but only tick
+ # labels below the xaxis; this can be customized
+ In [288]: axis.get_ticklines()
+ Out[288]: <a list of 20 Line2D ticklines objects>
+
+ # by default you get the major ticks back
+ In [291]: axis.get_ticklines()
+ Out[291]: <a list of 20 Line2D ticklines objects>
+
+ # but you can also ask for the minor ticks
+ In [292]: axis.get_ticklines(minor=True)
+ Out[292]: <a list of 0 Line2D ticklines objects>
+
+Here is a summary of some of the useful accessor methods of the Axis
+(these have corresponding setters where useful, such as
+set_major_formatter)
+
+======================
=========================================================
+Accessor method Description
+======================
=========================================================
+get_scale The scale of the axis, eg 'log' or 'linear'
+get_view_interval The interval instance of the axis view limits
+get_data_interval The interval instance of the axis data limits
+get_gridlines A list of grid lines for the Axis
+get_label The axis label - a Text instance
+get_ticklabels A list of Text instances - keyword minor=True|False
+get_ticklines A list of Line2D instances - keyword minor=True|False
+get_ticklocs A list of Tick locations - keyword minor=True|False
+get_major_locator The matplotlib.ticker.Locator instance for major ticks
+get_major_formatter The matplotlib.ticker.Formatter instance for major
ticks
+get_minor_locator The matplotlib.ticker.Locator instance for minor ticks
+get_minor_formatter The matplotlib.ticker.Formatter instance for minor
ticks
+get_major_ticks A list of Tick instances for major ticks
+get_minor_ticks A list of Tick instances for minor ticks
+grid Turn the grid on or off for the major or minor ticks
+======================
=========================================================
+
+Try creating the figure below
+
+.. image:: figures/fig_axes_customize_simple.png
+ :scale: 75
+
+Exercise solution::
+
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ # plt.figure creates a matplotlib.figure.Figure instance
+ fig = plt.figure()
+ rect = fig.figurePatch # a rectangle instance
+ rect.set_facecolor('lightgoldenrodyellow')
+
+ ax1 = fig.add_axes([0.1, 0.3, 0.4, 0.4])
+ rect = ax1.axesPatch
+ rect.set_facecolor('lightslategray')
+
+
+ for label in ax1.xaxis.get_ticklabels():
+ # label is a Text instance
+ label.set_color('red')
+ label.set_rotation(45)
+ label.set_fontsize(16)
+
+ for line in ax1.yaxis.get_ticklines():
+ # line is a Line2D instance
+ line.set_color('green')
+ line.set_markersize(25)
+ line.set_markeredgewidth(3)
+
+ fig.savefig('figures/fig_axes_customize_simple.png', dpi=150)
+ fig.savefig('figures/fig_axes_customize_simple.eps')
+ plt.show()
+
+
+
+The Tick containers
+-------------------
+
+The matplotlib.axis.Tick is the final container object in our descent
+from the Figure to the Axes to the Axis to the Tick. The Tick
+contains the tick and grid line instances, as well as the label
+instances for the upper and lower ticks. Each of these is accessible
+directly as an attribute of the Tick. In addition, there are boolean
+variables that determine whether the upper labels and ticks are on for
+the xaxis and whether the right labels and ticks are on for the yaxis.
+
+============== ==========================================================
+Tick attribute Description
+============== ==========================================================
+tick1line Line2D instance
+tick2line Line2D instance
+gridline Line2D instance
+label1 Text instance
+label2 Text instance
+gridOn boolean which determines whether to draw the tickline
+tick1On boolean which determines whether to draw the 1st tickline
+tick2On boolean which determines whether to draw the 2nd tickline
+label1On boolean which determines whether to draw tick label
+label2On boolean which determines whether to draw tick label
+============== ==========================================================
+
+Here is an example which sets the formatter for the upper ticks with
+dollar signs and colors them green on the right side of the yaxis::
+
+ import numpy as np
+ import matplotlib.pyplot as plt
+ import matplotlib.ticker as ticker
+
+ fig = plt.figure()
+ ax = fig.add_subplot(111)
+ ax.plot(100*np.random.rand(20))
+
+ formatter = ticker.FormatStrFormatter('$%1.2f')
+ ax.yaxis.set_major_formatter(formatter)
+
+ for tick in ax.yaxis.get_major_ticks():
+ tick.label1On = False
+ tick.label2On = True
+ tick.label2.set_color('green')
+
+ plt.show()
+
+
+.. image:: figures/dollar_ticks.png
+ :scale: 75
Added: trunk/matplotlib/doc/event_handling_tut.txt
===================================================================
--- trunk/matplotlib/doc/event_handling_tut.txt (rev 0)
+++ trunk/matplotlib/doc/event_handling_tut.txt 2008-03-21 17:51:06 UTC (rev
5014)
@@ -0,0 +1,470 @@
+Event Handling and Picking Tutorial
+===================================
+
+matplotlib works with 5 user interface toolkits (wxpython, tkinter,
+qt, gtk and fltk) and in order to support features like interactive
+panning and zooming of figures, it is helpful to the developers to
+have an API for interacting with the figure via key presses and mouse
+movements that is "GUI neutral" so we don't have to repeat a lot of
+code across the different user interfaces. Although the event
+handling API is GUI neutral, it is based on the GTK model, which was
+the first user interface matplotlib supported. The events that are
+triggered are also a bit richer vis-a-vis matplotlib than standard GUI
+events, including information like which Axes the event occurred in.
+The events also understand the matplotlib coordinate system, and
+report event locations in both pixel and data coordinates.
+
+
+Event connections
+=================
+
+To receive events, you need to write a callback function and then
+connect your function to the event manager, which is part of the
+FigureCanvas. Here is a simple example that prints the location of
+the mouse click and which button was pressed::
+
+ fig = plt.figure()
+ ax = fig.add_subplot(111)
+ ax.plot(np.random.rand(10))
+
+ def onclick(event):
+ print 'button=%d, x=%d, y=%d, xdata=%f, ydata=%f'%(
+ event.button, event.x, event.y, event.xdata, event.ydata)
+
+ cid = fig.canvas.mpl_connect('button_press_event', onclick)
+
+The FigureCanvas method mpl_connect returns a connection id which is
+simply an integer. When you want to disconnect the callback, just
+call::
+
+ fig.canvas.mpl_disconnect(cid)
+
+Here are the events that you can connect to, the class instances that
+are sent back to you when the event occurs, and the event descriptions
+
+
+===================== =========== ===================================
+Event name Class Description
+===================== =========== ===================================
+button_press_event MouseEvent mouse button is pressed
+button_release_event MouseEvent mouse button is released
+draw_event DrawEvent canvas draw
+key_press_event KeyEvent key is pressed
+key_release_event KeyEvent key is released
+motion_notify_event MouseEvent mouse motion
+pick_event PickEvent an object in the canvas is selected
+resize_event ResizeEvent figure canvas is resized
+scroll_event MouseEvent mouse scroll wheel is rolled
+===================== =========== ===================================
+
+
+Event attributes
+================
+
+All matplotlib events inherit from the base class
+matplotlib.backend_bases.Event, which store the attributes
+
+=============== =================================================
+Event attribute Description
+=============== =================================================
+name the event name
+canvas the FigureCanvas instance generating the event
+guiEvent the GUI event that triggered the matplotlib event
+=============== =================================================
+
+The most common events that are the bread and butter of event handling
+are key press/release events and mouse press/release and movement
+events. The KeyEvent and MouseEvent classes that handle these events
+are both derived from the LocationEvent, which has the following
+attributes
+
+======================= ========================================
+LocationEvent attribute Description
+======================= ========================================
+x x position - pixels from left of canvas
+y y position - pixels from right of canvas
+button button pressed None, 1, 2, 3
+inaxes the Axes instance if mouse us over axes
+xdata x coord of mouse in data coords
+ydata y coord of mouse in data coords
+======================= ========================================
+
+Let's look a simple example of a canvas, where a simple line segment
+is created every time a mouse is pressed::
+
+ class LineBuilder:
+ def __init__(self, line):
+ self.line = line
+ self.xs = list(line.get_xdata())
+ self.ys = list(line.get_ydata())
+ self.cid = line.figure.canvas.mpl_connect('button_press_event',
self)
+
+ def __call__(self, event):
+ print 'click', event
+ if event.inaxes!=self.line.axes: return
+ self.xs.append(event.xdata)
+ self.ys.append(event.ydata)
+ self.line.set_data(self.xs, self.ys)
+ self.line.figure.canvas.draw()
+
+ fig = plt.figure()
+ ax = fig.add_subplot(111)
+ ax.set_title('click to build line segments')
+ line, = ax.plot([0], [0]) # empty line
+ linebuilder = LineBuilder(line)
+
+
+
+The MouseEvent that we just used is a LocationEvent, so we have access
+to the data and pixel coordinates in event.x and event.xdata. In
+addition to the LocationEvent attributes, it has
+
+====================
==============================================================
+MouseEvent attribute Description
+====================
==============================================================
+button button pressed None, 1, 2, 3
+key the key pressed: None, chr(range(255)), shift, win, or
control
+====================
==============================================================
+
+Draggable Rectangle Exercise
+----------------------------
+
+Write draggable rectangle class that is initialized with a Rectangle
+instance but will move its x,y location when dragged. Hint: you will
+need to store the orginal xy location of the rectangle which is stored
+as rect.xy and connect to the press, motion and release mouse events.
+When the mouse is pressed, check to see if the click occurs over your
+rectangle (see rect.contains) and if it does, store the rectangle xy
+and the location of the mouse click in data coords. In the motion
+event callback, compute the deltax and deltay of the mouse movement,
+and add those deltas to the origin of the rectangle you stored. The
+redraw the figure. On the button release event, just reset all the
+button press data you stored as None.
+
+Here is the solution::
+
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ class DraggableRectangle:
+ def __init__(self, rect):
+ self.rect = rect
+ self.press = None
+
+ def connect(self):
+ 'connect to all the events we need'
+ self.cidpress = self.rect.figure.canvas.mpl_connect(
+ 'button_press_event', self.on_press)
+ self.cidrelease = self.rect.figure.canvas.mpl_connect(
+ 'button_release_event', self.on_release)
+ self.cidmotion = self.rect.figure.canvas.mpl_connect(
+ 'motion_notify_event', self.on_motion)
+
+ def on_press(self, event):
+ 'on button press we will see if the mouse is over us and store
some data'
+ if event.inaxes != self.rect.axes: return
+
+ contains, attrd = self.rect.contains(event)
+ if not contains: return
+ print 'event contains', self.rect.xy
+ x0, y0 = self.rect.xy
+ self.press = x0, y0, event.xdata, event.ydata
+
+ def on_motion(self, event):
+ 'on motion we will move the rect if the mouse is over us'
+ if self.press is None: return
+ if event.inaxes != self.rect.axes: return
+ x0, y0, xpress, ypress = self.press
+ dx = event.xdata - xpress
+ dy = event.ydata - ypress
+ #print 'x0=%f, xpress=%f, event.xdata=%f, dx=%f, x0+dx=%f'%(x0,
xpress, event.xdata, dx, x0+dx)
+ self.rect.set_x(x0+dx)
+ self.rect.set_y(y0+dy)
+
+ self.rect.figure.canvas.draw()
+
+
+ def on_release(self, event):
+ 'on release we reset the press data'
+ self.press = None
+ self.rect.figure.canvas.draw()
+
+ def disconnect(self):
+ 'disconnect all the stored connection ids'
+ self.rect.figure.canvas.mpl_disconnect(self.cidpress)
+ self.rect.figure.canvas.mpl_disconnect(self.cidrelease)
+ self.rect.figure.canvas.mpl_disconnect(self.cidmotion)
+
+ fig = plt.figure()
+ ax = fig.add_subplot(111)
+ rects = ax.bar(range(10), 20*np.random.rand(10))
+ drs = []
+ for rect in rects:
+ dr = DraggableRectangle(rect)
+ dr.connect()
+ drs.append(dr)
+
+ plt.show()
+
+
+**Extra credit**: use the animation blit techniques discussed at
+http://www.scipy.org/Cookbook/Matplotlib/Animations to make the
+animated drawing faster and smoother.
+
+Extra credit solution::
+
+ # draggable rectangle with the animation blit techniques; see
+ # http://www.scipy.org/Cookbook/Matplotlib/Animations
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ class DraggableRectangle:
+ lock = None # only one can be animated at a time
+ def __init__(self, rect):
+ self.rect = rect
+ self.press = None
+ self.background = None
+
+ def connect(self):
+ 'connect to all the events we need'
+ self.cidpress = self.rect.figure.canvas.mpl_connect(
+ 'button_press_event', self.on_press)
+ self.cidrelease = self.rect.figure.canvas.mpl_connect(
+ 'button_release_event', self.on_release)
+ self.cidmotion = self.rect.figure.canvas.mpl_connect(
+ 'motion_notify_event', self.on_motion)
+
+ def on_press(self, event):
+ 'on button press we will see if the mouse is over us and store
some data'
+ if event.inaxes != self.rect.axes: return
+ if DraggableRectangle.lock is not None: return
+ contains, attrd = self.rect.contains(event)
+ if not contains: return
+ print 'event contains', self.rect.xy
+ x0, y0 = self.rect.xy
+ self.press = x0, y0, event.xdata, event.ydata
+ DraggableRectangle.lock = self
+
+ # draw everything but the selected rectangle and store the pixel
buffer
+ canvas = self.rect.figure.canvas
+ axes = self.rect.axes
+ self.rect.set_animated(True)
+ canvas.draw()
+ self.background = canvas.copy_from_bbox(self.rect.axes.bbox)
+
+ # now redraw just the rectangle
+ axes.draw_artist(self.rect)
+
+ # and blit just the redrawn area
+ canvas.blit(axes.bbox)
+
+ def on_motion(self, event):
+ 'on motion we will move the rect if the mouse is over us'
+ if DraggableRectangle.lock is not self:
+ return
+ if event.inaxes != self.rect.axes: return
+ x0, y0, xpress, ypress = self.press
+ dx = event.xdata - xpress
+ dy = event.ydata - ypress
+ self.rect.set_x(x0+dx)
+ self.rect.set_y(y0+dy)
+
+
+ canvas = self.rect.figure.canvas
+ axes = self.rect.axes
+ # restore the background region
+ canvas.restore_region(self.background)
+
+ # redraw just the current rectangle
+ axes.draw_artist(self.rect)
+
+ # blit just the redrawn area
+ canvas.blit(axes.bbox)
+
+
+
+ def on_release(self, event):
+ 'on release we reset the press data'
+ if DraggableRectangle.lock is not self:
+ return
+
+ self.press = None
+ DraggableRectangle.lock = None
+
+ # turn off the rect animation property and reset the background
+ self.rect.set_animated(False)
+ self.background = None
+
+ # redraw the full figure
+ self.rect.figure.canvas.draw()
+ def disconnect(self):
+ 'disconnect all the stored connection ids'
+ self.rect.figure.canvas.mpl_disconnect(self.cidpress)
+ self.rect.figure.canvas.mpl_disconnect(self.cidrelease)
+ self.rect.figure.canvas.mpl_disconnect(self.cidmotion)
+
+ fig = plt.figure()
+ ax = fig.add_subplot(111)
+ rects = ax.bar(range(10), 20*np.random.rand(10))
+ drs = []
+ for rect in rects:
+ dr = DraggableRectangle(rect)
+ dr.connect()
+ drs.append(dr)
+
+ plt.show()
+
+
+Object Picking
+==============
+
+You can enable picking by setting the ``picker`` property of an Artist
+(eg a matplotlib Line2D, Text, Patch, Polygon, AxesImage,
+etc...)
+
+There are a variety of meanings of the picker property:
+
+- None : picking is disabled for this artist (default)
+
+- boolean : if True then picking will be enabled and the artist will
+ fire a pick event if the mouse event is over the artist
+
+- float : if picker is a number it is interpreted as an epsilon
+ tolerance in points and the the artist will fire off an event if its
+ data is within epsilon of the mouse event. For some artists like
+ lines and patch collections, the artist may provide additional data
+ to the pick event that is generated, eg the indices of the data
+ within epsilon of the pick event.
+
+- function : if picker is callable, it is a user supplied function
+ which determines whether the artist is hit by the mouse event. The
+ signature is ``hit, props = picker(artist, mouseevent)`` to
+ determine the hit test. If the mouse event is over the artist,
+ return hit=True and props is a dictionary of properties you want
+ added to the PickEvent attributes
+
+
+After you have enabled an artist for picking by setting the ``picker``
+property, you need to connect to the figure canvas pick_event to get
+pick callbacks on mouse press events. Eg::
+
+ def pick_handler(event):
+ mouseevent = event.mouseevent
+ artist = event.artist
+ # now do something with this...
+
+
+The pick event (matplotlib.backend_bases.PickEvent) which is passed to
+your callback is always fired with two attributes:
+
+- mouseevent : the mouse event that generate the pick event. The
+ mouse event in turn has attributes like x and y (the coords in
+ display space, eg pixels from left, bottom) and xdata, ydata (the
+ coords in data space). Additionally, you can get information about
+ which buttons were pressed, which keys were pressed, which Axes the
+ mouse is over, etc. See matplotlib.backend_bases.MouseEvent for
+ details.
+
+- artist : the matplotlib.artist that generated the pick event.
+
+Additionally, certain artists like Line2D and PatchCollection may
+attach additional meta data like the indices into the data that meet
+the picker criteria (eg all the points in the line that are within the
+specified epsilon tolerance)
+
+Simple picking example
+----------------------
+
+In the example below, we set the line picker property to a scalar, so
+it represents a tolerance in points (72 points per inch). The onpick
+callback function will be called when the pick event it within the
+tolerance distance from the line, and has the indices of the data
+vertices that are within the pick distance tolerance. Our onpick
+callback function simply prints the data that are under the pick
+location. Different matplotlib Artists can attach different data to
+the PickEvent. For example, Line2D attaches the ind property, which
+are the indices into the line data under the pick point. See
+Line2D.pick for details on the PickEvent properties of the line. Here
+is the code::
+
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ fig = plt.figure()
+ ax = fig.add_subplot(111)
+ ax.set_title('click on points')
+
+ line, = ax.plot(np.random.rand(100), 'o', picker=5) # 5 points tolerance
+
+ def onpick(event):
+ thisline = event.artist
+ xdata = thisline.get_xdata()
+ ydata = thisline.get_ydata()
+ ind = event.ind
+ print 'onpick points:', zip(xdata[ind], ydata[ind])
+
+ fig.canvas.mpl_connect('pick_event', onpick)
+
+ plt.show()
+
+
+Picking Exercise
+----------------
+
+Create a data set of 100 arrays of 1000 Gaussian random numbers and
+compute the sample mean and standard deviation of each of them (hint:
+numpy arrays have a mean and std method) and make a xy marker plot of
+the 100 means vs the 100 standard deviations. Connect the line
+created by the plot command to the pick event, and plot the original
+time series of the data that generated the clicked on points. If more
+than one point is within the tolerance of the clicked on point, you
+can use multiple subplots to plot the multiple time series.
+
+Exercise solution::
+
+ """
+ compute the mean and stddev of 100 data sets and plot mean vs stddev.
+ When you click on one of the mu, sigma points, plot the raw data from
+ the dataset that generated the mean and stddev
+ """
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ X = np.random.rand(100, 1000)
+ xs = np.mean(X, axis=1)
+ ys = np.std(X, axis=1)
+
+ fig = plt.figure()
+ ax = fig.add_subplot(111)
+ ax.set_title('click on point to plot time series')
+ line, = ax.plot(xs, ys, 'o', picker=5) # 5 points tolerance
+
+
+ def onpick(event):
+
+ if event.artist!=line: return True
+
+ N = len(event.ind)
+ if not N: return True
+
+
+ figi = plt.figure()
+ for subplotnum, dataind in enumerate(event.ind):
+ ax = figi.add_subplot(N,1,subplotnum+1)
+ ax.plot(X[dataind])
+ ax.text(0.05, 0.9, 'mu=%1.3f\nsigma=%1.3f'%(xs[dataind],
ys[dataind]),
+ transform=ax.transAxes, va='top')
+ ax.set_ylim(-0.5, 1.5)
+ figi.show()
+ return True
+
+ fig.canvas.mpl_connect('pick_event', onpick)
+
+ plt.show()
+
+
+
+
+
+
+
Added: trunk/matplotlib/doc/figures/dollar_ticks.py
===================================================================
--- trunk/matplotlib/doc/figures/dollar_ticks.py
(rev 0)
+++ trunk/matplotlib/doc/figures/dollar_ticks.py 2008-03-21 17:51:06 UTC
(rev 5014)
@@ -0,0 +1,20 @@
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.ticker as ticker
+
+fig = plt.figure()
+ax = fig.add_subplot(111)
+ax.plot(100*np.random.rand(20))
+
+formatter = ticker.FormatStrFormatter('$%1.2f')
+ax.yaxis.set_major_formatter(formatter)
+
+for tick in ax.yaxis.get_major_ticks():
+ tick.label1On = False
+ tick.label2On = True
+ tick.label2.set_color('green')
+
+fig.savefig('dollar_ticks')
+plt.show()
+
+
Added: trunk/matplotlib/doc/figures/fig_axes_customize_simple.py
===================================================================
--- trunk/matplotlib/doc/figures/fig_axes_customize_simple.py
(rev 0)
+++ trunk/matplotlib/doc/figures/fig_axes_customize_simple.py 2008-03-21
17:51:06 UTC (rev 5014)
@@ -0,0 +1,29 @@
+import numpy as np
+import matplotlib.pyplot as plt
+
+# plt.figure creates a matplotlib.figure.Figure instance
+fig = plt.figure()
+rect = fig.figurePatch # a rectangle instance
+rect.set_facecolor('lightgoldenrodyellow')
+
+ax1 = fig.add_axes([0.1, 0.3, 0.4, 0.4])
+rect = ax1.axesPatch
+rect.set_facecolor('lightslategray')
+
+
+for label in ax1.xaxis.get_ticklabels():
+ # label is a Text instance
+ label.set_color('red')
+ label.set_rotation(45)
+ label.set_fontsize(16)
+
+for line in ax1.yaxis.get_ticklines():
+ # line is a Line2D instance
+ line.set_color('green')
+ line.set_markersize(25)
+ line.set_markeredgewidth(3)
+
+
+fig.savefig('fig_axes_customize_simple')
+
+plt.show()
Added: trunk/matplotlib/doc/figures/fig_axes_labels_simple.py
===================================================================
--- trunk/matplotlib/doc/figures/fig_axes_labels_simple.py
(rev 0)
+++ trunk/matplotlib/doc/figures/fig_axes_labels_simple.py 2008-03-21
17:51:06 UTC (rev 5014)
@@ -0,0 +1,21 @@
+import numpy as np
+import matplotlib.pyplot as plt
+
+fig = plt.figure()
+fig.subplots_adjust(top=0.8)
+ax1 = fig.add_subplot(211)
+ax1.set_ylabel('volts')
+ax1.set_title('a sine wave')
+
+t = np.arange(0.0, 1.0, 0.01)
+s = np.sin(2*np.pi*t)
+line, = ax1.plot(t, s, color='blue', lw=2)
+
+ax2 = fig.add_axes([0.15, 0.1, 0.7, 0.3])
+n, bins, patches = ax2.hist(np.random.randn(1000), 50,
+ facecolor='yellow', edgecolor='yellow')
+ax2.set_xlabel('time (s)')
+
+fig.savefig('fig_axes_labels_simple')
+
+plt.show()
Added: trunk/matplotlib/doc/figures/make.py
===================================================================
--- trunk/matplotlib/doc/figures/make.py (rev 0)
+++ trunk/matplotlib/doc/figures/make.py 2008-03-21 17:51:06 UTC (rev
5014)
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+import sys, os, glob
+import matplotlib
+matplotlib.use('Agg')
+
+def figs():
+ # each one of these will make a figure when imported
+ import dollar_ticks
+ import fig_axes_customize_simple
+ import fig_axes_labels_simple
+
+ print 'all figures made'
+ for fname in glob.glob('*.pyc'):
+ os.remove(fname)
+
+def clean():
+ patterns = ['#*', '*~', '*.png']
+ for pattern in patterns:
+ for fname in glob.glob(pattern):
+ os.remove(fname)
+ print 'all clean'
+
+
+
+def all():
+ figs()
+
+funcd = {'figs':figs,
+ 'clean':clean,
+ 'all':all,
+ }
+
+if len(sys.argv)>1:
+ for arg in sys.argv[1:]:
+ func = funcd.get(arg)
+ if func is None:
+ raise SystemExit('Do not know how to handle %s; valid args are'%(
+ arg, funcd.keys()))
+ func()
+else:
+ all()
+
+
+
+
Property changes on: trunk/matplotlib/doc/figures/make.py
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/matplotlib/doc/make.py
===================================================================
--- trunk/matplotlib/doc/make.py (rev 0)
+++ trunk/matplotlib/doc/make.py 2008-03-21 17:51:06 UTC (rev 5014)
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+import os, sys, glob
+
+def check_png():
+ if not len(glob.glob('figures/*.png')):
+ raise SystemExit('No PNG files in figures dir; please run make.py in
the figures directory first')
+
+def check_rst2latex():
+ sin, sout = os.popen2('which rst2latex')
+ if not sout.read():
+ raise SystemExit('Build requires rst2latex')
+
+def check_pdflatex():
+ sin, sout = os.popen2('which pdflatex')
+ if not sout.read():
+ raise SystemExit('Build requires pdflatex')
+
+
+
+
+def artist_tut():
+ check_png()
+ check_rst2latex()
+ check_pdflatex()
+ os.system('rst2latex artist_api_tut.txt > artist_api_tut.tex')
+ os.system('pdflatex artist_api_tut.tex')
+
+
+def event_tut():
+ check_png()
+ check_rst2latex()
+ check_pdflatex()
+ os.system('rst2latex event_handling_tut.txt > event_handling_tut.tex')
+ os.system('pdflatex event_handling_tut.tex')
+
+def clean():
+ patterns = ['#*', '*~', '*.tex', '*.log', '*.out', '*.aux']
+ for pattern in patterns:
+ for fname in glob.glob(pattern):
+ os.remove(fname)
+ print 'all clean'
+
+def all():
+ artist_tut()
+ event_tut()
+
+funcd = {'artist_tut': artist_tut,
+ 'event_tut': event_tut,
+ 'clean': clean,
+ 'all': all,
+ }
+
+if len(sys.argv)>1:
+ for arg in sys.argv[1:]:
+ func = funcd.get(arg)
+ if func is None:
+ raise SystemExit('Do not know how to handle %s; valid args are'%(
+ arg, funcd.keys()))
+ func()
+else:
+ all()
+
+
+
+
+
+
+
+
+
+
Property changes on: trunk/matplotlib/doc/make.py
___________________________________________________________________
Name: svn:executable
+ *
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins