From: <md...@us...> - 2007-10-10 13:37:31
|
Revision: 3932 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3932&view=rev Author: mdboom Date: 2007-10-10 06:37:28 -0700 (Wed, 10 Oct 2007) Log Message: ----------- Lots more work on making examples work. Details, details, details... Modified Paths: -------------- branches/transforms/lib/matplotlib/axes.py branches/transforms/lib/matplotlib/axis.py branches/transforms/lib/matplotlib/backend_bases.py branches/transforms/lib/matplotlib/backends/backend_agg.py branches/transforms/lib/matplotlib/cbook.py branches/transforms/lib/matplotlib/collections.py branches/transforms/lib/matplotlib/colorbar.py branches/transforms/lib/matplotlib/dates.py branches/transforms/lib/matplotlib/figure.py branches/transforms/lib/matplotlib/lines.py branches/transforms/lib/matplotlib/scale.py branches/transforms/lib/matplotlib/text.py branches/transforms/lib/matplotlib/ticker.py branches/transforms/lib/matplotlib/transforms.py branches/transforms/src/_backend_agg.cpp Modified: branches/transforms/lib/matplotlib/axes.py =================================================================== --- branches/transforms/lib/matplotlib/axes.py 2007-10-09 15:58:36 UTC (rev 3931) +++ branches/transforms/lib/matplotlib/axes.py 2007-10-10 13:37:28 UTC (rev 3932) @@ -477,7 +477,11 @@ """ % {'scale': ' | '.join([repr(x) for x in mscale.get_scale_names()])} martist.Artist.__init__(self) - self._position = mtransforms.Bbox.from_lbwh(*rect) + if isinstance(rect, mtransforms.Bbox): + self._position = rect + else: + warnings.warn("Passing non-bbox as rect to Axes") + mtransforms.Bbox.from_lbwh(*rect) self._originalPosition = self._position.frozen() self.set_axes(self) self.set_aspect('auto') @@ -564,16 +568,16 @@ # 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 + # The parentheses are important for efficiency here -- they + # group the last two (which are usually affines) separately + # from the first (which, with log-scaling can be non-affine). + self.transData = self.transScale + (self.transLimits + self.transAxes) + self._xaxis_transform = mtransforms.blended_transform_factory( self.axes.transData, self.axes.transAxes) self._yaxis_transform = mtransforms.blended_transform_factory( @@ -807,9 +811,9 @@ ', '.join(mtransforms.BBox.coefs.keys())) def get_data_ratio(self): - xmin,xmax = self.get_xlim() + xmin,xmax = self.get_xbound() xsize = max(math.fabs(xmax-xmin), 1e-30) - ymin,ymax = self.get_ylim() + ymin,ymax = self.get_ybound() ysize = max(math.fabs(ymax-ymin), 1e-30) return ysize/xsize @@ -819,7 +823,7 @@ axes box or the view limits. ''' #MGDTODO: Numpify - + if self._aspect == 'auto': self.set_position( self._originalPosition , 'active') return @@ -843,7 +847,6 @@ self.set_position(pb1.anchored(self._anchor, pb), 'active') return - xmin,xmax = self.get_xbound() xsize = max(math.fabs(xmax-xmin), 1e-30) ymin,ymax = self.get_ybound() @@ -1519,7 +1522,9 @@ if xmin is None: xmin = old_xmin if xmax is None: xmax = old_xmax - xmax, xmin = mtransforms.nonsingular(xmax, xmin, increasing=False) + xmin, xmax = mtransforms.nonsingular(xmin, xmax) + xmin, xmax = self.xaxis.limit_range_for_scale(xmin, xmax) + self.viewLim.intervalx = (xmin, xmax) if emit: @@ -1678,6 +1683,7 @@ if ymax is None: ymax = old_ymax ymin, ymax = mtransforms.nonsingular(ymin, ymax, increasing=False) + ymin, ymax = self.yaxis.limit_range_for_scale(ymin, ymax) self.viewLim.intervaly = (ymin, ymax) if emit: @@ -1884,10 +1890,12 @@ .transformed(p.trans_inverse) elif button == 3: try: - # MGDTODO: This is broken with log scales - dx, dy = format_deltas(key, dx, dy) dx = -dx / float(self.bbox.width) dy = -dy / float(self.bbox.height) + dx, dy = format_deltas(key, dx, dy) + if self.get_aspect() != 'auto': + dx = 0.5 * (dx + dy) + dy = dx xmin, ymin, xmax, ymax = p.lim.lbrt alpha = npy.power(10.0, (dx, dy)) @@ -2375,7 +2383,7 @@ axvspan.__doc__ = cbook.dedent(axvspan.__doc__) % martist.kwdocd - def hlines(self, y, xmin, xmax, colors='k', linestyle='solid', + def hlines(self, y, xmin, xmax, colors='k', linestyles='solid', label='', **kwargs): """ HLINES(y, xmin, xmax, colors='k', linestyle='solid', **kwargs) @@ -2417,7 +2425,7 @@ verts = [ ((thisxmin, thisy), (thisxmax, thisy)) for thisxmin, thisxmax, thisy in zip(xmin, xmax, y)] coll = mcoll.LineCollection(verts, colors=colors, - linestyle=linestyle, label=label) + linestyles=linestyles, label=label) self.add_collection(coll) coll.update(kwargs) @@ -4896,7 +4904,7 @@ self.set_xlabel('Frequency') self.set_ylabel('Cross Spectrum Magnitude (dB)') self.grid(True) - vmin, vmax = self.viewLim.intervaly().get_bounds() + vmin, vmax = self.viewLim.intervaly intv = vmax-vmin step = 10*int(npy.log10(intv)) @@ -5177,8 +5185,7 @@ self.update_params() # _axes_class is set in the subplot_class_factory - self._axes_class.__init__(self, fig, [self.figLeft, self.figBottom, - self.figW, self.figH], **kwargs) + self._axes_class.__init__(self, fig, self.figbox, **kwargs) def get_geometry(self): 'get the subplot geometry, eg 2,2,3' @@ -5190,7 +5197,7 @@ self._cols = numcols self._num = num-1 self.update_params() - self.set_position([self.figLeft, self.figBottom, self.figW, self.figH]) + self.set_position(self.figbox) def update_params(self): 'update the subplot position from fig.subplotpars' @@ -5220,10 +5227,7 @@ figBottom = top - (rowNum+1)*figH - rowNum*sepH figLeft = left + colNum*(figW + sepW) - self.figBottom = figBottom - self.figLeft = figLeft - self.figW = figW - self.figH = figH + self.figbox = mtransforms.Bbox.from_lbwh(figLeft, figBottom, figW, figH) self.rowNum = rowNum self.colNum = colNum self.numRows = rows Modified: branches/transforms/lib/matplotlib/axis.py =================================================================== --- branches/transforms/lib/matplotlib/axis.py 2007-10-09 15:58:36 UTC (rev 3931) +++ branches/transforms/lib/matplotlib/axis.py 2007-10-10 13:37:28 UTC (rev 3932) @@ -524,7 +524,10 @@ def set_scale(self, value, **kwargs): self._scale = scale_factory(value, self, **kwargs) self._scale.set_default_locators_and_formatters(self) - + + def limit_range_for_scale(self, vmin, vmax): + return self._scale.limit_range_for_scale(vmin, vmax, self.get_minpos()) + def get_children(self): children = [self.label] majorticks = self.get_major_ticks() @@ -580,6 +583,10 @@ 'return the Interval instance for this axis data limits' raise NotImplementedError('Derived must override') + def set_data_interval(self): + 'Set the axis data limits' + raise NotImplementedError('Derived must override') + def _set_artist_props(self, a): if a is None: return a.set_figure(self.figure) @@ -887,7 +894,7 @@ ACCEPTS: A Formatter instance """ self.major.formatter = formatter - self.major.formatter.set_axis(self) + formatter.set_axis(self) def set_minor_formatter(self, formatter): @@ -897,7 +904,7 @@ ACCEPTS: A Formatter instance """ self.minor.formatter = formatter - self.minor.formatter.set_axis(self) + formatter.set_axis(self) def set_major_locator(self, locator): @@ -907,7 +914,7 @@ ACCEPTS: a Locator instance """ self.major.locator = locator - self.major.locator.set_axis(self) + locator.set_axis(self) def set_minor_locator(self, locator): @@ -917,7 +924,7 @@ ACCEPTS: a Locator instance """ self.minor.locator = locator - self.minor.locator.set_axis(self) + locator.set_axis(self) def set_pickradius(self, pickradius): """ @@ -1180,7 +1187,15 @@ 'return the Interval instance for this axis data limits' return self.axes.dataLim.intervalx + def set_data_interval(self, vmin, vmax, ignore=False): + 'return the Interval instance for this axis data limits' + if ignore: + self.axes.dataLim.intervalx = vmin, vmax + else: + Vmin, Vmax = self.get_data_interval() + self.axes.dataLim.intervalx = min(vmin, Vmin), max(vmax, Vmax) + class YAxis(Axis): __name__ = 'yaxis' axis_name = 'y' @@ -1395,5 +1410,12 @@ 'return the Interval instance for this axis data limits' return self.axes.dataLim.intervaly + def set_data_interval(self, vmin, vmax, ignore=False): + 'return the Interval instance for this axis data limits' + if ignore: + self.axes.dataLim.intervaly = vmin, vmax + else: + Vmin, Vmax = self.get_data_interval() + self.axes.dataLim.intervaly = min(vmin, Vmin), max(vmax, Vmax) Modified: branches/transforms/lib/matplotlib/backend_bases.py =================================================================== --- branches/transforms/lib/matplotlib/backend_bases.py 2007-10-09 15:58:36 UTC (rev 3931) +++ branches/transforms/lib/matplotlib/backend_bases.py 2007-10-10 13:37:28 UTC (rev 3932) @@ -1598,7 +1598,7 @@ for a, ind in self._xypress: a.end_pan() if not self._xypress: return - self._xypress = None + self._xypress = [] self._button_pressed=None self.push_current() self.release(event) Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py =================================================================== --- branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-10-09 15:58:36 UTC (rev 3931) +++ branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-10-10 13:37:28 UTC (rev 3932) @@ -381,11 +381,11 @@ return 'png' def print_raw(self, filename, *args, **kwargs): - self.draw() + FigureCanvasAgg.draw(self) self.get_renderer()._renderer.write_rgba(str(filename)) print_rgba = print_raw def print_png(self, filename, *args, **kwargs): - self.draw() - self.get_renderer()._renderer.write_png(str(filename), self.figure.dpi.get()) + FigureCanvasAgg.draw(self) + self.get_renderer()._renderer.write_png(str(filename), self.figure.dpi) Modified: branches/transforms/lib/matplotlib/cbook.py =================================================================== --- branches/transforms/lib/matplotlib/cbook.py 2007-10-09 15:58:36 UTC (rev 3931) +++ branches/transforms/lib/matplotlib/cbook.py 2007-10-10 13:37:28 UTC (rev 3932) @@ -1051,7 +1051,6 @@ a1 = a[1: ] delta = ((a1 - a0) / steps) - # MGDTODO: Could use linspace here? for i in range(1, int(steps)): result[i::steps] = delta * i + a0 result[steps::steps] = a1 Modified: branches/transforms/lib/matplotlib/collections.py =================================================================== --- branches/transforms/lib/matplotlib/collections.py 2007-10-09 15:58:36 UTC (rev 3931) +++ branches/transforms/lib/matplotlib/collections.py 2007-10-10 13:37:28 UTC (rev 3932) @@ -59,12 +59,6 @@ _offsets = npy.zeros((1, 2)) _transOffset = transforms.IdentityTransform() - _facecolors = [None] - _edgecolors = [None] - _lw = [1.0] - _ls = [None] - _aa = [True] - _pickradius = 5.0 _transforms = [None] zorder = 1 @@ -107,9 +101,8 @@ self._uniform_offsets = None self._offsets = npy.zeros((1, 2)) if offsets is not None: - offsets = npy.asarray(offsets) - if len(offsets.shape) == 1: - offsets = offsets[npy.newaxis,:] # Make it Nx2. +# if len(offsets.shape) == 1: +# offsets = offsets[npy.newaxis,:] # Make it Nx2. if transOffset is not None: Affine2D = transforms.Affine2D self._offsets = offsets @@ -152,29 +145,37 @@ transform = self.get_transform() transOffset = self._transOffset offsets = self._offsets + paths = self.get_paths() - # MGDTODO: Transform the paths (since we don't keep track of segments anymore + # MGDTODO: Test me if self.have_units(): - segments = [] - for segment in self._segments: + paths = [] + for path in self._paths: + vertices = path.vertices xs, ys = zip(*segment) xs = self.convert_xunits(xs) ys = self.convert_yunits(ys) - segments.append(zip(xs, ys)) -# if self._offsets is not None: -# xs = self.convert_xunits(self._offsets[:0]) -# ys = self.convert_yunits(self._offsets[:1]) -# offsets = zip(xs, ys) + paths.append(path.Path(zip(xs, ys), path.codes)) + if self._offsets is not None: + xs = self.convert_xunits(self._offsets[:0]) + ys = self.convert_yunits(self._offsets[:1]) + offsets = zip(xs, ys) self.update_scalarmappable() #print 'calling renderer draw line collection' clippath, clippath_trans = self.get_transformed_clip_path_and_affine() + if not transform.is_affine: + paths = [transform.transform_path_non_affine(path) for path in paths] + transform = transform.get_affine() + renderer.draw_path_collection( transform, self.clipbox, clippath, clippath_trans, - self.get_paths(), self.get_transforms(), offsets, transOffset, - self._facecolors, self._edgecolors, self._lw, self._ls, self._aa) + paths, self.get_transforms(), + npy.asarray(offsets, npy.float_), transOffset, + self._facecolors, self._edgecolors, self._linewidths, + self._linestyles, self._antialiaseds) renderer.close_group(self.__class__.__name__) def contains(self, mouseevent): @@ -190,7 +191,7 @@ self._offsetTrans, self._facecolors) return len(ind)>0,dict(ind=ind) - # MGDTODO + # MGDTODO: Update def get_transformed_patches(self): """ get a sequence of the polygons in the collection in display (transformed) space @@ -272,7 +273,7 @@ except ValueError: raise ValueError('Do not know how to convert %s to dashes'%ls) - self._ls = dashes + self._linestyles = dashes def set_color(self, c): """ @@ -328,13 +329,13 @@ self._edgecolors = [(r,g,b,alpha) for r,g,b,a in self._edgecolors] def get_linewidth(self): - return self._lw - + return self._linewidths + def get_linestyle(self): - return self._ls + return self._linestyles def get_dashes(self): - return self._ls + return self._linestyles def update_scalarmappable(self): """ @@ -509,14 +510,20 @@ self._sizes = sizes self._dpi = dpi self._paths = [path.Path.unit_regular_polygon(numsides)] - self._transforms = [transforms.Affine2D().scale(x) for x in sizes] + # sizes is the area of the circle circumscribing the polygon + # in points^2 + self._transforms = [ + transforms.Affine2D().rotate(rotation).scale( + (math.sqrt(x) * self._dpi / 72.0) * (1.0 / math.sqrt(math.pi))) + for x in sizes] + self.set_transform(transforms.IdentityTransform()) __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd def get_paths(self): return self._paths - # MGDTODO + # MGDTODO: Update def get_transformed_patches(self): # Shouldn't need all these calls to asarray; # the variables should be converted when stored. Modified: branches/transforms/lib/matplotlib/colorbar.py =================================================================== --- branches/transforms/lib/matplotlib/colorbar.py 2007-10-09 15:58:36 UTC (rev 3931) +++ branches/transforms/lib/matplotlib/colorbar.py 2007-10-10 13:37:28 UTC (rev 3932) @@ -317,12 +317,13 @@ intv = transforms.Interval(transforms.Value(self._values[0]), transforms.Value(self._values[-1])) else: - intv = transforms.Interval(transforms.Value(self.vmin), - transforms.Value(self.vmax)) - locator.set_view_interval(intv) - locator.set_data_interval(intv) - formatter.set_view_interval(intv) - formatter.set_data_interval(intv) + intv = self.vmin, self.vmax + locator.create_dummy_axis() + locator.set_view_interval(*intv) + locator.set_data_interval(*intv) + formatter.create_dummy_axis() + formatter.set_view_interval(*intv) + formatter.set_data_interval(*intv) b = npy.array(locator()) b, ticks = self._locate(b) formatter.set_locs(b) Modified: branches/transforms/lib/matplotlib/dates.py =================================================================== --- branches/transforms/lib/matplotlib/dates.py 2007-10-09 15:58:36 UTC (rev 3931) +++ branches/transforms/lib/matplotlib/dates.py 2007-10-10 13:37:28 UTC (rev 3932) @@ -429,13 +429,11 @@ self.tz = tz def datalim_to_dt(self): - self.verify_intervals() - dmin, dmax = self.dataInterval.get_bounds() + dmin, dmax = self.axis.get_data_interval() return num2date(dmin, self.tz), num2date(dmax, self.tz) def viewlim_to_dt(self): - self.verify_intervals() - vmin, vmax = self.viewInterval.get_bounds() + vmin, vmax = self.axis.get_view_interval() return num2date(vmin, self.tz), num2date(vmax, self.tz) def _get_unit(self): @@ -459,8 +457,6 @@ self.rule = o def __call__(self): - self.verify_intervals() - # if no data have been set, this will tank with a ValueError try: dmin, dmax = self.viewlim_to_dt() except ValueError: return [] @@ -500,7 +496,6 @@ """ Set the view limits to include the data range """ - self.verify_intervals() dmin, dmax = self.datalim_to_dt() if dmin>dmax: dmax, dmin = dmin, dmax @@ -537,6 +532,10 @@ self.refresh() return self._locator() + def set_axis(self, axis): + DateLocator.set_axis(self, axis) + self._locator.set_axis(axis) + def refresh(self): 'refresh internal information based on current lim' dmin, dmax = self.viewlim_to_dt() @@ -563,8 +562,6 @@ def autoscale(self): 'Try to choose the view limits intelligently' - - self.verify_intervals() dmin, dmax = self.datalim_to_dt() self._locator = self.get_locator(dmin, dmax) return self._locator.autoscale() @@ -667,9 +664,10 @@ bysecond=bysecond ) locator = RRuleLocator(rrule, self.tz) - - locator.set_view_interval(self.viewInterval) - locator.set_data_interval(self.dataInterval) + locator.set_axis(self.axis) + + locator.set_view_interval(*self.axis.get_view_interval()) + locator.set_data_interval(*self.axis.get_data_interval()) return locator @@ -710,8 +708,6 @@ return 365 def __call__(self): - self.verify_intervals() - dmin, dmax = self.viewlim_to_dt() ymin = self.base.le(dmin.year) ymax = self.base.ge(dmax.year) @@ -728,7 +724,6 @@ """ Set the view limits to include the data range """ - self.verify_intervals() dmin, dmax = self.datalim_to_dt() ymin = self.base.le(dmin.year) Modified: branches/transforms/lib/matplotlib/figure.py =================================================================== --- branches/transforms/lib/matplotlib/figure.py 2007-10-09 15:58:36 UTC (rev 3931) +++ branches/transforms/lib/matplotlib/figure.py 2007-10-10 13:37:28 UTC (rev 3932) @@ -818,17 +818,17 @@ self.subplotpars.update(*args, **kwargs) import matplotlib.axes for ax in self.axes: - if not isinstance(ax, matplotlib.axes.Subplot): + if not isinstance(ax, matplotlib.axes.SubplotBase): # Check if sharing a subplots axis - if ax._sharex is not None and isinstance(ax._sharex, matplotlib.axes.Subplot): + if ax._sharex is not None and isinstance(ax._sharex, matplotlib.axes.SubplotBase): ax._sharex.update_params() - ax.set_position([ax._sharex.figLeft, ax._sharex.figBottom, ax._sharex.figW, ax._sharex.figH]) - elif ax._sharey is not None and isinstance(ax._sharey, matplotlib.axes.Subplot): + ax.set_position(ax._sharex.figbox) + elif ax._sharey is not None and isinstance(ax._sharey, matplotlib.axes.SubplotBase): ax._sharey.update_params() - ax.set_position([ax._sharey.figLeft, ax._sharey.figBottom, ax._sharey.figW, ax._sharey.figH]) + ax.set_position(ax._sharey.figbox) else: ax.update_params() - ax.set_position([ax.figLeft, ax.figBottom, ax.figW, ax.figH]) + ax.set_position(ax.figbox) Modified: branches/transforms/lib/matplotlib/lines.py =================================================================== --- branches/transforms/lib/matplotlib/lines.py 2007-10-09 15:58:36 UTC (rev 3931) +++ branches/transforms/lib/matplotlib/lines.py 2007-10-10 13:37:28 UTC (rev 3932) @@ -300,18 +300,19 @@ raise ValueError,"pick radius should be a distance" # transform in backend - x = self._x - y = self._y - if len(x)==0: return False,{} + if len(self._xy)==0: return False,{} - xt, yt = self.get_transform().numerix_x_y(x, y) - + xyt = self.get_transform().transform(self._xy) + xt = xyt[:, 0] + yt = xyt[:, 1] + if self.figure == None: print str(self),' has no figure set' pixels = self.pickradius else: - pixels = self.figure.dpi.get()/72. * self.pickradius - + pixels = self.figure.dpi/72. * self.pickradius + + path, transform = self._transformed_path.get_transformed_path_and_affine() if self._linestyle == 'None': # If no line, return the nearby point(s) d = npy.sqrt((xt-mouseevent.x)**2 + (yt-mouseevent.y)**2) @@ -384,11 +385,17 @@ def recache(self): #if self.axes is None: print 'recache no axes' #else: print 'recache units', self.axes.xaxis.units, self.axes.yaxis.units - x = ma.asarray(self.convert_xunits(self._xorig), float) - y = ma.asarray(self.convert_yunits(self._yorig), float) - - x = ma.ravel(x) - y = ma.ravel(y) + if ma.isMaskedArray(self._xorig) or ma.isMaskedArray(self._yorig): + x = ma.asarray(self.convert_xunits(self._xorig), float) + y = ma.asarray(self.convert_yunits(self._yorig), float) + x = ma.ravel(x) + y = ma.ravel(y) + else: + x = npy.asarray(self.convert_xunits(self._xorig), float) + y = npy.asarray(self.convert_yunits(self._yorig), float) + x = npy.ravel(x) + y = npy.ravel(y) + if len(x)==1 and len(y)>1: x = x * npy.ones(y.shape, float) if len(y)==1 and len(x)>1: @@ -399,8 +406,11 @@ x = x.reshape((len(x), 1)) y = y.reshape((len(y), 1)) - - self._xy = ma.concatenate((x, y), 1) + + if ma.isMaskedArray(x) or ma.isMaskedArray(y): + self._xy = ma.concatenate((x, y), 1) + else: + self._xy = npy.concatenate((x, y), 1) self._x = self._xy[:, 0] # just a view self._y = self._xy[:, 1] # just a view self._logcache = None Modified: branches/transforms/lib/matplotlib/scale.py =================================================================== --- branches/transforms/lib/matplotlib/scale.py 2007-10-09 15:58:36 UTC (rev 3931) +++ branches/transforms/lib/matplotlib/scale.py 2007-10-10 13:37:28 UTC (rev 3932) @@ -14,7 +14,10 @@ class ScaleBase(object): def set_default_locators_and_formatters(self, axis): raise NotImplementedError - + + def limit_range_for_scale(self, vmin, vmax, minpos): + return vmin, vmax + class LinearScale(ScaleBase): name = 'linear' @@ -39,6 +42,9 @@ is_separable = True def transform(self, a): + # MGDTODO: Remove me + if len(a) > 10: + print "log transforming" return ma.log10(ma.masked_where(a <= 0.0, a * 10.0)) def inverted(self): @@ -159,6 +165,9 @@ def get_transform(self): return self._transform + def limit_range_for_scale(self, vmin, vmax, minpos): + return (vmin <= 0.0 and minpos or vmin, + vmax <= 0.0 and minpos or vmax) _scale_mapping = { 'linear' : LinearScale, Modified: branches/transforms/lib/matplotlib/text.py =================================================================== --- branches/transforms/lib/matplotlib/text.py 2007-10-09 15:58:36 UTC (rev 3931) +++ branches/transforms/lib/matplotlib/text.py 2007-10-10 13:37:28 UTC (rev 3932) @@ -179,14 +179,17 @@ key = self.get_prop_tup() if self.cached.has_key(key): return self.cached[key] horizLayout = [] - thisx, thisy = self._get_xy_display() + transform = self.get_transform() + x, y = self.get_position() + thisx, thisy = transform.transform_point((x, y)) + tx, ty = thisx, thisy + width = 0 height = 0 xmin, ymin = thisx, thisy lines = self._text.split('\n') - # MGDTODO: whs could be a numpy.array whs = [] # Find full vertical extent of font, # including ascenders and descenders: @@ -267,11 +270,10 @@ # now rotate the positions around the first x,y position xys = M.transform(offsetLayout) - xys[:, 0] += offsetx - xys[:, 1] += offsety + xys += (offsetx, offsety) # now inverse transform back to data coords - inverse_transform = self.get_transform().inverted() + inverse_transform = transform.inverted() xys = inverse_transform.transform(xys) xs, ys = xys[:, 0], xys[:, 1] @@ -781,13 +783,14 @@ # Compute the dash end points # The 'c' prefix is for canvas coordinates - cxy = npy.array(transform.xy_tup((dashx, dashy))) + cxy = transform.transform_point((dashx, dashy)) cd = npy.array([cos_theta, sin_theta]) c1 = cxy+dashpush*cd c2 = cxy+(dashpush+dashlength)*cd - (x1, y1) = transform.inverse_xy_tup(tuple(c1)) - (x2, y2) = transform.inverse_xy_tup(tuple(c2)) + inverse = transform.inverted() + (x1, y1) = inverse.transform_point(tuple(c1)) + (x2, y2) = inverse.transform_point(tuple(c2)) self.dashline.set_data((x1, x2), (y1, y2)) # We now need to extend this vector out to @@ -805,7 +808,7 @@ # but I don't grok the transformation stuff # well enough yet. we = Text.get_window_extent(self, renderer=renderer) - w, h = we.width(), we.height() + w, h = we.width, we.height # Watch for zeros if sin_theta == 0.0: dx = w @@ -824,13 +827,13 @@ cwd *= 1+dashpad/npy.sqrt(npy.dot(cwd,cwd)) cw = c2+(dashdirection*2-1)*cwd - self._x, self._y = transform.inverse_xy_tup(tuple(cw)) + self._x, self._y = inverse.transform_point(tuple(cw)) # Now set the window extent # I'm not at all sure this is the right way to do this. we = Text.get_window_extent(self, renderer=renderer) - self._twd_window_extent = we.deepcopy() - self._twd_window_extent.update(((c1[0], c1[1]),), False) + self._twd_window_extent = we.frozen() + self._twd_window_extent.update_from_data_xy(npy.array([c1]), False) # Finally, make text align center Text.set_horizontalalignment(self, 'center') Modified: branches/transforms/lib/matplotlib/ticker.py =================================================================== --- branches/transforms/lib/matplotlib/ticker.py 2007-10-09 15:58:36 UTC (rev 3931) +++ branches/transforms/lib/matplotlib/ticker.py 2007-10-10 13:37:28 UTC (rev 3932) @@ -116,10 +116,35 @@ class TickHelper: axis = None + class DummyAxis: + def __init__(self): + self.dataLim = mtransforms.Bbox + self.viewLim = mtransforms.Bbox + + def get_view_interval(self): + return self.viewLim.intervalx + + def set_view_interval(self, vmin, vmax): + self.viewLim.intervalx = vmin, vmax + + def get_data_interval(self): + return self.dataLim.intervalx + + def set_data_interval(self, vmin, vmax): + self.dataLim.intervalx = vmin, vmax + def set_axis(self, axis): self.axis = axis + def create_dummy_axis(self): + self.axis = self.DummyAxis() + + def set_view_interval(self, vmin, vmax): + self.axis.set_view_interval(vmin, vmax) + def set_data_interval(self, vmin, vmax): + self.axis.set_data_interval(vmin, vmax) + class Formatter(TickHelper): """ Convert the tick location to a string @@ -900,6 +925,9 @@ vmin, vmax = self.axis.get_view_interval() if vmin <= 0.0: vmin = self.axis.get_minpos() + if vmin <= 0.0: + raise ValueError( + "Data has no positive values, and therefore can not be log-scaled.") vmin = math.log(vmin)/math.log(b) vmax = math.log(vmax)/math.log(b) @@ -936,7 +964,8 @@ minpos = self.axis.get_minpos() if minpos<=0: - raise RuntimeError('No positive data to plot') + raise ValueError( + "Data has no positive values, and therefore can not be log-scaled.") if vmin <= minpos: vmin = minpos Modified: branches/transforms/lib/matplotlib/transforms.py =================================================================== --- branches/transforms/lib/matplotlib/transforms.py 2007-10-09 15:58:36 UTC (rev 3931) +++ branches/transforms/lib/matplotlib/transforms.py 2007-10-10 13:37:28 UTC (rev 3932) @@ -32,7 +32,7 @@ import cbook from path import Path -DEBUG = False +DEBUG = True class TransformNode(object): """ @@ -403,7 +403,6 @@ if len(x) == 0 or len(y) == 0: return - # MGDTODO: All getters of minpos should be aware that is is sometimes -inf if ma.isMaskedArray(x) or ma.isMaskedArray(y): xpos = ma.where(x > 0.0, x, npy.inf) ypos = ma.where(y > 0.0, y, npy.inf) @@ -616,26 +615,28 @@ #@staticmethod def union(bboxes): """ - Return a Bbox that bounds all the given bboxes. + Return a Bbox that contains all of the given bboxes. """ - # MGDTODO: There's got to be a way to utilize numpy here - # to make this faster... assert(len(bboxes)) if len(bboxes) == 1: return bboxes[0] - - bbox = bboxes[0] - xmin0, ymin0, xmax0, ymax0 = bbox.lbrt - for bbox in bboxes[1:]: - xmin, ymin, xmax, ymax = bbox.lbrt - xmin0 = min(xmin0, xmin) - ymin0 = min(ymin0, ymin) - xmax0 = max(xmax0, xmax) - ymax0 = max(ymax0, ymax) + xmin = npy.inf + ymin = npy.inf + xmax = -npy.inf + ymax = -npy.inf - return Bbox.from_lbrt(xmin0, ymin0, xmax0, ymax0) + for bbox in bboxes: + points = bbox.get_points() + xs = points[:, 0] + ys = points[:, 1] + xmin = min(xmin, npy.min(xs)) + ymin = min(ymin, npy.min(ys)) + xmax = max(xmax, npy.max(xs)) + ymax = max(ymax, npy.max(ys)) + + return Bbox.from_lbrt(xmin, ymin, xmax, ymax) union = staticmethod(union) @@ -1243,22 +1244,18 @@ # MGDTODO: The major speed trap here is just converting to # the points to an array in the first place. If we can use # more arrays upstream, that should help here. - if DEBUG and not isinstance(values, npy.ndarray): + if DEBUG and not ma.isMaskedArray(points) and not isinstance(points, npy.ndarray): import traceback print '-' * 60 - print 'A non-numpy array of type %s was passed in for transformation.' % type(values) + print 'A non-numpy array of type %s was passed in for transformation.' % type(points) print 'Please correct this.' print "".join(traceback.format_stack()) mtx = self.get_matrix() if ma.isMaskedArray(points): - points = points.transpose() - points = ma.dot(mtx[0:2, 0:2], points) - points = points + mtx[0:2, 2:] + points = ma.dot(mtx[0:2, 0:2], points.transpose()) + mtx[0:2, 2:] else: - points = npy.asarray(points, npy.float_) - points = points.transpose() - points = npy.dot(mtx[0:2, 0:2], points) - points = points + mtx[0:2, 2:] + # points = npy.asarray(points, npy.float_) + points = npy.dot(mtx[0:2, 0:2], points.transpose()) + mtx[0:2, 2:] return points.transpose() transform.__doc__ = AffineBase.transform.__doc__ @@ -1558,7 +1555,10 @@ y_points = y.transform(points[:, 1]) y_points = y_points.reshape((len(y_points), 1)) - return ma.concatenate((x_points, y_points), 1) + if ma.isMaskedArray(x_points) or ma.isMaskedArray(y_points): + return ma.concatenate((x_points, y_points), 1) + else: + return npy.concatenate((x_points, y_points), 1) transform.__doc__ = Transform.transform.__doc__ transform_non_affine = transform @@ -1741,14 +1741,6 @@ return "CompositeGenericTransform(%s, %s)" % (self._a, self._b) __str__ = __repr__ - # MGDTODO: Remove -# def get_matrix(self): -# if self._invalid: -# assert self._a.is_affine and self._b.is_affine -# self._mtx = npy.dot(self._b.get_matrix(), self._a.get_matrix()) -# self._invalid = 0 -# return self._mtx - def transform(self, points): return self._b.transform( self._a.transform(points)) @@ -1927,18 +1919,18 @@ the transform already applied, along with the affine part of the path necessary to complete the transformation. """ - if (self._invalid != self.INVALID_AFFINE or + if (self._invalid & self.INVALID_NON_AFFINE or self._transformed_path is None): self._transformed_path = \ self._transform.transform_path_non_affine(self._path) - self._invalid = 0 + self._invalid = 0 return self._transformed_path, self._transform.get_affine() def get_fully_transformed_path(self): """ Return a fully-transformed copy of the child path. """ - if (self._invalid != self.INVALID_AFFINE + if (self._invalid & self.INVALID_NON_AFFINE or self._transformed_path is None): self._transformed_path = \ self._transform.transform_path_non_affine(self._path) Modified: branches/transforms/src/_backend_agg.cpp =================================================================== --- branches/transforms/src/_backend_agg.cpp 2007-10-09 15:58:36 UTC (rev 3931) +++ branches/transforms/src/_backend_agg.cpp 2007-10-10 13:37:28 UTC (rev 3932) @@ -527,10 +527,8 @@ RendererAgg::draw_markers(const Py::Tuple& args) { typedef agg::conv_transform<PathIterator> transformed_path_t; typedef conv_quantize<transformed_path_t> quantize_t; - typedef agg::conv_curve<transformed_path_t> curve_t; + typedef agg::conv_curve<transformed_path_t> curve_t; typedef agg::conv_stroke<curve_t> stroke_t; - typedef agg::conv_dash<curve_t> dash_t; - typedef agg::conv_stroke<dash_t> stroke_dash_t; typedef agg::pixfmt_amask_adaptor<pixfmt, alpha_mask_type> pixfmt_amask_type; typedef agg::renderer_base<pixfmt_amask_type> amask_ren_type; typedef agg::renderer_scanline_aa_solid<amask_ren_type> amask_aa_renderer_type; @@ -836,16 +834,30 @@ // Render face if (face.first) { - if (has_clippath) { - pixfmt_amask_type pfa(*pixFmt, *alphaMask); - amask_ren_type r(pfa); - amask_aa_renderer_type ren(r); - ren.color(face.second); - agg::render_scanlines(*theRasterizer, *slineP8, ren); + if (gc.isaa) { + if (has_clippath) { + pixfmt_amask_type pfa(*pixFmt, *alphaMask); + amask_ren_type r(pfa); + amask_aa_renderer_type ren(r); + ren.color(face.second); + agg::render_scanlines(*theRasterizer, *slineP8, ren); + } else { + rendererAA->color(face.second); + theRasterizer->add_path(curve); + agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); + } } else { - rendererAA->color(face.second); - theRasterizer->add_path(curve); - agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); + if (has_clippath) { + pixfmt_amask_type pfa(*pixFmt, *alphaMask); + amask_ren_type r(pfa); + amask_bin_renderer_type ren(r); + ren.color(face.second); + agg::render_scanlines(*theRasterizer, *slineP8, ren); + } else { + rendererBin->color(face.second); + theRasterizer->add_path(curve); + agg::render_scanlines(*theRasterizer, *slineP8, *rendererBin); + } } } @@ -959,7 +971,7 @@ size_t Naa = antialiaseds.length(); size_t i = 0; - + // Convert all of the transforms up front typedef std::vector<agg::trans_affine> transforms_t; transforms_t transforms; @@ -1028,6 +1040,8 @@ bool has_clippath = render_clippath(clippath, clippath_trans); for (i = 0; i < N; ++i) { + PathIterator path(paths[i % Npaths]); + bool snap = (path.total_vertices() == 2); double xo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 0); double yo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 1); offset_trans.transform(&xo, &yo); @@ -1039,8 +1053,6 @@ gc.dashes = dashes[i % Nlinestyles].second; gc.dashOffset = dashes[i % Nlinestyles].first; gc.isaa = bool(Py::Int(antialiaseds[i % Naa])); - PathIterator path(paths[i % Npaths]); - bool snap = (path.total_vertices() == 2); _draw_path(path, trans * transOffset, snap, has_clippath, face, gc); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |