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
(1) |
3
(4) |
4
(9) |
5
(14) |
6
(8) |
7
(14) |
8
(1) |
9
(2) |
10
(9) |
11
(5) |
12
(11) |
13
(4) |
14
(4) |
15
(1) |
16
|
17
(1) |
18
(2) |
19
(4) |
20
(10) |
21
(3) |
22
(3) |
23
(2) |
24
(8) |
25
(6) |
26
(5) |
27
|
28
(3) |
29
|
30
(3) |
|
|
|
|
|
|
Revision: 3892 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3892&view=rev Author: mdboom Date: 2007年09月25日 12:53:56 -0700 (2007年9月25日) Log Message: ----------- Important bugfixes. Modified Paths: -------------- branches/transforms/lib/matplotlib/lines.py branches/transforms/lib/matplotlib/path.py branches/transforms/lib/matplotlib/transforms.py Modified: branches/transforms/lib/matplotlib/lines.py =================================================================== --- branches/transforms/lib/matplotlib/lines.py 2007年09月25日 19:08:51 UTC (rev 3891) +++ branches/transforms/lib/matplotlib/lines.py 2007年09月25日 19:53:56 UTC (rev 3892) @@ -499,7 +499,7 @@ lineFunc(renderer, gc, *self._transformed_path.get_path_and_affine()) # MGDTODO: Deal with markers - if self._marker is not None and False: + if self._marker is not None: gc = renderer.new_gc() self._set_gc_clip(gc) gc.set_foreground(self.get_markeredgecolor()) @@ -507,7 +507,7 @@ gc.set_alpha(self._alpha) funcname = self._markers.get(self._marker, '_draw_nothing') markerFunc = getattr(self, funcname) - markerFunc(renderer, gc, self._path) + markerFunc(renderer, gc, *self._transformed_path.get_path_and_affine()) #renderer.close_group('line2d') Modified: branches/transforms/lib/matplotlib/path.py =================================================================== --- branches/transforms/lib/matplotlib/path.py 2007年09月25日 19:08:51 UTC (rev 3891) +++ branches/transforms/lib/matplotlib/path.py 2007年09月25日 19:53:56 UTC (rev 3892) @@ -65,7 +65,10 @@ def __repr__(self): return "Path(%s, %s)" % (self.vertices, self.codes) - + + def __len__(self): + return len(self._vertices) + def _get_codes(self): return self._codes codes = property(_get_codes) @@ -108,7 +111,7 @@ # This initial rotation is to make sure the polygon always # "points-up" theta += npy.pi / 2.0 - verts = npy.concatenate((npy.cos(theta), npy.sin(theta))) + verts = npy.concatenate((npy.cos(theta), npy.sin(theta)), 1) path = Path(verts) cls._unit_regular_polygons[numVertices] = path return path Modified: branches/transforms/lib/matplotlib/transforms.py =================================================================== --- branches/transforms/lib/matplotlib/transforms.py 2007年09月25日 19:08:51 UTC (rev 3891) +++ branches/transforms/lib/matplotlib/transforms.py 2007年09月25日 19:53:56 UTC (rev 3892) @@ -24,7 +24,10 @@ _gid = 0 def __init__(self): - self._parents = WeakKeyDictionary() + # MGDTODO: I'd like to use a WeakKeyDictionary here, but it makes + # these instances uncopyable. As it stands, _parents grows + # unboundedly... Not a good idea. + self._parents = Set() self._children = Set() self._id = TransformNode._gid @@ -34,7 +37,7 @@ if not self._do_invalidation(affine_only): self._id = TransformNode._gid TransformNode._gid += 1 - for parent in self._parents.iterkeys(): + for parent in self._parents: parent.invalidate(affine_only) def _do_invalidation(self, affine_only): @@ -42,7 +45,7 @@ def set_children(self, children): for child in children: - getattr(self, child)._parents[self] = None + getattr(self, child)._parents.add(self) self._children = children def make_graphviz(self, fobj): @@ -1034,8 +1037,8 @@ def composite_transform_factory(a, b): - if isinstance(a, BboxTransform) and isinstance(b, BboxTransform): - return BboxTransform(a._boxin, b._boxout) +# if isinstance(a, BboxTransform) and isinstance(b, BboxTransform): +# return BboxTransform(a._boxin, b._boxout) if isinstance(a, AffineBase) and isinstance(b, AffineBase): return CompositeAffine2D(a, b) return CompositeGenericTransform(a, b) @@ -1162,19 +1165,23 @@ self._path = path self._transform = transform + self.set_children(['_transform']) self._transformed_path = None - self._last_id = transform.get_id() + + def _do_invalidation(self, affine_only): + if not affine_only: + self._transformed_path = None + return True def get_path_and_affine(self): - if (self._transformed_path is None or - self._last_id != self._transform.get_id()): + if self._transformed_path is None: vertices = self._transform.transform_non_affine(self._path.vertices) self._transformed_path = Path(vertices, self._path.codes) + return self._transformed_path, self._transform.get_affine() def get_path(self): - if (self._transformed_path is None or - self._last_id != self._transform.get_id()): + if self._transformed_path is None: vertices = self._tranform.transform_non_affine(self._path.vertices) self._transformed_path = Path(vertices, self._path.codes) vertices = self._transform.transform_affine(self._transformed_path.vertices) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 3891 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3891&view=rev Author: jswhit Date: 2007年09月25日 12:08:51 -0700 (2007年9月25日) Log Message: ----------- clarify satellite height units Modified Paths: -------------- trunk/toolkits/basemap/examples/geos_demo.py Modified: trunk/toolkits/basemap/examples/geos_demo.py =================================================================== --- trunk/toolkits/basemap/examples/geos_demo.py 2007年09月25日 18:29:44 UTC (rev 3890) +++ trunk/toolkits/basemap/examples/geos_demo.py 2007年09月25日 19:08:51 UTC (rev 3891) @@ -2,7 +2,7 @@ from pylab import title, show, arange # create Basemap instance for Geostationary (satellite view) projection. lon_0 = float(raw_input('enter reference longitude (lon_0):')) -h = float(raw_input('enter satellite height above equator (satellite_height):')) +h = float(raw_input('enter satellite height above equator in meters (satellite_height):')) m = Basemap(projection='geos',lon_0=lon_0,satellite_height=h,rsphere=(6378137.00,6356752.3142),) # plot land-sea mask. rgba_land = (0,255,0,255) # land green. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 3890 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3890&view=rev Author: mdboom Date: 2007年09月25日 11:29:44 -0700 (2007年9月25日) Log Message: ----------- Minor speed improvements in new transformations. Modified Paths: -------------- branches/transforms/lib/matplotlib/path.py branches/transforms/lib/matplotlib/text.py branches/transforms/lib/matplotlib/transforms.py Modified: branches/transforms/lib/matplotlib/path.py =================================================================== --- branches/transforms/lib/matplotlib/path.py 2007年09月25日 17:04:51 UTC (rev 3889) +++ branches/transforms/lib/matplotlib/path.py 2007年09月25日 18:29:44 UTC (rev 3890) @@ -41,9 +41,10 @@ assert len(codes) == len(vertices) # The path being passed in may have masked values. However, - # the backends are not expected to deal with masked arrays, so - # we must remove them from the array (using compressed), and - # add MOVETO commands to the codes array accordingly. + # the backends (and any affine transformations in matplotlib + # itself), are not expected to deal with masked arrays, so we + # must remove them from the array (using compressed), and add + # MOVETO commands to the codes array accordingly. mask = ma.getmask(vertices) if mask is not ma.nomask: mask1d = ma.mask_or(mask[:, 0], mask[:, 1]) Modified: branches/transforms/lib/matplotlib/text.py =================================================================== --- branches/transforms/lib/matplotlib/text.py 2007年09月25日 17:04:51 UTC (rev 3889) +++ branches/transforms/lib/matplotlib/text.py 2007年09月25日 18:29:44 UTC (rev 3890) @@ -402,9 +402,7 @@ return (x, y, self._text, self._color, self._verticalalignment, self._horizontalalignment, hash(self._fontproperties), self._rotation, - # MGDTODO: Find a better way to determine if the - # transform as changed - str(self.get_transform()) + self.get_transform().get_id() ) def get_text(self): Modified: branches/transforms/lib/matplotlib/transforms.py =================================================================== --- branches/transforms/lib/matplotlib/transforms.py 2007年09月25日 17:04:51 UTC (rev 3889) +++ branches/transforms/lib/matplotlib/transforms.py 2007年09月25日 18:29:44 UTC (rev 3890) @@ -21,24 +21,28 @@ # relationships class TransformNode(object): + _gid = 0 + def __init__(self): - self._parents = Set() - self._children = [] + self._parents = WeakKeyDictionary() + self._children = Set() + self._id = TransformNode._gid - def invalidate(self, which_child=None, affine_only=[]): - if which_child is None: - which_child = self - self._do_invalidation(which_child, affine_only) - # affine_only = affine_only and (self.is_affine() or self.is_bbox()) - for parent in self._parents: - parent.invalidate(self, affine_only + [self]) + def invalidate(self, affine_only=None): + if affine_only is None: + affine_only = self.is_affine() or self.is_bbox() + if not self._do_invalidation(affine_only): + self._id = TransformNode._gid + TransformNode._gid += 1 + for parent in self._parents.iterkeys(): + parent.invalidate(affine_only) - def _do_invalidation(self, which_child, affine_only): - pass + def _do_invalidation(self, affine_only): + return False def set_children(self, children): for child in children: - getattr(self, child)._parents.add(self) + getattr(self, child)._parents[self] = None self._children = children def make_graphviz(self, fobj): @@ -74,7 +78,10 @@ def is_bbox(self): return False + def get_id(self): + return self._id + class BboxBase(TransformNode): ''' This is the read-only part of a bounding-box @@ -214,6 +221,7 @@ def __init__(self, points): BboxBase.__init__(self) self._points = npy.asarray(points, npy.float_) + self._invalid = False #@staticmethod def unit(): @@ -235,6 +243,11 @@ return 'Bbox(%s)' % repr(self._points) __str__ = __repr__ + def _do_invalidation(self, affine_only): + result = self._invalid + self._invalid = True + return result + def update_from_data(self, x, y, ignore=True): if ignore: self._points = npy.array( @@ -294,6 +307,7 @@ bounds = property(BboxBase._get_bounds, _set_bounds) def get_points(self): + self._invalid = False return self._points def set_points(self, points): @@ -348,21 +362,23 @@ assert transform.output_dims == 2 BboxBase.__init__(self) - self.bbox = bbox - self.transform = transform - self.set_children(['bbox', 'transform']) + self._bbox = bbox + self._transform = transform + self.set_children(['_bbox', '_transform']) self._points = None def __repr__(self): - return "TransformedBbox(%s, %s)" % (self.bbox, self.transform) + return "TransformedBbox(%s, %s)" % (self._bbox, self._transform) __str__ = __repr__ - def _do_invalidation(self, which_child, affine_only): + def _do_invalidation(self, affine_only): + result = self._points is None self._points = None + return result def get_points(self): if self._points is None: - self._points = self.transform.transform(self.bbox.get_points()) + self._points = self._transform.transform(self._bbox.get_points()) return self._points @@ -461,9 +477,6 @@ def __array__(self, *args, **kwargs): return self.get_matrix() - def _do_invalidation(self, which_child, affine_only): - self._inverted = None - #@staticmethod def _concat(a, b): return npy.dot(b, a) @@ -477,9 +490,6 @@ def get_matrix(self): raise NotImplementedError() - def transform_affine(self, points): - return self.transform(points) - def transform_non_affine(self, points): return points @@ -528,9 +538,11 @@ # print "".join(traceback.format_stack()) # print points mtx = self.get_matrix() - points = ma.asarray(values, npy.float_) + points = npy.asarray(values, npy.float_) return points * mtx[0,0] + mtx[0,1] + transform_affine = transform + def inverted(self): if self._inverted is None: mtx = self.get_matrix() @@ -575,7 +587,7 @@ def set_matrix(self, mtx): self._mtx = mtx self.invalidate() - + def set(self, other): self._mtx = other.get_matrix() self.invalidate() @@ -620,9 +632,11 @@ return "IntervalTransform(%s)" % (getattr(self._bbox, self._direction)) __str__ = __repr__ - def _do_invalidation(self, which_child, affine_only): + def _do_invalidation(self, affine_only): + result = self._mtx is None self._mtx = None - Affine1DBase._do_invalidation(self, which_child, affine_only) + self._inverted = None + return result def get_matrix(self): if self._mtx is None: @@ -678,12 +692,14 @@ # print "".join(traceback.format_stack()) # print points mtx = self.get_matrix() - points = ma.asarray(points, npy.float_) + points = npy.asarray(points, npy.float_) points = points.transpose() - points = ma.dot(mtx[0:2, 0:2], points) + points = npy.dot(mtx[0:2, 0:2], points) points = points + mtx[0:2, 2:] return points.transpose() + transform_affine = transform + def inverted(self): if self._inverted is None: mtx = self.get_matrix() @@ -801,19 +817,12 @@ def transform(self, points): return points + transform_affine = transform_non_affine = transform - def transform_affine(self, points): - return points - - def transform_non_affine(self, points): - return points - def get_affine(self): return self + inverted = get_affine - def inverted(self): - return self - class BlendedGenericTransform(Transform): input_dims = 2 @@ -857,14 +866,12 @@ y_points = y.transform(points[:, 1]) y_points = y_points.reshape((len(y_points), 1)) - return ma.concatenate((x_points, y_points), 1) - + return npy.concatenate((x_points, y_points), 1) + transform_non_affine = transform + def transform_affine(self, points): return points - def transform_non_affine(self, points): - return self.transform(points) - def get_affine(self): return IdentityTransform() @@ -892,9 +899,10 @@ return "BlendedAffine1D(%s,%s)" % (self._x, self._y) __str__ = __repr__ - def _do_invalidation(self, which_child, affine_only): + def _do_invalidation(self, affine_only): + result = self._mtx is None self._mtx = None - Affine2DBase._do_invalidation(self, which_child, affine_only) + self._inverted = None def get_matrix(self): if self._mtx is None: @@ -928,9 +936,11 @@ return "BlendedAffine2D(%s,%s)" % (self._x, self._y) __str__ = __repr__ - def _do_invalidation(self, which_child, affine_only): + def _do_invalidation(self, affine_only): + result = self._mtx is None self._mtx = None - Affine2DBase._do_invalidation(self, which_child, affine_only) + self._inverted = None + return result def get_matrix(self): if self._mtx is None: @@ -985,7 +995,7 @@ return self._b.transform_non_affine(self._a.transform_non_affine(points)) def get_affine(self): - return self._a.get_affine() + self._b.get_affine() + return CompositeAffine2D(self._a.get_affine(), self._b.get_affine()) def inverted(self): return CompositeGenericTransform(self._b.inverted(), self._a.inverted()) @@ -1009,9 +1019,11 @@ return "CompositeAffine2D(%s, %s)" % (self._a, self._b) __str__ = __repr__ - def _do_invalidation(self, which_child, affine_only): + def _do_invalidation(self, affine_only): + result = self._mtx is None self._mtx = None - Affine2DBase._do_invalidation(self, which_child, affine_only) + self._inverted = None + return result def get_matrix(self): if self._mtx is None: @@ -1117,10 +1129,12 @@ return "BboxTransform(%s, %s)" % (self._boxin, self._boxout) __str__ = __repr__ - def _do_invalidation(self, which_child, affine_only): + def _do_invalidation(self, affine_only): + result = self._mtx is None self._mtx = None - Affine2DBase._do_invalidation(self, which_child, affine_only) - + self._inverted = None + return result + def is_separable(self): return True @@ -1148,21 +1162,19 @@ self._path = path self._transform = transform - self.set_children(['_transform']) self._transformed_path = None + self._last_id = transform.get_id() - def _do_invalidation(self, which_child, affine_only): - if not (affine_only[0].is_affine() or affine_only[0].is_bbox()): - self._transformed_path = None - def get_path_and_affine(self): - if self._transformed_path is None: + if (self._transformed_path is None or + self._last_id != self._transform.get_id()): vertices = self._transform.transform_non_affine(self._path.vertices) self._transformed_path = Path(vertices, self._path.codes) return self._transformed_path, self._transform.get_affine() def get_path(self): - if self._transformed_path is None: + if (self._transformed_path is None or + self._last_id != self._transform.get_id()): vertices = self._tranform.transform_non_affine(self._path.vertices) self._transformed_path = Path(vertices, self._path.codes) vertices = self._transform.transform_affine(self._transformed_path.vertices) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 3889 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3889&view=rev Author: mdboom Date: 2007年09月25日 10:04:51 -0700 (2007年9月25日) Log Message: ----------- Automaticall separate affine from non-affine transforms Modified Paths: -------------- branches/transforms/lib/matplotlib/axes.py branches/transforms/lib/matplotlib/axis.py branches/transforms/lib/matplotlib/backends/backend_agg.py branches/transforms/lib/matplotlib/lines.py branches/transforms/lib/matplotlib/path.py branches/transforms/lib/matplotlib/scale.py branches/transforms/lib/matplotlib/ticker.py branches/transforms/lib/matplotlib/transforms.py Modified: branches/transforms/lib/matplotlib/axes.py =================================================================== --- branches/transforms/lib/matplotlib/axes.py 2007年09月25日 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/axes.py 2007年09月25日 17:04:51 UTC (rev 3889) @@ -545,7 +545,7 @@ "move this out of __init__ because non-separable axes don't use it" self.xaxis = maxis.XAxis(self) self.yaxis = maxis.YAxis(self) - self._update_transAxisXY() + self._update_transScale() def sharex_foreign(self, axforeign): """ @@ -631,12 +631,28 @@ self.viewLim = mtransforms.Bbox.unit() self.transAxes = mtransforms.BboxTransform( mtransforms.Bbox.unit(), self.bbox) - self.transAxisXY = mtransforms.TransformWrapper() - self.transData = self.transAxisXY + self.transAxes - def _update_transAxisXY(self): - self.transAxisXY.set(mtransforms.blended_transform_factory( + # Transforms the x and y axis separately by a scale factor + # It is assumed that this part will have non-linear components + self.transScale = mtransforms.TransformWrapper(mtransforms.IdentityTransform()) + + # A (possibly non-linear) projection on the (already scaled) data + self.transProjection = mtransforms.IdentityTransform() + + # An affine transformation on the data, generally to limit the + # range of the axes + self.transLimits = mtransforms.BboxTransform( + mtransforms.TransformedBbox(self.viewLim, self.transScale), mtransforms.Bbox.unit()) + + self.transData = self.transScale + self.transProjection + self.transLimits + self.transAxes + + + def _update_transScale(self): + self.transScale.set( + mtransforms.blended_transform_factory( self.xaxis.get_transform(), self.yaxis.get_transform())) + + self.transData.make_graphviz(open("trans.dot", "w")) def get_position(self, original=False): 'Return the axes rectangle left, bottom, width, height' @@ -1537,7 +1553,7 @@ ACCEPTS: ['log' | 'linear' ] """ self.xaxis.set_scale(value, **kwargs) - self._update_transAxisXY() + self._update_transScale() def get_xticks(self): 'Return the x ticks as a list of locations' @@ -1647,7 +1663,7 @@ ACCEPTS: ['log' | 'linear'] """ self.yaxis.set_scale(value, basey, subsy) - self._update_transAxisXY() + self._update_transScale() def get_yticks(self): 'Return the y ticks as a list of locations' Modified: branches/transforms/lib/matplotlib/axis.py =================================================================== --- branches/transforms/lib/matplotlib/axis.py 2007年09月25日 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/axis.py 2007年09月25日 17:04:51 UTC (rev 3889) @@ -508,16 +508,15 @@ self.majorTicks = [] self.minorTicks = [] self.pickradius = pickradius - self._transform = LinearScale(self.axes.viewLim, self.axis).get_transform() - self._scale = 'linear' + self._scale = LinearScale() self.cla() def get_transform(self): - return self._transform - + return self._scale.get_transform() + def get_scale(self): - return self._scale + return self._scale.name def set_scale(self, value, base=10, subs=None): # MGDTODO: Move these settings (ticker etc.) into the scale class itself @@ -528,17 +527,16 @@ self.set_major_formatter(ScalarFormatter()) self.set_minor_locator(NullLocator()) self.set_minor_formatter(NullFormatter()) - self._transform = LinearScale(self.axes.viewLim, self.axis).get_transform() + self._scale = LinearScale() elif value == 'log': self.set_major_locator(LogLocator(base)) self.set_major_formatter(LogFormatterMathtext(base)) self.set_minor_locator(LogLocator(base,subs)) # MGDTODO: Pass base along - self._transform = LogScale(self.axes.viewLim, self.axis).get_transform() + self._scale = LogScale() miny, maxy = getattr(self.axes.viewLim, 'interval' + self.axis) if min(miny, maxy)<=0: self.axes.autoscale_view() - self._scale = value def get_children(self): children = [self.label] Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py =================================================================== --- branches/transforms/lib/matplotlib/backends/backend_agg.py 2007年09月25日 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/backends/backend_agg.py 2007年09月25日 17:04:51 UTC (rev 3889) @@ -132,14 +132,14 @@ # MGDTODO: This is a hack for now to allow for arbitrary transformations def draw_path(self, gc, path, trans, rgbFace=None): - new_path, affine = path.transformed_without_affine(trans) - self._renderer.draw_path(gc, new_path, affine, rgbFace) + assert trans.is_affine() + self._renderer.draw_path(gc, path, trans, rgbFace) # MGDTODO: This is a hack for now to allow for arbitrary transformations def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None): assert marker_trans.is_affine() - new_path, affine = path.transformed_without_affine(trans) - self._renderer.draw_markers(gc, marker_path, marker_trans, new_path, affine, rgbFace) + assert trans.is_affine() + self._renderer.draw_markers(gc, marker_path, marker_trans, path, trans, rgbFace) def draw_mathtext(self, gc, x, y, s, prop, angle): """ Modified: branches/transforms/lib/matplotlib/lines.py =================================================================== --- branches/transforms/lib/matplotlib/lines.py 2007年09月25日 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/lines.py 2007年09月25日 17:04:51 UTC (rev 3889) @@ -17,7 +17,7 @@ from cbook import iterable, is_string_like, is_numlike from colors import colorConverter from path import Path -from transforms import Affine2D, Bbox +from transforms import Affine2D, Bbox, TransformedPath from matplotlib import rcParams @@ -416,8 +416,18 @@ self._logcache = None # Masked arrays are now handled by the Path class itself self._path = Path(self._xy, closed=False) + self._transformed_path = TransformedPath(self._path, self.get_transform()) # MGDTODO: If _draw_steps is removed, remove the following line also self._step_path = None + + def set_transform(self, t): + """ + set the Transformation instance used by this artist + + ACCEPTS: a matplotlib.transform transformation instance + """ + Artist.set_transform(self, t) + self._transformed_path = TransformedPath(self._path, self.get_transform()) def _is_sorted(self, x): "return true if x is sorted" @@ -486,10 +496,10 @@ funcname = self._lineStyles.get(self._linestyle, '_draw_nothing') lineFunc = getattr(self, funcname) - lineFunc(renderer, gc, self._path) + lineFunc(renderer, gc, *self._transformed_path.get_path_and_affine()) # MGDTODO: Deal with markers - if self._marker is not None: + if self._marker is not None and False: gc = renderer.new_gc() self._set_gc_clip(gc) gc.set_foreground(self.get_markeredgecolor()) @@ -678,7 +688,7 @@ self.set_linestyle('--') self._dashSeq = seq # TODO: offset ignored for now - def _draw_nothing(self, renderer, gc, path): + def _draw_nothing(self, *args, **kwargs): pass @@ -704,191 +714,191 @@ renderer.draw_path(gc, self._step_path, self.get_transform()) - def _draw_solid(self, renderer, gc, path): + def _draw_solid(self, renderer, gc, path, trans): gc.set_linestyle('solid') - renderer.draw_path(gc, path, self.get_transform()) + renderer.draw_path(gc, path, trans) - def _draw_dashed(self, renderer, gc, path): + def _draw_dashed(self, renderer, gc, path, trans): gc.set_linestyle('dashed') if self._dashSeq is not None: gc.set_dashes(0, self._dashSeq) - renderer.draw_path(gc, path, self.get_transform()) + renderer.draw_path(gc, path, trans) - def _draw_dash_dot(self, renderer, gc, path): + def _draw_dash_dot(self, renderer, gc, path, trans): gc.set_linestyle('dashdot') - renderer.draw_path(gc, path, self.get_transform()) + renderer.draw_path(gc, path, trans) - def _draw_dotted(self, renderer, gc, path): + def _draw_dotted(self, renderer, gc, path, trans): gc.set_linestyle('dotted') - renderer.draw_path(gc, path, self.get_transform()) + renderer.draw_path(gc, path, trans) - def _draw_point(self, renderer, gc, path): + def _draw_point(self, renderer, gc, path, path_trans): w = renderer.points_to_pixels(self._markersize) * \ self._point_size_reduction * 0.5 rgbFace = self._get_rgb_face() transform = Affine2D().scale(w) renderer.draw_markers( - gc, Path.unit_circle(), transform, path, self.get_transform(), + gc, Path.unit_circle(), transform, path, path_trans, rgbFace) - def _draw_pixel(self, renderer, gc, path): + def _draw_pixel(self, renderer, gc, path, path_trans): rgbFace = self._get_rgb_face() transform = Affine2D().translate(-0.5, -0.5) renderer.draw_markers(gc, Path.unit_rectangle, transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_circle(self, renderer, gc, path): + def _draw_circle(self, renderer, gc, path, path_trans): w = renderer.points_to_pixels(self._markersize) * 0.5 rgbFace = self._get_rgb_face() transform = Affine2D().scale(w, w) renderer.draw_markers( - gc, Path.unit_circle(), transform, path, self.get_transform(), + gc, Path.unit_circle(), transform, path, path_trans, rgbFace) _triangle_path = Path([[0.0, 1.0], [-1.0, -1.0], [1.0, -1.0]]) - def _draw_triangle_up(self, renderer, gc, path): + def _draw_triangle_up(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset, offset) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, self._triangle_path, transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_triangle_down(self, renderer, gc, path): + def _draw_triangle_down(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset, -offset) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, self._triangle_path, transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_triangle_left(self, renderer, gc, path): + def _draw_triangle_left(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset, offset).rotate_deg(90) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, self._triangle_path, transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_triangle_right(self, renderer, gc, path): + def _draw_triangle_right(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset, offset).rotate_deg(-90) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, self._triangle_path, transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_square(self, renderer, gc, path): + def _draw_square(self, renderer, gc, path, path_trans): side = renderer.points_to_pixels(self._markersize) transform = Affine2D().translate(-0.5, -0.5).scale(side) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, Path.unit_rectangle(), transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_diamond(self, renderer, gc, path): + def _draw_diamond(self, renderer, gc, path, path_trans): side = renderer.points_to_pixels(self._markersize) transform = Affine2D().translate(0.5, 0.5).rotate_deg(45).scale(side) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, Path.unit_rectangle(), transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_thin_diamond(self, renderer, gc, path): + def _draw_thin_diamond(self, renderer, gc, path, path_trans): offset = renderer.points_to_pixels(self._markersize) transform = Affine2D().translate(0.5, 0.5) \ .rotate_deg(45).scale(offset * 0.8, offset) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, Path.unit_rectangle(), transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_pentagon(self, renderer, gc, path): + def _draw_pentagon(self, renderer, gc, path, path_trans): offset = 0.5 * renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, Path.unit_regular_polygon(5), transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_hexagon1(self, renderer, gc, path): + def _draw_hexagon1(self, renderer, gc, path, path_trans): offset = 0.5 * renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, Path.unit_regular_polygon(6), transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_hexagon2(self, renderer, gc, path): + def _draw_hexagon2(self, renderer, gc, path, path_trans): offset = 0.5 * renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(30) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, Path.unit_regular_polygon(6), transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) _line_marker_path = Path([[0.0, -1.0], [0.0, 1.0]], closed=False) - def _draw_vline(self, renderer, gc, path): + def _draw_vline(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) renderer.draw_markers(gc, self._line_marker_path, transform, - path, self.get_transform()) + path, path_trans) - def _draw_hline(self, renderer, gc, path): + def _draw_hline(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(90) renderer.draw_markers(gc, self._line_marker_path, transform, - path, self.get_transform()) + path, path_trans) _tickhoriz_path = Path([[0.0, 0.5], [1.0, 0.5]], closed=False) - def _draw_tickleft(self, renderer, gc, path): + def _draw_tickleft(self, renderer, gc, path, path_trans): offset = renderer.points_to_pixels(self._markersize) marker_transform = Affine2D().scale(-offset, 1.0) renderer.draw_markers(gc, self._tickhoriz_path, marker_transform, - path, self.get_transform()) + path, path_trans) - def _draw_tickright(self, renderer, gc, path): + def _draw_tickright(self, renderer, gc, path, path_trans): offset = renderer.points_to_pixels(self._markersize) marker_transform = Affine2D().scale(offset, 1.0) renderer.draw_markers(gc, self._tickhoriz_path, marker_transform, - path, self.get_transform()) + path, path_trans) _tickvert_path = Path([[-0.5, 0.0], [-0.5, 1.0]], closed=False) - def _draw_tickup(self, renderer, gc, path): + def _draw_tickup(self, renderer, gc, path, path_trans): offset = renderer.points_to_pixels(self._markersize) marker_transform = Affine2D().scale(1.0, offset) renderer.draw_markers(gc, self._tickvert_path, marker_transform, - path, self.get_transform()) + path, path_trans) - def _draw_tickdown(self, renderer, gc, path): + def _draw_tickdown(self, renderer, gc, path, path_trans): offset = renderer.points_to_pixels(self._markersize) marker_transform = Affine2D().scale(1.0, -offset) renderer.draw_markers(gc, self._tickvert_path, marker_transform, - path, self.get_transform()) + path, path_trans) _plus_path = Path([[-1.0, 0.0], [1.0, 0.0], [0.0, -1.0], [0.0, 1.0]], [Path.MOVETO, Path.LINETO, Path.MOVETO, Path.LINETO]) - def _draw_plus(self, renderer, gc, path): + def _draw_plus(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) renderer.draw_markers(gc, self._plus_path, transform, - path, self.get_transform()) + path, path_trans) _tri_path = Path([[0.0, 0.0], [0.0, -1.0], @@ -897,61 +907,61 @@ [Path.MOVETO, Path.LINETO, Path.MOVETO, Path.LINETO, Path.MOVETO, Path.LINETO]) - def _draw_tri_down(self, renderer, gc, path): + def _draw_tri_down(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) renderer.draw_markers(gc, self._tri_path, transform, - path, self.get_transform()) + path, path_trans) - def _draw_tri_up(self, renderer, gc, path): + def _draw_tri_up(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(180) renderer.draw_markers(gc, self._tri_path, transform, - path, self.get_transform()) + path, path_trans) - def _draw_tri_left(self, renderer, gc, path): + def _draw_tri_left(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(90) renderer.draw_markers(gc, self._tri_path, transform, - path, self.get_transform()) + path, path_trans) - def _draw_tri_right(self, renderer, gc, path): + def _draw_tri_right(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(270) renderer.draw_markers(gc, self._tri_path, transform, - path, self.get_transform()) + path, path_trans) _caret_path = Path([[-1.0, 1.5], [0.0, 0.0], [1.0, 1.5]], closed=False) - def _draw_caretdown(self, renderer, gc, path): + def _draw_caretdown(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) renderer.draw_markers(gc, self._caret_path, transform, - path, self.get_transform()) + path, path_trans) - def _draw_caretup(self, renderer, gc, path): + def _draw_caretup(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(180) renderer.draw_markers(gc, self._caret_path, transform, - path, self.get_transform()) + path, path_trans) - def _draw_caretleft(self, renderer, gc, path): + def _draw_caretleft(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(90) renderer.draw_markers(gc, self._caret_path, transform, - path, self.get_transform()) + path, path_trans) - def _draw_caretright(self, renderer, gc, path): + def _draw_caretright(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(270) renderer.draw_markers(gc, self._caret_path, transform, - path, self.get_transform()) + path, path_trans) _x_path = Path([[-1.0, -1.0], [1.0, 1.0], @@ -962,7 +972,7 @@ offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) renderer.draw_markers(gc, self._x_path, transform, - path, self.get_transform()) + path, path_trans) def update_from(self, other): Modified: branches/transforms/lib/matplotlib/path.py =================================================================== --- branches/transforms/lib/matplotlib/path.py 2007年09月25日 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/path.py 2007年09月25日 17:04:51 UTC (rev 3889) @@ -88,10 +88,6 @@ def transformed(self, transform): return Path(transform.transform(self.vertices), self.codes) - - def transformed_without_affine(self, transform): - vertices, affine = transform.transform_without_affine(self.vertices) - return Path(vertices, self.codes), affine _unit_rectangle = None #@classmethod @@ -152,6 +148,3 @@ cls._unit_circle = Path(vertices, codes) return cls._unit_circle unit_circle = classmethod(unit_circle) - -# MGDTODO: Add a transformed path that would automatically invalidate -# itself when its transform changes Modified: branches/transforms/lib/matplotlib/scale.py =================================================================== --- branches/transforms/lib/matplotlib/scale.py 2007年09月25日 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/scale.py 2007年09月25日 17:04:51 UTC (rev 3889) @@ -1,66 +1,54 @@ import numpy as npy from numpy import ma +from numpy.linalg import inv -from transforms import Affine1D, IntervalTransform, Transform +from transforms import Affine1DBase, IntervalTransform, Transform, \ + composite_transform_factory, IdentityTransform class ScaleBase(object): pass class LinearScale(ScaleBase): - def __init__(self, viewLim, direction): - direction = 'interval' + direction - self._transform = IntervalTransform(viewLim, direction) - def get_transform(self): - return self._transform + return IdentityTransform() class LogScale(ScaleBase): class LogTransform(Transform): input_dims = 1 output_dims = 1 - def __init__(self, viewLim, direction, base): + def __init__(self, base): Transform.__init__(self) self._base = base - self._viewLim = viewLim - self._direction = direction - self.set_children(['_viewLim']) + def is_separable(self): + return True + def transform(self, a): - a, affine = self.transform_without_affine(a) - return affine.transform(a) + if len(a) > 10: + print "Log Transforming..." + return ma.log10(ma.masked_where(a <= 0.0, a * 10.0)) - def transform_without_affine(self, a): - # MGDTODO: Support different bases - base = self._base - marray = ma.masked_where(a <= 0.0, a * 10.0) - marray = npy.log10(marray) - minimum, maximum = npy.log10(getattr(self._viewLim, self._direction) * 10.0) - return marray, Affine1D.from_values(maximum - minimum, minimum).inverted() - def inverted(self): - return LogScale.InvertedLogTransform(self._viewLim, self._direction, self._base) + return LogScale.InvertedLogTransform(self._base) class InvertedLogTransform(Transform): input_dims = 1 output_dims = 1 - def __init__(self, viewLim, direction, base): + def __init__(self, base): Transform.__init__(self) self._base = base - self._viewLim = viewLim - self._direction = direction - self.set_children(['_viewLim']) + + def is_separable(self): + return True def transform(self, a): - minimum, maximum = npy.log10(getattr(self._viewLim, self._direction) * 10.0) - a = Affine1D.from_values(maximum - minimum, minimum).transform(a) return ma.power(10.0, a) / 10.0 def inverted(self): - return LogScale.LogTransform(self._viewLim, self._direction, self._base) + return LogScale.LogTransform(self._base) - def __init__(self, viewLim, direction, base=10): - direction = 'interval' + direction - self._transform = self.LogTransform(viewLim, direction, base) + def __init__(self, base=10): + self._transform = self.LogTransform(base) def get_transform(self): return self._transform Modified: branches/transforms/lib/matplotlib/ticker.py =================================================================== --- branches/transforms/lib/matplotlib/ticker.py 2007年09月25日 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/ticker.py 2007年09月25日 17:04:51 UTC (rev 3889) @@ -937,9 +937,7 @@ if vmin==vmax: vmin = decade_down(vmin,self._base) vmax = decade_up(vmax,self._base) - print vmin, vmax result = mtransforms.nonsingular(vmin, vmax) - print result return result class AutoLocator(MaxNLocator): Modified: branches/transforms/lib/matplotlib/transforms.py =================================================================== --- branches/transforms/lib/matplotlib/transforms.py 2007年09月25日 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/transforms.py 2007年09月25日 17:04:51 UTC (rev 3889) @@ -8,7 +8,10 @@ from numpy import ma as ma from numpy.linalg import inv from sets import Set +from weakref import WeakKeyDictionary +from path import Path + DEBUG = False # MGDTODO: This creates a ton of cyclical references. We may want to @@ -22,45 +25,54 @@ self._parents = Set() self._children = [] - def invalidate(self): - self._do_invalidation() + def invalidate(self, which_child=None, affine_only=[]): + if which_child is None: + which_child = self + self._do_invalidation(which_child, affine_only) + # affine_only = affine_only and (self.is_affine() or self.is_bbox()) for parent in self._parents: - parent.invalidate() + parent.invalidate(self, affine_only + [self]) - def _do_invalidation(self): - return False - + def _do_invalidation(self, which_child, affine_only): + pass + def set_children(self, children): for child in children: getattr(self, child)._parents.add(self) self._children = children def make_graphviz(self, fobj): + seen = Set() + def recurse(root): + if root in seen: + return + seen.add(root) fobj.write('%s [label="%s"];\n' % (hash(root), root.__class__.__name__)) - if isinstance(root, Affine2DBase): + if root.is_affine(): fobj.write('%s [style=filled, color=".7 .7 .9"];\n' % hash(root)) - elif isinstance(root, BboxBase): + elif root.is_bbox(): fobj.write('%s [style=filled, color=".9 .9 .7"];\n' % hash(root)) for child_name in root._children: child = getattr(root, child_name) - fobj.write("%s -> %s;\n" % ( + fobj.write('%s -> %s [label="%s"];\n' % ( hash(root), - hash(child))) + hash(child), + child_name)) recurse(child) - + fobj.write("digraph G {\n") recurse(self) fobj.write("}\n") def is_affine(self): - return isinstance(self, Affine2DBase) + return False def is_bbox(self): - return isinstance(self, BboxBase) + return False class BboxBase(TransformNode): @@ -70,7 +82,10 @@ def __init__(self): TransformNode.__init__(self) - + + def is_bbox(self): + return True + def __array__(self): return self.get_points() @@ -125,63 +140,81 @@ height = property(_get_height) def _get_bounds(self): - return (self.xmin, self.ymin, - self.xmax - self.xmin, self.ymax - self.ymin) + ((xmin, ymin), (xmax, ymax)) = self.get_points() + return (xmin, ymin, xmax - xmin, ymax - ymin) bounds = property(_get_bounds) + def _get_lbrt(self): + return self.get_points().flatten().copy() + lbrt = property(_get_lbrt) + def get_points(self): return NotImplementedError() - + # MGDTODO: Optimize def containsx(self, x): - return x >= self.xmin and x <= self.xmax + xmin, xmax = self.intervalx + return x >= xmin and x <= xmax def containsy(self, y): - return y >= self.ymin and y <= self.ymax + ymin, ymax = self.intervaly + return y >= ymin and y <= ymax def contains(self, x, y): return self.containsx(x) and self.containsy(y) def overlapsx(self, other): - return self.containsx(other.xmin) \ - or self.containsx(other.xmax) + xmin, xmax = other.intervalx + return self.containsx(xmin) \ + or self.containsx(xmax) def overlapsy(self, other): - return self.containsy(other.ymin) \ - or self.containsx(other.ymax) + ymin, ymax = other.intervaly + return self.containsy(ymin) \ + or self.containsx(ymax) def overlaps(self, other): return self.overlapsx(other) \ and self.overlapsy(other) def fully_containsx(self, x): - return x > self.xmin and x < self.xmax + xmin, xmax = self.intervalx + return x > xmin and x < xmax def fully_containsy(self, y): - return y > self.ymin and y < self.ymax + ymin, ymax = self.intervaly + return y > ymin and y < ymax def fully_contains(self, x, y): return self.fully_containsx(x) \ and self.fully_containsy(y) def fully_overlapsx(self, other): - return self.fully_containsx(other.xmin) \ - or self.fully_containsx(other.xmax) + xmin, xmax = other.intervalx + return self.fully_containsx(xmin) \ + or self.fully_containsx(xmax) def fully_overlapsy(self, other): - return self.fully_containsy(other.ymin) \ - or self.fully_containsx(other.ymax) + ymin, ymax = other.intervaly + return self.fully_containsy(ymin) \ + or self.fully_containsx(ymax) def fully_overlaps(self, other): return self.fully_overlapsx(other) and \ self.fully_overlapsy(other) + def transformed(self, transform): + return Bbox(transform.transform(self.get_points())) + + def inverse_transformed(self, transform): + return Bbox(transform.inverted().transform(self.get_points())) + class Bbox(BboxBase): def __init__(self, points): BboxBase.__init__(self) self._points = npy.asarray(points, npy.float_) - + #@staticmethod def unit(): return Bbox.from_lbrt(0., 0., 1., 1.) @@ -198,12 +231,6 @@ return Bbox(points) from_lbrt = staticmethod(from_lbrt) - def __cmp__(self, other): - # MGDTODO: Totally suboptimal - if isinstance(other, Bbox) and (self._points == other._points).all(): - return 0 - return -1 - def __repr__(self): return 'Bbox(%s)' % repr(self._points) __str__ = __repr__ @@ -219,8 +246,7 @@ [max(x.max(), self.xmax), max(y.max(), self.ymax)]], npy.float_) self.invalidate() - - # MGDTODO: Probably a more efficient ways to do this... + def _set_xmin(self, val): self._points[0, 0] = val self.invalidate() @@ -278,12 +304,6 @@ self._points = other.get_points() self.invalidate() - def transformed(self, transform): - return Bbox(transform.transform(self._points)) - - def inverse_transformed(self, transform): - return Bbox(transform.inverted().transform(self._points)) - def expanded(self, sw, sh): width = self.width height = self.height @@ -324,6 +344,8 @@ def __init__(self, bbox, transform): assert bbox.is_bbox() assert isinstance(transform, Transform) + assert transform.input_dims == 2 + assert transform.output_dims == 2 BboxBase.__init__(self) self.bbox = bbox @@ -335,7 +357,7 @@ return "TransformedBbox(%s, %s)" % (self.bbox, self.transform) __str__ = __repr__ - def _do_invalidation(self): + def _do_invalidation(self, which_child, affine_only): self._points = None def get_points(self): @@ -347,13 +369,10 @@ class Transform(TransformNode): def __init__(self): TransformNode.__init__(self) - - def transform(self, points): - raise NotImplementedError() - def transform_without_affine(self, points): - return self.transform(points), IDENTITY - + def is_separable(self): + return False + def __add__(self, other): if isinstance(other, Transform): return composite_transform_factory(self, other) @@ -366,39 +385,69 @@ raise TypeError( "Can not add Transform to object of type '%s'" % type(other)) + def transform(self, points): + raise NotImplementedError + + def transform_affine(self, points): + raise NotImplementedError + + def transform_non_affine(self, points): + raise NotImplementedError + + def get_affine(self): + raise NotImplementedError + def transform_point(self, point): return self.transform(npy.asarray([point]))[0] - + def has_inverse(self): raise NotImplementedError() def inverted(self): raise NotImplementedError() - def is_separable(self): - return False +class TransformWrapper(Transform): + def __init__(self, child): + assert isinstance(child, Transform) + + Transform.__init__(self) + self.input_dims = child.input_dims + self.output_dims = child.output_dims + self._child = child + self.set_children(['_child']) -class TransformWrapper(Transform): - input_dims = 2 - output_dims = 2 - + def __repr__(self): + return "TransformWrapper(%r)" % self._child + __str__ = __repr__ + def set(self, child): - self.child = child - self.child._parents.add(self) + assert child.input_dims == self.input_dims + assert child.output_dims == self.output_dims + self._child = child + self.set_children(['_child']) self.invalidate() + + def is_separable(self): + return self._child.is_separable() + def is_affine(self): + return self._child.is_affine() + def transform(self, points): - return self.child.transform(points) + return self._child.transform(points) - def transform_without_affine(points): - return self.child.transform_without_affine(points) + def transform_affine(self, points): + return self._child.transform_affine(points) + + def transform_non_affine(self, points): + return self._child.transform_non_affine(points) + + def get_affine(self): + return self._child.get_affine() def inverted(self): - return self.child.inverted() - - def is_separable(self): - return self.child.is_separable() + return self._child.inverted() class AffineBase(Transform): @@ -406,10 +455,13 @@ Transform.__init__(self) self._inverted = None + def is_affine(self): + return True + def __array__(self, *args, **kwargs): return self.get_matrix() - def _do_invalidation(self): + def _do_invalidation(self, which_child, affine_only): self._inverted = None #@staticmethod @@ -425,10 +477,14 @@ def get_matrix(self): raise NotImplementedError() - def transform_without_affine(self, points): - # MGDTODO: Should we copy the points here? I'd like to avoid it, - # if possible - return points, self + def transform_affine(self, points): + return self.transform(points) + + def transform_non_affine(self, points): + return points + + def get_affine(self): + return self class Affine1DBase(AffineBase): @@ -437,13 +493,16 @@ def __init__(self): AffineBase.__init__(self) - + + def is_separable(self): + return True + def __array__(self, *args, **kwargs): return self.get_matrix() - + def to_values(self): mtx = self.get_matrix() - return tuple(mtx[0]) + return mtx[0] #@staticmethod def matrix_from_values(a, b): @@ -472,9 +531,6 @@ points = ma.asarray(values, npy.float_) return points * mtx[0,0] + mtx[0,1] - def is_separable(self): - return True - def inverted(self): if self._inverted is None: mtx = self.get_matrix() @@ -551,9 +607,12 @@ class IntervalTransform(Affine1DBase): def __init__(self, bbox, direction): + assert direction in ('x', 'y') + assert bbox.is_bbox() + Affine1DBase.__init__(self) self._bbox = bbox - self._direction = direction + self._direction = "interval" + direction self.set_children(['_bbox']) self._mtx = None @@ -561,10 +620,9 @@ return "IntervalTransform(%s)" % (getattr(self._bbox, self._direction)) __str__ = __repr__ - def _do_invalidation(self): - print "IntervalTransform.invalidation", self._bbox + def _do_invalidation(self, which_child, affine_only): self._mtx = None - Affine1DBase._do_invalidation(self) + Affine1DBase._do_invalidation(self, which_child, affine_only) def get_matrix(self): if self._mtx is None: @@ -581,6 +639,10 @@ def __init__(self): AffineBase.__init__(self) + def is_separable(self): + mtx = self.get_matrix() + return mtx[0, 1] == 0.0 and mtx[1, 0] == 0.0 + def __array__(self, *args, **kwargs): return self.get_matrix() @@ -627,10 +689,6 @@ mtx = self.get_matrix() self._inverted = Affine2D(inv(mtx)) return self._inverted - - def is_separable(self): - mtx = self.get_matrix() - return mtx[0, 1] == 0.0 and mtx[1, 0] == 0.0 class Affine2D(Affine2DBase): @@ -728,6 +786,10 @@ """ _mtx = npy.identity(3) + def __repr__(self): + return "IdentityTransform()" + __str__ = __repr__ + def __cmp__(self, other): if (isinstance(other, Affine2D) and (other == IDENTITY)): @@ -735,34 +797,44 @@ return -1 def get_matrix(self): - return _mtx + return self._mtx def transform(self, points): return points - def transform_without_affine(self, points): - return points, self + def transform_affine(self, points): + return points + def transform_non_affine(self, points): + return points + + def get_affine(self): + return self + def inverted(self): return self + -IDENTITY = Affine2D() - class BlendedGenericTransform(Transform): input_dims = 2 output_dims = 2 def __init__(self, x_transform, y_transform): # Here we ask: "Does it blend?" - # MGDTODO: Turn these checks back on - # assert x_transform.is_separable() - # assert y_transform.is_separable() + assert x_transform.is_separable() + assert y_transform.is_separable() Transform.__init__(self) self._x = x_transform self._y = y_transform self.set_children(['_x', '_y']) + def is_affine(self): + return self._x.is_affine() and self._y.is_affine() + + def is_separable(self): + return True + def __repr__(self): return "BlendedGenericTransform(%s,%s)" % (self._x, self._y) __str__ = __repr__ @@ -787,33 +859,17 @@ return ma.concatenate((x_points, y_points), 1) - def transform_without_affine(self, points): - x = self._x - y = self._y - if x == y and x.input_dims == 2: - return self._x.transform_without_affine(points) - - if x.input_dims == 2: - x_points, x_affine = x.transform_without_affine(points) - x_points = x_points[:, 0:1] - else: - x_points, x_affine = x.transform_without_affine(points[:, 0]) - x_points = x_points.reshape((len(x_points), 1)) - - if y.input_dims == 2: - y_points, y_affine = y.transform_without_affine(points) - y_points = y_points[:, 1:] - else: - y_points, y_affine = y.transform_without_affine(points[:, 1]) - y_points = y_points.reshape((len(y_points), 1)) - - return ma.concatenate((x_points, y_points), 1), blended_transform_factory(x_affine, y_affine) + def transform_affine(self, points): + return points + + def transform_non_affine(self, points): + return self.transform(points) + + def get_affine(self): + return IdentityTransform() def inverted(self): return BlendedGenericTransform(self._x.inverted(), self._y.inverted()) - - def is_separable(self): - return True class BlendedAffine1D(Affine2DBase, Transform): @@ -829,17 +885,17 @@ Affine2DBase.__init__(self) self._mtx = None + def is_separable(self): + return True + def __repr__(self): return "BlendedAffine1D(%s,%s)" % (self._x, self._y) __str__ = __repr__ - def _do_invalidation(self): + def _do_invalidation(self, which_child, affine_only): self._mtx = None - Affine2DBase._do_invalidation(self) + Affine2DBase._do_invalidation(self, which_child, affine_only) - def is_separable(self): - return True - def get_matrix(self): if self._mtx is None: x_mtx = self._x.get_matrix() @@ -854,9 +910,9 @@ def __init__(self, x_transform, y_transform): assert x_transform.is_affine() assert y_transform.is_affine() - # MGDTODO: Turn these checks back on - # assert x_transform.is_separable() - # assert y_transform.is_separable() + assert x_transform.is_separable() + assert y_transform.is_separable() + Transform.__init__(self) self._x = x_transform self._y = y_transform @@ -865,17 +921,17 @@ Affine2DBase.__init__(self) self._mtx = None + def is_separable(self): + return True + def __repr__(self): return "BlendedAffine2D(%s,%s)" % (self._x, self._y) __str__ = __repr__ - def _do_invalidation(self): + def _do_invalidation(self, which_child, affine_only): self._mtx = None - Affine2DBase._do_invalidation(self) + Affine2DBase._do_invalidation(self, which_child, affine_only) - def is_separable(self): - return True - def get_matrix(self): if self._mtx is None: if self._x == self._y: @@ -909,8 +965,12 @@ self._b = b self.set_children(['_a', '_b']) - self.take_shortcut = b.is_affine() - + def is_affine(self): + return self._a.is_affine() and self._b.is_affine() + + def is_separable(self): + return self._a.is_separable() and self._b.is_separable() + def __repr__(self): return "CompositeGenericTransform(%s, %s)" % (self._a, self._b) __str__ = __repr__ @@ -918,20 +978,24 @@ def transform(self, points): return self._b.transform(self._a.transform(points)) - def transform_without_affine(self, points): - if self.take_shortcut: - return self._a.transform(points), self._b - return self.transform(points), IDENTITY + def transform_affine(self, points): + return self._b.transform_affine(self._a.transform_affine(points)) + + def transform_non_affine(self, points): + return self._b.transform_non_affine(self._a.transform_non_affine(points)) + + def get_affine(self): + return self._a.get_affine() + self._b.get_affine() def inverted(self): return CompositeGenericTransform(self._b.inverted(), self._a.inverted()) - - def is_separable(self): - return self._a.is_separable() and self._b.is_separable() class CompositeAffine2D(Affine2DBase): def __init__(self, a, b): + assert a.output_dims == b.input_dims + self.input_dims = a.input_dims + self.output_dims = b.output_dims assert a.is_affine() assert b.is_affine() @@ -945,9 +1009,9 @@ return "CompositeAffine2D(%s, %s)" % (self._a, self._b) __str__ = __repr__ - def _do_invalidation(self): + def _do_invalidation(self, which_child, affine_only): self._mtx = None - Affine2DBase._do_invalidation(self) + Affine2DBase._do_invalidation(self, which_child, affine_only) def get_matrix(self): if self._mtx is None: @@ -958,7 +1022,9 @@ def composite_transform_factory(a, b): - if a.is_affine() and b.is_affine(): + if isinstance(a, BboxTransform) and isinstance(b, BboxTransform): + return BboxTransform(a._boxin, b._boxout) + if isinstance(a, AffineBase) and isinstance(b, AffineBase): return CompositeAffine2D(a, b) return CompositeGenericTransform(a, b) @@ -972,33 +1038,6 @@ return npy.log10(m) -class TestLogTransform(Transform): - input_dims = 1 - output_dims = 1 - def transform(self, a): - marray = ma.masked_where(a <= 0.0, a * 10.0) - return (npy.log10(marray) * 0.5) + 0.5 - - def inverted(self): - return TestInvertLogTransform() - - def is_separable(self): - return True - - -class TestInvertLogTransform(Transform): - input_dims = 1 - output_dims = 1 - def transform(self, a): - return ma.power(10, (a - 0.5) * 2.0) / 10.0 - - def inverted(self): - return TestLogTransform() - - def is_separable(self): - return True - - class TestPolarTransform(Transform): input_dims = 2 output_dims = 2 @@ -1078,9 +1117,9 @@ return "BboxTransform(%s, %s)" % (self._boxin, self._boxout) __str__ = __repr__ - def _do_invalidation(self): + def _do_invalidation(self, which_child, affine_only): self._mtx = None - Affine2DBase._do_invalidation(self) + Affine2DBase._do_invalidation(self, which_child, affine_only) def is_separable(self): return True @@ -1101,7 +1140,38 @@ self._mtx = affine._mtx return self._mtx + +class TransformedPath(TransformNode): + def __init__(self, path, transform): + assert isinstance(transform, Transform) + TransformNode.__init__(self) + + self._path = path + self._transform = transform + self.set_children(['_transform']) + self._transformed_path = None + + def _do_invalidation(self, which_child, affine_only): + if not (affine_only[0].is_affine() or affine_only[0].is_bbox()): + self._transformed_path = None + + def get_path_and_affine(self): + if self._transformed_path is None: + vertices = self._transform.transform_non_affine(self._path.vertices) + self._transformed_path = Path(vertices, self._path.codes) + return self._transformed_path, self._transform.get_affine() + + def get_path(self): + if self._transformed_path is None: + vertices = self._tranform.transform_non_affine(self._path.vertices) + self._transformed_path = Path(vertices, self._path.codes) + vertices = self._transform.transform_affine(self._transformed_path.vertices) + return Path(vertices, self._transformed_path.codes) + + def get_affine(self): + return self._transform.get_affine() + def nonsingular(vmin, vmax, expander=0.001, tiny=1e-15, increasing=True): ''' Ensure the endpoints of a range are not too close together. @@ -1128,6 +1198,7 @@ vmin, vmax = vmax, vmin return vmin, vmax + # MGDTODO: Optimize (perhaps in an extension) def interval_contains(interval, val): return interval[0] <= val and interval[1] >= val @@ -1173,8 +1244,8 @@ bbox = Bbox.from_lbwh(10, 11, 12, 13) assert bbox.bounds == (10, 11, 12, 13) - bbox_copy = copy.copy(bbox) - assert bbox == bbox_copy + bbox_copy = copy.deepcopy(bbox) + assert (bbox.lbrt == bbox_copy.lbrt).all() bbox_copy.max = (14, 15) assert bbox.bounds == (10, 11, 12, 13) assert bbox_copy.bounds == (10, 11, 4, 4) @@ -1183,7 +1254,7 @@ bbox2 = Bbox([[30., 35.], [40., 45.]]) trans = BboxTransform(bbox1, bbox2) bbox3 = bbox1.transformed(trans) - assert bbox3 == bbox2 + assert (bbox3.lbrt == bbox2.lbrt).all() translation = Affine2D().translate(10, 20) assert translation.to_values() == (1, 0, 0, 1, 10, 20) @@ -1210,12 +1281,6 @@ print points - comp = TestLogTransform() + Affine2D().rotate_deg(15) - tpoints = comp.transform(points) - itpoints = comp.inverted().transform(tpoints) - print tpoints, itpoints - assert (points.round() == itpoints.round()).all() - # Here are some timing tests points = npy.asarray([(random(), random()) for i in xrange(10000)]) t = timeit.Timer("trans_sum.transform(points)", "from __main__ import trans_sum, points") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 3888 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3888&view=rev Author: jswhit Date: 2007年09月25日 05:15:22 -0700 (2007年9月25日) Log Message: ----------- fix addcyclic Modified Paths: -------------- trunk/toolkits/basemap/Changelog Modified: trunk/toolkits/basemap/Changelog =================================================================== --- trunk/toolkits/basemap/Changelog 2007年09月25日 12:14:28 UTC (rev 3887) +++ trunk/toolkits/basemap/Changelog 2007年09月25日 12:15:22 UTC (rev 3888) @@ -1,4 +1,5 @@ -version 0.9.6 (svn revision 3878) +version 0.9.6 (svn revision 3888) + * fix addcyclic function so it handles masked arrays. * labelling of meridians and parallels now works with very small map regions (less than 0.2 degrees square). * Subregions of the globe may be specified with llcrnrlat, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 3887 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3887&view=rev Author: jswhit Date: 2007年09月25日 05:14:28 -0700 (2007年9月25日) Log Message: ----------- fix addcyclic so it can handle masked arrays Modified Paths: -------------- trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py Modified: trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py =================================================================== --- trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py 2007年09月24日 17:33:03 UTC (rev 3886) +++ trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py 2007年09月25日 12:14:28 UTC (rev 3887) @@ -2917,10 +2917,16 @@ """ nlats = arrin.shape[0] nlons = arrin.shape[1] - arrout = NX.zeros((nlats,nlons+1),arrin.dtype) + if hasattr(arrin,'mask'): + arrout = ma.zeros((nlats,nlons+1),arrin.dtype) + else: + arrout = NX.zeros((nlats,nlons+1),arrin.dtype) arrout[:,0:nlons] = arrin[:,:] arrout[:,nlons] = arrin[:,0] - lonsout = NX.zeros(nlons+1,lonsin.dtype) + if hasattr(lonsin,'mask'): + lonsout = ma.zeros(nlons+1,lonsin.dtype) + else: + lonsout = NX.zeros(nlons+1,lonsin.dtype) lonsout[0:nlons] = lonsin[:] lonsout[nlons] = lonsin[-1] + lonsin[1]-lonsin[0] return arrout,lonsout This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.