You can subscribe to this list here.
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(115) |
Aug
(120) |
Sep
(137) |
Oct
(170) |
Nov
(461) |
Dec
(263) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2008 |
Jan
(120) |
Feb
(74) |
Mar
(35) |
Apr
(74) |
May
(245) |
Jun
(356) |
Jul
(240) |
Aug
(115) |
Sep
(78) |
Oct
(225) |
Nov
(98) |
Dec
(271) |
2009 |
Jan
(132) |
Feb
(84) |
Mar
(74) |
Apr
(56) |
May
(90) |
Jun
(79) |
Jul
(83) |
Aug
(296) |
Sep
(214) |
Oct
(76) |
Nov
(82) |
Dec
(66) |
2010 |
Jan
(46) |
Feb
(58) |
Mar
(51) |
Apr
(77) |
May
(58) |
Jun
(126) |
Jul
(128) |
Aug
(64) |
Sep
(50) |
Oct
(44) |
Nov
(48) |
Dec
(54) |
2011 |
Jan
(68) |
Feb
(52) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
|
|
|
|
1
(2) |
2
(2) |
3
(2) |
4
|
5
(2) |
6
(4) |
7
|
8
|
9
|
10
|
11
|
12
|
13
(1) |
14
(2) |
15
(3) |
16
(7) |
17
(1) |
18
(1) |
19
(3) |
20
(16) |
21
(3) |
22
(4) |
23
(2) |
24
|
25
|
26
(6) |
27
(3) |
28
(9) |
29
(2) |
30
(2) |
|
Revision: 8241 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8241&view=rev Author: efiring Date: 2010年04月18日 23:11:24 +0000 (2010年4月18日) Log Message: ----------- Improve access to ScalarFormatter useOffset and offset parameters Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/boilerplate.py trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/pyplot.py trunk/matplotlib/lib/matplotlib/ticker.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010年04月17日 13:45:13 UTC (rev 8240) +++ trunk/matplotlib/CHANGELOG 2010年04月18日 23:11:24 UTC (rev 8241) @@ -1,3 +1,6 @@ +2010年04月18日 Control ScalarFormatter offsets directly and via the + Axes.ticklabel_format() method, and add that to pyplot. -EF + 2010年04月16日 Add a close_event to the backends. -RM 2010年04月06日 modify axes_grid examples to use axes_grid1 and axisartist. -JJL Modified: trunk/matplotlib/boilerplate.py =================================================================== --- trunk/matplotlib/boilerplate.py 2010年04月17日 13:45:13 UTC (rev 8240) +++ trunk/matplotlib/boilerplate.py 2010年04月18日 23:11:24 UTC (rev 8241) @@ -101,6 +101,7 @@ 'table', 'text', 'annotate', + 'ticklabel_format', ) cmappable = { Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010年04月17日 13:45:13 UTC (rev 8240) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010年04月18日 23:11:24 UTC (rev 8241) @@ -1880,6 +1880,11 @@ be used for numbers outside the range 10`-m`:sup: to 10`n`:sup:. Use (0,0) to include all numbers. + *useOffset* [True | False | offset]; if True, + the offset will be calculated as needed; + if False, no offset will be used; if a + numeric offset is specified, it will be + used. *axis* [ 'x' | 'y' | 'both' ] ============ ===================================== @@ -1892,13 +1897,14 @@ """ style = kwargs.pop('style', '').lower() scilimits = kwargs.pop('scilimits', None) + useOffset = kwargs.pop('useOffset', None) + axis = kwargs.pop('axis', 'both').lower() if scilimits is not None: try: m, n = scilimits m+n+1 # check that both are numbers except (ValueError, TypeError): raise ValueError("scilimits must be a sequence of 2 integers") - axis = kwargs.pop('axis', 'both').lower() if style[:3] == 'sci': sb = True elif style in ['plain', 'comma']: @@ -1923,6 +1929,11 @@ self.xaxis.major.formatter.set_powerlimits(scilimits) if axis == 'both' or axis == 'y': self.yaxis.major.formatter.set_powerlimits(scilimits) + if useOffset is not None: + if axis == 'both' or axis == 'x': + self.xaxis.major.formatter.set_useOffset(useOffset) + if axis == 'both' or axis == 'y': + self.yaxis.major.formatter.set_useOffset(useOffset) except AttributeError: raise AttributeError( "This method only works with the ScalarFormatter.") Modified: trunk/matplotlib/lib/matplotlib/pyplot.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pyplot.py 2010年04月17日 13:45:13 UTC (rev 8240) +++ trunk/matplotlib/lib/matplotlib/pyplot.py 2010年04月18日 23:11:24 UTC (rev 8241) @@ -2529,6 +2529,14 @@ # This function was autogenerated by boilerplate.py. Do not edit as # changes will be lost +...@do...py_dedent(Axes.ticklabel_format) +def ticklabel_format(**kwargs): + ret = gca().ticklabel_format(**kwargs) + draw_if_interactive() + return ret + +# This function was autogenerated by boilerplate.py. Do not edit as +# changes will be lost def autumn(): ''' set the default colormap to autumn and apply to current image if any. Modified: trunk/matplotlib/lib/matplotlib/ticker.py =================================================================== --- trunk/matplotlib/lib/matplotlib/ticker.py 2010年04月17日 13:45:13 UTC (rev 8240) +++ trunk/matplotlib/lib/matplotlib/ticker.py 2010年04月18日 23:11:24 UTC (rev 8241) @@ -321,22 +321,34 @@ data < 10^-n or data >= 10^m, where n and m are the power limits set using set_powerlimits((n,m)). The defaults for these are controlled by the axes.formatter.limits rc parameter. + """ def __init__(self, useOffset=True, useMathText=False): # useOffset allows plotting small data ranges with large offsets: # for example: [1+1e-9,1+2e-9,1+3e-9] # useMathText will render the offset and scientific notation in mathtext - self._useOffset = useOffset + self.set_useOffset(useOffset) self._usetex = rcParams['text.usetex'] self._useMathText = useMathText - self.offset = 0 self.orderOfMagnitude = 0 self.format = '' self._scientific = True self._powerlimits = rcParams['axes.formatter.limits'] + def get_useOffset(self): + return self._useOffset + def set_useOffset(self, val): + if val in [True, False]: + self.offset = 0 + self._useOffset = val + else: + self._useOffset = False + self.offset = val + + useOffset = property(fget=get_useOffset, fset=set_useOffset) + def fix_minus(self, s): 'use a unicode minus rather than hyphen' if rcParams['text.usetex'] or not rcParams['axes.unicode_minus']: return s @@ -412,7 +424,8 @@ if len(self.locs) > 0: vmin, vmax = self.axis.get_view_interval() d = abs(vmax-vmin) - if self._useOffset: self._set_offset(d) + if self._useOffset: + self._set_offset(d) self._set_orderOfMagnitude(d) self._set_format() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8240 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8240&view=rev Author: mdehoon Date: 2010年04月17日 13:45:13 +0000 (2010年4月17日) Log Message: ----------- Fixing bug #2891502 by allowing window sizes larger than the screen. Modified Paths: -------------- trunk/matplotlib/src/_macosx.m Modified: trunk/matplotlib/src/_macosx.m =================================================================== --- trunk/matplotlib/src/_macosx.m 2010年04月16日 19:02:22 UTC (rev 8239) +++ trunk/matplotlib/src/_macosx.m 2010年04月17日 13:45:13 UTC (rev 8240) @@ -320,6 +320,7 @@ { PyObject* manager; } - (Window*)initWithContentRect:(NSRect)rect styleMask:(unsigned int)mask backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation withManager: (PyObject*)theManager; +- (NSRect)constrainFrameRect:(NSRect)rect toScreen:(NSScreen*)screen; - (BOOL)closeButtonPressed; - (void)close; - (void)dealloc; @@ -4396,6 +4397,16 @@ return self; } +- (NSRect)constrainFrameRect:(NSRect)rect toScreen:(NSScreen*)screen +{ + /* Allow window sizes larger than the screen */ + NSRect suggested = [super constrainFrameRect: rect toScreen: screen]; + const CGFloat difference = rect.size.height - suggested.size.height; + suggested.origin.y -= difference; + suggested.size.height += difference; + return suggested; +} + - (BOOL)closeButtonPressed { PyObject* result; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8239 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8239&view=rev Author: ryanmay Date: 2010年04月16日 19:02:22 +0000 (2010年4月16日) Log Message: ----------- Remove unused import. Modified Paths: -------------- trunk/matplotlib/examples/animation/strip_chart_demo.py Modified: trunk/matplotlib/examples/animation/strip_chart_demo.py =================================================================== --- trunk/matplotlib/examples/animation/strip_chart_demo.py 2010年04月16日 19:01:30 UTC (rev 8238) +++ trunk/matplotlib/examples/animation/strip_chart_demo.py 2010年04月16日 19:02:22 UTC (rev 8239) @@ -9,7 +9,7 @@ different GUI that supports animation (GTKAgg, TkAgg, WXAgg) and use your toolkits idle/timer functions. """ -import gobject, gtk +import gobject import matplotlib matplotlib.use('GTKAgg') import numpy as np This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8238 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8238&view=rev Author: ryanmay Date: 2010年04月16日 19:01:30 +0000 (2010年4月16日) Log Message: ----------- Add basic example/test for close_event. Added Paths: ----------- trunk/matplotlib/examples/event_handling/close_event.py Added: trunk/matplotlib/examples/event_handling/close_event.py =================================================================== --- trunk/matplotlib/examples/event_handling/close_event.py (rev 0) +++ trunk/matplotlib/examples/event_handling/close_event.py 2010年04月16日 19:01:30 UTC (rev 8238) @@ -0,0 +1,10 @@ +import matplotlib.pyplot as plt + +def handle_close(evt): + print 'Closed Figure!' + +fig = plt.figure() +fig.canvas.mpl_connect('close_event', handle_close) + +plt.text(0.35, 0.5, 'Close Me!', dict(size=30)) +plt.show() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8237 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8237&view=rev Author: ryanmay Date: 2010年04月16日 19:00:55 +0000 (2010年4月16日) Log Message: ----------- Add the appropriate code to each of the backends to call close_event() so that the events are properly dispatched. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py trunk/matplotlib/lib/matplotlib/backends/backend_wx.py Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2010年04月16日 18:37:44 UTC (rev 8236) +++ trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2010年04月16日 19:00:55 UTC (rev 8237) @@ -186,6 +186,7 @@ def destroy(self): #gtk.DrawingArea.destroy(self) + self.close_event() gobject.source_remove(self._idle_event_id) if self._idle_draw_id != 0: gobject.source_remove(self._idle_draw_id) Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2010年04月16日 18:37:44 UTC (rev 8236) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2010年04月16日 19:00:55 UTC (rev 8237) @@ -104,6 +104,9 @@ w,h = self.get_width_height() self.resize( w, h ) + QtCore.QObject.connect(self, QtCore.SIGNAL('destroyed()'), + self.close_event) + def __timerEvent(self, event): # hide until we can test and fix self.mpl_idle_event(event) Modified: trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2010年04月16日 18:37:44 UTC (rev 8236) +++ trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2010年04月16日 19:00:55 UTC (rev 8237) @@ -177,6 +177,13 @@ root = self._tkcanvas.winfo_toplevel() root.bind("<MouseWheel>", self.scroll_event_windows) + # Can't get destroy events by binding ot _tkcanvas. Therefore, bind + # to the window and filter. + def filter_destroy(evt): + if evt.widget is self._tkcanvas: + self.close_event() + root.bind("<Destroy>", filter_destroy) + self._master = master self._tkcanvas.focus_set() @@ -765,4 +772,3 @@ FigureManager = FigureManagerTkAgg - Modified: trunk/matplotlib/lib/matplotlib/backends/backend_wx.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2010年04月16日 18:37:44 UTC (rev 8236) +++ trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2010年04月16日 19:00:55 UTC (rev 8237) @@ -1476,6 +1476,7 @@ def _onClose(self, evt): DEBUG_MSG("onClose()", 1, self) + self.canvas.close_event() self.canvas.stop_event_loop() Gcf.destroy(self.num) #self.Destroy() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8236 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8236&view=rev Author: ryanmay Date: 2010年04月16日 18:37:44 +0000 (2010年4月16日) Log Message: ----------- Remove debug output. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backend_bases.py Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2010年04月16日 18:32:53 UTC (rev 8235) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2010年04月16日 18:37:44 UTC (rev 8236) @@ -1,3 +1,4 @@ + """ Abstract base classes define the primitives that renderers and graphics contexts must implement to serve as a matplotlib backend @@ -928,7 +929,6 @@ """ def __init__(self, name, canvas, guiEvent=None): Event.__init__(self, name, canvas, guiEvent) - print 'Initing CloseEvent' class LocationEvent(Event): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8235 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8235&view=rev Author: ryanmay Date: 2010年04月16日 18:32:53 +0000 (2010年4月16日) Log Message: ----------- Add a generic close event that notifies when the figure has been closed. Useful for disable other thing like timers when figure is closed. Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/backend_bases.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010年04月16日 14:28:06 UTC (rev 8234) +++ trunk/matplotlib/CHANGELOG 2010年04月16日 18:32:53 UTC (rev 8235) @@ -1,3 +1,5 @@ +2010年04月16日 Add a close_event to the backends. -RM + 2010年04月06日 modify axes_grid examples to use axes_grid1 and axisartist. -JJL 2010年04月06日 rebase axes_grid using axes_grid1 and axisartist modules. -JJL @@ -2,3 +4,3 @@ -2010年04月06日 axes_grid toolkit is splitted into two separate modules, +2010年04月06日 axes_grid toolkit is splitted into two separate modules, axes_grid1 and axisartist. -JJL Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2010年04月16日 14:28:06 UTC (rev 8234) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2010年04月16日 18:32:53 UTC (rev 8235) @@ -920,6 +920,16 @@ Event.__init__(self, name, canvas) self.width, self.height = canvas.get_width_height() +class CloseEvent(Event): + """ + An event triggered by a figure being closed + + In addition to the :class:`Event` attributes, the following event attributes are defined: + """ + def __init__(self, name, canvas, guiEvent=None): + Event.__init__(self, name, canvas, guiEvent) + print 'Initing CloseEvent' + class LocationEvent(Event): """ A event that has a screen location @@ -1157,7 +1167,8 @@ 'figure_enter_event', 'figure_leave_event', 'axes_enter_event', - 'axes_leave_event' + 'axes_leave_event', + 'close_event' ] @@ -1293,6 +1304,15 @@ event = ResizeEvent(s, self) self.callbacks.process(s, event) + def close_event(self, guiEvent=None): + """ + This method will be called by all functions connected to the + 'close_event' with a :class:`CloseEvent` + """ + s = 'close_event' + event = CloseEvent(s, self, guiEvent=guiEvent) + self.callbacks.process(s, event) + def key_press_event(self, key, guiEvent=None): """ This method will be call all functions connected to the @@ -1742,6 +1762,7 @@ - 'figure_leave_event', - 'axes_enter_event', - 'axes_leave_event' + - 'close_event' For the location events (button and key press/release), if the mouse is over the axes, the variable ``event.inaxes`` will be This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8234 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8234&view=rev Author: mdboom Date: 2010年04月16日 14:28:06 +0000 (2010年4月16日) Log Message: ----------- Updating mathtext tests with fixed baselines. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext.png trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext_stix.png trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext_stixsans.png Modified: trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext.png =================================================================== (Binary files differ) Modified: trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext_stix.png =================================================================== (Binary files differ) Modified: trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext_stixsans.png =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8233 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8233&view=rev Author: mdboom Date: 2010年04月16日 13:20:19 +0000 (2010年4月16日) Log Message: ----------- Eliminate wiggly baseline compensation. Seems to work without it now -- have no idea why it was needed before. Modified Paths: -------------- trunk/matplotlib/src/ft2font.cpp Modified: trunk/matplotlib/src/ft2font.cpp =================================================================== --- trunk/matplotlib/src/ft2font.cpp 2010年04月15日 07:30:44 UTC (rev 8232) +++ trunk/matplotlib/src/ft2font.cpp 2010年04月16日 13:20:19 UTC (rev 8233) @@ -1329,8 +1329,8 @@ long x = (long)xd; long y = (long)yd; FT_Vector sub_offset; - sub_offset.x = int(-(xd - (double)x) * 64.0); - sub_offset.y = int(-(yd - (double)y) * 64.0); + sub_offset.x = 0; // int((xd - (double)x) * 64.0); + sub_offset.y = 0; // int((yd - (double)y) * 64.0); if (!Glyph::check(args[3].ptr())) throw Py::TypeError("Usage: draw_glyph_to_bitmap(bitmap, x,y,glyph)"); @@ -1853,7 +1853,7 @@ add_keyword_method("load_char", &FT2Font::load_char, FT2Font::load_char__doc__); add_keyword_method("load_glyph", &FT2Font::load_glyph, - FT2Font::load_glyph__doc__); + FT2Font::load_glyph__doc__); add_keyword_method("set_text", &FT2Font::set_text, FT2Font::set_text__doc__); add_varargs_method("set_size", &FT2Font::set_size, @@ -1861,7 +1861,7 @@ add_varargs_method("set_charmap", &FT2Font::set_charmap, FT2Font::set_charmap__doc__); add_varargs_method("select_charmap", &FT2Font::select_charmap, - FT2Font::select_charmap__doc__); + FT2Font::select_charmap__doc__); add_varargs_method("get_width_height", &FT2Font::get_width_height, FT2Font::get_width_height__doc__); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8232 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8232&view=rev Author: efiring Date: 2010年04月15日 07:30:44 +0000 (2010年4月15日) Log Message: ----------- contour: refactoring by Ian Thomas to facilitate new tricontour functionality Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/contour.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010年04月15日 07:17:42 UTC (rev 8231) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010年04月15日 07:30:44 UTC (rev 8232) @@ -6896,14 +6896,14 @@ def contour(self, *args, **kwargs): if not self._hold: self.cla() kwargs['filled'] = False - return mcontour.ContourSet(self, *args, **kwargs) - contour.__doc__ = mcontour.ContourSet.contour_doc + return mcontour.QuadContourSet(self, *args, **kwargs) + contour.__doc__ = mcontour.QuadContourSet.contour_doc def contourf(self, *args, **kwargs): if not self._hold: self.cla() kwargs['filled'] = True - return mcontour.ContourSet(self, *args, **kwargs) - contourf.__doc__ = mcontour.ContourSet.contour_doc + return mcontour.QuadContourSet(self, *args, **kwargs) + contourf.__doc__ = mcontour.QuadContourSet.contour_doc def clabel(self, CS, *args, **kwargs): return CS.clabel(*args, **kwargs) Modified: trunk/matplotlib/lib/matplotlib/contour.py =================================================================== --- trunk/matplotlib/lib/matplotlib/contour.py 2010年04月15日 07:17:42 UTC (rev 8231) +++ trunk/matplotlib/lib/matplotlib/contour.py 2010年04月15日 07:30:44 UTC (rev 8232) @@ -577,7 +577,7 @@ class ContourSet(cm.ScalarMappable, ContourLabeler): """ - Create and store a set of contour lines or filled regions. + Store a set of contour lines or filled regions. User-callable method: clabel @@ -592,17 +592,49 @@ same as levels for line contours; half-way between levels for filled contours. See _process_colors method. """ - - def __init__(self, ax, *args, **kwargs): """ Draw contour lines or filled regions, depending on whether keyword arg 'filled' is False (default) or True. - The first argument of the initializer must be an axes - object. The remaining arguments and keyword arguments - are described in ContourSet.contour_doc. + The first three arguments must be: + *ax*: axes object. + + *levels*: [level0, level1, ..., leveln] + A list of floating point numbers indicating the contour + levels. + + *allsegs*: [level0segs, level1segs, ...] + List of all the polygon segments for all the *levels*. + For contour lines len(allsegs) == len(levels), and for + filled contour regions len(allsegs) = len(levels)-1. + + level0segs = [polygon0, polygon1, ...] + + polygon0 = array_like [[x0,y0], [x1,y1], ...] + + *allkinds*: None or [level0kinds, level1kinds, ...] + Optional list of all the polygon vertex kinds (code types), as + described and used in Path. This is used to allow multiply- + connected paths such as holes within filled polygons. + If not None, len(allkinds) == len(allsegs). + + level0kinds = [polygon0kinds, ...] + + polygon0kinds = [vertexcode0, vertexcode1, ...] + + If allkinds is not None, usually all polygons for a particular + contour level are grouped together so that + + level0segs = [polygon0] and level0kinds = [polygon0kinds]. + + Keyword arguments are as described in + :class:`~matplotlib.contour.QuadContourSet` object. + + **Examples:** + + .. plot:: mpl_examples/misc/contour_manual.py """ self.ax = ax self.levels = kwargs.get('levels', None) @@ -638,24 +670,7 @@ raise ValueError('Either colors or cmap must be None') if self.origin == 'image': self.origin = mpl.rcParams['image.origin'] - if isinstance(args[0], ContourSet): - C = args[0].Cntr - if self.levels is None: - self.levels = args[0].levels - else: - x, y, z = self._contour_args(args, kwargs) - - x0 = ma.minimum(x) - x1 = ma.maximum(x) - y0 = ma.minimum(y) - y1 = ma.maximum(y) - self.ax.update_datalim([(x0,y0), (x1,y1)]) - self.ax.autoscale_view() - _mask = ma.getmask(z) - if _mask is ma.nomask: - _mask = None - C = _cntr.Cntr(x, y, z.filled(), _mask) - self.Cntr = C + self._process_args(*args, **kwargs) self._process_levels() if self.colors is not None: @@ -673,28 +688,23 @@ kw['norm'] = norm cm.ScalarMappable.__init__(self, **kw) # sets self.cmap; self._process_colors() + + self.allsegs, self.allkinds = self._get_allsegs_and_allkinds() + if self.filled: if self.linewidths is not None: warnings.warn('linewidths is ignored by contourf') - lowers = self._levels[:-1] - if self.zmin == lowers[0]: - # Include minimum values in lowest interval - lowers = lowers.copy() # so we don't change self._levels - if self.logscale: - lowers[0] = 0.99 * self.zmin - else: - lowers[0] -= 1 - uppers = self._levels[1:] + # Lower and upper contour levels. + lowers, uppers = self._get_lowers_and_uppers() - for level, level_upper in zip(lowers, uppers): - nlist = C.trace(level, level_upper, nchunk = self.nchunk) - nseg = len(nlist)//2 - segs = nlist[:nseg] - kinds = nlist[nseg:] + # Ensure allkinds can be zipped below. + if self.allkinds is None: + self.allkinds = [None]*len(self.allsegs) + for level, level_upper, segs, kinds in \ + zip(lowers, uppers, self.allsegs, self.allkinds): paths = self._make_paths(segs, kinds) - # Default zorder taken from Collection zorder = kwargs.get('zorder', 1) col = collections.PathCollection(paths, @@ -708,12 +718,8 @@ tlinewidths = self._process_linewidths() self.tlinewidths = tlinewidths tlinestyles = self._process_linestyles() - for level, width, lstyle in zip(self.levels, tlinewidths, tlinestyles): - nlist = C.trace(level) - nseg = len(nlist)//2 - segs = nlist[:nseg] - #kinds = nlist[nseg:] - + for level, width, lstyle, segs in \ + zip(self.levels, tlinewidths, tlinestyles, self.allsegs): # Default zorder taken from LineCollection zorder = kwargs.get('zorder', 2) col = collections.LineCollection(segs, @@ -721,20 +727,81 @@ linestyle = lstyle, alpha=self.alpha, zorder=zorder) - col.set_label('_nolegend_') self.ax.add_collection(col, False) self.collections.append(col) self.changed() # set the colors - def _make_paths(self, segs, kinds): - paths = [] - for seg, kind in zip(segs, kinds): - paths.append(mpath.Path(seg, codes=kind)) - return paths + def _process_args(self, *args, **kwargs): + """ + Process args and kwargs; override in derived classes. + Must set self.levels, self.zmin and self.zmax, and update axes + limits. + """ + self.levels = args[0] + self.allsegs = args[1] + self.allkinds = len(args) > 2 and args[2] or None + self.zmax = np.amax(self.levels) + self.zmin = np.amin(self.levels) + self._auto = False + # Check lengths of levels and allsegs. + if self.filled: + if len(self.allsegs) != len(self.levels)-1: + raise ValueError('must be one less number of segments as levels') + else: + if len(self.allsegs) != len(self.levels): + raise ValueError('must be same number of segments as levels') + # Check length of allkinds. + if self.allkinds is not None and len(self.allkinds) != len(self.allsegs): + raise ValueError('allkinds has different length to allsegs') + + # Determine x,y bounds and update axes data limits. + havelimits = False + for segs in self.allsegs: + for seg in segs: + seg = np.asarray(seg) + if havelimits: + min = np.minimum(min, seg.min(axis=0)) + max = np.maximum(max, seg.max(axis=0)) + else: + min = seg.min(axis=0) + max = seg.max(axis=0) + havelimits = True + if havelimits: + self.ax.update_datalim([min, max]) + self.ax.autoscale_view() + + def _get_allsegs_and_allkinds(self): + """ + Override in derived classes to create and return allsegs and allkinds. + allkinds can be None. + """ + return self.allsegs, self.allkinds + + def _get_lowers_and_uppers(self): + """ + Return (lowers,uppers) for filled contours. + """ + lowers = self._levels[:-1] + if self.zmin == lowers[0]: + # Include minimum values in lowest interval + lowers = lowers.copy() # so we don't change self._levels + if self.logscale: + lowers[0] = 0.99 * self.zmin + else: + lowers[0] -= 1 + uppers = self._levels[1:] + return (lowers, uppers) + + def _make_paths(self, segs, kinds): + if kinds is not None: + return [mpath.Path(seg,codes=kind) for seg,kind in zip(segs,kinds)] + else: + return [mpath.Path(seg) for seg in segs] + def changed(self): tcolors = [ (tuple(rgba),) for rgba in self.to_rgba(self.cvalues, alpha=self.alpha)] @@ -750,7 +817,6 @@ # add label colors cm.ScalarMappable.changed(self) - def _autolev(self, z, N): ''' Select contour levels to span the data. @@ -778,101 +844,18 @@ # For line contours, drop levels outside the data range. return lev[(lev > zmin) & (lev < zmax)] - def _initialize_x_y(self, z): - ''' - Return X, Y arrays such that contour(Z) will match imshow(Z) - if origin is not None. - The center of pixel Z[i,j] depends on origin: - if origin is None, x = j, y = i; - if origin is 'lower', x = j + 0.5, y = i + 0.5; - if origin is 'upper', x = j + 0.5, y = Nrows - i - 0.5 - If extent is not None, x and y will be scaled to match, - as in imshow. - If origin is None and extent is not None, then extent - will give the minimum and maximum values of x and y. - ''' - if z.ndim != 2: - raise TypeError("Input must be a 2D array.") - else: - Ny, Nx = z.shape - if self.origin is None: # Not for image-matching. - if self.extent is None: - return np.meshgrid(np.arange(Nx), np.arange(Ny)) - else: - x0,x1,y0,y1 = self.extent - x = np.linspace(x0, x1, Nx) - y = np.linspace(y0, y1, Ny) - return np.meshgrid(x, y) - # Match image behavior: - if self.extent is None: - x0,x1,y0,y1 = (0, Nx, 0, Ny) - else: - x0,x1,y0,y1 = self.extent - dx = float(x1 - x0)/Nx - dy = float(y1 - y0)/Ny - x = x0 + (np.arange(Nx) + 0.5) * dx - y = y0 + (np.arange(Ny) + 0.5) * dy - if self.origin == 'upper': - y = y[::-1] - return np.meshgrid(x,y) - - def _check_xyz(self, args, kwargs): - ''' - For functions like contour, check that the dimensions - of the input arrays match; if x and y are 1D, convert - them to 2D using meshgrid. - - Possible change: I think we should make and use an ArgumentError - Exception class (here and elsewhere). - ''' - x, y = args[:2] - self.ax._process_unit_info(xdata=x, ydata=y, kwargs=kwargs) - x = self.ax.convert_xunits(x) - y = self.ax.convert_yunits(y) - - x = np.asarray(x, dtype=np.float64) - y = np.asarray(y, dtype=np.float64) - z = ma.asarray(args[2], dtype=np.float64) - if z.ndim != 2: - raise TypeError("Input z must be a 2D array.") - else: Ny, Nx = z.shape - if x.shape == z.shape and y.shape == z.shape: - return x,y,z - if x.ndim != 1 or y.ndim != 1: - raise TypeError("Inputs x and y must be 1D or 2D.") - nx, = x.shape - ny, = y.shape - if nx != Nx or ny != Ny: - raise TypeError("Length of x must be number of columns in z,\n" + - "and length of y must be number of rows.") - x,y = np.meshgrid(x,y) - return x,y,z - - - def _contour_args(self, args, kwargs): + def _contour_level_args(self, z, args): + """ + Determine the contour levels and store in self.levels. + """ if self.filled: fn = 'contourf' else: fn = 'contour' - Nargs = len(args) - if Nargs <= 2: - z = ma.asarray(args[0], dtype=np.float64) - x, y = self._initialize_x_y(z) - elif Nargs <=4: - x,y,z = self._check_xyz(args[:3], kwargs) - else: - raise TypeError("Too many arguments to %s; see help(%s)" % (fn,fn)) - z = ma.masked_invalid(z, copy=False) - self.zmax = ma.maximum(z) - self.zmin = ma.minimum(z) - if self.logscale and self.zmin <= 0: - z = ma.masked_where(z <= 0, z) - warnings.warn('Log scale: values of z <=0 have been masked') - self.zmin = z.min() self._auto = False if self.levels is None: - if Nargs == 1 or Nargs == 3: + if len(args) == 0: lev = self._autolev(z, 7) - else: # 2 or 4 args - level_arg = args[-1] + else: + level_arg = args[0] try: if type(level_arg) == int: lev = self._autolev(z, level_arg) @@ -884,7 +867,6 @@ if self.filled and len(lev) < 2: raise ValueError("Filled contours require at least 2 levels.") self.levels = lev - return (x, y, z) def _process_levels(self): self._levels = list(self.levels) @@ -907,7 +889,6 @@ if self.extend in ('both', 'max'): self.layers[-1] = 0.5 * (self.vmax + self._levels[-2]) - def _process_colors(self): """ Color argument processing for contouring. @@ -989,6 +970,241 @@ self.alpha = alpha self.changed() + def find_nearest_contour( self, x, y, indices=None, pixel=True ): + """ + Finds contour that is closest to a point. Defaults to + measuring distance in pixels (screen space - useful for manual + contour labeling), but this can be controlled via a keyword + argument. + + Returns a tuple containing the contour, segment, index of + segment, x & y of segment point and distance to minimum point. + + Call signature:: + + conmin,segmin,imin,xmin,ymin,dmin = find_nearest_contour( + self, x, y, indices=None, pixel=True ) + + Optional keyword arguments:: + + *indices*: + Indexes of contour levels to consider when looking for + nearest point. Defaults to using all levels. + + *pixel*: + If *True*, measure distance in pixel space, if not, measure + distance in axes space. Defaults to *True*. + + """ + + # This function uses a method that is probably quite + # inefficient based on converting each contour segment to + # pixel coordinates and then comparing the given point to + # those coordinates for each contour. This will probably be + # quite slow for complex contours, but for normal use it works + # sufficiently well that the time is not noticeable. + # Nonetheless, improvements could probably be made. + + if indices==None: + indices = range(len(self.levels)) + + dmin = 1e10 + conmin = None + segmin = None + xmin = None + ymin = None + + for icon in indices: + con = self.collections[icon] + paths = con.get_paths() + for segNum, linepath in enumerate(paths): + lc = linepath.vertices + + # transfer all data points to screen coordinates if desired + if pixel: + lc = self.ax.transData.transform(lc) + + ds = (lc[:,0]-x)**2 + (lc[:,1]-y)**2 + d = min( ds ) + if d < dmin: + dmin = d + conmin = icon + segmin = segNum + imin = mpl.mlab.find( ds == d )[0] + xmin = lc[imin,0] + ymin = lc[imin,1] + + return (conmin,segmin,imin,xmin,ymin,dmin) + + +class QuadContourSet(ContourSet): + """ + Create and store a set of contour lines or filled regions. + + User-callable method: clabel + + Useful attributes: + ax: + the axes object in which the contours are drawn + collections: + a silent_list of LineCollections or PolyCollections + levels: + contour levels + layers: + same as levels for line contours; half-way between + levels for filled contours. See _process_colors method. + """ + def __init__(self, ax, *args, **kwargs): + """ + Calculate and draw contour lines or filled regions, depending + on whether keyword arg 'filled' is False (default) or True. + + The first argument of the initializer must be an axes + object. The remaining arguments and keyword arguments + are described in QuadContourSet.contour_doc. + """ + ContourSet.__init__(self, ax, *args, **kwargs) + + def _process_args(self, *args, **kwargs): + """ + Process args and kwargs. + """ + if isinstance(args[0], QuadContourSet): + C = args[0].Cntr + if self.levels is None: + self.levels = args[0].levels + else: + x, y, z = self._contour_args(args, kwargs) + + x0 = ma.minimum(x) + x1 = ma.maximum(x) + y0 = ma.minimum(y) + y1 = ma.maximum(y) + self.ax.update_datalim([(x0,y0), (x1,y1)]) + self.ax.autoscale_view() + _mask = ma.getmask(z) + if _mask is ma.nomask: + _mask = None + C = _cntr.Cntr(x, y, z.filled(), _mask) + self.Cntr = C + + def _get_allsegs_and_allkinds(self): + """ + Create and return allsegs and allkinds by calling underlying C code. + """ + allsegs = [] + if self.filled: + lowers, uppers = self._get_lowers_and_uppers() + allkinds = [] + for level, level_upper in zip(lowers, uppers): + nlist = self.Cntr.trace(level, level_upper, nchunk = self.nchunk) + nseg = len(nlist)//2 + segs = nlist[:nseg] + kinds = nlist[nseg:] + allsegs.append(segs) + allkinds.append(kinds) + else: + allkinds = None + for level in self.levels: + nlist = self.Cntr.trace(level) + nseg = len(nlist)//2 + segs = nlist[:nseg] + allsegs.append(segs) + return allsegs, allkinds + + def _contour_args(self, args, kwargs): + if self.filled: fn = 'contourf' + else: fn = 'contour' + Nargs = len(args) + if Nargs <= 2: + z = ma.asarray(args[0], dtype=np.float64) + x, y = self._initialize_x_y(z) + args = args[1:] + elif Nargs <=4: + x,y,z = self._check_xyz(args[:3], kwargs) + args = args[3:] + else: + raise TypeError("Too many arguments to %s; see help(%s)" % (fn,fn)) + z = ma.masked_invalid(z, copy=False) + self.zmax = ma.maximum(z) + self.zmin = ma.minimum(z) + if self.logscale and self.zmin <= 0: + z = ma.masked_where(z <= 0, z) + warnings.warn('Log scale: values of z <= 0 have been masked') + self.zmin = z.min() + self._contour_level_args(z, args) + return (x, y, z) + + def _check_xyz(self, args, kwargs): + ''' + For functions like contour, check that the dimensions + of the input arrays match; if x and y are 1D, convert + them to 2D using meshgrid. + + Possible change: I think we should make and use an ArgumentError + Exception class (here and elsewhere). + ''' + x, y = args[:2] + self.ax._process_unit_info(xdata=x, ydata=y, kwargs=kwargs) + x = self.ax.convert_xunits(x) + y = self.ax.convert_yunits(y) + + x = np.asarray(x, dtype=np.float64) + y = np.asarray(y, dtype=np.float64) + z = ma.asarray(args[2], dtype=np.float64) + if z.ndim != 2: + raise TypeError("Input z must be a 2D array.") + else: Ny, Nx = z.shape + if x.shape == z.shape and y.shape == z.shape: + return x,y,z + if x.ndim != 1 or y.ndim != 1: + raise TypeError("Inputs x and y must be 1D or 2D.") + nx, = x.shape + ny, = y.shape + if nx != Nx or ny != Ny: + raise TypeError("Length of x must be number of columns in z,\n" + + "and length of y must be number of rows.") + x,y = np.meshgrid(x,y) + return x,y,z + + def _initialize_x_y(self, z): + ''' + Return X, Y arrays such that contour(Z) will match imshow(Z) + if origin is not None. + The center of pixel Z[i,j] depends on origin: + if origin is None, x = j, y = i; + if origin is 'lower', x = j + 0.5, y = i + 0.5; + if origin is 'upper', x = j + 0.5, y = Nrows - i - 0.5 + If extent is not None, x and y will be scaled to match, + as in imshow. + If origin is None and extent is not None, then extent + will give the minimum and maximum values of x and y. + ''' + if z.ndim != 2: + raise TypeError("Input must be a 2D array.") + else: + Ny, Nx = z.shape + if self.origin is None: # Not for image-matching. + if self.extent is None: + return np.meshgrid(np.arange(Nx), np.arange(Ny)) + else: + x0,x1,y0,y1 = self.extent + x = np.linspace(x0, x1, Nx) + y = np.linspace(y0, y1, Ny) + return np.meshgrid(x, y) + # Match image behavior: + if self.extent is None: + x0,x1,y0,y1 = (0, Nx, 0, Ny) + else: + x0,x1,y0,y1 = self.extent + dx = float(x1 - x0)/Nx + dy = float(y1 - y0)/Ny + x = x0 + (np.arange(Nx) + 0.5) * dx + y = y0 + (np.arange(Ny) + 0.5) * dy + if self.origin == 'upper': + y = y[::-1] + return np.meshgrid(x,y) + contour_doc = """ :func:`~matplotlib.pyplot.contour` and :func:`~matplotlib.pyplot.contourf` draw contour lines and @@ -1047,7 +1263,7 @@ handle internal masked regions correctly. ``C = contour(...)`` returns a - :class:`~matplotlib.contour.ContourSet` object. + :class:`~matplotlib.contour.QuadContourSet` object. Optional keyword arguments: @@ -1170,69 +1386,3 @@ .. plot:: mpl_examples/pylab_examples/contourf_demo.py """ - - def find_nearest_contour( self, x, y, indices=None, pixel=True ): - """ - Finds contour that is closest to a point. Defaults to - measuring distance in pixels (screen space - useful for manual - contour labeling), but this can be controlled via a keyword - argument. - - Returns a tuple containing the contour, segment, index of - segment, x & y of segment point and distance to minimum point. - - Call signature:: - - conmin,segmin,imin,xmin,ymin,dmin = find_nearest_contour( - self, x, y, indices=None, pixel=True ) - - Optional keyword arguments:: - - *indices*: - Indexes of contour levels to consider when looking for - nearest point. Defaults to using all levels. - - *pixel*: - If *True*, measure distance in pixel space, if not, measure - distance in axes space. Defaults to *True*. - - """ - - # This function uses a method that is probably quite - # inefficient based on converting each contour segment to - # pixel coordinates and then comparing the given point to - # those coordinates for each contour. This will probably be - # quite slow for complex contours, but for normal use it works - # sufficiently well that the time is not noticeable. - # Nonetheless, improvements could probably be made. - - if indices==None: - indices = range(len(self.levels)) - - dmin = 1e10 - conmin = None - segmin = None - xmin = None - ymin = None - - for icon in indices: - con = self.collections[icon] - paths = con.get_paths() - for segNum, linepath in enumerate(paths): - lc = linepath.vertices - - # transfer all data points to screen coordinates if desired - if pixel: - lc = self.ax.transData.transform(lc) - - ds = (lc[:,0]-x)**2 + (lc[:,1]-y)**2 - d = min( ds ) - if d < dmin: - dmin = d - conmin = icon - segmin = segNum - imin = mpl.mlab.find( ds == d )[0] - xmin = lc[imin,0] - ymin = lc[imin,1] - - return (conmin,segmin,imin,xmin,ymin,dmin) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8231 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8231&view=rev Author: efiring Date: 2010年04月15日 07:17:42 +0000 (2010年4月15日) Log Message: ----------- Fixed a problem in the last commit Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backend_bases.py Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2010年04月15日 07:06:10 UTC (rev 8230) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2010年04月15日 07:17:42 UTC (rev 8231) @@ -298,8 +298,6 @@ xo, yo = toffsets[i % Noffsets] if Nfacecolors: rgbFace = facecolors[i % Nfacecolors] - if len(rgbFace) == 4 and rgbFace[3] == 0: - rgbFace = None if Nedgecolors: gc0.set_foreground(edgecolors[i % Nedgecolors]) if Nlinewidths: @@ -307,8 +305,11 @@ if Nlinestyles: gc0.set_dashes(*linestyles[i % Nlinestyles]) if rgbFace is not None and len(rgbFace)==4: - gc0.set_alpha(rgbFace[-1]) - rgbFace = rgbFace[:3] + if rgbFace[3] == 0: + rgbFace = None + else: + gc0.set_alpha(rgbFace[-1]) + rgbFace = rgbFace[:3] gc0.set_antialiased(antialiaseds[i % Naa]) if Nurls: gc0.set_url(urls[i % Nurls]) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8230 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8230&view=rev Author: efiring Date: 2010年04月15日 07:06:10 +0000 (2010年4月15日) Log Message: ----------- backend_bases: handle facecolor [0,0,0,0] in patch collection; fixes 2881485 Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backend_bases.py Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2010年04月14日 22:44:13 UTC (rev 8229) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2010年04月15日 07:06:10 UTC (rev 8230) @@ -298,6 +298,8 @@ xo, yo = toffsets[i % Noffsets] if Nfacecolors: rgbFace = facecolors[i % Nfacecolors] + if len(rgbFace) == 4 and rgbFace[3] == 0: + rgbFace = None if Nedgecolors: gc0.set_foreground(edgecolors[i % Nedgecolors]) if Nlinewidths: @@ -1534,14 +1536,14 @@ # check for registered backends if format in _backend_d: backend_class = _backend_d[format] - + def _print_method(*args, **kwargs): backend = self.switch_backends(backend_class) print_method = getattr(backend, method_name) return print_method(*args, **kwargs) return _print_method - + if (format not in self.filetypes or not hasattr(self, method_name)): formats = self.filetypes.keys() @@ -1610,7 +1612,7 @@ format = format.lower() print_method = self._get_print_method(format) - + if dpi is None: dpi = rcParams['savefig.dpi'] @@ -2233,7 +2235,7 @@ self._switch_off_zoom_mode) self._ids_zoom = id1, id2, id3 - + self._zoom_mode = event.key @@ -2242,11 +2244,11 @@ def _switch_on_zoom_mode(self, event): self._zoom_mode = event.key self.mouse_move(event) - + def _switch_off_zoom_mode(self, event): self._zoom_mode = None self.mouse_move(event) - + def push_current(self): 'push the current view limits and position onto the stack' lims = []; pos = [] @@ -2298,11 +2300,11 @@ x, y = event.x, event.y lastx, lasty, a, ind, lim, trans = self._xypress[0] - # adjust x, last, y, last + # adjust x, last, y, last x1, y1, x2, y2 = a.bbox.extents x, lastx = max(min(x, lastx), x1), min(max(x, lastx), x2) y, lasty = max(min(y, lasty), y1), min(max(y, lasty), y2) - + if self._zoom_mode == "x": x1, y1, x2, y2 = a.bbox.extents y, lasty = y1, y2 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8229 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8229&view=rev Author: efiring Date: 2010年04月14日 22:44:13 +0000 (2010年4月14日) Log Message: ----------- backend_ps: fix file perms when TeX is used; minor clarifications Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2010年04月14日 18:48:36 UTC (rev 8228) +++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2010年04月14日 22:44:13 UTC (rev 8229) @@ -997,7 +997,6 @@ """ isEPSF = format == 'eps' passed_in_file_object = False - fd, tmpfile = mkstemp() if is_string_like(outfile): title = outfile elif is_writable_file_like(outfile): @@ -1005,9 +1004,10 @@ passed_in_file_object = True else: raise ValueError("outfile must be a path or a file-like object") - os.close(fd) - fh = file(tmpfile, 'w') + fd, tmpfile = mkstemp() + fh = os.fdopen(fd, 'w') + # find the appropriate papertype width, height = self.figure.get_size_inches() if papertype == 'auto': @@ -1153,12 +1153,11 @@ xpdf_distill(tmpfile, isEPSF, ptype=papertype, bbox=bbox) if passed_in_file_object: - fh = file(tmpfile) + fh = open(tmpfile) print >>outfile, fh.read() else: - f = open(outfile, 'w') + open(outfile, 'w') mode = os.stat(outfile).st_mode - f.close() shutil.move(tmpfile, outfile) os.chmod(outfile, mode) @@ -1175,8 +1174,7 @@ # write to a temp file, we'll move it to outfile when done fd, tmpfile = mkstemp() - os.close(fd) - fh = file(tmpfile, 'w') + fh = os.fdopen(fd, 'w') self.figure.dpi = 72 # ignore the dpi kwarg width, height = self.figure.get_size_inches() @@ -1301,7 +1299,11 @@ if isinstance(outfile, file): fh = file(tmpfile) print >>outfile, fh.read() - else: shutil.move(tmpfile, outfile) + else: + open(outfile, 'w') + mode = os.stat(outfile).st_mode + shutil.move(tmpfile, outfile) + os.chmod(outfile, mode) def convert_psfrags(tmpfile, psfrags, font_preamble, custom_preamble, paperWidth, paperHeight, orientation): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8228 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8228&view=rev Author: jrevans Date: 2010年04月14日 18:48:36 +0000 (2010年4月14日) Log Message: ----------- Added the ps temp file ipermissions copy fix (as discussed on the devel list). Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2010年04月13日 22:55:23 UTC (rev 8227) +++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2010年04月14日 18:48:36 UTC (rev 8228) @@ -1156,7 +1156,11 @@ fh = file(tmpfile) print >>outfile, fh.read() else: + f = open(outfile, 'w') + mode = os.stat(outfile).st_mode + f.close() shutil.move(tmpfile, outfile) + os.chmod(outfile, mode) def _print_figure_tex(self, outfile, format, dpi, facecolor, edgecolor, orientation, isLandscape, papertype, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8227 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8227&view=rev Author: leejjoon Date: 2010年04月13日 22:55:23 +0000 (2010年4月13日) Log Message: ----------- fix a bug that _bbox_patch of annotation is not correctly updated Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/offsetbox.py trunk/matplotlib/lib/matplotlib/text.py Modified: trunk/matplotlib/lib/matplotlib/offsetbox.py =================================================================== --- trunk/matplotlib/lib/matplotlib/offsetbox.py 2010年04月06日 20:38:31 UTC (rev 8226) +++ trunk/matplotlib/lib/matplotlib/offsetbox.py 2010年04月13日 22:55:23 UTC (rev 8227) @@ -159,7 +159,7 @@ if a: return a, b return False, {} - + def set_offset(self, xy): """ Set the offset @@ -1307,11 +1307,10 @@ else: ox0, oy0 = self._get_xy(renderer, x, y, self.textcoords) - #self.offsetbox.set_bbox_to_anchor((ox0, oy0)) w, h, xd, yd = self.offsetbox.get_extent(renderer) _fw, _fh = self._box_alignment - self.offsetbox.set_offset((ox0-_fw*w, oy0-_fh*h)) + self.offsetbox.set_offset((ox0-_fw*w+xd, oy0-_fh*h+yd)) # update patch position bbox = self.offsetbox.get_window_extent(renderer) @@ -1401,7 +1400,7 @@ offset from the point where the mouse drag started. Optionally you may override following two methods. - + def artist_picker(self, artist, evt): return self.ref_artist.contains(evt) @@ -1420,7 +1419,7 @@ self.ref_artist = ref_artist self.got_artist = False self._use_blit = use_blit - + self.canvas = self.ref_artist.figure.canvas c2 = self.canvas.mpl_connect('pick_event', self.on_pick) c3 = self.canvas.mpl_connect('button_release_event', self.on_release) @@ -1484,7 +1483,7 @@ def update_offset(self, dx, dy): pass - + def finalize_offset(self): pass @@ -1504,7 +1503,7 @@ def update_offset(self, dx, dy): loc_in_canvas = self.offsetbox_x + dx, self.offsetbox_y + dy self.offsetbox.set_offset(loc_in_canvas) - + def get_loc_in_canvas(self): offsetbox=self.offsetbox @@ -1514,8 +1513,8 @@ loc_in_canvas = (ox-xd, oy-yd) return loc_in_canvas - + class DraggableAnnotation(DraggableBase): def __init__(self, annotation, use_blit=False): DraggableBase.__init__(self, annotation, use_blit=use_blit) Modified: trunk/matplotlib/lib/matplotlib/text.py =================================================================== --- trunk/matplotlib/lib/matplotlib/text.py 2010年04月06日 20:38:31 UTC (rev 8226) +++ trunk/matplotlib/lib/matplotlib/text.py 2010年04月13日 22:55:23 UTC (rev 8227) @@ -468,11 +468,6 @@ be updated before actually drawing the bbox. """ - # For arrow_patch, use textbox as patchA by default. - - if not isinstance(self.arrow_patch, FancyArrowPatch): - return - if self._bbox_patch: trans = self.get_transform() @@ -495,32 +490,7 @@ self._bbox_patch.set_mutation_scale(fontsize_in_pixel) #self._bbox_patch.draw(renderer) - else: - props = self._bbox - if props is None: props = {} - props = props.copy() # don't want to alter the pad externally - pad = props.pop('pad', 4) - pad = renderer.points_to_pixels(pad) - if self.get_text() == "": - self.arrow_patch.set_patchA(None) - return - bbox = self.get_window_extent(renderer) - l,b,w,h = bbox.bounds - l-=pad/2. - b-=pad/2. - w+=pad - h+=pad - r = Rectangle(xy=(l,b), - width=w, - height=h, - ) - r.set_transform(mtransforms.IdentityTransform()) - r.set_clip_on( False ) - r.update(props) - - self.arrow_patch.set_patchA(r) - def _draw_bbox(self, renderer, posx, posy): """ Update the location and the size of the bbox @@ -1425,7 +1395,7 @@ x, y = self._artist.transform_point(self._ref_coord) else: raise RuntimeError("unknown type") - + sc = self._get_scale(renderer) tr = Affine2D().scale(sc, sc).translate(x, y) @@ -1501,7 +1471,7 @@ tr = PolarAxes.PolarTransform() trans = tr + self.axes.transData return trans - + s_ = s.split() if len(s_) != 2: raise ValueError("%s is not a recognized coodinate" % s) @@ -1611,8 +1581,8 @@ y = b + y*sc return x, y - + def set_annotation_clip(self, b): """ set *annotation_clip* attribute. @@ -1896,13 +1866,38 @@ mutation_scale = renderer.points_to_pixels(mutation_scale) self.arrow_patch.set_mutation_scale(mutation_scale) - if self._bbox_patch: - patchA = d.pop("patchA", self._bbox_patch) - self.arrow_patch.set_patchA(patchA) + if "patchA" in d: + self.arrow_patch.set_patchA(d.pop("patchA")) else: - patchA = d.pop("patchA", self._bbox) - self.arrow_patch.set_patchA(patchA) + if self._bbox_patch: + self.arrow_patch.set_patchA(self._bbox_patch) + else: + patchA = d.pop("patchA", None) + props = self._bbox + if props is None: props = {} + props = props.copy() # don't want to alter the pad externally + pad = props.pop('pad', 4) + pad = renderer.points_to_pixels(pad) + if self.get_text() == "": + self.arrow_patch.set_patchA(None) + return + bbox = self.get_window_extent(renderer) + l,b,w,h = bbox.bounds + l-=pad/2. + b-=pad/2. + w+=pad + h+=pad + r = Rectangle(xy=(l,b), + width=w, + height=h, + ) + r.set_transform(mtransforms.IdentityTransform()) + r.set_clip_on( False ) + r.update(props) + + self.arrow_patch.set_patchA(r) + else: # pick the x,y corner of the text bbox closest to point @@ -1933,6 +1928,34 @@ self.arrow.set_clip_box(self.get_clip_box()) + def update_bbox_position_size(self, renderer): + """ + Update the location and the size of the bbox. This method + should be used when the position and size of the bbox needs to + be updated before actually drawing the bbox. + """ + + # For arrow_patch, use textbox as patchA by default. + + if not isinstance(self.arrow_patch, FancyArrowPatch): + return + + if self._bbox_patch: + posx, posy = self._x, self._y + print posx, posy + + x_box, y_box, w_box, h_box = _get_textbox(self, renderer) + self._bbox_patch.set_bounds(0., 0., + w_box, h_box) + theta = self.get_rotation()/180.*math.pi + tr = mtransforms.Affine2D().rotate(theta) + tr = tr.translate(posx+x_box, posy+y_box) + self._bbox_patch.set_transform(tr) + fontsize_in_pixel = renderer.points_to_pixels(self.get_size()) + self._bbox_patch.set_mutation_scale(fontsize_in_pixel) + + + @allow_rasterization def draw(self, renderer): """ @@ -1944,14 +1967,13 @@ if not self.get_visible(): return xy_pixel = self._get_position_xy(renderer) - if not self._check_xy(renderer, xy_pixel): return self._update_position_xytext(renderer, xy_pixel) - self.update_bbox_position_size(renderer) + if self.arrow is not None: if self.arrow.figure is None and self.figure is not None: self.arrow.figure = self.figure This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8226 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8226&view=rev Author: leejjoon Date: 2010年04月06日 20:38:31 +0000 (2010年4月06日) Log Message: ----------- modify axes_grid toolkit examples to use axes_grid1 and axisartist Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/axes_grid/demo_axes_divider.py trunk/matplotlib/examples/axes_grid/demo_axes_grid.py trunk/matplotlib/examples/axes_grid/demo_axes_grid2.py trunk/matplotlib/examples/axes_grid/demo_axes_rgb.py trunk/matplotlib/examples/axes_grid/demo_colorbar_with_inset_locator.py trunk/matplotlib/examples/axes_grid/demo_floating_axes.py trunk/matplotlib/examples/axes_grid/demo_floating_axis.py trunk/matplotlib/examples/axes_grid/demo_parasite_axes2.py trunk/matplotlib/examples/axes_grid/inset_locator_demo.py trunk/matplotlib/examples/axes_grid/inset_locator_demo2.py trunk/matplotlib/examples/axes_grid/parasite_simple2.py trunk/matplotlib/examples/axes_grid/scatter_hist.py trunk/matplotlib/examples/axes_grid/simple_anchored_artists.py trunk/matplotlib/examples/axes_grid/simple_axesgrid.py trunk/matplotlib/examples/axes_grid/simple_axesgrid2.py trunk/matplotlib/examples/axes_grid/simple_axisline4.py trunk/matplotlib/examples/pylab_examples/axes_zoom_effect.py trunk/matplotlib/examples/pylab_examples/demo_text_rotation_mode.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/CHANGELOG 2010年04月06日 20:38:31 UTC (rev 8226) @@ -1,3 +1,5 @@ +2010年04月06日 modify axes_grid examples to use axes_grid1 and axisartist. -JJL + 2010年04月06日 rebase axes_grid using axes_grid1 and axisartist modules. -JJL 2010年04月06日 axes_grid toolkit is splitted into two separate modules, Modified: trunk/matplotlib/examples/axes_grid/demo_axes_divider.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_axes_divider.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/demo_axes_divider.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -19,7 +19,7 @@ def demo_locatable_axes_hard(fig1): - from mpl_toolkits.axes_grid \ + from mpl_toolkits.axes_grid1 \ import SubplotDivider, LocatableAxes, Size divider = SubplotDivider(fig1, 2, 2, 2, aspect=True) @@ -57,7 +57,7 @@ def demo_locatable_axes_easy(ax): - from mpl_toolkits.axes_grid import make_axes_locatable + from mpl_toolkits.axes_grid1 import make_axes_locatable divider = make_axes_locatable(ax) @@ -76,7 +76,7 @@ def demo_images_side_by_sied(ax): - from mpl_toolkits.axes_grid import make_axes_locatable + from mpl_toolkits.axes_grid1 import make_axes_locatable divider = make_axes_locatable(ax) Modified: trunk/matplotlib/examples/axes_grid/demo_axes_grid.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_axes_grid.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/demo_axes_grid.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -1,5 +1,5 @@ import matplotlib.pyplot as plt -from mpl_toolkits.axes_grid import AxesGrid +from mpl_toolkits.axes_grid1 import AxesGrid def get_demo_image(): import numpy as np @@ -38,6 +38,7 @@ axes_pad = 0.0, share_all=True, label_mode = "L", + cbar_location = "top", cbar_mode="single", ) @@ -47,6 +48,9 @@ #plt.colorbar(im, cax = grid.cbar_axes[0]) grid.cbar_axes[0].colorbar(im) + for cax in grid.cbar_axes: + cax.toggle_label(False) + # This affects all axes as share_all = True. grid.axes_llc.set_xticks([-2, 0, 2]) grid.axes_llc.set_yticks([-2, 0, 2]) @@ -72,6 +76,9 @@ im = grid[i].imshow(Z, extent=extent, interpolation="nearest") grid.cbar_axes[i].colorbar(im) + for cax in grid.cbar_axes: + cax.toggle_label(False) + # This affects all axes because we set share_all = True. grid.axes_llc.set_xticks([-2, 0, 2]) grid.axes_llc.set_yticks([-2, 0, 2]) Modified: trunk/matplotlib/examples/axes_grid/demo_axes_grid2.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_axes_grid2.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/demo_axes_grid2.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -1,5 +1,5 @@ import matplotlib.pyplot as plt -from mpl_toolkits.axes_grid import ImageGrid +from mpl_toolkits.axes_grid1 import ImageGrid import numpy as np def get_demo_image(): @@ -57,10 +57,10 @@ for ax, z in zip(grid, ZS): ax.cax.toggle_label(True) - axis = ax.cax.axis[ax.cax.orientation] - axis.label.set_text("counts s$^{-1}$") - axis.label.set_size(10) - axis.major_ticklabels.set_size(6) + #axis = ax.cax.axis[ax.cax.orientation] + #axis.label.set_text("counts s$^{-1}$") + #axis.label.set_size(10) + #axis.major_ticklabels.set_size(6) # changing the colorbar ticks grid[1].cax.set_xticks([-1, 0, 1]) Modified: trunk/matplotlib/examples/axes_grid/demo_axes_rgb.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_axes_rgb.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/demo_axes_rgb.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -1,9 +1,17 @@ import numpy as np import matplotlib.pyplot as plt -from demo_axes_divider import get_demo_image -from mpl_toolkits.axes_grid.axes_rgb import make_rgb_axes, RGBAxes +from mpl_toolkits.axes_grid1.axes_rgb import make_rgb_axes, RGBAxes +def get_demo_image(): + from matplotlib.cbook import get_sample_data + f = get_sample_data("axes_grid/bivariate_normal.npy", asfileobj=False) + z = np.load(f) + # z is a numpy array of 15x15 + return z, (-3,4,-4,3) + + + def get_rgb(): Z, extent = get_demo_image() @@ -67,9 +75,11 @@ ax.RGB.set_ylim(0.9, 10.6) for ax1 in [ax.RGB, ax.R, ax.G, ax.B]: - for axisline in ax1._axislines.values(): - axisline.line.set_color("w") - axisline.major_ticks.set_mec("w") + for sp1 in ax1.spines.values(): + sp1.set_color("w") + for tick in ax1.xaxis.get_major_ticks() + ax1.yaxis.get_major_ticks(): + tick.tick1line.set_mec("w") + tick.tick2line.set_mec("w") return ax Modified: trunk/matplotlib/examples/axes_grid/demo_colorbar_with_inset_locator.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_colorbar_with_inset_locator.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/demo_colorbar_with_inset_locator.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -1,7 +1,6 @@ import matplotlib.pyplot as plt -from mpl_toolkits.axes_grid.inset_locator import inset_axes -from mpl_toolkits.axes_grid.colorbar import colorbar +from mpl_toolkits.axes_grid1.inset_locator import inset_axes fig = plt.figure(1, [6, 3]) @@ -14,7 +13,7 @@ loc=1) im1=ax1.imshow([[1,2],[2, 3]]) -colorbar(im1, cax=axins1, orientation="horizontal", ticks=[1,2,3]) +plt.colorbar(im1, cax=axins1, orientation="horizontal", ticks=[1,2,3]) axins1.xaxis.set_ticks_position("bottom") # first subplot @@ -34,7 +33,7 @@ # the bbox_to_anchor coordinate. im=ax.imshow([[1,2],[2, 3]]) -colorbar(im, cax=axins, ticks=[1,2,3]) +plt.colorbar(im, cax=axins, ticks=[1,2,3]) plt.draw() plt.show() Modified: trunk/matplotlib/examples/axes_grid/demo_floating_axes.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_floating_axes.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/demo_floating_axes.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -1,12 +1,11 @@ from matplotlib.transforms import Affine2D -from mpl_toolkits.axes_grid.floating_axes import FloatingSubplot,\ - GridHelperCurveLinear +import mpl_toolkits.axisartist.floating_axes as floating_axes import numpy as np -import mpl_toolkits.axes_grid.angle_helper as angle_helper +import mpl_toolkits.axisartist.angle_helper as angle_helper from matplotlib.projections import PolarAxes -from mpl_toolkits.axes_grid.grid_finder import FixedLocator, MaxNLocator, \ +from mpl_toolkits.axisartist.grid_finder import FixedLocator, MaxNLocator, \ DictFormatter def setup_axes1(fig, rect): @@ -15,9 +14,9 @@ """ tr = Affine2D().scale(2, 1).rotate_deg(30) - grid_helper = GridHelperCurveLinear(tr, extremes=(0, 4, 0, 4)) + grid_helper = floating_axes.GridHelperCurveLinear(tr, extremes=(0, 4, 0, 4)) - ax1 = FloatingSubplot(fig, rect, grid_helper=grid_helper) + ax1 = floating_axes.FloatingSubplot(fig, rect, grid_helper=grid_helper) fig.add_subplot(ax1) grid_helper.grid_finder.grid_locator1._nbins = 4 @@ -45,7 +44,7 @@ grid_locator2 = MaxNLocator(2) - grid_helper = GridHelperCurveLinear(tr, + grid_helper = floating_axes.GridHelperCurveLinear(tr, extremes=(.5*pi, 0, 2, 1), grid_locator1=grid_locator1, grid_locator2=grid_locator2, @@ -53,7 +52,7 @@ tick_formatter2=None, ) - ax1 = FloatingSubplot(fig, rect, grid_helper=grid_helper) + ax1 = floating_axes.FloatingSubplot(fig, rect, grid_helper=grid_helper) fig.add_subplot(ax1) # create a parasite axes whose transData in RA, cz @@ -88,7 +87,7 @@ ra0, ra1 = 8.*15, 14.*15 cz0, cz1 = 0, 14000 - grid_helper = GridHelperCurveLinear(tr, + grid_helper = floating_axes.GridHelperCurveLinear(tr, extremes=(ra0, ra1, cz0, cz1), grid_locator1=grid_locator1, grid_locator2=grid_locator2, @@ -96,7 +95,7 @@ tick_formatter2=None, ) - ax1 = FloatingSubplot(fig, rect, grid_helper=grid_helper) + ax1 = floating_axes.FloatingSubplot(fig, rect, grid_helper=grid_helper) fig.add_subplot(ax1) # adjust axis Modified: trunk/matplotlib/examples/axes_grid/demo_floating_axis.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_floating_axis.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/demo_floating_axis.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -9,13 +9,13 @@ """ global ax1 import numpy as np - import mpl_toolkits.axes_grid.angle_helper as angle_helper + import mpl_toolkits.axisartist.angle_helper as angle_helper from matplotlib.projections import PolarAxes from matplotlib.transforms import Affine2D - from mpl_toolkits.axes_grid.parasite_axes import SubplotHost + from mpl_toolkits.axisartist import SubplotHost - from mpl_toolkits.axes_grid.grid_helper_curvelinear import GridHelperCurveLinear + from mpl_toolkits.axisartist import GridHelperCurveLinear # see demo_curvelinear_grid.py for details tr = Affine2D().scale(np.pi/180., 1.) + PolarAxes.PolarTransform() Modified: trunk/matplotlib/examples/axes_grid/demo_parasite_axes2.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_parasite_axes2.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/demo_parasite_axes2.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -1,4 +1,4 @@ -from mpl_toolkits.axes_grid.parasite_axes import SubplotHost +from mpl_toolkits.axes_grid1.parasite_axes import SubplotHost import matplotlib.pyplot as plt if 1: @@ -6,25 +6,24 @@ host = SubplotHost(fig, 111) - host.set_ylabel("Density") - host.set_xlabel("Distance") - par1 = host.twinx() par2 = host.twinx() - par1.set_ylabel("Temperature") + offset = 60 + if hasattr(par2.axis["right"].line, "set_position"): + # use spine method + par2.axis["right"].line.set_position(('outward',offset)) + # set_position calls axis.cla() + par2.axis["left"].toggle(all=False) + else: + new_axisline = par2.get_grid_helper().new_fixed_axis + par2.axis["right"] = new_axisline(loc="right", + axes=par2, + offset=(offset, 0)) + + par2.axis["right"].toggle(all=True) - par2.axis["right"].set_visible(False) - offset = 60, 0 - new_axisline = par2.get_grid_helper().new_fixed_axis - par2.axis["right2"] = new_axisline(loc="right", - axes=par2, - offset=offset) - - par2.axis["right2"].label.set_visible(True) - par2.axis["right2"].set_label("Velocity") - fig.add_axes(host) plt.subplots_adjust(right=0.75) @@ -34,6 +33,7 @@ host.set_xlabel("Distance") host.set_ylabel("Density") par1.set_ylabel("Temperature") + par2.set_ylabel("Velocity") p1, = host.plot([0, 1, 2], [0, 1, 2], label="Density") p2, = par1.plot([0, 1, 2], [0, 3, 2], label="Temperature") @@ -46,7 +46,7 @@ host.axis["left"].label.set_color(p1.get_color()) par1.axis["right"].label.set_color(p2.get_color()) - par2.axis["right2"].label.set_color(p3.get_color()) + par2.axis["right"].label.set_color(p3.get_color()) plt.draw() plt.show() Modified: trunk/matplotlib/examples/axes_grid/inset_locator_demo.py =================================================================== --- trunk/matplotlib/examples/axes_grid/inset_locator_demo.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/inset_locator_demo.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -1,7 +1,7 @@ import matplotlib.pyplot as plt -from mpl_toolkits.axes_grid.inset_locator import inset_axes, zoomed_inset_axes -from mpl_toolkits.axes_grid.anchored_artists import AnchoredSizeBar +from mpl_toolkits.axes_grid1.inset_locator import inset_axes, zoomed_inset_axes +from mpl_toolkits.axes_grid1.anchored_artists import AnchoredSizeBar def add_sizebar(ax, size): Modified: trunk/matplotlib/examples/axes_grid/inset_locator_demo2.py =================================================================== --- trunk/matplotlib/examples/axes_grid/inset_locator_demo2.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/inset_locator_demo2.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -1,7 +1,7 @@ import matplotlib.pyplot as plt -from mpl_toolkits.axes_grid.inset_locator import zoomed_inset_axes -from mpl_toolkits.axes_grid.inset_locator import mark_inset +from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes +from mpl_toolkits.axes_grid1.inset_locator import mark_inset import numpy as np Modified: trunk/matplotlib/examples/axes_grid/parasite_simple2.py =================================================================== --- trunk/matplotlib/examples/axes_grid/parasite_simple2.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/parasite_simple2.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -1,6 +1,6 @@ import matplotlib.transforms as mtransforms import matplotlib.pyplot as plt -from mpl_toolkits.axes_grid.parasite_axes import SubplotHost +from mpl_toolkits.axes_grid1.parasite_axes import SubplotHost obs = [["01_S1", 3.88, 0.14, 1970, 63], ["01_S4", 5.6, 0.82, 1622, 150], Modified: trunk/matplotlib/examples/axes_grid/scatter_hist.py =================================================================== --- trunk/matplotlib/examples/axes_grid/scatter_hist.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/scatter_hist.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -8,7 +8,7 @@ fig = plt.figure(1, figsize=(5.5,5.5)) -from mpl_toolkits.axes_grid import make_axes_locatable +from mpl_toolkits.axes_grid1 import make_axes_locatable axScatter = plt.subplot(111) divider = make_axes_locatable(axScatter) Modified: trunk/matplotlib/examples/axes_grid/simple_anchored_artists.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_anchored_artists.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/simple_anchored_artists.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -2,7 +2,7 @@ def draw_text(ax): - from mpl_toolkits.axes_grid.anchored_artists import AnchoredText + from mpl_toolkits.axes_grid1.anchored_artists import AnchoredText at = AnchoredText("Figure 1a", loc=2, prop=dict(size=8), frameon=True, ) @@ -18,7 +18,7 @@ ax.add_artist(at2) def draw_circle(ax): # circle in the canvas coordinate - from mpl_toolkits.axes_grid.anchored_artists import AnchoredDrawingArea + from mpl_toolkits.axes_grid1.anchored_artists import AnchoredDrawingArea from matplotlib.patches import Circle ada = AnchoredDrawingArea(20, 20, 0, 0, loc=1, pad=0., frameon=False) @@ -27,7 +27,7 @@ ax.add_artist(ada) def draw_ellipse(ax): - from mpl_toolkits.axes_grid.anchored_artists import AnchoredEllipse + from mpl_toolkits.axes_grid1.anchored_artists import AnchoredEllipse # draw an ellipse of width=0.1, height=0.15 in the data coordinate ae = AnchoredEllipse(ax.transData, width=0.1, height=0.15, angle=0., loc=3, pad=0.5, borderpad=0.4, frameon=True) @@ -35,7 +35,7 @@ ax.add_artist(ae) def draw_sizebar(ax): - from mpl_toolkits.axes_grid.anchored_artists import AnchoredSizeBar + from mpl_toolkits.axes_grid1.anchored_artists import AnchoredSizeBar # draw a horizontal bar with length of 0.1 in Data coordinate # (ax.transData) with a label underneath. asb = AnchoredSizeBar(ax.transData, Modified: trunk/matplotlib/examples/axes_grid/simple_axesgrid.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axesgrid.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/simple_axesgrid.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -1,12 +1,12 @@ import matplotlib.pyplot as plt -from mpl_toolkits.axes_grid import AxesGrid +from mpl_toolkits.axes_grid1 import ImageGrid import numpy as np im = np.arange(100) im.shape = 10, 10 fig = plt.figure(1, (4., 4.)) -grid = AxesGrid(fig, 111, # similar to subplot(111) +grid = ImageGrid(fig, 111, # similar to subplot(111) nrows_ncols = (2, 2), # creates 2x2 grid of axes axes_pad=0.1, # pad between axes in inch. ) Modified: trunk/matplotlib/examples/axes_grid/simple_axesgrid2.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axesgrid2.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/simple_axesgrid2.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -1,5 +1,5 @@ import matplotlib.pyplot as plt -from mpl_toolkits.axes_grid import AxesGrid +from mpl_toolkits.axes_grid1 import ImageGrid def get_demo_image(): import numpy as np @@ -10,7 +10,7 @@ return z, (-3,4,-4,3) F = plt.figure(1, (5.5, 3.5)) -grid = AxesGrid(F, 111, # similar to subplot(111) +grid = ImageGrid(F, 111, # similar to subplot(111) nrows_ncols = (1, 3), axes_pad = 0.1, add_all=True, Modified: trunk/matplotlib/examples/axes_grid/simple_axisline4.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axisline4.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/axes_grid/simple_axisline4.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -1,5 +1,5 @@ import matplotlib.pyplot as plt -from mpl_toolkits.axes_grid.parasite_axes import SubplotHost +from mpl_toolkits.axes_grid1.parasite_axes import SubplotHost import numpy as np fig = plt.figure(1, (4,3)) @@ -12,7 +12,7 @@ ax2 = ax.twin() # ax2 is responsible for "top" axis and "right" axis ax2.set_xticks([0., .5*np.pi, np.pi, 1.5*np.pi, 2*np.pi]) -ax2.set_xticklabels(["0", r"$\frac{1}{2}\pi$", +ax2.set_xticklabels(["0ドル$", r"$\frac{1}{2}\pi$", r"$\pi$", r"$\frac{3}{2}\pi$", r"2ドル\pi$"]) ax2.axis["right"].major_ticklabels.set_visible(False) Modified: trunk/matplotlib/examples/pylab_examples/axes_zoom_effect.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/axes_zoom_effect.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/pylab_examples/axes_zoom_effect.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -1,7 +1,7 @@ from matplotlib.transforms import Bbox, TransformedBbox, \ blended_transform_factory -from mpl_toolkits.axes_grid.inset_locator import BboxPatch, BboxConnector,\ +from mpl_toolkits.axes_grid1.inset_locator import BboxPatch, BboxConnector,\ BboxConnectorPatch Modified: trunk/matplotlib/examples/pylab_examples/demo_text_rotation_mode.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/demo_text_rotation_mode.py 2010年04月06日 19:47:30 UTC (rev 8225) +++ trunk/matplotlib/examples/pylab_examples/demo_text_rotation_mode.py 2010年04月06日 20:38:31 UTC (rev 8226) @@ -1,11 +1,11 @@ #clf() -from mpl_toolkits.axes_grid.axes_grid import AxesGrid +from mpl_toolkits.axes_grid1.axes_grid import ImageGrid def test_rotation_mode(fig, mode, subplot_location): ha_list = "left center right".split() va_list = "top center baseline bottom".split() - grid = AxesGrid(fig, subplot_location, + grid = ImageGrid(fig, subplot_location, nrows_ncols=(len(va_list), len(ha_list)), share_all=True, aspect=True, #label_mode='1', cbar_mode=None) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8225 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8225&view=rev Author: leejjoon Date: 2010年04月06日 19:47:30 +0000 (2010年4月06日) Log Message: ----------- add axes_size.py in axes_grid Added Paths: ----------- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py 2010年04月06日 19:47:30 UTC (rev 8225) @@ -0,0 +1 @@ +from mpl_toolkits.axes_grid1.axes_size import * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8224 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8224&view=rev Author: leejjoon Date: 2010年04月06日 17:06:52 +0000 (2010年4月06日) Log Message: ----------- rebase axes_grid using axes_grid1 and axisartist modules Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/mpl_toolkits/axes_grid/anchored_artists.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/angle_helper.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_divider.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_rgb.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axis_artist.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axisline_style.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/clip_path.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/floating_axes.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_finder.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_helper_curvelinear.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/inset_locator.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/parasite_axes.py Removed Paths: ------------- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010年04月06日 17:05:51 UTC (rev 8223) +++ trunk/matplotlib/CHANGELOG 2010年04月06日 17:06:52 UTC (rev 8224) @@ -1,3 +1,5 @@ +2010年04月06日 rebase axes_grid using axes_grid1 and axisartist modules. -JJL + 2010年04月06日 axes_grid toolkit is splitted into two separate modules, axes_grid1 and axisartist. -JJL Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/anchored_artists.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/anchored_artists.py 2010年04月06日 17:05:51 UTC (rev 8223) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/anchored_artists.py 2010年04月06日 17:06:52 UTC (rev 8224) @@ -1,160 +1,6 @@ - -from matplotlib.patches import Rectangle, Ellipse - -import numpy as np - from matplotlib.offsetbox import AnchoredOffsetbox, AuxTransformBox, VPacker,\ TextArea, AnchoredText, DrawingArea, AnnotationBbox - -class AnchoredDrawingArea(AnchoredOffsetbox): - """ - AnchoredOffsetbox with DrawingArea - """ - - def __init__(self, width, height, xdescent, ydescent, - loc, pad=0.4, borderpad=0.5, prop=None, frameon=True, - **kwargs): - """ - *width*, *height*, *xdescent*, *ydescent* : the dimensions of the DrawingArea. - *prop* : font property. this is only used for scaling the paddings. - """ - - self.da = DrawingArea(width, height, xdescent, ydescent, clip=True) - self.drawing_area = self.da - - super(AnchoredDrawingArea, self).__init__(loc, pad=pad, borderpad=borderpad, - child=self.da, - prop=None, - frameon=frameon, - **kwargs) - - -class AnchoredAuxTransformBox(AnchoredOffsetbox): - def __init__(self, transform, loc, - pad=0.4, borderpad=0.5, prop=None, frameon=True, **kwargs): - - self.drawing_area = AuxTransformBox(transform) - - AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad, - child=self.drawing_area, - prop=prop, - frameon=frameon, - **kwargs) - - - -class AnchoredEllipse(AnchoredOffsetbox): - def __init__(self, transform, width, height, angle, loc, - pad=0.1, borderpad=0.1, prop=None, frameon=True, **kwargs): - """ - Draw an ellipse the size in data coordinate of the give axes. - - pad, borderpad in fraction of the legend font size (or prop) - """ - self._box = AuxTransformBox(transform) - self.ellipse = Ellipse((0,0), width, height, angle) - self._box.add_artist(self.ellipse) - - AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad, - child=self._box, - prop=prop, - frameon=frameon, **kwargs) - - - -class AnchoredSizeBar(AnchoredOffsetbox): - def __init__(self, transform, size, label, loc, - pad=0.1, borderpad=0.1, sep=2, prop=None, frameon=True, - **kwargs): - """ - Draw a horizontal bar with the size in data coordinate of the give axes. - A label will be drawn underneath (center-alinged). - - pad, borderpad in fraction of the legend font size (or prop) - sep in points. - """ - self.size_bar = AuxTransformBox(transform) - self.size_bar.add_artist(Rectangle((0,0), size, 0, fc="none")) - - self.txt_label = TextArea(label, minimumdescent=False) - - self._box = VPacker(children=[self.size_bar, self.txt_label], - align="center", - pad=0, sep=sep) - - AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad, - child=self._box, - prop=prop, - frameon=frameon, **kwargs) - - -if __name__ == "__main__": - - import matplotlib.pyplot as plt - - fig = plt.gcf() - fig.clf() - ax = plt.subplot(111) - - offsetbox = AnchoredText("Test", loc=6, pad=0.3, - borderpad=0.3, prop=None) - xy = (0.5, 0.5) - ax.plot([0.5], [0.5], "xk") - ab = AnnotationBbox(offsetbox, xy, - xybox=(1., .5), - xycoords='data', - boxcoords=("axes fraction", "data"), - arrowprops=dict(arrowstyle="->")) - #arrowprops=None) - - ax.add_artist(ab) - - - from matplotlib.patches import Circle - ada = AnchoredDrawingArea(20, 20, 0, 0, - loc=6, pad=0.1, borderpad=0.3, frameon=True) - p = Circle((10, 10), 10) - ada.da.add_artist(p) - - ab = AnnotationBbox(ada, (0.3, 0.4), - xybox=(1., 0.4), - xycoords='data', - boxcoords=("axes fraction", "data"), - arrowprops=dict(arrowstyle="->")) - #arrowprops=None) - - ax.add_artist(ab) - - - arr = np.arange(100).reshape((10,10)) - im = AnchoredImage(arr, - loc=4, - pad=0.5, borderpad=0.2, prop=None, frameon=True, - zoom=1, - cmap = None, - norm = None, - interpolation=None, - origin=None, - extent=None, - filternorm=1, - filterrad=4.0, - resample = False, - ) - - ab = AnnotationBbox(im, (0.5, 0.5), - xybox=(-10., 10.), - xycoords='data', - boxcoords="offset points", - arrowprops=dict(arrowstyle="->")) - #arrowprops=None) - - ax.add_artist(ab) - - ax.set_xlim(0, 1) - ax.set_ylim(0, 1) - - - plt.draw() - plt.show() - +from mpl_toolkits.axes_grid1.anchored_artists import \ + AnchoredDrawingArea, AnchoredAuxTransformBox, \ + AnchoredEllipse, AnchoredSizeBar Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/angle_helper.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/angle_helper.py 2010年04月06日 17:05:51 UTC (rev 8223) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/angle_helper.py 2010年04月06日 17:06:52 UTC (rev 8224) @@ -1,345 +1 @@ -from math import floor - -import numpy as np -import math - -A = np.array - -from mpl_toolkits.axes_grid.grid_finder import ExtremeFinderSimple - -def select_step_degree(dv): - - degree_limits_ = [1.5, 3, 7, 13, 20, 40, 70, 120, 270, 520] - degree_steps_ = [ 1, 2, 5, 10, 15, 30, 45, 90, 180, 360] - degree_factors = [1.] * len(degree_steps_) - - minsec_limits_ = [1.5, 2.5, 3.5, 8, 11, 18, 25, 45] - minsec_steps_ = [1, 2, 3, 5, 10, 15, 20, 30] - - minute_limits_ = A(minsec_limits_)*(1./60.) - minute_factors = [60.] * len(minute_limits_) - - second_limits_ = A(minsec_limits_)*(1./3600.) - second_factors = [3600.] * len(second_limits_) - - degree_limits = np.concatenate([second_limits_, - minute_limits_, - degree_limits_]) - - degree_steps = np.concatenate([minsec_steps_, - minsec_steps_, - degree_steps_]) - - degree_factors = np.concatenate([second_factors, - minute_factors, - degree_factors]) - - n = degree_limits.searchsorted(dv) - step = degree_steps[n] - factor = degree_factors[n] - - return step, factor - - - -def select_step_hour(dv): - - hour_limits_ = [1.5, 2.5, 3.5, 5, 7, 10, 15, 21, 36] - hour_steps_ = [1, 2 , 3, 4, 6, 8, 12, 18, 24] - hour_factors = [1.] * len(hour_steps_) - - minsec_limits_ = [1.5, 2.5, 3.5, 4.5, 5.5, 8, 11, 14, 18, 25, 45] - minsec_steps_ = [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30] - - minute_limits_ = A(minsec_limits_)*(1./60.) - minute_factors = [60.] * len(minute_limits_) - - second_limits_ = A(minsec_limits_)*(1./3600.) - second_factors = [3600.] * len(second_limits_) - - hour_limits = np.concatenate([second_limits_, - minute_limits_, - hour_limits_]) - - hour_steps = np.concatenate([minsec_steps_, - minsec_steps_, - hour_steps_]) - - hour_factors = np.concatenate([second_factors, - minute_factors, - hour_factors]) - - n = hour_limits.searchsorted(dv) - step = hour_steps[n] - factor = hour_factors[n] - - return step, factor - - -def select_step_sub(dv): - - # subarcsec or degree - tmp = 10.**(int(math.log10(dv))-1.) - dv2 = dv/tmp - substep_limits_ = [1.5, 3., 7.] - substep_steps_ = [1. , 2., 5.] - - factor = 1./tmp - - if 1.5*tmp >= dv: - step = 1 - elif 3.*tmp >= dv: - step = 2 - elif 7.*tmp >= dv: - step = 5 - else: - step = 1 - factor = 0.1*factor - - return step, factor - - -def select_step(v1, v2, nv, hour=False): - - if v1 > v2: - v1, v2 = v2, v1 - - A = np.array - - dv = float(v2 - v1) / nv - - if hour: - _select_step = select_step_hour - cycle = 24. - else: - _select_step = select_step_degree - cycle = 360. - - # for degree - if dv > 1./3600.: - #print "degree" - step, factor = _select_step(dv) - else: - step, factor = select_step_sub(dv*3600.) - #print "feac", step, factor - - factor = factor * 3600. - - - f1, f2, fstep = v1*factor, v2*factor, step/factor - levs = np.arange(math.floor(f1/step), math.ceil(f2/step)+0.5, - 1, dtype="i") * step - - # n : number valid levels. If there is a cycle, e.g., [0, 90, 180, - # 270, 360], the a grid line needs to be extend from 0 to 360, so - # we need to return the whole array. However, the last level (360) - # needs to be ignored often. In this case, so we return n=4. - - n = len(levs) - - - # we need to check the range of values - # for example, -90 to 90, 0 to 360, - - - if factor == 1. and (levs[-1] >= levs[0]+cycle): # check for cycle - nv = int(cycle / step) - levs = np.arange(0, nv, 1) * step - n = len(levs) - - return np.array(levs), n, factor - - -def select_step24(v1, v2, nv): - v1, v2 = v1/15., v2/15. - levs, n, factor = select_step(v1, v2, nv, hour=True) - return levs*15., n, factor - -def select_step360(v1, v2, nv): - return select_step(v1, v2, nv, hour=False) - - - - -class LocatorHMS(object): - def __init__(self, den): - self.den = den - def __call__(self, v1, v2): - return select_step24(v1, v2, self.den) - - -class LocatorDMS(object): - def __init__(self, den): - self.den = den - def __call__(self, v1, v2): - return select_step360(v1, v2, self.den) - - -class FormatterHMS(object): - def __call__(self, direction, factor, values): # hour - if len(values) == 0: - return [] - ss = [[-1, 1][v>0] for v in values] - values = np.abs(values)/15. - - if factor == 1: - return ["$%d^{\mathrm{h}}$" % (int(v),) for v in values] - elif factor == 60: - return ["$%d^{\mathrm{h}},円%02d^{\mathrm{m}}$" % (s*floor(v/60.), v%60) \ - for s, v in zip(ss, values)] - elif factor == 3600: - if ss[-1] == -1: - inverse_order = True - values = values[::-1] - else: - inverse_order = False - degree = floor(values[0]/3600.) - hm_fmt = "$%d^{\mathrm{h}},円%02d^{\mathrm{m}},円" - s_fmt = "%02d^{\mathrm{s}}$" - l_hm_old = "" - r = [] - for v in values-3600*degree: - l_hm = hm_fmt % (ss[0]*degree, floor(v/60.)) - l_s = s_fmt % (v%60,) - if l_hm != l_hm_old: - l_hm_old = l_hm - l = l_hm + l_s - else: - l = "$"+l_s - r.append(l) - if inverse_order: - return r[::-1] - else: - return r - #return [fmt % (ss[0]*degree, floor(v/60.), v%60) \ - # for s, v in zip(ss, values-3600*degree)] - else: # factor > 3600. - return [r"$%s^{\mathrm{h}}$" % (str(v),) for v in ss*values] - - -class FormatterDMS(object): - def __call__(self, direction, factor, values): - if len(values) == 0: - return [] - ss = [[-1, 1][v>0] for v in values] - values = np.abs(values) - if factor == 1: - return ["$%d^{\circ}$" % (s*int(v),) for (s, v) in zip(ss, values)] - elif factor == 60: - return ["$%d^{\circ},円%02d^{\prime}$" % (s*floor(v/60.), v%60) \ - for s, v in zip(ss, values)] - elif factor == 3600: - if ss[-1] == -1: - inverse_order = True - values = values[::-1] - else: - inverse_order = False - degree = floor(values[0]/3600.) - hm_fmt = "$%d^{\circ},円%02d^{\prime},円" - s_fmt = "%02d^{\prime\prime}$" - l_hm_old = "" - r = [] - for v in values-3600*degree: - l_hm = hm_fmt % (ss[0]*degree, floor(v/60.)) - l_s = s_fmt % (v%60,) - if l_hm != l_hm_old: - l_hm_old = l_hm - l = l_hm + l_s - else: - l = "$"+l_s - r.append(l) - if inverse_order: - return r[::-1] - else: - return r - #return [fmt % (ss[0]*degree, floor(v/60.), v%60) \ - # for s, v in zip(ss, values-3600*degree)] - else: # factor > 3600. - return [r"$%s^{\circ}$" % (str(v),) for v in ss*values] - - - - -class ExtremeFinderCycle(ExtremeFinderSimple): - """ - When there is a cycle, e.g., longitude goes from 0-360. - """ - def __init__(self, - nx, ny, - lon_cycle = 360., - lat_cycle = None, - lon_minmax = None, - lat_minmax = (-90, 90) - ): - #self.transfrom_xy = transform_xy - #self.inv_transfrom_xy = inv_transform_xy - self.nx, self.ny = nx, ny - self.lon_cycle, self.lat_cycle = lon_cycle, lat_cycle - self.lon_minmax = lon_minmax - self.lat_minmax = lat_minmax - - - def __call__(self, transform_xy, x1, y1, x2, y2): - """ - get extreme values. - - x1, y1, x2, y2 in image coordinates (0-based) - nx, ny : number of dvision in each axis - """ - x_, y_ = np.linspace(x1, x2, self.nx), np.linspace(y1, y2, self.ny) - x, y = np.meshgrid(x_, y_) - lon, lat = transform_xy(np.ravel(x), np.ravel(y)) - - # iron out jumps, but algorithm should be improved. - # Tis is just naive way of doing and my fail for some cases. - if self.lon_cycle is not None: - lon0 = np.nanmin(lon) - lon -= 360. * ((lon - lon0) > 180.) - if self.lat_cycle is not None: - lat0 = np.nanmin(lat) - lat -= 360. * ((lat - lat0) > 180.) - - lon_min, lon_max = np.nanmin(lon), np.nanmax(lon) - lat_min, lat_max = np.nanmin(lat), np.nanmax(lat) - - lon_min, lon_max, lat_min, lat_max = \ - self._adjust_extremes(lon_min, lon_max, lat_min, lat_max) - - return lon_min, lon_max, lat_min, lat_max - - - def _adjust_extremes(self, lon_min, lon_max, lat_min, lat_max): - - lon_min, lon_max, lat_min, lat_max = \ - self._add_pad(lon_min, lon_max, lat_min, lat_max) - - # check cycle - if self.lon_cycle: - lon_max = min(lon_max, lon_min + self.lon_cycle) - if self.lat_cycle: - lat_max = min(lat_max, lat_min + self.lat_cycle) - - if self.lon_minmax is not None: - min0 = self.lon_minmax[0] - lon_min = max(min0, lon_min) - max0 = self.lon_minmax[1] - lon_max = min(max0, lon_max) - - if self.lat_minmax is not None: - min0 = self.lat_minmax[0] - lat_min = max(min0, lat_min) - max0 = self.lat_minmax[1] - lat_max = min(max0, lat_max) - - return lon_min, lon_max, lat_min, lat_max - - - - - -if __name__ == "__main__": - #test2() - print select_step360(21.2, 33.3, 5) - print select_step360(20+21.2/60., 21+33.3/60., 5) - print select_step360(20.5+21.2/3600., 20.5+33.3/3600., 5) - print select_step360(20+21.2/60., 20+53.3/60., 5) +from mpl_toolkits.axisartist.angle_helper import * Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_divider.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_divider.py 2010年04月06日 17:05:51 UTC (rev 8223) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_divider.py 2010年04月06日 17:06:52 UTC (rev 8224) @@ -1,751 +1,8 @@ -""" -The axes_divider module provide helper classes to adjust the positions of -multiple axes at the drawing time. +#from mpl_toolkits.axes_grid1.axes_divider import * - Divider: this is the class that is used calculates the axes - position. It divides the given renctangular area into several sub - rectangles. You intialize the divider by setting the horizontal - and vertical list of sizes that the division will be based on. You - then use the new_locator method, whose return value is a callable - object that can be used to set the axes_locator of the axes. +from mpl_toolkits.axes_grid1.axes_divider import Divider, AxesLocator, SubplotDivider, \ + AxesDivider, locatable_axes_factory, make_axes_locatable -""" - -import matplotlib.transforms as mtransforms - -from matplotlib.axes import SubplotBase - -import new - -import axes_size as Size - - -class Divider(object): - """ - This is the class that is used calculates the axes position. It - divides the given renctangular area into several - sub-rectangles. You intialize the divider by setting the - horizontal and vertical lists of sizes - (:mod:`mpl_toolkits.axes_grid.axes_size`) that the division will - be based on. You then use the new_locator method to create a - callable object that can be used to as the axes_locator of the - axes. - """ - - - def __init__(self, fig, pos, horizontal, vertical, aspect=None, anchor="C"): - """ - :param fig: matplotlib figure - :param pos: position (tuple of 4 floats) of the rectangle that - will be divided. - :param horizontal: list of sizes - (:mod:`~mpl_toolkits.axes_grid.axes_size`) - for horizontal division - :param vertical: list of sizes - (:mod:`~mpl_toolkits.axes_grid.axes_size`) - for vertical division - :param aspect: if True, the overall rectalngular area is reduced - so that the relative part of the horizontal and - vertical scales have same scale. - :param anchor: Detrmine how the reduced rectangle is placed - when aspect is True, - """ - - self._fig = fig - self._pos = pos - self._horizontal = horizontal - self._vertical = vertical - self._anchor = anchor - self._aspect = aspect - self._xrefindex = 0 - self._yrefindex = 0 - - - @staticmethod - def _calc_k(l, total_size, renderer): - - rs_sum, as_sum = 0., 0. - - for s in l: - _rs, _as = s.get_size(renderer) - rs_sum += _rs - as_sum += _as - - if rs_sum != 0.: - k = (total_size - as_sum) / rs_sum - return k - else: - return 0. - - - @staticmethod - def _calc_offsets(l, k, renderer): - - offsets = [0.] - - for s in l: - _rs, _as = s.get_size(renderer) - offsets.append(offsets[-1] + _rs*k + _as) - - return offsets - - - def set_position(self, pos): - """ - set the position of the rectangle. - - :param pos: position (tuple of 4 floats) of the rectangle that - will be divided. - """ - self._pos = pos - - def get_position(self): - "return the position of the rectangle." - return self._pos - - def set_anchor(self, anchor): - """ - :param anchor: anchor position - - ===== ============ - value description - ===== ============ - 'C' Center - 'SW' bottom left - 'S' bottom - 'SE' bottom right - 'E' right - 'NE' top right - 'N' top - 'NW' top left - 'W' left - ===== ============ - - """ - if anchor in mtransforms.Bbox.coefs.keys() or len(anchor) == 2: - self._anchor = anchor - else: - raise ValueError('argument must be among %s' % - ', '.join(mtransforms.BBox.coefs.keys())) - - def get_anchor(self): - "return the anchor" - return self._anchor - - def set_horizontal(self, h): - """ - :param horizontal: list of sizes - (:mod:`~mpl_toolkits.axes_grid.axes_size`) - for horizontal division - """ - self._horizontal = h - - - def get_horizontal(self): - "return horizontal sizes" - return self._horizontal - - def set_vertical(self, v): - """ - :param horizontal: list of sizes - (:mod:`~mpl_toolkits.axes_grid.axes_size`) - for horizontal division - """ - self._vertical = v - - def get_vertical(self): - "return vertical sizes" - return self._vertical - - - def set_aspect(self, aspect=False): - """ - :param anchor: True or False - """ - self._aspect = aspect - - def get_aspect(self): - "return aspect" - return self._aspect - - - def locate(self, nx, ny, nx1=None, ny1=None, renderer=None): - """ - - :param nx, nx1: Integers specifying the column-position of the - cell. When nx1 is None, a single nx-th column is - specified. Otherwise location of columns spanning between nx - to nx1 (but excluding nx1-th column) is specified. - - :param ny, ny1: same as nx and nx1, but for row positions. - """ - - - figW,figH = self._fig.get_size_inches() - x, y, w, h = self.get_position() - - k_h = self._calc_k(self._horizontal, figW*w, renderer) - k_v = self._calc_k(self._vertical, figH*h, renderer) - - if self.get_aspect(): - k = min(k_h, k_v) - ox = self._calc_offsets(self._horizontal, k, renderer) - oy = self._calc_offsets(self._vertical, k, renderer) - - ww = (ox[-1] - ox[0])/figW - hh = (oy[-1] - oy[0])/figH - pb = mtransforms.Bbox.from_bounds(x, y, w, h) - pb1 = mtransforms.Bbox.from_bounds(x, y, ww, hh) - pb1_anchored = pb1.anchored(self.get_anchor(), pb) - x0, y0 = pb1_anchored.x0, pb1_anchored.y0 - - else: - ox = self._calc_offsets(self._horizontal, k_h, renderer) - oy = self._calc_offsets(self._vertical, k_v, renderer) - x0, y0 = x, y - - - if nx1 is None: - nx1=nx+1 - if ny1 is None: - ny1=ny+1 - - x1, w1 = x0 + ox[nx]/figW, (ox[nx1] - ox[nx])/figW - y1, h1 = y0 + oy[ny]/figH, (oy[ny1] - oy[ny])/figH - - return mtransforms.Bbox.from_bounds(x1, y1, w1, h1) - - - def new_locator(self, nx, ny, nx1=None, ny1=None): - """ - returns a new locator - (:class:`mpl_toolkits.axes_grid.axes_divider.AxesLocator`) for - specified cell. - - :param nx, nx1: Integers specifying the column-position of the - cell. When nx1 is None, a single nx-th column is - specified. Otherwise location of columns spanning between nx - to nx1 (but excluding nx1-th column) is specified. - - :param ny, ny1: same as nx and nx1, but for row positions. - """ - return AxesLocator(self, nx, ny, nx1, ny1) - - - -class AxesLocator(object): - """ - A simple callable object, initiallized with AxesDivider class, - returns the position and size of the given cell. - """ - def __init__(self, axes_divider, nx, ny, nx1=None, ny1=None): - """ - :param axes_divider: An instance of AxesDivider class. - - :param nx, nx1: Integers specifying the column-position of the - cell. When nx1 is None, a single nx-th column is - specified. Otherwise location of columns spanning between nx - to nx1 (but excluding nx1-th column) is is specified. - - :param ny, ny1: same as nx and nx1, but for row positions. - """ - self._axes_divider = axes_divider - - _xrefindex = axes_divider._xrefindex - _yrefindex = axes_divider._yrefindex - - self._nx, self._ny = nx - _xrefindex, ny - _yrefindex - - if nx1 is None: - nx1 = nx+1 - if ny1 is None: - ny1 = ny+1 - - self._nx1 = nx1 - _xrefindex - self._ny1 = ny1 - _yrefindex - - - def __call__(self, axes, renderer): - - _xrefindex = self._axes_divider._xrefindex - _yrefindex = self._axes_divider._yrefindex - - return self._axes_divider.locate(self._nx + _xrefindex, - self._ny + _yrefindex, - self._nx1 + _xrefindex, - self._ny1 + _yrefindex, - renderer) - - - -class SubplotDivider(Divider): - """ - The Divider class whose rectangle area is specified as a subplot grometry. - """ - - - def __init__(self, fig, *args, **kwargs): - """ - *fig* is a :class:`matplotlib.figure.Figure` instance. - - *args* is the tuple (*numRows*, *numCols*, *plotNum*), where - the array of subplots in the figure has dimensions *numRows*, - *numCols*, and where *plotNum* is the number of the subplot - being created. *plotNum* starts at 1 in the upper left - corner and increases to the right. - - If *numRows* <= *numCols* <= *plotNum* < 10, *args* can be the - decimal integer *numRows* * 100 + *numCols* * 10 + *plotNum*. - """ - - self.figure = fig - - if len(args)==1: - s = str(args[0]) - if len(s) != 3: - raise ValueError('Argument to subplot must be a 3 digits long') - rows, cols, num = map(int, s) - elif len(args)==3: - rows, cols, num = args - else: - raise ValueError( 'Illegal argument to subplot') - - - total = rows*cols - num -= 1 # convert from matlab to python indexing - # ie num in range(0,total) - if num >= total: - raise ValueError( 'Subplot number exceeds total subplots') - self._rows = rows - self._cols = cols - self._num = num - - self.update_params() - - pos = self.figbox.bounds - horizontal = kwargs.pop("horizontal", []) - vertical = kwargs.pop("vertical", []) - aspect = kwargs.pop("aspect", None) - anchor = kwargs.pop("anchor", "C") - - if kwargs: - raise Exception("") - - Divider.__init__(self, fig, pos, horizontal, vertical, - aspect=aspect, anchor=anchor) - - - def get_position(self): - "return the bounds of the subplot box" - self.update_params() - return self.figbox.bounds - - - def update_params(self): - 'update the subplot position from fig.subplotpars' - - rows = self._rows - cols = self._cols - num = self._num - - pars = self.figure.subplotpars - left = pars.left - right = pars.right - bottom = pars.bottom - top = pars.top - wspace = pars.wspace - hspace = pars.hspace - totWidth = right-left - totHeight = top-bottom - - figH = totHeight/(rows + hspace*(rows-1)) - sepH = hspace*figH - - figW = totWidth/(cols + wspace*(cols-1)) - sepW = wspace*figW - - rowNum, colNum = divmod(num, cols) - - figBottom = top - (rowNum+1)*figH - rowNum*sepH - figLeft = left + colNum*(figW + sepW) - - self.figbox = mtransforms.Bbox.from_bounds(figLeft, figBottom, - figW, figH) - - -class AxesDivider(Divider): - """ - Divider based on the pre-existing axes. - """ - - def __init__(self, axes): - """ - :param axes: axes - """ - self._axes = axes - self._xref = Size.AxesX(axes) - self._yref = Size.AxesY(axes) - Divider.__init__(self, fig=axes.get_figure(), pos=None, - horizontal=[self._xref], vertical=[self._yref], - aspect=None, anchor="C") - - def _get_new_axes(self, **kwargs): - axes = self._axes - - axes_class = kwargs.pop("axes_class", None) - - if axes_class is None: - if isinstance(axes, SubplotBase): - axes_class = axes._axes_class - else: - axes_class = type(axes) - - ax = axes_class(axes.get_figure(), - axes.get_position(original=True), **kwargs) - - return ax - - - def new_horizontal(self, size, pad=None, pack_start=False, **kwargs): - """ - Add a new axes on the right (or left) side of the main axes. - - :param size: A width of the axes. A :mod:`~mpl_toolkits.axes_grid.axes_size` - instance or if float or string is given, *from_any* - fucntion is used to create one, with *ref_size* set to AxesX instance - of the current axes. - :param pad: pad between the axes. It takes same argument as *size*. - :param pack_start: If False, the new axes is appended at the end - of the list, i.e., it became the right-most axes. If True, it is - inseted at the start of the list, and becomes the left-most axes. - - All extra keywords argument is passed to when creating a axes. - if *axes_class* is given, the new axes will be created as an - instance of the given class. Otherwise, the same class of the - main axes will be used. if Not provided - - """ - - if pad: - if not isinstance(pad, Size._Base): - pad = Size.from_any(pad, - fraction_ref=self._xref) - if pack_start: - self._horizontal.insert(0, pad) - self._xrefindex += 1 - else: - self._horizontal.append(pad) - - if not isinstance(size, Size._Base): - size = Size.from_any(size, - fraction_ref=self._xref) - - if pack_start: - self._horizontal.insert(0, size) - self._xrefindex += 1 - locator = self.new_locator(nx=0, ny=0) - else: - self._horizontal.append(size) - locator = self.new_locator(nx=len(self._horizontal)-1, ny=0) - - ax = self._get_new_axes(**kwargs) - ax.set_axes_locator(locator) - - return ax - - def new_vertical(self, size, pad=None, pack_start=False, **kwargs): - """ - Add a new axes on the top (or bottom) side of the main axes. - - :param size: A height of the axes. A :mod:`~mpl_toolkits.axes_grid.axes_size` - instance or if float or string is given, *from_any* - fucntion is used to create one, with *ref_size* set to AxesX instance - of the current axes. - :param pad: pad between the axes. It takes same argument as *size*. - :param pack_start: If False, the new axes is appended at the end - of the list, i.e., it became the top-most axes. If True, it is - inseted at the start of the list, and becomes the bottom-most axes. - - All extra keywords argument is passed to when creating a axes. - if *axes_class* is given, the new axes will be created as an - instance of the given class. Otherwise, the same class of the - main axes will be used. if Not provided - - """ - - if pad: - if not isinstance(pad, Size._Base): - pad = Size.from_any(pad, - fraction_ref=self._yref) - if pack_start: - self._vertical.insert(0, pad) - self._yrefindex += 1 - else: - self._vertical.append(pad) - - if not isinstance(size, Size._Base): - size = Size.from_any(size, - fraction_ref=self._yref) - - if pack_start: - self._vertical.insert(0, size) - self._yrefindex += 1 - locator = self.new_locator(nx=0, ny=0) - else: - self._vertical.append(size) - locator = self.new_locator(nx=0, ny=len(self._vertical)-1) - - ax = self._get_new_axes(**kwargs) - ax.set_axes_locator(locator) - - return ax - - - def append_axes(self, position, size, pad=None, **kwargs): - """ - create an axes at the given *position* with the same height - (or width) of the main axes. - - *position* - ["left"|"right"|"bottom"|"top"] - - *size* and *pad* should be axes_grid.axes_size compatible. - """ - - if position == "left": - ax = self.new_horizontal(size, pad, pack_start=True, **kwargs) - elif position == "right": - ax = self.new_horizontal(size, pad, pack_start=False, **kwargs) - elif position == "bottom": - ax = self.new_vertical(size, pad, pack_start=True, **kwargs) - elif position == "top": - ax = self.new_vertical(size, pad, pack_start=False, **kwargs) - else: - raise ValueError("the position must be one of left, right, bottom, or top") - - self._fig.add_axes(ax) - return ax - - def get_aspect(self): - if self._aspect is None: - aspect = self._axes.get_aspect() - if aspect == "auto": - return False - else: - return True - else: - return self._aspect - - def get_position(self): - if self._pos is None: - bbox = self._axes.get_position(original=True) - return bbox.bounds - else: - return self._pos - - def get_anchor(self): - if self._anchor is None: - return self._axes.get_anchor() - else: - return self._anchor - - - -class LocatableAxesBase: - def __init__(self, *kl, **kw): - - self._axes_class.__init__(self, *kl, **kw) - - self._locator = None - self._locator_renderer = None - - def set_axes_locator(self, locator): - self._locator = locator - - def get_axes_locator(self): - return self._locator - - def apply_aspect(self, position=None): - - if self.get_axes_locator() is None: - self._axes_class.apply_aspect(self, position) - else: - pos = self.get_axes_locator()(self, self._locator_renderer) - self._axes_class.apply_aspect(self, position=pos) - - - def draw(self, renderer=None, inframe=False): - - self._locator_renderer = renderer - - self._axes_class.draw(self, renderer, inframe) - - - -_locatableaxes_classes = {} -def locatable_axes_factory(axes_class): - - new_class = _locatableaxes_classes.get(axes_class) - if new_class is None: - new_class = new.classobj("Locatable%s" % (axes_class.__name__), - (LocatableAxesBase, axes_class), - {'_axes_class': axes_class}) - _locatableaxes_classes[axes_class] = new_class - - return new_class - -#if hasattr(maxes.Axes, "get_axes_locator"): -# LocatableAxes = maxes.Axes -#else: - from mpl_toolkits.axes_grid.axislines import Axes LocatableAxes = locatable_axes_factory(Axes) - -def make_axes_locatable(axes): - if not hasattr(axes, "set_axes_locator"): - new_class = locatable_axes_factory(type(axes)) - axes.__class__ = new_class - - divider = AxesDivider(axes) - locator = divider.new_locator(nx=0, ny=0) - axes.set_axes_locator(locator) - - return divider - - -def get_demo_image(): - # prepare image - delta = 0.5 - - extent = (-3,4,-4,3) - import numpy as np - x = np.arange(-3.0, 4.001, delta) - y = np.arange(-4.0, 3.001, delta) - X, Y = np.meshgrid(x, y) - import matplotlib.mlab as mlab - Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) - Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1) - Z = (Z1 - Z2) * 10 - - return Z, extent - -def demo_locatable_axes(): - import matplotlib.pyplot as plt - - fig1 = plt.figure(1, (6, 6)) - fig1.clf() - - ## PLOT 1 - # simple image & colorbar - ax = fig1.add_subplot(2, 2, 1) - - Z, extent = get_demo_image() - - im = ax.imshow(Z, extent=extent, interpolation="nearest") - cb = plt.colorbar(im) - plt.setp(cb.ax.get_yticklabels(), visible=False) - - - ## PLOT 2 - # image and colorbar whose location is adjusted in the drawing time. - # a hard way - - divider = SubplotDivider(fig1, 2, 2, 2, aspect=True) - - # axes for image - ax = LocatableAxes(fig1, divider.get_position()) - - # axes for coloarbar - ax_cb = LocatableAxes(fig1, divider.get_position()) - - h = [Size.AxesX(ax), # main axes - Size.Fixed(0.05), # padding, 0.1 inch - Size.Fixed(0.2), # colorbar, 0.3 inch - ] - - v = [Size.AxesY(ax)] - - divider.set_horizontal(h) - divider.set_vertical(v) - - ax.set_axes_locator(divider.new_locator(nx=0, ny=0)) - ax_cb.set_axes_locator(divider.new_locator(nx=2, ny=0)) - - fig1.add_axes(ax) - fig1.add_axes(ax_cb) - - ax_cb.yaxis.set_ticks_position("right") - - Z, extent = get_demo_image() - - im = ax.imshow(Z, extent=extent, interpolation="nearest") - plt.colorbar(im, cax=ax_cb) - plt.setp(ax_cb.get_yticklabels(), visible=False) - - plt.draw() - #plt.colorbar(im, cax=ax_cb) - - - ## PLOT 3 - # image and colorbar whose location is adjusted in the drawing time. - # a easy way - - ax = fig1.add_subplot(2, 2, 3) - divider = make_axes_locatable(ax) - - ax_cb = divider.new_horizontal(size="5%", pad=0.05) - fig1.add_axes(ax_cb) - - im = ax.imshow(Z, extent=extent, interpolation="nearest") - plt.colorbar(im, cax=ax_cb) - plt.setp(ax_cb.get_yticklabels(), visible=False) - - - ## PLOT 4 - # two images side by sied with fixed padding. - - ax = fig1.add_subplot(2, 2, 4) - divider = make_axes_locatable(ax) - - ax2 = divider.new_horizontal(size="100%", pad=0.05) - fig1.add_axes(ax2) - - ax.imshow(Z, extent=extent, interpolation="nearest") - ax2.imshow(Z, extent=extent, interpolation="nearest") - plt.setp(ax2.get_yticklabels(), visible=False) - plt.draw() - plt.show() - - -def demo_fixed_size_axes(): - import matplotlib.pyplot as plt - - fig2 = plt.figure(2, (6, 6)) - - # The first items are for padding and the second items are for the axes. - # sizes are in inch. - h = [Size.Fixed(1.0), Size.Fixed(4.5)] - v = [Size.Fixed(0.7), Size.Fixed(5.)] - - divider = Divider(fig2, (0.0, 0.0, 1., 1.), h, v, aspect=False) - # the width and height of the rectangle is ignored. - - ax = LocatableAxes(fig2, divider.get_position()) - ax.set_axes_locator(divider.new_locator(nx=1, ny=1)) - - fig2.add_axes(ax) - - ax.plot([1,2,3]) - - plt.draw() - plt.show() - #plt.colorbar(im, cax=ax_cb) - - - - - -if __name__ == "__main__": - demo_locatable_axes() - demo_fixed_size_axes() Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py 2010年04月06日 17:05:51 UTC (rev 8223) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py 2010年04月06日 17:06:52 UTC (rev 8224) @@ -1,71 +1,9 @@ -import matplotlib.cbook as cbook -import matplotlib.pyplot as plt -import matplotlib.axes as maxes -#import matplotlib.colorbar as mcolorbar -import colorbar as mcolorbar -import matplotlib as mpl -import matplotlib.patches as mpatches -import matplotlib.lines as mlines -import matplotlib.ticker as ticker -from axes_divider import Size, SubplotDivider, LocatableAxes, Divider +import mpl_toolkits.axes_grid1.axes_grid as axes_grid_orig +from axes_divider import LocatableAxes -import numpy as np - -def _tick_only(ax, bottom_on, left_on): - bottom_off = not bottom_on - left_off = not left_on - [l.set_visible(bottom_off) for l in ax.get_xticklabels()] - [l.set_visible(left_off) for l in ax.get_yticklabels()] - ax.xaxis.label.set_visible(bottom_off) - ax.yaxis.label.set_visible(left_off) - if hasattr(ax, "_axislines"): - ax._axislines["bottom"].major_ticklabels.set_visible(bottom_off) - ax._axislines["left"].major_ticklabels.set_visible(left_off) - ax._axislines["bottom"].minor_ticklabels.set_visible(bottom_off) - ax._axislines["left"].minor_ticklabels.set_visible(left_off) - ax.axis["bottom"].label.set_visible(bottom_off) - ax.axis["left"].label.set_visible(left_off) - -class Colorbar(mcolorbar.Colorbar): - def _config_axes_deprecated(self, X, Y): - ''' - Make an axes patch and outline. - ''' - ax = self.ax - ax.set_frame_on(False) - ax.set_navigate(False) - xy = self._outline(X, Y) - ax.update_datalim(xy) - ax.set_xlim(*ax.dataLim.intervalx) - ax.set_ylim(*ax.dataLim.intervaly) - self.outline = mlines.Line2D(xy[:, 0], xy[:, 1], color=mpl.rcParams['axes.edgecolor'], - linewidth=mpl.rcParams['axes.linewidth']) - ax.add_artist(self.outline) - self.outline.set_clip_box(None) - self.outline.set_clip_path(None) - c = mpl.rcParams['axes.facecolor'] - self.patch = mpatches.Polygon(xy, edgecolor=c, - facecolor=c, - linewidth=0.01, - zorder=-1) - ax.add_artist(self.patch) - ticks, ticklabels, offset_string = self._ticker() - - if self.orientation == 'vertical': - ax.set_yticks(ticks) - ax.set_yticklabels(ticklabels) - ax.yaxis.get_major_formatter().set_offset_string(offset_string) - - else: - ax.set_xticks(ticks) - ax.set_xticklabels(ticklabels) - ax.xaxis.get_major_formatter().set_offset_string(offset_string) - - - -class CbarAxes(LocatableAxes): +class CbarAxes(axes_grid_orig.CbarAxesBase, LocatableAxes): def __init__(self, *kl, **kwargs): orientation=kwargs.pop("orientation", None) if orientation is None: @@ -74,706 +12,19 @@ self._default_label_on = False self.locator = None - super(CbarAxes, self).__init__(*kl, **kwargs) + super(LocatableAxes, self).__init__(*kl, **kwargs) - - def colorbar(self, mappable, **kwargs): - locator=kwargs.pop("locator", None) - if locator is None: - locator = ticker.MaxNLocator(5) - self.locator = locator - - kwargs["ticks"] = locator - - - self.hold(True) - if self.orientation in ["top", "bottom"]: - orientation="horizontal" - else: - orientation="vertical" - - cb = Colorbar(self, mappable, orientation=orientation, **kwargs) - #self._config_axes() - - def on_changed(m): - #print 'calling on changed', m.get_cmap().name - cb.set_cmap(m.get_cmap()) - cb.set_clim(m.get_clim()) - cb.update_bruteforce(m) - - self.cbid = mappable.callbacksSM.connect('changed', on_changed) - mappable.set_colorbar(cb, self) - return cb - def cla(self): - super(CbarAxes, self).cla() + super(LocatableAxes, self).cla() self._config_axes() - def _config_axes(self): - ''' - Make an axes patch and outline. - ''' - ax = self - ax.set_navigate(False) - for axis in ax.axis.values(): - axis.major_ticks.set_visible(False) - axis.minor_ticks.set_visible(False) - axis.major_ticklabels.set_visible(False) - axis.minor_ticklabels.set_visible(False) - axis.label.set_visible(False) +class Grid(axes_grid_orig.Grid): + _defaultLocatableAxesClass = LocatableAxes - axis = ax.axis[self.orientation] - axis.major_ticks.set_visible(True) - axis.minor_ticks.set_visible(True) - axis.major_ticklabels.set_size(int(axis.major_ticklabels.get_size()*.9)) - axis.major_tick_pad = 3 +class ImageGrid(axes_grid_orig.ImageGrid): + _defaultLocatableAxesClass = LocatableAxes + _defaultCbarAxesClass = CbarAxes - b = self._default_label_on - axis.major_ticklabels.set_visible(b) - axis.minor_ticklabels.set_visible(b) - axis.label.set_visible(b) - - - def toggle_label(self, b): - self._default_label_on = b - axis = self.axis[self.orientation] - axis.major_ticklabels.set_visible(b) - axis.minor_ticklabels.set_visible(b) - axis.label.set_visible(b) - - - -class Grid(object): - """ - A class that creates a grid of Axes. In matplotlib, the axes - location (and size) is specified in the normalized figure - coordinates. This may not be ideal for images that needs to be - displayed with a given aspect ratio. For example, displaying - images of a same size with some fixed padding between them cannot - be easily done in matplotlib. AxesGrid is used in such case. - """ - - def __init__(self, fig, - rect, - nrows_ncols, - ngrids = None, - direction="row", - axes_pad = 0.02, - add_all=True, - share_all=False, - share_x=True, - share_y=True, - #aspect=True, - label_mode="L", - axes_class=None, - ): - """ - Build an :class:`Grid` instance with a grid nrows*ncols - :class:`~matplotlib.axes.Axes` in - :class:`~matplotlib.figure.Figure` *fig* with - *rect=[left, bottom, width, height]* (in - :class:`~matplotlib.figure.Figure` coordinates) or - the subplot position code (e.g., "121"). - - Optional keyword arguments: - - ================ ======== ========================================= - Keyword Default Description - ================ ======== ========================================= - direction "row" [ "row" | "column" ] - axes_pad 0.02 float| pad betweein axes given in inches - add_all True [ True | False ] - share_all False [ True | False ] - share_x True [ True | False ] - share_y True [ True | False ] - label_mode "L" [ "L" | "1" | "all" ] - axes_class None a type object which must be a subclass - of :class:`~matplotlib.axes.Axes` - ================ ======== ========================================= - """ - self._nrows, self._ncols = nrows_ncols - - if ngrids is None: - ngrids = self._nrows * self._ncols - else: - if (ngrids > self._nrows * self._ncols) or (ngrids <= 0): - raise Exception("") - - self.ngrids = ngrids - - self._init_axes_pad(axes_pad) - - if direction not in ["column", "row"]: - raise Exception("") - - self._direction = direction - - - if axes_class is None: - axes_class = LocatableAxes - axes_class_args = {} - else: - if isinstance(axes_class, maxes.Axes): - axes_class_args = {} - else: - axes_class, axes_class_args = axes_class - - self.axes_all = [] - self.axes_column = [[] for i in range(self._ncols)] - self.axes_row = [[] for i in range(self._nrows)] - - - h = [] - v = [] - if cbook.is_string_like(rect) or cbook.is_numlike(rect): - self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v, - aspect=False) - elif len(rect) == 3: - kw = dict(horizontal=h, vertical=v, aspect=False) - self._divider = SubplotDivider(fig, *rect, **kw) - elif len(rect) == 4: - self._divider = Divider(fig, rect, horizontal=h, vertical=v, - aspect=False) - else: - raise Exception("") - - - rect = self._divider.get_position() - - # reference axes - self._column_refax = [None for i in range(self._ncols)] - self._row_refax = [None for i in range(self._nrows)] - self._refax = None - - for i in range(self.ngrids): - - col, row = self._get_col_row(i) - - if share_all: - sharex = self._refax - sharey = self._refax - else: - if share_x: - sharex = self._column_refax[col] - else: - sharex = None - - if share_y: - sharey = self._row_refax[row] - else: - sharey = None - - ax = axes_class(fig, rect, sharex=sharex, sharey=sharey, - **axes_class_args) - - if share_all: - if self._refax is None: - self._refax = ax - else: - if sharex is None: - self._column_refax[col] = ax - if sharey is None: - self._row_refax[row] = ax - - self.axes_all.append(ax) - self.axes_column[col].append(ax) - self.axes_row[row].append(ax) - - self.axes_llc = self.axes_column[0][-1] - - self._update_locators() - - if add_all: - for ax in self.axes_all: - fig.add_axes(ax) - - self.set_label_mode(label_mode) - - - def _init_axes_pad(self, axes_pad): - self._axes_pad = axes_pad - - self._horiz_pad_size = Size.Fixed(axes_pad) - self._vert_pad_size = Size.Fixed(axes_pad) - - - def _update_locators(self): - - h = [] - - h_ax_pos = [] - h_cb_pos = [] - - for ax in self._column_refax: - #if h: h.append(Size.Fixed(self._axes_pad)) - if h: h.append(self._horiz_pad_size) - - h_ax_pos.append(len(h)) - - sz = Size.Scaled(1) - h.append(sz) - - v = [] - - v_ax_pos = [] - v_cb_pos = [] - for ax in self._row_refax[::-1]: - #if v: v.append(Size.Fixed(self._axes_pad)) - if v: v.append(self._vert_pad_size) - - v_ax_pos.append(len(v)) - sz = Size.Scaled(1) - v.append(sz) - - - for i in range(self.ngrids): - col, row = self._get_col_row(i) - locator = self._divider.new_locator(nx=h_ax_pos[col], - ny=v_ax_pos[self._nrows -1 - row]) - self.axes_all[i].set_axes_locator(locator) - - self._divider.set_horizontal(h) - self._divider.set_vertical(v) - - - - def _get_col_row(self, n): - if self._direction == "column": - col, row = divmod(n, self._nrows) - else: - row, col = divmod(n, self._ncols) - - return col, row - - - def __getitem__(self, i): - return self.axes_all[i] - - - def get_geometry(self): - """ - get geometry of the grid. Returns a tuple of two integer, - representing number of rows and number of columns. - """ - return self._nrows, self._ncols - - def set_axes_pad(self, axes_pad): - "set axes_pad" - self._axes_pad = axes_pad - - self._horiz_pad_size.fixed_size = axes_pad - self._vert_pad_size.fixed_size = axes_pad - - - def get_axes_pad(self): - "get axes_pad" - return self._axes_pad - - def set_aspect(self, aspect): - "set aspect" - self._divider.set_aspect(aspect) - - def get_aspect(self): - "get aspect" - return self._divider.get_aspect() - - def set_label_mode(self, mode): - "set label_mode" - if mode == "all": - for ax in self.axes_all: - _tick_only(ax, False, False) - elif mode == "L": - # left-most axes - for ax in self.axes_column[0][:-1]: - _tick_only(ax, bottom_on=True, left_on=False) - # lower-left axes - ax = self.axes_column[0][-1] - _tick_only(ax, bottom_on=False, left_on=False) - - for col in self.axes_column[1:]: - # axes with no labels - for ax in col[:-1]: - _tick_only(ax, bottom_on=True, left_on=True) - - # bottom - ax = col[-1] - _tick_only(ax, bottom_on=False, left_on=True) - - elif mode == "1": - for ax in self.axes_all: - _tick_only(ax, bottom_on=True, left_on=True) - - ax = self.axes_llc - _tick_only(ax, bottom_on=False, left_on=False) - - -class ImageGrid(Grid): - """ - A class that creates a grid of Axes. In matplotlib, the axes - location (and size) is specified in the normalized figure - coordinates. This may not be ideal for images that needs to be - displayed with a given aspect ratio. For example, displaying - images of a same size with some fixed padding between them cannot - be easily done in matplotlib. ImageGrid is used in such case. - """ - - def __init__(self, fig, - rect, - nrows_ncols, - ngrids = None, - direction="row", - axes_pad = 0.02, - add_all=True, - share_all=False, - aspect=True, - label_mode="L", - cbar_mode=None, - cbar_location="right", - cbar_pad=None, - cbar_size="5%", - cbar_set_cax=True, - axes_class=None, - ): - """ - Build an :class:`ImageGrid` instance with a grid nrows*ncols - :class:`~matplotlib.axes.Axes` in - :class:`~matplotlib.figure.Figure` *fig* with - *rect=[left, bottom, width, height]* (in - :class:`~matplotlib.figure.Figure` coordinates) or - the subplot position code (e.g., "121"). - - Optional keyword arguments: - - ================ ======== ========================================= - Keyword Default Description - ================ ======== ========================================= - direction "row" [ "row" | "column" ] - axes_pad 0.02 float| pad betweein axes given in inches - add_all True [ True | False ] - share_all False [ True | False ] - aspect True [ True | False ] - label_mode "L" [ "L" | "1" | "all" ] - cbar_mode None [ "each" | "single" ] - cbar_location "right" [ "right" | "top" ] - cbar_pad None - cbar_size "5%" - cbar_set_cax True [ True | False ] - axes_class None a type object which must be a subclass - of :class:`~matplotlib.axes.Axes` - ================ ======== ========================================= - - *cbar_set_cax* : if True, each axes in the grid has a cax - attribute that is bind to associated cbar_axes. - """ - self._nrows, self._ncols = nrows_ncols - - if ngrids is None: - ngrids = self._nrows * self._ncols - else: - if (ngrids > self._nrows * self._ncols) or (ngrids <= 0): - raise Exception("") - - self.ngrids = ngrids - - self._axes_pad = axes_pad - - self._colorbar_mode = cbar_mode - self._colorbar_location = cbar_location - if cbar_pad is None: - self._colorbar_pad = axes_pad - else: - self._colorbar_pad = cbar_pad - - self._colorbar_size = cbar_size - - self._init_axes_pad(axes_pad) - - if direction not in ["column", "row"]: - raise Exception("") - - self._direction = direction - - - if axes_class is None: - axes_class = LocatableAxes - axes_class_args = {} - else: - if isinstance(axes_class, maxes.Axes): - axes_class_args = {} - else: - axes_class, axes_class_args = axes_class - - cbar_axes_class = CbarAxes - - - self.axes_all = [] - self.axes_column = [[] for i in range(self._ncols)] - self.axes_row = [[] for i in range(self._nrows)] - - self.cbar_axes = [] - - h = [] - v = [] - if cbook.is_string_like(rect) or cbook.is_numlike(rect): - self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v, - aspec... [truncated message content]
Revision: 8223 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8223&view=rev Author: leejjoon Date: 2010年04月06日 17:05:51 +0000 (2010年4月06日) Log Message: ----------- axes_grid toolkit is splitted into two separate modules, axes_grid1 and axisartist. Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/setup.py Added Paths: ----------- trunk/matplotlib/lib/mpl_toolkits/axes_grid1/ trunk/matplotlib/lib/mpl_toolkits/axes_grid1/__init__.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/anchored_artists.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_divider.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_grid.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_rgb.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_size.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/colorbar.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/inset_locator.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/mpl_axes.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/parasite_axes.py trunk/matplotlib/lib/mpl_toolkits/axisartist/ trunk/matplotlib/lib/mpl_toolkits/axisartist/__init__.py trunk/matplotlib/lib/mpl_toolkits/axisartist/angle_helper.py trunk/matplotlib/lib/mpl_toolkits/axisartist/axis_artist.py trunk/matplotlib/lib/mpl_toolkits/axisartist/axisline_style.py trunk/matplotlib/lib/mpl_toolkits/axisartist/axislines.py trunk/matplotlib/lib/mpl_toolkits/axisartist/clip_path.py trunk/matplotlib/lib/mpl_toolkits/axisartist/floating_axes.py trunk/matplotlib/lib/mpl_toolkits/axisartist/grid_finder.py trunk/matplotlib/lib/mpl_toolkits/axisartist/grid_helper_curvelinear.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010年04月05日 18:46:18 UTC (rev 8222) +++ trunk/matplotlib/CHANGELOG 2010年04月06日 17:05:51 UTC (rev 8223) @@ -1,3 +1,6 @@ +2010年04月06日 axes_grid toolkit is splitted into two separate modules, + axes_grid1 and axisartist. -JJL + 2010年04月05日 Speed up import: import pytz only if and when it is needed. It is not needed if the rc timezone is UTC. - EF Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid1/__init__.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid1/__init__.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid1/__init__.py 2010年04月06日 17:05:51 UTC (rev 8223) @@ -0,0 +1,5 @@ +import axes_size as Size +from axes_divider import Divider, SubplotDivider, LocatableAxes, \ + make_axes_locatable +from axes_grid import Grid, ImageGrid, AxesGrid +#from axes_divider import make_axes_locatable Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid1/anchored_artists.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid1/anchored_artists.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid1/anchored_artists.py 2010年04月06日 17:05:51 UTC (rev 8223) @@ -0,0 +1,160 @@ + +from matplotlib.patches import Rectangle, Ellipse + +import numpy as np + +from matplotlib.offsetbox import AnchoredOffsetbox, AuxTransformBox, VPacker,\ + TextArea, AnchoredText, DrawingArea, AnnotationBbox + + +class AnchoredDrawingArea(AnchoredOffsetbox): + """ + AnchoredOffsetbox with DrawingArea + """ + + def __init__(self, width, height, xdescent, ydescent, + loc, pad=0.4, borderpad=0.5, prop=None, frameon=True, + **kwargs): + """ + *width*, *height*, *xdescent*, *ydescent* : the dimensions of the DrawingArea. + *prop* : font property. this is only used for scaling the paddings. + """ + + self.da = DrawingArea(width, height, xdescent, ydescent, clip=True) + self.drawing_area = self.da + + super(AnchoredDrawingArea, self).__init__(loc, pad=pad, borderpad=borderpad, + child=self.da, + prop=None, + frameon=frameon, + **kwargs) + + +class AnchoredAuxTransformBox(AnchoredOffsetbox): + def __init__(self, transform, loc, + pad=0.4, borderpad=0.5, prop=None, frameon=True, **kwargs): + + self.drawing_area = AuxTransformBox(transform) + + AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad, + child=self.drawing_area, + prop=prop, + frameon=frameon, + **kwargs) + + + +class AnchoredEllipse(AnchoredOffsetbox): + def __init__(self, transform, width, height, angle, loc, + pad=0.1, borderpad=0.1, prop=None, frameon=True, **kwargs): + """ + Draw an ellipse the size in data coordinate of the give axes. + + pad, borderpad in fraction of the legend font size (or prop) + """ + self._box = AuxTransformBox(transform) + self.ellipse = Ellipse((0,0), width, height, angle) + self._box.add_artist(self.ellipse) + + AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad, + child=self._box, + prop=prop, + frameon=frameon, **kwargs) + + + +class AnchoredSizeBar(AnchoredOffsetbox): + def __init__(self, transform, size, label, loc, + pad=0.1, borderpad=0.1, sep=2, prop=None, frameon=True, + **kwargs): + """ + Draw a horizontal bar with the size in data coordinate of the give axes. + A label will be drawn underneath (center-alinged). + + pad, borderpad in fraction of the legend font size (or prop) + sep in points. + """ + self.size_bar = AuxTransformBox(transform) + self.size_bar.add_artist(Rectangle((0,0), size, 0, fc="none")) + + self.txt_label = TextArea(label, minimumdescent=False) + + self._box = VPacker(children=[self.size_bar, self.txt_label], + align="center", + pad=0, sep=sep) + + AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad, + child=self._box, + prop=prop, + frameon=frameon, **kwargs) + + +if __name__ == "__main__": + + import matplotlib.pyplot as plt + + fig = plt.gcf() + fig.clf() + ax = plt.subplot(111) + + offsetbox = AnchoredText("Test", loc=6, pad=0.3, + borderpad=0.3, prop=None) + xy = (0.5, 0.5) + ax.plot([0.5], [0.5], "xk") + ab = AnnotationBbox(offsetbox, xy, + xybox=(1., .5), + xycoords='data', + boxcoords=("axes fraction", "data"), + arrowprops=dict(arrowstyle="->")) + #arrowprops=None) + + ax.add_artist(ab) + + + from matplotlib.patches import Circle + ada = AnchoredDrawingArea(20, 20, 0, 0, + loc=6, pad=0.1, borderpad=0.3, frameon=True) + p = Circle((10, 10), 10) + ada.da.add_artist(p) + + ab = AnnotationBbox(ada, (0.3, 0.4), + xybox=(1., 0.4), + xycoords='data', + boxcoords=("axes fraction", "data"), + arrowprops=dict(arrowstyle="->")) + #arrowprops=None) + + ax.add_artist(ab) + + + arr = np.arange(100).reshape((10,10)) + im = AnchoredImage(arr, + loc=4, + pad=0.5, borderpad=0.2, prop=None, frameon=True, + zoom=1, + cmap = None, + norm = None, + interpolation=None, + origin=None, + extent=None, + filternorm=1, + filterrad=4.0, + resample = False, + ) + + ab = AnnotationBbox(im, (0.5, 0.5), + xybox=(-10., 10.), + xycoords='data', + boxcoords="offset points", + arrowprops=dict(arrowstyle="->")) + #arrowprops=None) + + ax.add_artist(ab) + + ax.set_xlim(0, 1) + ax.set_ylim(0, 1) + + + plt.draw() + plt.show() + Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_divider.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_divider.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_divider.py 2010年04月06日 17:05:51 UTC (rev 8223) @@ -0,0 +1,753 @@ +""" +The axes_divider module provide helper classes to adjust the positions of +multiple axes at the drawing time. + + Divider: this is the class that is used calculates the axes + position. It divides the given renctangular area into several sub + rectangles. You intialize the divider by setting the horizontal + and vertical list of sizes that the division will be based on. You + then use the new_locator method, whose return value is a callable + object that can be used to set the axes_locator of the axes. + +""" + +import matplotlib.transforms as mtransforms + +from matplotlib.axes import SubplotBase + +import new + +import axes_size as Size + + +class Divider(object): + """ + This is the class that is used calculates the axes position. It + divides the given renctangular area into several + sub-rectangles. You intialize the divider by setting the + horizontal and vertical lists of sizes + (:mod:`mpl_toolkits.axes_grid.axes_size`) that the division will + be based on. You then use the new_locator method to create a + callable object that can be used to as the axes_locator of the + axes. + """ + + + def __init__(self, fig, pos, horizontal, vertical, aspect=None, anchor="C"): + """ + :param fig: matplotlib figure + :param pos: position (tuple of 4 floats) of the rectangle that + will be divided. + :param horizontal: list of sizes + (:mod:`~mpl_toolkits.axes_grid.axes_size`) + for horizontal division + :param vertical: list of sizes + (:mod:`~mpl_toolkits.axes_grid.axes_size`) + for vertical division + :param aspect: if True, the overall rectalngular area is reduced + so that the relative part of the horizontal and + vertical scales have same scale. + :param anchor: Detrmine how the reduced rectangle is placed + when aspect is True, + """ + + self._fig = fig + self._pos = pos + self._horizontal = horizontal + self._vertical = vertical + self._anchor = anchor + self._aspect = aspect + self._xrefindex = 0 + self._yrefindex = 0 + + + @staticmethod + def _calc_k(l, total_size, renderer): + + rs_sum, as_sum = 0., 0. + + for s in l: + _rs, _as = s.get_size(renderer) + rs_sum += _rs + as_sum += _as + + if rs_sum != 0.: + k = (total_size - as_sum) / rs_sum + return k + else: + return 0. + + + @staticmethod + def _calc_offsets(l, k, renderer): + + offsets = [0.] + + for s in l: + _rs, _as = s.get_size(renderer) + offsets.append(offsets[-1] + _rs*k + _as) + + return offsets + + + def set_position(self, pos): + """ + set the position of the rectangle. + + :param pos: position (tuple of 4 floats) of the rectangle that + will be divided. + """ + self._pos = pos + + def get_position(self): + "return the position of the rectangle." + return self._pos + + def set_anchor(self, anchor): + """ + :param anchor: anchor position + + ===== ============ + value description + ===== ============ + 'C' Center + 'SW' bottom left + 'S' bottom + 'SE' bottom right + 'E' right + 'NE' top right + 'N' top + 'NW' top left + 'W' left + ===== ============ + + """ + if anchor in mtransforms.Bbox.coefs.keys() or len(anchor) == 2: + self._anchor = anchor + else: + raise ValueError('argument must be among %s' % + ', '.join(mtransforms.BBox.coefs.keys())) + + def get_anchor(self): + "return the anchor" + return self._anchor + + def set_horizontal(self, h): + """ + :param horizontal: list of sizes + (:mod:`~mpl_toolkits.axes_grid.axes_size`) + for horizontal division + """ + self._horizontal = h + + + def get_horizontal(self): + "return horizontal sizes" + return self._horizontal + + def set_vertical(self, v): + """ + :param horizontal: list of sizes + (:mod:`~mpl_toolkits.axes_grid.axes_size`) + for horizontal division + """ + self._vertical = v + + def get_vertical(self): + "return vertical sizes" + return self._vertical + + + def set_aspect(self, aspect=False): + """ + :param anchor: True or False + """ + self._aspect = aspect + + def get_aspect(self): + "return aspect" + return self._aspect + + + def locate(self, nx, ny, nx1=None, ny1=None, renderer=None): + """ + + :param nx, nx1: Integers specifying the column-position of the + cell. When nx1 is None, a single nx-th column is + specified. Otherwise location of columns spanning between nx + to nx1 (but excluding nx1-th column) is specified. + + :param ny, ny1: same as nx and nx1, but for row positions. + """ + + + figW,figH = self._fig.get_size_inches() + x, y, w, h = self.get_position() + + k_h = self._calc_k(self._horizontal, figW*w, renderer) + k_v = self._calc_k(self._vertical, figH*h, renderer) + + if self.get_aspect(): + k = min(k_h, k_v) + ox = self._calc_offsets(self._horizontal, k, renderer) + oy = self._calc_offsets(self._vertical, k, renderer) + + ww = (ox[-1] - ox[0])/figW + hh = (oy[-1] - oy[0])/figH + pb = mtransforms.Bbox.from_bounds(x, y, w, h) + pb1 = mtransforms.Bbox.from_bounds(x, y, ww, hh) + pb1_anchored = pb1.anchored(self.get_anchor(), pb) + x0, y0 = pb1_anchored.x0, pb1_anchored.y0 + + else: + ox = self._calc_offsets(self._horizontal, k_h, renderer) + oy = self._calc_offsets(self._vertical, k_v, renderer) + x0, y0 = x, y + + + if nx1 is None: + nx1=nx+1 + if ny1 is None: + ny1=ny+1 + + x1, w1 = x0 + ox[nx]/figW, (ox[nx1] - ox[nx])/figW + y1, h1 = y0 + oy[ny]/figH, (oy[ny1] - oy[ny])/figH + + return mtransforms.Bbox.from_bounds(x1, y1, w1, h1) + + + def new_locator(self, nx, ny, nx1=None, ny1=None): + """ + returns a new locator + (:class:`mpl_toolkits.axes_grid.axes_divider.AxesLocator`) for + specified cell. + + :param nx, nx1: Integers specifying the column-position of the + cell. When nx1 is None, a single nx-th column is + specified. Otherwise location of columns spanning between nx + to nx1 (but excluding nx1-th column) is specified. + + :param ny, ny1: same as nx and nx1, but for row positions. + """ + return AxesLocator(self, nx, ny, nx1, ny1) + + + +class AxesLocator(object): + """ + A simple callable object, initiallized with AxesDivider class, + returns the position and size of the given cell. + """ + def __init__(self, axes_divider, nx, ny, nx1=None, ny1=None): + """ + :param axes_divider: An instance of AxesDivider class. + + :param nx, nx1: Integers specifying the column-position of the + cell. When nx1 is None, a single nx-th column is + specified. Otherwise location of columns spanning between nx + to nx1 (but excluding nx1-th column) is is specified. + + :param ny, ny1: same as nx and nx1, but for row positions. + """ + self._axes_divider = axes_divider + + _xrefindex = axes_divider._xrefindex + _yrefindex = axes_divider._yrefindex + + self._nx, self._ny = nx - _xrefindex, ny - _yrefindex + + if nx1 is None: + nx1 = nx+1 + if ny1 is None: + ny1 = ny+1 + + self._nx1 = nx1 - _xrefindex + self._ny1 = ny1 - _yrefindex + + + def __call__(self, axes, renderer): + + _xrefindex = self._axes_divider._xrefindex + _yrefindex = self._axes_divider._yrefindex + + return self._axes_divider.locate(self._nx + _xrefindex, + self._ny + _yrefindex, + self._nx1 + _xrefindex, + self._ny1 + _yrefindex, + renderer) + + + +class SubplotDivider(Divider): + """ + The Divider class whose rectangle area is specified as a subplot grometry. + """ + + + def __init__(self, fig, *args, **kwargs): + """ + *fig* is a :class:`matplotlib.figure.Figure` instance. + + *args* is the tuple (*numRows*, *numCols*, *plotNum*), where + the array of subplots in the figure has dimensions *numRows*, + *numCols*, and where *plotNum* is the number of the subplot + being created. *plotNum* starts at 1 in the upper left + corner and increases to the right. + + If *numRows* <= *numCols* <= *plotNum* < 10, *args* can be the + decimal integer *numRows* * 100 + *numCols* * 10 + *plotNum*. + """ + + self.figure = fig + + if len(args)==1: + s = str(args[0]) + if len(s) != 3: + raise ValueError('Argument to subplot must be a 3 digits long') + rows, cols, num = map(int, s) + elif len(args)==3: + rows, cols, num = args + else: + raise ValueError( 'Illegal argument to subplot') + + + total = rows*cols + num -= 1 # convert from matlab to python indexing + # ie num in range(0,total) + if num >= total: + raise ValueError( 'Subplot number exceeds total subplots') + self._rows = rows + self._cols = cols + self._num = num + + self.update_params() + + pos = self.figbox.bounds + horizontal = kwargs.pop("horizontal", []) + vertical = kwargs.pop("vertical", []) + aspect = kwargs.pop("aspect", None) + anchor = kwargs.pop("anchor", "C") + + if kwargs: + raise Exception("") + + Divider.__init__(self, fig, pos, horizontal, vertical, + aspect=aspect, anchor=anchor) + + + def get_position(self): + "return the bounds of the subplot box" + self.update_params() + return self.figbox.bounds + + + def update_params(self): + 'update the subplot position from fig.subplotpars' + + rows = self._rows + cols = self._cols + num = self._num + + pars = self.figure.subplotpars + left = pars.left + right = pars.right + bottom = pars.bottom + top = pars.top + wspace = pars.wspace + hspace = pars.hspace + totWidth = right-left + totHeight = top-bottom + + figH = totHeight/(rows + hspace*(rows-1)) + sepH = hspace*figH + + figW = totWidth/(cols + wspace*(cols-1)) + sepW = wspace*figW + + rowNum, colNum = divmod(num, cols) + + figBottom = top - (rowNum+1)*figH - rowNum*sepH + figLeft = left + colNum*(figW + sepW) + + self.figbox = mtransforms.Bbox.from_bounds(figLeft, figBottom, + figW, figH) + + +class AxesDivider(Divider): + """ + Divider based on the pre-existing axes. + """ + + def __init__(self, axes): + """ + :param axes: axes + """ + self._axes = axes + self._xref = Size.AxesX(axes) + self._yref = Size.AxesY(axes) + Divider.__init__(self, fig=axes.get_figure(), pos=None, + horizontal=[self._xref], vertical=[self._yref], + aspect=None, anchor="C") + + def _get_new_axes(self, **kwargs): + axes = self._axes + + axes_class = kwargs.pop("axes_class", None) + + if axes_class is None: + if isinstance(axes, SubplotBase): + axes_class = axes._axes_class + else: + axes_class = type(axes) + + ax = axes_class(axes.get_figure(), + axes.get_position(original=True), **kwargs) + + return ax + + + def new_horizontal(self, size, pad=None, pack_start=False, **kwargs): + """ + Add a new axes on the right (or left) side of the main axes. + + :param size: A width of the axes. A :mod:`~mpl_toolkits.axes_grid.axes_size` + instance or if float or string is given, *from_any* + fucntion is used to create one, with *ref_size* set to AxesX instance + of the current axes. + :param pad: pad between the axes. It takes same argument as *size*. + :param pack_start: If False, the new axes is appended at the end + of the list, i.e., it became the right-most axes. If True, it is + inseted at the start of the list, and becomes the left-most axes. + + All extra keywords argument is passed to when creating a axes. + if *axes_class* is given, the new axes will be created as an + instance of the given class. Otherwise, the same class of the + main axes will be used. if Not provided + + """ + + if pad: + if not isinstance(pad, Size._Base): + pad = Size.from_any(pad, + fraction_ref=self._xref) + if pack_start: + self._horizontal.insert(0, pad) + self._xrefindex += 1 + else: + self._horizontal.append(pad) + + if not isinstance(size, Size._Base): + size = Size.from_any(size, + fraction_ref=self._xref) + + if pack_start: + self._horizontal.insert(0, size) + self._xrefindex += 1 + locator = self.new_locator(nx=0, ny=0) + else: + self._horizontal.append(size) + locator = self.new_locator(nx=len(self._horizontal)-1, ny=0) + + ax = self._get_new_axes(**kwargs) + ax.set_axes_locator(locator) + + return ax + + def new_vertical(self, size, pad=None, pack_start=False, **kwargs): + """ + Add a new axes on the top (or bottom) side of the main axes. + + :param size: A height of the axes. A :mod:`~mpl_toolkits.axes_grid.axes_size` + instance or if float or string is given, *from_any* + fucntion is used to create one, with *ref_size* set to AxesX instance + of the current axes. + :param pad: pad between the axes. It takes same argument as *size*. + :param pack_start: If False, the new axes is appended at the end + of the list, i.e., it became the top-most axes. If True, it is + inseted at the start of the list, and becomes the bottom-most axes. + + All extra keywords argument is passed to when creating a axes. + if *axes_class* is given, the new axes will be created as an + instance of the given class. Otherwise, the same class of the + main axes will be used. if Not provided + + """ + + if pad: + if not isinstance(pad, Size._Base): + pad = Size.from_any(pad, + fraction_ref=self._yref) + if pack_start: + self._vertical.insert(0, pad) + self._yrefindex += 1 + else: + self._vertical.append(pad) + + if not isinstance(size, Size._Base): + size = Size.from_any(size, + fraction_ref=self._yref) + + if pack_start: + self._vertical.insert(0, size) + self._yrefindex += 1 + locator = self.new_locator(nx=0, ny=0) + else: + self._vertical.append(size) + locator = self.new_locator(nx=0, ny=len(self._vertical)-1) + + ax = self._get_new_axes(**kwargs) + ax.set_axes_locator(locator) + + return ax + + + def append_axes(self, position, size, pad=None, **kwargs): + """ + create an axes at the given *position* with the same height + (or width) of the main axes. + + *position* + ["left"|"right"|"bottom"|"top"] + + *size* and *pad* should be axes_grid.axes_size compatible. + """ + + if position == "left": + ax = self.new_horizontal(size, pad, pack_start=True, **kwargs) + elif position == "right": + ax = self.new_horizontal(size, pad, pack_start=False, **kwargs) + elif position == "bottom": + ax = self.new_vertical(size, pad, pack_start=True, **kwargs) + elif position == "top": + ax = self.new_vertical(size, pad, pack_start=False, **kwargs) + else: + raise ValueError("the position must be one of left, right, bottom, or top") + + self._fig.add_axes(ax) + return ax + + def get_aspect(self): + if self._aspect is None: + aspect = self._axes.get_aspect() + if aspect == "auto": + return False + else: + return True + else: + return self._aspect + + def get_position(self): + if self._pos is None: + bbox = self._axes.get_position(original=True) + return bbox.bounds + else: + return self._pos + + def get_anchor(self): + if self._anchor is None: + return self._axes.get_anchor() + else: + return self._anchor + + + +class LocatableAxesBase: + def __init__(self, *kl, **kw): + + self._axes_class.__init__(self, *kl, **kw) + + self._locator = None + self._locator_renderer = None + + def set_axes_locator(self, locator): + self._locator = locator + + def get_axes_locator(self): + return self._locator + + def apply_aspect(self, position=None): + + if self.get_axes_locator() is None: + self._axes_class.apply_aspect(self, position) + else: + pos = self.get_axes_locator()(self, self._locator_renderer) + self._axes_class.apply_aspect(self, position=pos) + + + def draw(self, renderer=None, inframe=False): + + self._locator_renderer = renderer + + self._axes_class.draw(self, renderer, inframe) + + + +_locatableaxes_classes = {} +def locatable_axes_factory(axes_class): + + new_class = _locatableaxes_classes.get(axes_class) + if new_class is None: + new_class = new.classobj("Locatable%s" % (axes_class.__name__), + (LocatableAxesBase, axes_class), + {'_axes_class': axes_class}) + _locatableaxes_classes[axes_class] = new_class + + return new_class + +#if hasattr(maxes.Axes, "get_axes_locator"): +# LocatableAxes = maxes.Axes +#else: + +def make_axes_locatable(axes): + if not hasattr(axes, "set_axes_locator"): + new_class = locatable_axes_factory(type(axes)) + axes.__class__ = new_class + + divider = AxesDivider(axes) + locator = divider.new_locator(nx=0, ny=0) + axes.set_axes_locator(locator) + + return divider + + +#from matplotlib.axes import Axes +from mpl_axes import Axes +LocatableAxes = locatable_axes_factory(Axes) + + + +def get_demo_image(): + # prepare image + delta = 0.5 + + extent = (-3,4,-4,3) + import numpy as np + x = np.arange(-3.0, 4.001, delta) + y = np.arange(-4.0, 3.001, delta) + X, Y = np.meshgrid(x, y) + import matplotlib.mlab as mlab + Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) + Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1) + Z = (Z1 - Z2) * 10 + + return Z, extent + +def demo_locatable_axes(): + import matplotlib.pyplot as plt + + fig1 = plt.figure(1, (6, 6)) + fig1.clf() + + ## PLOT 1 + # simple image & colorbar + ax = fig1.add_subplot(2, 2, 1) + + Z, extent = get_demo_image() + + im = ax.imshow(Z, extent=extent, interpolation="nearest") + cb = plt.colorbar(im) + plt.setp(cb.ax.get_yticklabels(), visible=False) + + + ## PLOT 2 + # image and colorbar whose location is adjusted in the drawing time. + # a hard way + + divider = SubplotDivider(fig1, 2, 2, 2, aspect=True) + + # axes for image + ax = LocatableAxes(fig1, divider.get_position()) + + # axes for coloarbar + ax_cb = LocatableAxes(fig1, divider.get_position()) + + h = [Size.AxesX(ax), # main axes + Size.Fixed(0.05), # padding, 0.1 inch + Size.Fixed(0.2), # colorbar, 0.3 inch + ] + + v = [Size.AxesY(ax)] + + divider.set_horizontal(h) + divider.set_vertical(v) + + ax.set_axes_locator(divider.new_locator(nx=0, ny=0)) + ax_cb.set_axes_locator(divider.new_locator(nx=2, ny=0)) + + fig1.add_axes(ax) + fig1.add_axes(ax_cb) + + ax_cb.yaxis.set_ticks_position("right") + + Z, extent = get_demo_image() + + im = ax.imshow(Z, extent=extent, interpolation="nearest") + plt.colorbar(im, cax=ax_cb) + plt.setp(ax_cb.get_yticklabels(), visible=False) + + plt.draw() + #plt.colorbar(im, cax=ax_cb) + + + ## PLOT 3 + # image and colorbar whose location is adjusted in the drawing time. + # a easy way + + ax = fig1.add_subplot(2, 2, 3) + divider = make_axes_locatable(ax) + + ax_cb = divider.new_horizontal(size="5%", pad=0.05) + fig1.add_axes(ax_cb) + + im = ax.imshow(Z, extent=extent, interpolation="nearest") + plt.colorbar(im, cax=ax_cb) + plt.setp(ax_cb.get_yticklabels(), visible=False) + + + ## PLOT 4 + # two images side by sied with fixed padding. + + ax = fig1.add_subplot(2, 2, 4) + divider = make_axes_locatable(ax) + + ax2 = divider.new_horizontal(size="100%", pad=0.05) + fig1.add_axes(ax2) + + ax.imshow(Z, extent=extent, interpolation="nearest") + ax2.imshow(Z, extent=extent, interpolation="nearest") + plt.setp(ax2.get_yticklabels(), visible=False) + plt.draw() + plt.show() + + +def demo_fixed_size_axes(): + import matplotlib.pyplot as plt + + fig2 = plt.figure(2, (6, 6)) + + # The first items are for padding and the second items are for the axes. + # sizes are in inch. + h = [Size.Fixed(1.0), Size.Fixed(4.5)] + v = [Size.Fixed(0.7), Size.Fixed(5.)] + + divider = Divider(fig2, (0.0, 0.0, 1., 1.), h, v, aspect=False) + # the width and height of the rectangle is ignored. + + ax = LocatableAxes(fig2, divider.get_position()) + ax.set_axes_locator(divider.new_locator(nx=1, ny=1)) + + fig2.add_axes(ax) + + ax.plot([1,2,3]) + + plt.draw() + plt.show() + #plt.colorbar(im, cax=ax_cb) + + + + + +if __name__ == "__main__": + demo_locatable_axes() + demo_fixed_size_axes() Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_grid.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_grid.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_grid.py 2010年04月06日 17:05:51 UTC (rev 8223) @@ -0,0 +1,786 @@ +import matplotlib.cbook as cbook + +import matplotlib.pyplot as plt +import matplotlib.axes as maxes +#import matplotlib.colorbar as mcolorbar +import colorbar as mcolorbar +import matplotlib as mpl +import matplotlib.patches as mpatches +import matplotlib.lines as mlines +import matplotlib.ticker as ticker + +from axes_divider import Size, SubplotDivider, LocatableAxes, Divider + +#import numpy as np + +def _tick_only(ax, bottom_on, left_on): + bottom_off = not bottom_on + left_off = not left_on + # [l.set_visible(bottom_off) for l in ax.get_xticklabels()] + # [l.set_visible(left_off) for l in ax.get_yticklabels()] + # ax.xaxis.label.set_visible(bottom_off) + # ax.yaxis.label.set_visible(left_off) + ax.axis["bottom"].toggle(ticklabels=bottom_off, label=bottom_off) + ax.axis["left"].toggle(ticklabels=left_off, label=left_off) + +class Colorbar(mcolorbar.Colorbar): + def _config_axes_deprecated(self, X, Y): + ''' + Make an axes patch and outline. + ''' + ax = self.ax + ax.set_frame_on(False) + ax.set_navigate(False) + xy = self._outline(X, Y) + ax.update_datalim(xy) + ax.set_xlim(*ax.dataLim.intervalx) + ax.set_ylim(*ax.dataLim.intervaly) + self.outline = mlines.Line2D(xy[:, 0], xy[:, 1], color=mpl.rcParams['axes.edgecolor'], + linewidth=mpl.rcParams['axes.linewidth']) + ax.add_artist(self.outline) + self.outline.set_clip_box(None) + self.outline.set_clip_path(None) + c = mpl.rcParams['axes.facecolor'] + self.patch = mpatches.Polygon(xy, edgecolor=c, + facecolor=c, + linewidth=0.01, + zorder=-1) + ax.add_artist(self.patch) + ticks, ticklabels, offset_string = self._ticker() + + if self.orientation == 'vertical': + ax.set_yticks(ticks) + ax.set_yticklabels(ticklabels) + ax.yaxis.get_major_formatter().set_offset_string(offset_string) + + else: + ax.set_xticks(ticks) + ax.set_xticklabels(ticklabels) + ax.xaxis.get_major_formatter().set_offset_string(offset_string) + + + +class CbarAxesBase(object): + + def colorbar(self, mappable, **kwargs): + locator=kwargs.pop("locator", None) + if locator is None: + locator = ticker.MaxNLocator(5) + self.locator = locator + + kwargs["ticks"] = locator + + + self.hold(True) + if self.orientation in ["top", "bottom"]: + orientation="horizontal" + else: + orientation="vertical" + + cb = Colorbar(self, mappable, orientation=orientation, **kwargs) + self._config_axes() + + def on_changed(m): + #print 'calling on changed', m.get_cmap().name + cb.set_cmap(m.get_cmap()) + cb.set_clim(m.get_clim()) + cb.update_bruteforce(m) + + self.cbid = mappable.callbacksSM.connect('changed', on_changed) + mappable.set_colorbar(cb, self) + return cb + + def _config_axes(self): + ''' + Make an axes patch and outline. + ''' + ax = self + ax.set_navigate(False) + + ax.axis[:].toggle(all=False) + b = self._default_label_on + ax.axis[self.orientation].toggle(all=b) + + # for axis in ax.axis.values(): + # axis.major_ticks.set_visible(False) + # axis.minor_ticks.set_visible(False) + # axis.major_ticklabels.set_visible(False) + # axis.minor_ticklabels.set_visible(False) + # axis.label.set_visible(False) + + # axis = ax.axis[self.orientation] + # axis.major_ticks.set_visible(True) + # axis.minor_ticks.set_visible(True) + + + #axis.major_ticklabels.set_size(int(axis.major_ticklabels.get_size()*.9)) + #axis.major_tick_pad = 3 + + # axis.major_ticklabels.set_visible(b) + # axis.minor_ticklabels.set_visible(b) + # axis.label.set_visible(b) + + + def toggle_label(self, b): + self._default_label_on = b + axis = self.axis[self.orientation] + axis.toggle(ticklabels=b, label=b) + #axis.major_ticklabels.set_visible(b) + #axis.minor_ticklabels.set_visible(b) + #axis.label.set_visible(b) + + + +class CbarAxes(CbarAxesBase, LocatableAxes): + def __init__(self, *kl, **kwargs): + orientation=kwargs.pop("orientation", None) + if orientation is None: + raise ValueError("orientation must be specified") + self.orientation = orientation + self._default_label_on = True + self.locator = None + + super(LocatableAxes, self).__init__(*kl, **kwargs) + + def cla(self): + super(LocatableAxes, self).cla() + self._config_axes() + + +class Grid(object): + """ + A class that creates a grid of Axes. In matplotlib, the axes + location (and size) is specified in the normalized figure + coordinates. This may not be ideal for images that needs to be + displayed with a given aspect ratio. For example, displaying + images of a same size with some fixed padding between them cannot + be easily done in matplotlib. AxesGrid is used in such case. + """ + + _defaultLocatableAxesClass = LocatableAxes + + def __init__(self, fig, + rect, + nrows_ncols, + ngrids = None, + direction="row", + axes_pad = 0.02, + add_all=True, + share_all=False, + share_x=True, + share_y=True, + #aspect=True, + label_mode="L", + axes_class=None, + ): + """ + Build an :class:`Grid` instance with a grid nrows*ncols + :class:`~matplotlib.axes.Axes` in + :class:`~matplotlib.figure.Figure` *fig* with + *rect=[left, bottom, width, height]* (in + :class:`~matplotlib.figure.Figure` coordinates) or + the subplot position code (e.g., "121"). + + Optional keyword arguments: + + ================ ======== ========================================= + Keyword Default Description + ================ ======== ========================================= + direction "row" [ "row" | "column" ] + axes_pad 0.02 float| pad betweein axes given in inches + add_all True [ True | False ] + share_all False [ True | False ] + share_x True [ True | False ] + share_y True [ True | False ] + label_mode "L" [ "L" | "1" | "all" ] + axes_class None a type object which must be a subclass + of :class:`~matplotlib.axes.Axes` + ================ ======== ========================================= + """ + self._nrows, self._ncols = nrows_ncols + + if ngrids is None: + ngrids = self._nrows * self._ncols + else: + if (ngrids > self._nrows * self._ncols) or (ngrids <= 0): + raise Exception("") + + self.ngrids = ngrids + + self._init_axes_pad(axes_pad) + + if direction not in ["column", "row"]: + raise Exception("") + + self._direction = direction + + + if axes_class is None: + axes_class = self._defaultLocatableAxesClass + axes_class_args = {} + else: + if isinstance(axes_class, maxes.Axes): + axes_class_args = {} + else: + axes_class, axes_class_args = axes_class + + self.axes_all = [] + self.axes_column = [[] for i in range(self._ncols)] + self.axes_row = [[] for i in range(self._nrows)] + + + h = [] + v = [] + if cbook.is_string_like(rect) or cbook.is_numlike(rect): + self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v, + aspect=False) + elif len(rect) == 3: + kw = dict(horizontal=h, vertical=v, aspect=False) + self._divider = SubplotDivider(fig, *rect, **kw) + elif len(rect) == 4: + self._divider = Divider(fig, rect, horizontal=h, vertical=v, + aspect=False) + else: + raise Exception("") + + + rect = self._divider.get_position() + + # reference axes + self._column_refax = [None for i in range(self._ncols)] + self._row_refax = [None for i in range(self._nrows)] + self._refax = None + + for i in range(self.ngrids): + + col, row = self._get_col_row(i) + + if share_all: + sharex = self._refax + sharey = self._refax + else: + if share_x: + sharex = self._column_refax[col] + else: + sharex = None + + if share_y: + sharey = self._row_refax[row] + else: + sharey = None + + ax = axes_class(fig, rect, sharex=sharex, sharey=sharey, + **axes_class_args) + + if share_all: + if self._refax is None: + self._refax = ax + else: + if sharex is None: + self._column_refax[col] = ax + if sharey is None: + self._row_refax[row] = ax + + self.axes_all.append(ax) + self.axes_column[col].append(ax) + self.axes_row[row].append(ax) + + self.axes_llc = self.axes_column[0][-1] + + self._update_locators() + + if add_all: + for ax in self.axes_all: + fig.add_axes(ax) + + self.set_label_mode(label_mode) + + + def _init_axes_pad(self, axes_pad): + self._axes_pad = axes_pad + + self._horiz_pad_size = Size.Fixed(axes_pad) + self._vert_pad_size = Size.Fixed(axes_pad) + + + def _update_locators(self): + + h = [] + + h_ax_pos = [] + h_cb_pos = [] + + for ax in self._column_refax: + #if h: h.append(Size.Fixed(self._axes_pad)) + if h: h.append(self._horiz_pad_size) + + h_ax_pos.append(len(h)) + + sz = Size.Scaled(1) + h.append(sz) + + v = [] + + v_ax_pos = [] + v_cb_pos = [] + for ax in self._row_refax[::-1]: + #if v: v.append(Size.Fixed(self._axes_pad)) + if v: v.append(self._vert_pad_size) + + v_ax_pos.append(len(v)) + sz = Size.Scaled(1) + v.append(sz) + + + for i in range(self.ngrids): + col, row = self._get_col_row(i) + locator = self._divider.new_locator(nx=h_ax_pos[col], + ny=v_ax_pos[self._nrows -1 - row]) + self.axes_all[i].set_axes_locator(locator) + + self._divider.set_horizontal(h) + self._divider.set_vertical(v) + + + + def _get_col_row(self, n): + if self._direction == "column": + col, row = divmod(n, self._nrows) + else: + row, col = divmod(n, self._ncols) + + return col, row + + + def __getitem__(self, i): + return self.axes_all[i] + + + def get_geometry(self): + """ + get geometry of the grid. Returns a tuple of two integer, + representing number of rows and number of columns. + """ + return self._nrows, self._ncols + + def set_axes_pad(self, axes_pad): + "set axes_pad" + self._axes_pad = axes_pad + + self._horiz_pad_size.fixed_size = axes_pad + self._vert_pad_size.fixed_size = axes_pad + + + def get_axes_pad(self): + "get axes_pad" + return self._axes_pad + + def set_aspect(self, aspect): + "set aspect" + self._divider.set_aspect(aspect) + + def get_aspect(self): + "get aspect" + return self._divider.get_aspect() + + def set_label_mode(self, mode): + "set label_mode" + if mode == "all": + for ax in self.axes_all: + _tick_only(ax, False, False) + elif mode == "L": + # left-most axes + for ax in self.axes_column[0][:-1]: + _tick_only(ax, bottom_on=True, left_on=False) + # lower-left axes + ax = self.axes_column[0][-1] + _tick_only(ax, bottom_on=False, left_on=False) + + for col in self.axes_column[1:]: + # axes with no labels + for ax in col[:-1]: + _tick_only(ax, bottom_on=True, left_on=True) + + # bottom + ax = col[-1] + _tick_only(ax, bottom_on=False, left_on=True) + + elif mode == "1": + for ax in self.axes_all: + _tick_only(ax, bottom_on=True, left_on=True) + + ax = self.axes_llc + _tick_only(ax, bottom_on=False, left_on=False) + + +class ImageGrid(Grid): + """ + A class that creates a grid of Axes. In matplotlib, the axes + location (and size) is specified in the normalized figure + coordinates. This may not be ideal for images that needs to be + displayed with a given aspect ratio. For example, displaying + images of a same size with some fixed padding between them cannot + be easily done in matplotlib. ImageGrid is used in such case. + """ + + _defaultCbarAxesClass = CbarAxes + + def __init__(self, fig, + rect, + nrows_ncols, + ngrids = None, + direction="row", + axes_pad = 0.02, + add_all=True, + share_all=False, + aspect=True, + label_mode="L", + cbar_mode=None, + cbar_location="right", + cbar_pad=None, + cbar_size="5%", + cbar_set_cax=True, + axes_class=None, + ): + """ + Build an :class:`ImageGrid` instance with a grid nrows*ncols + :class:`~matplotlib.axes.Axes` in + :class:`~matplotlib.figure.Figure` *fig* with + *rect=[left, bottom, width, height]* (in + :class:`~matplotlib.figure.Figure` coordinates) or + the subplot position code (e.g., "121"). + + Optional keyword arguments: + + ================ ======== ========================================= + Keyword Default Description + ================ ======== ========================================= + direction "row" [ "row" | "column" ] + axes_pad 0.02 float| pad betweein axes given in inches + add_all True [ True | False ] + share_all False [ True | False ] + aspect True [ True | False ] + label_mode "L" [ "L" | "1" | "all" ] + cbar_mode None [ "each" | "single" ] + cbar_location "right" [ "right" | "top" ] + cbar_pad None + cbar_size "5%" + cbar_set_cax True [ True | False ] + axes_class None a type object which must be a subclass + of :class:`~matplotlib.axes.Axes` + ================ ======== ========================================= + + *cbar_set_cax* : if True, each axes in the grid has a cax + attribute that is bind to associated cbar_axes. + """ + self._nrows, self._ncols = nrows_ncols + + if ngrids is None: + ngrids = self._nrows * self._ncols + else: + if (ngrids > self._nrows * self._ncols) or (ngrids <= 0): + raise Exception("") + + self.ngrids = ngrids + + self._axes_pad = axes_pad + + self._colorbar_mode = cbar_mode + self._colorbar_location = cbar_location + if cbar_pad is None: + self._colorbar_pad = axes_pad + else: + self._colorbar_pad = cbar_pad + + self._colorbar_size = cbar_size + + self._init_axes_pad(axes_pad) + + if direction not in ["column", "row"]: + raise Exception("") + + self._direction = direction + + + if axes_class is None: + axes_class = self._defaultLocatableAxesClass + axes_class_args = {} + else: + if isinstance(axes_class, maxes.Axes): + axes_class_args = {} + else: + axes_class, axes_class_args = axes_class + + + + self.axes_all = [] + self.axes_column = [[] for i in range(self._ncols)] + self.axes_row = [[] for i in range(self._nrows)] + + self.cbar_axes = [] + + h = [] + v = [] + if cbook.is_string_like(rect) or cbook.is_numlike(rect): + self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v, + aspect=aspect) + elif len(rect) == 3: + kw = dict(horizontal=h, vertical=v, aspect=aspect) + self._divider = SubplotDivider(fig, *rect, **kw) + elif len(rect) == 4: + self._divider = Divider(fig, rect, horizontal=h, vertical=v, + aspect=aspect) + else: + raise Exception("") + + + rect = self._divider.get_position() + + # reference axes + self._column_refax = [None for i in range(self._ncols)] + self._row_refax = [None for i in range(self._nrows)] + self._refax = None + + for i in range(self.ngrids): + + col, row = self._get_col_row(i) + + if share_all: + sharex = self._refax + sharey = self._refax + else: + sharex = self._column_refax[col] + sharey = self._row_refax[row] + + ax = axes_class(fig, rect, sharex=sharex, sharey=sharey, + **axes_class_args) + + if share_all: + if self._refax is None: + self._refax = ax + else: + if sharex is None: + self._column_refax[col] = ax + if sharey is None: + self._row_refax[row] = ax + + self.axes_all.append(ax) + self.axes_column[col].append(ax) + self.axes_row[row].append(ax) + + cax = self._defaultCbarAxesClass(fig, rect, + orientation=self._colorbar_location) + self.cbar_axes.append(cax) + + self.axes_llc = self.axes_column[0][-1] + + self._update_locators() + + if add_all: + for ax in self.axes_all+self.cbar_axes: + fig.add_axes(ax) + + if cbar_set_cax: + if self._colorbar_mode == "single": + for ax in self.axes_all: + ax.cax = self.cbar_axes[0] + else: + for ax, cax in zip(self.axes_all, self.cbar_axes): + ax.cax = cax + + self.set_label_mode(label_mode) + + + + def _update_locators(self): + + h = [] + + h_ax_pos = [] + h_cb_pos = [] + for ax in self._column_refax: + if h: h.append(self._horiz_pad_size) #Size.Fixed(self._axes_pad)) + + h_ax_pos.append(len(h)) + + if ax: + sz = Size.AxesX(ax) + else: + sz = Size.AxesX(self.axes_llc) + h.append(sz) + + if self._colorbar_mode == "each" and self._colorbar_location == "right": + h.append(Size.from_any(self._colorbar_pad, sz)) + h_cb_pos.append(len(h)) + h.append(Size.from_any(self._colorbar_size, sz)) + + + v = [] + + v_ax_pos = [] + v_cb_pos = [] + for ax in self._row_refax[::-1]: + if v: v.append(self._horiz_pad_size) #Size.Fixed(self._axes_pad)) + + v_ax_pos.append(len(v)) + if ax: + sz = Size.AxesY(ax) + else: + sz = Size.AxesY(self.axes_llc) + v.append(sz) + + + if self._colorbar_mode == "each" and self._colorbar_location == "top": + v.append(Size.from_any(self._colorbar_pad, sz)) + v_cb_pos.append(len(v)) + v.append(Size.from_any(self._colorbar_size, sz)) + + + for i in range(self.ngrids): + col, row = self._get_col_row(i) + #locator = self._divider.new_locator(nx=4*col, ny=2*(self._nrows - row - 1)) + locator = self._divider.new_locator(nx=h_ax_pos[col], + ny=v_ax_pos[self._nrows -1 - row]) + self.axes_all[i].set_axes_locator(locator) + + if self._colorbar_mode == "each": + if self._colorbar_location == "right": + locator = self._divider.new_locator(nx=h_cb_pos[col], + ny=v_ax_pos[self._nrows -1 - row]) + elif self._colorbar_location == "top": + locator = self._divider.new_locator(nx=h_ax_pos[col], + ny=v_cb_pos[self._nrows -1 - row]) + self.cbar_axes[i].set_axes_locator(locator) + + + if self._colorbar_mode == "single": + if self._colorbar_location == "right": + #sz = Size.Fraction(Size.AxesX(self.axes_llc), self._nrows) + sz = Size.Fraction(self._nrows, Size.AxesX(self.axes_llc)) + h.append(Size.from_any(self._colorbar_pad, sz)) + h.append(Size.from_any(self._colorbar_size, sz)) + locator = self._divider.new_locator(nx=-2, ny=0, ny1=-1) + elif self._colorbar_location == "top": + #sz = Size.Fraction(Size.AxesY(self.axes_llc), self._ncols) + sz = Size.Fraction(self._ncols, Size.AxesY(self.axes_llc)) + v.append(Size.from_any(self._colorbar_pad, sz)) + v.append(Size.from_any(self._colorbar_size, sz)) + locator = self._divider.new_locator(nx=0, nx1=-1, ny=-2) + for i in range(self.ngrids): + self.cbar_axes[i].set_visible(False) + self.cbar_axes[0].set_axes_locator(locator) + self.cbar_axes[0].set_visible(True) + elif self._colorbar_mode == "each": + for i in range(self.ngrids): + self.cbar_axes[i].set_visible(True) + else: + for i in range(self.ngrids): + self.cbar_axes[i].set_visible(False) + self.cbar_axes[i].set_position([1., 1., 0.001, 0.001], + which="active") + + self._divider.set_horizontal(h) + self._divider.set_vertical(v) + + +AxesGrid = ImageGrid + + + +#if __name__ == "__main__": +if 0: + F = plt.figure(1, (7, 6)) + F.clf() + + F.subplots_adjust(left=0.15, right=0.9) + + grid = Grid(F, 111, # similar to subplot(111) + nrows_ncols = (2, 2), + direction="row", + axes_pad = 0.05, + add_all=True, + label_mode = "1", + ) + + + +#if __name__ == "__main__": +if 0: + from axes_divider import get_demo_image + F = plt.figure(1, (9, 3.5)) + F.clf() + + F.subplots_adjust(left=0.05, right=0.98) + + grid = ImageGrid(F, 131, # similar to subplot(111) + nrows_ncols = (2, 2), + direction="row", + axes_pad = 0.05, + add_all=True, + label_mode = "1", + ) + + Z, extent = get_demo_image() + plt.ioff() + for i in range(4): + im = grid[i].imshow(Z, extent=extent, interpolation="nearest") + + # This only affects axes in first column and second row as share_all = False. + grid.axes_llc.set_xticks([-2, 0, 2]) + grid.axes_llc.set_yticks([-2, 0, 2]) + plt.ion() + + + grid = ImageGrid(F, 132, # similar to subplot(111) + nrows_ncols = (2, 2), + direction="row", + axes_pad = 0.0, + add_all=True, + share_all=True, + label_mode = "1", + cbar_mode="single", + ) + + Z, extent = get_demo_image() + plt.ioff() + for i in range(4): + im = grid[i].imshow(Z, extent=extent, interpolation="nearest") + plt.colorbar(im, cax = grid.cbar_axes[0]) + plt.setp(grid.cbar_axes[0].get_yticklabels(), visible=False) + + # This affects all axes as share_all = True. + grid.axes_llc.set_xticks([-2, 0, 2]) + grid.axes_llc.set_yticks([-2, 0, 2]) + + plt.ion() + + + + grid = ImageGrid(F, 133, # similar to subplot(122) + nrows_ncols = (2, 2), + direction="row", + axes_pad = 0.1, + add_all=True, + label_mode = "1", + share_all = True, + cbar_location="top", + cbar_mode="each", + cbar_size="7%", + cbar_pad="2%", + ) + plt.ioff() + for i in range(4): + im = grid[i].imshow(Z, extent=extent, interpolation="nearest") + plt.colorbar(im, cax = grid.cbar_axes[i], + orientation="horizontal") + grid.cbar_axes[i].xaxis.set_ticks_position("top") + plt.setp(grid.cbar_axes[i].get_xticklabels(), visible=False) + + # This affects all axes as share_all = True. + grid.axes_llc.set_xticks([-2, 0, 2]) + grid.axes_llc.set_yticks([-2, 0, 2]) + + plt.ion() + plt.draw() + + Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_rgb.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_rgb.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_rgb.py 2010年04月06日 17:05:51 UTC (rev 8223) @@ -0,0 +1,162 @@ +import numpy as np +from axes_divider import make_axes_locatable, Size, locatable_axes_factory + +def make_rgb_axes(ax, pad=0.01, axes_class=None, add_all=True): + """ + pad : fraction of the axes height. + """ + + divider = make_axes_locatable(ax) + + pad_size = Size.Fraction(pad, Size.AxesY(ax)) + + xsize = Size.Fraction((1.-2.*pad)/3., Size.AxesX(ax)) + ysize = Size.Fraction((1.-2.*pad)/3., Size.AxesY(ax)) + + divider.set_horizontal([Size.AxesX(ax), pad_size, xsize]) + divider.set_vertical([ysize, pad_size, ysize, pad_size, ysize]) + + ax.set_axes_locator(divider.new_locator(0, 0, ny1=-1)) + + ax_rgb = [] + if axes_class is None: + try: + axes_class = locatable_axes_factory(ax._axes_class) + except AttributeError: + axes_class = locatable_axes_factory(type(ax)) + + for ny in [4, 2, 0]: + ax1 = axes_class(ax.get_figure(), + ax.get_position(original=True), + sharex=ax, sharey=ax) + locator = divider.new_locator(nx=2, ny=ny) + ax1.set_axes_locator(locator) + for t in ax1.yaxis.get_ticklabels() + ax1.xaxis.get_ticklabels(): + t.set_visible(False) + try: + for axis in ax1.axis.values(): + axis.major_ticklabels.set_visible(False) + except AttributeError: + pass + + ax_rgb.append(ax1) + + if add_all: + fig = ax.get_figure() + for ax1 in ax_rgb: + fig.add_axes(ax1) ... [truncated message content]
Revision: 8222 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8222&view=rev Author: efiring Date: 2010年04月05日 18:46:18 +0000 (2010年4月05日) Log Message: ----------- Don't import pytz unless and until it is needed Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/pylab_examples/finance_demo.py trunk/matplotlib/lib/matplotlib/config/cutils.py trunk/matplotlib/lib/matplotlib/dates.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010年04月05日 01:06:57 UTC (rev 8221) +++ trunk/matplotlib/CHANGELOG 2010年04月05日 18:46:18 UTC (rev 8222) @@ -1,3 +1,6 @@ +2010年04月05日 Speed up import: import pytz only if and when it is + needed. It is not needed if the rc timezone is UTC. - EF + 2010年04月03日 Added color kwarg to Axes.hist(), based on work by Jeff Klukas. - EF Modified: trunk/matplotlib/examples/pylab_examples/finance_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/finance_demo.py 2010年04月05日 01:06:57 UTC (rev 8221) +++ trunk/matplotlib/examples/pylab_examples/finance_demo.py 2010年04月05日 18:46:18 UTC (rev 8222) @@ -1,7 +1,7 @@ #!/usr/bin/env python from pylab import * from matplotlib.dates import DateFormatter, WeekdayLocator, HourLocator, \ - DayLocator, MONDAY, timezone + DayLocator, MONDAY from matplotlib.finance import quotes_historical_yahoo, candlestick,\ plot_day_summary, candlestick2 Modified: trunk/matplotlib/lib/matplotlib/config/cutils.py =================================================================== --- trunk/matplotlib/lib/matplotlib/config/cutils.py 2010年04月05日 01:06:57 UTC (rev 8221) +++ trunk/matplotlib/lib/matplotlib/config/cutils.py 2010年04月05日 18:46:18 UTC (rev 8222) @@ -4,7 +4,6 @@ # Stdlib imports import os -import pytz import sys import tempfile import warnings Modified: trunk/matplotlib/lib/matplotlib/dates.py =================================================================== --- trunk/matplotlib/lib/matplotlib/dates.py 2010年04月05日 01:06:57 UTC (rev 8221) +++ trunk/matplotlib/lib/matplotlib/dates.py 2010年04月05日 18:46:18 UTC (rev 8222) @@ -92,15 +92,6 @@ """ import re, time, math, datetime -import pytz - -# compatability for 2008c and older versions -try: - import pytz.zoneinfo -except ImportError: - pytz.zoneinfo = pytz.tzinfo - pytz.zoneinfo.UTC = pytz.UTC - import matplotlib import numpy as np @@ -108,7 +99,6 @@ import matplotlib.cbook as cbook import matplotlib.ticker as ticker -from pytz import timezone from dateutil.rrule import rrule, MO, TU, WE, TH, FR, SA, SU, YEARLY, \ MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, SECONDLY from dateutil.relativedelta import relativedelta @@ -127,11 +117,28 @@ 'seconds', 'minutes', 'hours', 'weeks') +# Make a simple UTC instance so we don't always have to import +# pytz. From the python datetime library docs: -UTC = pytz.timezone('UTC') +class _UTC(datetime.tzinfo): + """UTC""" + def utcoffset(self, dt): + return datetime.timedelta(0) + + def tzname(self, dt): + return "UTC" + + def dst(self, dt): + return datetime.timedelta(0) + +UTC = _UTC() + def _get_rc_timezone(): s = matplotlib.rcParams['timezone'] + if s == 'UTC': + return UTC + import pytz return pytz.timezone(s) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8221 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8221&view=rev Author: efiring Date: 2010年04月05日 01:06:57 +0000 (2010年4月05日) Log Message: ----------- Axes.hist: make 'label' an explicit kwarg, like 'color' Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010年04月03日 23:22:48 UTC (rev 8220) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010年04月05日 01:06:57 UTC (rev 8221) @@ -6989,7 +6989,7 @@ def hist(self, x, bins=10, range=None, normed=False, weights=None, cumulative=False, bottom=None, histtype='bar', align='mid', orientation='vertical', rwidth=None, log=False, - color=None, + color=None, label=None, **kwargs): """ call signature:: @@ -7101,24 +7101,21 @@ dataset. Default (*None*) uses the standard line color sequence. - kwargs are used to update the properties of the hist - :class:`~matplotlib.patches.Rectangle` instances: + *label*: + String, or sequence of strings to match multiple + datasets. Bar charts yield multiple patches per + dataset, but only the first gets the label, so + that the legend command will work as expected:: - %(Rectangle)s + ax.hist(10+2*np.random.randn(1000), label='men') + ax.hist(12+3*np.random.randn(1000), label='women', alpha=0.5) + ax.legend() - You can use labels for your histogram, and only the first - :class:`~matplotlib.patches.Rectangle` gets the label (the - others get the magic string '_nolegend_'. This will make the - histograms work in the intuitive way for bar charts:: + kwargs are used to update the properties of the + :class:`~matplotlib.patches.Patch` instances returned by *hist*: - ax.hist(10+2*np.random.randn(1000), label='men') - ax.hist(12+3*np.random.randn(1000), label='women', alpha=0.5) - ax.legend() + %(Patch)s - label can also be a sequence of strings. If multiple data is - provided in *x*, the labels are asigned sequentially to the - histograms. - **Example:** .. plot:: mpl_examples/pylab_examples/histogram_demo.py @@ -7315,9 +7312,9 @@ self.dataLim.intervaly = (ymin, ymax) self.autoscale_view() - label = kwargs.pop('label', '_nolegend_') - - if is_string_like(label): + if label is None: + labels = ['_nolegend_'] + elif is_string_like(label): labels = [label] elif is_sequence_of_strings(label): labels = list(label) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8220 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8220&view=rev Author: efiring Date: 2010年04月03日 23:22:48 +0000 (2010年4月03日) Log Message: ----------- Update docs, examples, for new color kwarg in hist. Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/api/api_changes.rst trunk/matplotlib/examples/pylab_examples/histogram_demo_extended.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010年04月03日 07:18:18 UTC (rev 8219) +++ trunk/matplotlib/CHANGELOG 2010年04月03日 23:22:48 UTC (rev 8220) @@ -1,7 +1,10 @@ -2010年03月24日 refactor colorbar code so that no cla() is necessary when +2010年04月03日 Added color kwarg to Axes.hist(), based on work by + Jeff Klukas. - EF + +2010年03月24日 refactor colorbar code so that no cla() is necessary when mappable is changed. -JJL -2010年03月22日 fix incorrect rubber band during the zoom mode when mouse +2010年03月22日 fix incorrect rubber band during the zoom mode when mouse leaves the axes. -JJL 2010年03月21日 x/y key during the zoom mode only changes the x/y limits. -JJL Modified: trunk/matplotlib/doc/api/api_changes.rst =================================================================== --- trunk/matplotlib/doc/api/api_changes.rst 2010年04月03日 07:18:18 UTC (rev 8219) +++ trunk/matplotlib/doc/api/api_changes.rst 2010年04月03日 23:22:48 UTC (rev 8220) @@ -10,6 +10,9 @@ Changes beyond 0.99.x ===================== +* The :meth:`matplotlib.axes.Axes.hist` *color* kwarg now accepts + a sequence of color specs to match a sequence of datasets. + * The :class:'~matplotlib.collections.EllipseCollection' has been changed in two ways: @@ -19,7 +22,7 @@ + The *height* and *width* kwargs have been changed to specify the height and width, again for consistency with - :class:'~matplotlib.patches.Ellipse`, and to better match + :class:`~matplotlib.patches.Ellipse`, and to better match their names; previously they specified the half-height and half-width. Modified: trunk/matplotlib/examples/pylab_examples/histogram_demo_extended.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/histogram_demo_extended.py 2010年04月03日 07:18:18 UTC (rev 8219) +++ trunk/matplotlib/examples/pylab_examples/histogram_demo_extended.py 2010年04月03日 23:22:48 UTC (rev 8220) @@ -63,13 +63,18 @@ # # histogram has the ability to plot multiple data in parallel ... +# Note the new color kwarg, used to override the default, which +# uses the line color cycle. # P.figure() # create a new data-set x = mu + sigma*P.randn(1000,3) -n, bins, patches = P.hist(x, 10, normed=1, histtype='bar') +n, bins, patches = P.hist(x, 10, normed=1, histtype='bar', + color=['crimson', 'burlywood', 'chartreuse'], + label=['Crimson', 'Burlywood', 'Chartreuse']) +P.legend() # # ... or we can stack the data This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8219 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8219&view=rev Author: efiring Date: 2010年04月03日 07:18:18 +0000 (2010年4月03日) Log Message: ----------- Axes.hist: add color kwarg. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010年04月02日 21:29:38 UTC (rev 8218) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010年04月03日 07:18:18 UTC (rev 8219) @@ -7097,8 +7097,10 @@ *patches*) will be returned. *color*: + Color spec or sequence of color specs, one per + dataset. Default (*None*) uses the standard line + color sequence. - kwargs are used to update the properties of the hist :class:`~matplotlib.patches.Rectangle` instances: @@ -7163,6 +7165,14 @@ nx = len(x) # number of datasets + if color is None: + color = [self._get_lines.color_cycle.next() + for i in xrange(nx)] + else: + color = mcolors.colorConverter.to_rgba_array(color) + if len(color) != nx: + raise ValueError("color kwarg must have one color per dataset") + if weights is not None: if isinstance(w, np.ndarray): w = np.array(weights) @@ -7245,11 +7255,10 @@ else: # orientation == 'vertical' _barfunc = self.bar - for m in n: - color = self._get_lines.color_cycle.next() + for m, c in zip(n, color): patch = _barfunc(bins[:-1]+boffset, m, width, bottom, align='center', log=log, - color=color) + color=c) patches.append(patch) if stacked: if bottom is None: @@ -7277,20 +7286,19 @@ fill = (histtype == 'stepfilled') - for m in n: + for m, c in zip(n, color): y[1:-1:2], y[2::2] = m, m if log: y[y<1e-100]=1e-100 if orientation == 'horizontal': x,y = y,x - color = self._get_lines.color_cycle.next() if fill: patches.append( self.fill(x, y, - closed=False, facecolor=color) ) + closed=False, facecolor=c) ) else: patches.append( self.fill(x, y, - closed=False, edgecolor=color, fill=False) ) + closed=False, edgecolor=c, fill=False) ) # adopted from adjust_x/ylim part of the bar method if orientation == 'horizontal': This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8218 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8218&view=rev Author: efiring Date: 2010年04月02日 21:29:38 +0000 (2010年4月02日) Log Message: ----------- Axes.hist: style changes, bug fixes Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010年04月02日 18:47:00 UTC (rev 8217) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010年04月02日 21:29:38 UTC (rev 8218) @@ -5311,7 +5311,7 @@ s = np.ma.ravel(s) # This doesn't have to match x, y in size. - c_is_stringy = is_string_like(c) or cbook.is_sequence_of_strings(c) + c_is_stringy = is_string_like(c) or is_sequence_of_strings(c) if not c_is_stringy: c = np.asanyarray(c) if c.size == x.size: @@ -6989,6 +6989,7 @@ def hist(self, x, bins=10, range=None, normed=False, weights=None, cumulative=False, bottom=None, histtype='bar', align='mid', orientation='vertical', rwidth=None, log=False, + color=None, **kwargs): """ call signature:: @@ -7002,16 +7003,21 @@ [*patches0*, *patches1*,...]) if the input contains multiple data. + Multiple data can be provided via *x* as a list of datasets + of potentially different length ([*x0*, *x1*, ...]), or as + a 2-D ndarray in which each column is a dataset. Note that + the ndarray form is transposed relative to the list form. + + Masked arrays are not supported at present. + Keyword arguments: *bins*: Either an integer number of bins or a sequence giving the - bins. *x* are the data to be binned. *x* can be an array, - a 2D array with multiple data in its columns, or a list of - arrays with data of different length. Note, if *bins* - is an integer input argument=numbins, *bins* + 1 bin edges - will be returned, compatible with the semantics of - :func:`numpy.histogram` with the *new* = True argument. + bins. If *bins* is an integer, *bins* + 1 bin edges + will be returned, consistent with :func:`numpy.histogram` + for numpy version >= 1.3, and with the *new* = True argument + in earlier versions. Unequally spaced bins are supported if *bins* is a sequence. *range*: @@ -7090,6 +7096,9 @@ be filtered out and only the non-empty (*n*, *bins*, *patches*) will be returned. + *color*: + + kwargs are used to update the properties of the hist :class:`~matplotlib.patches.Rectangle` instances: @@ -7117,65 +7126,74 @@ # NOTE: the range keyword overwrites the built-in func range !!! # needs to be fixed in numpy !!! + # Validate string inputs here so we don't have to clutter + # subsequent code. + if histtype not in ['bar', 'barstacked', 'step', 'stepfilled']: + raise ValueError("histtype %s is not recognized" % histtype) + + if align not in ['left', 'mid', 'right']: + raise ValueError("align kwarg %s is not recognized" % align) + + if orientation not in [ 'horizontal', 'vertical']: + raise ValueError( + "orientation kwarg %s is not recognized" % orientation) + + if kwargs.get('width') is not None: raise DeprecationWarning( 'hist now uses the rwidth to give relative width ' 'and not absolute width') - try: - # make sure a copy is created: don't use asarray - x = np.transpose(np.array(x)) - if len(x.shape)==1: - x.shape = (1,x.shape[0]) - elif len(x.shape)==2 and x.shape[1]<x.shape[0]: - warnings.warn('2D hist should be nsamples x nvariables; ' + if isinstance(x, np.ndarray): + # TODO: support masked arrays; + # Why is the copy needed? + x = np.array(x, copy=True, subok=False) + if x.ndim == 2: + x = x.T + elif x.ndim == 1: + x.shape = (1, x.shape[0]) + else: + raise ValueError("x must be 1D or 2D") + if x.shape[1] < x.shape[0]: + warnings.warn('2D hist input should be nsamples x nvariables; ' 'this looks transposed') - except ValueError: + else: # multiple hist with data of different length - if iterable(x[0]) and not is_string_like(x[0]): - tx = [] - for i in xrange(len(x)): - tx.append( np.array(x[i]) ) - x = tx - else: - raise ValueError, 'Can not use provided data to create a histogram' + x = [np.array(xi) for xi in x] + nx = len(x) # number of datasets + if weights is not None: - try: - w = np.transpose(np.array(weights)) - if len(w.shape)==1: + if isinstance(w, np.ndarray): + w = np.array(weights) + if w.ndim == 2: + w = w.T + elif w.ndim == 1: w.shape = (1, w.shape[0]) - except: - if iterable(weights[0]) and not is_string_like(weights[0]): - tw = [] - for i in xrange(len(weights)): - tw.append( np.array(weights[i]) ) - w = tw else: - raise ValueError, 'Can not use provided weights to create a hist' + raise ValueError("weights must be 1D or 2D") + else: + w = [np.array(wi) for wi in weights] - if len(x) != len(w): - raise ValueError, 'weights should have the same shape as x' - for i in xrange(len(x)): - if len(x[i]) != len(w[i]): - raise ValueError, 'weights should have the same shape as x' + if len(w) != nx: + raise ValueError('weights should have the same shape as x') + for i in xrange(nx): + if len(w[i]) != len(x[i]): + raise ValueError( + 'weights should have the same shape as x') else: - w = [None]*len(x) + w = [None]*nx # Check whether bins or range are given explicitly. In that # case do not autoscale axes. binsgiven = (cbook.iterable(bins) or range != None) - # check the version of the numpy + hist_kwargs = dict(range=range, normed=bool(normed)) if np.__version__ < "1.3": # version 1.1 and 1.2 - hist_kwargs = dict(range=range, - normed=bool(normed), new=True) - else: # version 1.3 and later, drop new=True - hist_kwargs = dict(range=range, - normed=bool(normed)) + hist_kwargs['new'] = True n = [] - for i in xrange(len(x)): + for i in xrange(nx): # this will automatically overwrite bins, # so that each histogram uses the same bins m, bins = np.histogram(x[i], bins, weights=w[i], **hist_kwargs) @@ -7195,60 +7213,50 @@ if histtype.startswith('bar'): totwidth = np.diff(bins) - stacked = False - if rwidth is not None: dr = min(1., max(0., rwidth)) - elif len(n)>1: dr = 0.8 - else: dr = 1.0 + if rwidth is not None: + dr = min(1.0, max(0.0, rwidth)) + elif len(n)>1: + dr = 0.8 + else: + dr = 1.0 if histtype=='bar': - width = dr*totwidth/len(n) + width = dr*totwidth/nx dw = width - if len(n)>1: - boffset = -0.5*dr*totwidth*(1.-1./len(n)) + if nx > 1: + boffset = -0.5*dr*totwidth*(1.0-1.0/nx) else: boffset = 0.0 + stacked = False elif histtype=='barstacked': width = dr*totwidth boffset, dw = 0.0, 0.0 - stacked = True - else: - raise ValueError, 'invalid histtype: %s' % histtype if align == 'mid' or align == 'edge': boffset += 0.5*totwidth elif align == 'right': boffset += totwidth - elif align != 'left' and align != 'center': - raise ValueError, 'invalid align: %s' % align if orientation == 'horizontal': - for m in n: - color = self._get_lines.color_cycle.next() - patch = self.barh(bins[:-1]+boffset, m, height=width, - left=bottom, align='center', log=log, - color=color) - patches.append(patch) - if stacked: - if bottom is None: bottom = 0.0 - bottom += m - boffset += dw - elif orientation == 'vertical': - for m in n: - color = self._get_lines.color_cycle.next() - patch = self.bar(bins[:-1]+boffset, m, width=width, - bottom=bottom, align='center', log=log, - color=color) - patches.append(patch) - if stacked: - if bottom is None: bottom = 0.0 - bottom += m - boffset += dw - else: - raise ValueError, 'invalid orientation: %s' % orientation + _barfunc = self.barh + else: # orientation == 'vertical' + _barfunc = self.bar + for m in n: + color = self._get_lines.color_cycle.next() + patch = _barfunc(bins[:-1]+boffset, m, width, bottom, + align='center', log=log, + color=color) + patches.append(patch) + if stacked: + if bottom is None: + bottom = 0.0 + bottom += m + boffset += dw + elif histtype.startswith('step'): x = np.zeros( 2*len(bins), np.float ) y = np.zeros( 2*len(bins), np.float ) @@ -7259,21 +7267,15 @@ x -= 0.5*(bins[1]-bins[0]) elif align == 'right': x += 0.5*(bins[1]-bins[0]) - elif align != 'mid' and align != 'edge': - raise ValueError, 'invalid align: %s' % align if log: y[0],y[-1] = 1e-100, 1e-100 if orientation == 'horizontal': self.set_xscale('log') - elif orientation == 'vertical': + else: # orientation == 'vertical' self.set_yscale('log') - fill = False - if histtype == 'stepfilled': - fill = True - elif histtype != 'step': - raise ValueError, 'invalid histtype: %s' % histtype + fill = (histtype == 'stepfilled') for m in n: y[1:-1:2], y[2::2] = m, m @@ -7281,8 +7283,6 @@ y[y<1e-100]=1e-100 if orientation == 'horizontal': x,y = y,x - elif orientation != 'vertical': - raise ValueError, 'invalid orientation: %s' % orientation color = self._get_lines.color_cycle.next() if fill: @@ -7307,17 +7307,17 @@ self.dataLim.intervaly = (ymin, ymax) self.autoscale_view() - else: - raise ValueError, 'invalid histtype: %s' % histtype + label = kwargs.pop('label', '_nolegend_') - label = kwargs.pop('label', '') - if is_string_like(label): - labels = [label] + ['_nolegend_']*(len(patches)-1) - elif is_sequence_of_strings: - labels = list(label) + ['_nolegend_']*(len(patches)-1) + labels = [label] + elif is_sequence_of_strings(label): + labels = list(label) else: - raise ValueError, 'invalid label: must be string or sequence of strings' + raise ValueError( + 'invalid label: must be string or sequence of strings') + if len(labels) < nx: + labels += ['_nolegend_'] * (nx - len(labels)) for (patch, lbl) in zip(patches, labels): for p in patch: @@ -7329,14 +7329,16 @@ 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]) + 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]) + YL = self.yaxis.get_major_locator().view_limits( + bins[0], bins[-1]) self.set_ybound(YL) - if len(n)==1: + if nx == 1: return n[0], bins, cbook.silent_list('Patch', patches[0]) else: return n, bins, cbook.silent_list('Lists of Patches', patches) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8217 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8217&view=rev Author: ryanmay Date: 2010年04月02日 18:47:00 +0000 (2010年4月02日) Log Message: ----------- Correct calculation of vectors with quiver and angles='xy'. Using just a small eps can result in roundoff problems if X,Y are large (such as with Basemap). Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/quiver.py Modified: trunk/matplotlib/lib/matplotlib/quiver.py =================================================================== --- trunk/matplotlib/lib/matplotlib/quiver.py 2010年04月01日 03:41:24 UTC (rev 8216) +++ trunk/matplotlib/lib/matplotlib/quiver.py 2010年04月02日 18:47:00 UTC (rev 8217) @@ -537,10 +537,11 @@ # points, regardless of the axis scaling (including log). angles, lengths = self._angles_lengths(U, V, eps=1) elif self.angles == 'xy' or self.scale_units == 'xy': - # We could refine this by calculating eps based on - # the magnitude of U, V relative to that of X, Y, - # to ensure we are always making small shifts in X, Y. - angles, lengths = self._angles_lengths(U, V, eps=0.001) + # Calculate eps based on the extents of the plot + # so that we don't end up with roundoff error from + # adding a small number to a large. + angles, lengths = self._angles_lengths(U, V, + eps=np.abs(self.ax.dataLim.extents).max() * 0.001) if self.scale_units == 'xy': a = lengths else: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.