From: <ef...@us...> - 2008-11-18 23:38:59
|
Revision: 6414 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6414&view=rev Author: efiring Date: 2008-11-18 23:38:53 +0000 (Tue, 18 Nov 2008) Log Message: ----------- New custom colormap example; and fix typo in Axes.autoscale_view Modified Paths: -------------- trunk/matplotlib/examples/tests/backend_driver.py trunk/matplotlib/lib/matplotlib/axes.py Added Paths: ----------- trunk/matplotlib/examples/pylab_examples/custom_cmap.py Added: trunk/matplotlib/examples/pylab_examples/custom_cmap.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/custom_cmap.py (rev 0) +++ trunk/matplotlib/examples/pylab_examples/custom_cmap.py 2008-11-18 23:38:53 UTC (rev 6414) @@ -0,0 +1,134 @@ +#!/usr/bin/env python + +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.colors import LinearSegmentedColormap + +""" + +Example: suppose you want red to increase from 0 to 1 over the bottom +half, green to do the same over the middle half, and blue over the top +half. Then you would use: + +cdict = {'red': ((0.0, 0.0, 0.0), + (0.5, 1.0, 1.0), + (1.0, 1.0, 1.0)), + + 'green': ((0.0, 0.0, 0.0), + (0.25, 0.0, 0.0), + (0.75, 1.0, 1.0), + (1.0, 1.0, 1.0)), + + 'blue': ((0.0, 0.0, 0.0), + (0.5, 0.0, 0.0), + (1.0, 1.0, 1.0))} + +If, as in this example, there are no discontinuities in the r, g, and b +components, then it is quite simple: the second and third element of +each tuple, above, is the same--call it "y". The first element ("x") +defines interpolation intervals over the full range of 0 to 1, and it +must span that whole range. In other words, the values of x divide the +0-to-1 range into a set of segments, and y gives the end-point color +values for each segment. + +Now consider the green. cdict['green'] is saying that for +0 <= x <= 0.25, y is zero; no green. +0.25 < x <= 0.75, y varies linearly from 0 to 1. +x > 0.75, y remains at 1, full green. + +If there are discontinuities, then it is a little more complicated. +Label the 3 elements in each row in the cdict entry for a given color as +(x, y0, y1). Then for values of x between x[i] and x[i+1] the color +value is interpolated between y1[i] and y0[i+1]. + +Going back to the cookbook example, look at cdict['red']; because y0 != +y1, it is saying that for x from 0 to 0.5, red increases from 0 to 1, +but then it jumps down, so that for x from 0.5 to 1, red increases from +0.7 to 1. Green ramps from 0 to 1 as x goes from 0 to 0.5, then jumps +back to 0, and ramps back to 1 as x goes from 0.5 to 1. + +row i: x y0 y1 + / + / +row i+1: x y0 y1 + +Above is an attempt to show that for x in the range x[i] to x[i+1], the +interpolation is between y1[i] and y0[i+1]. So, y0[0] and y1[-1] are +never used. + +""" + + + +cdict1 = {'red': ((0.0, 0.0, 0.0), + (0.5, 0.0, 0.1), + (1.0, 1.0, 1.0)), + + 'green': ((0.0, 0.0, 0.0), + (1.0, 0.0, 0.0)), + + 'blue': ((0.0, 0.0, 1.0), + (0.5, 0.1, 0.0), + (1.0, 0.0, 0.0)) + } + +cdict2 = {'red': ((0.0, 0.0, 0.0), + (0.5, 0.0, 1.0), + (1.0, 0.1, 1.0)), + + 'green': ((0.0, 0.0, 0.0), + (1.0, 0.0, 0.0)), + + 'blue': ((0.0, 0.0, 0.1), + (0.5, 1.0, 0.0), + (1.0, 0.0, 0.0)) + } + +cdict3 = {'red': ((0.0, 0.0, 0.0), + (0.25,0.0, 0.0), + (0.5, 0.8, 1.0), + (0.75,1.0, 1.0), + (1.0, 0.4, 1.0)), + + 'green': ((0.0, 0.0, 0.0), + (0.25,0.0, 0.0), + (0.5, 0.9, 0.9), + (0.75,0.0, 0.0), + (1.0, 0.0, 0.0)), + + 'blue': ((0.0, 0.0, 0.4), + (0.25,1.0, 1.0), + (0.5, 1.0, 0.8), + (0.75,0.0, 0.0), + (1.0, 0.0, 0.0)) + } + + +blue_red1 = LinearSegmentedColormap('BlueRed1', cdict1) +blue_red2 = LinearSegmentedColormap('BlueRed2', cdict2) +blue_red3 = LinearSegmentedColormap('BlueRed3', cdict3) + +x = np.arange(0, np.pi, 0.1) +y = np.arange(0, 2*np.pi, 0.1) +X, Y = np.meshgrid(x,y) +Z = np.cos(X) * np.sin(Y) + +plt.figure(figsize=(10,4)) +plt.subplots_adjust(wspace=0.3) + +plt.subplot(1,3,1) +plt.imshow(Z, interpolation='nearest', cmap=blue_red1) +plt.colorbar() + +plt.subplot(1,3,2) +plt.imshow(Z, interpolation='nearest', cmap=blue_red2) +plt.colorbar() + +plt.subplot(1,3,3) +plt.imshow(Z, interpolation='nearest', cmap=blue_red3) +plt.colorbar() + +plt.suptitle('Custom Blue-Red colormaps') + +plt.show() + Modified: trunk/matplotlib/examples/tests/backend_driver.py =================================================================== --- trunk/matplotlib/examples/tests/backend_driver.py 2008-11-18 21:37:25 UTC (rev 6413) +++ trunk/matplotlib/examples/tests/backend_driver.py 2008-11-18 23:38:53 UTC (rev 6414) @@ -43,6 +43,7 @@ 'contour_demo.py', 'contour_label_demo.py', 'contourf_demo.py', + 'custom_cmap.py', 'geo_demo.py', 'griddata_demo.py', 'csd_demo.py', Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-11-18 21:37:25 UTC (rev 6413) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-11-18 23:38:53 UTC (rev 6414) @@ -1496,7 +1496,7 @@ if scalex: self.set_xbound(x0, x1) if scaley: - self.set_ybound(y0, 11) + self.set_ybound(y0, y1) return if scalex: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2008-11-19 14:45:51
|
Revision: 6415 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6415&view=rev Author: mdboom Date: 2008-11-19 14:45:44 +0000 (Wed, 19 Nov 2008) Log Message: ----------- Converted API_CHANGES to reST and included it in the documentation tree. Modified Paths: -------------- trunk/matplotlib/doc/api/index.rst Added Paths: ----------- trunk/matplotlib/doc/api/api_changes.rst Removed Paths: ------------- trunk/matplotlib/API_CHANGES Deleted: trunk/matplotlib/API_CHANGES =================================================================== --- trunk/matplotlib/API_CHANGES 2008-11-18 23:38:53 UTC (rev 6414) +++ trunk/matplotlib/API_CHANGES 2008-11-19 14:45:44 UTC (rev 6415) @@ -1,1310 +0,0 @@ -Changes for 0.98.x -================== - -* set_xlim, ylim now return a copy of the viewlim array to - avoid modify inplace surprises - -* AFM.get_fullname() and get_familyname() no longer raise an - exception if the AFM file does not specify these optional attributes, - but returns a guess based on the required FontName attribute. - -* Changed precision kwarg in spy; default is 0, and the string value - 'present' is used for sparse arrays only to show filled locations. - -* EllipseCollection added. - -* Added angles kwarg to quiver for more flexible specification of - the arrow angles. - -* Deprecated (raise NotImplementedError) all the mlab2 functions from - matplotlib.mlab out of concern that some of them were not clean room - implementations. - -* Methods get_offsets and set_offsets added to Collections base - class. - -* Figure.figurePatch renamed Figure.patch, Axes.axesPatch renamed - Axes.patch, Axes.axesFrame renamed Axes.frame, Axes.get_frame, which - returns Axes.patch, is deprecated. Examples and users guide updated - -* Changes in the ContourLabeler attributes (clabel function) so that they - all have a form like .labelAttribute. The three attributes that are most - likely to be used by end users, .cl, .cl_xy and .cl_cvalues have been - maintained for the moment (in addition to their renamed versions), but they - are depricated and will eventually be removed. - -* Moved several function in mlab.py and cbook.py into a separate module - numerical_methods.py because they were unrelated to the initial purpose of - mlab or cbook and appeared more coherent elsewhere. - -Changes for 0.98.1 -================== - -* Removed broken axes3d support and replaced it with a non implemented - error pointing to 0.91.x - -Changes for 0.98.0 -================== - - matplotlib.image.imread now no longer always returns RGBA -- if - the image is luminance or RGB, it will return a MxN or MxNx3 array - if possible. Also uint8 is no longer always forced to float. - - Rewrote the cm.ScalarMappable callback infrastructure to use - cbook.CallbackRegistry rather than custom callback handling. Amy - users of add_observer/notify of the cm.ScalarMappable should uae - the cm.ScalarMappable.callbacksSM CallbackRegistry instead. - - New axes function and Axes method provide control over the plot - color cycle: axes.set_default_color_cycle(clist) and - Axes.set_color_cycle(clist). - - matplotlib now requires python2.4, so matplotlib.cbook will no - loner provide set, enumerate, reversed or izip compatability functions - - In numpy 1.0 bins are specified by the left edges only. The axes - method "hist" now uses future numpy 1.3 semantic for histograms. - Providing binedges, the last value gives the upper-right edge now, - which was implicitly set to +infinity in numpy 1.0. This also means - that the last bin doesn't contain upper outliers any more by default. - - New axes method and pyplot function, hexbin, is an alternative - to scatter for large datasets. It makes something like a - pcolor of a 2-D histogram, but uses hexagonal bins. - - New kwarg, "symmetric", in MaxNLocator - allows one require an axis to be centered on zero. - - toolkits must now be imported from mpl_toolkits (not matplotlib.toolkits) - -TRANSFORMS REFACTORING - - The primary goal of this refactoring was to make it easier to - extend matplotlib to support new kinds of projections. This is - primarily an internal improvement, and the possible user-visible - changes it allows are yet to come. - - See transforms.py for a description of the design of the new - transformation framework. - - For efficiency, many of these functions return views into Numpy - arrays. This means that if you hold on to a reference to them, - their contents may change. If you want to store a snapshot of - their current values, use the Numpy array method copy(). - - The view intervals are now stored only in one place -- in the Axes - instance, not in the formatter instances as well. This means - formatters must get their limits from their Axis, which in turn - looks up its limits from the Axes. If a Locator is used - temporarily and not assigned to an Axis or Axes, (e.g. in - contour.py), a dummy axis must be created to store its bounds. - Call Locator.create_dummy_axis() to do so. - - The functionality of Pbox has been merged with Bbox. Its methods - now all return copies rather than modifying in place. - - The following lists many of the simple changes necessary to update - code from the old transformation framework to the new one. In - particular, methods that return a copy are named with a verb in - the past tense, whereas methods that alter an object in place are - named with a very in the present tense. - - transforms.py - Bbox.get_bounds() Bbox.bounds - - Bbox.width() Bbox.width - - Bbox.height() Bbox.height - - Bbox.intervalx().get_bounds() Bbox.intervalx - Bbox.intervalx().set_bounds() - [Bbox.intervalx is now a property.] - - Bbox.intervaly().get_bounds() Bbox.intervaly - Bbox.intervaly().set_bounds() - [Bbox.intervaly is now a property.] - - Bbox.xmin() Bbox.x0 or Bbox.xmin - Bbox.ymin() Bbox.y0 or Bbox.ymin - Bbox.xmax() Bbox.x1 or Bbox.xmax - Bbox.ymax() Bbox.y1 or Bbox.ymax - [The Bbox is bound by the points (x0, y0) to (x1, y1) and - there is no defined order to these points, that is, x0 is not - necessarily the left edge of the box. To get the left edge of - the Bbox, use the read-only property xmin.] - - Bbox.overlaps(bboxes) Bbox.count_overlaps(bboxes) - - bbox_all(bboxes) Bbox.union(bboxes) - [Bbox.union is a staticmethod.] - - lbwh_to_bbox(l, b, w, h) Bbox.from_bounds(x0, y0, w, h) - - inverse_transform_bbox(trans, bbox) bbox.inverse_transformed(trans) - - Interval.contains_open(v) interval_contains_open(tuple, v) - Interval.contains(v) interval_contains_open(tuple, v) - - identity_transform() IdentityTransform() - - blend_xy_sep_transform(xtrans, ytrans) blended_transform_factory(xtrans, ytrans) - - scale_transform(xs, ys) Affine2D().scale(xs[, ys]) - - get_bbox_transform(boxin, boxout) BboxTransform(boxin, boxout) or - BboxTransformFrom(boxin) or - BboxTransformTo(boxout) - - Transform.seq_xy_tup(points) Transform.transform(points) - - Transform.inverse_xy_tup(points) Transform.inverted().transform(points) - - axes.py - Axes.get_position() Axes.get_position() - [Axes.get_position() used to return a list of points, not it - returns a transforms.Bbox instance.] - - Axes.set_position() Axes.set_position() - [Axes.set_position() now accepts either four scalars or a - transforms Bbox instance.] - - [also returns a Bbox] - Axes.toggle_log_lineary() Axes.set_yscale() - [Since the recfactoring allows for more than two scale types - ('log' or 'linear'), it no longer makes sense to have a - toggle. Axes.toggle_log_lineary() has been removed.] - - Axes.hlines(linestyle=) Axes.hlines(linestyles=) - Axes.vlines(linestyle=) Axes.vlines(linestyles=) - [The kwarg 'linestyle' has been replaced with 'linestyles', - which accepts either a single linestyle or a list of - linestyles to use.] - - Subplot class is gone -- now there is only SubplotBase. - - The Polar class has moved to projections/polar.py - - artist.py - Artist.set_clip_path(path) Artist.set_clip_path(path, transform) - [set_clip_path now accepts a path.Path instance and a - transformation that will be applied to the path immediately - before clipping.] - - collections.py - linestyle linestyles - [Linestyles are now treated like all other collection - attributes -- a single value or multiple values may be - provided.] - - colors.py - ColorConvertor.to_rgba_list(c) ColorConvertor.to_rgba_array(c) - [ColorConvertor.to_rgba_array(c) returns an Nx4 Numpy array of - RGBA color quadruples.] - - contour.py - Contour._segments Contour.get_paths() - [Contour.get_paths() now returns a list of path.Path instances.] - - figure.py - Figure.dpi.get()/set() Figure.dpi (a property) - - patches.py - get_verts() get_path() - [Patch.get_path() returns a path.Path instance.] - - backend_bases.py - GraphicsContext.set_clip_rectangle(tuple) GraphicsContext.set_clip_rectangle(bbox) - - GraphicsContext.get_clip_path() GraphicsContext.get_clip_path() - [GraphicsContext.get_clip_path() returns a tuple of the form - (path, affine_transform), where path is a path.Path instance - and affine_transform is a transforms.Affine2D instance.] - - GraphicsContext.set_clip_path(clippath) GraphicsContext.set_clip_path(clippath) - [Now accepts only an instance of transforms.TransformedPath.] - - RendererBase class: - **new methods** ---> - draw_path(self, gc, path, transform, rgbFace) - - draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace) - - draw_path_collection(self, master_transform, cliprect, clippath, - clippath_trans, paths, all_transforms, offsets, - offsetTrans, facecolors, edgecolors, linewidths, - linestyles, antialiaseds) [optional] - - - **changed methods** ---> - draw_image(self, x, y, im, bbox) draw_image(self, x, y, im, bbox, - clippath, clippath_trans) - - **removed methods** ---> - draw_arc - draw_line_collection - draw_line - draw_lines - draw_point - draw_quad_mesh - draw_poly_collection - draw_polygon - draw_rectangle - draw_regpoly_collection - -END OF TRANSFORMS REFACTORING - - - - -0.91.2 Released - - For csv2rec, checkrows=0 is the new default indicating all rows - will be checked for type inference - - A warning is issued when an image is drawn on log-scaled - axes, since it will not log-scale the image data. - - Moved rec2gtk to matplotlib.toolkits.gtktools - - Moved rec2excel to matplotlib.toolkits.exceltools - - Removed, dead/experimental ExampleInfo, Namespace and Importer - code from matplotlib/__init__.py - -0.91.1 Released - -0.91.0 Released - - Changed cbook.is_file_like to cbook.is_writable_file_like and - corrected behavior. - - Added ax kwarg to pyplot.colorbar and Figure.colorbar so that - one can specify the axes object from which space for the colorbar - is to be taken, if one does not want to make the colorbar axes - manually. - - Changed cbook.reversed so it yields a tuple rather than a - (index, tuple). This agrees with the python reversed builtin, - and cbook only defines reversed if python doesnt provide the - builtin. - - Made skiprows=1 the default on csv2rec - - The gd and paint backends have been deleted. - - The errorbar method and function now accept additional kwargs - so that upper and lower limits can be indicated by capping the - bar with a caret instead of a straight line segment. - - The dviread.py file now has a parser for files like psfonts.map - and pdftex.map, to map TeX font names to external files. - - The file type1font.py contains a new class for Type 1 fonts. - Currently it simply reads pfa and pfb format files and stores the - data in a way that is suitable for embedding in pdf files. In the - future the class might actually parse the font to allow e.g. - subsetting. - - FT2Font now supports FT_Attach_File. In practice this can be used - to read an afm file in addition to a pfa/pfb file, to get metrics - and kerning information for a Type 1 font. - - The AFM class now supports querying CapHeight and stem widths. The - get_name_char method now has an isord kwarg like get_width_char. - - Changed pcolor default to shading='flat'; but as noted now in the - docstring, it is preferable to simply use the edgecolor kwarg. - - The mathtext font commands (\cal, \rm, \it, \tt) now behave as TeX - does: they are in effect until the next font change command or the - end of the grouping. Therefore uses of $\cal{R}$ should be - changed to ${\cal R}$. Alternatively, you may use the new - LaTeX-style font commands (\mathcal, \mathrm, \mathit, \mathtt) - which do affect the following group, eg. $\mathcal{R}$. - - Text creation commands have a new default linespacing and - a new linespacing kwarg, which is a multiple of the maximum - vertical extent of a line of ordinary text. The default is - 1.2; linespacing=2 would be like ordinary double spacing, for - example. - - Changed default kwarg in colors.Normalize.__init__ to clip=False; - clipping silently defeats the purpose of the special over, under, - and bad values in the colormap, thereby leading to unexpected - behavior. The new default should reduce such surprises. - - Made the emit property of set_xlim and set_ylim true by default; - removed the Axes custom callback handling into a 'callbacks' - attribute which is a cbook.CallbackRegistry instance. This now - supports the xlim_changed and ylim_changed Axes events. - -0.90.1 released - - The file dviread.py has a (very limited and fragile) dvi reader - for usetex support. The API might change in the future so don't - depend on it yet. - - Removed deprecated support for a float value as a gray-scale; - now it must be a string, like '0.5'. Added alpha kwarg to - ColorConverter.to_rgba_list. - - New method set_bounds(vmin, vmax) for formatters, locators sets - the viewInterval and dataInterval from floats. - - Removed deprecated colorbar_classic. - - Line2D.get_xdata and get_ydata valid_only=False kwarg is replaced - by orig=True. When True, it returns the original data, otherwise - the processed data (masked, converted) - - Some modifications to the units interface. - units.ConversionInterface.tickers renamed to - units.ConversionInterface.axisinfo and it now returns a - units.AxisInfo object rather than a tuple. This will make it - easier to add axis info functionality (eg I added a default label - on this iteration) w/o having to change the tuple length and hence - the API of the client code everytime new functionality is added. - Also, units.ConversionInterface.convert_to_value is now simply - named units.ConversionInterface.convert. - - Axes.errorbar uses Axes.vlines and Axes.hlines to draw its error - limits int he vertical and horizontal direction. As you'll see - in the changes below, these funcs now return a LineCollection - rather than a list of lines. The new return signature for - errorbar is ylins, caplines, errorcollections where - errorcollections is a xerrcollection, yerrcollection - - Axes.vlines and Axes.hlines now create and returns a LineCollection, not a list - of lines. This is much faster. The kwarg signature has changed, - so consult the docs - - MaxNLocator accepts a new Boolean kwarg ('integer') to force - ticks to integer locations. - - Commands that pass an argument to the Text constructor or to - Text.set_text() now accept any object that can be converted - with '%s'. This affects xlabel(), title(), etc. - - Barh now takes a **kwargs dict instead of most of the old - arguments. This helps ensure that bar and barh are kept in sync, - but as a side effect you can no longer pass e.g. color as a - positional argument. - - ft2font.get_charmap() now returns a dict that maps character codes - to glyph indices (until now it was reversed) - - Moved data files into lib/matplotlib so that setuptools' develop - mode works. Re-organized the mpl-data layout so that this source - structure is maintained in the installation. (I.e. the 'fonts' and - 'images' sub-directories are maintained in site-packages.). - Suggest removing site-packages/matplotlib/mpl-data and - ~/.matplotlib/ttffont.cache before installing - -0.90.0 released - - All artists now implement a "pick" method which users should not - call. Rather, set the "picker" property of any artist you want to - pick on (the epsilon distance in points for a hit test) and - register with the "pick_event" callback. See - examples/pick_event_demo.py for details - - Bar, barh, and hist have "log" binary kwarg: log=True - sets the ordinate to a log scale. - - Boxplot can handle a list of vectors instead of just - an array, so vectors can have different lengths. - - Plot can handle 2-D x and/or y; it plots the columns. - - Added linewidth kwarg to bar and barh. - - Made the default Artist._transform None (rather than invoking - identity_transform for each artist only to have it overridden - later). Use artist.get_transform() rather than artist._transform, - even in derived classes, so that the default transform will be - created lazily as needed - - New LogNorm subclass of Normalize added to colors.py. - All Normalize subclasses have new inverse() method, and - the __call__() method has a new clip kwarg. - - Changed class names in colors.py to match convention: - normalize -> Normalize, no_norm -> NoNorm. Old names - are still available for now. - - Removed obsolete pcolor_classic command and method. - - Removed lineprops and markerprops from the Annotation code and - replaced them with an arrow configurable with kwarg arrowprops. - See examples/annotation_demo.py - JDH - -0.87.7 released - - Completely reworked the annotations API because I found the old - API cumbersome. The new design is much more legible and easy to - read. See matplotlib.text.Annotation and - examples/annotation_demo.py - - markeredgecolor and markerfacecolor cannot be configured in - matplotlibrc any more. Instead, markers are generally colored - automatically based on the color of the line, unless marker colors - are explicitely set as kwargs - NN - - Changed default comment character for load to '#' - JDH - - math_parse_s_ft2font_svg from mathtext.py & mathtext2.py now returns - width, height, svg_elements. svg_elements is an instance of Bunch ( - cmbook.py) and has the attributes svg_glyphs and svg_lines, which are both - lists. - - Renderer.draw_arc now takes an additional parameter, rotation. - It specifies to draw the artist rotated in degrees anti- - clockwise. It was added for rotated ellipses. - - Renamed Figure.set_figsize_inches to Figure.set_size_inches to - better match the get method, Figure.get_size_inches. - - Removed the copy_bbox_transform from transforms.py; added - shallowcopy methods to all transforms. All transforms already - had deepcopy methods. - - FigureManager.resize(width, height): resize the window - specified in pixels - - barh: x and y args have been renamed to width and bottom - respectively, and their order has been swapped to maintain - a (position, value) order. - - bar and barh: now accept kwarg 'edgecolor'. - - bar and barh: The left, height, width and bottom args can - now all be scalars or sequences; see docstring. - - barh: now defaults to edge aligned instead of center - aligned bars - - bar, barh and hist: Added a keyword arg 'align' that - controls between edge or center bar alignment. - - Collections: PolyCollection and LineCollection now accept - vertices or segments either in the original form [(x,y), - (x,y), ...] or as a 2D numerix array, with X as the first column - and Y as the second. Contour and quiver output the numerix - form. The transforms methods Bbox.update() and - Transformation.seq_xy_tups() now accept either form. - - Collections: LineCollection is now a ScalarMappable like - PolyCollection, etc. - - Specifying a grayscale color as a float is deprecated; use - a string instead, e.g., 0.75 -> '0.75'. - - Collections: initializers now accept any mpl color arg, or - sequence of such args; previously only a sequence of rgba - tuples was accepted. - - Colorbar: completely new version and api; see docstring. The - original version is still accessible as colorbar_classic, but - is deprecated. - - Contourf: "extend" kwarg replaces "clip_ends"; see docstring. - Masked array support added to pcolormesh. - - Modified aspect-ratio handling: - Removed aspect kwarg from imshow - Axes methods: - set_aspect(self, aspect, adjustable=None, anchor=None) - set_adjustable(self, adjustable) - set_anchor(self, anchor) - Pylab interface: - axis('image') - - Backend developers: ft2font's load_char now takes a flags - argument, which you can OR together from the LOAD_XXX - constants. - -API Changes in matplotlib-0.86 - - Matplotlib data is installed into the matplotlib module. - This is similar to package_data. This should get rid of - having to check for many possibilities in _get_data_path(). - The MATPLOTLIBDATA env key is still checked first to allow - for flexibility. - - 1) Separated the color table data from cm.py out into - a new file, _cm.py, to make it easier to find the actual - code in cm.py and to add new colormaps. Everything - from _cm.py is imported by cm.py, so the split should be - transparent. - 2) Enabled automatic generation of a colormap from - a list of colors in contour; see modified - examples/contour_demo.py. - 3) Support for imshow of a masked array, with the - ability to specify colors (or no color at all) for - masked regions, and for regions that are above or - below the normally mapped region. See - examples/image_masked.py. - 4) In support of the above, added two new classes, - ListedColormap, and no_norm, to colors.py, and modified - the Colormap class to include common functionality. Added - a clip kwarg to the normalize class. - - -API Changes in matplotlib-0.85 - - Made xtick and ytick separate props in rc - - made pos=None the default for tick formatters rather than 0 to - indicate "not supplied" - - Removed "feature" of minor ticks which prevents them from - overlapping major ticks. Often you want major and minor ticks at - the same place, and can offset the major ticks with the pad. This - could be made configurable - - Changed the internal structure of contour.py to a more OO style. - Calls to contour or contourf in axes.py or pylab.py now return - a ContourSet object which contains references to the - LineCollections or PolyCollections created by the call, - as well as the configuration variables that were used. - The ContourSet object is a "mappable" if a colormap was used. - - Added a clip_ends kwarg to contourf. From the docstring: - * clip_ends = True - If False, the limits for color scaling are set to the - minimum and maximum contour levels. - True (default) clips the scaling limits. Example: - if the contour boundaries are V = [-100, 2, 1, 0, 1, 2, 100], - then the scaling limits will be [-100, 100] if clip_ends - is False, and [-3, 3] if clip_ends is True. - Added kwargs linewidths, antialiased, and nchunk to contourf. These - are experimental; see the docstring. - - Changed Figure.colorbar(): - kw argument order changed; - if mappable arg is a non-filled ContourSet, colorbar() shows - lines instead hof polygons. - if mappable arg is a filled ContourSet with clip_ends=True, - the endpoints are not labelled, so as to give the - correct impression of open-endedness. - - Changed LineCollection.get_linewidths to get_linewidth, for - consistency. - - -API Changes in matplotlib-0.84 - - Unified argument handling between hlines and vlines. Both now - take optionally a fmt argument (as in plot) and a keyword args - that can be passed onto Line2D. - - Removed all references to "data clipping" in rc and lines.py since - these were not used and not optimized. I'm sure they'll be - resurrected later with a better implementation when needed. - - 'set' removed - no more deprecation warnings. Use 'setp' instead. - - Backend developers: Added flipud method to image and removed it - from to_str. Removed origin kwarg from backend.draw_image. - origin is handled entirely by the frontend now. - -API Changes in matplotlib-0.83 - - - Made HOME/.matplotlib the new config dir where the matplotlibrc - file, the ttf.cache, and the tex.cache live. The new default - filenames in .matplotlib have no leading dot and are not hidden. - Eg, the new names are matplotlibrc, tex.cache, and ttffont.cache. - This is how ipython does it so it must be right. - - If old files are found, a warning is issued and they are moved to - the new location. - - - backends/__init__.py no longer imports new_figure_manager, - draw_if_interactive and show from the default backend, but puts - these imports into a call to pylab_setup. Also, the Toolbar is no - longer imported from WX/WXAgg. New usage: - - from backends import pylab_setup - new_figure_manager, draw_if_interactive, show = pylab_setup() - - - Moved Figure.get_width_height() to FigureCanvasBase. It now - returns int instead of float. - -API Changes in matplotlib-0.82 - - - toolbar import change in GTKAgg, GTKCairo and WXAgg - - - Added subplot config tool to GTK* backends -- note you must now - import the NavigationToolbar2 from your backend of choice rather - than from backend_gtk because it needs to know about the backend - specific canvas -- see examples/embedding_in_gtk2.py. Ditto for - wx backend -- see examples/embedding_in_wxagg.py - - - - hist bin change - - Sean Richards notes there was a problem in the way we created - the binning for histogram, which made the last bin - underrepresented. From his post: - - I see that hist uses the linspace function to create the bins - and then uses searchsorted to put the values in their correct - bin. Thats all good but I am confused over the use of linspace - for the bin creation. I wouldn't have thought that it does - what is needed, to quote the docstring it creates a "Linear - spaced array from min to max". For it to work correctly - shouldn't the values in the bins array be the same bound for - each bin? (i.e. each value should be the lower bound of a - bin). To provide the correct bins for hist would it not be - something like - - def bins(xmin, xmax, N): - if N==1: return xmax - dx = (xmax-xmin)/N # instead of N-1 - return xmin + dx*arange(N) - - - This suggestion is implemented in 0.81. My test script with these - changes does not reveal any bias in the binning - - from matplotlib.numerix.mlab import randn, rand, zeros, Float - from matplotlib.mlab import hist, mean - - Nbins = 50 - Ntests = 200 - results = zeros((Ntests,Nbins), typecode=Float) - for i in range(Ntests): - print 'computing', i - x = rand(10000) - n, bins = hist(x, Nbins) - results[i] = n - print mean(results) - - -API CHANGES in matplotlib-0.81 - - - pylab and artist "set" functions renamed to setp to avoid clash - with python2.4 built-in set. Current version will issue a - deprecation warning which will be removed in future versions - - - imshow interpolation arguments changes for advanced interpolation - schemes. See help imshow, particularly the interpolation, - filternorm and filterrad kwargs - - - Support for masked arrays has been added to the plot command and - to the Line2D object. Only the valid points are plotted. A - "valid_only" kwarg was added to the get_xdata() and get_ydata() - methods of Line2D; by default it is False, so that the original - data arrays are returned. Setting it to True returns the plottable - points. - - - contour changes: - - Masked arrays: contour and contourf now accept masked arrays as - the variable to be contoured. Masking works correctly for - contour, but a bug remains to be fixed before it will work for - contourf. The "badmask" kwarg has been removed from both - functions. - - Level argument changes: - - Old version: a list of levels as one of the positional - arguments specified the lower bound of each filled region; the - upper bound of the last region was taken as a very large - number. Hence, it was not possible to specify that z values - between 0 and 1, for example, be filled, and that values - outside that range remain unfilled. - - New version: a list of N levels is taken as specifying the - boundaries of N-1 z ranges. Now the user has more control over - what is colored and what is not. Repeated calls to... [truncated message content] |
From: <jd...@us...> - 2008-11-20 18:58:57
|
Revision: 6423 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6423&view=rev Author: jdh2358 Date: 2008-11-20 18:58:54 +0000 (Thu, 20 Nov 2008) Log Message: ----------- added some helper functions for poly collections and masked regions Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/collections.py trunk/matplotlib/lib/matplotlib/mlab.py trunk/matplotlib/src/_backend_agg.cpp Added Paths: ----------- trunk/matplotlib/examples/api/filled_masked_regions.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-11-20 15:46:46 UTC (rev 6422) +++ trunk/matplotlib/CHANGELOG 2008-11-20 18:58:54 UTC (rev 6423) @@ -1,3 +1,11 @@ +2008-11-20 Added some static helper methods + BrokenHBarCollection.span_masked and + PolyCollection.fill_between_masked for visualizing + non-masked regions. In the longer term, the better + solution will be to fix the relevant classes and functions + to handle masked data, so this may be a temporary solution + - JDH + 2008-11-12 Add x_isdata and y_isdata attributes to Artist instances, and use them to determine whether either or both coordinates are used when updating dataLim. This is Added: trunk/matplotlib/examples/api/filled_masked_regions.py =================================================================== --- trunk/matplotlib/examples/api/filled_masked_regions.py (rev 0) +++ trunk/matplotlib/examples/api/filled_masked_regions.py 2008-11-20 18:58:54 UTC (rev 6423) @@ -0,0 +1,45 @@ +""" +Illustrate some helper functions for shading regions where a logical +mask is True +""" +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.collections as collections + + +t = np.arange(0.0, 2, 0.01) +s = np.sin(2*np.pi*t) + +fig = plt.figure() +ax = fig.add_subplot(111) +ax.set_title('using fill_between_masked') +ax.plot(t, s, '-') +ax.axhline(0, color='black', lw=2) + +collection = collections.PolyCollection.fill_between_masked(t, s, s>=0, yboundary=0, color='green', alpha=0.5) +ax.add_collection(collection) + +collection = collections.PolyCollection.fill_between_masked(t, s, s<=0, yboundary=0, color='red', alpha=0.5) +ax.add_collection(collection) + + +fig = plt.figure() +ax = fig.add_subplot(111) +ax.set_title('using span_masked') +ax.plot(t, s, '-') +ax.axhline(0, color='black', lw=2) + +collection = collections.BrokenBarHCollection.span_masked(t, s>0, ymin=0, ymax=1, facecolor='green', alpha=0.5) +ax.add_collection(collection) + +collection = collections.BrokenBarHCollection.span_masked(t, s<0, ymin=-1, ymax=0, facecolor='red', alpha=0.5) +ax.add_collection(collection) + + + +plt.show() + + + + + Modified: trunk/matplotlib/lib/matplotlib/collections.py =================================================================== --- trunk/matplotlib/lib/matplotlib/collections.py 2008-11-20 15:46:46 UTC (rev 6422) +++ trunk/matplotlib/lib/matplotlib/collections.py 2008-11-20 18:58:54 UTC (rev 6423) @@ -19,6 +19,7 @@ import matplotlib.artist as artist import matplotlib.backend_bases as backend_bases import matplotlib.path as mpath +import matplotlib.mlab as mlab class Collection(artist.Artist, cm.ScalarMappable): """ @@ -234,7 +235,7 @@ self._urls = [None,] else: self._urls = urls - + def get_urls(self): return self._urls def set_offsets(self, offsets): @@ -671,6 +672,49 @@ for x in self._sizes] return Collection.draw(self, renderer) + + @staticmethod + def fill_between_masked(x, y, mask, yboundary=0, **kwargs): + """ + Create a :class:`PolyCollection` filling the regions between *y* + and *yboundary7* where ``mask==True`` + + + *x* + an N length np array of the x data + + *y* + an N length np array of the y data + + *mask* + an N length numpy boolean array + + *yboundary* + a scalar to fill between *y* and the boundary + + *kwargs* + keyword args passed on to the :class:`PolyCollection` + + """ + polys = [] + for ind0, ind1 in mlab.contiguous_regions(mask): + theseverts = [] + xslice = x[ind0:ind1] + yslice = y[ind0:ind1] + N = len(xslice) + X = np.zeros((2*N+2, 2), np.float) + X[0] = xslice[0], yboundary + X[N+1] = xslice[-1], yboundary + X[1:N+1,0] = xslice + X[1:N+1,1] = yslice + X[N+2:,0] = xslice[::-1] + X[N+2:,1] = yboundary + + polys.append(X) + + collection = PolyCollection(polys, **kwargs) + return collection + class BrokenBarHCollection(PolyCollection): """ A collection of horizontal bars spanning *yrange* with a sequence of @@ -692,6 +736,25 @@ PolyCollection.__init__(self, verts, **kwargs) __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd + + @staticmethod + def span_masked(x, mask, ymin, ymax, **kwargs): + """ + Create a BrokenBarHCollection to plot horizontal bars from + over the regions in *x* where *mask* is True. The bars range + on the y-axis from *ymin* to *ymax* + + A :class:`BrokenBarHCollection` is returned. + **kwargs are passed on to the collection + """ + xranges = [] + for ind0, ind1 in mlab.contiguous_regions(mask): + xslice = x[ind0:ind1] + xranges.append((xslice[0], xslice[-1]-xslice[0])) + + collection = BrokenBarHCollection(xranges, [ymin, ymax-ymin], **kwargs) + return collection + class RegularPolyCollection(Collection): """Draw a collection of regular polygons with *numsides*.""" _path_generator = mpath.Path.unit_regular_polygon Modified: trunk/matplotlib/lib/matplotlib/mlab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mlab.py 2008-11-20 15:46:46 UTC (rev 6422) +++ trunk/matplotlib/lib/matplotlib/mlab.py 2008-11-20 18:58:54 UTC (rev 6423) @@ -159,7 +159,7 @@ import csv, warnings, copy, os import numpy as np - +ma = np.ma from matplotlib import verbose import matplotlib.nxutils as nxutils @@ -247,7 +247,7 @@ #The checks for if y is x are so that we can use the same function to #implement the core of psd(), csd(), and spectrogram() without doing #extra calculations. We return the unaveraged Pxy, freqs, and t. - + #Make sure we're dealing with a numpy array. If y and x were the same #object to start with, keep them that way same_data = y is x @@ -309,7 +309,7 @@ Pxy /= (np.abs(windowVals)**2).sum() t = 1./Fs * (ind + NFFT / 2.) freqs = float(Fs) / pad_to * np.arange(numFreqs) - + return Pxy, freqs, t #Split out these keyword docs so that they can be used elsewhere @@ -2104,7 +2104,8 @@ def csv2rec(fname, comments='#', skiprows=0, checkrows=0, delimiter=',', - converterd=None, names=None, missing='', missingd=None): + converterd=None, names=None, missing='', missingd=None, + use_mrecords=True): """ Load data from comma/space/tab delimited file in *fname* into a numpy record array and return the record array. @@ -2139,9 +2140,11 @@ be masked, e.g. '0000-00-00' or 'unused' - *missing*: a string whose value signals a missing field regardless of - the column it appears in, e.g. 'unused' + the column it appears in - If no rows are found, *None* is returned -- see :file:`examples/loadrec.py` + - *use_mrecords*: if True, return an mrecords.fromrecords record array if any of the data are missing + + If no rows are found, *None* is returned -- see :file:`examples/loadrec.py` """ if converterd is None: @@ -2338,7 +2341,8 @@ if not len(rows): return None - if np.any(rowmasks): + + if use_mrecords and np.any(rowmasks): try: from numpy.ma import mrecords except ImportError: raise RuntimeError('numpy 1.05 or later is required for masked array support') @@ -2938,19 +2942,25 @@ xv, yv = poly_below(0, x, y) ax.fill(xv, yv) """ - xs = np.asarray(xs) - ys = np.asarray(ys) + if ma.isMaskedArray(xs) or ma.isMaskedArray(ys): + nx = ma + else: + nx = np + + xs = nx.asarray(xs) + ys = nx.asarray(ys) Nx = len(xs) Ny = len(ys) assert(Nx==Ny) - x = xmin*np.ones(2*Nx) - y = np.ones(2*Nx) + x = xmin*nx.ones(2*Nx) + y = nx.ones(2*Nx) x[:Nx] = xs y[:Nx] = ys y[Nx:] = ys[::-1] return x, y + def poly_between(x, ylower, yupper): """ Given a sequence of *x*, *ylower* and *yupper*, return the polygon @@ -2961,17 +2971,23 @@ Return value is *x*, *y* arrays for use with :meth:`matplotlib.axes.Axes.fill`. """ + if ma.isMaskedArray(ylower) or ma.isMaskedArray(yupper) or ma.isMaskedArray(x): + nx = ma + else: + nx = np + Nx = len(x) if not cbook.iterable(ylower): - ylower = ylower*np.ones(Nx) + ylower = ylower*nx.ones(Nx) if not cbook.iterable(yupper): - yupper = yupper*np.ones(Nx) + yupper = yupper*nx.ones(Nx) - x = np.concatenate( (x, x[::-1]) ) - y = np.concatenate( (yupper, ylower[::-1]) ) + x = nx.concatenate( (x, x[::-1]) ) + y = nx.concatenate( (yupper, ylower[::-1]) ) return x,y + def is_closed_polygon(X): """ Tests whether first and last object in a sequence are the same. These are @@ -2980,6 +2996,28 @@ """ return np.all(X[0] == X[-1]) + +def contiguous_regions(mask): + """ + return a list of (ind0, ind1) such that mask[ind0:ind1].all() is + True and we cover all such regions + + TODO: this is a pure python implementation which probably has a much faster numpy impl + """ + + in_region = None + boundaries = [] + for i, val in enumerate(mask): + if in_region is None and val: + in_region = i + elif in_region is not None and not val: + boundaries.append((in_region, i)) + in_region = None + + if in_region is not None: + boundaries.append((in_region, i+1)) + return boundaries + ################################################## # Vector and path length geometry calculations ################################################## Modified: trunk/matplotlib/src/_backend_agg.cpp =================================================================== --- trunk/matplotlib/src/_backend_agg.cpp 2008-11-20 15:46:46 UTC (rev 6422) +++ trunk/matplotlib/src/_backend_agg.cpp 2008-11-20 18:58:54 UTC (rev 6423) @@ -385,7 +385,8 @@ if (!py_convert_bbox(box_obj.ptr(), l, b, r, t)) throw Py::TypeError("Invalid bbox provided to copy_from_bbox"); - agg::rect_i rect((int)l, height - (int)t, (int)r, height - (int)b); + // std::cout << l << " " << b << " " << r << " " << t << " " << (height - (int)b) << " " << height - (int)t << std::endl; + agg::rect_i rect((int)l, height - (int)b, (int)r, height - (int)t); BufferRegion* reg = NULL; try { @@ -419,9 +420,11 @@ BufferRegion* region = static_cast<BufferRegion*>(args[0].ptr()); if (region->data==NULL) - return Py::Object(); - //throw Py::ValueError("Cannot restore_region from NULL data"); + throw Py::ValueError("Cannot restore_region from NULL data"); + //return Py::Object(); + //std::cout << "restoring " << region->width << " " << region->height << " " << region->stride << " " << region->rect.x1 << " " << region->rect.y1 << std::endl; + agg::rendering_buffer rbuf; rbuf.attach(region->data, region->width, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-11-20 20:22:13
|
Revision: 6424 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6424&view=rev Author: jdh2358 Date: 2008-11-20 20:22:08 +0000 (Thu, 20 Nov 2008) Log Message: ----------- reverted a bug I introduced when toying around with copy region in agg Modified Paths: -------------- trunk/matplotlib/examples/event_handling/path_editor.py trunk/matplotlib/lib/matplotlib/collections.py trunk/matplotlib/src/_backend_agg.cpp Modified: trunk/matplotlib/examples/event_handling/path_editor.py =================================================================== --- trunk/matplotlib/examples/event_handling/path_editor.py 2008-11-20 18:58:54 UTC (rev 6423) +++ trunk/matplotlib/examples/event_handling/path_editor.py 2008-11-20 20:22:08 UTC (rev 6424) @@ -1,3 +1,5 @@ +import matplotlib +matplotlib.use('TkAgg') import numpy as np import matplotlib.path as mpath import matplotlib.patches as mpatches Modified: trunk/matplotlib/lib/matplotlib/collections.py =================================================================== --- trunk/matplotlib/lib/matplotlib/collections.py 2008-11-20 18:58:54 UTC (rev 6423) +++ trunk/matplotlib/lib/matplotlib/collections.py 2008-11-20 20:22:08 UTC (rev 6424) @@ -701,6 +701,9 @@ theseverts = [] xslice = x[ind0:ind1] yslice = y[ind0:ind1] + if not len(xslice): + continue + N = len(xslice) X = np.zeros((2*N+2, 2), np.float) X[0] = xslice[0], yboundary @@ -750,6 +753,8 @@ xranges = [] for ind0, ind1 in mlab.contiguous_regions(mask): xslice = x[ind0:ind1] + if not len(xslice): + continue xranges.append((xslice[0], xslice[-1]-xslice[0])) collection = BrokenBarHCollection(xranges, [ymin, ymax-ymin], **kwargs) Modified: trunk/matplotlib/src/_backend_agg.cpp =================================================================== --- trunk/matplotlib/src/_backend_agg.cpp 2008-11-20 18:58:54 UTC (rev 6423) +++ trunk/matplotlib/src/_backend_agg.cpp 2008-11-20 20:22:08 UTC (rev 6424) @@ -386,7 +386,7 @@ throw Py::TypeError("Invalid bbox provided to copy_from_bbox"); // std::cout << l << " " << b << " " << r << " " << t << " " << (height - (int)b) << " " << height - (int)t << std::endl; - agg::rect_i rect((int)l, height - (int)b, (int)r, height - (int)t); + agg::rect_i rect((int)l, height - (int)t, (int)r, height - (int)b); BufferRegion* reg = NULL; try { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-11-21 11:28:35
|
Revision: 6429 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6429&view=rev Author: jdh2358 Date: 2008-11-21 11:28:32 +0000 (Fri, 21 Nov 2008) Log Message: ----------- Merged revisions 6086,6365,6427-6428 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_91_maint ........ r6086 | mdboom | 2008-09-11 15:28:11 -0500 (Thu, 11 Sep 2008) | 2 lines Fix backticks in PS output. ........ r6365 | mdboom | 2008-11-05 09:15:28 -0600 (Wed, 05 Nov 2008) | 1 line Fix bug in zoom rectangle with twin axes ........ r6427 | jdh2358 | 2008-11-21 05:14:12 -0600 (Fri, 21 Nov 2008) | 1 line fixed poly between ........ r6428 | jdh2358 | 2008-11-21 05:15:04 -0600 (Fri, 21 Nov 2008) | 1 line fixed poly below ........ Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/mlab.py Property Changed: ---------------- trunk/matplotlib/ Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6073,6149 + /branches/v0_91_maint:1-6428 Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-11-21 11:15:04 UTC (rev 6428) +++ trunk/matplotlib/CHANGELOG 2008-11-21 11:28:32 UTC (rev 6429) @@ -54,6 +54,10 @@ 2008-10-08 Add path simplification support to paths with gaps. - EF +======= +2008-11-05 Fix bug with zoom to rectangle and twin axes - MGD + +>>>>>>> .merge-right.r6428 2008-10-05 Fix problem with AFM files that don't specify the font's full name or family name. - JKS @@ -97,6 +101,10 @@ 2008-09-10 Add "filled" kwarg to Path.intersects_path and Path.intersects_bbox. - MGD +======= +2008-09-11 Fix use of backticks in PS - MGD + +>>>>>>> .merge-right.r6086 2008-09-07 Changed full arrows slightly to avoid an xpdf rendering problem reported by Friedrich Hagedorn. - JKS Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-11-21 11:15:04 UTC (rev 6428) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-11-21 11:28:32 UTC (rev 6429) @@ -1883,6 +1883,8 @@ for cur_xypress in self._xypress: x, y = event.x, event.y lastx, lasty, a, ind, lim, trans = cur_xypress + if a._sharex or a._sharey: + continue # ignore singular clicks - 5 pixels is a threshold if abs(x-lastx)<5 or abs(y-lasty)<5: self._xypress = None Modified: trunk/matplotlib/lib/matplotlib/mlab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mlab.py 2008-11-21 11:15:04 UTC (rev 6428) +++ trunk/matplotlib/lib/matplotlib/mlab.py 2008-11-21 11:28:32 UTC (rev 6429) @@ -1438,6 +1438,181 @@ else: return X +def slopes(x,y): + """ + SLOPES calculate the slope y'(x) Given data vectors X and Y SLOPES + calculates Y'(X), i.e the slope of a curve Y(X). The slope is + estimated using the slope obtained from that of a parabola through + any three consecutive points. + + This method should be superior to that described in the appendix + of A CONSISTENTLY WELL BEHAVED METHOD OF INTERPOLATION by Russel + W. Stineman (Creative Computing July 1980) in at least one aspect: + + Circles for interpolation demand a known aspect ratio between x- + and y-values. For many functions, however, the abscissa are given + in different dimensions, so an aspect ratio is completely + arbitrary. + + The parabola method gives very similar results to the circle + method for most regular cases but behaves much better in special + cases + + Norbert Nemec, Institute of Theoretical Physics, University or + Regensburg, April 2006 Norbert.Nemec at physik.uni-regensburg.de + + (inspired by a original implementation by Halldor Bjornsson, + Icelandic Meteorological Office, March 2006 halldor at vedur.is) + """ + # Cast key variables as float. + x=np.asarray(x, np.float_) + y=np.asarray(y, np.float_) + + yp=np.zeros(y.shape, np.float_) + + dx=x[1:] - x[:-1] + dy=y[1:] - y[:-1] + dydx = dy/dx + yp[1:-1] = (dydx[:-1] * dx[1:] + dydx[1:] * dx[:-1])/(dx[1:] + dx[:-1]) + yp[0] = 2.0 * dy[0]/dx[0] - yp[1] + yp[-1] = 2.0 * dy[-1]/dx[-1] - yp[-2] + return yp + + +def stineman_interp(xi,x,y,yp=None): + """ + STINEMAN_INTERP Well behaved data interpolation. Given data + vectors X and Y, the slope vector YP and a new abscissa vector XI + the function stineman_interp(xi,x,y,yp) uses Stineman + interpolation to calculate a vector YI corresponding to XI. + + Here's an example that generates a coarse sine curve, then + interpolates over a finer abscissa: + + x = linspace(0,2*pi,20); y = sin(x); yp = cos(x) + xi = linspace(0,2*pi,40); + yi = stineman_interp(xi,x,y,yp); + plot(x,y,'o',xi,yi) + + The interpolation method is described in the article A + CONSISTENTLY WELL BEHAVED METHOD OF INTERPOLATION by Russell + W. Stineman. The article appeared in the July 1980 issue of + Creative Computing with a note from the editor stating that while + they were + + not an academic journal but once in a while something serious + and original comes in adding that this was + "apparently a real solution" to a well known problem. + + For yp=None, the routine automatically determines the slopes using + the "slopes" routine. + + X is assumed to be sorted in increasing order + + For values xi[j] < x[0] or xi[j] > x[-1], the routine tries a + extrapolation. The relevance of the data obtained from this, of + course, questionable... + + original implementation by Halldor Bjornsson, Icelandic + Meteorolocial Office, March 2006 halldor at vedur.is + + completely reworked and optimized for Python by Norbert Nemec, + Institute of Theoretical Physics, University or Regensburg, April + 2006 Norbert.Nemec at physik.uni-regensburg.de + + """ + + # Cast key variables as float. + x=np.asarray(x, np.float_) + y=np.asarray(y, np.float_) + assert x.shape == y.shape + N=len(y) + + if yp is None: + yp = slopes(x,y) + else: + yp=np.asarray(yp, np.float_) + + xi=np.asarray(xi, np.float_) + yi=np.zeros(xi.shape, np.float_) + + # calculate linear slopes + dx = x[1:] - x[:-1] + dy = y[1:] - y[:-1] + s = dy/dx #note length of s is N-1 so last element is #N-2 + + # find the segment each xi is in + # this line actually is the key to the efficiency of this implementation + idx = np.searchsorted(x[1:-1], xi) + + # now we have generally: x[idx[j]] <= xi[j] <= x[idx[j]+1] + # except at the boundaries, where it may be that xi[j] < x[0] or xi[j] > x[-1] + + # the y-values that would come out from a linear interpolation: + sidx = s.take(idx) + xidx = x.take(idx) + yidx = y.take(idx) + xidxp1 = x.take(idx+1) + yo = yidx + sidx * (xi - xidx) + + # the difference that comes when using the slopes given in yp + dy1 = (yp.take(idx)- sidx) * (xi - xidx) # using the yp slope of the left point + dy2 = (yp.take(idx+1)-sidx) * (xi - xidxp1) # using the yp slope of the right point + + dy1dy2 = dy1*dy2 + # The following is optimized for Python. The solution actually + # does more calculations than necessary but exploiting the power + # of numpy, this is far more efficient than coding a loop by hand + # in Python + yi = yo + dy1dy2 * np.choose(np.array(np.sign(dy1dy2), np.int32)+1, + ((2*xi-xidx-xidxp1)/((dy1-dy2)*(xidxp1-xidx)), + 0.0, + 1/(dy1+dy2),)) + return yi + +def inside_poly(points, verts): + """ + points is a sequence of x,y points + verts is a sequence of x,y vertices of a poygon + + return value is a sequence of indices into points for the points + that are inside the polygon + """ + res, = np.nonzero(nxutils.points_inside_poly(points, verts)) + return res + +def poly_below(ymin, xs, ys): + """ + given a arrays *xs* and *ys*, return the vertices of a polygon + that has a scalar lower bound *ymin* and an upper bound at the *ys*. + + intended for use with Axes.fill, eg:: + + xv, yv = poly_below(0, x, y) + ax.fill(xv, yv) + """ + return poly_between(xs, ys, xmin) + + +def poly_between(x, ylower, yupper): + """ + given a sequence of x, ylower and yupper, return the polygon that + fills the regions between them. ylower or yupper can be scalar or + iterable. If they are iterable, they must be equal in length to x + + return value is x, y arrays for use with Axes.fill + """ + Nx = len(x) + if not cbook.iterable(ylower): + ylower = ylower*np.ones(Nx) + + if not cbook.iterable(yupper): + yupper = yupper*np.ones(Nx) + + x = np.concatenate( (x, x[::-1]) ) + y = np.concatenate( (yupper, ylower[::-1]) ) + return x,y + ### the following code was written and submitted by Fernando Perez ### from the ipython numutils package under a BSD license # begin fperez functions This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-11-23 19:04:40
|
Revision: 6432 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6432&view=rev Author: jdh2358 Date: 2008-11-23 19:04:35 +0000 (Sun, 23 Nov 2008) Log Message: ----------- generalized fill between poly collection Modified Paths: -------------- trunk/matplotlib/examples/api/filled_masked_regions.py trunk/matplotlib/lib/matplotlib/collections.py Modified: trunk/matplotlib/examples/api/filled_masked_regions.py =================================================================== --- trunk/matplotlib/examples/api/filled_masked_regions.py 2008-11-21 18:20:00 UTC (rev 6431) +++ trunk/matplotlib/examples/api/filled_masked_regions.py 2008-11-23 19:04:35 UTC (rev 6432) @@ -8,31 +8,36 @@ t = np.arange(0.0, 2, 0.01) -s = np.sin(2*np.pi*t) +s1 = np.sin(2*np.pi*t) +s2 = 1.2*np.sin(4*np.pi*t) fig = plt.figure() ax = fig.add_subplot(111) -ax.set_title('using fill_between_masked') -ax.plot(t, s, '-') +ax.set_title('using fill_between_where') +ax.plot(t, s1, t, s2) ax.axhline(0, color='black', lw=2) -collection = collections.PolyCollection.fill_between_masked(t, s, s>=0, yboundary=0, color='green', alpha=0.5) +collection = collections.PolyCollection.fill_between_where( + t, s1, s2, s1>=s2, color='green', alpha=0.5) ax.add_collection(collection) -collection = collections.PolyCollection.fill_between_masked(t, s, s<=0, yboundary=0, color='red', alpha=0.5) +collection = collections.PolyCollection.fill_between_where( + t, s1, s2, s1<=s2, color='red', alpha=0.5) ax.add_collection(collection) fig = plt.figure() ax = fig.add_subplot(111) ax.set_title('using span_masked') -ax.plot(t, s, '-') +ax.plot(t, s1, '-') ax.axhline(0, color='black', lw=2) -collection = collections.BrokenBarHCollection.span_masked(t, s>0, ymin=0, ymax=1, facecolor='green', alpha=0.5) +collection = collections.BrokenBarHCollection.span_masked( + t, s1>0, ymin=0, ymax=1, facecolor='green', alpha=0.5) ax.add_collection(collection) -collection = collections.BrokenBarHCollection.span_masked(t, s<0, ymin=-1, ymax=0, facecolor='red', alpha=0.5) +collection = collections.BrokenBarHCollection.span_masked( + t, s1<0, ymin=-1, ymax=0, facecolor='red', alpha=0.5) ax.add_collection(collection) Modified: trunk/matplotlib/lib/matplotlib/collections.py =================================================================== --- trunk/matplotlib/lib/matplotlib/collections.py 2008-11-21 18:20:00 UTC (rev 6431) +++ trunk/matplotlib/lib/matplotlib/collections.py 2008-11-23 19:04:35 UTC (rev 6432) @@ -674,7 +674,7 @@ @staticmethod - def fill_between_masked(x, y, mask, yboundary=0, **kwargs): + def fill_between_where(x, y1, y2, mask, **kwargs): """ Create a :class:`PolyCollection` filling the regions between *y* and *yboundary7* where ``mask==True`` @@ -683,35 +683,50 @@ *x* an N length np array of the x data - *y* - an N length np array of the y data + *y1* + an N length scalar or np array of the x data + *y2* + an N length scalar or np array of the x data + *mask* an N length numpy boolean array - *yboundary* - a scalar to fill between *y* and the boundary - *kwargs* keyword args passed on to the :class:`PolyCollection` """ + if not cbook.iterable(y1): + y1 = np.ones_like(x)*y1 + + if not cbook.iterable(y2): + y2 = np.ones_like(x)*y2 + + assert( (len(x)==len(y1)) and (len(x)==len(y2)) ) + polys = [] for ind0, ind1 in mlab.contiguous_regions(mask): theseverts = [] xslice = x[ind0:ind1] - yslice = y[ind0:ind1] + y1slice = y1[ind0:ind1] + y2slice = y2[ind0:ind1] + if not len(xslice): continue N = len(xslice) X = np.zeros((2*N+2, 2), np.float) - X[0] = xslice[0], yboundary - X[N+1] = xslice[-1], yboundary + + # the purpose of the next two lines is for when y2 is a + # scalar like 0 and we want the fill to go all the way + # down to 0 even if none of the y1 sample points do + X[0] = xslice[0], y2slice[0] + X[N+1] = xslice[-1], y2slice[-1] + X[1:N+1,0] = xslice - X[1:N+1,1] = yslice + X[1:N+1,1] = y1slice X[N+2:,0] = xslice[::-1] - X[N+2:,1] = yboundary + X[N+2:,1] = y2slice[::-1] polys.append(X) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-11-23 19:06:02
|
Revision: 6433 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6433&view=rev Author: jdh2358 Date: 2008-11-23 19:05:58 +0000 (Sun, 23 Nov 2008) Log Message: ----------- renamed fill where examples Modified Paths: -------------- trunk/matplotlib/CHANGELOG Added Paths: ----------- trunk/matplotlib/examples/api/fill_where_demo.py Removed Paths: ------------- trunk/matplotlib/examples/api/filled_masked_regions.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-11-23 19:04:35 UTC (rev 6432) +++ trunk/matplotlib/CHANGELOG 2008-11-23 19:05:58 UTC (rev 6433) @@ -1,10 +1,7 @@ 2008-11-20 Added some static helper methods BrokenHBarCollection.span_masked and - PolyCollection.fill_between_masked for visualizing - non-masked regions. In the longer term, the better - solution will be to fix the relevant classes and functions - to handle masked data, so this may be a temporary solution - - JDH + PolyCollection.fill_between_where for visualizing logical + regions. See examples/api/fill_where_demo.py - JDH 2008-11-12 Add x_isdata and y_isdata attributes to Artist instances, and use them to determine whether either or both Copied: trunk/matplotlib/examples/api/fill_where_demo.py (from rev 6432, trunk/matplotlib/examples/api/filled_masked_regions.py) =================================================================== --- trunk/matplotlib/examples/api/fill_where_demo.py (rev 0) +++ trunk/matplotlib/examples/api/fill_where_demo.py 2008-11-23 19:05:58 UTC (rev 6433) @@ -0,0 +1,50 @@ +""" +Illustrate some helper functions for shading regions where a logical +mask is True +""" +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.collections as collections + + +t = np.arange(0.0, 2, 0.01) +s1 = np.sin(2*np.pi*t) +s2 = 1.2*np.sin(4*np.pi*t) + +fig = plt.figure() +ax = fig.add_subplot(111) +ax.set_title('using fill_between_where') +ax.plot(t, s1, t, s2) +ax.axhline(0, color='black', lw=2) + +collection = collections.PolyCollection.fill_between_where( + t, s1, s2, s1>=s2, color='green', alpha=0.5) +ax.add_collection(collection) + +collection = collections.PolyCollection.fill_between_where( + t, s1, s2, s1<=s2, color='red', alpha=0.5) +ax.add_collection(collection) + + +fig = plt.figure() +ax = fig.add_subplot(111) +ax.set_title('using span_masked') +ax.plot(t, s1, '-') +ax.axhline(0, color='black', lw=2) + +collection = collections.BrokenBarHCollection.span_masked( + t, s1>0, ymin=0, ymax=1, facecolor='green', alpha=0.5) +ax.add_collection(collection) + +collection = collections.BrokenBarHCollection.span_masked( + t, s1<0, ymin=-1, ymax=0, facecolor='red', alpha=0.5) +ax.add_collection(collection) + + + +plt.show() + + + + + Deleted: trunk/matplotlib/examples/api/filled_masked_regions.py =================================================================== --- trunk/matplotlib/examples/api/filled_masked_regions.py 2008-11-23 19:04:35 UTC (rev 6432) +++ trunk/matplotlib/examples/api/filled_masked_regions.py 2008-11-23 19:05:58 UTC (rev 6433) @@ -1,50 +0,0 @@ -""" -Illustrate some helper functions for shading regions where a logical -mask is True -""" -import numpy as np -import matplotlib.pyplot as plt -import matplotlib.collections as collections - - -t = np.arange(0.0, 2, 0.01) -s1 = np.sin(2*np.pi*t) -s2 = 1.2*np.sin(4*np.pi*t) - -fig = plt.figure() -ax = fig.add_subplot(111) -ax.set_title('using fill_between_where') -ax.plot(t, s1, t, s2) -ax.axhline(0, color='black', lw=2) - -collection = collections.PolyCollection.fill_between_where( - t, s1, s2, s1>=s2, color='green', alpha=0.5) -ax.add_collection(collection) - -collection = collections.PolyCollection.fill_between_where( - t, s1, s2, s1<=s2, color='red', alpha=0.5) -ax.add_collection(collection) - - -fig = plt.figure() -ax = fig.add_subplot(111) -ax.set_title('using span_masked') -ax.plot(t, s1, '-') -ax.axhline(0, color='black', lw=2) - -collection = collections.BrokenBarHCollection.span_masked( - t, s1>0, ymin=0, ymax=1, facecolor='green', alpha=0.5) -ax.add_collection(collection) - -collection = collections.BrokenBarHCollection.span_masked( - t, s1<0, ymin=-1, ymax=0, facecolor='red', alpha=0.5) -ax.add_collection(collection) - - - -plt.show() - - - - - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-11-23 19:15:04
|
Revision: 6434 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6434&view=rev Author: jdh2358 Date: 2008-11-23 19:15:01 +0000 (Sun, 23 Nov 2008) Log Message: ----------- updated api for fill_between_where and span_where Modified Paths: -------------- trunk/matplotlib/examples/api/fill_where_demo.py trunk/matplotlib/lib/matplotlib/collections.py Modified: trunk/matplotlib/examples/api/fill_where_demo.py =================================================================== --- trunk/matplotlib/examples/api/fill_where_demo.py 2008-11-23 19:05:58 UTC (rev 6433) +++ trunk/matplotlib/examples/api/fill_where_demo.py 2008-11-23 19:15:01 UTC (rev 6434) @@ -1,6 +1,9 @@ """ Illustrate some helper functions for shading regions where a logical mask is True + +See :meth:`matplotlib.collections.PolyCollection.fill_between_where` +and :meth:`matplotlib.collections.BrokenBarHCollection.span_where` """ import numpy as np import matplotlib.pyplot as plt @@ -18,26 +21,26 @@ ax.axhline(0, color='black', lw=2) collection = collections.PolyCollection.fill_between_where( - t, s1, s2, s1>=s2, color='green', alpha=0.5) + t, s1, s2, where=s1>=s2, color='green', alpha=0.5) ax.add_collection(collection) collection = collections.PolyCollection.fill_between_where( - t, s1, s2, s1<=s2, color='red', alpha=0.5) + t, s1, s2, where=s1<=s2, color='red', alpha=0.5) ax.add_collection(collection) fig = plt.figure() ax = fig.add_subplot(111) -ax.set_title('using span_masked') +ax.set_title('using span_where') ax.plot(t, s1, '-') ax.axhline(0, color='black', lw=2) -collection = collections.BrokenBarHCollection.span_masked( - t, s1>0, ymin=0, ymax=1, facecolor='green', alpha=0.5) +collection = collections.BrokenBarHCollection.span_where( + t, ymin=0, ymax=1, where=s1>0, facecolor='green', alpha=0.5) ax.add_collection(collection) -collection = collections.BrokenBarHCollection.span_masked( - t, s1<0, ymin=-1, ymax=0, facecolor='red', alpha=0.5) +collection = collections.BrokenBarHCollection.span_where( + t, ymin=-1, ymax=0, where=s1<0, facecolor='red', alpha=0.5) ax.add_collection(collection) Modified: trunk/matplotlib/lib/matplotlib/collections.py =================================================================== --- trunk/matplotlib/lib/matplotlib/collections.py 2008-11-23 19:05:58 UTC (rev 6433) +++ trunk/matplotlib/lib/matplotlib/collections.py 2008-11-23 19:15:01 UTC (rev 6434) @@ -674,10 +674,10 @@ @staticmethod - def fill_between_where(x, y1, y2, mask, **kwargs): + def fill_between_where(x, y1, y2, where, **kwargs): """ Create a :class:`PolyCollection` filling the regions between *y* - and *yboundary7* where ``mask==True`` + and *yboundary7* where ``where==True`` *x* @@ -689,7 +689,7 @@ *y2* an N length scalar or np array of the x data - *mask* + *where* an N length numpy boolean array *kwargs* @@ -705,7 +705,7 @@ assert( (len(x)==len(y1)) and (len(x)==len(y2)) ) polys = [] - for ind0, ind1 in mlab.contiguous_regions(mask): + for ind0, ind1 in mlab.contiguous_regions(where): theseverts = [] xslice = x[ind0:ind1] y1slice = y1[ind0:ind1] @@ -756,17 +756,17 @@ @staticmethod - def span_masked(x, mask, ymin, ymax, **kwargs): + def span_where(x, ymin, ymax, where, **kwargs): """ Create a BrokenBarHCollection to plot horizontal bars from - over the regions in *x* where *mask* is True. The bars range + over the regions in *x* where *where* is True. The bars range on the y-axis from *ymin* to *ymax* A :class:`BrokenBarHCollection` is returned. **kwargs are passed on to the collection """ xranges = [] - for ind0, ind1 in mlab.contiguous_regions(mask): + for ind0, ind1 in mlab.contiguous_regions(where): xslice = x[ind0:ind1] if not len(xslice): continue This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-11-23 19:56:41
|
Revision: 6437 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6437&view=rev Author: jdh2358 Date: 2008-11-23 19:56:37 +0000 (Sun, 23 Nov 2008) Log Message: ----------- moved fill_between to axes/pyplot method Modified Paths: -------------- trunk/matplotlib/boilerplate.py trunk/matplotlib/doc/_templates/index.html trunk/matplotlib/examples/api/fill_where_demo.py trunk/matplotlib/examples/pylab_examples/fill_between.py trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/collections.py trunk/matplotlib/lib/matplotlib/pyplot.py Added Paths: ----------- trunk/matplotlib/examples/api/span_regions.py Modified: trunk/matplotlib/boilerplate.py =================================================================== --- trunk/matplotlib/boilerplate.py 2008-11-23 19:18:24 UTC (rev 6436) +++ trunk/matplotlib/boilerplate.py 2008-11-23 19:56:37 UTC (rev 6437) @@ -64,6 +64,7 @@ 'csd', 'errorbar', 'fill', + 'fill_between', 'hexbin', 'hist', 'hlines', Modified: trunk/matplotlib/doc/_templates/index.html =================================================================== --- trunk/matplotlib/doc/_templates/index.html 2008-11-23 19:18:24 UTC (rev 6436) +++ trunk/matplotlib/doc/_templates/index.html 2008-11-23 19:56:37 UTC (rev 6437) @@ -409,8 +409,21 @@ </td> </tr> + <tr> <th align="left"> + <a href="api/pyplot_api.html#matplotlib.pyplot.fill_between">fill_between</a> + + </th> + + <td align="left"> + make filled polygons between two curves + </td> + + </tr> + + <tr> + <th align="left"> <a href="api/pyplot_api.html#matplotlib.pyplot.findobj">findobj</a> </th> Modified: trunk/matplotlib/examples/api/fill_where_demo.py =================================================================== --- trunk/matplotlib/examples/api/fill_where_demo.py 2008-11-23 19:18:24 UTC (rev 6436) +++ trunk/matplotlib/examples/api/fill_where_demo.py 2008-11-23 19:56:37 UTC (rev 6437) @@ -17,7 +17,7 @@ fig = plt.figure() ax = fig.add_subplot(111) ax.set_title('using fill_between_where') -ax.plot(t, s1, t, s2) +ax.plot(t, s1, t, s2, color='black') ax.axhline(0, color='black', lw=2) collection = collections.PolyCollection.fill_between_where( @@ -32,7 +32,7 @@ fig = plt.figure() ax = fig.add_subplot(111) ax.set_title('using span_where') -ax.plot(t, s1, '-') +ax.plot(t, s1, , color='black') ax.axhline(0, color='black', lw=2) collection = collections.BrokenBarHCollection.span_where( Added: trunk/matplotlib/examples/api/span_regions.py =================================================================== --- trunk/matplotlib/examples/api/span_regions.py (rev 0) +++ trunk/matplotlib/examples/api/span_regions.py 2008-11-23 19:56:37 UTC (rev 6437) @@ -0,0 +1,38 @@ +""" +Illustrate some helper functions for shading regions where a logical +mask is True + +See :meth:`matplotlib.collections.BrokenBarHCollection.span_where` +""" +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.collections as collections + + +t = np.arange(0.0, 2, 0.01) +s1 = np.sin(2*np.pi*t) +s2 = 1.2*np.sin(4*np.pi*t) + + +fig = plt.figure() +ax = fig.add_subplot(111) +ax.set_title('using span_where') +ax.plot(t, s1, color='black') +ax.axhline(0, color='black', lw=2) + +collection = collections.BrokenBarHCollection.span_where( + t, ymin=0, ymax=1, where=s1>0, facecolor='green', alpha=0.5) +ax.add_collection(collection) + +collection = collections.BrokenBarHCollection.span_where( + t, ymin=-1, ymax=0, where=s1<0, facecolor='red', alpha=0.5) +ax.add_collection(collection) + + + +plt.show() + + + + + Modified: trunk/matplotlib/examples/pylab_examples/fill_between.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/fill_between.py 2008-11-23 19:18:24 UTC (rev 6436) +++ trunk/matplotlib/examples/pylab_examples/fill_between.py 2008-11-23 19:56:37 UTC (rev 6437) @@ -3,27 +3,31 @@ from pylab import figure, show import numpy as np -x = np.arange(0, 2, 0.01) +x = np.arange(0.0, 2, 0.01) y1 = np.sin(2*np.pi*x) -y2 = np.sin(4*np.pi*x) + 2 +y2 = 1.2*np.sin(4*np.pi*x) fig = figure() -ax = fig.add_subplot(311) -ax2 = fig.add_subplot(312) -ax3 = fig.add_subplot(313) +ax1 = fig.add_subplot(311) +ax2 = fig.add_subplot(312, sharex=ax1) +ax3 = fig.add_subplot(313, sharex=ax1) +ax1.fill_between(x, 0, y1) +ax1.set_ylabel('between y1 and 0') -xs, ys = mlab.poly_between(x, 0, y1) -ax.fill(xs, ys) -ax.set_ylabel('between y1 and 0') - -xs, ys = mlab.poly_between(x, y1, 1) -ax2.fill(xs, ys) +ax2.fill_between(x, y1, 1) ax2.set_ylabel('between y1 and 1') -xs, ys = mlab.poly_between(x, y1, y2) -ax3.fill(xs, ys) +ax3.fill_between(x, y1, y2) ax3.set_ylabel('between y1 and y2') ax3.set_xlabel('x') + +fig = figure() +ax = fig.add_subplot(111) +ax1.plot(x, y1, x, y2, color='black') +ax.fill_between(x, y1, y2, where=y2>y1, facecolor='green') +ax.fill_between(x, y1, y2, where=y2<=y1, facecolor='red') +ax.set_title('fill between where') + show() Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-11-23 19:18:24 UTC (rev 6436) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-11-23 19:56:37 UTC (rev 6437) @@ -1302,6 +1302,7 @@ if autolim: if collection._paths and len(collection._paths): self.update_datalim(collection.get_datalim(self.transData)) + collection._remove_method = lambda h: self.collections.remove(h) def add_line(self, line): @@ -5456,12 +5457,8 @@ supports are supported by the fill format string. If you would like to fill below a curve, eg. shade a region - between 0 and *y* along *x*, use - :func:`~matplotlib.pylab.poly_between`, eg.:: + between 0 and *y* along *x*, use :meth:`fill_between` - xs, ys = poly_between(x, 0, y) - axes.fill(xs, ys, facecolor='red', alpha=0.5) - The *closed* kwarg will close the polygon when *True* (default). kwargs control the Polygon properties: @@ -5472,9 +5469,6 @@ .. plot:: mpl_examples/pylab_examples/fill_demo.py - .. seealso:: - :file:`examples/pylab_examples/fill_between.py`: - For more examples. """ if not self._hold: self.cla() @@ -5486,6 +5480,92 @@ return patches fill.__doc__ = cbook.dedent(fill.__doc__) % martist.kwdocd + def fill_between(self, x, y1, y2=0, where=None, **kwargs): + """ + call signature:: + + fill_between(x, y1, y2=0, where=None, **kwargs) + + Create a :class:`~matplotlib.collectionsPolyCollection` + filling the regions between *y1* and *y2* where + ``where==True`` + + *x* + an N length np array of the x data + + *y1* + an N length scalar or np array of the x data + + *y2* + an N length scalar or np array of the x data + + *where* + if None, default to fill between everywhere. If not None, + it is a a N length numpy boolean array and the fill will + only happen over the regions where ``where==True`` + + *kwargs* + keyword args passed on to the :class:`PolyCollection` + + .. seealso:: + :file:`examples/pylab_examples/fill_between.py`: + For more examples. + + kwargs control the Polygon properties: + + %(PolyCollection)s + + """ + x = np.asarray(x) + if not cbook.iterable(y1): + y1 = np.ones_like(x)*y1 + + if not cbook.iterable(y2): + y2 = np.ones_like(x)*y2 + + if where is None: + where = np.ones(len(x), np.bool) + + y1 = np.asarray(y1) + y2 = np.asarray(y2) + where = np.asarray(where) + assert( (len(x)==len(y1)) and (len(x)==len(y2)) and len(x)==len(where)) + + polys = [] + for ind0, ind1 in mlab.contiguous_regions(where): + theseverts = [] + xslice = x[ind0:ind1] + y1slice = y1[ind0:ind1] + y2slice = y2[ind0:ind1] + + if not len(xslice): + continue + + N = len(xslice) + X = np.zeros((2*N+2, 2), np.float) + + # the purpose of the next two lines is for when y2 is a + # scalar like 0 and we want the fill to go all the way + # down to 0 even if none of the y1 sample points do + X[0] = xslice[0], y2slice[0] + X[N+1] = xslice[-1], y2slice[-1] + + X[1:N+1,0] = xslice + X[1:N+1,1] = y1slice + X[N+2:,0] = xslice[::-1] + X[N+2:,1] = y2slice[::-1] + + polys.append(X) + + collection = mcoll.PolyCollection(polys, **kwargs) + + self.update_datalim_numerix(x[where], y1[where]) + self.update_datalim_numerix(x[where], y2[where]) + self.add_collection(collection) + self.autoscale_view() + return collection + fill_between.__doc__ = cbook.dedent(fill_between.__doc__) % martist.kwdocd + #### plotting z(x,y): imshow, pcolor and relatives, contour def imshow(self, X, cmap=None, norm=None, aspect=None, Modified: trunk/matplotlib/lib/matplotlib/collections.py =================================================================== --- trunk/matplotlib/lib/matplotlib/collections.py 2008-11-23 19:18:24 UTC (rev 6436) +++ trunk/matplotlib/lib/matplotlib/collections.py 2008-11-23 19:56:37 UTC (rev 6437) @@ -673,66 +673,6 @@ return Collection.draw(self, renderer) - @staticmethod - def fill_between_where(x, y1, y2, where, **kwargs): - """ - Create a :class:`PolyCollection` filling the regions between *y* - and *yboundary7* where ``where==True`` - - - *x* - an N length np array of the x data - - *y1* - an N length scalar or np array of the x data - - *y2* - an N length scalar or np array of the x data - - *where* - an N length numpy boolean array - - *kwargs* - keyword args passed on to the :class:`PolyCollection` - - """ - if not cbook.iterable(y1): - y1 = np.ones_like(x)*y1 - - if not cbook.iterable(y2): - y2 = np.ones_like(x)*y2 - - assert( (len(x)==len(y1)) and (len(x)==len(y2)) ) - - polys = [] - for ind0, ind1 in mlab.contiguous_regions(where): - theseverts = [] - xslice = x[ind0:ind1] - y1slice = y1[ind0:ind1] - y2slice = y2[ind0:ind1] - - if not len(xslice): - continue - - N = len(xslice) - X = np.zeros((2*N+2, 2), np.float) - - # the purpose of the next two lines is for when y2 is a - # scalar like 0 and we want the fill to go all the way - # down to 0 even if none of the y1 sample points do - X[0] = xslice[0], y2slice[0] - X[N+1] = xslice[-1], y2slice[-1] - - X[1:N+1,0] = xslice - X[1:N+1,1] = y1slice - X[N+2:,0] = xslice[::-1] - X[N+2:,1] = y2slice[::-1] - - polys.append(X) - - collection = PolyCollection(polys, **kwargs) - return collection - class BrokenBarHCollection(PolyCollection): """ A collection of horizontal bars spanning *yrange* with a sequence of Modified: trunk/matplotlib/lib/matplotlib/pyplot.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pyplot.py 2008-11-23 19:18:24 UTC (rev 6436) +++ trunk/matplotlib/lib/matplotlib/pyplot.py 2008-11-23 19:56:37 UTC (rev 6437) @@ -1120,61 +1120,62 @@ """ Plotting commands - ========= ================================================= - Command Description - ========= ================================================= - axes Create a new axes - axis Set or return the current axis limits - bar make a bar chart - boxplot make a box and whiskers chart - cla clear current axes - clabel label a contour plot - clf clear a figure window - close close a figure window - colorbar add a colorbar to the current figure - cohere make a plot of coherence - contour make a contour plot - contourf make a filled contour plot - csd make a plot of cross spectral density - draw force a redraw of the current figure - errorbar make an errorbar graph - figlegend add a legend to the figure - figimage add an image to the figure, w/o resampling - figtext add text in figure coords - figure create or change active figure - fill make filled polygons - gca return the current axes - gcf return the current figure - gci get the current image, or None - getp get a handle graphics property - hist make a histogram - hold set the hold state on current axes - legend add a legend to the axes - loglog a log log plot - imread load image file into array - imshow plot image data - matshow display a matrix in a new figure preserving aspect - pcolor make a pseudocolor plot - plot make a line plot - plotfile plot data from a flat file - psd make a plot of power spectral density - quiver make a direction field (arrows) plot - rc control the default params - savefig save the current figure - scatter make a scatter plot - setp set a handle graphics property - semilogx log x axis - semilogy log y axis - show show the figures - specgram a spectrogram plot - stem make a stem plot - subplot make a subplot (numrows, numcols, axesnum) - table add a table to the axes - text add some text at location x,y to the current axes - title add a title to the current axes - xlabel add an xlabel to the current axes - ylabel add a ylabel to the current axes - ========= ================================================= + ========= ================================================= + Command Description + ========= ================================================= + axes Create a new axes + axis Set or return the current axis limits + bar make a bar chart + boxplot make a box and whiskers chart + cla clear current axes + clabel label a contour plot + clf clear a figure window + close close a figure window + colorbar add a colorbar to the current figure + cohere make a plot of coherence + contour make a contour plot + contourf make a filled contour plot + csd make a plot of cross spectral density + draw force a redraw of the current figure + errorbar make an errorbar graph + figlegend add a legend to the figure + figimage add an image to the figure, w/o resampling + figtext add text in figure coords + figure create or change active figure + fill make filled polygons + fill_between make filled polygons + gca return the current axes + gcf return the current figure + gci get the current image, or None + getp get a handle graphics property + hist make a histogram + hold set the hold state on current axes + legend add a legend to the axes + loglog a log log plot + imread load image file into array + imshow plot image data + matshow display a matrix in a new figure preserving aspect + pcolor make a pseudocolor plot + plot make a line plot + plotfile plot data from a flat file + psd make a plot of power spectral density + quiver make a direction field (arrows) plot + rc control the default params + savefig save the current figure + scatter make a scatter plot + setp set a handle graphics property + semilogx log x axis + semilogy log y axis + show show the figures + specgram a spectrogram plot + stem make a stem plot + subplot make a subplot (numrows, numcols, axesnum) + table add a table to the axes + text add some text at location x,y to the current axes + title add a title to the current axes + xlabel add an xlabel to the current axes + ylabel add a ylabel to the current axes + ========= ================================================= The following commands will set the default colormap accordingly: @@ -1493,7 +1494,6 @@ ## Plotting part 2: autogenerated wrappers for axes methods ## -### Do not edit below this point # This function was autogenerated by boilerplate.py. Do not edit as # changes will be lost def acorr(*args, **kwargs): @@ -1870,6 +1870,50 @@ # This function was autogenerated by boilerplate.py. Do not edit as # changes will be lost +def fill_between(*args, **kwargs): + # allow callers to override the hold state by passing hold=True|False + b = ishold() + h = kwargs.pop('hold', None) + if h is not None: + hold(h) + try: + ret = gca().fill_between(*args, **kwargs) + draw_if_interactive() + except: + hold(b) + raise + + hold(b) + return ret +if Axes.fill_between.__doc__ is not None: + fill_between.__doc__ = dedent(Axes.fill_between.__doc__) + """ + +Additional kwargs: hold = [True|False] overrides default hold state""" + +# This function was autogenerated by boilerplate.py. Do not edit as +# changes will be lost +def hexbin(*args, **kwargs): + # allow callers to override the hold state by passing hold=True|False + b = ishold() + h = kwargs.pop('hold', None) + if h is not None: + hold(h) + try: + ret = gca().hexbin(*args, **kwargs) + draw_if_interactive() + except: + hold(b) + raise + gci._current = ret + hold(b) + return ret +if Axes.hexbin.__doc__ is not None: + hexbin.__doc__ = dedent(Axes.hexbin.__doc__) + """ + +Additional kwargs: hold = [True|False] overrides default hold state""" + +# This function was autogenerated by boilerplate.py. Do not edit as +# changes will be lost def hist(*args, **kwargs): # allow callers to override the hold state by passing hold=True|False b = ishold() @@ -2156,28 +2200,6 @@ # This function was autogenerated by boilerplate.py. Do not edit as # changes will be lost -def hexbin(*args, **kwargs): - # allow callers to override the hold state by passing hold=True|False - b = ishold() - h = kwargs.pop('hold', None) - if h is not None: - hold(h) - try: - ret = gca().hexbin(*args, **kwargs) - draw_if_interactive() - except: - hold(b) - raise - gci._current = ret - hold(b) - return ret -if Axes.hexbin.__doc__ is not None: - hexbin.__doc__ = dedent(Axes.hexbin.__doc__) + """ - -Additional kwargs: hold = [True|False] overrides default hold state""" - -# This function was autogenerated by boilerplate.py. Do not edit as -# changes will be lost def semilogx(*args, **kwargs): # allow callers to override the hold state by passing hold=True|False b = ishold() @@ -2438,10 +2460,8 @@ # changes will be lost def autumn(): ''' - Set the default colormap to *autumn* and apply to current image if any. - - .. seealso:: - :func:`colormaps` + set the default colormap to autumn and apply to current image if any. + See help(colormaps) for more information ''' rc('image', cmap='autumn') im = gci() @@ -2455,10 +2475,8 @@ # changes will be lost def bone(): ''' - Set the default colormap to bone and apply to current image if any. - - .. seealso:: - :func:`colormaps` + set the default colormap to bone and apply to current image if any. + See help(colormaps) for more information ''' rc('image', cmap='bone') im = gci() @@ -2472,10 +2490,8 @@ # changes will be lost def cool(): ''' - Set the default colormap to cool and apply to current image if any. - - .. seealso:: - :func:`colormaps` + set the default colormap to cool and apply to current image if any. + See help(colormaps) for more information ''' rc('image', cmap='cool') im = gci() @@ -2489,10 +2505,8 @@ # changes will be lost def copper(): ''' - Set the default colormap to copper and apply to current image if any. - - .. seealso:: - :func:`colormaps` + set the default colormap to copper and apply to current image if any. + See help(colormaps) for more information ''' rc('image', cmap='copper') im = gci() @@ -2506,10 +2520,8 @@ # changes will be lost def flag(): ''' - Set the default colormap to flag and apply to current image if any. - - .. seealso:: - :func:`colormaps` + set the default colormap to flag and apply to current image if any. + See help(colormaps) for more information ''' rc('image', cmap='flag') im = gci() @@ -2523,10 +2535,8 @@ # changes will be lost def gray(): ''' - Set the default colormap to gray and apply to current image if any. - - .. seealso:: - :func:`colormaps` + set the default colormap to gray and apply to current image if any. + See help(colormaps) for more information ''' rc('image', cmap='gray') im = gci() @@ -2540,10 +2550,8 @@ # changes will be lost def hot(): ''' - Set the default colormap to hot and apply to current image if any. - - .. seealso:: - :func:`colormaps` + set the default colormap to hot and apply to current image if any. + See help(colormaps) for more information ''' rc('image', cmap='hot') im = gci() @@ -2557,10 +2565,8 @@ # changes will be lost def hsv(): ''' - Set the default colormap to hsv and apply to current image if any. - - .. seealso:: - :func:`colormaps` + set the default colormap to hsv and apply to current image if any. + See help(colormaps) for more information ''' rc('image', cmap='hsv') im = gci() @@ -2574,10 +2580,8 @@ # changes will be lost def jet(): ''' - Set the default colormap to jet and apply to current image if any. - - .. seealso:: - :func:`colormaps` + set the default colormap to jet and apply to current image if any. + See help(colormaps) for more information ''' rc('image', cmap='jet') im = gci() @@ -2591,10 +2595,8 @@ # changes will be lost def pink(): ''' - Set the default colormap to pink and apply to current image if any. - - .. seealso:: - :func:`colormaps` + set the default colormap to pink and apply to current image if any. + See help(colormaps) for more information ''' rc('image', cmap='pink') im = gci() @@ -2608,10 +2610,8 @@ # changes will be lost def prism(): ''' - Set the default colormap to prism and apply to current image if any. - - .. seealso:: - :func:`colormaps` + set the default colormap to prism and apply to current image if any. + See help(colormaps) for more information ''' rc('image', cmap='prism') im = gci() @@ -2625,10 +2625,8 @@ # changes will be lost def spring(): ''' - Set the default colormap to spring and apply to current image if any. - - .. seealso:: - :func:`colormaps` + set the default colormap to spring and apply to current image if any. + See help(colormaps) for more information ''' rc('image', cmap='spring') im = gci() @@ -2642,10 +2640,8 @@ # changes will be lost def summer(): ''' - Set the default colormap to summer and apply to current image if any. - - .. seealso:: - :func:`colormaps` + set the default colormap to summer and apply to current image if any. + See help(colormaps) for more information ''' rc('image', cmap='summer') im = gci() @@ -2659,10 +2655,8 @@ # changes will be lost def winter(): ''' - Set the default colormap to winter and apply to current image if any. - - .. seealso:: - :func:`colormaps` + set the default colormap to winter and apply to current image if any. + See help(colormaps) for more information ''' rc('image', cmap='winter') im = gci() @@ -2676,10 +2670,8 @@ # changes will be lost def spectral(): ''' - Set the default colormap to spectral and apply to current image if any. - - .. seealso:: - :func:`colormaps` + set the default colormap to spectral and apply to current image if any. + See help(colormaps) for more information ''' rc('image', cmap='spectral') im = gci() @@ -2687,3 +2679,5 @@ if im is not None: im.set_cmap(cm.spectral) draw_if_interactive() + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2008-11-24 20:12:59
|
Revision: 6442 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6442&view=rev Author: mdboom Date: 2008-11-24 20:12:55 +0000 (Mon, 24 Nov 2008) Log Message: ----------- [ 2314869 ] Log base-2 axes fail with certain axis limits Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/ticker.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-11-24 03:53:14 UTC (rev 6441) +++ trunk/matplotlib/CHANGELOG 2008-11-24 20:12:55 UTC (rev 6442) @@ -1,3 +1,5 @@ +2008-11-24 Fix crash in log ticking. - MGD + 2008-11-20 Added some static helper methods BrokenHBarCollection.span_masked and PolyCollection.fill_between_where for visualizing logical Modified: trunk/matplotlib/lib/matplotlib/ticker.py =================================================================== --- trunk/matplotlib/lib/matplotlib/ticker.py 2008-11-24 03:53:14 UTC (rev 6441) +++ trunk/matplotlib/lib/matplotlib/ticker.py 2008-11-24 20:12:55 UTC (rev 6442) @@ -1037,7 +1037,7 @@ decades = np.arange(math.floor(vmin), math.ceil(vmax)+stride, stride) - if len(subs) > 1 or subs[0] != 1.0: + if len(subs) > 1 or (len(subs == 1) and subs[0] != 1.0): ticklocs = [] for decadeStart in b**decades: ticklocs.extend( subs*decadeStart ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-11-25 04:04:05
|
Revision: 6445 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6445&view=rev Author: jdh2358 Date: 2008-11-25 04:03:59 +0000 (Tue, 25 Nov 2008) Log Message: ----------- point to the right url for the rc file Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/_templates/gallery.html trunk/matplotlib/doc/_templates/indexsidebar.html trunk/matplotlib/doc/make.py trunk/matplotlib/doc/users/customizing.rst trunk/matplotlib/lib/matplotlib/__init__.py trunk/matplotlib/matplotlibrc.template Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-11-24 20:18:38 UTC (rev 6444) +++ trunk/matplotlib/CHANGELOG 2008-11-25 04:03:59 UTC (rev 6445) @@ -1,9 +1,8 @@ 2008-11-24 Fix crash in log ticking. - MGD -2008-11-20 Added some static helper methods - BrokenHBarCollection.span_masked and - PolyCollection.fill_between_where for visualizing logical - regions. See examples/api/fill_where_demo.py - JDH +2008-11-20 Added static helper method BrokenHBarCollection.span_where + and Axes/pyplot method fill_between. See + examples/pylab/fill_between.py - JDH 2008-11-12 Add x_isdata and y_isdata attributes to Artist instances, and use them to determine whether either or both Modified: trunk/matplotlib/doc/_templates/gallery.html =================================================================== --- trunk/matplotlib/doc/_templates/gallery.html 2008-11-24 20:18:38 UTC (rev 6444) +++ trunk/matplotlib/doc/_templates/gallery.html 2008-11-25 04:03:59 UTC (rev 6445) @@ -49,6 +49,8 @@ <a href="examples/api/scatter_piecharts.html"><img src="_static/plot_directive/mpl_examples/api/thumbnails/scatter_piecharts.png" border="0" alt="scatter_piecharts"/></a> +<a href="examples/api/span_regions.html"><img src="_static/plot_directive/mpl_examples/api/thumbnails/span_regions.png" border="0" alt="span_regions"/></a> + <a href="examples/api/two_scales.html"><img src="_static/plot_directive/mpl_examples/api/thumbnails/two_scales.png" border="0" alt="two_scales"/></a> <a href="examples/api/watermark_image.html"><img src="_static/plot_directive/mpl_examples/api/thumbnails/watermark_image.png" border="0" alt="watermark_image"/></a> @@ -157,6 +159,8 @@ <a href="examples/pylab_examples/csd_demo.html"><img src="_static/plot_directive/mpl_examples/pylab_examples/thumbnails/csd_demo.png" border="0" alt="csd_demo"/></a> +<a href="examples/pylab_examples/custom_cmap.html"><img src="_static/plot_directive/mpl_examples/pylab_examples/thumbnails/custom_cmap.png" border="0" alt="custom_cmap"/></a> + <a href="examples/pylab_examples/custom_figure_class.html"><img src="_static/plot_directive/mpl_examples/pylab_examples/thumbnails/custom_figure_class.png" border="0" alt="custom_figure_class"/></a> <a href="examples/pylab_examples/custom_ticker1.html"><img src="_static/plot_directive/mpl_examples/pylab_examples/thumbnails/custom_ticker1.png" border="0" alt="custom_ticker1"/></a> @@ -223,9 +227,9 @@ <a href="examples/pylab_examples/figure_title.html"><img src="_static/plot_directive/mpl_examples/pylab_examples/thumbnails/figure_title.png" border="0" alt="figure_title"/></a> -<a href="examples/pylab_examples/fill_between.html"><img src="_static/plot_directive/mpl_examples/pylab_examples/thumbnails/fill_between.png" border="0" alt="fill_between"/></a> +<a href="examples/pylab_examples/fill_between.html"><img src="_static/plot_directive/mpl_examples/pylab_examples/thumbnails/fill_between_00.png" border="0" alt="fill_between"/></a> -<a href="examples/pylab_examples/fill_between_posneg.html"><img src="_static/plot_directive/mpl_examples/pylab_examples/thumbnails/fill_between_posneg.png" border="0" alt="fill_between_posneg"/></a> +<a href="examples/pylab_examples/fill_between.html"><img src="_static/plot_directive/mpl_examples/pylab_examples/thumbnails/fill_between_01.png" border="0" alt="fill_between"/></a> <a href="examples/pylab_examples/fill_demo.html"><img src="_static/plot_directive/mpl_examples/pylab_examples/thumbnails/fill_demo.png" border="0" alt="fill_demo"/></a> @@ -419,6 +423,8 @@ <a href="examples/pylab_examples/psd_demo.html"><img src="_static/plot_directive/mpl_examples/pylab_examples/thumbnails/psd_demo.png" border="0" alt="psd_demo"/></a> +<a href="examples/pylab_examples/psd_demo2.html"><img src="_static/plot_directive/mpl_examples/pylab_examples/thumbnails/psd_demo2.png" border="0" alt="psd_demo2"/></a> + <a href="examples/pylab_examples/pythonic_matplotlib.html"><img src="_static/plot_directive/mpl_examples/pylab_examples/thumbnails/pythonic_matplotlib.png" border="0" alt="pythonic_matplotlib"/></a> <a href="examples/pylab_examples/quadmesh_demo.html"><img src="_static/plot_directive/mpl_examples/pylab_examples/thumbnails/quadmesh_demo.png" border="0" alt="quadmesh_demo"/></a> Modified: trunk/matplotlib/doc/_templates/indexsidebar.html =================================================================== --- trunk/matplotlib/doc/_templates/indexsidebar.html 2008-11-24 20:18:38 UTC (rev 6444) +++ trunk/matplotlib/doc/_templates/indexsidebar.html 2008-11-25 04:03:59 UTC (rev 6445) @@ -33,7 +33,7 @@ <p>For details on what's new, see the detailed <a href="{{ pathto('_static/CHANGELOG', 1) }}">changelog</a>. Anything that could -required changes to your existing codes is logged in the <a href="{{ +require changes to your existing codes is logged in the <a href="{{ pathto('api/api_changes.html', 1) }}">api changes</a> file.</p> <h3>Other stuff</h3> Modified: trunk/matplotlib/doc/make.py =================================================================== --- trunk/matplotlib/doc/make.py 2008-11-24 20:18:38 UTC (rev 6444) +++ trunk/matplotlib/doc/make.py 2008-11-25 04:03:59 UTC (rev 6445) @@ -17,9 +17,6 @@ def sf(): 'push a copy to the sf site' shutil.copy('../CHANGELOG', 'build/html/_static/CHANGELOG') - shutil.copy('../API_CHANGES', 'build/html/_static/API_CHANGES') - shutil.copy('../MIGRATION.txt', 'build/html/_static/MIGRATION.txt') - os.system('cd build/html; rsync -avz . jdh2358,mat...@we...:/home/groups/m/ma/matplotlib/htdocs/ -essh --cvs-exclude') def sfpdf(): @@ -44,6 +41,7 @@ check_build() if not os.path.exists('examples/index.rst'): examples() + shutil.copy('mpl_data/matplotlibrc', '_static/matplotlibrc') #figs() if os.system('sphinx-build -b html -d build/doctrees . build/html'): raise SystemExit("Building HTML failed.") Modified: trunk/matplotlib/doc/users/customizing.rst =================================================================== --- trunk/matplotlib/doc/users/customizing.rst 2008-11-24 20:18:38 UTC (rev 6444) +++ trunk/matplotlib/doc/users/customizing.rst 2008-11-25 04:03:59 UTC (rev 6445) @@ -61,6 +61,10 @@ .. _matplotlibrc-sample: A sample matplotlibrc file --------------------------- +-------------------------------------------------------------------- +.. htmlonly:: + + `(download) <../_static/matplotlibrc>`__ + .. literalinclude:: ../mpl_data/matplotlibrc Modified: trunk/matplotlib/lib/matplotlib/__init__.py =================================================================== --- trunk/matplotlib/lib/matplotlib/__init__.py 2008-11-24 20:18:38 UTC (rev 6444) +++ trunk/matplotlib/lib/matplotlib/__init__.py 2008-11-25 04:03:59 UTC (rev 6445) @@ -666,7 +666,7 @@ Bad key "%s" on line %d in %s. You probably need to get an updated matplotlibrc file from -http://matplotlib.sf.net/matplotlibrc or from the matplotlib source +http://matplotlib.sf.net/_static/matplotlibrc or from the matplotlib source distribution""" % (key, cnt, fname) if ret['datapath'] is None: Modified: trunk/matplotlib/matplotlibrc.template =================================================================== --- trunk/matplotlib/matplotlibrc.template 2008-11-24 20:18:38 UTC (rev 6444) +++ trunk/matplotlib/matplotlibrc.template 2008-11-25 04:03:59 UTC (rev 6445) @@ -10,13 +10,16 @@ # (win32 systems). # # This file is best viewed in a editor which supports python mode -# syntax highlighting # Blank lines, or lines starting with a comment +# syntax highlighting. Blank lines, or lines starting with a comment # symbol, are ignored, as are trailing comments. Other lines must -# have the format # key : val # optional comment # Colors: for the -# color values below, you can either use - a matplotlib color string, -# such as r, k, or b - an rgb tuple, such as (1.0, 0.5, 0.0) - a hex -# string, such as ff00ff or #ff00ff - a scalar grayscale intensity -# such as 0.75 - a legal html color name, eg red, blue, darkslategray +# have the format +# key : val # optional comment +# +# Colors: for the color values below, you can either use - a +# matplotlib color string, such as r, k, or b - an rgb tuple, such as +# (1.0, 0.5, 0.0) - a hex string, such as ff00ff or #ff00ff - a scalar +# grayscale intensity such as 0.75 - a legal html color name, eg red, +# blue, darkslategray #### CONFIGURATION BEGINS HERE This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2008-11-25 18:57:02
|
Revision: 6448 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6448&view=rev Author: leejjoon Date: 2008-11-25 18:56:57 +0000 (Tue, 25 Nov 2008) Log Message: ----------- scatterpoints support in Legend. patch by Erik Tollerud Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/legend.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-11-25 18:28:13 UTC (rev 6447) +++ trunk/matplotlib/CHANGELOG 2008-11-25 18:56:57 UTC (rev 6448) @@ -1,3 +1,6 @@ +2008-11-25 Added scatterpoints support in Legend. patch by Erik + Tollerud - JJL + 2008-11-24 Fix crash in log ticking. - MGD 2008-11-20 Added static helper method BrokenHBarCollection.span_where Modified: trunk/matplotlib/lib/matplotlib/legend.py =================================================================== --- trunk/matplotlib/lib/matplotlib/legend.py 2008-11-25 18:28:13 UTC (rev 6447) +++ trunk/matplotlib/lib/matplotlib/legend.py 2008-11-25 18:56:57 UTC (rev 6448) @@ -83,6 +83,7 @@ def __init__(self, parent, handles, labels, loc = None, numpoints = None, # the number of points in the legend line + scatterpoints = 3, # TODO: may be an rcParam prop = None, pad = None, # the fractional whitespace inside the legend border borderpad = None, @@ -101,6 +102,7 @@ labels # a list of strings to label the legend loc # a location code numpoints = 4 # the number of points in the legend line + scatterpoints = 3 # the number of points for the scatterplot legend prop = FontProperties(size='smaller') # the font property pad = 0.2 # the fractional whitespace inside the legend border markerscale = 0.6 # the relative size of legend markers vs. original @@ -118,10 +120,10 @@ Artist.__init__(self) - proplist=[numpoints, pad, borderpad, markerscale, labelsep, + proplist=[numpoints, scatterpoints, pad, borderpad, markerscale, labelsep, handlelen, handletextsep, axespad, shadow] - propnames=['numpoints', 'pad', 'borderpad', 'markerscale', 'labelsep', - 'handlelen', 'handletextsep', 'axespad', 'shadow'] + propnames=['numpoints','scatterpoints', 'pad', 'borderpad', 'markerscale', + 'labelsep', 'handlelen', 'handletextsep', 'axespad', 'shadow'] for name, value in safezip(propnames,proplist): if value is None: value=rcParams["legend."+name] @@ -130,7 +132,9 @@ warnings.warn("Use 'borderpad' instead of 'pad'.", DeprecationWarning) # 2008/10/04 if self.numpoints <= 0: - raise ValueError("numpoints must be >= 0; it was %d"% numpoints) + raise ValueError("numpoints must be > 0; it was %d"% numpoints) + if self.scatterpoints <= 0: + raise ValueError("scatterpoints must be > 0; it was %d"% numpoints) if prop is None: self.prop=FontProperties(size=rcParams["legend.fontsize"]) else: @@ -142,8 +146,8 @@ self._scatteryoffsets = np.array([4./8., 5./8., 3./8.]) else: self._scatteryoffsets = np.asarray(scatteryoffsets) - reps = int(self.numpoints / len(self._scatteryoffsets)) + 1 - self._scatteryoffsets = np.tile(self._scatteryoffsets, reps)[:self.numpoints] + reps = int(self.scatterpoints / len(self._scatteryoffsets)) + 1 + self._scatteryoffsets = np.tile(self._scatteryoffsets, reps)[:self.scatterpoints] if isinstance(parent,Axes): self.isaxes = True @@ -261,10 +265,14 @@ # centered marker proxy for handle, label in safezip(handles, texts): - if self.numpoints > 1: - xdata = np.linspace(left, left + self.handlelen, self.numpoints) + if isinstance(handle, RegularPolyCollection): + npoints = self.scatterpoints + else: + npoints = self.numpoints + if npoints > 1: + xdata = np.linspace(left, left + self.handlelen, npoints) xdata_marker = xdata - elif self.numpoints == 1: + elif npoints == 1: xdata = np.linspace(left, left + self.handlelen, 2) xdata_marker = [left + 0.5*self.handlelen] @@ -326,8 +334,11 @@ # we may need to scale these sizes by "markerscale" # attribute. But other handle types does not seem # to care about this attribute and it is currently ignored. - sizes = [.5*(size_max+size_min), size_max, - size_min] + if self.scatterpoints < 4: + sizes = [.5*(size_max+size_min), size_max, + size_min] + else: + sizes = size_max*np.linspace(0,1,self.scatterpoints)+size_min p = type(handle)(handle.get_numsides(), rotation=handle.get_rotation(), This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-11-25 22:22:52
|
Revision: 6453 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6453&view=rev Author: jdh2358 Date: 2008-11-25 21:43:36 +0000 (Tue, 25 Nov 2008) Log Message: ----------- added rc param axes.unicode_minus Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/projections/polar.py trunk/matplotlib/lib/matplotlib/rcsetup.py trunk/matplotlib/lib/matplotlib/ticker.py trunk/matplotlib/matplotlibrc.template Added Paths: ----------- trunk/matplotlib/examples/api/unicode_minus.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-11-25 21:14:13 UTC (rev 6452) +++ trunk/matplotlib/CHANGELOG 2008-11-25 21:43:36 UTC (rev 6453) @@ -1,3 +1,6 @@ +2008-11-25 Added rcParam axes.unicode_minus which allows plain hypen + for minus when False - JDH + 2008-11-25 Added scatterpoints support in Legend. patch by Erik Tollerud - JJL Added: trunk/matplotlib/examples/api/unicode_minus.py =================================================================== --- trunk/matplotlib/examples/api/unicode_minus.py (rev 0) +++ trunk/matplotlib/examples/api/unicode_minus.py 2008-11-25 21:43:36 UTC (rev 6453) @@ -0,0 +1,18 @@ +""" +You can use the proper typesetting unicode minus (see +http://en.wikipedia.org/wiki/Plus_sign#Plus_sign) or the ASCII hypen +for minus, which some people prefer. The matplotlibrc param +axes.unicode_minus controls the default behavior. + +The default is to use the unicode minus +""" +import numpy as np +import matplotlib +import matplotlib.pyplot as plt + +matplotlib.rcParams['axes.unicode_minus'] = False +fig = plt.figure() +ax = fig.add_subplot(111) +ax.plot(10*np.random.randn(100), 10*np.random.randn(100), 'o') +ax.set_title('Using hypen instead of unicode minus') +plt.show() Modified: trunk/matplotlib/lib/matplotlib/projections/polar.py =================================================================== --- trunk/matplotlib/lib/matplotlib/projections/polar.py 2008-11-25 21:14:13 UTC (rev 6452) +++ trunk/matplotlib/lib/matplotlib/projections/polar.py 2008-11-25 21:43:36 UTC (rev 6453) @@ -139,6 +139,11 @@ if rcParams['text.usetex'] and not rcParams['text.latex.unicode']: return r"$%d^\circ$" % ((x / npy.pi) * 180.0) else: + # we use unicode, rather than mathtext with \circ, so + # that it will work correctly with any arbitrary font + # (assuming it has a degree sign), whereas $5\circ$ + # will only work correctly with one of the supported + # math fonts (Computer Modern and STIX) return u"%d\u00b0" % ((x / npy.pi) * 180.0) class RadialLocator(Locator): Modified: trunk/matplotlib/lib/matplotlib/rcsetup.py =================================================================== --- trunk/matplotlib/lib/matplotlib/rcsetup.py 2008-11-25 21:14:13 UTC (rev 6452) +++ trunk/matplotlib/lib/matplotlib/rcsetup.py 2008-11-25 21:43:36 UTC (rev 6453) @@ -412,6 +412,7 @@ # use scientific notation if log10 # of the axis range is smaller than the # first or larger than the second + 'axes.unicode_minus' : [True, validate_bool], 'polaraxes.grid' : [True, validate_bool], # display polar grid or not Modified: trunk/matplotlib/lib/matplotlib/ticker.py =================================================================== --- trunk/matplotlib/lib/matplotlib/ticker.py 2008-11-25 21:14:13 UTC (rev 6452) +++ trunk/matplotlib/lib/matplotlib/ticker.py 2008-11-25 21:43:36 UTC (rev 6453) @@ -313,7 +313,7 @@ def fix_minus(self, s): 'use a unicode minus rather than hyphen' - if rcParams['text.usetex']: return s + if rcParams['text.usetex'] or not rcParams['axes.unicode_minus']: return s else: return s.replace('-', u'\u2212') def __call__(self, x, pos=None): Modified: trunk/matplotlib/matplotlibrc.template =================================================================== --- trunk/matplotlib/matplotlibrc.template 2008-11-25 21:14:13 UTC (rev 6452) +++ trunk/matplotlib/matplotlibrc.template 2008-11-25 21:43:36 UTC (rev 6453) @@ -205,6 +205,8 @@ #axes.formatter.limits : -7, 7 # use scientific notation if log10 # of the axis range is smaller than the # first or larger than the second +#axes.unicode_minus : True # use unicode for the minus symbol + # rather than hypen. See http://en.wikipedia.org/wiki/Plus_sign#Plus_sign #polaraxes.grid : True # display grid on polar axes This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-11-26 17:43:12
|
Revision: 6454 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6454&view=rev Author: jdh2358 Date: 2008-11-26 17:43:09 +0000 (Wed, 26 Nov 2008) Log Message: ----------- added figure/axes enter/leave events Modified Paths: -------------- trunk/matplotlib/doc/users/event_handling.rst trunk/matplotlib/lib/matplotlib/backend_bases.py Added Paths: ----------- trunk/matplotlib/examples/event_handling/figure_axes_enter_leave.py Modified: trunk/matplotlib/doc/users/event_handling.rst =================================================================== --- trunk/matplotlib/doc/users/event_handling.rst 2008-11-25 21:43:36 UTC (rev 6453) +++ trunk/matplotlib/doc/users/event_handling.rst 2008-11-26 17:43:09 UTC (rev 6454) @@ -53,15 +53,19 @@ ======================= ====================================================================================== Event name Class and description ======================= ====================================================================================== -'button_press_event' :class:`~matplotlib.backend_bases.MouseEvent` - mouse button is pressed -'button_release_event' :class:`~matplotlib.backend_bases.MouseEvent` - mouse button is released -'draw_event' :class:`~matplotlib.backend_bases.DrawEvent` - canvas draw -'key_press_event' :class:`~matplotlib.backend_bases.KeyEvent` - key is pressed -'key_release_event' :class:`~matplotlib.backend_bases.KeyEvent` - key is released -'motion_notify_event' :class:`~matplotlib.backend_bases.MouseEvent` - mouse motion -'pick_event' :class:`~matplotlib.backend_bases.PickEvent` - an object in the canvas is selected -'resize_event' :class:`~matplotlib.backend_bases.ResizeEvent` - figure canvas is resized -'scroll_event' :class:`~matplotlib.backend_bases.MouseEvent` - mouse scroll wheel is rolled +'button_press_event' :class:`~matplotlib.backend_bases.MouseEvent` - mouse button is pressed +'button_release_event' :class:`~matplotlib.backend_bases.MouseEvent` - mouse button is released +'draw_event' :class:`~matplotlib.backend_bases.DrawEvent` - canvas draw +'key_press_event' :class:`~matplotlib.backend_bases.KeyEvent` - key is pressed +'key_release_event' :class:`~matplotlib.backend_bases.KeyEvent` - key is released +'motion_notify_event' :class:`~matplotlib.backend_bases.MouseEvent` - mouse motion +'pick_event' :class:`~matplotlib.backend_bases.PickEvent` - an object in the canvas is selected +'resize_event' :class:`~matplotlib.backend_bases.ResizeEvent` - figure canvas is resized +'scroll_event' :class:`~matplotlib.backend_bases.MouseEvent` - mouse scroll wheel is rolled +'figure_enter_event' :class:`~matplotlib.backend_bases.LocationEvent` - mouse enters a new figure +'figure_leave_event' :class:`~matplotlib.backend_bases.LocationEvent` - mouse leaves a figure +'axes_enter_event' :class:`~matplotlib.backend_bases.LocationEvent` - mouse enters a new axes +'axes_leave_event' :class:`~matplotlib.backend_bases.LocationEvent` - mouse leaves an axes ======================= ====================================================================================== .. _event-attributes: @@ -330,6 +334,66 @@ plt.show() +.. _enter-leave-events: + +Mouse enter and leave +====================== + +If you want to be notified when the mouse enters or leaves a figure or +axes, you can connect to the figure/axes enter/leave events. Here is +a simple example that changes the colors of the axes and figure +background that the mouse is over:: + + """ + Illustrate the figure and axes enter and leave events by changing the + frame colors on enter and leave + """ + import matplotlib.pyplot as plt + + def enter_axes(event): + print 'enter_axes', event.inaxes + event.inaxes.patch.set_facecolor('yellow') + event.canvas.draw() + + def leave_axes(event): + print 'leave_axes', event.inaxes + event.inaxes.patch.set_facecolor('white') + event.canvas.draw() + + def enter_figure(event): + print 'enter_figure', event.canvas.figure + event.canvas.figure.patch.set_facecolor('red') + event.canvas.draw() + + def leave_figure(event): + print 'leave_figure', event.canvas.figure + event.canvas.figure.patch.set_facecolor('grey') + event.canvas.draw() + + fig1 = plt.figure() + fig1.suptitle('mouse hover over figure or axes to trigger events') + ax1 = fig1.add_subplot(211) + ax2 = fig1.add_subplot(212) + + fig1.canvas.mpl_connect('figure_enter_event', enter_figure) + fig1.canvas.mpl_connect('figure_leave_event', leave_figure) + fig1.canvas.mpl_connect('axes_enter_event', enter_axes) + fig1.canvas.mpl_connect('axes_leave_event', leave_axes) + + fig2 = plt.figure() + fig2.suptitle('mouse hover over figure or axes to trigger events') + ax1 = fig2.add_subplot(211) + ax2 = fig2.add_subplot(212) + + fig2.canvas.mpl_connect('figure_enter_event', enter_figure) + fig2.canvas.mpl_connect('figure_leave_event', leave_figure) + fig2.canvas.mpl_connect('axes_enter_event', enter_axes) + fig2.canvas.mpl_connect('axes_leave_event', leave_axes) + + plt.show() + + + .. _object-picking: Object picking Added: trunk/matplotlib/examples/event_handling/figure_axes_enter_leave.py =================================================================== --- trunk/matplotlib/examples/event_handling/figure_axes_enter_leave.py (rev 0) +++ trunk/matplotlib/examples/event_handling/figure_axes_enter_leave.py 2008-11-26 17:43:09 UTC (rev 6454) @@ -0,0 +1,49 @@ +""" +Illustrate the figure and axes enter and leave events by changing the +frame colors on enter and leave +""" +import matplotlib.pyplot as plt + +def enter_axes(event): + print 'enter_axes', event.inaxes + event.inaxes.patch.set_facecolor('yellow') + event.canvas.draw() + +def leave_axes(event): + print 'leave_axes', event.inaxes + event.inaxes.patch.set_facecolor('white') + event.canvas.draw() + +def enter_figure(event): + print 'enter_figure', event.canvas.figure + event.canvas.figure.patch.set_facecolor('red') + event.canvas.draw() + +def leave_figure(event): + print 'leave_figure', event.canvas.figure + event.canvas.figure.patch.set_facecolor('grey') + event.canvas.draw() + +fig1 = plt.figure() +fig1.suptitle('mouse hover over figure or axes to trigger events') +ax1 = fig1.add_subplot(211) +ax2 = fig1.add_subplot(212) + +fig1.canvas.mpl_connect('figure_enter_event', enter_figure) +fig1.canvas.mpl_connect('figure_leave_event', leave_figure) +fig1.canvas.mpl_connect('axes_enter_event', enter_axes) +fig1.canvas.mpl_connect('axes_leave_event', leave_axes) + +fig2 = plt.figure() +fig2.suptitle('mouse hover over figure or axes to trigger events') +ax1 = fig2.add_subplot(211) +ax2 = fig2.add_subplot(212) + +fig2.canvas.mpl_connect('figure_enter_event', enter_figure) +fig2.canvas.mpl_connect('figure_leave_event', leave_figure) +fig2.canvas.mpl_connect('axes_enter_event', enter_axes) +fig2.canvas.mpl_connect('axes_leave_event', leave_axes) + +plt.show() + + Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-11-25 21:43:36 UTC (rev 6453) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-11-26 17:43:09 UTC (rev 6454) @@ -743,6 +743,9 @@ xdata = None # x coord of mouse in data coords ydata = None # y coord of mouse in data coords + # the last event that was triggered before this one + _lastevent = None + def __init__(self, name, canvas, x, y,guiEvent=None): """ *x*, *y* in figure coords, 0,0 = bottom, left @@ -751,8 +754,12 @@ self.x = x self.y = y + + if x is None or y is None: # cannot check if event was in axes if no x,y info + self.inaxes = False + self._update_enter_leave() return # Find all axes containing the mouse @@ -760,6 +767,7 @@ if len(axes_list) == 0: # None found self.inaxes = None + self._update_enter_leave() return elif (len(axes_list) > 1): # Overlap, get the highest zorder axCmp = lambda _x,_y: cmp(_x.zorder, _y.zorder) @@ -777,6 +785,36 @@ self.xdata = xdata self.ydata = ydata + self._update_enter_leave() + + def _update_enter_leave(self): + 'process the figure/axes enter leave events' + if LocationEvent._lastevent is not None: + last = LocationEvent._lastevent + if last.canvas!=self.canvas: + # process figure enter/leave event + last.canvas.callbacks.process('figure_leave_event', last) + self.canvas.callbacks.process('figure_enter_event', self) + if last.inaxes!=self.inaxes: + # process axes enter/leave events + if last.inaxes is not None: + last.canvas.callbacks.process('axes_leave_event', last) + if self.inaxes is not None: + self.canvas.callbacks.process('axes_enter_event', self) + + else: + # process a figure enter event + self.canvas.callbacks.process('figure_enter_event', self) + # process an axes enter event if we are over an axes + if self.inaxes is not None: + self.canvas.callbacks.process('axes_enter_event', self) + + + LocationEvent._lastevent = self + + + + class MouseEvent(LocationEvent): """ A mouse event ('button_press_event', 'button_release_event', 'scroll_event', @@ -914,6 +952,12 @@ 'motion_notify_event', 'pick_event', 'idle_event', + 'figure_enter_event', + # todo: we only process this when a mouse enters a different + # figure -- we need to connect to the GUI leavel event + 'figure_leave_event', + 'axes_enter_event', + 'axes_leave_event' ] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mme...@us...> - 2008-12-01 10:10:46
|
Revision: 6459 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6459&view=rev Author: mmetz_bn Date: 2008-12-01 10:10:39 +0000 (Mon, 01 Dec 2008) Log Message: ----------- Fixed histogram autoscaling bug when bins or range are given explicitly Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-11-30 18:33:55 UTC (rev 6458) +++ trunk/matplotlib/CHANGELOG 2008-12-01 10:10:39 UTC (rev 6459) @@ -1,3 +1,6 @@ +2008-12-01 Fixed histogram autoscaling bug when bins or range are given + explicitly (fixes Debian bug 503148) - MM + 2008-11-25 Added rcParam axes.unicode_minus which allows plain hypen for minus when False - JDH Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-11-30 18:33:55 UTC (rev 6458) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-12-01 10:10:39 UTC (rev 6459) @@ -6510,6 +6510,9 @@ """ if not self._hold: self.cla() + # NOTE: the range keyword overwrites the built-in func range !!! + # needs to be fixed in with numpy !!! + if kwargs.get('width') is not None: raise DeprecationWarning( 'hist now uses the rwidth to give relative width ' @@ -6531,6 +6534,10 @@ tx.append( np.array(x[i]) ) x = tx + # Check whether bins or range are given explicitly. In that + # case do not autoscale axes. + binsgiven = (cbook.iterable(bins) or range != None) + n = [] for i in xrange(len(x)): # this will automatically overwrite bins, @@ -6541,9 +6548,8 @@ if cumulative: slc = slice(None) - if cbook.is_numlike(cumulative): - if cumulative < 0: - slc = slice(None,None,-1) + if cbook.is_numlike(cumulative) and cumulative < 0: + slc = slice(None,None,-1) if normed: n = [(m * np.diff(bins))[slc].cumsum()[slc] for m in n] @@ -6675,6 +6681,16 @@ p.set_label(label) label = '_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) + else: + self.autoscale_view(scalex=True, scaley=False) + YL = self.yaxis.get_major_locator().view_limits(bins[0], bins[-1]) + self.set_ybound(YL) if len(n)==1: return n[0], bins, cbook.silent_list('Patch', patches[0]) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-12-01 14:51:40
|
Revision: 6461 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6461&view=rev Author: jdh2358 Date: 2008-12-01 14:51:35 +0000 (Mon, 01 Dec 2008) Log Message: ----------- added Jae Joon's legend and offsetbox implementation Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/legend.py trunk/matplotlib/lib/matplotlib/rcsetup.py Added Paths: ----------- trunk/matplotlib/examples/pylab_examples/legend_demo3.py trunk/matplotlib/lib/matplotlib/offsetbox.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-12-01 14:06:49 UTC (rev 6460) +++ trunk/matplotlib/CHANGELOG 2008-12-01 14:51:35 UTC (rev 6461) @@ -1,3 +1,6 @@ +2008-11-30 Reimplementaion of the legend which supports baseline alignement, + multi-column, and expand mode. - JJL + 2008-12-01 Fixed histogram autoscaling bug when bins or range are given explicitly (fixes Debian bug 503148) - MM Added: trunk/matplotlib/examples/pylab_examples/legend_demo3.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/legend_demo3.py (rev 0) +++ trunk/matplotlib/examples/pylab_examples/legend_demo3.py 2008-12-01 14:51:35 UTC (rev 6461) @@ -0,0 +1,34 @@ +#!/usr/bin/env python + +import matplotlib.pyplot as plt +import numpy as np + +def myplot(ax): + t1 = np.arange(0.0, 1.0, 0.1) + for n in [1, 2, 3, 4]: + ax.plot(t1, t1**n, label="n=%d"%(n,)) + +ax1 = plt.subplot(3,1,1) +ax1.plot([1], label="multi\nline") +ax1.plot([1], label="$2^{2^2}$") +ax1.plot([1], label=r"$\frac{1}{2}\pi$") +ax1.legend(loc=1, ncol=3, shadow=True) + +ax2 = plt.subplot(3,1,2) +myplot(ax2) +ax2.legend(loc=1, ncol=2, shadow=True) + + +ax3 = plt.subplot(3,1,3) +myplot(ax3) +ax3.legend(loc=1, ncol=4, mode="expand", shadow=True) + + +#title('Damped oscillation') + +plt.draw() +plt.show() + +#plt.savefig("legend_demo3") + + Modified: trunk/matplotlib/lib/matplotlib/legend.py =================================================================== --- trunk/matplotlib/lib/matplotlib/legend.py 2008-12-01 14:06:49 UTC (rev 6460) +++ trunk/matplotlib/lib/matplotlib/legend.py 2008-12-01 14:51:35 UTC (rev 6461) @@ -26,16 +26,21 @@ import numpy as np from matplotlib import rcParams -from artist import Artist -from cbook import is_string_like, iterable, silent_list, safezip -from font_manager import FontProperties -from lines import Line2D -from mlab import segments_intersect -from patches import Patch, Rectangle, Shadow, bbox_artist -from collections import LineCollection, RegularPolyCollection -from text import Text -from transforms import Affine2D, Bbox, BboxTransformTo +from matplotlib.artist import Artist +from matplotlib.cbook import is_string_like, iterable, silent_list, safezip +from matplotlib.font_manager import FontProperties +from matplotlib.lines import Line2D +from matplotlib.mlab import segments_intersect +from matplotlib.patches import Patch, Rectangle, Shadow, bbox_artist, FancyBboxPatch +from matplotlib.collections import LineCollection, RegularPolyCollection +from matplotlib.text import Text +from matplotlib.transforms import Affine2D, Bbox, BboxTransformTo +from itertools import cycle, izip + +from matplotlib.offsetbox import HPacker, VPacker, TextArea, DrawingArea + + class Legend(Artist): """ Place a legend on the axes at location loc. Labels are a @@ -75,7 +80,6 @@ } - zorder = 5 def __str__(self): return "Legend" @@ -83,72 +87,132 @@ def __init__(self, parent, handles, labels, loc = None, numpoints = None, # the number of points in the legend line + markerscale = None, # the relative size of legend markers vs. original scatterpoints = 3, # TODO: may be an rcParam - prop = None, - pad = None, # the fractional whitespace inside the legend border - borderpad = None, - markerscale = None, # the relative size of legend markers vs. original + scatteryoffsets=None, + prop = None, # properties for the legend texts + # the following dimensions are in axes coords - labelsep = None, # the vertical space between the legend entries - handlelen = None, # the length of the legend lines - handletextsep = None, # the space between the legend line and legend text - axespad = None, # the border between the axes and legend edge + pad = None, # deprecated; use borderpad + labelsep = None, # deprecated; use labelspacing + handlelen = None, # deprecated; use handlelength + handletextsep = None, # deprecated; use handletextpad + axespad = None, # deprecated; use borderaxespad + + # spacing & pad defined as a fractionof the font-size + borderpad = None, # the fractional whitespace inside the legend border + labelspacing=None, #the vertical space between the legend entries + handlelength=None, # the length of the legend handles + handletextpad=None, # the pad between the legend handle and text + borderaxespad=None, # the pad between the axes and legend border + columnspacing=None, # spacing between columns + + ncol=1, # number of columns + mode=None, # mode for horizontal distribution of columns. None, "expand" + shadow = None, - scatteryoffsets=None, ): """ - parent # the artist that contains the legend - handles # a list of artists (lines, patches) to add to the legend - labels # a list of strings to label the legend - loc # a location code - numpoints = 4 # the number of points in the legend line - scatterpoints = 3 # the number of points for the scatterplot legend - prop = FontProperties(size='smaller') # the font property - pad = 0.2 # the fractional whitespace inside the legend border - markerscale = 0.6 # the relative size of legend markers vs. original - shadow # if True, draw a shadow behind legend - scatteryoffsets # a list of yoffsets for scatter symbols in legend + - *parent* : the artist that contains the legend + - *handles* : a list of artists (lines, patches) to add to the legend + - *labels* : a list of strings to label the legend -The following dimensions are in axes coords - labelsep = 0.005 # the vertical space between the legend entries - handlelen = 0.05 # the length of the legend lines - handletextsep = 0.02 # the space between the legend line and legend text - axespad = 0.02 # the border between the axes and legend edge + Optional keyword arguments: + + ================ ========================================= + Keyword Description + ================ ========================================= + + loc a location code + numpoints the number of points in the legend line + prop the font property + markerscale the relative size of legend markers vs. original + shadow if True, draw a shadow behind legend + scatteryoffsets a list of yoffsets for scatter symbols in legend + + borderpad the fractional whitespace inside the legend border + labelspacing the vertical space between the legend entries + handlelength the length of the legend handles + handletextpad the pad between the legend handle and text + borderaxespad the pad between the axes and legend border + columnspacing the spacing between columns + +The dimensions of pad and spacing are given as a fraction of the +fontsize. Values from rcParams will be used if None. + """ - from axes import Axes # local import only to avoid circularity - from figure import Figure # local import only to avoid circularity + from matplotlib.axes import Axes # local import only to avoid circularity + from matplotlib.figure import Figure # local import only to avoid circularity Artist.__init__(self) - proplist=[numpoints, scatterpoints, pad, borderpad, markerscale, labelsep, - handlelen, handletextsep, axespad, shadow] - propnames=['numpoints','scatterpoints', 'pad', 'borderpad', 'markerscale', - 'labelsep', 'handlelen', 'handletextsep', 'axespad', 'shadow'] - for name, value in safezip(propnames,proplist): - if value is None: - value=rcParams["legend."+name] - setattr(self,name,value) - if pad: - warnings.warn("Use 'borderpad' instead of 'pad'.", DeprecationWarning) - # 2008/10/04 - if self.numpoints <= 0: - raise ValueError("numpoints must be > 0; it was %d"% numpoints) - if self.scatterpoints <= 0: - raise ValueError("scatterpoints must be > 0; it was %d"% numpoints) if prop is None: self.prop=FontProperties(size=rcParams["legend.fontsize"]) else: self.prop=prop self.fontsize = self.prop.get_size_in_points() + propnames=['numpoints', 'markerscale', 'shadow', "columnspacing", + "scatterpoints"] + + localdict = locals() + + for name in propnames: + if localdict[name] is None: + value = rcParams["legend."+name] + else: + value = localdict[name] + setattr(self, name, value) + + # Take care the deprecated keywords + deprecated_kwds = {"pad":"borderpad", + "labelsep":"labelspacing", + "handlelen":"handlelength", + "handletextsep":"handletextpad", + "axespad":"borderaxespad"} + + # convert values of deprecated keywords (ginve in axes coords) + # to new vaules in a fraction of the font size + + # conversion factor + bbox = parent.bbox + axessize_fontsize = min(bbox.width, bbox.height)/self.fontsize + + for k, v in deprecated_kwds.items(): + # use deprecated value if not None and if their newer + # counter part is None. + if localdict[k] is not None and localdict[v] is None: + warnings.warn("Use '%s' instead of '%s'." % (v, k), + DeprecationWarning) + setattr(self, v, localdict[k]*axessize_fontsize) + continue + + # Otherwise, use new keywords + if localdict[v] is None: + setattr(self, v, rcParams["legend."+v]) + else: + setattr(self, v, localdict[v]) + + del localdict + + self._ncol = ncol + + if self.numpoints <= 0: + raise ValueError("numpoints must be >= 0; it was %d"% numpoints) + # introduce y-offset for handles of the scatter plot if scatteryoffsets is None: - self._scatteryoffsets = np.array([4./8., 5./8., 3./8.]) + self._scatteryoffsets = np.array([3./8., 4./8., 2.5/8.]) else: self._scatteryoffsets = np.asarray(scatteryoffsets) - reps = int(self.scatterpoints / len(self._scatteryoffsets)) + 1 + reps = int(self.numpoints / len(self._scatteryoffsets)) + 1 self._scatteryoffsets = np.tile(self._scatteryoffsets, reps)[:self.scatterpoints] + # _legend_box is an OffsetBox instance that contains all + # legend items and will be initialized from _init_legend_box() + # method. + self._legend_box = None + if isinstance(parent,Axes): self.isaxes = True self.set_figure(parent.figure) @@ -158,9 +222,6 @@ else: raise TypeError("Legend needs either Axes or Figure as parent") self.parent = parent - self._offsetTransform = Affine2D() - self._parentTransform = BboxTransformTo(parent.bbox) - Artist.set_transform(self, self._offsetTransform + self._parentTransform) if loc is None: loc = rcParams["legend.loc"] @@ -186,100 +247,165 @@ loc = 1 self._loc = loc + self._mode = mode - self.legendPatch = Rectangle( - xy=(0.0, 0.0), width=0.5, height=0.5, + # We use FancyBboxPatch to draw a legend frame. The location + # and size of the box will be updated during the drawing time. + self.legendPatch = FancyBboxPatch( + xy=(0.0, 0.0), width=1., height=1., facecolor='w', edgecolor='k', + mutation_scale=self.fontsize, ) + + # The width and height of the legendPatch will be set (in the + # draw()) to the length that includes the padding. Thus we set + # pad=0 here. + self.legendPatch.set_boxstyle("round",pad=0, #self.borderpad, + rounding_size=0.2) + self._set_artist_props(self.legendPatch) - # make a trial box in the middle of the axes. relocate it - # based on it's bbox - left, top = 0.5, 0.5 - textleft = left+ self.handlelen+self.handletextsep - self.texts = self._get_texts(labels, textleft, top) - self.legendHandles = self._get_handles(handles, self.texts) - self._drawFrame = True + # populate the legend_box with legend items. + self._init_legend_box(handles, labels) + self._legend_box.set_figure(self.figure) + + def _set_artist_props(self, a): + """ + set the boilerplate props for artists added to axes + """ a.set_figure(self.figure) + + for c in self.get_children(): + c.set_figure(self.figure) + a.set_transform(self.get_transform()) - def _approx_text_height(self): - return self.fontsize/72.0*self.figure.dpi/self.parent.bbox.height + def _findoffset_best(self, width, height, xdescent, ydescent): + "Heper function to locate the legend" + ox, oy = self._find_best_position(width, height) + return ox+xdescent, oy+ydescent + def _findoffset_loc(self, width, height, xdescent, ydescent): + "Heper function to locate the legend" + bbox = Bbox.from_bounds(0, 0, width, height) + x, y = self._get_anchored_bbox(self._loc, bbox, self.parent.bbox) + return x+xdescent, y+ydescent def draw(self, renderer): + "Draw everything that belongs to the legend" if not self.get_visible(): return + renderer.open_group('legend') - self._update_positions(renderer) + + # find_offset function will be provided to _legend_box and + # _legend_box will draw itself at the location of the return + # value of the find_offset. + if self._loc == 0: + self._legend_box.set_offset(self._findoffset_best) + else: + self._legend_box.set_offset(self._findoffset_loc) + + # if mode == fill, set the width of the legend_box to the + # width of the paret (minus pads) + if self._mode in ["expand"]: + pad = 2*(self.borderaxespad+self.borderpad)*self.fontsize + self._legend_box.set_width(self.parent.bbox.width-pad) + if self._drawFrame: + # update the location and size of the legend + bbox = self._legend_box.get_window_extent(renderer) + self.legendPatch.set_bounds(bbox.x0, bbox.y0, + bbox.width, bbox.height) + if self.shadow: - shadow = Shadow(self.legendPatch, -0.005, -0.005) + shadow = Shadow(self.legendPatch, 2, -2) shadow.draw(renderer) + self.legendPatch.draw(renderer) + self._legend_box.draw(renderer) - if not len(self.legendHandles) and not len(self.texts): return - for h in self.legendHandles: - if h is not None: - h.draw(renderer) - if hasattr(h, '_legmarker'): - h._legmarker.draw(renderer) - if 0: bbox_artist(h, renderer) - - for t in self.texts: - if 0: bbox_artist(t, renderer) - t.draw(renderer) renderer.close_group('legend') - #draw_bbox(self.save, renderer, 'g') - #draw_bbox(self.ibox, renderer, 'r', self.get_transform()) - def _get_handle_text_bbox(self, renderer): - 'Get a bbox for the text and lines in axes coords' - bboxesText = [t.get_window_extent(renderer) for t in self.texts] - bboxesHandles = [h.get_window_extent(renderer) for h in self.legendHandles if h is not None] + def _approx_text_height(self): + """ + Return the approximate height of the text. This is used to place + the legend handle. + """ + return self.fontsize/72.0*self.figure.dpi - bboxesAll = bboxesText - bboxesAll.extend(bboxesHandles) - bbox = Bbox.union(bboxesAll) - self.save = bbox + def _init_legend_box(self, handles, labels): + """ + Initiallize the legend_box. The legend_box is an instance of + the OffsetBox, which is packed with legend handles and + texts. Once packed, their location is calculated during the + drawing time. + """ - ibox = bbox.inverse_transformed(self.get_transform()) - self.ibox = ibox + # legend_box is a HPacker, horizontally packed with + # columns. Each column is a VPacker, vertically packed with + # legend items. Each legend item is HPacker packed with + # legend handleBox and labelBox. handleBox is an instance of + # offsetbox.DrawingArea which contains legend handle. labelBox + # is an instance of offsetbox.TextArea which contains legend + # text. - return ibox + + text_list = [] # the list of text instances + handle_list = [] # the list of text instances - def _get_handles(self, handles, texts): - handles = list(handles) - texts = list(texts) - HEIGHT = self._approx_text_height() - left = 0.5 + label_prop = dict(verticalalignment='baseline', + horizontalalignment='left', + fontproperties=self.prop, + ) - ret = [] # the returned legend lines + labelboxes = [] - # we need to pad the text with empties for the numpoints=1 - # centered marker proxy + for l in labels: + textbox = TextArea(l, textprops=label_prop) + text_list.append(textbox._text) + labelboxes.append(textbox) - for handle, label in safezip(handles, texts): + handleboxes = [] + + + # The approximate height and descent of text. These values are + # only used for plotting the legend handle. + height = self._approx_text_height() * 0.6 + descent = 0. #height/6. + + # each handle needs to be drawn inside a box of + # (x, y, w, h) = (0, -descent, width, height). + # And their corrdinates should be given in the display coordinates. + + # The transformation of each handle will be automatically set + # to self.get_trasnform(). If the artist does not uses its + # default trasnform (eg, Collections), you need to + # manually set their transform to the self.get_transform(). + + for handle in handles: if isinstance(handle, RegularPolyCollection): npoints = self.scatterpoints else: npoints = self.numpoints if npoints > 1: - xdata = np.linspace(left, left + self.handlelen, npoints) + # we put some pad here to compensate the size of the + # marker + xdata = np.linspace(0.3*self.fontsize, + (self.handlelength-0.3)*self.fontsize, + npoints) xdata_marker = xdata elif npoints == 1: - xdata = np.linspace(left, left + self.handlelen, 2) - xdata_marker = [left + 0.5*self.handlelen] + xdata = np.linspace(0, self.handlelength, 2) + xdata_marker = [0.5*self.handlelength*self.fontsize] - x, y = label.get_position() - x -= self.handlelen + self.handletextsep if isinstance(handle, Line2D): - ydata = (y-HEIGHT/2)*np.ones(xdata.shape, float) + ydata = ((height-descent)/2.)*np.ones(xdata.shape, float) legline = Line2D(xdata, ydata) legline.update_from(handle) @@ -288,8 +414,9 @@ legline.set_clip_path(None) legline.set_drawstyle('default') legline.set_marker('None') - ret.append(legline) + handle_list.append(legline) + legline_marker = Line2D(xdata_marker, ydata[:len(xdata_marker)]) legline_marker.update_from(handle) self._set_artist_props(legline_marker) @@ -302,16 +429,17 @@ legline._legmarker = legline_marker elif isinstance(handle, Patch): - p = Rectangle(xy=(min(xdata), y-3/4*HEIGHT), - width = self.handlelen, height=HEIGHT/2, + p = Rectangle(xy=(0, -0.*descent), + width = self.handlelength*self.fontsize, + height=0.*descent+(height-descent)*.9, ) p.update_from(handle) self._set_artist_props(p) p.set_clip_box(None) p.set_clip_path(None) - ret.append(p) + handle_list.append(p) elif isinstance(handle, LineCollection): - ydata = (y-HEIGHT/2)*np.ones(xdata.shape, float) + ydata = ((height-descent)/2.)*np.ones(xdata.shape, float) legline = Line2D(xdata, ydata) self._set_artist_props(legline) legline.set_clip_box(None) @@ -322,13 +450,13 @@ legline.set_color(color) legline.set_linewidth(lw) legline.set_dashes(dashes) - ret.append(legline) + handle_list.append(legline) elif isinstance(handle, RegularPolyCollection): - # the ydata values set here have no effects as it will - # be updated in the _update_positions() method. - ydata = (y-HEIGHT/2)*np.ones(np.asarray(xdata_marker).shape, float) + #ydata = self._scatteryoffsets + ydata = height*self._scatteryoffsets + size_max, size_min = max(handle.get_sizes()),\ min(handle.get_sizes()) # we may need to scale these sizes by "markerscale" @@ -338,32 +466,86 @@ sizes = [.5*(size_max+size_min), size_max, size_min] else: - sizes = size_max*np.linspace(0,1,self.scatterpoints)+size_min - + sizes = (size_max-size_min)*np.linspace(0,1,self.scatterpoints)+size_min + p = type(handle)(handle.get_numsides(), rotation=handle.get_rotation(), sizes=sizes, offsets=zip(xdata_marker,ydata), - transOffset=self.get_transform()) - + transOffset=self.get_transform(), + ) + p.update_from(handle) p.set_figure(self.figure) p.set_clip_box(None) p.set_clip_path(None) - ret.append(p) + handle_list.append(p) else: - ret.append(None) + handle_list.append(None) - return ret + handlebox = DrawingArea(width=self.handlelength*self.fontsize, + height=height, + xdescent=0., ydescent=descent) + handle = handle_list[-1] + handlebox.add_artist(handle) + if hasattr(handle, "_legmarker"): + handlebox.add_artist(handle._legmarker) + handleboxes.append(handlebox) + + + # We calculate number of lows in each column. The first + # (num_largecol) columns will have (nrows+1) rows, and remaing + # (num_smallcol) columns will have (nrows) rows. + nrows, num_largecol = divmod(len(handleboxes), self._ncol) + num_smallcol = self._ncol-num_largecol + + # starting index of each column and number of rows in it. + largecol = zip(range(0, num_largecol*(nrows+1), (nrows+1)), + [nrows+1] * num_largecol) + smallcol = zip(range(num_largecol*(nrows+1), len(handleboxes), nrows), + [nrows] * num_smallcol) + + handle_label = zip(handleboxes, labelboxes) + columnbox = [] + for i0, di in largecol+smallcol: + # pack handleBox and labelBox into itemBox + itemBoxes = [HPacker(pad=0, + sep=self.handletextpad*self.fontsize, + children=[h, t], align="baseline") + for h, t in handle_label[i0:i0+di]] + + # pack columnBox + columnbox.append(VPacker(pad=0, + sep=self.labelspacing*self.fontsize, + align="baseline", + children=itemBoxes)) + + if self._mode == "expand": + mode = "expand" + else: + mode = "fixed" + + sep = self.columnspacing*self.fontsize + + self._legend_box = HPacker(pad=self.borderpad*self.fontsize, + sep=sep, align="baseline", + mode=mode, + children=columnbox) + + self.texts = text_list + self.legendHandles = handle_list + + def _auto_legend_data(self): - """ Returns list of vertices and extents covered by the plot. + """ + Returns list of vertices and extents covered by the plot. Returns a two long list. First element is a list of (x, y) vertices (in - axes-coordinates) covered by all the lines and line + display-coordinates) covered by all the lines and line collections, in the legend's handles. Second element is a list of bounding boxes for all the patches in @@ -377,24 +559,21 @@ bboxes = [] lines = [] - inverse_transform = ax.transAxes.inverted() - for handle in ax.lines: assert isinstance(handle, Line2D) path = handle.get_path() trans = handle.get_transform() tpath = trans.transform_path(path) - apath = inverse_transform.transform_path(tpath) - lines.append(apath) + lines.append(tpath) for handle in ax.patches: assert isinstance(handle, Patch) if isinstance(handle, Rectangle): - transform = handle.get_data_transform() + inverse_transform + transform = handle.get_data_transform() bboxes.append(handle.get_bbox().transformed(transform)) else: - transform = handle.get_transform() + inverse_transform + transform = handle.get_transform() bboxes.append(handle.get_path().get_extents(transform)) return [vertices, bboxes, lines] @@ -404,9 +583,10 @@ self._drawFrame = b def get_children(self): + 'return a list of child artists' children = [] - children.extend(self.legendHandles) - children.extend(self.texts) + if self._legend_box: + children.append(self._legend_box) return children def get_frame(self): @@ -425,51 +605,61 @@ 'return a list of text.Text instance in the legend' return silent_list('Text', self.texts) - def _get_texts(self, labels, left, upper): + def get_window_extent(self): + 'return a extent of the the legend' + return self.legendPatch.get_window_extent() - # height in axes coords - HEIGHT = self._approx_text_height() - pos = upper - x = left - ret = [] # the returned list of text instances - for l in labels: - text = Text( - x=x, y=pos, - text=l, - fontproperties=self.prop, - verticalalignment='top', - horizontalalignment='left' - ) - self._set_artist_props(text) - ret.append(text) - pos -= HEIGHT + def _get_anchored_bbox(self, loc, bbox, parentbbox): + """ + Place the *bbox* inside the *parentbbox* according to a given + location code. Return the (x,y) coordinate of the bbox. - return ret + - loc: a location code in range(1, 11). + This corresponds to the possible values for self._loc, excluding "best". + - bbox: bbox to be placed, display coodinate units. + - parentbbox: a parent box which will ... [truncated message content] |
From: <ds...@us...> - 2008-12-02 17:12:17
|
Revision: 6471 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6471&view=rev Author: dsdale Date: 2008-12-02 17:11:07 +0000 (Tue, 02 Dec 2008) Log Message: ----------- improved checks for external dependencies Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/__init__.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-12-02 17:07:57 UTC (rev 6470) +++ trunk/matplotlib/CHANGELOG 2008-12-02 17:11:07 UTC (rev 6471) @@ -1,3 +1,7 @@ +2008-12-02 Improve checks for external dependencies, using subprocess + (instead of deprecated popen*) and distutils (for version + checking) - DSD + 2008-11-30 Reimplementaion of the legend which supports baseline alignement, multi-column, and expand mode. - JJL Modified: trunk/matplotlib/lib/matplotlib/__init__.py =================================================================== --- trunk/matplotlib/lib/matplotlib/__init__.py 2008-12-02 17:07:57 UTC (rev 6470) +++ trunk/matplotlib/lib/matplotlib/__init__.py 2008-12-02 17:11:07 UTC (rev 6471) @@ -93,8 +93,9 @@ __revision__ = '$Revision$' __date__ = '$Date$' -import os, re, shutil, sys, warnings +import os, re, shutil, subprocess, sys, warnings import distutils.sysconfig +import distutils.version NEWCONFIG = False @@ -256,10 +257,10 @@ def checkdep_dvipng(): try: - stdin, stdout = os.popen4('dvipng -version') - line = stdout.readlines()[1] + s = subprocess.Popen(['dvipng','-version'], stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + line = s.stdout.readlines()[1] v = line.split()[-1] - float(v) return v except (IndexError, ValueError): return None @@ -267,47 +268,45 @@ def checkdep_ghostscript(): try: if sys.platform == 'win32': - command = 'gswin32c --version' + command_args = ['gswin32c', '--version'] else: - command = 'gs --version' - stdin, stdout = os.popen4(command) - v = stdout.read()[:-1] - vtest = '.'.join(v.split('.')[:2]) # deal with version numbers like '7.07.1' - float(vtest) - return vtest + command_args = ['gs', '--version'] + s = subprocess.Popen(command_args, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + v = s.stdout.read()[:-1] + return v except (IndexError, ValueError): return None def checkdep_tex(): try: - stdin, stdout = os.popen4('tex -version') - line = stdout.readlines()[0] + s = subprocess.Popen(['tex','-version'], stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + line = s.stdout.readlines()[0] pattern = '3\.1\d+' match = re.search(pattern, line) v = match.group(0) - float(v) return v except (IndexError, ValueError, AttributeError): return None def checkdep_pdftops(): try: - stdin, stdout = os.popen4('pdftops -v') - for line in stdout.readlines(): + s = subprocess.Popen(['pdftops','-v'], stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + for line in s.stderr: if 'version' in line: v = line.split()[-1] - float(v) return v except (IndexError, ValueError, UnboundLocalError): return None def compare_versions(a, b): - "return True if a is greater than b" + "return True if a is greater than or equal to b" if a: - a = [int(i) for i in a.split('.')] - b = [int(i) for i in b.split('.')] - if a[0]>b[0]: return True - elif (a[0]==b[0]) and (a[1]>=b[1]): return True + a = distutils.version.LooseVersion(a) + b = distutils.version.LooseVersion(b) + if a>=b: return True else: return False else: return False @@ -330,8 +329,13 @@ if s == 'xpdf': pdftops_req = '3.0' + pdftops_req_alt = '0.9' # poppler version numbers, ugh pdftops_v = checkdep_pdftops() - if compare_versions(pdftops_v, pdftops_req): pass + if compare_versions(pdftops_v, pdftops_req): + pass + elif compare_versions(pdftops_v, pdftops_req_alt) and not \ + compare_versions(pdftops_v, '1.0'): + pass else: flag = False warnings.warn(('matplotlibrc ps.usedistiller can not be set to ' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2008-12-02 22:27:43
|
Revision: 6479 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6479&view=rev Author: leejjoon Date: 2008-12-02 22:27:38 +0000 (Tue, 02 Dec 2008) Log Message: ----------- Fixed a bug in the new legend class that didn't allowed a tuple of coordinate vlaues as loc Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/legend.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-12-02 22:04:41 UTC (rev 6478) +++ trunk/matplotlib/CHANGELOG 2008-12-02 22:27:38 UTC (rev 6479) @@ -1,3 +1,6 @@ +2008-12-02 Fixed a bug in the new legend class that didn't allowed + a tuple of coordinate vlaues as loc. -JJL + 2008-12-02 Improve checks for external dependencies, using subprocess (instead of deprecated popen*) and distutils (for version checking) - DSD Modified: trunk/matplotlib/lib/matplotlib/legend.py =================================================================== --- trunk/matplotlib/lib/matplotlib/legend.py 2008-12-02 22:04:41 UTC (rev 6478) +++ trunk/matplotlib/lib/matplotlib/legend.py 2008-12-02 22:27:38 UTC (rev 6479) @@ -61,6 +61,9 @@ 'upper center' : 9, 'center' : 10, + loc can be a tuple of the noramilzed coordinate values with + respect its parent. + Return value is a sequence of text, line instances that make up the legend """ @@ -100,7 +103,7 @@ axespad = None, # deprecated; use borderaxespad # spacing & pad defined as a fractionof the font-size - borderpad = None, # the fractional whitespace inside the legend border + borderpad = None, # the whitespace inside the legend border labelspacing=None, #the vertical space between the legend entries handlelength=None, # the length of the legend handles handletextpad=None, # the pad between the legend handle and text @@ -119,11 +122,11 @@ Optional keyword arguments: - ================ ========================================= + ================ ================================================= Keyword Description - ================ ========================================= + ================ ================================================= - loc a location code + loc a location code or a tuple of coordinates numpoints the number of points in the legend line prop the font property markerscale the relative size of legend markers vs. original @@ -284,14 +287,22 @@ a.set_transform(self.get_transform()) def _findoffset_best(self, width, height, xdescent, ydescent): - "Heper function to locate the legend" + "Heper function to locate the legend at its best position" ox, oy = self._find_best_position(width, height) return ox+xdescent, oy+ydescent def _findoffset_loc(self, width, height, xdescent, ydescent): - "Heper function to locate the legend" - bbox = Bbox.from_bounds(0, 0, width, height) - x, y = self._get_anchored_bbox(self._loc, bbox, self.parent.bbox) + "Heper function to locate the legend using the location code" + + if iterable(self._loc) and len(self._loc)==2: + # when loc is a tuple of axes(or figure) coordinates. + fx, fy = self._loc + bbox = self.parent.bbox + x, y = bbox.x0 + bbox.width * fx, bbox.y0 + bbox.height * fy + else: + bbox = Bbox.from_bounds(0, 0, width, height) + x, y = self._get_anchored_bbox(self._loc, bbox, self.parent.bbox) + return x+xdescent, y+ydescent def draw(self, renderer): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2008-12-03 07:40:13
|
Revision: 6480 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6480&view=rev Author: leejjoon Date: 2008-12-03 07:40:09 +0000 (Wed, 03 Dec 2008) Log Message: ----------- reorganization of style classes in patches.py Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/patches.py Added Paths: ----------- trunk/matplotlib/examples/pylab_examples/fancyarrow_demo.py trunk/matplotlib/examples/pylab_examples/fancybox_demo2.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-12-02 22:27:38 UTC (rev 6479) +++ trunk/matplotlib/CHANGELOG 2008-12-03 07:40:09 UTC (rev 6480) @@ -1,3 +1,7 @@ +2008-12-02 The transmuter classes in the patches.py are reorganized as + subclasses of the Style classes. A few more box and arrow + styles are added. -JJL + 2008-12-02 Fixed a bug in the new legend class that didn't allowed a tuple of coordinate vlaues as loc. -JJL Added: trunk/matplotlib/examples/pylab_examples/fancyarrow_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/fancyarrow_demo.py (rev 0) +++ trunk/matplotlib/examples/pylab_examples/fancyarrow_demo.py 2008-12-03 07:40:09 UTC (rev 6480) @@ -0,0 +1,43 @@ +import matplotlib.patches as mpatches +import matplotlib.pyplot as plt + +styles = mpatches.ArrowStyle.get_styles() + +figheight = (len(styles)+.5) +fig1 = plt.figure(1, (4, figheight)) +fontsize = 0.3 * fig1.dpi + +ax = plt.Axes(fig1, [0, 0, 1, 1], frameon=False, aspect=1.) +fig1.add_axes(ax) + +ax.set_xlim(0, 4) +ax.set_ylim(0, figheight) + +for i, (stylename, styleclass) in enumerate(sorted(styles.items())): + y = (float(len(styles)) -0.25 - i) # /figheight + p = mpatches.Circle((3.2, y), 0.2, fc="w") + ax.add_patch(p) + #ax.plot([0.8], [y], "o", mec="b", mfc="w", ms=20, transform=fig1.transFigure) + #ax.scatter([0.8], [y], s=20*20, marker="o", edgecolors=["b"], facecolors=["w"], + # ) + ax.annotate(stylename, (3.2, y), + (2., y), + #xycoords="figure fraction", textcoords="figure fraction", + ha="right", va="center", + size=fontsize, + arrowprops=dict(arrowstyle=stylename, + patchB=p, + shrinkA=5, + shrinkB=5, + fc="w", ec="k", + connectionstyle="arc3,rad=-0.05", + ), + bbox=dict(boxstyle="square", fc="w")) + +ax.xaxis.set_visible(False) +ax.yaxis.set_visible(False) + + + +plt.draw() +plt.show() Added: trunk/matplotlib/examples/pylab_examples/fancybox_demo2.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/fancybox_demo2.py (rev 0) +++ trunk/matplotlib/examples/pylab_examples/fancybox_demo2.py 2008-12-03 07:40:09 UTC (rev 6480) @@ -0,0 +1,17 @@ +import matplotlib.patches as mpatch +import matplotlib.pyplot as plt + +styles = mpatch.BoxStyle.get_styles() + +figheight = (len(styles)+.5) +fig1 = plt.figure(1, (4, figheight)) +fontsize = 0.4 * fig1.dpi + +for i, (stylename, styleclass) in enumerate(styles.items()): + fig1.text(0.5, (float(len(styles)) - 0.5 - i)/figheight, stylename, + ha="center", + size=fontsize, + transform=fig1.transFigure, + bbox=dict(boxstyle=stylename, fc="w", ec="k")) +plt.draw() +plt.show() Modified: trunk/matplotlib/lib/matplotlib/patches.py =================================================================== --- trunk/matplotlib/lib/matplotlib/patches.py 2008-12-02 22:27:38 UTC (rev 6479) +++ trunk/matplotlib/lib/matplotlib/patches.py 2008-12-03 07:40:09 UTC (rev 6480) @@ -289,6 +289,7 @@ rgbFace = (r, g, b) gc.set_alpha(a) + if self._hatch: gc.set_hatch(self._hatch ) @@ -1366,319 +1367,576 @@ r.draw(renderer) -class BboxTransmuterBase(object): + +def _pprint_table(_table, leadingspace=2): """ - :class:`BBoxTransmuterBase` and its derivatives are used to make a - fancy box around a given rectangle. The :meth:`__call__` method - returns the :class:`~matplotlib.path.Path` of the fancy box. This - class is not an artist and actual drawing of the fancy box is done - by the :class:`FancyBboxPatch` class. + Given the list of list of strings, return a string of REST table format. """ + if leadingspace: + pad = ' '*leadingspace + else: + pad = '' - # The derived classes are required to be able to be initialized - # w/o arguments, i.e., all its argument (except self) must have - # the default values. + columns = [[] for cell in _table[0]] - def __init__(self): - super(BboxTransmuterBase, self).__init__() + for row in _table: + for column, cell in zip(columns, row): + column.append(cell) + + + col_len = [max([len(cell) for cell in column]) for column in columns] + lines = [] + table_formatstr = pad + ' '.join([('=' * cl) for cl in col_len]) + lines.append('') + lines.append(table_formatstr) + lines.append(pad + ' '.join([cell.ljust(cl) for cell, cl in zip(_table[0], col_len)])) + lines.append(table_formatstr) + + lines.extend([(pad + ' '.join([cell.ljust(cl) for cell, cl in zip(row, col_len)])) + for row in _table[1:]]) + + lines.append(table_formatstr) + lines.append('') + return "\n".join(lines) - def transmute(self, x0, y0, width, height, mutation_size): + +def _pprint_styles(_styles, leadingspace=2): + """ + A helper function for the _Style class. Given the dictionary of + (stylename : styleclass), return a formatted string listing all the + styles. Used to update the documentation. + """ + if leadingspace: + pad = ' '*leadingspace + else: + pad = '' + + names, attrss, clss = [], [], [] + + import inspect + + _table = [["Class", "Name", "Attrs"]] + + for name, cls in sorted(_styles.items()): + args, varargs, varkw, defaults = inspect.getargspec(cls.__init__) + if defaults: + args = [(argname, argdefault) \ + for argname, argdefault in zip(args[1:], defaults)] + else: + args = [] + + _table.append([cls.__name__, name, + ",".join([("%s=%s" % (an, av)) for an, av in args])]) + + return _pprint_table(_table) + + + +class _Style(object): + """ + A base class for the Styles. It is meant to be a container class, + where actual styles are declared as subclass of it, and it + provides some helper functions. + """ + def __new__(self, stylename, **kw): """ - The transmute method is a very core of the - :class:`BboxTransmuter` class and must be overriden in the - subclasses. It receives the location and size of the - rectangle, and the mutation_size, with which the amount of - padding and etc. will be scaled. It returns a - :class:`~matplotlib.path.Path` instance. + return the instance of the subclass with the given style name. """ - raise NotImplementedError('Derived must override') + # the "class" should have the _style_list attribute, which is + # a dictionary of stylname, style class paie. + + _list = stylename.replace(" ","").split(",") + _name = _list[0].lower() + try: + _cls = self._style_list[_name] + except KeyError: + raise ValueError("Unknown style : %s" % stylename) + try: + _args_pair = [cs.split("=") for cs in _list[1:]] + _args = dict([(k, float(v)) for k, v in _args_pair]) + except ValueError: + raise ValueError("Incorrect style argument : %s" % stylename) + _args.update(kw) - def __call__(self, x0, y0, width, height, mutation_size, - aspect_ratio=1.): + return _cls(**_args) + + + @classmethod + def get_styles(klass): """ - The __call__ method a thin wrapper around the transmute method - and take care of the aspect. + A class method which returns a dictionary of available styles. """ - if aspect_ratio is not None: - # Squeeze the given height by the aspect_ratio - y0, height = y0/aspect_ratio, height/aspect_ratio - # call transmute method with squeezed height. - path = self.transmute(x0, y0, width, height, mutation_size) - vertices, codes = path.vertices, path.codes - # Restore the height - vertices[:,1] = vertices[:,1] * aspect_ratio - return Path(vertices, codes) - else: - return self.transmute(x0, y0, width, height, mutation_size) + return klass._style_list + @classmethod + def pprint_styles(klass): + """ + A class method which returns a string of the available styles. + """ + return _pprint_styles(klass._style_list) -class SquareBoxTransmuter(BboxTransmuterBase): + + +class BoxStyle(_Style): """ - Simple square box. + :class:`BoxStyle` is a container class which defines several + boxstyle classes, which are used for :class:`FancyBoxPatch`. - *pad*: an amount of padding. + A style object can be created as + + BoxStyle.Round(pad=0.2) + + or + + BoxStyle("Round", pad=0.2) + + or + + BoxStyle("Round, pad=0.2") + + Following boxstyle classes are defined. + + %(AvailableBoxstyles)s + + An instance of any boxstyle class is an callable object, + whose call signature is + + __call__(self, x0, y0, width, height, mutation_size, aspect_ratio=1.) + + and returns a :class:`Path` instance. *x0*, *y0*, *width* and + *height* specify the location and size of the box to be + drawn. *mutation_scale* determines the overall size of the + mutation (by which I mean the transformation of the rectangle to + the fancy box). *mutation_aspect* determines the aspect-ratio of + the mutation. + """ + + _style_list = {} - def __init__(self, pad=0.3): - self.pad = pad - super(SquareBoxTransmuter, self).__init__() - def transmute(self, x0, y0, width, height, mutation_size): + class _Base(object): + """ + :class:`BBoxTransmuterBase` and its derivatives are used to make a + fancy box around a given rectangle. The :meth:`__call__` method + returns the :class:`~matplotlib.path.Path` of the fancy box. This + class is not an artist and actual drawing of the fancy box is done + by the :class:`FancyBboxPatch` class. + """ - # padding - pad = mutation_size * self.pad + # The derived classes are required to be able to be initialized + # w/o arguments, i.e., all its argument (except self) must have + # the default values. - # width and height with padding added. - width, height = width + 2.*pad, \ - height + 2.*pad, + def __init__(self): + """ + initializtion. + """ + super(BoxStyle._Base, self).__init__() - # boundary of the padded box - x0, y0 = x0-pad, y0-pad, - x1, y1 = x0+width, y0 + height - cp = [(x0, y0), (x1, y0), (x1, y1), (x0, y1), - (x0, y0), (x0, y0)] - com = [Path.MOVETO, - Path.LINETO, - Path.LINETO, - Path.LINETO, - Path.LINETO, - Path.CLOSEPOLY] - path = Path(cp, com) + def transmute(self, x0, y0, width, height, mutation_size): + """ + The transmute method is a very core of the + :class:`BboxTransmuter` class and must be overriden in the + subclasses. It receives the location and size of the + rectangle, and the mutation_size, with which the amount of + padding and etc. will be scaled. It returns a + :class:`~matplotlib.path.Path` instance. + """ + raise NotImplementedError('Derived must override') - return path -class RoundBoxTransmuter(BboxTransmuterBase): - """ - A box with round corners. - """ + def __call__(self, x0, y0, width, height, mutation_size, + aspect_ratio=1.): + """ + Given the location and size of the box, return the path of + the box around it. - def __init__(self, pad=0.3, rounding_size=None): - self.pad = pad - self.rounding_size = rounding_size - BboxTransmuterBase.__init__(self) + - *x0*, *y0*, *width*, *height* : location and size of the box + - *mutation_size* : a reference scale for the mutation. + - *aspect_ratio* : aspect-ration for the mutation. + """ + # The __call__ method is a thin wrapper around the transmute method + # and take care of the aspect. - def transmute(self, x0, y0, width, height, mutation_size): + if aspect_ratio is not None: + # Squeeze the given height by the aspect_ratio + y0, height = y0/aspect_ratio, height/aspect_ratio + # call transmute method with squeezed height. + path = self.transmute(x0, y0, width, height, mutation_size) + vertices, codes = path.vertices, path.codes + # Restore the height + vertices[:,1] = vertices[:,1] * aspect_ratio + return Path(vertices, codes) + else: + return self.transmute(x0, y0, width, height, mutation_size) - # padding - pad = mutation_size * self.pad - # size of the roudning corner - if self.rounding_size: - dr = mutation_size * self.rounding_size - else: - dr = pad - width, height = width + 2.*pad, \ - height + 2.*pad, + class Square(_Base): + """ + A simple square box. + """ + def __init__(self, pad=0.3): + """ + *pad* + amount of padding + """ + + self.pad = pad + super(BoxStyle.Square, self).__init__() - x0, y0 = x0-pad, y0-pad, - x1, y1 = x0+width, y0 + height + def transmute(self, x0, y0, width, height, mutation_size): - # Round corners are implemented as quadratic bezier. eg. - # [(x0, y0-dr), (x0, y0), (x0+dr, y0)] for lower left corner. - cp = [(x0+dr, y0), - (x1-dr, y0), - (x1, y0), (x1, y0+dr), - (x1, y1-dr), - (x1, y1), (x1-dr, y1), - (x0+dr, y1), - (x0, y1), (x0, y1-dr), - (x0, y0+dr), - (x0, y0), (x0+dr, y0), - (x0+dr, y0)] + # padding + pad = mutation_size * self.pad - com = [Path.MOVETO, - Path.LINETO, - Path.CURVE3, Path.CURVE3, - Path.LINETO, - Path.CURVE3, Path.CURVE3, - Path.LINETO, - Path.CURVE3, Path.CURVE3, - Path.LINETO, - Path.CURVE3, Path.CURVE3, - Path.CLOSEPOLY] + # width and height with padding added. + width, height = width + 2.*pad, \ + height + 2.*pad, - path = Path(cp, com) + # boundary of the padded box + x0, y0 = x0-pad, y0-pad, + x1, y1 = x0+width, y0 + height - return path + cp = [(x0, y0), (x1, y0), (x1, y1), (x0, y1), + (x0, y0), (x0, y0)] + com = [Path.MOVETO, + Path.LINETO, + Path.LINETO, + Path.LINETO, + Path.LINETO, + Path.CLOSEPOLY] -class Round4BoxTransmuter(BboxTransmuterBase): - """ - A box with round edges. - """ + path = Path(cp, com) - def __init__(self, pad=0.3, rounding_size=None): - self.pad = pad - self.rounding_size = rounding_size - BboxTransmuterBase.__init__(self) + return path - def transmute(self, x0, y0, width, height, mutation_size): + _style_list["square"] = Square - # padding - pad = mutation_size * self.pad - # roudning size. Use a half of the pad if not set. - if self.rounding_size: - dr = mutation_size * self.rounding_size - else: - dr = pad / 2. + class LArrow(_Base): + """ + (left) Arrow Box + """ - width, height = width + 2.*pad - 2*dr, \ - height + 2.*pad - 2*dr, + def __init__(self, pad=0.3): + self.pad = pad + super(BoxStyle.LArrow, self).__init__() + def transmute(self, x0, y0, width, height, mutation_size): - x0, y0 = x0-pad+dr, y0-pad+dr, - x1, y1 = x0+width, y0 + height + # padding + pad = mutation_size * self.pad + # width and height with padding added. + width, height = width + 2.*pad, \ + height + 2.*pad, - cp = [(x0, y0), - (x0+dr, y0-dr), (x1-dr, y0-dr), (x1, y0), - (x1+dr, y0+dr), (x1+dr, y1-dr), (x1, y1), - (x1-dr, y1+dr), (x0+dr, y1+dr), (x0, y1), - (x0-dr, y1-dr), (x0-dr, y0+dr), (x0, y0), - (x0, y0)] + # boundary of the padded box + x0, y0 = x0-pad, y0-pad, + x1, y1 = x0+width, y0 + height - com = [Path.MOVETO, - Path.CURVE4, Path.CURVE4, Path.CURVE4, - Path.CURVE4, Path.CURVE4, Path.CURVE4, - Path.CURVE4, Path.CURVE4, Path.CURVE4, - Path.CURVE4, Path.CURVE4, Path.CURVE4, - Path.CLOSEPOLY] + dx = (y1-y0)/2. + dxx = dx*.5 + # adjust x0. 1.4 <- sqrt(2) + x0 = x0 + pad / 1.4 + + cp = [(x0+dxx, y0), (x1, y0), (x1, y1), (x0+dxx, y1), + (x0+dxx, y1+dxx), (x0-dx, y0+dx), (x0+dxx, y0-dxx), # arrow + (x0+dxx, y0), (x0+dxx, y0)] - path = Path(cp, com) + com = [Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.CLOSEPOLY] - return path + path = Path(cp, com) + return path + _style_list["larrow"] = LArrow -class SawtoothBoxTransmuter(BboxTransmuterBase): - """ - A sawtooth box. - """ + class RArrow(LArrow): + """ + (right) Arrow Box + """ - def __init__(self, pad=0.3, tooth_size=None): - self.pad = pad - self.tooth_size = tooth_size - BboxTransmuterBase.__init__(self) + def __init__(self, pad=0.3): + self.pad = pad + super(BoxStyle.RArrow, self).__init__() - def _get_sawtooth_vertices(self, x0, y0, width, height, mutation_size): + def transmute(self, x0, y0, width, height, mutation_size): + p = BoxStyle.LArrow.transmute(self, x0, y0, + width, height, mutation_size) - # padding - pad = mutation_size * self.pad + p.vertices[:,0] = 2*x0 + width - p.vertices[:,0] - # size of sawtooth - if self.tooth_size is None: - tooth_size = self.pad * .5 * mutation_size - else: - tooth_size = self.tooth_size * mutation_size + return p - tooth_size2 = tooth_size / 2. - width, height = width + 2.*pad - tooth_size, \ - height + 2.*pad - tooth_size, + + _style_list["rarrow"] = RArrow - # the sizes of the vertical and horizontal sawtooth are - # separately adjusted to fit the given box size. - dsx_n = int(round((width - tooth_size) / (tooth_size * 2))) * 2 - dsx = (width - tooth_size) / dsx_n - dsy_n = int(round((height - tooth_size) / (tooth_size * 2))) * 2 - dsy = (height - tooth_size) / dsy_n + class Round(_Base): + """ + A box with round corners. + """ - x0, y0 = x0-pad+tooth_size2, y0-pad+tooth_size2 - x1, y1 = x0+width, y0 + height + def __init__(self, pad=0.3, rounding_size=None): + """ + *pad* + amount of padding + *rounding_size* + rounding radius of corners. *pad* if None + """ + self.pad = pad + self.rounding_size = rounding_size + super(BoxStyle.Round, self).__init__() - bottom_saw_x = [x0] + \ - [x0 + tooth_size2 + dsx*.5* i for i in range(dsx_n*2)] + \ - [x1 - tooth_size2] - bottom_saw_y = [y0] + \ - [y0 - tooth_size2, y0, y0 + tooth_size2, y0] * dsx_n + \ - [y0 - tooth_size2] + def transmute(self, x0, y0, width, height, mutation_size): - right_saw_x = [x1] + \ - [x1 + tooth_size2, x1, x1 - tooth_size2, x1] * dsx_n + \ - [x1 + tooth_size2] - right_saw_y = [y0] + \ - [y0 + tooth_size2 + dsy*.5* i for i in range(dsy_n*2)] + \ - [y1 - tooth_size2] + # padding + pad = mutation_size * self.pad - top_saw_x = [x1] + \ - [x1 - tooth_size2 - dsx*.5* i for i in range(dsx_n*2)] + \ - [x0 + tooth_size2] - top_saw_y = [y1] + \ - [y1 + tooth_size2, y1, y1 - tooth_size2, y1] * dsx_n + \ - [y1 + tooth_size2] + # size of the roudning corner + if self.rounding_size: + dr = mutation_size * self.rounding_size + else: + dr = pad - left_saw_x = [x0] + \ - [x0 - tooth_size2, x0, x0 + tooth_size2, x0] * dsy_n + \ - [x0 - tooth_size2] - left_saw_y = [y1] + \ - [y1 - tooth_size2 - dsy*.5* i for i in range(dsy_n*2)] + \ - [y0 + tooth_size2] + width, height = width + 2.*pad, \ + height + 2.*pad, - saw_vertices = zip(bottom_saw_x, bottom_saw_y) + \ - zip(right_saw_x, right_saw_y) + \ - zip(top_saw_x, top_saw_y) + \ - zip(left_saw_x, left_saw_y) + \ - [(bottom_saw_x[0], bottom_saw_y[0])] - return saw_vertices + x0, y0 = x0-pad, y0-pad, + x1, y1 = x0+width, y0 + height + # Round corners are implemented as quadratic bezier. eg. + # [(x0, y0-dr), (x0, y0), (x0+dr, y0)] for lower left corner. + cp = [(x0+dr, y0), + (x1-dr, y0), + (x1, y0), (x1, y0+dr), + (x1, y1-dr), + (x1, y1), (x1-dr, y1), + (x0+dr, y1), + (x0, y1), (x0, y1-dr), + (x0, y0+dr), + (x0, y0), (x0+dr, y0), + (x0+dr, y0)] - def transmute(self, x0, y0, width, height, mutation_size): + com = [Path.MOVETO, + Path.LINETO, + Path.CURVE3, Path.CURVE3, + Path.LINETO, + Path.CURVE3, Path.CURVE3, + Path.LINETO, + Path.CURVE3, Path.CURVE3, + Path.LINETO, + Path.CURVE3, Path.CURVE3, + Path.CLOSEPOLY] - saw_vertices = self._get_sawtooth_vertices(x0, y0, width, height, mutation_size) - path = Path(saw_vertices) - return path + path = Path(cp, com) + return path -class RoundtoothBoxTransmuter(SawtoothBoxTransmuter): - """ - A roundtooth(?) box. - """ + _style_list["round"] = Round - def transmute(self, x0, y0, width, height, mutation_size): - saw_vertices = self._get_sawtooth_vertices(x0, y0, width, height, mutation_size) + class Round4(_Base): + """ + Another box with round edges. + """ - cp = [Path.MOVETO] + ([Path.CURVE3, Path.CURVE3] * ((len(saw_vertices)-1)//2)) - path = Path(saw_vertices, cp) + def __init__(self, pad=0.3, rounding_size=None): + """ + *pad* + amount of padding - return path + *rounding_size* + rounding size of edges. *pad* if None + """ + + self.pad = pad + self.rounding_size = rounding_size + super(BoxStyle.Round4, self).__init__() + def transmute(self, x0, y0, width, height, mutation_size): -def _list_available_boxstyles(transmuters): - """ a helper function of the :class:`FancyBboxPatch` to list the available - box styles. It inspects the arguments of the __init__ methods of - each classes and report them - """ - import inspect - s = [] - for name, cls in transmuters.items(): - args, varargs, varkw, defaults = inspect.getargspec(cls.__init__) - args_string = ["%s=%s" % (argname, str(argdefault)) \ - for argname, argdefault in zip(args[1:], defaults)] - s.append(",".join([name]+args_string)) - return s + # padding + pad = mutation_size * self.pad + # roudning size. Use a half of the pad if not set. + if self.rounding_size: + dr = mutation_size * self.rounding_size + else: + dr = pad / 2. + width, height = width + 2.*pad - 2*dr, \ + height + 2.*pad - 2*dr, + x0, y0 = x0-pad+dr, y0-pad+dr, + x1, y1 = x0+width, y0 + height + + cp = [(x0, y0), + (x0+dr, y0-dr), (x1-dr, y0-dr), (x1, y0), + (x1+dr, y0+dr), (x1+dr, y1-dr), (x1, y1), + (x1-dr, y1+dr), (x0+dr, y1+dr), (x0, y1), + (x0-dr, y1-dr), (x0-dr, y0+dr), (x0, y0), + (x0, y0)] + + com = [Path.MOVETO, + Path.CURVE4, Path.CURVE4, Path.CURVE4, + Path.CURVE4, Path.CURVE4, Path.CURVE4, + Path.CURVE4, Path.CURVE4, Path.CURVE4, + Path.CURVE4, Path.CURVE4, Path.CURVE4, + Path.CLOSEPOLY] + + path = Path(cp, com) + + return path + + _style_list["round4"] = Round4 + + + class Sawtooth(_Base): + """ + A sawtooth box. + """ + + def __init__(self, pad=0.3, tooth_size=None): + """ + *pad* + amount of padding + + *tooth_size* + size of the sawtooth. pad* if None + """ + self.pad = pad + self.tooth_size = tooth_size + super(BoxStyle.Sawtooth, self).__init__() + + def _get_sawtooth_vertices(self, x0, y0, width, height, mutation_size): + + + # padding + pad = mutation_size * self.pad + + # size of sawtooth + if self.tooth_size is None: + tooth_size = self.pad * .5 * mutation_size + else: + tooth_size = self.tooth_size * mutation_size + + tooth_size2 = tooth_size / 2. + width, height = width + 2.*pad - tooth_size, \ + height + 2.*pad - tooth_size, + + # the sizes of the vertical and horizontal sawtooth are + # separately adjusted to fit the given box size. + dsx_n = int(round((width - tooth_size) / (tooth_size * 2))) * 2 + dsx = (width - tooth_size) / dsx_n + dsy_n = int(round((height - tooth_size) / (tooth_size * 2))) * 2 + dsy = (height - tooth_size) / dsy_n + + + x0, y0 = x0-pad+tooth_size2, y0-pad+tooth_size2 + x1, y1 = x0+width, y0 + height + + + bottom_saw_x = [x0] + \ + [x0 + tooth_size2 + dsx*.5* i for i in range(dsx_n*2)] + \ + [x1 - tooth_size2] + bottom_saw_y = [y0] + \ + [y0 - tooth_size2, y0, y0 + tooth_size2, y0] * dsx_n + \ + [y0 - tooth_size2] + + right_saw_x = [x1] + \ + [x1 + tooth_size2, x1, x1 - tooth_size2, x1] * dsx_n + \ + [x1 + tooth_size2] + right_saw_y = [y0] + \ + [y0 + tooth_size2 + dsy*.5* i for i in range(dsy_n*2)] + \ + [y1 - tooth_size2] + + top_saw_x = [x1] + \ + [x1 - tooth_size2 - dsx*.5* i for i in range(dsx_n*2)] + \ + [x0 + tooth_size2] + top_saw_y = [y1] + \ + [y1 + tooth_size2, y1, y1 - tooth_size2, y1] * dsx_n + \ + [y1 + tooth_size2] + + left_saw_x = [x0] + \ + [x0 - tooth_size2, x0, x0 + tooth_size2, x0] * dsy_n + \ + [x0 - tooth_size2] + left_saw_y = [y1] + \ + [y1 - tooth_size2 - dsy*.5* i for i in range(dsy_n*2)] + \ + [y0 + tooth_size2] + + saw_vertices = zip(bottom_saw_x, bottom_saw_y) + \ + zip(right_saw_x, right_saw_y) + \ + zip(top_saw_x, top_saw_y) + \ + zip(left_saw_x, left_saw_y) + \ + [(bottom_saw_x[0], bottom_saw_y[0])] + + return saw_v... [truncated message content] |
From: <as...@us...> - 2008-12-04 18:49:20
|
Revision: 6488 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6488&view=rev Author: astraw Date: 2008-12-04 18:49:16 +0000 (Thu, 04 Dec 2008) Log Message: ----------- git documentation: remove README.git and add to FAQ Modified Paths: -------------- trunk/matplotlib/doc/faq/installing_faq.rst Removed Paths: ------------- trunk/matplotlib/README.git Deleted: trunk/matplotlib/README.git =================================================================== --- trunk/matplotlib/README.git 2008-12-04 01:58:58 UTC (rev 6487) +++ trunk/matplotlib/README.git 2008-12-04 18:49:16 UTC (rev 6488) @@ -1,29 +0,0 @@ -There is an experimental `matplotlib github mirror`_ of the subversion -repository. To make a local clone it the directory ``mpl.git``, enter -the following commands. These instructions assume you already have a -github login (-- they use the personal gi...@gi... clone URL -instead of the git://github.com clone URL):: - - # This will create your copy in the mpl.git directory - git clone gi...@gi...:astraw/matplotlib.git mpl.git - cd mpl.git - git config --add remote.origin.fetch +refs/remotes/*:refs/remotes/* - git fetch - git svn init --trunk=trunk/matplotlib --tags=tags https://matplotlib.svn.sourceforge.net/svnroot/matplotlib - - # Now just get the latest svn revisions from the SourceForge SVN repository - git svn fetch -r 6300:HEAD - -.. _matplotlib github mirror: http://github.com/astraw/matplotlib - -To update your git repository with the latest svn updates from SourceForge:: - - git svn rebase - -To list what changes will be committed to svn:: - - git svn dcommit -n - -To commit your changes to svn:: - - git svn dcommit Modified: trunk/matplotlib/doc/faq/installing_faq.rst =================================================================== --- trunk/matplotlib/doc/faq/installing_faq.rst 2008-12-04 01:58:58 UTC (rev 6487) +++ trunk/matplotlib/doc/faq/installing_faq.rst 2008-12-04 18:49:16 UTC (rev 6488) @@ -106,8 +106,50 @@ > cd matplotlib > python setup.py install +Install from git +================ +There is an experimental `matplotlib github mirror`_ of the subversion +repository. To make a local clone it the directory ``mpl.git``, enter +the following commands:: + # This will create your copy in the mpl.git directory + git clone git://github.com/astraw/matplotlib.git mpl.git + cd mpl.git + git config --add remote.origin.fetch +refs/remotes/*:refs/remotes/* + git fetch + git svn init --trunk=trunk/matplotlib --tags=tags https://matplotlib.svn.sourceforge.net/svnroot/matplotlib + + # Now just get the latest svn revisions from the SourceForge SVN repository + git svn fetch -r 6300:HEAD + +.. _matplotlib github mirror: http://github.com/astraw/matplotlib + +To update your git repository with the latest svn updates from SourceForge:: + + git svn rebase + +To list what changes will be committed to svn:: + + git svn dcommit -n + +To commit your changes to svn:: + + git svn dcommit + +A note about git write access +----------------------------- + +The matplotlib developers need to figure out if there should be write +access to the git repository. This implies using the personal URL +(``gi...@gi...:astraw/matplotlib.git``) rather than the public URL +(``git://github.com/astraw/matplotlib.git``) for the +repository. However, doing so may make life complicated in the sense +that then there are two writeable matplotlib repositories, which must +be synced to prevent divergence. This is probably not an +insurmountable problem, but it is a problem that the developers should +reach a consensus about. Watch this space... + Backends ======== This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2008-12-05 00:06:31
|
Revision: 6494 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6494&view=rev Author: leejjoon Date: 2008-12-05 00:06:26 +0000 (Fri, 05 Dec 2008) Log Message: ----------- some minor changes for the legend Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/pylab_examples/legend_demo3.py trunk/matplotlib/lib/matplotlib/legend.py trunk/matplotlib/lib/matplotlib/offsetbox.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-12-04 22:13:57 UTC (rev 6493) +++ trunk/matplotlib/CHANGELOG 2008-12-05 00:06:26 UTC (rev 6494) @@ -1,3 +1,7 @@ +2008-12-04 Added fancybox keyword to legend. Also applied some changes + for better look, including baseline adjustment of the + multiline texts so that it is center aligned. -JJL + 2008-12-02 The transmuter classes in the patches.py are reorganized as subclasses of the Style classes. A few more box and arrow styles are added. -JJL Modified: trunk/matplotlib/examples/pylab_examples/legend_demo3.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/legend_demo3.py 2008-12-04 22:13:57 UTC (rev 6493) +++ trunk/matplotlib/examples/pylab_examples/legend_demo3.py 2008-12-05 00:06:26 UTC (rev 6494) @@ -2,6 +2,7 @@ import matplotlib.pyplot as plt import numpy as np +import pylab def myplot(ax): t1 = np.arange(0.0, 1.0, 0.1) @@ -21,7 +22,7 @@ ax3 = plt.subplot(3,1,3) myplot(ax3) -ax3.legend(loc=1, ncol=4, mode="expand", shadow=True) +ax3.legend(loc=1, ncol=4, mode="expand", fancybox=False, shadow=True) #title('Damped oscillation') Modified: trunk/matplotlib/lib/matplotlib/legend.py =================================================================== --- trunk/matplotlib/lib/matplotlib/legend.py 2008-12-04 22:13:57 UTC (rev 6493) +++ trunk/matplotlib/lib/matplotlib/legend.py 2008-12-05 00:06:26 UTC (rev 6494) @@ -113,6 +113,7 @@ ncol=1, # number of columns mode=None, # mode for horizontal distribution of columns. None, "expand" + fancybox=True, shadow = None, ): """ @@ -130,6 +131,7 @@ numpoints the number of points in the legend line prop the font property markerscale the relative size of legend markers vs. original + fancybox if True, draw a frame with a round fancybox. shadow if True, draw a shadow behind legend scatteryoffsets a list of yoffsets for scatter symbols in legend @@ -263,8 +265,11 @@ # The width and height of the legendPatch will be set (in the # draw()) to the length that includes the padding. Thus we set # pad=0 here. - self.legendPatch.set_boxstyle("round",pad=0, #self.borderpad, - rounding_size=0.2) + if fancybox == True: + self.legendPatch.set_boxstyle("round",pad=0, + rounding_size=0.2) + else: + self.legendPatch.set_boxstyle("square",pad=0) self._set_artist_props(self.legendPatch) @@ -378,7 +383,8 @@ labelboxes = [] for l in labels: - textbox = TextArea(l, textprops=label_prop) + textbox = TextArea(l, textprops=label_prop + multilinebaseline=True, minimumdescent=True) text_list.append(textbox._text) labelboxes.append(textbox) @@ -387,8 +393,8 @@ # The approximate height and descent of text. These values are # only used for plotting the legend handle. - height = self._approx_text_height() * 0.6 - descent = 0. #height/6. + height = self._approx_text_height() * 0.7 + descent = 0. # each handle needs to be drawn inside a box of # (x, y, w, h) = (0, -descent, width, height). @@ -440,9 +446,9 @@ legline._legmarker = legline_marker elif isinstance(handle, Patch): - p = Rectangle(xy=(0, -0.*descent), + p = Rectangle(xy=(0., 0.), width = self.handlelength*self.fontsize, - height=0.*descent+(height-descent)*.9, + height=(height-descent), ) p.update_from(handle) self._set_artist_props(p) @@ -513,12 +519,12 @@ num_smallcol = self._ncol-num_largecol # starting index of each column and number of rows in it. - largecol = zip(range(0, num_largecol*(nrows+1), (nrows+1)), - [nrows+1] * num_largecol) - smallcol = zip(range(num_largecol*(nrows+1), len(handleboxes), nrows), - [nrows] * num_smallcol) + largecol = safezip(range(0, num_largecol*(nrows+1), (nrows+1)), + [nrows+1] * num_largecol) + smallcol = safezip(range(num_largecol*(nrows+1), len(handleboxes), nrows), + [nrows] * num_smallcol) - handle_label = zip(handleboxes, labelboxes) + handle_label = safezip(handleboxes, labelboxes) columnbox = [] for i0, di in largecol+smallcol: # pack handleBox and labelBox into itemBox @@ -526,6 +532,8 @@ sep=self.handletextpad*self.fontsize, children=[h, t], align="baseline") for h, t in handle_label[i0:i0+di]] + # minimumdescent=False for the text of the last row of the column + itemBoxes[-1].get_children()[1].set_minimumdescent(False) # pack columnBox columnbox.append(VPacker(pad=0, Modified: trunk/matplotlib/lib/matplotlib/offsetbox.py =================================================================== --- trunk/matplotlib/lib/matplotlib/offsetbox.py 2008-12-04 22:13:57 UTC (rev 6493) +++ trunk/matplotlib/lib/matplotlib/offsetbox.py 2008-12-05 00:06:26 UTC (rev 6494) @@ -23,9 +23,9 @@ from matplotlib.patches import bbox_artist as mbbox_artist DEBUG=False # for debuging use -def bbox_artist(*kl, **kw): +def bbox_artist(*args, **kwargs): if DEBUG: - mbbox_artist(*kl, **kw) + mbbox_artist(*args, **kwargs) # _get_packed_offsets() and _get_aligned_offsets() are coded assuming @@ -122,9 +122,9 @@ The OffsetBox is a simple container artist. The child artist are meant to be drawn at a relative position to its parent. """ - def __init__(self, *kl, **kw): + def __init__(self, *args, **kwargs): - super(OffsetBox, self).__init__(*kl, **kw) + super(OffsetBox, self).__init__(*args, **kwargs) self._children = [] self._offset = (0, 0) @@ -441,10 +441,18 @@ - def __init__(self, s, textprops=None, **kw): + def __init__(self, s, + textprops=None, + multilinebaseline=None, + minimumdescent=True, + ): """ - *s* : a string to be displayer. - *trnaspose* : transformation matrrix + *s* : a string to be displayed. + *textprops* : property dictionary for the text + *multilinebaseline* : If True, baseline for multiline text is + adjusted so that it is (approximatedly) + center-aligned with singleline text. + *minimumdescent* : If True, the box has a minimum descent of "p". """ if textprops is None: textprops = {} @@ -462,9 +470,48 @@ self.offset_transform = mtransforms.Affine2D() self.offset_transform.clear() self.offset_transform.translate(0, 0) - self._text.set_transform(self.offset_transform) + self._baseline_transform = mtransforms.Affine2D() + self._text.set_transform(self.offset_transform+self._baseline_transform) + self._multilinebaseline = multilinebaseline + self._minimumdescent = minimumdescent + + def set_multilinebaseline(self, t): + """ + Set multilinebaseline . + + If True, baseline for multiline text is + adjusted so that it is (approximatedly) center-aligned with + singleline text. + """ + self._multilinebaseline = t + + + def get_multilinebaseline(self): + """ + get multilinebaseline . + """ + return self._multilinebaseline + + + def set_minimumdescent(self, t): + """ + Set minimumdescent . + + If True, extent of the single line text is adjusted so that + it has minimum descent of "p" + """ + self._minimumdescent = t + + + def get_minimumdescent(self): + """ + get minimumdescent. + """ + return self._minimumdescent + + def set_transform(self, t): """ set_transform is ignored. @@ -507,17 +554,34 @@ bbox, info = self._text._get_layout(renderer) w, h = bbox.width, bbox.height + line = info[0][0] # first line _, hh, dd = renderer.get_text_width_height_descent( line, self._text._fontproperties, ismath=ismath) - d = h-(hh-dd) # the baseline of the first line - # for multiple lines, h or d may greater than h_ or d_. - h_d = max(h_ - d_, h-d) - d = max(d, d_) - h = h_d + d + self._baseline_transform.clear() + if len(info) > 1 and self._multilinebaseline: # multi line + d = h-(hh-dd) # the baseline of the first line + d_new = 0.5 * h - 0.5 * (h_ - d_) + + self._baseline_transform.translate(0, d - d_new) + d = d_new + + else: # single line + + h_d = max(h_ - d_, h-dd) + + if self.get_minimumdescent(): + ## to have a minimum descent, #i.e., "l" and "p" have same + ## descents. + d = max(dd, d_) + else: + d = dd + + h = h_d + d + return w, h, 0., d This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2008-12-05 21:09:45
|
Revision: 6499 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6499&view=rev Author: leejjoon Date: 2008-12-05 21:09:42 +0000 (Fri, 05 Dec 2008) Log Message: ----------- Fixed a handlelegth bug in the legend class Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/legend.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-12-05 19:30:28 UTC (rev 6498) +++ trunk/matplotlib/CHANGELOG 2008-12-05 21:09:42 UTC (rev 6499) @@ -1,3 +1,6 @@ +2008-12-05 Fixed a bug that the handlelength of the new legend class + set too short when numpoints=1 -JJL + 2008-12-04 Added support for data with units (e.g. dates) to Axes.fill_between. -RM Modified: trunk/matplotlib/lib/matplotlib/legend.py =================================================================== --- trunk/matplotlib/lib/matplotlib/legend.py 2008-12-05 19:30:28 UTC (rev 6498) +++ trunk/matplotlib/lib/matplotlib/legend.py 2008-12-05 21:09:42 UTC (rev 6499) @@ -418,7 +418,7 @@ npoints) xdata_marker = xdata elif npoints == 1: - xdata = np.linspace(0, self.handlelength, 2) + xdata = np.linspace(0, self.handlelength*self.fontsize, 2) xdata_marker = [0.5*self.handlelength*self.fontsize] if isinstance(handle, Line2D): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2008-12-06 23:17:16
|
Revision: 6502 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6502&view=rev Author: leejjoon Date: 2008-12-06 23:17:10 +0000 (Sat, 06 Dec 2008) Log Message: ----------- Fixed a small bug in svg backend Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/backends/backend_svg.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-12-06 14:36:35 UTC (rev 6501) +++ trunk/matplotlib/CHANGELOG 2008-12-06 23:17:10 UTC (rev 6502) @@ -1,3 +1,6 @@ +2008-12-06 Fixed a bug in svg backend that new_figure_manager() + ignores keywords arguments such as figsize, etc. -JJL + 2008-12-05 Fixed a bug that the handlelength of the new legend class set too short when numpoints=1 -JJL Modified: trunk/matplotlib/lib/matplotlib/backends/backend_svg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2008-12-06 14:36:35 UTC (rev 6501) +++ trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2008-12-06 23:17:10 UTC (rev 6502) @@ -27,7 +27,7 @@ def new_figure_manager(num, *args, **kwargs): FigureClass = kwargs.pop('FigureClass', Figure) - thisFig = FigureClass(*args) + thisFig = FigureClass(*args, **kwargs) canvas = FigureCanvasSVG(thisFig) manager = FigureManagerSVG(canvas, num) return manager This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2008-12-07 20:40:17
|
Revision: 6503 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6503&view=rev Author: leejjoon Date: 2008-12-07 20:40:12 +0000 (Sun, 07 Dec 2008) Log Message: ----------- drop "new" keyword of np.histogram() for numpy 1.2 or later Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-12-06 23:17:10 UTC (rev 6502) +++ trunk/matplotlib/CHANGELOG 2008-12-07 20:40:12 UTC (rev 6503) @@ -1,3 +1,6 @@ +2008-12-07 drop the deprecated "new" keyword of np.histogram() for + numpy 1.2 or later. -JJL + 2008-12-06 Fixed a bug in svg backend that new_figure_manager() ignores keywords arguments such as figsize, etc. -JJL Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-12-06 23:17:10 UTC (rev 6502) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-12-07 20:40:12 UTC (rev 6503) @@ -6550,12 +6550,20 @@ # case do not autoscale axes. binsgiven = (cbook.iterable(bins) or range != None) + # check the version of the numpy + np_version = float(".".join(np.__version__.split(".")[:2])) + if np_version < 1.2: # version 1.1 + hist_kwargs = dict(range=range, + normed=bool(normed), new=True) + else: # version 1.2 and later, drop new=True + hist_kwargs = dict(range=range, + normed=bool(normed)) + n = [] for i in xrange(len(x)): # this will automatically overwrite bins, # so that each histogram uses the same bins - m, bins = np.histogram(x[i], bins, range=range, - normed=bool(normed), new=True) + m, bins = np.histogram(x[i], bins, **hist_kwargs) n.append(m) if cumulative: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-12-08 15:30:58
|
Revision: 6511 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6511&view=rev Author: jdh2358 Date: 2008-12-08 15:30:56 +0000 (Mon, 08 Dec 2008) Log Message: ----------- added rc param to control legend fancybox Modified Paths: -------------- trunk/matplotlib/examples/pylab_examples/legend_demo.py trunk/matplotlib/examples/pylab_examples/legend_demo3.py trunk/matplotlib/lib/matplotlib/legend.py trunk/matplotlib/lib/matplotlib/rcsetup.py trunk/matplotlib/matplotlibrc.template Modified: trunk/matplotlib/examples/pylab_examples/legend_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/legend_demo.py 2008-12-08 15:10:20 UTC (rev 6510) +++ trunk/matplotlib/examples/pylab_examples/legend_demo.py 2008-12-08 15:30:56 UTC (rev 6511) @@ -15,7 +15,7 @@ ax = plt.subplot(111) plt.plot(a,c,'k--',a,d,'k:',a,c+d,'k') plt.legend(('Model length', 'Data length', 'Total message length'), - 'upper center', shadow=True) + 'upper center', shadow=True, fancybox=True) plt.ylim([-1,20]) plt.grid(False) plt.xlabel('Model complexity --->') Modified: trunk/matplotlib/examples/pylab_examples/legend_demo3.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/legend_demo3.py 2008-12-08 15:10:20 UTC (rev 6510) +++ trunk/matplotlib/examples/pylab_examples/legend_demo3.py 2008-12-08 15:30:56 UTC (rev 6511) @@ -1,5 +1,6 @@ #!/usr/bin/env python - +import matplotlib +matplotlib.rcParams['legend.fancybox'] = True import matplotlib.pyplot as plt import numpy as np import pylab @@ -22,7 +23,7 @@ ax3 = plt.subplot(3,1,3) myplot(ax3) -ax3.legend(loc=1, ncol=4, mode="expand", fancybox=False, shadow=True) +ax3.legend(loc=1, ncol=4, mode="expand", shadow=True) #title('Damped oscillation') Modified: trunk/matplotlib/lib/matplotlib/legend.py =================================================================== --- trunk/matplotlib/lib/matplotlib/legend.py 2008-12-08 15:10:20 UTC (rev 6510) +++ trunk/matplotlib/lib/matplotlib/legend.py 2008-12-08 15:30:56 UTC (rev 6511) @@ -63,7 +63,7 @@ loc can be a tuple of the noramilzed coordinate values with respect its parent. - + Return value is a sequence of text, line instances that make up the legend """ @@ -94,15 +94,15 @@ scatterpoints = 3, # TODO: may be an rcParam scatteryoffsets=None, prop = None, # properties for the legend texts - + # the following dimensions are in axes coords pad = None, # deprecated; use borderpad - labelsep = None, # deprecated; use labelspacing - handlelen = None, # deprecated; use handlelength - handletextsep = None, # deprecated; use handletextpad + labelsep = None, # deprecated; use labelspacing + handlelen = None, # deprecated; use handlelength + handletextsep = None, # deprecated; use handletextpad axespad = None, # deprecated; use borderaxespad - # spacing & pad defined as a fractionof the font-size + # spacing & pad defined as a fractionof the font-size borderpad = None, # the whitespace inside the legend border labelspacing=None, #the vertical space between the legend entries handlelength=None, # the length of the legend handles @@ -113,7 +113,7 @@ ncol=1, # number of columns mode=None, # mode for horizontal distribution of columns. None, "expand" - fancybox=True, + fancybox=None, # True use a fancy box, false use a rounded box, none use rc shadow = None, ): """ @@ -131,7 +131,7 @@ numpoints the number of points in the legend line prop the font property markerscale the relative size of legend markers vs. original - fancybox if True, draw a frame with a round fancybox. + fancybox if True, draw a frame with a round fancybox. If None, use rc shadow if True, draw a shadow behind legend scatteryoffsets a list of yoffsets for scatter symbols in legend @@ -144,7 +144,7 @@ The dimensions of pad and spacing are given as a fraction of the fontsize. Values from rcParams will be used if None. - + """ from matplotlib.axes import Axes # local import only to avoid circularity from matplotlib.figure import Figure # local import only to avoid circularity @@ -172,7 +172,7 @@ # Take care the deprecated keywords deprecated_kwds = {"pad":"borderpad", "labelsep":"labelspacing", - "handlelen":"handlelength", + "handlelen":"handlelength", "handletextsep":"handletextpad", "axespad":"borderaxespad"} @@ -182,7 +182,7 @@ # conversion factor bbox = parent.bbox axessize_fontsize = min(bbox.width, bbox.height)/self.fontsize - + for k, v in deprecated_kwds.items(): # use deprecated value if not None and if their newer # counter part is None. @@ -199,7 +199,7 @@ setattr(self, v, localdict[v]) del localdict - + self._ncol = ncol if self.numpoints <= 0: @@ -265,6 +265,9 @@ # The width and height of the legendPatch will be set (in the # draw()) to the length that includes the padding. Thus we set # pad=0 here. + if fancybox is None: + fancybox = rcParams["legend.fancybox"] + if fancybox == True: self.legendPatch.set_boxstyle("round",pad=0, rounding_size=0.2) @@ -318,7 +321,7 @@ # find_offset function will be provided to _legend_box and # _legend_box will draw itself at the location of the return - # value of the find_offset. + # value of the find_offset. if self._loc == 0: self._legend_box.set_offset(self._findoffset_best) else: @@ -339,7 +342,7 @@ if self.shadow: shadow = Shadow(self.legendPatch, 2, -2) shadow.draw(renderer) - + self.legendPatch.draw(renderer) self._legend_box.draw(renderer) @@ -360,7 +363,7 @@ Initiallize the legend_box. The legend_box is an instance of the OffsetBox, which is packed with legend handles and texts. Once packed, their location is calculated during the - drawing time. + drawing time. """ # legend_box is a HPacker, horizontally packed with @@ -371,7 +374,7 @@ # is an instance of offsetbox.TextArea which contains legend # text. - + text_list = [] # the list of text instances handle_list = [] # the list of text instances @@ -394,12 +397,12 @@ # The approximate height and descent of text. These values are # only used for plotting the legend handle. height = self._approx_text_height() * 0.7 - descent = 0. + descent = 0. # each handle needs to be drawn inside a box of # (x, y, w, h) = (0, -descent, width, height). # And their corrdinates should be given in the display coordinates. - + # The transformation of each handle will be automatically set # to self.get_trasnform(). If the artist does not uses its # default trasnform (eg, Collections), you need to @@ -413,7 +416,7 @@ if npoints > 1: # we put some pad here to compensate the size of the # marker - xdata = np.linspace(0.3*self.fontsize, + xdata = np.linspace(0.3*self.fontsize, (self.handlelength-0.3)*self.fontsize, npoints) xdata_marker = xdata @@ -484,14 +487,14 @@ size_min] else: sizes = (size_max-size_min)*np.linspace(0,1,self.scatterpoints)+size_min - + p = type(handle)(handle.get_numsides(), rotation=handle.get_rotation(), sizes=sizes, offsets=zip(xdata_marker,ydata), transOffset=self.get_transform(), ) - + p.update_from(handle) p.set_figure(self.figure) p.set_clip_box(None) @@ -534,7 +537,7 @@ for h, t in handle_label[i0:i0+di]] # minimumdescent=False for the text of the last row of the column itemBoxes[-1].get_children()[1].set_minimumdescent(False) - + # pack columnBox columnbox.append(VPacker(pad=0, sep=self.labelspacing*self.fontsize, @@ -547,7 +550,7 @@ mode = "fixed" sep = self.columnspacing*self.fontsize - + self._legend_box = HPacker(pad=self.borderpad*self.fontsize, sep=sep, align="baseline", mode=mode, @@ -555,8 +558,8 @@ self.texts = text_list self.legendHandles = handle_list - + def _auto_legend_data(self): """ Returns list of vertices and extents covered by the plot. @@ -655,12 +658,12 @@ LC:"S", UC:"N", C:"C"} - + c = anchor_coefs[loc] container = parentbbox.padded(-(self.borderaxespad) * self.fontsize) anchored_box = bbox.anchored(c, container=container) - return anchored_box.x0, anchored_box.y0 + return anchored_box.x0, anchored_box.y0 def _find_best_position(self, width, height, consider=None): Modified: trunk/matplotlib/lib/matplotlib/rcsetup.py =================================================================== --- trunk/matplotlib/lib/matplotlib/rcsetup.py 2008-12-08 15:10:20 UTC (rev 6510) +++ trunk/matplotlib/lib/matplotlib/rcsetup.py 2008-12-08 15:30:56 UTC (rev 6511) @@ -417,6 +417,7 @@ 'polaraxes.grid' : [True, validate_bool], # display polar grid or not #legend properties + 'legend.fancybox' : [False,validate_bool], 'legend.loc' : ['upper right',validate_legend_loc], # at some point, this should be changed to 'best' 'legend.isaxes' : [True,validate_bool], # this option is internally ignored - it never served any useful purpose 'legend.numpoints' : [2, validate_int], # the number of points in the legend line Modified: trunk/matplotlib/matplotlibrc.template =================================================================== --- trunk/matplotlib/matplotlibrc.template 2008-12-08 15:10:20 UTC (rev 6510) +++ trunk/matplotlib/matplotlibrc.template 2008-12-08 15:30:56 UTC (rev 6511) @@ -235,6 +235,8 @@ #grid.linewidth : 0.5 # in points ### Legend +#legend.fancybox : False # if True, use a rounded box for the + # legend, else a rectangle #legend.isaxes : True #legend.numpoints : 2 # the number of points in the legend line #legend.fontsize : large This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |