From: <jd...@us...> - 2007-07-19 17:04:22
|
Revision: 3576 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3576&view=rev Author: jdh2358 Date: 2007-07-19 10:04:19 -0700 (Thu, 19 Jul 2007) Log Message: ----------- working draft Modified Paths: -------------- trunk/matplotlib/mpl1/DESIGN_GOALS trunk/matplotlib/mpl1/mpl1.py trunk/matplotlib/mpl1/mtraits.py trunk/matplotlib/mpl1/scratch.py trunk/matplotlib/mpl1/test.py Modified: trunk/matplotlib/mpl1/DESIGN_GOALS =================================================================== --- trunk/matplotlib/mpl1/DESIGN_GOALS 2007-07-19 16:53:36 UTC (rev 3575) +++ trunk/matplotlib/mpl1/DESIGN_GOALS 2007-07-19 17:04:19 UTC (rev 3576) @@ -24,7 +24,7 @@ limits -> axes units (AxesCoords.affineview), the transformation from axes units to normalized figure units (AxesCoords.affineaxes), and the transformation from normalized figure units to display -(Renderer.affine) +(Renderer.affinerenderer) Do we want to use 3x3 or 4x4 to leave the door open for 3D developers? Modified: trunk/matplotlib/mpl1/mpl1.py =================================================================== --- trunk/matplotlib/mpl1/mpl1.py 2007-07-19 16:53:36 UTC (rev 3575) +++ trunk/matplotlib/mpl1/mpl1.py 2007-07-19 17:04:19 UTC (rev 3576) @@ -5,7 +5,115 @@ import numpy as npy import mtraits # some handy traits for mpl + +class Renderer: + def __init__(self, width, height): + self.width, self.height = width, height + + # almost all renderers assume 0,0 is left, upper, so we'll flip y here by default + self.affinerenderer = npy.array( + [[width, 0, 0], [0, -height, height], [0, 0, 1]], dtype=npy.float_) + self.pathd = dict() # dict mapping path id -> path instance + + + def add_path(self, pathid, path): + self.pathd[pathid] = path + + def remove_path(self, pathid): + if pathid in self.pathd: + del self.pathd[pathid] + + def render_path(self, pathid): + pass + + + +class RendererAgg(Renderer): + gray = agg.rgba8(128,128,128,255) + white = agg.rgba8(255,255,255,255) + blue = agg.rgba8(0,0,255,255) + black = agg.rgba8(0,0,0,0) + + def __init__(self, width, height): + Renderer.__init__(self, width, height) + + stride = width*4 + self.buf = buf = agg.buffer(width, height, stride) + + self.rbuf = rbuf = agg.rendering_buffer() + rbuf.attachb(buf) + + self.pf = pf = agg.pixel_format_rgba(rbuf) + self.rbase = rbase = agg.renderer_base_rgba(pf) + rbase.clear_rgba8(self.gray) + + # the antialiased renderers + self.renderer = agg.renderer_scanline_aa_solid_rgba(rbase); + self.rasterizer = agg.rasterizer_scanline_aa() + self.scanline = agg.scanline_p8() + self.trans = None + + # the aliased renderers + self.rendererbin = agg.renderer_scanline_bin_solid_rgba(rbase); + self.scanlinebin = agg.scanline_bin() + + + def add_path(self, pathid, path): + self.pathd[pathid] = AggPath(path) + + def render_path(self, pathid): + + + path = self.pathd[pathid] + + if path.antialiased: + renderer = self.renderer + scanline = self.scanline + render_scanlines = agg.render_scanlines_rgba + else: + renderer = self.rendererbin + scanline = self.scanlinebin + render_scanlines = agg.render_scanlines_bin_rgba + + + affine = npy.dot(self.affinerenderer, path.affine) + #print 'display affine:\n', self.affinerenderer + #print 'path affine:\n', path.affine + #print 'product affine:\n', affine + a, b, tx = affine[0] + c, d, ty = affine[1] + aggaffine = agg.trans_affine(a,b,c,d,tx,ty) + transpath = agg.conv_transform_path(path.agg_path, aggaffine) + + renderer.color_rgba8( path.agg_strokecolor ) + if path.fillcolor is not None: + self.rasterizer.add_path(transpath) + renderer.color_rgba8( path.agg_fillcolor ) + render_scanlines(self.rasterizer, scanline, renderer); + + if path.strokecolor is not None: + stroke = agg.conv_stroke_transpath(transpath) + stroke.width(path.linewidth) + self.rasterizer.add_path(stroke) + renderer.color_rgba8( path.agg_strokecolor ) + render_scanlines(self.rasterizer, scanline, renderer); + + + def show(self): + # we'll cheat a little and use pylab for display + + X = npy.fromstring(self.buf.to_string(), npy.uint8) + X.shape = self.height, self.width, 4 + if 1: + import pylab + fig = pylab.figure() + ax = fig.add_axes([0,0,1,1], xticks=[], yticks=[], + frameon=False, aspect='auto') + ax.imshow(X, aspect='auto') + pylab.show() + + class Func: def __call__(self, X): 'transform the numpy array with shape N,2' @@ -62,47 +170,67 @@ """ MOVETO, LINETO, CLOSEPOLY = range(3) - strokecolor = mtraits.color('black') - fillcolor = mtraits.color('blue') - alpha = mtraits.alpha(1.0) - linewidth = mtraits.linewidth(1.0) - antialiased = mtraits.flexible_true_trait - verts= mtraits.verts - codes = mtraits.codes + strokecolor = mtraits.Color('black') + fillcolor = mtraits.Color('blue') + alpha = mtraits.Alpha(1.0) + linewidth = mtraits.Linewidth(1.0) + antialiased = mtraits.FlexibleTrueTrait + pathdata = mtraits.PathData + affine = mtraits.Affine + +mtraits.Path = traits.Trait(Path()) -mtraits.path = traits.Trait(Path()) +class AggPath(Path): + + def __init__(self, path): + self.strokecolor = path.strokecolor + self.fillcolor = path.fillcolor + self.alpha = path.alpha + self.linewidth = path.linewidth + self.antialiased = path.antialiased + self.pathdata = path.pathdata + self.affine = path.affine + -class AggPath: - def __init__(self, path): - """ - Path stored with agg data structs - """ + path.sync_trait('strokecolor', self) + path.sync_trait('fillcolor', self) + path.sync_trait('alpha', self) + path.sync_trait('linewidth', self) + path.sync_trait('antialiased', self) + path.sync_trait('pathdata', self) + path.sync_trait('affine', self) + + def _pathdata_changed(self, olddata, newdata): MOVETO, LINETO, CLOSEPOLY = Path.MOVETO, Path.LINETO, Path.CLOSEPOLY - aggpath = agg.path_storage() - verts = path.verts - codes = path.codes - for i in range(len(verts)): + agg_path = agg.path_storage() + codes, verts = newdata + N = len(codes) + for i in range(N): x, y = verts[i] code = codes[i] if code==MOVETO: - aggpath.move_to(x, y) + agg_path.move_to(x, y) elif code==LINETO: - aggpath.line_to(x, y) + agg_path.line_to(x, y) elif code==CLOSEPOLY: - aggpath.close_polygon() + agg_path.close_polygon() + + self.agg_path = agg_path + + def _fillcolor_changed(self, oldcolor, newcolor): + self.agg_fillcolor = self.color_to_rgba8(newcolor) - self.fillcolor = self.color_to_rgba8(path.fillcolor) - self.strokecolor = self.color_to_rgba8(path.strokecolor) + def _strokecolor_changed(self, oldcolor, newcolor): - self.aggpath = aggpath - self.alpha = float(path.alpha) - self.linewidth = float(path.linewidth) - self.antialiased = bool(path.antialiased) + c = self.color_to_rgba8(newcolor) + #print 'stroke change: old=%s, new=%s, agg=%s, ret=%s'%( + # oldcolor, newcolor, self.agg_strokecolor, c) + self.agg_strokecolor = c + def color_to_rgba8(self, color): if color is None: return None rgba = [int(255*c) for c in color.r, color.g, color.b, color.a] - return agg.rgba8(*rgba) # coordinates: @@ -111,216 +239,84 @@ # to a separable cartesian coordinate, eg for polar is takes r, # theta -> r*cos(theta), r*sin(theta) # -# affineData : an affine 3x3 matrix that takes model output and +# AxesCoords.affineview : an affine 3x3 matrix that takes model output and # transforms it to axes 0,1. We are kind of stuck with the # mpl/matlab convention that 0,0 is the bottom left of the axes, # even though it contradicts pretty much every GUI layout in the # world # -# affineFigure: an affine 3x3 that transforms an axes.view into figure +# AxesCoords.affineaxes: an affine 3x3 that transforms an axesview into figure # 0,1 # -# affineDisplay : takes an affine 3x3 and puts figure view into display. 0, +# Renderer.affinerenderer : takes an affine 3x3 and puts figure view into display. 0, # 0 is left, top, which is the typical coordinate system of most # graphics formats -class Renderer: - def __init__(self, width, height): - self.width, self.height = width, height - # almost all renderers assume 0,0 is left, upper, so we'll flip y here by default - self.displayview = npy.array( - [[width, 0, 0], [0, -height, height], [0, 0, 1]], dtype=npy.float_) - self.pathd = dict() # dict mapping path id -> path instance - - def push_affine(self, affine): - 'set the current affine' - self.affine = npy.dot(self.displayview, affine) +class Rectangle(Path): + facecolor = mtraits.Color('Yellow') + edgecolor = mtraits.Color('Black') + edgewidth = mtraits.Linewidth(1.0) + + def __init__(self, lbwh, **kwargs): - def add_path(self, pathid, path): - self.pathd[pathid] = path + # support some legacy names + self.sync_trait('facecolor', self, 'fillcolor', True) + self.sync_trait('edgecolor', self, 'strokecolor', True) + self.sync_trait('edgewidth', self, 'strokewidth', True) - def remove_path(self, pathid): - if pathid in self.pathd: - del self.pathd[pathid] + for k,v in kwargs.items(): + setattr(self, k, v) - def render_path(self, pathid): - pass - + l,b,w,h = lbwh + t = b+h + r = l+w + verts = npy.array([(l,b), (l,t), (r, t), (r, b), (0,0)], npy.float_) + codes = Path.LINETO*npy.ones(5, npy.uint8) + codes[0] = Path.MOVETO + codes[-1] = Path.CLOSEPOLY + self.pathdata = codes, verts -class RendererAgg(Renderer): - gray = agg.rgba8(128,128,128,255) - white = agg.rgba8(255,255,255,255) - blue = agg.rgba8(0,0,255,255) - def __init__(self, width, height): - Renderer.__init__(self, width, height) - self.aggpathd = dict() # map path ids to AggPaths - stride = width*4 - self.buf = buf = agg.buffer(width, height, stride) +def Alias(name): + return Property(lambda obj: getattr(obj, name), + lambda obj, val: setattr(obj, name, val)) - self.rbuf = rbuf = agg.rendering_buffer() - rbuf.attachb(buf) +class Line(Path): + # aliases for matplotlib compat + color = mtraits.Color('blue') + linewidth = mtraits.Linewidth(1.0) - self.pf = pf = agg.pixel_format_rgba(rbuf) - self.rbase = rbase = agg.renderer_base_rgba(pf) - rbase.clear_rgba8(self.gray) + + def __init__(self, x, y, model=identity, **kwargs): + """ + The model is a function taking Nx2->Nx2. This is where the + nonlinear transformation can be used + """ - # the antialiased renderers - self.renderer = agg.renderer_scanline_aa_solid_rgba(rbase); - self.rasterizer = agg.rasterizer_scanline_aa() - self.scanline = agg.scanline_p8() - self.trans = None + self.sync_trait('color', self, 'strokecolor', True) + self.sync_trait('linewidth', self, 'strokewidth', True) - # the aliased renderers - self.rendererbin = agg.renderer_scanline_bin_solid_rgba(rbase); - self.scanlinebin = agg.scanline_bin() + # probably a better way to do this with traits + for k,v in kwargs.items(): + setattr(self, k, v) - def add_path(self, pathid, path): - Renderer.add_path(self, pathid, path) - self.aggpathd[pathid] = AggPath(path) + X = npy.array([x,y]).T + numrows, numcols = X.shape - def remove_path(self, pathid): - Renderer.remove_path(self, pathid) - if pathid in self.aggpathd: - del self.aggpathd[pathid] + codes = Path.LINETO*npy.ones(numrows, npy.uint8) + codes[0] = Path.MOVETO - def push_affine(self, affine): - 'set the current affine' - Renderer.push_affine(self, affine) - a, b, tx = self.affine[0] - c, d, ty = self.affine[1] - self.trans = agg.trans_affine(a,b,c,d,tx,ty) + verts = model(X) + self.pathdata = codes, verts + self.fillcolor = None - def render_path(self, pathid): - if self.trans is None: - raise RuntimeError('you must first push_affine') - - - - aggpath = self.aggpathd[pathid] - - if aggpath.antialiased: - renderer = self.renderer - scanline = self.scanline - render_scanlines = agg.render_scanlines_rgba - else: - renderer = self.rendererbin - scanline = self.scanlinebin - render_scanlines = agg.render_scanlines_bin_rgba - - renderer.color_rgba8( aggpath.strokecolor ) - transpath = agg.conv_transform_path(aggpath.aggpath, self.trans) - - if aggpath.fillcolor is not None: - self.rasterizer.add_path(transpath) - renderer.color_rgba8( aggpath.fillcolor ) - render_scanlines(self.rasterizer, scanline, renderer); - - stroke = agg.conv_stroke_transpath(transpath) - stroke.width(aggpath.linewidth) - self.rasterizer.add_path(stroke) - renderer.color_rgba8( aggpath.strokecolor ) - render_scanlines(self.rasterizer, scanline, renderer); - - - def show(self): - # we'll cheat a little and use pylab for display - - X = npy.fromstring(self.buf.to_string(), npy.uint8) - X.shape = self.height, self.width, 4 - if 1: - import pylab - fig = pylab.figure() - ax = fig.add_axes([0,0,1,1], xticks=[], yticks=[], - frameon=False, aspect='auto') - ax.imshow(X, aspect='auto') - pylab.show() - - - - - -def rectangle(l, b, w, h, facecolor='yellow', edgecolor='black', - edgewidth=1.0, alpha=1.0): - - t = b+h - r = l+w - verts = npy.array([(l,b), (l,t), (r, t), (r, b), (0,0)], npy.float_) - codes = Path.LINETO*npy.ones(5, npy.uint8) - codes[0] = Path.MOVETO - codes[-1] = Path.CLOSEPOLY - - path = Path() - part.verts = verts - path.codes = codes - path.strokecolor = edgecolor - path.fillcolor = facecolor - path.linewidth = edgewidth - path.alpha = alpha - return path - -def line(x, y, color='black', linewidth=1.0, alpha=1.0, antialiased=True, - model=identity): - X = npy.asarray([x,y]).T - numrows, numcols = X.shape - - codes = Path.LINETO*npy.ones(numrows, npy.uint8) - codes[0] = Path.MOVETO - - path = Path() - path.verts = model(X) - path.codes = codes - path.fillcolor = None - path.strokecolor = color - path.strokewidth = linewidth - path.alpha = alpha - path.antialiased = antialiased - return path - -class AxesCoords(traits.HasTraits): - xviewlim = mtraits.interval - yviewlim = mtraits.interval - affineview = mtraits.affine - affineaxes = mtraits.affine - affine = mtraits.affine - - def _affineview_changed(self, old, new): - print 'affine view changed' - self.affine = npy.dot(self.affineaxes, new) - - def _affineaxes_changed(self, old, new): - print 'affine axes changed' - self.affine = npy.dot(new, self.affineview) - - - def _xviewlim_changed(self, old, new): - print 'xviewlim changed' - xmin, xmax = new - scale = 1./(xmax-xmin) - tx = -xmin*scale - self.affineview[0][0] = scale - self.affineview[0][-1] = tx - self.affine = npy.dot(self.affineaxes, self.affineview) - print '\t', self.affine - - def _yviewlim_changed(self, old, new): - print 'yviewlim changed' - ymin, ymax = new - scale = 1./(ymax-ymin) - ty = -ymin*scale - self.affineview[1][1] = scale - self.affineview[1][-1] = ty - self.affine = npy.dot(self.affineaxes, self.affineview) - print '\t', self.affine - - class Figure: def __init__(self): self.renderer = None @@ -343,9 +339,7 @@ if self.renderer is None: raise RuntimeError('call set_renderer renderer first') - for pathid, path in self.pathd.items(): - print 'path', pathid, path.affine - renderer.push_affine(path.affine) + for pathid in self.pathd: renderer.render_path(pathid) @@ -384,43 +378,94 @@ dtype=npy.float_) -coords1 = AxesCoords() -coords1.affineaxes = affine_axes([0.55, 0.55, 0.4, 0.4]) # upper right quadrant +class AxesCoords(traits.HasTraits): + xviewlim = mtraits.Interval + yviewlim = mtraits.Interval + affineview = mtraits.Affine + affineaxes = mtraits.Affine + affine = mtraits.Affine + + def _affineview_changed(self, old, new): + #print 'affineview changed before:\n', self.affine + self.affine = npy.dot(self.affineaxes, new) + #print 'affineview changed after:\n', self.affine + def _affineaxes_changed(self, old, new): + #print 'affineaxes changed before:\n', self.affine + self.affine = npy.dot(new, self.affineview) + #print 'affineaxes changed after:\n', self.affine + + def _xviewlim_changed(self, old, new): -fig = Figure() + #print 'xviewlim changed before:\n', self.affine + xmin, xmax = new + scale = 1./(xmax-xmin) + tx = -xmin*scale + self.affineview[0][0] = scale + self.affineview[0][-1] = tx + self.affine = npy.dot(self.affineaxes, self.affineview) + #print 'xviewlim changed after:\n', self.affine + + def _yviewlim_changed(self, old, new): + #print 'yviewlim changed before:\n', self.affine + ymin, ymax = new + scale = 1./(ymax-ymin) + ty = -ymin*scale + self.affineview[1][1] = scale + self.affineview[1][-1] = ty + self.affine = npy.dot(self.affineaxes, self.affineview) + #print 'yviewlim changed after:\n', self.affine + x = npy.arange(0, 10, 0.01) y1 = npy.cos(2*npy.pi*x) y2 = 10*npy.exp(-x) -line1 = line(x, y1, color='blue', linewidth=2.0) -line1.sync_trait('affine', coords1) +# the axes rectangle +axrect1 = [0.1, 0.1, 0.4, 0.4] +coords1 = AxesCoords() +coords1.affineaxes = affine_axes(axrect1) +fig = Figure() + +line1 = Line(x, y1, color='blue', linewidth=2.0) +rect1 = Rectangle([0,0,1,1], facecolor='white') +coords1.sync_trait('affine', line1) +coords1.sync_trait('affineaxes', rect1, 'affine') + +fig.add_path(rect1) fig.add_path(line1) -print 'before', line1.affine # update the view limits, all the affines should be automagically updated coords1.xviewlim = 0, 10 coords1.yviewlim = -1.1, 1.1 -print 'after', line1.affine +# the axes rectangle +axrect2 = [0.55, 0.55, 0.4, 0.4] +coords2 = AxesCoords() +coords2.affineaxes = affine_axes(axrect2) -if 0: - coords2 = AxesCoords() - coords2.xviewlim = coords1.xviewlim # share the x axis - coords2.affineaxes = affine_axes([0.1, 0.1, 0.4, 0.4]) # lower left quadrant +r = npy.arange(0.0, 1.0, 0.01) +theta = r*4*npy.pi - line2 = line(x, y2, color='red', linewidth=2.0) - line2.affine = coords2.affine - coords2.yviewlim = 0, 10 - fig.add_path(line2) +line2 = Line(r, theta, model=Polar(), color='#ee8d18', linewidth=2.0) +rect2 = Rectangle([0,0,1,1], facecolor='#d5de9c') +coords2.sync_trait('affine', line2) +coords2.sync_trait('affineaxes', rect2, 'affine') +fig.add_path(rect2) +fig.add_path(line2) -if 0: +# update the view limits, all the affines should be automagically updated +coords2.xviewlim = -1.1, 1.1 +coords2.yviewlim = -1.1, 1.1 + + + +if 1: renderer = RendererAgg(600,400) fig.set_renderer(renderer) fig.draw() Modified: trunk/matplotlib/mpl1/mtraits.py =================================================================== --- trunk/matplotlib/mpl1/mtraits.py 2007-07-19 16:53:36 UTC (rev 3575) +++ trunk/matplotlib/mpl1/mtraits.py 2007-07-19 17:04:19 UTC (rev 3576) @@ -32,12 +32,12 @@ import numpy as npy doprint = True -flexible_true_trait = traits.Trait( +FlexibleTrueTrait = traits.Trait( True, { 'true': True, 't': True, 'yes': True, 'y': True, 'on': True, True: True, 'false': False, 'f': False, 'no': False, 'n': False, 'off': False, False: False } ) -flexible_false_trait = traits.Trait( False, flexible_true_trait ) +FlexibleFalseTrait = traits.Trait( False, FlexibleTrueTrait ) colors = mcolors.cnames @@ -56,9 +56,9 @@ self.g = g self.b = b self.a = a + def __repr__(self): - return 'r,g,b,a = (%1.2f, %1.2f, %1.2f, %1.2f)'%\ - (self.r, self.g, self.b, self.a) + return '(%1.2f, %1.2f, %1.2f, %1.2f)'%(self.r, self.g, self.b, self.a) def tuple_to_rgba(ob, name, val): tup = [float(x) for x in val] @@ -117,17 +117,18 @@ ) -linewidth = traits.Float(0.5) -linestyle = traits.Trait(*linestyles) -color = Color -marker = traits.Trait(*linemarkers) -markersize = traits.Float(6) -antialiased = flexible_true_trait -alpha = traits.Range(0., 1., 0.) -interval = traits.Array('d', (2,), npy.array([0.0, 1.0], npy.float_)) -affine = traits.Array('d', (3,3), +Alpha = traits.Float(1.0) +Linewidth = traits.Float(0.5) +Linestyle = traits.Trait(*linestyles) +Color = Color +Marker = traits.Trait(*linemarkers) +Markersize = traits.Float(6) +Antialiased = FlexibleTrueTrait +Alpha = traits.Range(0., 1., 0.) +Interval = traits.Array('d', (2,), npy.array([0.0, 1.0], npy.float_)) +Affine = traits.Array('d', (3,3), npy.array([[1,0,0],[0,1,0],[0,0,1]], npy.float_)) -verts = traits.Array('d', value=npy.array([[0,0],[0,0]], npy.float_)) -codes = traits.Array('b', value=npy.array([0,0], dtype=npy.uint8)) +Verts = traits.Array('d', value=npy.array([[0,0],[0,0]], npy.float_)) +Codes = traits.Array('b', value=npy.array([0,0], dtype=npy.uint8)) +PathData = traits.Tuple(Codes, Verts) - Modified: trunk/matplotlib/mpl1/scratch.py =================================================================== --- trunk/matplotlib/mpl1/scratch.py 2007-07-19 16:53:36 UTC (rev 3575) +++ trunk/matplotlib/mpl1/scratch.py 2007-07-19 17:04:19 UTC (rev 3576) @@ -1,4 +1,64 @@ +class AggPath(Path): + + agg_fillcolor = mtraits.ColorAgg(RendererAgg.blue) + agg_strokecolor = mtraits.ColorAgg(RendererAgg.black) + agg_path = mtraits.PathAgg + + + def __init__(self, path): + self.strokecolor = path.strokecolor + self.fillcolor = path.fillcolor + self.alpha = path.alpha + self.linewidth = path.linewidth + self.antialiased = path.antialiased + self.pathdata = path.pathdata + self.affine = path.affine + + + path.sync_trait('strokecolor', self) + path.sync_trait('fillcolor', self) + path.sync_trait('alpha', self) + path.sync_trait('linewidth', self) + path.sync_trait('antialiased', self) + path.sync_trait('pathdata', self) + path.sync_trait('affine', self) + + def _pathdata_changed(self, olddata, newdata): + print 'pathdata changed' + MOVETO, LINETO, CLOSEPOLY = Path.MOVETO, Path.LINETO, Path.CLOSEPOLY + agg_path = agg.path_storage() + codes, verts = newdata + N = len(codes) + for i in range(N): + x, y = verts[i] + code = codes[i] + if code==MOVETO: + agg_path.move_to(x, y) + elif code==LINETO: + agg_path.line_to(x, y) + elif code==CLOSEPOLY: + agg_path.close_polygon() + + self.agg_path = agg_path + + def _fillcolor_changed(self, oldcolor, newcolor): + self.agg_fillcolor = self.color_to_rgba8(newcolor) + + def _strokecolor_changed(self, oldcolor, newcolor): + + c = self.color_to_rgba8(newcolor) + print 'stroke change: old=%s, new=%s, agg=%s, ret=%s'%( + oldcolor, newcolor, self.agg_strokecolor, c) + self.agg_strokecolor = c + + + def color_to_rgba8(self, color): + if color is None: return None + rgba = [int(255*c) for c in color.r, color.g, color.b, color.a] + return agg.rgba8(*rgba) + + class Axis(Artist): tickcolor = mtraits.color('black') axiscolor = mtraits.color('black') Modified: trunk/matplotlib/mpl1/test.py =================================================================== --- trunk/matplotlib/mpl1/test.py 2007-07-19 16:53:36 UTC (rev 3575) +++ trunk/matplotlib/mpl1/test.py 2007-07-19 17:04:19 UTC (rev 3576) @@ -1,36 +1,50 @@ -import numpy -from enthought.traits.api import HasTraits, Array, Delegate, Trait +import numpy as npy +import enthought.traits.api as traits -Affine = Array('d', (3,3), - value=numpy.array([[1,0,0], [0,1,0], [0,0,1]], numpy.float_)) -class C(HasTraits): - affine1 = Affine - affine2 = Affine - affine = Affine +class C(traits.HasTraits): + x = traits.Float(0.0) + y = traits.Float(1.0) - def _affine1_changed(self, old, new): - self.affine = numpy.dot(new, self.affine2) +class MyC(C): + xy = traits.Float(0.0) - def _affine2_changed(self, old, new): - self.affine = numpy.dot(self.affine1, new) + def __init__(self, c): + self.x = c.x + self.y = c.y + c.sync_trait('x', self) + c.sync_trait('y', self) -class D(HasTraits): - affine = Delegate('c') - c = Trait(C) + def _x_changed(self, old, new): + self.xy = self.x * self.y - + def _y_changed(self, old, new): + self.xy = self.x * self.y + + +# C objects are created at top level c = C() -d = D() -d.affine = c.affine +c.x = 1 +c.y = 1 -print 'before c', type(c.affine), c.affine -print 'before d', type(d.affine), d.affine -c.affine1 = numpy.random.rand(3,3) -print 'after c', type(c.affine), c.affine -print 'after d', type(d.affine), d.affine +class Backend: + + def register_c(self, c): + # only gets C objects after creation + self.myc = MyC(c) + +backend = Backend() + +backend.register_c(c) + +c.x = 4 + +print backend.myc.xy + + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |