You can subscribe to this list here.
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(115) |
Aug
(120) |
Sep
(137) |
Oct
(170) |
Nov
(461) |
Dec
(263) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2008 |
Jan
(120) |
Feb
(74) |
Mar
(35) |
Apr
(74) |
May
(245) |
Jun
(356) |
Jul
(240) |
Aug
(115) |
Sep
(78) |
Oct
(225) |
Nov
(98) |
Dec
(271) |
2009 |
Jan
(132) |
Feb
(84) |
Mar
(74) |
Apr
(56) |
May
(90) |
Jun
(79) |
Jul
(83) |
Aug
(296) |
Sep
(214) |
Oct
(76) |
Nov
(82) |
Dec
(66) |
2010 |
Jan
(46) |
Feb
(58) |
Mar
(51) |
Apr
(77) |
May
(58) |
Jun
(126) |
Jul
(128) |
Aug
(64) |
Sep
(50) |
Oct
(44) |
Nov
(48) |
Dec
(54) |
2011 |
Jan
(68) |
Feb
(52) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <md...@us...> - 2010-06-02 02:22:22
|
Revision: 8365 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8365&view=rev Author: mdehoon Date: 2010-06-02 02:22:16 +0000 (Wed, 02 Jun 2010) Log Message: ----------- Check if Python is installed as a framework, and print a warning otherwise. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py Modified: trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py 2010-06-01 19:06:28 UTC (rev 8364) +++ trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py 2010-06-02 02:22:16 UTC (rev 8365) @@ -2,6 +2,7 @@ import os import numpy +import MacOS from matplotlib._pylab_helpers import Gcf from matplotlib.backend_bases import RendererBase, GraphicsContextBase,\ @@ -222,6 +223,9 @@ """ Create a new figure manager instance """ + if not MacOS.WMAvailable(): + import warnings + warnings.warn("Python is not installed as a framework. The MacOSX backend may not work correctly if Python is not installed as a framework. Please see the Python documentation for more information on installing Python as a framework on Mac OS X") FigureClass = kwargs.pop('FigureClass', Figure) figure = FigureClass(*args, **kwargs) canvas = FigureCanvasMac(figure) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2010-06-01 19:06:35
|
Revision: 8364 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8364&view=rev Author: mdboom Date: 2010-06-01 19:06:28 +0000 (Tue, 01 Jun 2010) Log Message: ----------- Fix compiler warnings. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/delaunay/_delaunay.cpp trunk/matplotlib/lib/matplotlib/tri/_tri.cpp trunk/matplotlib/src/_path.cpp trunk/matplotlib/src/cntr.c trunk/matplotlib/src/path_converters.h Modified: trunk/matplotlib/lib/matplotlib/delaunay/_delaunay.cpp =================================================================== --- trunk/matplotlib/lib/matplotlib/delaunay/_delaunay.cpp 2010-06-01 19:04:17 UTC (rev 8363) +++ trunk/matplotlib/lib/matplotlib/delaunay/_delaunay.cpp 2010-06-01 19:06:28 UTC (rev 8364) @@ -12,8 +12,8 @@ extern "C" { -static void reorder_edges(int npoints, int ntriangles, - double *x, double *y, +static void reorder_edges(int npoints, int ntriangles, + double *x, double *y, int *edge_db, int *tri_edges, int *tri_nbrs) { int neighbors[3], nodes[3]; @@ -69,7 +69,7 @@ // Not trusting me? Okay, let's go through it: // We have three edges to deal with and three nodes. Without loss - // of generality, let's label the nodes A, B, and C with (A, B) + // of generality, let's label the nodes A, B, and C with (A, B) // forming the first edge in the order they arrive on input. // Then there are eight possibilities as to how the other edge-tuples // may be labeled, but only two variations that are going to affect the @@ -85,7 +85,7 @@ // The second test we need to perform is for counter-clockwiseness. // Again, there are only two variations that will affect the outcome: // either ABC is counter-clockwise, or it isn't. In the former case, - // we're done setting the node order, we just need to associate the + // we're done setting the node order, we just need to associate the // appropriate neighbor triangles with their opposite nodes, something // which can be done by inspection. In the latter case, to order the // nodes counter-clockwise, we only have to switch B and C to get @@ -113,7 +113,7 @@ static PyObject* getMesh(int npoints, double *x, double *y) { - PyObject *vertices, *edge_db, *tri_edges, *tri_nbrs; + PyObject *vertices = NULL, *edge_db = NULL, *tri_edges = NULL, *tri_nbrs = NULL; PyObject *temp; int tri0, tri1, reg0, reg1; double tri0x, tri0y, tri1x, tri1y; @@ -138,7 +138,7 @@ edge_db = PyArray_SimpleNew(2, dim, PyArray_INT); if (!edge_db) goto fail; edge_db_ptr = (int*)PyArray_DATA(edge_db); - + dim[0] = numtri; vertices = PyArray_SimpleNew(2, dim, PyArray_DOUBLE); if (!vertices) goto fail; @@ -192,7 +192,7 @@ // tri_edges contains lists of edges; convert to lists of nodes in // counterclockwise order and reorder tri_nbrs to match. Each node // corresponds to the edge opposite it in the triangle. - reorder_edges(npoints, numtri, x, y, edge_db_ptr, tri_edges_ptr, + reorder_edges(npoints, numtri, x, y, edge_db_ptr, tri_edges_ptr, tri_nbrs_ptr); temp = Py_BuildValue("(OOOO)", vertices, edge_db, tri_edges, tri_nbrs); @@ -221,7 +221,7 @@ int i; double *planes_ptr; double x02, y02, z02, x12, y12, z12, xy0212; - + dims[0] = ntriangles; dims[1] = 3; planes = PyArray_SimpleNew(2, dims, PyArray_DOUBLE); @@ -240,15 +240,15 @@ xy0212 = y02/y12; INDEX3(planes_ptr,i,0) = (z02 - z12 * xy0212) / (x02 - x12 * xy0212); INDEX3(planes_ptr,i,1) = (z12 - INDEX3(planes_ptr,i,0)*x12) / y12; - INDEX3(planes_ptr,i,2) = (z[INDEX3(nodes,i,2)] - - INDEX3(planes_ptr,i,0)*x[INDEX3(nodes,i,2)] - + INDEX3(planes_ptr,i,2) = (z[INDEX3(nodes,i,2)] - + INDEX3(planes_ptr,i,0)*x[INDEX3(nodes,i,2)] - INDEX3(planes_ptr,i,1)*y[INDEX3(nodes,i,2)]); } else { xy0212 = x02/x12; INDEX3(planes_ptr,i,1) = (z02 - z12 * xy0212) / (y02 - y12 * xy0212); INDEX3(planes_ptr,i,0) = (z12 - INDEX3(planes_ptr,i,1)*y12) / x12; - INDEX3(planes_ptr,i,2) = (z[INDEX3(nodes,i,2)] - - INDEX3(planes_ptr,i,0)*x[INDEX3(nodes,i,2)] - + INDEX3(planes_ptr,i,2) = (z[INDEX3(nodes,i,2)] - + INDEX3(planes_ptr,i,0)*x[INDEX3(nodes,i,2)] - INDEX3(planes_ptr,i,1)*y[INDEX3(nodes,i,2)]); } } @@ -256,24 +256,24 @@ return (PyObject*)planes; } -static double linear_interpolate_single(double targetx, double targety, +static double linear_interpolate_single(double targetx, double targety, double *x, double *y, int *nodes, int *neighbors, PyObject *planes, double defvalue, int start_triangle, int *end_triangle) { double *planes_ptr; planes_ptr = (double*)PyArray_DATA(planes); if (start_triangle == -1) start_triangle = 0; - *end_triangle = walking_triangles(start_triangle, targetx, targety, + *end_triangle = walking_triangles(start_triangle, targetx, targety, x, y, nodes, neighbors); if (*end_triangle == -1) return defvalue; - return (targetx*INDEX3(planes_ptr,*end_triangle,0) + + return (targetx*INDEX3(planes_ptr,*end_triangle,0) + targety*INDEX3(planes_ptr,*end_triangle,1) + INDEX3(planes_ptr,*end_triangle,2)); } -static PyObject *linear_interpolate_grid(double x0, double x1, int xsteps, +static PyObject *linear_interpolate_grid(double x0, double x1, int xsteps, double y0, double y1, int ysteps, - PyObject *planes, double defvalue, + PyObject *planes, double defvalue, int npoints, double *x, double *y, int *nodes, int *neighbors) { int ix, iy; @@ -312,7 +312,7 @@ static PyObject *compute_planes_method(PyObject *self, PyObject *args) { PyObject *pyx, *pyy, *pyz, *pynodes; - PyObject *x, *y, *z, *nodes; + PyObject *x = NULL, *y = NULL, *z = NULL, *nodes = NULL; int npoints, ntriangles; PyObject *planes; @@ -351,7 +351,7 @@ goto fail; } - planes = linear_planes(ntriangles, (double*)PyArray_DATA(x), + planes = linear_planes(ntriangles, (double*)PyArray_DATA(x), (double*)PyArray_DATA(y), (double*)PyArray_DATA(z), (int*)PyArray_DATA(nodes)); Py_DECREF(x); @@ -374,7 +374,7 @@ double x0, x1, y0, y1, defvalue; int xsteps, ysteps; PyObject *pyplanes, *pyx, *pyy, *pynodes, *pyneighbors, *grid; - PyObject *planes, *x, *y, *nodes, *neighbors; + PyObject *planes = NULL, *x = NULL, *y = NULL, *nodes = NULL, *neighbors = NULL; int npoints; @@ -417,7 +417,7 @@ (PyObject*)planes, defvalue, npoints, (double*)PyArray_DATA(x), (double*)PyArray_DATA(y), (int*)PyArray_DATA(nodes), (int*)PyArray_DATA(neighbors)); - + Py_DECREF(x); Py_DECREF(y); Py_DECREF(planes); @@ -455,7 +455,7 @@ { PyObject *pyx, *pyy, *pyz, *pycenters, *pynodes, *pyneighbors, *pyintx, *pyinty; PyObject *x = NULL, *y = NULL, *z = NULL, *centers = NULL, *nodes = NULL, - *neighbors = NULL, *intx = NULL, *inty = NULL, *intz; + *neighbors = NULL, *intx = NULL, *inty = NULL, *intz = NULL; double defvalue; int size, npoints, ntriangles; @@ -506,7 +506,7 @@ return NULL; } ntriangles = PyArray_DIM(neighbors, 0); - if ((PyArray_DIM(nodes, 0) != ntriangles) || + if ((PyArray_DIM(nodes, 0) != ntriangles) || (PyArray_DIM(centers, 0) != ntriangles)) { PyErr_SetString(PyExc_ValueError, "centers,nodes,neighbors must be of equal length"); CLEANUP @@ -542,13 +542,13 @@ return NULL; } - NaturalNeighbors nn(npoints, ntriangles, + NaturalNeighbors nn(npoints, ntriangles, (double*)PyArray_DATA(x), (double*)PyArray_DATA(y), - (double*)PyArray_DATA(centers), (int*)PyArray_DATA(nodes), + (double*)PyArray_DATA(centers), (int*)PyArray_DATA(nodes), (int*)PyArray_DATA(neighbors)); size = PyArray_Size(intx); - nn.interpolate_unstructured((double*)PyArray_DATA(z), size, - (double*)PyArray_DATA(intx), (double*)PyArray_DATA(inty), + nn.interpolate_unstructured((double*)PyArray_DATA(z), size, + (double*)PyArray_DATA(intx), (double*)PyArray_DATA(inty), (double*)PyArray_DATA(intz), defvalue); Py_XDECREF(x); @@ -575,13 +575,13 @@ static PyObject *nn_interpolate_method(PyObject *self, PyObject *args) { PyObject *pyx, *pyy, *pyz, *pycenters, *pynodes, *pyneighbors, *grid; - PyObject *x, *y, *z, *centers, *nodes, *neighbors; + PyObject *x = NULL, *y = NULL, *z = NULL, *centers = NULL, *nodes = NULL, *neighbors = NULL; double x0, x1, y0, y1, defvalue; int xsteps, ysteps; int npoints, ntriangles; intp dims[2]; - if (!PyArg_ParseTuple(args, "ddiddidOOOOOO", &x0, &x1, &xsteps, + if (!PyArg_ParseTuple(args, "ddiddidOOOOOO", &x0, &x1, &xsteps, &y0, &y1, &ysteps, &defvalue, &pyx, &pyy, &pyz, &pycenters, &pynodes, &pyneighbors)) { return NULL; @@ -629,7 +629,7 @@ return NULL; } ntriangles = PyArray_DIM(neighbors, 0); - if ((PyArray_DIM(nodes, 0) != ntriangles) || + if ((PyArray_DIM(nodes, 0) != ntriangles) || (PyArray_DIM(centers, 0) != ntriangles)) { PyErr_SetString(PyExc_ValueError, "centers,nodes,neighbors must be of equal length"); CLEANUP @@ -644,11 +644,11 @@ return NULL; } - NaturalNeighbors nn(npoints, ntriangles, + NaturalNeighbors nn(npoints, ntriangles, (double*)PyArray_DATA(x), (double*)PyArray_DATA(y), - (double*)PyArray_DATA(centers), (int*)PyArray_DATA(nodes), + (double*)PyArray_DATA(centers), (int*)PyArray_DATA(nodes), (int*)PyArray_DATA(neighbors)); - nn.interpolate_grid((double*)PyArray_DATA(z), + nn.interpolate_grid((double*)PyArray_DATA(z), x0, x1, xsteps, y0, y1, ysteps, (double*)PyArray_DATA(grid), @@ -664,7 +664,7 @@ static PyObject *delaunay_method(PyObject *self, PyObject *args) { PyObject *pyx, *pyy, *mesh; - PyObject *x, *y; + PyObject *x = NULL, *y = NULL; int npoints; if (!PyArg_ParseTuple(args, "OO", &pyx, &pyy)) { @@ -703,7 +703,7 @@ } static PyMethodDef delaunay_methods[] = { - {"delaunay", (PyCFunction)delaunay_method, METH_VARARGS, + {"delaunay", (PyCFunction)delaunay_method, METH_VARARGS, "Compute the Delaunay triangulation of a cloud of 2-D points.\n\n" "circumcenters, edges, tri_points, tri_neighbors = delaunay(x, y)\n\n" "x, y -- shape-(npoints,) arrays of floats giving the X and Y coordinates of the points\n" @@ -730,7 +730,7 @@ PyMODINIT_FUNC init_delaunay(void) { PyObject* m; - m = Py_InitModule3("_delaunay", delaunay_methods, + m = Py_InitModule3("_delaunay", delaunay_methods, "Tools for computing the Delaunay triangulation and some operations on it.\n" ); if (m == NULL) Modified: trunk/matplotlib/lib/matplotlib/tri/_tri.cpp =================================================================== --- trunk/matplotlib/lib/matplotlib/tri/_tri.cpp 2010-06-01 19:04:17 UTC (rev 8363) +++ trunk/matplotlib/lib/matplotlib/tri/_tri.cpp 2010-06-01 19:06:28 UTC (rev 8364) @@ -990,7 +990,8 @@ #endif init_tri() { - static TriModule* triModule = new TriModule; + static TriModule* triModule = NULL; + triModule = new TriModule(); import_array(); } Modified: trunk/matplotlib/src/_path.cpp =================================================================== --- trunk/matplotlib/src/_path.cpp 2010-06-01 19:04:17 UTC (rev 8363) +++ trunk/matplotlib/src/_path.cpp 2010-06-01 19:06:28 UTC (rev 8364) @@ -818,7 +818,7 @@ } Polygon polygon1, polygon2; - double x, y; + double x = 0, y = 0; unsigned code = 0; path.rewind(0); Modified: trunk/matplotlib/src/cntr.c =================================================================== --- trunk/matplotlib/src/cntr.c 2010-06-01 19:04:17 UTC (rev 8363) +++ trunk/matplotlib/src/cntr.c 2010-06-01 19:06:28 UTC (rev 8364) @@ -607,8 +607,8 @@ } if (fwd < 0 && level0 && left < 0) { - /* remove J0_START from this boundary edge as boundary is - * included by the upwards slit from contour line below. */ + /* remove J0_START from this boundary edge as boundary is + * included by the upwards slit from contour line below. */ data[edge] &= ~J0_START; if (n_kind) kcp[n_kind] += kind_start_slit; return slit_cutter (site, 0, pass2); @@ -1479,8 +1479,8 @@ int nparts, long ntotal) { PyObject *all_contours; - PyArrayObject *xyv; - PyArrayObject *kv; + PyArrayObject *xyv = NULL; + PyArrayObject *kv = NULL; npy_intp dims[2]; npy_intp kdims[1]; int i; Modified: trunk/matplotlib/src/path_converters.h =================================================================== --- trunk/matplotlib/src/path_converters.h 2010-06-01 19:04:17 UTC (rev 8363) +++ trunk/matplotlib/src/path_converters.h 2010-06-01 19:06:28 UTC (rev 8364) @@ -233,9 +233,9 @@ } while (MPL_notisfinite64(*x) || MPL_notisfinite64(*y)); return agg::path_cmd_move_to; } + + return code; } - - return code; } }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-06-01 19:04:25
|
Revision: 8363 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8363&view=rev Author: efiring Date: 2010-06-01 19:04:17 +0000 (Tue, 01 Jun 2010) Log Message: ----------- backend_driver: suppress "invalid value" warnings Modified Paths: -------------- trunk/matplotlib/examples/tests/backend_driver.py Modified: trunk/matplotlib/examples/tests/backend_driver.py =================================================================== --- trunk/matplotlib/examples/tests/backend_driver.py 2010-06-01 18:21:30 UTC (rev 8362) +++ trunk/matplotlib/examples/tests/backend_driver.py 2010-06-01 19:04:17 UTC (rev 8363) @@ -360,6 +360,8 @@ 'import matplotlib\n', 'matplotlib.use("%s")\n' % backend, 'from pylab import savefig\n', + 'import numpy\n', + 'numpy.seterr(invalid="ignore")\n', )) for line in file(fullpath): line_lstrip = line.lstrip() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-06-01 18:21:36
|
Revision: 8362 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8362&view=rev Author: efiring Date: 2010-06-01 18:21:30 +0000 (Tue, 01 Jun 2010) Log Message: ----------- widget example improvements by M. Michler, patch 2944605 Modified Paths: -------------- trunk/matplotlib/examples/widgets/buttons.py trunk/matplotlib/examples/widgets/check_buttons.py trunk/matplotlib/examples/widgets/cursor.py trunk/matplotlib/examples/widgets/menu.py trunk/matplotlib/examples/widgets/rectangle_selector.py Modified: trunk/matplotlib/examples/widgets/buttons.py =================================================================== --- trunk/matplotlib/examples/widgets/buttons.py 2010-06-01 16:38:34 UTC (rev 8361) +++ trunk/matplotlib/examples/widgets/buttons.py 2010-06-01 18:21:30 UTC (rev 8362) @@ -1,38 +1,40 @@ -from pylab import * + +import numpy as np +import matplotlib.pyplot as plt from matplotlib.widgets import Button -freqs = arange(2,20,3) +freqs = np.arange(2, 20, 3) -ax = subplot(111) -subplots_adjust(bottom=0.2) -t = arange(0.0, 1.0, 0.001) -s = sin(2*pi*freqs[0]*t) -l, = plot(t,s, lw=2) +ax = plt.subplot(111) +plt.subplots_adjust(bottom=0.2) +t = np.arange(0.0, 1.0, 0.001) +s = np.sin(2*np.pi*freqs[0]*t) +l, = plt.plot(t, s, lw=2) class Index: ind = 0 def next(self, event): self.ind += 1 - i = self.ind%len(freqs) - ydata = sin(2*pi*freqs[i]*t) + i = self.ind % len(freqs) + ydata = np.sin(2*np.pi*freqs[i]*t) l.set_ydata(ydata) - draw() + plt.draw() def prev(self, event): self.ind -= 1 - i = self.ind%len(freqs) - ydata = sin(2*pi*freqs[i]*t) + i = self.ind % len(freqs) + ydata = np.sin(2*np.pi*freqs[i]*t) l.set_ydata(ydata) - draw() + plt.draw() callback = Index() -axprev = axes([0.7, 0.05, 0.1, 0.075]) -axnext = axes([0.81, 0.05, 0.1, 0.075]) +axprev = plt.axes([0.7, 0.05, 0.1, 0.075]) +axnext = plt.axes([0.81, 0.05, 0.1, 0.075]) bnext = Button(axnext, 'Next') bnext.on_clicked(callback.next) bprev = Button(axprev, 'Previous') bprev.on_clicked(callback.prev) -show() +plt.show() Modified: trunk/matplotlib/examples/widgets/check_buttons.py =================================================================== --- trunk/matplotlib/examples/widgets/check_buttons.py 2010-06-01 16:38:34 UTC (rev 8361) +++ trunk/matplotlib/examples/widgets/check_buttons.py 2010-06-01 18:21:30 UTC (rev 8362) @@ -1,25 +1,26 @@ -from pylab import * +import numpy as np +import matplotlib.pyplot as plt from matplotlib.widgets import CheckButtons -t = arange(0.0, 2.0, 0.01) -s0 = sin(2*pi*t) -s1 = sin(4*pi*t) -s2 = sin(6*pi*t) +t = np.arange(0.0, 2.0, 0.01) +s0 = np.sin(2*np.pi*t) +s1 = np.sin(4*np.pi*t) +s2 = np.sin(6*np.pi*t) -ax = subplot(111) +ax = plt.subplot(111) l0, = ax.plot(t, s0, visible=False, lw=2) l1, = ax.plot(t, s1, lw=2) l2, = ax.plot(t, s2, lw=2) -subplots_adjust(left=0.2) +plt.subplots_adjust(left=0.2) -rax = axes([0.05, 0.4, 0.1, 0.15]) +rax = plt.axes([0.05, 0.4, 0.1, 0.15]) check = CheckButtons(rax, ('2 Hz', '4 Hz', '6 Hz'), (False, True, True)) def func(label): - if label=='2 Hz': l0.set_visible(not l0.get_visible()) - elif label=='4 Hz': l1.set_visible(not l1.get_visible()) - elif label=='6 Hz': l2.set_visible(not l2.get_visible()) - draw() + if label == '2 Hz': l0.set_visible(not l0.get_visible()) + elif label == '4 Hz': l1.set_visible(not l1.get_visible()) + elif label == '6 Hz': l2.set_visible(not l2.get_visible()) + plt.draw() check.on_clicked(func) -show() +plt.show() Modified: trunk/matplotlib/examples/widgets/cursor.py =================================================================== --- trunk/matplotlib/examples/widgets/cursor.py 2010-06-01 16:38:34 UTC (rev 8361) +++ trunk/matplotlib/examples/widgets/cursor.py 2010-06-01 18:21:30 UTC (rev 8362) @@ -1,20 +1,19 @@ #!/usr/bin/env python from matplotlib.widgets import Cursor -import pylab +import numpy as np +import matplotlib.pyplot as plt -fig = pylab.figure(figsize=(8,6)) -ax = fig.add_axes([0.075, 0.25, 0.9, 0.725], axisbg='#FFFFCC') -#ax = fig.add_subplot(111, axisbg='#FFFFCC') -canvas = ax.figure.canvas +fig = plt.figure(figsize=(8, 6)) +ax = fig.add_subplot(111, axisbg='#FFFFCC') -x,y = 4*(pylab.rand(2,100)-.5) -ax.plot(x,y,'o') -ax.set_xlim(-2,2) -ax.set_ylim(-2,2) +x, y = 4*(np.random.rand(2, 100)-.5) +ax.plot(x, y, 'o') +ax.set_xlim(-2, 2) +ax.set_ylim(-2, 2) # set useblit = True on gtkagg for enhanced performance cursor = Cursor(ax, useblit=True, color='red', linewidth=2 ) -pylab.show() +plt.show() Modified: trunk/matplotlib/examples/widgets/menu.py =================================================================== --- trunk/matplotlib/examples/widgets/menu.py 2010-06-01 16:38:34 UTC (rev 8361) +++ trunk/matplotlib/examples/widgets/menu.py 2010-06-01 18:21:30 UTC (rev 8362) @@ -9,7 +9,8 @@ class ItemProperties: - def __init__(self, fontsize=14, labelcolor='black', bgcolor='yellow', alpha=1.0): + def __init__(self, fontsize=14, labelcolor='black', bgcolor='yellow', + alpha=1.0): self.fontsize = fontsize self.labelcolor = labelcolor self.bgcolor = bgcolor @@ -21,8 +22,9 @@ class MenuItem(artist.Artist): parser = mathtext.MathTextParser("Bitmap") padx = 5 - pady =5 - def __init__(self, fig, labelstr, props=None, hoverprops=None, on_select=None): + pady = 5 + def __init__(self, fig, labelstr, props=None, hoverprops=None, + on_select=None): artist.Artist.__init__(self) self.set_figure(fig) @@ -44,14 +46,15 @@ labelstr, fontsize=props.fontsize, dpi=fig.dpi) if props.fontsize!=hoverprops.fontsize: - raise NotImplementedError('support for different font sizes not implemented') + raise NotImplementedError( + 'support for different font sizes not implemented') self.labelwidth = x.shape[1] self.labelheight = x.shape[0] self.labelArray = np.zeros((x.shape[0], x.shape[1], 4)) - self.labelArray[:,:,-1] = x/255. + self.labelArray[:, :, -1] = x/255. self.label = image.FigureImage(fig, origin='upper') self.label.set_array(self.labelArray) @@ -95,9 +98,9 @@ props = self.props r, g, b = props.labelcolor_rgb - self.labelArray[:,:,0] = r - self.labelArray[:,:,1] = g - self.labelArray[:,:,2] = b + self.labelArray[:, :, 0] = r + self.labelArray[:, :, 1] = g + self.labelArray[:, :, 2] = b self.label.set_array(self.labelArray) self.rect.set(facecolor=props.bgcolor, alpha=props.alpha) @@ -169,12 +172,9 @@ for label in ('open', 'close', 'save', 'save as', 'quit'): def on_select(item): print 'you selected', item.labelstr - item = MenuItem(fig, label, props=props, hoverprops=hoverprops, on_select=on_select) + item = MenuItem(fig, label, props=props, hoverprops=hoverprops, + on_select=on_select) menuitems.append(item) menu = Menu(fig, menuitems) plt.show() - - - - Modified: trunk/matplotlib/examples/widgets/rectangle_selector.py =================================================================== --- trunk/matplotlib/examples/widgets/rectangle_selector.py 2010-06-01 16:38:34 UTC (rev 8361) +++ trunk/matplotlib/examples/widgets/rectangle_selector.py 2010-06-01 18:21:30 UTC (rev 8362) @@ -8,28 +8,41 @@ """ from matplotlib.widgets import RectangleSelector -from pylab import subplot, arange, plot, sin, cos, pi, show -def line_select_callback(event1, event2): - 'event1 and event2 are the press and release events' - x1, y1 = event1.xdata, event1.ydata - x2, y2 = event2.xdata, event2.ydata - print "(%3.2f, %3.2f) --> (%3.2f, %3.2f)"%(x1,y1,x2,y2) - print " The button you used were: ",event1.button, event2.button +import numpy as np +import matplotlib.pyplot as plt +def line_select_callback(eclick, erelease): + 'eclick and erelease are the press and release events' + x1, y1 = eclick.xdata, eclick.ydata + x2, y2 = erelease.xdata, erelease.ydata + print "(%3.2f, %3.2f) --> (%3.2f, %3.2f)" % (x1, y1, x2, y2) + print " The button you used were: ", eclick.button, erelease.button -current_ax=subplot(111) # make a new plotingrange -N=100000 # If N is large one can see improvement -x=10.0*arange(N)/(N-1) # by use blitting! +def toggle_selector(event): + print ' Key pressed.' + if event.key in ['Q', 'q'] and toggle_selector.RS.active: + print ' RectangleSelector deactivated.' + toggle_selector.RS.set_active(False) + if event.key in ['A', 'a'] and not toggle_selector.RS.active: + print ' RectangleSelector activated.' + toggle_selector.RS.set_active(True) -plot(x,sin(.2*pi*x),lw=3,c='b',alpha=.7) # plot something -plot(x,cos(.2*pi*x),lw=3.5,c='r',alpha=.5) -plot(x,-sin(.2*pi*x),lw=3.5,c='g',alpha=.3) +current_ax = plt.subplot(111) # make a new plotingrange +N = 100000 # If N is large one can see +x = np.linspace(0.0, 10.0, N) # improvement by use blitting! + +plt.plot(x, +np.sin(.2*np.pi*x), lw=3.5, c='b', alpha=.7) # plot something +plt.plot(x, +np.cos(.2*np.pi*x), lw=3.5, c='r', alpha=.5) +plt.plot(x, -np.sin(.2*np.pi*x), lw=3.5, c='g', alpha=.3) + print "\n click --> release" # drawtype is 'box' or 'line' or 'none' -LS = RectangleSelector(current_ax, line_select_callback, - drawtype='box',useblit=True, - button = [1, 3], # don't use center mouse button - minspanx=5,minspany=5,spancoords='pixels') -show() +toggle_selector.RS = RectangleSelector(current_ax, line_select_callback, + drawtype='box', useblit=True, + button=[1,3], # don't use middle button + minspanx=5, minspany=5, + spancoords='pixels') +plt.connect('key_press_event', toggle_selector) +plt.show() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-06-01 16:38:41
|
Revision: 8361 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8361&view=rev Author: efiring Date: 2010-06-01 16:38:34 +0000 (Tue, 01 Jun 2010) Log Message: ----------- contour: Jouni's patch to close 2797414 and 3009921; clabel with mathtext Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/contour.py trunk/matplotlib/lib/matplotlib/text.py Modified: trunk/matplotlib/lib/matplotlib/contour.py =================================================================== --- trunk/matplotlib/lib/matplotlib/contour.py 2010-06-01 03:11:39 UTC (rev 8360) +++ trunk/matplotlib/lib/matplotlib/contour.py 2010-06-01 16:38:34 UTC (rev 8361) @@ -17,6 +17,8 @@ import matplotlib.text as text import matplotlib.cbook as cbook import matplotlib.mlab as mlab +import matplotlib.mathtext as mathtext +import matplotlib.texmanager as texmanager # Import needed for adding manual selection capability to clabel from matplotlib.blocking_input import BlockingContourLabeler @@ -268,10 +270,21 @@ def get_label_width(self, lev, fmt, fsize): "get the width of the label in points" - if cbook.is_string_like(lev): + if not cbook.is_string_like(lev): + lev = self.get_text(lev, fmt) + + lev, ismath = text.Text.is_math_text(lev) + if ismath == 'TeX': + if not hasattr(self, '_TeX_manager'): + self._TeX_manager = texmanager.TexManager() + lw, _, _ = self._TeX_manager.get_text_width_height_descent(lev, fsize) + elif ismath: + if not hasattr(self, '_mathtext_parser'): + self._mathtext_parser = mathtext.MathTextParser('bitmap') + img, _ = self._mathtext_parser.parse(lev, dpi=72, prop=self.labelFontProps) + lw = img.get_width() # at dpi=72, the units are PostScript points + else: lw = (len(lev)) * fsize - else: - lw = (len(self.get_text(lev,fmt))) * fsize return lw @@ -330,7 +343,7 @@ if xsize == 1: ysize = nsize else: - ysize = labelwidth + ysize = int(labelwidth) XX = np.resize(linecontour[:,0],(xsize, ysize)) YY = np.resize(linecontour[:,1],(xsize, ysize)) Modified: trunk/matplotlib/lib/matplotlib/text.py =================================================================== --- trunk/matplotlib/lib/matplotlib/text.py 2010-06-01 03:11:39 UTC (rev 8360) +++ trunk/matplotlib/lib/matplotlib/text.py 2010-06-01 16:38:34 UTC (rev 8361) @@ -963,9 +963,14 @@ """ self._text = '%s' % (s,) - def is_math_text(self, s): + @staticmethod + def is_math_text(s): """ - Returns True if the given string *s* contains any mathtext. + Returns a cleaned string and a boolean flag. + The flag indicates if the given string *s* contains any mathtext, + determined by counting unescaped dollar signs. If no mathtext + is present, the cleaned string has its dollar signs unescaped. + If usetex is on, the flag always has the value "TeX". """ # Did we find an even number of non-escaped dollar signs? # If so, treat is as math text. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-06-01 03:11:45
|
Revision: 8360 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8360&view=rev Author: efiring Date: 2010-06-01 03:11:39 +0000 (Tue, 01 Jun 2010) Log Message: ----------- Axes.bar: let errorbar take care of most checking and processing of xerr, yerr. Closes 2804500. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010-06-01 02:36:47 UTC (rev 8359) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010-06-01 03:11:39 UTC (rev 8360) @@ -4306,6 +4306,9 @@ *xerr*, and *yerr* can be either scalars or sequences of length equal to the number of bars. This enables you to use bar as the basis for stacked bar charts, or candlestick plots. + Detail: *xerr* and *yerr* are passed directly to + :meth:`errorbar`, so they can also have shape 2xN for + independent specification of lower and upper errors. Other optional kwargs: @@ -4319,6 +4322,9 @@ color = kwargs.pop('color', None) edgecolor = kwargs.pop('edgecolor', None) linewidth = kwargs.pop('linewidth', None) + # Because xerr and yerr will be passed to errorbar, + # most dimension checking and processing will be left + # to the errorbar method. xerr = kwargs.pop('xerr', None) yerr = kwargs.pop('yerr', None) ecolor = kwargs.pop('ecolor', None) @@ -4396,14 +4402,6 @@ if len(edgecolor) < nbars: edgecolor *= nbars - if yerr is not None: - if not iterable(yerr): - yerr = [yerr]*nbars - - if xerr is not None: - if not iterable(xerr): - xerr = [xerr]*nbars - # FIXME: convert the following to proper input validation # raising ValueError; don't use assert for this. assert len(left)==nbars, "incompatible sizes: argument 'left' must be length %d or scalar" % nbars @@ -4414,13 +4412,6 @@ assert len(bottom)==nbars, ("incompatible sizes: argument 'bottom' must be length %d or scalar" % nbars) - if yerr is not None and len(yerr)!=nbars: - raise ValueError( - "incompatible sizes: bar() argument 'yerr' must be len(%s) or scalar" % nbars) - if xerr is not None and len(xerr)!=nbars: - raise ValueError( - "incompatible sizes: bar() argument 'xerr' must be len(%s) or scalar" % nbars) - patches = [] # lets do some conversions now since some types cannot be This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-06-01 02:36:53
|
Revision: 8359 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8359&view=rev Author: efiring Date: 2010-06-01 02:36:47 +0000 (Tue, 01 Jun 2010) Log Message: ----------- Axes.axhline, axvline: explicitly disallow transform kwarg. Closes 2864449. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010-06-01 02:20:53 UTC (rev 8358) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010-06-01 02:36:47 UTC (rev 8359) @@ -3087,7 +3087,8 @@ >>> axhline(y=.5, xmin=0.25, xmax=0.75) - Valid kwargs are :class:`~matplotlib.lines.Line2D` properties: + Valid kwargs are :class:`~matplotlib.lines.Line2D` properties, + with the exception of 'transform': %(Line2D)s @@ -3097,6 +3098,10 @@ for example plot and source code """ + if "transform" in kwargs: + raise ValueError( + "'transform' is not allowed as a kwarg;" + + "axhline generates its own transform.") ymin, ymax = self.get_ybound() # We need to strip away the units for comparison with @@ -3147,7 +3152,8 @@ >>> axvline(x=.5, ymin=0.25, ymax=0.75) - Valid kwargs are :class:`~matplotlib.lines.Line2D` properties: + Valid kwargs are :class:`~matplotlib.lines.Line2D` properties, + with the exception of 'transform': %(Line2D)s @@ -3157,6 +3163,10 @@ for example plot and source code """ + if "transform" in kwargs: + raise ValueError( + "'transform' is not allowed as a kwarg;" + + "axvline generates its own transform.") xmin, xmax = self.get_xbound() # We need to strip away the units for comparison with This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-06-01 02:20:59
|
Revision: 8358 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8358&view=rev Author: efiring Date: 2010-06-01 02:20:53 +0000 (Tue, 01 Jun 2010) Log Message: ----------- Line2D: fix point picking with zoom and pan, when line-clipping is in effect. Closes 2871992. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/lines.py Modified: trunk/matplotlib/lib/matplotlib/lines.py =================================================================== --- trunk/matplotlib/lib/matplotlib/lines.py 2010-06-01 01:30:19 UTC (rev 8357) +++ trunk/matplotlib/lib/matplotlib/lines.py 2010-06-01 02:20:53 UTC (rev 8358) @@ -305,6 +305,8 @@ # If line, return the nearby segment(s) ind = segment_hits(mouseevent.x,mouseevent.y,xt,yt,pixels) + ind += self.ind_offset + # Debugging message if False and self._label != u'': print "Checking line",self._label,"at",mouseevent.x,mouseevent.y @@ -496,12 +498,14 @@ def draw(self, renderer): if self._invalidy or self._invalidx: self.recache() + self.ind_offset = 0 # Needed for contains() method. if self._subslice and self.axes: # Need to handle monotonically decreasing case also... x0, x1 = self.axes.get_xbound() i0, = self._x.searchsorted([x0], 'left') i1, = self._x.searchsorted([x1], 'right') subslice = slice(max(i0-1, 0), i1+1) + self.ind_offset = subslice.start self._transform_path(subslice) if self._transformed_path is None: self._transform_path() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-06-01 01:30:25
|
Revision: 8357 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8357&view=rev Author: efiring Date: 2010-06-01 01:30:19 +0000 (Tue, 01 Jun 2010) Log Message: ----------- pylab: remove pointless imports of load, save from mlab Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/pylab.py Modified: trunk/matplotlib/lib/matplotlib/pylab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pylab.py 2010-06-01 01:03:06 UTC (rev 8356) +++ trunk/matplotlib/lib/matplotlib/pylab.py 2010-06-01 01:30:19 UTC (rev 8357) @@ -228,10 +228,12 @@ from matplotlib.mlab import window_hanning, window_none, detrend, demean, \ detrend_mean, detrend_none, detrend_linear, entropy, normpdf, levypdf, \ - find, longest_contiguous_ones, longest_ones, prepca, prctile, prctile_rank, \ - center_matrix, rk4, bivariate_normal, get_xyz_where, get_sparse_matrix, dist, \ + find, longest_contiguous_ones, longest_ones, prepca, \ + prctile, prctile_rank, \ + center_matrix, rk4, bivariate_normal, get_xyz_where, \ + get_sparse_matrix, dist, \ dist_point_to_segment, segments_intersect, fftsurr, liaupunov, movavg, \ - save, load, exp_safe, \ + exp_safe, \ amap, rms_flat, l1norm, l2norm, norm_flat, frange, identity, \ base_repr, binary_repr, log2, ispower2, \ rec_append_fields, rec_drop_fields, rec_join, csv2rec, rec2csv, isvector @@ -251,8 +253,8 @@ import numpy as np import numpy.ma as ma -def load(*args, **kwargs): - raise NotImplementedError(load.__doc__) +def load(*args, **kwargs): + raise NotImplementedError(load.__doc__) load.__doc__ = """\ pylab no longer provides a load function, though the old pylab function is still available as matplotlib.mlab.load (you can refer @@ -264,8 +266,8 @@ """ -def save(*args, **kwargs): - raise NotImplementedError(save.__doc__) +def save(*args, **kwargs): + raise NotImplementedError(save.__doc__) save.__doc__ = """\ pylab no longer provides a save function, though the old pylab function is still available as matplotlib.mlab.save (you can still This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-06-01 01:03:12
|
Revision: 8356 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8356&view=rev Author: efiring Date: 2010-06-01 01:03:06 +0000 (Tue, 01 Jun 2010) Log Message: ----------- colors.py: more improvement in alpha handling for over, under, and bad values Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/colors.py Modified: trunk/matplotlib/lib/matplotlib/colors.py =================================================================== --- trunk/matplotlib/lib/matplotlib/colors.py 2010-06-01 00:31:42 UTC (rev 8355) +++ trunk/matplotlib/lib/matplotlib/colors.py 2010-06-01 01:03:06 UTC (rev 8356) @@ -526,17 +526,21 @@ if bytes: lut = (self._lut * 255).astype(np.uint8) else: - lut = self._lut.copy() + lut = self._lut.copy() # Don't let alpha modify original _lut. if alpha is not None: alpha = min(alpha, 1.0) # alpha must be between 0 and 1 alpha = max(alpha, 0.0) - lut[:-1,-1] = alpha # Don't assign global alpha to i_bad; - # it would defeat the purpose of the - # default behavior, which is to not - # show anything where data are missing. + if (lut[-1] == 0).all(): + lut[:-1, -1] = alpha + # All zeros is taken as a flag for the default bad + # color, which is no color--fully transparent. We + # don't want to override this. + else: + lut[:,-1] = alpha + # If the bad value is set to have a color, then we + # override its alpha just as for any other value. - rgba = np.empty(shape=xa.shape+(4,), dtype=lut.dtype) lut.take(xa, axis=0, mode='clip', out=rgba) # twice as fast as lut[xa]; @@ -546,20 +550,20 @@ rgba = tuple(rgba[0,:]) return rgba - def set_bad(self, color = 'k', alpha = 1.0): + def set_bad(self, color = 'k', alpha = None): '''Set color to be used for masked values. ''' self._rgba_bad = colorConverter.to_rgba(color, alpha) if self._isinit: self._set_extremes() - def set_under(self, color = 'k', alpha = 1.0): + def set_under(self, color = 'k', alpha = None): '''Set color to be used for low out-of-range values. Requires norm.clip = False ''' self._rgba_under = colorConverter.to_rgba(color, alpha) if self._isinit: self._set_extremes() - def set_over(self, color = 'k', alpha = 1.0): + def set_over(self, color = 'k', alpha = None): '''Set color to be used for high out-of-range values. Requires norm.clip = False ''' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-06-01 00:31:48
|
Revision: 8355 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8355&view=rev Author: efiring Date: 2010-06-01 00:31:42 +0000 (Tue, 01 Jun 2010) Log Message: ----------- Colormap.__call__: override existing alpha only if alpha is specified. Closes 2891982. The color for masked data is still handled differently; this may need to be changed. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/colors.py Modified: trunk/matplotlib/lib/matplotlib/colors.py =================================================================== --- trunk/matplotlib/lib/matplotlib/colors.py 2010-05-31 23:05:55 UTC (rev 8354) +++ trunk/matplotlib/lib/matplotlib/colors.py 2010-06-01 00:31:42 UTC (rev 8355) @@ -482,7 +482,7 @@ self._isinit = False - def __call__(self, X, alpha=1.0, bytes=False): + def __call__(self, X, alpha=None, bytes=False): """ *X* is either a scalar or an array (of any dimension). If scalar, a tuple of rgba values is returned, otherwise @@ -490,18 +490,12 @@ are integers, then they are used as indices into the array. If they are floating point, then they must be in the interval (0.0, 1.0). - Alpha must be a scalar. + Alpha must be a scalar between 0 and 1, or None. If bytes is False, the rgba values will be floats on a 0-1 scale; if True, they will be uint8, 0-255. """ if not self._isinit: self._init() - alpha = min(alpha, 1.0) # alpha must be between 0 and 1 - alpha = max(alpha, 0.0) - self._lut[:-1,-1] = alpha # Don't assign global alpha to i_bad; - # it would defeat the purpose of the - # default behavior, which is to not - # show anything where data are missing. mask_bad = None if not cbook.iterable(X): vtype = 'scalar' @@ -532,7 +526,17 @@ if bytes: lut = (self._lut * 255).astype(np.uint8) else: - lut = self._lut + lut = self._lut.copy() + + if alpha is not None: + alpha = min(alpha, 1.0) # alpha must be between 0 and 1 + alpha = max(alpha, 0.0) + lut[:-1,-1] = alpha # Don't assign global alpha to i_bad; + # it would defeat the purpose of the + # default behavior, which is to not + # show anything where data are missing. + + rgba = np.empty(shape=xa.shape+(4,), dtype=lut.dtype) lut.take(xa, axis=0, mode='clip', out=rgba) # twice as fast as lut[xa]; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-05-31 23:06:01
|
Revision: 8354 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8354&view=rev Author: efiring Date: 2010-05-31 23:05:55 +0000 (Mon, 31 May 2010) Log Message: ----------- Axes.hist: fix auto range selection with multiple datasets. Close 2976990. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010-05-31 21:59:06 UTC (rev 8353) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010-05-31 23:05:55 UTC (rev 8354) @@ -7230,9 +7230,9 @@ are ignored. If not provided, *range* is (x.min(), x.max()). Range has no effect if *bins* is a sequence. - If *bins* is a sequence or *range* is specified, autoscaling is - set off (*autoscale_on* is set to *False*) and the xaxis limits - are set to encompass the full specified bin range. + If *bins* is a sequence or *range* is specified, autoscaling + is based on the specified bin range instead of the + range of x. *normed*: If *True*, the first element of the return tuple will @@ -7395,9 +7395,6 @@ else: w = [None]*nx - # Check whether bins or range are given explicitly. In that - # case use those values for autoscaling. - binsgiven = (cbook.iterable(bins) or range != None) # Save autoscale state for later restoration; turn autoscaling # off so we can do it all a single time at the end, instead @@ -7410,7 +7407,21 @@ # Save the datalimits for the same reason: _saved_bounds = self.dataLim.bounds + # Check whether bins or range are given explicitly. In that + # case use those values for autoscaling. + binsgiven = (cbook.iterable(bins) or range != None) + # If bins are not specified either explicitly or via range, + # we need to figure out the range required for all datasets, + # and supply that to np.histogram. + if not binsgiven: + xmin = np.inf + xmax = -np.inf + for xi in x: + xmin = min(xmin, xi.min()) + xmax = max(xmax, xi.max()) + range = (xmin, xmax) + hist_kwargs = dict(range=range, normed=bool(normed)) if np.__version__ < "1.3": # version 1.1 and 1.2 hist_kwargs['new'] = True This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-05-31 21:59:15
|
Revision: 8353 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8353&view=rev Author: efiring Date: 2010-05-31 21:59:06 +0000 (Mon, 31 May 2010) Log Message: ----------- Axes.hist: rework autoscaling. Closes 2971357. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010-05-31 19:41:20 UTC (rev 8352) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010-05-31 21:59:06 UTC (rev 8353) @@ -7396,9 +7396,21 @@ w = [None]*nx # Check whether bins or range are given explicitly. In that - # case do not autoscale axes. + # case use those values for autoscaling. binsgiven = (cbook.iterable(bins) or range != None) + # Save autoscale state for later restoration; turn autoscaling + # off so we can do it all a single time at the end, instead + # of having it done by bar or fill and then having to be redone. + _saved_autoscalex = self.get_autoscalex_on() + _saved_autoscaley = self.get_autoscaley_on() + self.set_autoscalex_on(False) + self.set_autoscaley_on(False) + + # Save the datalimits for the same reason: + _saved_bounds = self.dataLim.bounds + + hist_kwargs = dict(range=range, normed=bool(normed)) if np.__version__ < "1.3": # version 1.1 and 1.2 hist_kwargs['new'] = True @@ -7503,18 +7515,21 @@ # adopted from adjust_x/ylim part of the bar method if orientation == 'horizontal': - xmin, xmax = 0, self.dataLim.intervalx[1] + xmin0 = max(_saved_bounds[0]*0.9, 1e-100) + xmax = self.dataLim.intervalx[1] for m in n: xmin = np.amin(m[m!=0]) # filter out the 0 height bins xmin = max(xmin*0.9, 1e-100) + xmin = min(xmin0, xmin) self.dataLim.intervalx = (xmin, xmax) elif orientation == 'vertical': - ymin, ymax = 0, self.dataLim.intervaly[1] + ymin0 = max(_saved_bounds[1]*0.9, 1e-100) + ymax = self.dataLim.intervaly[1] for m in n: ymin = np.amin(m[m!=0]) # filter out the 0 height bins ymin = max(ymin*0.9, 1e-100) + ymin = min(ymin0, ymin) self.dataLim.intervaly = (ymin, ymax) - self.autoscale_view() if label is None: labels = ['_nolegend_'] @@ -7535,18 +7550,15 @@ lbl = '_nolegend_' if binsgiven: - self.set_autoscale_on(False) if orientation == 'vertical': - self.autoscale_view(scalex=False, scaley=True) - XL = self.xaxis.get_major_locator().view_limits( - bins[0], bins[-1]) - self.set_xbound(XL) + self.update_datalim([(bins[0],0), (bins[-1],0)], updatey=False) else: - self.autoscale_view(scalex=True, scaley=False) - YL = self.yaxis.get_major_locator().view_limits( - bins[0], bins[-1]) - self.set_ybound(YL) + self.update_datalim([(0,bins[0]), (0,bins[-1])], updatex=False) + self.set_autoscalex_on(_saved_autoscalex) + self.set_autoscaley_on(_saved_autoscaley) + self.autoscale_view() + if nx == 1: return n[0], bins, cbook.silent_list('Patch', patches[0]) else: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-05-31 19:41:26
|
Revision: 8352 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8352&view=rev Author: efiring Date: 2010-05-31 19:41:20 +0000 (Mon, 31 May 2010) Log Message: ----------- grid, box: allow 'on' or 'off' in place of boolean. Closes 2871949. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/pyplot.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010-05-31 18:45:39 UTC (rev 8351) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010-05-31 19:41:20 UTC (rev 8352) @@ -39,6 +39,15 @@ is_string_like = cbook.is_string_like is_sequence_of_strings = cbook.is_sequence_of_strings +def _string_to_bool(s): + if not is_string_like(s): + return s + if s == 'on': + return True + if s == 'off': + return False + raise ValueError("string argument must be either 'on' or 'off'") + def _process_plot_format(fmt): """ Process a matlab(TM) style color/line style format string. Return a @@ -1954,7 +1963,8 @@ grid(self, b=None, **kwargs) - Set the axes grids on or off; *b* is a boolean + Set the axes grids on or off; *b* is a boolean. (For Matlab + compatibility, *b* may also be a string, 'on' or 'off'.) If *b* is *None* and ``len(kwargs)==0``, toggle the grid state. If *kwargs* are supplied, it is assumed that you want a grid and *b* @@ -1968,7 +1978,9 @@ %(Line2D)s """ - if len(kwargs): b = True + if len(kwargs): + b = True + b = _string_to_bool(b) self.xaxis.grid(b, **kwargs) self.yaxis.grid(b, **kwargs) Modified: trunk/matplotlib/lib/matplotlib/pyplot.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pyplot.py 2010-05-31 18:45:39 UTC (rev 8351) +++ trunk/matplotlib/lib/matplotlib/pyplot.py 2010-05-31 19:41:20 UTC (rev 8352) @@ -12,7 +12,7 @@ from matplotlib.rcsetup import interactive_bk as _interactive_bk from matplotlib.artist import getp, get, Artist from matplotlib.artist import setp as _setp -from matplotlib.axes import Axes, Subplot +from matplotlib.axes import Axes, Subplot, _string_to_bool from matplotlib.projections import PolarAxes from matplotlib import mlab # for csv2rec, detrend_none, window_hanning from matplotlib.scale import get_scale_docs, get_scale_names @@ -886,10 +886,12 @@ def box(on=None): """ Turn the axes box on or off according to *on*. + *on* may be a boolean or a string, 'on' or 'off'. If *on* is *None*, toggle state. """ ax = gca() + on = _string_to_bool(on) if on is None: on = not ax.get_frame_on() ax.set_frame_on(on) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-05-31 18:45:45
|
Revision: 8351 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8351&view=rev Author: efiring Date: 2010-05-31 18:45:39 +0000 (Mon, 31 May 2010) Log Message: ----------- bugfix: set_ticklabels must operate on label2 as well as label1; closes 2957923 Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axis.py Modified: trunk/matplotlib/lib/matplotlib/axis.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axis.py 2010-05-31 18:44:13 UTC (rev 8350) +++ trunk/matplotlib/lib/matplotlib/axis.py 2010-05-31 18:45:39 UTC (rev 8351) @@ -1187,7 +1187,17 @@ """ Set the text values of the tick labels. Return a list of Text instances. Use *kwarg* *minor=True* to select minor ticks. + All other kwargs are used to update the text object properties. + As for get_ticklabels, label1 (left or bottom) is + affected for a given tick only if its label1On attribute + is True, and similarly for label2. The list of returned + label text objects consists of all such label1 objects followed + by all such label2 objects. + The input *ticklabels* is assumed to match the set of + tick locations, regardless of the state of label1On and + label2On. + ACCEPTS: sequence of strings """ #ticklabels = [str(l) for l in ticklabels] @@ -1201,13 +1211,19 @@ self.set_major_formatter( mticker.FixedFormatter(ticklabels) ) - ret = [] + ret1 = [] + ret2 = [] for i, tick in enumerate(ticks): if i<len(ticklabels): - tick.label1.set_text(ticklabels[i]) - ret.append(tick.label1) - tick.label1.update(kwargs) - return ret + if tick.label1On: + tick.label1.set_text(ticklabels[i]) + tick.label1.update(kwargs) + ret1.append(tick.label1) + if tick.label2On: + tick.label2.set_text(ticklabels[i]) + ret2.append(tick.label2) + tick.label2.update(kwargs) + return ret1 + ret2 def set_ticks(self, ticks, minor=False): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-05-31 18:44:20
|
Revision: 8350 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8350&view=rev Author: efiring Date: 2010-05-31 18:44:13 +0000 (Mon, 31 May 2010) Log Message: ----------- LogLocator: when using dummy axis, don't try to access axes attribute Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/ticker.py Modified: trunk/matplotlib/lib/matplotlib/ticker.py =================================================================== --- trunk/matplotlib/lib/matplotlib/ticker.py 2010-05-31 00:14:03 UTC (rev 8349) +++ trunk/matplotlib/lib/matplotlib/ticker.py 2010-05-31 18:44:13 UTC (rev 8350) @@ -1234,7 +1234,8 @@ vmin, vmax = self.axis.get_view_interval() - if self.axis.axes.name == 'polar': + # dummy axis has no axes attribute + if hasattr(self.axis, 'axes') and self.axis.axes.name == 'polar': vmax = math.ceil(math.log(vmax) / math.log(b)) decades = np.arange(vmax - self.numdecs, vmax) ticklocs = b ** decades This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-05-31 00:15:47
|
Revision: 8349 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8349&view=rev Author: efiring Date: 2010-05-31 00:14:03 +0000 (Mon, 31 May 2010) Log Message: ----------- set_yscale should autoscale only y, etc. closes 2872466 Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010-05-30 23:58:27 UTC (rev 8348) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010-05-31 00:14:03 UTC (rev 8349) @@ -2246,7 +2246,7 @@ %(scale_docs)s """ self.xaxis.set_scale(value, **kwargs) - self.autoscale_view() + self.autoscale_view(scaley=False) self._update_transScale() def get_xticks(self, minor=False): @@ -2420,7 +2420,7 @@ %(scale_docs)s """ self.yaxis.set_scale(value, **kwargs) - self.autoscale_view() + self.autoscale_view(scalex=False) self._update_transScale() def get_yticks(self, minor=False): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-05-30 23:58:33
|
Revision: 8348 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8348&view=rev Author: efiring Date: 2010-05-30 23:58:27 +0000 (Sun, 30 May 2010) Log Message: ----------- LogNorm.autoscale ignores nonpositive values; closes 2953069 Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/colors.py Modified: trunk/matplotlib/lib/matplotlib/colors.py =================================================================== --- trunk/matplotlib/lib/matplotlib/colors.py 2010-05-30 21:31:19 UTC (rev 8347) +++ trunk/matplotlib/lib/matplotlib/colors.py 2010-05-30 23:58:27 UTC (rev 8348) @@ -850,6 +850,8 @@ vtype = 'scalar' val = ma.array([value]).astype(np.float) + val = ma.masked_less_equal(val, 0, copy=False) + self.autoscale_None(val) vmin, vmax = self.vmin, self.vmax if vmin > vmax: @@ -879,6 +881,24 @@ else: return vmin * pow((vmax/vmin), value) + def autoscale(self, A): + ''' + Set *vmin*, *vmax* to min, max of *A*. + ''' + A = ma.masked_less_equal(A, 0, copy=False) + self.vmin = ma.min(A) + self.vmax = ma.max(A) + + def autoscale_None(self, A): + ' autoscale only None-valued vmin or vmax' + if self.vmin is not None and self.vmax is not None: + return + A = ma.masked_less_equal(A, 0, copy=False) + if self.vmin is None: + self.vmin = ma.min(A) + if self.vmax is None: + self.vmax = ma.max(A) + class BoundaryNorm(Normalize): ''' Generate a colormap index based on discrete intervals. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-05-30 21:31:26
|
Revision: 8347 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8347&view=rev Author: efiring Date: 2010-05-30 21:31:19 +0000 (Sun, 30 May 2010) Log Message: ----------- close 1287318; remove method deprecated in 2006; remove incorrect warning Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/figure.py Modified: trunk/matplotlib/lib/matplotlib/figure.py =================================================================== --- trunk/matplotlib/lib/matplotlib/figure.py 2010-05-30 21:15:47 UTC (rev 8346) +++ trunk/matplotlib/lib/matplotlib/figure.py 2010-05-30 21:31:19 UTC (rev 8347) @@ -411,11 +411,6 @@ self.images.append(im) return im - def set_figsize_inches(self, *args, **kwargs): - import warnings - warnings.warn('Use set_size_inches instead!', DeprecationWarning) - self.set_size_inches(*args, **kwargs) - def set_size_inches(self, *args, **kwargs): """ set_size_inches(w,h, forward=False) @@ -431,9 +426,6 @@ automatically updated; eg you can resize the figure window from the shell - WARNING: forward=True is broken on all backends except GTK* - and WX* - ACCEPTS: a w,h tuple with w,h in inches """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-05-30 21:15:53
|
Revision: 8346 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8346&view=rev Author: efiring Date: 2010-05-30 21:15:47 +0000 (Sun, 30 May 2010) Log Message: ----------- close 3009264; allow windows build on python 2.7; thanks to Christoph Gohlke Modified Paths: -------------- trunk/matplotlib/setupext.py Modified: trunk/matplotlib/setupext.py =================================================================== --- trunk/matplotlib/setupext.py 2010-05-30 20:30:47 UTC (rev 8345) +++ trunk/matplotlib/setupext.py 2010-05-30 21:15:47 UTC (rev 8346) @@ -997,7 +997,7 @@ message = None if sys.platform == 'win32': major, minor1, minor2, s, tmp = sys.version_info - if major == 2 and minor1 == 6: + if major == 2 and minor1 in [6, 7]: module.include_dirs.extend(['win32_static/include/tcl85']) module.libraries.extend(['tk85', 'tcl85']) elif major == 2 and minor1 in [3, 4, 5]: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2010-05-30 20:30:53
|
Revision: 8345 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8345&view=rev Author: jdh2358 Date: 2010-05-30 20:30:47 +0000 (Sun, 30 May 2010) Log Message: ----------- update version num for release Modified Paths: -------------- branches/v0_99_maint/lib/matplotlib/__init__.py Modified: branches/v0_99_maint/lib/matplotlib/__init__.py =================================================================== --- branches/v0_99_maint/lib/matplotlib/__init__.py 2010-05-30 18:48:35 UTC (rev 8344) +++ branches/v0_99_maint/lib/matplotlib/__init__.py 2010-05-30 20:30:47 UTC (rev 8345) @@ -89,7 +89,7 @@ """ from __future__ import generators -__version__ = '0.99.3rc1' +__version__ = '0.99.3' __revision__ = '$Revision$' __date__ = '$Date$' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-05-30 18:48:41
|
Revision: 8344 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8344&view=rev Author: efiring Date: 2010-05-30 18:48:35 +0000 (Sun, 30 May 2010) Log Message: ----------- pyplot.findobj: use docstring decorator. Closes 2994238. Thanks to Mark Roddy. Modified Paths: -------------- trunk/matplotlib/examples/tests/backend_driver.py trunk/matplotlib/lib/matplotlib/pyplot.py Modified: trunk/matplotlib/examples/tests/backend_driver.py =================================================================== --- trunk/matplotlib/examples/tests/backend_driver.py 2010-05-30 18:35:42 UTC (rev 8343) +++ trunk/matplotlib/examples/tests/backend_driver.py 2010-05-30 18:48:35 UTC (rev 8344) @@ -387,7 +387,7 @@ return failures def parse_options(): - doc = __doc__.split('\n\n') + doc = (__doc__ and __doc__.split('\n\n')) or " " op = OptionParser(description=doc[0].strip(), usage='%prog [options] [--] [backends and switches]', #epilog='\n'.join(doc[1:]) # epilog not supported on my python2.4 machine: JDH Modified: trunk/matplotlib/lib/matplotlib/pyplot.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pyplot.py 2010-05-30 18:35:42 UTC (rev 8343) +++ trunk/matplotlib/lib/matplotlib/pyplot.py 2010-05-30 18:48:35 UTC (rev 8344) @@ -78,12 +78,11 @@ from matplotlib.backends import pylab_setup new_figure_manager, draw_if_interactive, show = pylab_setup() - +...@do...py_dedent(Artist.findobj) def findobj(o=None, match=None): if o is None: o = gcf() return o.findobj(match) -findobj.__doc__ = Artist.findobj.__doc__ def switch_backend(newbackend): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-05-30 18:35:49
|
Revision: 8343 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8343&view=rev Author: efiring Date: 2010-05-30 18:35:42 +0000 (Sun, 30 May 2010) Log Message: ----------- pyplot_tutorial: add note about pyplot.close, add TM to first Matlab ref Modified Paths: -------------- trunk/matplotlib/doc/users/pyplot_tutorial.rst Modified: trunk/matplotlib/doc/users/pyplot_tutorial.rst =================================================================== --- trunk/matplotlib/doc/users/pyplot_tutorial.rst 2010-05-28 18:53:48 UTC (rev 8342) +++ trunk/matplotlib/doc/users/pyplot_tutorial.rst 2010-05-30 18:35:42 UTC (rev 8343) @@ -5,7 +5,8 @@ *************** :mod:`matplotlib.pyplot` is a collection of command style functions -that make matplotlib work like matlab. Each ``pyplot`` function makes +that make matplotlib work like `Matlab™ <http://www.mathworks.com>`_. +Each ``pyplot`` function makes some change to a figure: eg, create a figure, create a plotting area in a figure, plot some lines in a plotting area, decorate the plot with labels, etc.... :mod:`matplotlib.pyplot` is stateful, in that it @@ -29,10 +30,10 @@ plt.plot([1,2,3,4], [1,4,9,16]) -For every x, y pair of arguments, there is a optional third argument +For every x, y pair of arguments, there is an optional third argument which is the format string that indicates the color and line type of the plot. The letters and symbols of the format string are from -matlab, and you concatenate a color string with a line style string. +Matlab, and you concatenate a color string with a line style string. The default format string is 'b-', which is a solid blue line. For example, to plot the above with red circles, you would issue @@ -86,7 +87,7 @@ lines = plt.plot(x1, y1, x2, y2) # use keyword args plt.setp(lines, color='r', linewidth=2.0) - # or matlab style string value pairs + # or Matlab style string value pairs plt.setp(lines, 'color', 'r', 'linewidth', 2.0) @@ -204,6 +205,15 @@ stateful wrapper around an object oriented API, which you can use instead (see :ref:`artist-tutorial`) +If you are making a long sequence of figures, you need to be aware of one +more thing: the memory required for a figure is not completely +released until the figure is explicitly closed with +:func:`~matplotlib.pyplot.close`. Deleting all references to the +figure, and/or using the window manager to kill the window in which +the figure appears on the screen, is not enough, because pyplot +maintains internal references until :func:`~matplotlib.pyplot.close` +is called. + .. _working-with-text: Working with text @@ -270,3 +280,4 @@ :ref:`annotations-tutorial` and :ref:`plotting-guide-annotation` for details. More examples can be found in :ref:`pylab_examples-annotation_demo`. + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <js...@us...> - 2010-05-28 18:53:55
|
Revision: 8342 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8342&view=rev Author: jswhit Date: 2010-05-28 18:53:48 +0000 (Fri, 28 May 2010) Log Message: ----------- fix typo Modified Paths: -------------- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py =================================================================== --- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py 2010-05-28 17:42:05 UTC (rev 8341) +++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py 2010-05-28 18:53:48 UTC (rev 8342) @@ -2759,7 +2759,7 @@ import matplotlib.tri as tri except: msg='need basemap > 0.99.1 to plot on unstructured grids' - Raise ImportError(msg) + raise ImportError(msg) # for unstructured grids, toss out points outside # projection limb (don't use those points in triangulation). if hasattr(data,'mask'): @@ -2849,7 +2849,7 @@ import matplotlib.tri as tri except: msg='need basemap > 0.99.1 to plot on unstructured grids' - Raise ImportError(msg) + raise ImportError(msg) # for unstructured grids, toss out points outside # projection limb (don't use those points in triangulation). if hasattr(data,'mask'): @@ -2934,7 +2934,7 @@ import matplotlib.tri as tri except: msg='need basemap > 0.99.1 to plot on unstructured grids' - Raise ImportError(msg) + raise ImportError(msg) # for unstructured grids, toss out points outside # projection limb (don't use those points in triangulation). if hasattr(data,'mask'): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2010-05-28 17:42:12
|
Revision: 8341 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8341&view=rev Author: mdboom Date: 2010-05-28 17:42:05 +0000 (Fri, 28 May 2010) Log Message: ----------- Fix memory leak caused by never disconnecting callbacks. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/cbook.py Modified: trunk/matplotlib/lib/matplotlib/cbook.py =================================================================== --- trunk/matplotlib/lib/matplotlib/cbook.py 2010-05-28 16:56:45 UTC (rev 8340) +++ trunk/matplotlib/lib/matplotlib/cbook.py 2010-05-28 17:42:05 UTC (rev 8341) @@ -13,6 +13,7 @@ import os.path import random import urllib2 +import new import matplotlib @@ -124,12 +125,87 @@ callbacks.disconnect(ideat) # disconnect oneat callbacks.process('eat', 456) # nothing will be called + In practice, one should always disconnect all callbacks when they + are no longer needed to avoid dangling references (and thus memory + leaks). However, real code in matplotlib rarely does so, and due + to its design, it is rather difficult to place this kind of code. + To get around this, and prevent this class of memory leaks, we + instead store weak references to bound methods only, so when the + destination object needs to die, the CallbackRegistry won't keep + it alive. The Python stdlib weakref module can not create weak + references to bound methods directly, so we need to create a proxy + object to handle weak references to bound methods (or regular free + functions). This technique was shared by Peter Parente on his + `"Mindtrove" blog + <http://mindtrove.info/articles/python-weak-references/>`_. """ + class BoundMethodProxy(object): + ''' + Our own proxy object which enables weak references to bound and unbound + methods and arbitrary callables. Pulls information about the function, + class, and instance out of a bound method. Stores a weak reference to the + instance to support garbage collection. + + @organization: IBM Corporation + @copyright: Copyright (c) 2005, 2006 IBM Corporation + @license: The BSD License + + Minor bugfixes by Michael Droettboom + ''' + def __init__(self, cb): + try: + try: + self.inst = ref(cb.im_self) + except TypeError: + self.inst = None + self.func = cb.im_func + self.klass = cb.im_class + except AttributeError: + self.inst = None + self.func = cb + self.klass = None + + def __call__(self, *args, **kwargs): + ''' + Proxy for a call to the weak referenced object. Take + arbitrary params to pass to the callable. + + Raises `ReferenceError`: When the weak reference refers to + a dead object + ''' + if self.inst is not None and self.inst() is None: + raise ReferenceError + elif self.inst is not None: + # build a new instance method with a strong reference to the instance + mtd = new.instancemethod(self.func, self.inst(), self.klass) + else: + # not a bound method, just return the func + mtd = self.func + # invoke the callable and return the result + return mtd(*args, **kwargs) + + def __eq__(self, other): + ''' + Compare the held function and instance with that held by + another proxy. + ''' + try: + if self.inst is None: + return self.func == other.func and other.inst is None + else: + return self.func == other.func and self.inst() == other.inst() + except Exception: + return False + + def __ne__(self, other): + ''' + Inverse of __eq__. + ''' + return not self.__eq__(other) + def __init__(self, signals): '*signals* is a sequence of valid signals' self.signals = set(signals) - # callbacks is a dict mapping the signal to a dictionary - # mapping callback id to the callback function self.callbacks = dict([(s, dict()) for s in signals]) self._cid = 0 @@ -146,8 +222,15 @@ func will be called """ self._check_signal(s) - self._cid +=1 - self.callbacks[s][self._cid] = func + proxy = self.BoundMethodProxy(func) + for cid, callback in self.callbacks[s].items(): + # Clean out dead references + if callback.inst is not None and callback.inst() is None: + del self.callbacks[s][cid] + elif callback == proxy: + return cid + self._cid += 1 + self.callbacks[s][self._cid] = proxy return self._cid def disconnect(self, cid): @@ -155,9 +238,12 @@ disconnect the callback registered with callback id *cid* """ for eventname, callbackd in self.callbacks.items(): - try: del callbackd[cid] - except KeyError: continue - else: return + try: + del callbackd[cid] + except KeyError: + continue + else: + return def process(self, s, *args, **kwargs): """ @@ -165,8 +251,12 @@ callbacks on *s* will be called with *\*args* and *\*\*kwargs* """ self._check_signal(s) - for func in self.callbacks[s].values(): - func(*args, **kwargs) + for cid, proxy in self.callbacks[s].items(): + # Clean out dead references + if proxy.inst is not None and proxy.inst() is None: + del self.callbacks[s][cid] + else: + proxy(*args, **kwargs) class Scheduler(threading.Thread): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |