From: <lee...@us...> - 2009-06-24 05:47:10
|
Revision: 7233 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7233&view=rev Author: leejjoon Date: 2009-06-24 05:46:08 +0000 (Wed, 24 Jun 2009) Log Message: ----------- axes_grid: floating_axis support added Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/axes_grid/scatter_hist.py trunk/matplotlib/examples/axes_grid/simple_axisline.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_finder.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_helper_curvelinear.py Added Paths: ----------- trunk/matplotlib/examples/axes_grid/demo_floating_axis.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-06-23 12:47:49 UTC (rev 7232) +++ trunk/matplotlib/CHANGELOG 2009-06-24 05:46:08 UTC (rev 7233) @@ -1,3 +1,5 @@ +2009-06-24 axes_grid: floating axis support added. - JJL + 2009-06-14 Add new command line options to backend_driver.py to support running only some directories of tests - JKS Added: trunk/matplotlib/examples/axes_grid/demo_floating_axis.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_floating_axis.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/demo_floating_axis.py 2009-06-24 05:46:08 UTC (rev 7233) @@ -0,0 +1,77 @@ +""" +A floating axes for curvelinear grid. +. +""" + + +def curvelinear_test2(fig): + """ + polar projection, but in a rectangular box. + """ + import numpy as np + import mpl_toolkits.axes_grid.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.axes_grid.grid_helper_curvelinear import GridHelperCurveLinear + + # see demo_curvelinear_grid.py for details + tr = Affine2D().scale(np.pi/180., 1.) + PolarAxes.PolarTransform() + + extreme_finder = angle_helper.ExtremeFinderCycle(20, 20, + lon_cycle = 360, + lat_cycle = None, + lon_minmax = None, + lat_minmax = (0, np.inf), + ) + + grid_locator1 = angle_helper.LocatorDMS(12) + + tick_formatter1 = angle_helper.FormatterDMS() + + grid_helper = GridHelperCurveLinear(tr, + extreme_finder=extreme_finder, + grid_locator1=grid_locator1, + tick_formatter1=tick_formatter1 + ) + + + ax1 = SubplotHost(fig, 1, 1, 1, grid_helper=grid_helper) + + # make ticklabels of right and top axis visible. + for axis in ax1.axis.values(): + axis.toggle(all=False) + + fig.add_subplot(ax1) + + # Now creates floating axis + + grid_helper = ax1.get_grid_helper() + # floating axis whose first coordinate (theta) is fixed at 60 + ax1.axis["lat"] = axis = grid_helper.new_floating_axis(0, 60, axes=ax1) + axis.label.set_text(r"$\theta = 60^{\circ}$") + axis.label.set_visible(True) + + # floating axis whose second coordinate (r) is fixed at 6 + ax1.axis["lon"] = axis = grid_helper.new_floating_axis(1, 6, axes=ax1) + axis.label.set_text(r"$r = 6$") + + ax1.set_aspect(1.) + ax1.set_xlim(-5, 12) + ax1.set_ylim(-5, 10) + + ax1.grid(True) + +if __name__ == "__main__": + import matplotlib.pyplot as plt + fig = plt.figure(1, figsize=(5, 5)) + fig.clf() + + curvelinear_test2(fig) + + plt.draw() + plt.show() + + Modified: trunk/matplotlib/examples/axes_grid/scatter_hist.py =================================================================== --- trunk/matplotlib/examples/axes_grid/scatter_hist.py 2009-06-23 12:47:49 UTC (rev 7232) +++ trunk/matplotlib/examples/axes_grid/scatter_hist.py 2009-06-24 05:46:08 UTC (rev 7233) @@ -56,5 +56,5 @@ axHisty.set_xticks([0, 50, 100]) plt.draw() -#plt.show() -plt.savefig("a.pdf") +plt.show() +#plt.savefig("a.pdf") Modified: trunk/matplotlib/examples/axes_grid/simple_axisline.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axisline.py 2009-06-23 12:47:49 UTC (rev 7232) +++ trunk/matplotlib/examples/axes_grid/simple_axisline.py 2009-06-24 05:46:08 UTC (rev 7233) @@ -29,7 +29,8 @@ new_axisline = ax.get_grid_helper().new_fixed_axis ax.axis["right2"] = new_axisline(loc="right", - offset=offset) + offset=offset, + axes=ax) ax.axis["right2"].label.set_text("Label Y2") ax.plot([-2,3,2]) Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py 2009-06-23 12:47:49 UTC (rev 7232) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py 2009-06-24 05:46:08 UTC (rev 7233) @@ -143,7 +143,7 @@ -class AxesGrid(object): +class Grid(object): """ A class that creates a grid of Axes. In matplotlib, the axes location (and size) is specified in the normalized figure @@ -161,6 +161,269 @@ 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:`AxesGrid` 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" ] + 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 AxesGrid(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. 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, aspect=True, label_mode="L", cbar_mode=None, @@ -217,6 +480,8 @@ self._colorbar_size = cbar_size + self._init_axes_pad(axes_pad) + if direction not in ["column", "row"]: raise Exception("") @@ -312,7 +577,7 @@ 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) #Size.Fixed(self._axes_pad)) h_ax_pos.append(len(h)) @@ -333,7 +598,8 @@ 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._horiz_pad_size) #Size.Fixed(self._axes_pad)) + v_ax_pos.append(len(v)) if ax: sz = Size.AxesY(ax) @@ -396,75 +662,27 @@ - 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 +#if __name__ == "__main__": +if 0: + F = plt.figure(1, (7, 6)) + F.clf() - def __getitem__(self, i): - return self.axes_all[i] + 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", + ) - 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 - 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) - - - - if __name__ == "__main__": +#if 0: from axes_divider import get_demo_image F = plt.figure(1, (9, 3.5)) F.clf() Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py 2009-06-23 12:47:49 UTC (rev 7232) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py 2009-06-24 05:46:08 UTC (rev 7233) @@ -21,13 +21,14 @@ class Fixed(_Base): "Simple fixed size with absolute part = *fixed_size* and relative part = 0" def __init__(self, fixed_size): - self._fixed_size = fixed_size + self.fixed_size = fixed_size def get_size(self, renderer): rel_size = 0. - abs_size = self._fixed_size + abs_size = self.fixed_size return rel_size, abs_size + class Scaled(_Base): "Simple scaled(?) size with absolute part = 0 and relative part = *scalable_size*" def __init__(self, scalable_size): Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py 2009-06-23 12:47:49 UTC (rev 7232) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py 2009-06-24 05:46:08 UTC (rev 7233) @@ -54,6 +54,9 @@ from matplotlib.collections import LineCollection from matplotlib import rcParams + +from matplotlib.artist import allow_rasterization + import warnings import numpy as np @@ -127,7 +130,7 @@ will be axes attribute of the caller artist. - # LINE + # LINE (spinal line?) def get_line(self, axes): # path : Path @@ -168,24 +171,27 @@ """ + class _Base(object): - + """ + Base class for axis helper. + """ def __init__(self, label_direction): + """ + label direction must be one of + ["left", "right", "bottom", "top", + "curved"] + """ self.label_direction = label_direction - #def update(self): - # raise UnimplementedException("update method not implemented") - def update_lim(self, axes): pass _label_angles = dict(left=90, right=90, bottom=0, top=0) _ticklabel_angles = dict(left=0, right=0, bottom=0, top=0) - def _get_label_offset_transform(self, pad_points, fontprops, renderer, - bboxes=None, - #trans=None - ): + def _get_label_offset_transform(self, pad_points, fontprops, + renderer, bboxes=None): """ Returns (offset-transform, vertical-alignment, horiz-alignment) @@ -200,6 +206,7 @@ fontprops : font properties for label renderer : renderer bboxes=None : list of bboxes (window extents) of the tick labels. + This only make sense for axis label. all the above parameters are used to estimate the offset. @@ -223,44 +230,44 @@ tr = Affine2D() if self.label_direction == "left": tr.translate(-(pad_pixels+w), 0.) - #trans = trans + tr return tr, "center", "right" elif self.label_direction == "right": tr.translate(+(pad_pixels+w), 0.) - #trans = trans + tr return tr, "center", "left" elif self.label_direction == "bottom": tr.translate(0, -(pad_pixels+font_size_pixels+h)) - #trans = trans + tr return tr, "baseline", "center" elif self.label_direction == "top": tr.translate(0, +(pad_pixels+h)) - #trans = trans + tr return tr, "baseline", "center" + elif self.label_direction == "curved": + #tr.translate(0, +(pad_pixels+h)) + + return tr, "baseline", "center" + else: - raise ValueError("") + raise ValueError("Unknown label direction : %s" \ + % (self.label_direction,)) - def get_label_offset_transform(self, - axes, + def get_label_offset_transform(self, axes, pad_points, fontprops, renderer, bboxes, - #trans=None ): + """ + offset transform for axis label. + """ - tr, va, ha = self._get_label_offset_transform(pad_points, fontprops, - renderer, - bboxes, - #trans - ) + tr, va, ha = self._get_label_offset_transform( \ + pad_points, fontprops, renderer, bboxes) a = self._label_angles[self.label_direction] return tr, va, ha, a @@ -270,11 +277,12 @@ pad_points, fontprops, renderer, ): + """ + offset transform for ticklabels. + """ - tr, va, ha = self._get_label_offset_transform(pad_points, fontprops, - renderer, - None, - ) + tr, va, ha = self._get_label_offset_transform( \ + pad_points, fontprops, renderer, None) a = self._ticklabel_angles[self.label_direction] return tr, va, ha, a @@ -282,6 +290,9 @@ class Fixed(_Base): + """ + Helper class for a fixed (in the axes coordinate) axis. + """ _default_passthru_pt = dict(left=(0, 0), right=(1, 0), @@ -289,8 +300,8 @@ top=(0, 1)) def __init__(self, - loc, nth_coord=None, - passingthrough_point=None, label_direction=None): + loc, + label_direction=None): """ nth_coord = along which coordinate value varies in 2d, nth_coord = 0 -> x axis, nth_coord = 1 -> y axis @@ -298,23 +309,21 @@ if loc not in ["left", "right", "bottom", "top"]: raise ValueError("%s" % loc) - if nth_coord is None: - if loc in ["left", "right"]: - nth_coord = 1 - elif loc in ["bottom", "top"]: - nth_coord = 0 + #if nth_coord is None: + if loc in ["left", "right"]: + nth_coord = 1 + elif loc in ["bottom", "top"]: + nth_coord = 0 self.nth_coord = nth_coord super(AxisArtistHelper.Fixed, self).__init__(loc) - if passingthrough_point is None: - passingthrough_point = self._default_passthru_pt[loc] + self.passthru_pt = self._default_passthru_pt[loc] if label_direction is None: label_direction = loc - self.passthru_pt = passingthrough_point _verts = np.array([[0., 0.], [1., 1.]]) @@ -336,7 +345,7 @@ def get_line_transform(self, axes): return axes.transAxes - # LABLE + # LABEL def get_label_pos(self, axes): """ @@ -358,11 +367,9 @@ tr, va, ha = self._get_label_offset_transform( \ pad_points, fontprops, renderer, bboxes, - #trans ) a = self._label_angles[self.label_direction] - #tr = axes.transAxes + tr return tr, va, ha, a @@ -380,14 +387,12 @@ class Floating(_Base): def __init__(self, nth_coord, - passingthrough_point, label_direction, transform): + value, label_direction): self.nth_coord = nth_coord - self.passingthrough_point = passingthrough_point + self._value = value - self.transform = transform - super(AxisArtistHelper.Floating, self).__init__(label_direction) @@ -396,72 +401,25 @@ return self.nth_coord def get_line(self, axes): - _verts = np.array([[0., 0.], - [1., 1.]]) + raise RuntimeError("get_line method should be defined by the derived class") - fixed_coord = 1-self.nth_coord - trans_passingthrough_point = self.transform + axes.transAxes.inverted() - p = trans_passingthrough_point.transform_point(self.passingthrough_point) - _verts[:,fixed_coord] = p[fixed_coord] - return Path(_verts) - def get_line_transform(self, axes): - return axes.transAxes - def get_label_pos(self, axes): - _verts = [0.5, 0.5] - - fixed_coord = 1-self.nth_coord - trans_passingthrough_point = self.transform + axes.transAxes.inverted() - p = trans_passingthrough_point.transform_point(self.passingthrough_point) - _verts[fixed_coord] = p[fixed_coord] - if not (0. <= _verts[fixed_coord] <= 1.): - return None, None - else: - return _verts, axes.transAxes - - def get_label_transform(self, axes, - pad_points, fontprops, renderer, - bboxes, - ): - - tr, va, ha = self._get_label_offset_transform(pad_points, fontprops, - renderer, - bboxes, - #trans - ) - - a = self._label_angles[self.label_direction] - tr = axes.transAxes + tr - #tr = axes.transAxes + tr - - return tr, va, ha, a - - - - def get_tick_transform(self, axes): - return self.transform - - - - - class AxisArtistHelperRectlinear: class Fixed(AxisArtistHelper.Fixed): def __init__(self, - axes, loc, nth_coord=None, - passingthrough_point=None, label_direction=None): + axes, loc, #nth_coord=None, + label_direction=None): """ nth_coord = along which coordinate value varies in 2d, nth_coord = 0 -> x axis, nth_coord = 1 -> y axis """ super(AxisArtistHelperRectlinear.Fixed, self).__init__( \ - loc, nth_coord, - passingthrough_point, label_direction) + loc, label_direction) self.axis = [axes.xaxis, axes.yaxis][self.nth_coord] @@ -498,7 +456,7 @@ # check if the tick point is inside axes c2 = tr2ax.transform_point(c) - delta=0.001 + delta=0.00001 if 0. -delta<= c2[self.nth_coord] <= 1.+delta: yield c, angle, l @@ -508,14 +466,60 @@ class Floating(AxisArtistHelper.Floating): def __init__(self, axes, nth_coord, - passingthrough_point, label_direction, transform): + passingthrough_point, label_direction): super(AxisArtistHelperRectlinear.Floating, self).__init__( \ - nth_coord, passingthrough_point, label_direction, transform) + nth_coord, passingthrough_point, label_direction) self.axis = [axes.xaxis, axes.yaxis][self.nth_coord] + def get_line(self, axes): + _verts = np.array([[0., 0.], + [1., 1.]]) + + fixed_coord = 1-self.nth_coord + trans_passingthrough_point = axes.transData + axes.transAxes.inverted() + p = trans_passingthrough_point.transform_point([self._value, + self._value]) + _verts[:,fixed_coord] = p[fixed_coord] + + return Path(_verts) + + def get_line_transform(self, axes): + return axes.transAxes + + def get_label_pos(self, axes): + _verts = [0.5, 0.5] + + fixed_coord = 1-self.nth_coord + trans_passingthrough_point = axes.transData + axes.transAxes.inverted() + p = trans_passingthrough_point.transform_point([self._value, + self._value]) + _verts[fixed_coord] = p[fixed_coord] + if not (0. <= _verts[fixed_coord] <= 1.): + return None, None + else: + return _verts, axes.transAxes + + def get_label_transform(self, axes, + pad_points, fontprops, renderer, + bboxes, + ): + + tr, va, ha = self._get_label_offset_transform(pad_points, fontprops, + renderer, bboxes) + + a = self._label_angles[self.label_direction] + tr = axes.transAxes + tr + + return tr, va, ha, a + + + def get_tick_transform(self, axes): + return axes.transData + + def get_tick_iterators(self, axes): """tick_loc, tick_angle, tick_label""" @@ -531,12 +535,12 @@ minor.formatter.set_locs(minorLocs) minorLabels = [minor.formatter(val, i) for i, val in enumerate(minorLocs)] - tr2ax = self.transform + axes.transAxes.inverted() + tr2ax = axes.transData + axes.transAxes.inverted() def _f(locs, labels): for x, l in zip(locs, labels): - c = list(self.passingthrough_point) # copy + c = [self._value, self._value] c[self.nth_coord] = x c1, c2 = tr2ax.transform_point(c) if 0. <= c1 <= 1. and 0. <= c2 <= 1.: @@ -573,7 +577,10 @@ def invalidate(self): self._force_update = True + def valid(self): + return not self._force_update + def get_gridlines(self): return [] @@ -587,26 +594,10 @@ super(GridHelperRectlinear, self).__init__() self.axes = axes - #def set_axes(self, axes): - # self.axes = axes - def _get_axisline_helper_deprecated(self, nth_coord, loc, - passingthrough_point, transform=None): - if transform is None or transform is self.axes.transAxes: - return AxisArtistHelper.Fixed(self.axes, loc, - nth_coord, passingthrough_point) - else: - label_direction = loc - return AxisArtistHelper.Floating(self.axes, - nth_coord, passingthrough_point, - label_direction, - transform) - - def new_fixed_axis(self, loc, - nth_coord=None, passthrough_point=None, - #transform=None, + nth_coord=None, tick_direction="in", label_direction=None, offset=None, @@ -617,65 +608,38 @@ warnings.warn("'new_fixed_axis' explicitly requires the axes keyword.") axes = self.axes - _helper = AxisArtistHelperRectlinear.Fixed(axes, loc, - nth_coord, - passthrough_point) + _helper = AxisArtistHelperRectlinear.Fixed(axes, loc, nth_coord) - axisline = AxisArtist(axes, _helper, - #tick_direction="in", - offset=offset, - ) + axisline = AxisArtist(axes, _helper, offset=offset) return axisline - def new_floating_axis(self, nth_coord=None, passthrough_point=None, - transform=None, + def new_floating_axis(self, nth_coord, value, tick_direction="in", label_direction=None, - axes=None, - ): + axes=None, + ): if axes is None: warnings.warn("'new_floating_axis' explicitly requires the axes keyword.") axes = self.axes + passthrough_point = (value, value) + transform = axes.transData + _helper = AxisArtistHelperRectlinear.Floating( \ - axes, - nth_coord, passthrough_point, - label_direction, - transform) + axes, nth_coord, value, label_direction) - axisline = AxisArtist(axes, _helper, - #tick_direction="in", - ) + axisline = AxisArtist(axes, _helper) + axisline.line.set_clip_on(True) + axisline.line.set_clip_box(axisline.axes.bbox) return axisline - def new_axisline_deprecated(self, loc, - nth_coord=None, passthrough_point=None, - transform=None, - tick_direction="in", - label_direction=None, - offset=None): - warnings.warn("new_axisline is deprecated. Use new_fixed_axis " - "or new_floating_axis instead") - _helper = self._get_axisline_helper(nth_coord, loc, - passthrough_point, - transform) - - axisline = AxisArtist(self.axes, _helper, - #tick_direction="in", - offset=offset, - ) - - return axisline - - - from matplotlib.lines import Line2D class Ticks(Line2D): @@ -691,6 +655,7 @@ kwargs["markeredgewidth"] = "auto" super(Ticks, self).__init__([0.], [0.], **kwargs) + self.set_snap(True) def get_color(self): @@ -724,8 +689,8 @@ return self._markeredgewidth - def update_locs_angles(self, locs_angles, renderer): - self.locs_angles = locs_angles + def update_ticks(self, locs_angles_labels, renderer): + self.locs_angles_labels = locs_angles_labels _tickvert_path = Path([[0., 0.], [0., 1.]]) @@ -763,12 +728,12 @@ offset = renderer.points_to_pixels(size) marker_scale = Affine2D().scale(offset, offset) - for loc, angle in self.locs_angles: + for loc, angle, _ in self.locs_angles_labels: marker_rotation = Affine2D().rotate_deg(angle) #marker_rotation.clear().rotate_deg(angle) marker_transform = marker_scale + marker_rotation - locs = path_trans.transform_non_affine(np.array([loc])) + locs = path_trans.transform_non_affine(np.array([loc, loc])) renderer.draw_markers(gc, self._tickvert_path, marker_transform, Path(locs), path_trans.get_affine()) @@ -780,7 +745,7 @@ class TickLabels(mtext.Text): def __init__(self, size, **kwargs): - self._locs_labels = [] + self.locs_angles_labels = [] self._axis = kwargs.pop("axis", None) if self._axis is not None: @@ -790,10 +755,17 @@ super(TickLabels, self).__init__(x=0., y=0., text="", **kwargs ) + self._rotate_ticklabel = None - def update_locs_labels(self, locs_labels, renderer): - self._locs_labels = locs_labels + def set_rotate_along_line(self, b): + self._rotate_ticklabel = b + def get_rotate_along_line(self): + return self._rotate_ticklabel + + def update_ticks(self, locs_angles_labels, renderer): + self.locs_angles_labels = locs_angles_labels + def get_color(self): if self._color == 'auto': if self._axis is not None: @@ -809,15 +781,45 @@ def draw(self, renderer): if not self.get_visible(): return - for (x, y), l in self._locs_labels: - self.set_x(x) - self.set_y(y) - self.set_text(l) - super(TickLabels, self).draw(renderer) + if self.get_rotate_along_line(): + # curved axis + # save original and adjust some properties + tr = self.get_transform() + rm = self.get_rotation_mode() + + self.set_rotation_mode("anchor") + offset_tr = Affine2D() + self.set_transform(tr+offset_tr) + + # estimate pad + dd = 5 + renderer.points_to_pixels(self.get_size()) + + for (x, y), a, l in self.locs_angles_labels: + theta = (a+90.)/180.*np.pi + dx, dy = dd * np.cos(theta), dd * np.sin(theta) + offset_tr.translate(dx, dy) + self.set_rotation(a-180) + self.set_x(x) + self.set_y(y) + self.set_text(l) + super(TickLabels, self).draw(renderer) + offset_tr.clear() + + # restore original properties + self.set_transform(tr) + self.set_rotation_mode(rm) + else: + for (x, y), a, l in self.locs_angles_labels: + self.set_x(x) + self.set_y(y) + self.set_text(l) + super(TickLabels, self).draw(renderer) + + def get_window_extents(self, renderer): bboxes = [] - for (x, y), l in self._locs_labels: + for (x, y), a, l in self.locs_angles_labels: self.set_x(x) self.set_y(y) self.set_text(l) @@ -825,15 +827,10 @@ bboxes.append(self.get_window_extent()) return [b for b in bboxes if b.width!=0 or b.height!=0] - #if bboxes: - # return Bbox.union([b for b in bboxes if b.width!=0 or b.height!=0]) - #else: - # return Bbox.from_bounds(0, 0, 0, 0) - class AxisLabel(mtext.Text): def __init__(self, *kl, **kwargs): self._axis = kwargs.pop("axis", None) @@ -872,7 +869,6 @@ def draw(self, renderer): if self._grid_helper is not None: self._grid_helper.update_lim(self.axes) - #self.set_transform(self._grid_helper.get_gridlines_transform()) gl = self._grid_helper.get_gridlines() if gl: self.set_segments([np.transpose(l) for l in gl]) @@ -882,12 +878,8 @@ -class AxisGridLineBase(martist.Artist): - def __init__(self, *kl, **kw): - super(AxisGridLineBase, self).__init__(*kl, **kw) - -class AxisArtist(AxisGridLineBase): +class AxisArtist(martist.Artist): """ an artist which draws axis (a line along which the n-th axes coord is constant) line, ticks, ticklabels, and axis label. @@ -900,7 +892,6 @@ def __init__(self, axes, helper, - #offset_transform=None, offset=None, major_tick_size=None, major_tick_pad=None, @@ -910,7 +901,7 @@ """ axes is also used to follow the axis attribute (tick color, etc). """ - AxisGridLineBase.__init__(self, **kw) + super(AxisArtist, self).__init__(**kw) self.axes = axes @@ -922,9 +913,6 @@ self.offset_transform = ScaledTranslation(offset[0], offset[1], self.dpi_transform) - #self.set_transform(axes.transAxes + \ - # self.offset_transform) - self._label_visible = True self._majortick_visible = True self._majorticklabel_visible = True @@ -956,6 +944,14 @@ self.set_zorder(self.ZORDER) + self._rotate_label_along_line = False + + def set_rotate_label_along_line(self, b): + self._rotate_label_along_line = b + + def get_rotate_label_along_line(self): + return self._rotate_label_along_line + def get_transform(self): return self.axes.transAxes + self.offset_transform @@ -992,14 +988,10 @@ size = rcParams['xtick.labelsize'] fontprops = font_manager.FontProperties(size=size) - #tvhl = self._axis_artist_helper.get_ticklabel_transform( tvhl = self._axis_artist_helper.get_ticklabel_offset_transform( \ - self.axes, - self.major_tick_pad, - fontprops=fontprops, - renderer=None, - ) - #trans=transform) + self.axes, self.major_tick_pad, + fontprops=fontprops, renderer=None) + trans, vert, horiz, label_a = tvhl trans = transform + trans @@ -1031,9 +1023,6 @@ x,y,va,ha = self._offsetText_pos[direction] - #d = self._axis_artist_helper.label_direction - #fp = font_manager.FontProperties(size=rcParams['xtick.labelsize']) - #fp = font_manager.FontProperties(size=self.major_ticklabels.get_size()) self.offsetText = mtext.Annotation("", xy=(x,y), xycoords="axes fraction", xytext=(0,0), textcoords="offset points", @@ -1059,20 +1048,12 @@ def _draw_ticks(self, renderer): - #majortick_iter, minortick_iter): - #major_locs, major_angles, - #minor_locs, minor_angles): majortick_iter, minortick_iter = \ self._axis_artist_helper.get_tick_iterators(self.axes) - tick_loc_angles = [] - tick_loc_labels = [] - for tick_loc, tick_angle, tick_label in majortick_iter: - tick_loc_angles.append((tick_loc, tick_angle)) - tick_loc_labels.append((tick_loc, tick_label)) + tick_loc_angle_label = list(majortick_iter) - transform=self._axis_artist_helper.get_tick_transform(self.axes) \ + self.offset_transform fontprops = font_manager.FontProperties(size=12) @@ -1082,7 +1063,7 @@ fontprops=fontprops, renderer=renderer, ) - #trans=transform) + trans, va, ha, a = tvhl trans = transform + trans @@ -1090,20 +1071,16 @@ va=va, ha=ha, rotation=a) - self.major_ticks.update_locs_angles(tick_loc_angles, renderer) - self.major_ticklabels.update_locs_labels(tick_loc_labels, renderer) + self.major_ticks.update_ticks(tick_loc_angle_label, renderer) + self.major_ticklabels.update_ticks(tick_loc_angle_label, renderer) self.major_ticks.draw(renderer) self.major_ticklabels.draw(renderer) - tick_loc_angles = [] - tick_loc_labels = [] - for tick_loc, tick_angle, tick_label in minortick_iter: - tick_loc_angles.append((tick_loc, tick_angle)) - tick_loc_labels.append((tick_loc, tick_label)) + tick_loc_angle_label = list(minortick_iter) - self.minor_ticks.update_locs_angles(tick_loc_angles, renderer) - self.minor_ticklabels.update_locs_labels(tick_loc_labels, renderer) + self.minor_ticks.update_ticks(tick_loc_angle_label, renderer) + self.minor_ticklabels.update_ticks(tick_loc_angle_label, renderer) self.minor_ticks.draw(renderer) self.minor_ticklabels.draw(renderer) @@ -1113,9 +1090,11 @@ return self.major_ticklabels.get_window_extents(renderer) + def _init_label(self): # x in axes coords, y in display coords (to be updated at draw # time by _update_label_positions) + fontprops = font_manager.FontProperties(size=rcParams['axes.labelsize']) textprops = dict(fontproperties = fontprops, color = rcParams['axes.labelcolor'], @@ -1129,7 +1108,6 @@ self.label.set_figure(self.axes.figure) - #self._set_artist_props(label) def _draw_label(self, renderer, bboxes): @@ -1137,31 +1115,50 @@ return fontprops = font_manager.FontProperties(size=rcParams['axes.labelsize']) - pad_points = self.LABELPAD + self.major_tick_pad - xy, tr = self._axis_artist_helper.get_label_pos(self.axes) - if xy is None: return - x, y = xy - tr2, va, ha, a = self._axis_artist_helper.get_label_offset_transform(\ - self.axes, - pad_points, fontprops, - renderer, - bboxes=bboxes, - ) - #trans=tr+self.offset_transform) - tr2 = (tr+self.offset_transform) + tr2 + pad_points = self.major_tick_pad - self.label.set(x=x, y=y, - transform=tr2, - va=va, ha=ha, rotation=a) + if self.get_rotate_label_along_line(): + xy, tr, label_a = self._axis_artist_helper.get_label_pos( \ + self.axes, with_angle=True) + if xy is None: return -# if self.label.get_text() == "__from_axes__": -# label_text = self._helper.axis.get_label().get_text() -# self.label.set_text(label_text) -# self.label.draw(renderer) -# self.label.set_text("__from_axes__") -# else: + x, y = xy + offset_tr = Affine2D() + if self.major_ticklabels.get_visible(): + dd = renderer.points_to_pixels(self.major_ticklabels.get_size() \ + + pad_points + 2*self.LABELPAD ) + else: + dd = renderer.points_to_pixels(pad_points + 2*self.LABELPAD) + + theta = label_a - 0.5 * np.pi #(label_a)/180.*np.pi + dx, dy = dd * np.cos(theta), dd * np.sin(theta) + offset_tr.translate(dx, dy) + tr2 = (tr+offset_tr) #+ tr2 + + self.label.set(x=x, y=y, + rotation_mode="anchor", + transform=tr2, + va="center", ha="center", + rotation=label_a/np.pi*180.) + else: + xy, tr = self._axis_artist_helper.get_label_pos(self.axes) + if xy is None: return + + x, y = xy + tr2, va, ha, a = self._axis_artist_helper.get_label_offset_transform(\ + self.axes, + pad_points+2*self.LABELPAD, fontprops, + renderer, + bboxes=bboxes, + ) + tr2 = (tr+self.offset_transform) + tr2 + + self.label.set(x=x, y=y, + transform=tr2, + va=va, ha=ha, rotation=a) + self.label.draw(renderer) @@ -1169,6 +1166,7 @@ self.label.set_text(s) + @allow_rasterization def draw(self, renderer): 'Draw the axis lines, tick lines and labels' @@ -1239,8 +1237,6 @@ else: self._grid_helper = GridHelperRectlinear(self) - #if self._grid_helper.axes is None: - # self._grid_helper.set_axes(self) self._axisline_on = True super(Axes, self).__init__(*kl, **kw) @@ -1269,7 +1265,7 @@ super(Axes, self)._init_axis() - def _init_axislines(self): + def _init_axis_artists(self): self._axislines = self.AxisDict(self) new_fixed_axis = self.get_grid_helper().new_fixed_axis for loc in ["bottom", "top", "left", "right"]: @@ -1285,7 +1281,7 @@ axis = property(_get_axislines) - def new_gridlines(self, grid_helper=None): + def _init_gridlines(self, grid_helper=None): gridlines = GridlinesCollection(None, transform=self.transData, colors=rcParams['grid.color'], linestyles=rcParams['grid.linestyle'], @@ -1296,14 +1292,14 @@ gridlines.set_grid_helper(grid_helper) gridlines.set_clip_on(True) - return gridlines + self.gridlines = gridlines def cla(self): # gridlines need to b created before cla() since cla calls grid() - self.gridlines = self.new_gridlines() + self._init_gridlines() super(Axes, self).cla() - self._init_axislines() + self._init_axis_artists() def get_grid_helper(self): return self._grid_helper @@ -1322,9 +1318,6 @@ if len(kwargs): martist.setp(self.gridlines, **kwargs) - #def get_gridlines(self): - # return self._grid_helper.get_gridlines() - def get_children(self): if self._axisline_on: children = self._axislines.values()+[self.gridlines] @@ -1334,10 +1327,22 @@ return children def invalidate_grid_helper(self): - #self._grid_helper.update_lim(self, force_update=True) self._grid_helper.invalidate() + def new_floating_axis(self, nth_coord, value, + tick_direction="in", + label_direction=None, + ): + gh = self.get_grid_helper() + axis = gh.new_floating_axis(nth_coord, value, + tick_direction=tick_direction, + label_direction=label_direction, + axes=self) + return axis + + + def draw(self, renderer, inframe=False): if not self._axisline_on: @@ -1359,8 +1364,6 @@ if not self._axisline_on: return bb0 - - #artists = [] bb = [bb0] for axisline in self._axislines.values(): @@ -1397,13 +1400,12 @@ super(AxesZero, self).__init__(*kl, **kw) - def _init_axislines(self): - super(AxesZero, self)._init_axislines() + def _init_axis_artists(self): + super(AxesZero, self)._init_axis_artists() new_floating_axis = self._grid_helper.new_floating_axis xaxis_zero = new_floating_axis(nth_coord=0, - passthrough_point=(0.,0.), - transform=self.transData, + value=0., tick_direction="in", label_direction="bottom", axes=self) @@ -1413,8 +1415,7 @@ self._axislines["xzero"] = xaxis_zero yaxis_zero = new_floating_axis(nth_coord=1, - passthrough_point=(0.,0.), - transform=self.transData, + value=0., tick_direction="in", label_direction="left", axes=self) @@ -1428,6 +1429,8 @@ if __name__ == "__main__": + import matplotlib.pyplot as plt + fig = plt.figure(1, (4,3)) ax = SubplotZero(fig, 1, 1, 1) @@ -1441,7 +1444,8 @@ xx = np.arange(0, 2*np.pi, 0.01) ax.plot(xx, np.sin(xx)) - + ax.set_ylabel("Test") + plt.draw() plt.show() Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_finder.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_finder.py 2009-06-23 12:47:49 UTC (rev 7232) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_finder.py 2009-06-24 05:46:08 UTC (rev 7233) @@ -5,6 +5,7 @@ clip_line_to_rect = clip_path.clip_line_to_rect import matplotlib.ticker as mticker +from matplotlib.transforms import Transform # extremes finder @@ -51,9 +52,11 @@ tick_formatter1=None, tick_formatter2=None): """ - transform : transfrom from the image coordinate (which will be the transData of the axes to the world coordinate. locator1, locator2 : grid locator for 1st and 2nd axis. + + Derived must define "transform_xy, inv_transform_xy" + (may use update_transform) """ super(GridFinderBase, self).__init__() @@ -63,16 +66,14 @@ self.tick_formatter1 = tick_formatter1 self.tick_formatter2 = tick_formatter2 - def get_grid_info(self, - transform_xy, inv_transform_xy, x1, y1, x2, y2): """ lon_values, lat_values : list of grid values. if integer is given, rough number of grids in each direction. """ - extremes = self.extreme_finder(transform_xy, x1, y1, x2, y2) + extremes = self.extreme_finder(self.inv_transform_xy, x1, y1, x2, y2) # min & max rage of lat (or lon) for each grid line will be drawn. # i.e., gridline of lon=0 will be drawn from lat_min to lat_max. @@ -93,8 +94,7 @@ lat_values = np.asarray(lat_levs[:lat_n]/lat_factor) - lon_lines, lat_lines = self._get_raw_grid_lines(inv_transform_xy, - lon_values, + lon_lines, lat_lines = self._get_raw_grid_lines(lon_values, lat_values, lon_min, lon_max, lat_min, lat_max) @@ -132,23 +132,21 @@ return grid_info - def _get_raw_grid_lines(self, inv_transform_xy, + def _get_raw_grid_lines(self, lon_values, lat_values, lon_min, lon_max, lat_min, lat_max): lons_i = np.linspace(lon_min, lon_max, 100) # for interpolation lats_i = np.linspace(lat_min, lat_max, 100) - lon_lines = [inv_transform_xy(np.zeros_like(lats_i)+lon, lats_i) \ + lon_lines = [self.transform_xy(np.zeros_like(lats_i)+lon, lats_i) \ for lon in lon_values] - lat_lines = [inv_transform_xy(lons_i, np.zeros_like(lons_i)+lat) \ + lat_lines = [self.transform_xy(lons_i, np.zeros_like(lons_i)+lat) \ for lat in lat_values] return lon_lines, lat_lines - - def _clip_grid_lines_and_find_ticks(self, lines, values, levs, bb): gi = dict() gi["values"] = [] @@ -174,76 +172,45 @@ return gi - def _update_label_deprecated(self): - pass + def update_transform(self, aux_trans): + if isinstance(aux_trans, Transform): + def transform_xy(x, y): + x, y = np.asarray(x), np.asarray(y) + ll1 = np.concatenate((x[:,np.newaxis], y[:,np.newaxis]), 1) + ll2 = aux_trans.transform(ll1) + lon, lat = ll2[:,0], ll2[:,1] + return lon, lat - def _find_grid_values_deprecated(self, x1, y1, x2, y2, den_x, den_y): - """ - values_lon, values_lat : list of grid values. if integer is given, - rough number of grids in each direction. - """ - nx, ny = den_x * 20, den_y*20 + def inv_transform_xy(x, y): + x, y = np.asarray(x), np.asarray(y) + ll1 = np.concatenate((x[:,np.newaxis], y[:,np.newaxis]), 1) + ll2 = aux_trans.inverted().transform(ll1) + lon, lat = ll2[:,0], ll2[:,1] + return lon, lat - extremes = self.get_extremes(x1, y1, x2, y2, nx, ny) - lon_min, lon_max, lat_min, lat_max = extremes + else: + transform_xy, inv_transform_xy = aux_trans - lon_levs, lon_n, lon_factor = \ - self.grid_locator1(lon_min, lon_max) - lat_levs, lat_n, lat_factor = \ - self.grid_locator2(lat_min, lat_max) + self.transform_xy = transform_xy + self.inv_transform_xy = inv_transform_xy - return lon_levs, lon_n, lon_factor, lat_levs, lat_n, lat_factor + def update(self, **kw): + for k in kw: + if k in ["extreme_finder", + "grid_locator1", + "grid_locator2", + "tick_formatter1", + "tick_formatter2"]: + setattr(self, k, kw[k]) + else: + raise ValueError("unknwonw update property") -class GridFinder(GridFinderBase): - def __init__(self, - transform_xy, inv_transform_xy, - extreme_finder=None, - grid_locator1=None, - grid_locator2=None, - tick_formatter1=None, - tick_formatter2=None): - """ - transform : transfrom from the image coordinate (which will be - the transData of the axes to the world coordinate. - locator1, locator2 : grid locator for 1st and 2nd axis. - """ - if extreme_finder is None: - extreme_finder = ExtremeFinderSimple(20, 20) - if grid_locator1 is None: - grid_locator1 = MaxNLocator() - if grid_locator2 is None: - grid_locator2 = MaxNLocator() - if tick_formatter1 is None: - tick_formatter1 = FormatterPrettyPrint() - if tick_formatter2 is None: - tick_formatter2 = FormatterPrettyPrint() +class GridFinder(GridFinderBase): - super(GridFinder, self).__init__( \ - extreme_finder, - grid_locator1, - grid_locator2, - tick_formatter1, - tick_formatter2) - - self._transform_xy = transform_xy - self._inv_transform_xy = inv_transform_xy - - - def get_grid_info(self, - x1, y1, x2, y2): - - return super(GridFinder,self).get_grid_info( \ - self._inv_transform_xy, self._transform_xy, - x1, y1, x2, y2) - - - -class GridFinderMplTransform(GridFinderBase): - def __init__(self, transform, extreme_finder=None, @@ -254,6 +221,9 @@ """ transform : transfrom from the image coordinate (which will be the transData of the axes to the world coordinate. + + or transfor... [truncated message content] |