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

Reply via email to