From: <jd...@us...> - 2007-07-18 21:30:16
|
Revision: 3567 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3567&view=rev Author: jdh2358 Date: 2007-07-18 14:30:12 -0700 (Wed, 18 Jul 2007) Log Message: ----------- playing around with mpl1 api Modified Paths: -------------- trunk/matplotlib/mpl1/mpl1.py trunk/matplotlib/mpl1/mtraits.py Added Paths: ----------- trunk/matplotlib/mpl1/scratch.py trunk/matplotlib/mpl1/test.py Modified: trunk/matplotlib/mpl1/mpl1.py =================================================================== --- trunk/matplotlib/mpl1/mpl1.py 2007-07-18 20:38:32 UTC (rev 3566) +++ trunk/matplotlib/mpl1/mpl1.py 2007-07-18 21:30:12 UTC (rev 3567) @@ -1,5 +1,4 @@ -from matplotlib.enthought.traits import HasTraits -import matplotlib.enthought.traits as traits +import enthought.traits.api as traits from matplotlib import agg import numpy as npy @@ -54,7 +53,7 @@ identity = Identity() -class Path(HasTraits): +class Path(traits.HasTraits): """ The path is an object that talks to the backends, and is an intermediary between the high level path artists like Line and @@ -102,6 +101,7 @@ 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: @@ -178,7 +178,7 @@ self.scanlinebin = agg.scanline_bin() def add_path(self, pathid, path): - pathid = Renderer.add_path(self, pathid, path) + Renderer.add_path(self, pathid, path) self.aggpathd[pathid] = AggPath(path) def remove_path(self, pathid): @@ -274,6 +274,7 @@ path.verts = model(X) path.codes = codes path.fillcolor = None + path.strokecolor = color path.strokewidth = linewidth path.alpha = alpha path.antialiased = antialiased @@ -281,43 +282,49 @@ -class AxesCoords(HasTraits): +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): - self.affine = npy.dot( - npy.dot(self.affineaxes, new), self.affinedata) + print 'affine view changed' + self.affine = npy.dot(self.affineaxes, new) def _affineaxes_changed(self, old, new): - self.affine = npy.dot( - npy.dot(new, self.affineview), self.affinedata) + 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 self._pathid = 0 - self._pathd = dict() + self.pathd = dict() def add_path(self, path): id_ = self._pathid @@ -336,6 +343,7 @@ raise RuntimeError('call set_renderer renderer first') for pathid, path in self.pathd.items(): + print 'path', pathid, path.affine renderer.push_affine(path.affine) renderer.render_path(pathid) @@ -374,25 +382,12 @@ [0,0,1]], dtype=npy.float_) -xlim = mtraits.interval() -ylim1 = mtraits.interval() -ylim2 = mtraits.interval() -affineaxes = affine_axes([0.1, 0.1, 0.4, 0.4]) # lower, left quadrant - coords1 = AxesCoords() -coords1.xlim = xlim -coords1.ylim = ylim1 -print 'typedata', affineaxes.shape, affineaxes.dtype -coords1.affineaxes = affineaxes +coords1.affineaxes = affine_axes([0.55, 0.55, 0.4, 0.4]) # upper right quadrant -coords2 = AxesCoords() -coords2.xlim = xlim -coords2.ylim = ylim2 -coords2.affineaxes = affineaxes - fig = Figure() x = npy.arange(0, 10, 0.01) @@ -400,22 +395,32 @@ y2 = 10*npy.exp(-x) line1 = line(x, y1, color='blue', linewidth=2.0) -line1.affine = coords1.affime +line1.affine = coords1.affine -line2 = line(x, y2, color='red', linewidth=2.0) -line2.affine = coords1.affime - fig.add_path(line1) -fig.add_path(line2) +print 'before', line1.affine # update the view limits, all the affines should be automagically updated -xlim = 0,10 -ylim1 = -1.1, 1.1 -ylim2 = 0, 10 +coords1.xviewlim = 0, 10 +coords1.yviewlim = -1.1, 1.1 +print 'after', line1.affine -renderer = RendererAgg(600,400) -fig.set_renderer(renderer) -fig.draw() -print 'renderer affine', renderer.affine -renderer.show() + +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 + + + line2 = line(x, y2, color='red', linewidth=2.0) + line2.affine = coords2.affine + coords2.yviewlim = 0, 10 + fig.add_path(line2) + + +if 0: + renderer = RendererAgg(600,400) + fig.set_renderer(renderer) + fig.draw() + renderer.show() Modified: trunk/matplotlib/mpl1/mtraits.py =================================================================== --- trunk/matplotlib/mpl1/mtraits.py 2007-07-18 20:38:32 UTC (rev 3566) +++ trunk/matplotlib/mpl1/mtraits.py 2007-07-18 21:30:12 UTC (rev 3567) @@ -1,3 +1,17 @@ +""" +Install instructions for traits 2.0 + + rm -rf ~/dev/lib/python2.4/site-packages/enthought.* + + easy_install --install-dir=~/dev/lib/python2.4/site-packages --prefix=~/dev -f http://code.enthought.com/enstaller/eggs/source/unstable/ enthought.etsconfig enthought.util enthought.debug + + svn co https://svn.enthought.com/svn/enthought/branches/enthought.traits_2.0 enthought_traits + + cd enthought_traits/ + python setup.py install --prefix=~/dev + + +""" # Here is some example code showing how to define some representative # rc properties and construct a matplotlib artist using traits. # Because matplotlib ships with enthought traits already, you can run @@ -7,7 +21,7 @@ # below. import sys, os, re -import matplotlib.enthought.traits as traits +import enthought.traits.api as traits from matplotlib.cbook import is_string_like from matplotlib import colors as mcolors import numpy as npy @@ -86,7 +100,7 @@ def path_exists(ob, name, val): os.path.exists(val) -linestyles = ('-', '--', '-.', ':', 'steps', 'None') +linestyles = ('-', '--', '-.', ':', 'steps') TICKLEFT, TICKRIGHT, TICKUP, TICKDOWN = range(4) linemarkers = (None, '.', ',', 'o', '^', 'v', '<', '>', 's', '+', 'x', 'd', 'D', '|', '_', 'h', 'H', @@ -95,7 +109,7 @@ TICKRIGHT, TICKUP, TICKDOWN, - 'None') + ) linewidth = traits.Float(0.5) @@ -105,9 +119,10 @@ markersize = traits.Float(6) antialiased = flexible_true_trait alpha = traits.Range(0., 1., 0.) -interval = traits.Array('d', (2,)) -affine = traits.Array('d', (3,3)) -verts = traits.Array('d') -codes = traits.Array('b') +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)) Added: trunk/matplotlib/mpl1/scratch.py =================================================================== --- trunk/matplotlib/mpl1/scratch.py (rev 0) +++ trunk/matplotlib/mpl1/scratch.py 2007-07-18 21:30:12 UTC (rev 3567) @@ -0,0 +1,150 @@ + +class Axis(Artist): + tickcolor = mtraits.color('black') + axiscolor = mtraits.color('black') + tickwidth = mtraits.linewidth(0.5) + viewlim = mtraits.interval + tickpath = mtraits.path + axispath = mtraits.path + + def __init__(self, figure): + self.figure = figure + self.pathids = set() + +class XAxis(Axis): + def __init__(self, figure, **kwargs): + Axis.__init__(self, figure, **kwargs) + + def set_ticks(self, yloc, ysize, ticks, fmt): + # we'll deal with locators, formatter and autoscaling later... + # todo, remove old paths + + for pathid in self.pathids: + self.figure.remove_path(pathid) + + codes = [] + verts = [] + tickmin = yloc-ysize/2. + tickmax = yloc+ysize/2. + for tick in ticks: + codes.append(Path.MOVETO) + verts.append((tick, tickmin)) + codes.append(Path.LINETO) + verts.append((tick, tickmax)) + + + path = Path() + path.verts = npy.array(verts) + path.codes = npy.array(codes) + path.strokecolor = self.tickcolor + path.fillcolor = None + path.linewidth = self.tickwidth + path.antialiased = False + + self.pathids.add(self.figure.add_path(path)) + + + xmin, xmax = self.viewlim + + # the axis line + codes = [] + verts = [] + codes.append(Path.MOVETO) + verts.append((xmin, yloc)) + codes.append(Path.LINETO) + verts.append((xmax, yloc)) + + path = Path() + path.verts = npy.array(verts) + path.codes = npy.array(codes) + path.strokecolor = self.axiscolor + path.fillcolor = None + path.antialiased = False + + self.pathids.add(self.figure.add_path(path)) + + +class YAxis: + def __init__(self, figure): + Axis.__init__(self, figure) + + def set_ticks(self, xloc, xsize, ticks, fmt): + + for pathid in self.pathids: + self.figure.remove_path(pathid) + + codes = [] + verts = [] + tickmin = yloc-ysize/2. + tickmax = yloc+ysize/2. + for tick in ticks: + codes.append(Path.MOVETO) + verts.append((tickmin, tick)) + codes.append(Path.LINETO) + verts.append((tickmax, tick)) + + + self.tickpath = path = Path() + path.verts = npy.array(verts) + path.codes = npy.array(codes) + path.strokecolor = self.tickcolor + path.fillcolor = None + path.linewidth = self.tickwidth + path.antialiased = False + + self.pathids.add(self.figure.add_path(path)) + + + ymin, ymax = self.viewlim + + # the axis line + codes = [] + verts = [] + codes.append(Path.MOVETO) + verts.append((xloc, ymin)) + codes.append(Path.LINETO) + verts.append((xloc, ymax)) + + self.axispath = path = Path() + path.verts = npy.array(verts) + path.codes = npy.array(codes) + path.strokecolor = self.axiscolor + path.fillcolor = None + path.antialiased = False + + self.pathids.add(self.figure.add_path(path)) + + + + + + +if 0: + ax1.set_ylim(-1.1, 1.1) + + xaxis = XAxis(ax1) + xaxis.set_ticks(0, 0.1, npy.arange(11.0), '%d') + + yaxis1 = YAxis(ax1) + yaxis1.set_ticks(-1.1, 0.2, npy.arange(-1.0, 1.1, 0.5), '%d') + yaxis1.axiscolor = line1.color + + yaxis2 = YAxis(ax1) + yaxis2.set_ticks(5.0, 0.2, npy.arange(-1.0, 1.1, 0.5), '%d') + + + + + + theta = 0.25*npy.pi # 45 degree axes rotation + #rotate_axes(ax1, theta) + + + r = npy.arange(0, 1, 0.01) + theta = r*4*npy.pi + X2 = npy.array([r,theta]).T + line2 = Line(X2, model=Polar()) + ax2.add_line(line2) + # currently cartesian + ax2.set_xlim(-1,1) + ax2.set_ylim(-1,1) Added: trunk/matplotlib/mpl1/test.py =================================================================== --- trunk/matplotlib/mpl1/test.py (rev 0) +++ trunk/matplotlib/mpl1/test.py 2007-07-18 21:30:12 UTC (rev 3567) @@ -0,0 +1,15 @@ +import numpy +from enthought.traits.api import HasTraits, Array +import mtraits + + +class Path(HasTraits): + """ + The path is an object that talks to the backends, and is an + intermediary between the high level path artists like Line and + Polygon, and the backend renderer + """ + strokecolor = mtraits.color('white') + +p = Path() +print 'strokecolor', p.strokecolor This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2007-07-19 02:40:18
|
Revision: 3569 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3569&view=rev Author: jdh2358 Date: 2007-07-18 19:40:15 -0700 (Wed, 18 Jul 2007) Log Message: ----------- added design goals doc Modified Paths: -------------- trunk/matplotlib/mpl1/mpl1.py trunk/matplotlib/mpl1/mtraits.py Added Paths: ----------- trunk/matplotlib/mpl1/DESIGN_GOALS Added: trunk/matplotlib/mpl1/DESIGN_GOALS =================================================================== --- trunk/matplotlib/mpl1/DESIGN_GOALS (rev 0) +++ trunk/matplotlib/mpl1/DESIGN_GOALS 2007-07-19 02:40:15 UTC (rev 3569) @@ -0,0 +1,116 @@ +Here are some of the things I would like to accomplish with mpl1. Any +and all of this is open to discussion. What I present below is pretty +ambitious, so if there is support, we will need significant +contributions from several developers for several months. Ideally, we +would get a good sketch working, and then organize a spint (4 days?) +for late August, where we try get as far as possible to making this +viable. + += data copying = + +Push the data to the backend only once, or only when required. update +the transforms to the backend, but do not push transformed data on +every draw. This is potentially a major win, because we currently +move the data around on every draw + + += transformations = + +Support a normal transformation architecture. The current draft +implmentation assumes one nonlinear transformation, which happens at a +high layer, and all transformations after that are affines. Currently +there are two affines: the transformation from view limits -> axes +units, the transformation from axes units to normalized figure untis, +and the transformation from normalized figure units to display + +do we want to use 3x3 or 4x4 to leave the door open for 3D developers? + += objects that talk to the backend "primitives" = + +Have just a few, fairly rich obects the backends need to understand. +clear candidates are a Path, Text and Image. Each of these will carry +their metadata, eg a path will carry its stroke color, facecolor, +linewidth, etc.. Text will carry its font size, color, etc. We may +need some optimizations down the road, but start small. For now, +let's call these objects primitives + += where do the plot functions live? = + +In matplotlib, the plot functions are axes methods and this is a poor +design. Where should these live, what should they create, etc? + += how much of an intermediate artist layer do we need = + +Do we want to create high level objects like Circle, Rectangle and +Line, each of which manage a Path object under the hood? Probably. +By using traits properly here, these will be thin interfaces around +one of our primitives. + += z-ordering, containers, etc = + +Peter has been doing a lot of nice work on z-order and layers and +stuff like that for chaco, stuff that looks really useful for picking, +interactive, etc... We should look at their approach, and think +carefully about how this should be handled. Paul is a good candidate +for this. + += extension code = + +I would like to shed all of the CXX extension code -- it is just too +small a nitch of the python world to base our proect on. SWIG is +pretty clearly the right choice. mpl1 will use numpy for +transformations with some carefully chosen extension code where +necessary, so this gets rid of _transforms.cpp. I also plan to use +the SWIG agg wrapper, so this gets rid of _backend_agg. If we can +enhance the SWIG agg wrapper, we can also do images through here. +Having a fully featured python agg wrapper will be a plus. But with +the agg license change, I'm open to discussion of alternatives. + +I want to do away with *all* GUI extension code. This should live +outside MPL, eg in a toolkit, if we need it. This means someone +(Michael is probably a good choice) needs to figure out how to get tk +talking to a python buffer or numpy array. Maintaining the GUI +extension code is a drag. + += traits = + +I think we should make a major committment to traits and use them from +the ground up. w/o the UI stuff, they add plenty to make them +worthwhile. With the UI (wx only) , they are a major win for GUI +developers. + += axis handling = + +The whole conception of the Axes needs to be reworked, in light of the +fact that we need to support multiple axis objects on one Axes. This +will require a fair amount of thought, but we should aim for +supporting an arbitrary number of axis obects, presumably associated +with individual artists or primitives, on each Axes. They also need +to be *much* faster. matplotlib uses Artists for each tick, tickline, +gridline, ticklabel, etc, and this is mind-numbingsly slow. + += breakage = + +I think we need to be prepared to break the hell out of this thing. +The API will basically be a total rewrite. pylab will still mostly +work unchanged -- that is the beauty of pylab. We'll probably want to +install into a new namespace, eg mpl, and envision both matplotlib and +mpl co-existing for some time. In fact, mpl might depend on +matplotlib for a while (eg until a CXX free ft2font is available) + +We should expect to be supporting and using matplotlib for a long +time, since the proposals discussed here imply that it will be a long +wait until mpl1 is feature complete with matplotlib. In fact, we could +rightly consider this to be the mpl2 proposal, and keep releaseing +matplotlib ehancements to 1.0 and beyond w/o signfificant breakage. +It's a nominal difference so I don't really have a preference. + += chaco and kiva = + +This is probably a good idea for an enterprising developer to take a +careful look at Chaco and Kiva to see if we can integrate with them. +I am gunshy because they seem formiddable and complex, and one of my +maor goals here is to streamline and simplify, but they are incredible +pieces of work and we need to consider them, especially if we +integrate other parts of the enthought suite into our core, eg traits + Modified: trunk/matplotlib/mpl1/mpl1.py =================================================================== --- trunk/matplotlib/mpl1/mpl1.py 2007-07-18 21:52:01 UTC (rev 3568) +++ trunk/matplotlib/mpl1/mpl1.py 2007-07-19 02:40:15 UTC (rev 3569) @@ -1,3 +1,4 @@ +# see install instructions for enthrought traits2 in mtraits import enthought.traits.api as traits from matplotlib import agg @@ -395,7 +396,7 @@ y2 = 10*npy.exp(-x) line1 = line(x, y1, color='blue', linewidth=2.0) -line1.affine = coords1.affine +line1.sync_trait('affine', coords1) fig.add_path(line1) Modified: trunk/matplotlib/mpl1/mtraits.py =================================================================== --- trunk/matplotlib/mpl1/mtraits.py 2007-07-18 21:52:01 UTC (rev 3568) +++ trunk/matplotlib/mpl1/mtraits.py 2007-07-19 02:40:15 UTC (rev 3569) @@ -1,14 +1,19 @@ """ Install instructions for traits 2.0 + # blow away old enthought rm -rf ~/dev/lib/python2.4/site-packages/enthought.* - easy_install --install-dir=~/dev/lib/python2.4/site-packages --prefix=~/dev -f http://code.enthought.com/enstaller/eggs/source/unstable/ enthought.etsconfig enthought.util enthought.debug + # get easy_install, if necessary + wget http://peak.telecommunity.com/dist/ez_setup.py + sudo python sez_setup.py + sudo easy_install -f http://code.enthought.com/enstaller/eggs/source/unstable/ enthought.etsconfig enthought.util enthought.debug + svn co https://svn.enthought.com/svn/enthought/branches/enthought.traits_2.0 enthought_traits cd enthought_traits/ - python setup.py install --prefix=~/dev + sudo python setup.py install """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
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. |
From: <jd...@us...> - 2007-07-20 13:44:13
|
Revision: 3586 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3586&view=rev Author: jdh2358 Date: 2007-07-20 06:44:10 -0700 (Fri, 20 Jul 2007) Log Message: ----------- traits cleanup Modified Paths: -------------- trunk/matplotlib/mpl1/mpl1.py trunk/matplotlib/mpl1/test.py Removed Paths: ------------- trunk/matplotlib/mpl1/mtraits.py Modified: trunk/matplotlib/mpl1/mpl1.py =================================================================== --- trunk/matplotlib/mpl1/mpl1.py 2007-07-20 13:21:42 UTC (rev 3585) +++ trunk/matplotlib/mpl1/mpl1.py 2007-07-20 13:44:10 UTC (rev 3586) @@ -2,9 +2,57 @@ import enthought.traits.api as traits from matplotlib import agg +from matplotlib import colors as mcolors import numpy as npy -import mtraits # some handy traits for mpl + +class ColorHandler(traits.TraitHandler): + is_mapped = True + + def post_setattr(self, object, name, value): + object.__dict__[ name + '_' ] = self.mapped_value( value ) + + def mapped_value(self, value ): + if value is None: return None + return mcolors.colorConverter.to_rgba(value) + + + def validate(self, object, name, value): + try: + self.mapped_value(value) + except ValueError: + return self.error(object, name, value) + else: + return value + + def info(self): + return """\ +any valid matplotlib color, eg an abbreviation like 'r' for red, a full +name like 'orange', a hex color like '#efefef', a grayscale intensity +like '0.5', or an RGBA tuple (1,0,0,1)""" + +class MTraitsNamespace: + DPI = traits.Float(72.) + Affine = traits.Array('d', (3,3), npy.array([[1,0,0],[0,1,0],[0,0,1]], npy.float_)) + Alpha = traits.Range(0., 1., 0.) + AntiAliased = traits.true + Codes = traits.Array('b', value=npy.array([0,0], dtype=npy.uint8)) + Color = traits.Trait('black', ColorHandler()) + DPI = traits.Float(72.) + Interval = traits.Array('d', (2,), npy.array([0.0, 1.0], npy.float_)) + LineStyle = traits.Trait('-', '--', '-.', ':', 'steps', None) + LineWidth = traits.Float(1.0) + Marker = traits.Trait(None, '.', ',', 'o', '^', 'v', '<', '>', 's', + '+', 'x', 'd', 'D', '|', '_', 'h', 'H', + 'p', '1', '2', '3', '4') + MarkerSize = traits.Float(6) + Verts = traits.Array('d', value=npy.array([[0,0],[0,0]], npy.float_)) + PathData = traits.Tuple(Codes, Verts) + Visible = traits.true + + +mtraits = MTraitsNamespace() + def affine_axes(rect): 'make an affine for a typical l,b,w,h axes rectangle' @@ -35,7 +83,7 @@ dtype=npy.float_) -class Renderer: +class Renderer(traits.HasTraits): dpi = traits.Float(72.) def __init__(self, width, height): @@ -161,7 +209,7 @@ Locs = npy.dot(affineverts, Locs) - dpiscale = 1.0 # self.dpi/72. # for some reason this is broken + dpiscale = self.dpi/72. # for some reason this is broken # this will need to be highly optimized and hooked into some # extension code using cached marker rasters as we now do in # _backend_agg @@ -210,15 +258,16 @@ class Func(traits.HasTraits): def __call__(self, X): 'transform the numpy array with shape N,2' - raise NotImplementedError + return X def invert(self, x, y): 'invert the point x, y' - raise NotImplementedError + return x, y def point(self, x, y): 'transform the point x, y' - raise NotImplementedError + return x, y + class Identity(Func): def __call__(self, X): @@ -252,7 +301,7 @@ raise NotImplementedError -mtraits.Model = traits.Trait(None, Identity, Polar) +mtraits.Model = traits.Instance(Func, ()) @@ -268,7 +317,7 @@ fillcolor = mtraits.Color('blue') alpha = mtraits.Alpha(1.0) linewidth = mtraits.LineWidth(1.0) - antialiased = mtraits.FlexibleTrueTrait() + antialiased = mtraits.AntiAliased pathdata = mtraits.PathData() affine = mtraits.Affine() @@ -309,8 +358,8 @@ # hmm, I would have thought these would be called by the attr # setting above self._pathdata_changed(None, self.pathdata) - self._fillcolor_changed(None, self.fillcolor) - self._strokecolor_changed(None, self.strokecolor) + self._fillcolor__changed(None, self.fillcolor_) + self._strokecolor__changed(None, self.strokecolor_) @staticmethod @@ -334,10 +383,10 @@ self.agg_path = AggPath.make_agg_path(newdata) - def _fillcolor_changed(self, oldcolor, newcolor): + def _fillcolor__changed(self, oldcolor, newcolor): self.agg_fillcolor = self.color_to_rgba8(newcolor) - def _strokecolor_changed(self, oldcolor, newcolor): + def _strokecolor__changed(self, oldcolor, newcolor): c = self.color_to_rgba8(newcolor) self.agg_strokecolor = c @@ -345,7 +394,7 @@ 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] + rgba = [int(255*c) for c in color] return agg.rgba8(*rgba) class Markers(traits.HasTraits): @@ -405,8 +454,8 @@ class Artist(traits.HasTraits): zorder = traits.Float(1.0) - alpha = mtraits.Alpha(1.0) - visible = mtraits.FlexibleTrueTrait() + alpha = mtraits.Alpha() + visible = mtraits.Visible() affine = mtraits.Affine() def __init__(self): @@ -427,7 +476,7 @@ class Line(Artist): linestyle = mtraits.LineStyle('-') - antialiased = mtraits.FlexibleTrueTrait(True) + antialiased = mtraits.AntiAliased() color = mtraits.Color('blue') linewidth = mtraits.LineWidth(1.0) marker = mtraits.Marker(None) Deleted: trunk/matplotlib/mpl1/mtraits.py =================================================================== --- trunk/matplotlib/mpl1/mtraits.py 2007-07-20 13:21:42 UTC (rev 3585) +++ trunk/matplotlib/mpl1/mtraits.py 2007-07-20 13:44:10 UTC (rev 3586) @@ -1,135 +0,0 @@ -""" -Install instructions for traits 2.0 - - # blow away old enthought - rm -rf ~/dev/lib/python2.4/site-packages/enthought.* - - # get easy_install, if necessary - wget http://peak.telecommunity.com/dist/ez_setup.py - sudo python sez_setup.py - - sudo easy_install -f http://code.enthought.com/enstaller/eggs/source/unstable "enthought.etsconfig < 3.0a" "enthought.util <3.0a" "enthought.debug <3.0a" - - svn co https://svn.enthought.com/svn/enthought/branches/enthought.traits_2.0 enthought_traits - - cd enthought_traits/ - sudo python setup.py install - - -""" -# Here is some example code showing how to define some representative -# rc properties and construct a matplotlib artist using traits. -# Because matplotlib ships with enthought traits already, you can run -# this script with just matplotlib. Unfortunately, we do not ship the -# ex UI component so you can't test that part. I'm a bit of a traits -# newbie so there are probably better ways to do what I have done -# below. - -import sys, os, re -import enthought.traits.api as traits -from matplotlib.cbook import is_string_like -from matplotlib import colors as mcolors -import numpy as npy - -doprint = True -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 - } ) -FlexibleFalseTrait = traits.Trait( False, FlexibleTrueTrait ) - -colors = mcolors.cnames - -def hex2color(s): - "Convert hex string (like html uses, eg, #efefef) to a r,g,b tuple" - return tuple([int(n, 16)/255.0 for n in (s[1:3], s[3:5], s[5:7])]) - -def color_converter(x): - return mcolors.colorConverter(x) -class RGBA(traits.HasTraits): - # r,g,b,a in the range 0-1 with default color 0,0,0,1 (black) - r = traits.Range(0., 1., 0.) - g = traits.Range(0., 1., 0.) - b = traits.Range(0., 1., 0.) - a = traits.Range(0., 1., 1.) - def __init__(self, r=0., g=0., b=0., a=1.): - self.r = r - self.g = g - self.b = b - self.a = a - - def __repr__(self): - 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] - if len(tup)==3: - r,g,b = tup - return RGBA(r,g,b) - elif len(tup)==4: - r,g,b,a = tup - return RGBA(r,g,b,a) - else: - raise ValueError -tuple_to_rgba.info = 'a RGB or RGBA tuple of floats' - -def hex_to_rgba(ob, name, val): - rgx = re.compile('^#[0-9A-Fa-f]{6}$') - - if not is_string_like(val): - raise TypeError - if rgx.match(val) is None: - raise ValueError - r,g,b = hex2color(val) - return RGBA(r,g,b,1.0) -hex_to_rgba.info = 'a hex color string' - -def colorname_to_rgba(ob, name, val): - hex = colors[val.lower()] - r,g,b = hex2color(hex) - return RGBA(r,g,b,1.0) -colorname_to_rgba.info = 'a named color' - -def float_to_rgba(ob, name, val): - val = float(val) - return RGBA(val, val, val, 1.) -float_to_rgba.info = 'a grayscale intensity' - - - -def file_exists(ob, name, val): - fh = file(val, 'r') - return val - -def path_exists(ob, name, val): - os.path.exists(val) -linestyles = ('-', '--', '-.', ':', 'steps', None) -TICKLEFT, TICKRIGHT, TICKUP, TICKDOWN = range(4) -linemarkers = (None, '.', ',', 'o', '^', 'v', '<', '>', 's', - '+', 'x', 'd', 'D', '|', '_', 'h', 'H', - 'p', '1', '2', '3', '4', - TICKLEFT, - TICKRIGHT, - TICKUP, - TICKDOWN, - ) - -colorfuncs = RGBA(), float_to_rgba, colorname_to_rgba, RGBA, hex_to_rgba, tuple_to_rgba, None - -Affine = traits.Array('d', (3,3), npy.array([[1,0,0],[0,1,0],[0,0,1]], npy.float_)) -Alpha = traits.Float(1.0) -Alpha = traits.Range(0., 1., 0.) -Antialiased = FlexibleTrueTrait -Codes = traits.Array('b', value=npy.array([0,0], dtype=npy.uint8)) -Color = traits.Trait(*colorfuncs) -DPI = traits.Float(72.) -Interval = traits.Array('d', (2,), npy.array([0.0, 1.0], npy.float_)) -LineStyle = traits.Trait(*linestyles) -LineWidth = traits.Float(0.5) -Marker = traits.Trait(*linemarkers) -MarkerSize = traits.Float(6) -Verts = traits.Array('d', value=npy.array([[0,0],[0,0]], npy.float_)) -PathData = traits.Tuple(Codes, Verts) - - Modified: trunk/matplotlib/mpl1/test.py =================================================================== --- trunk/matplotlib/mpl1/test.py 2007-07-20 13:21:42 UTC (rev 3585) +++ trunk/matplotlib/mpl1/test.py 2007-07-20 13:44:10 UTC (rev 3586) @@ -1,50 +1,19 @@ -import numpy as npy -import enthought.traits.api as traits +from enthought.traits.api import * +def Alias(name): + return Property(lambda obj: getattr(obj, name), + lambda obj, val: setattr(obj, name, val)) -class C(traits.HasTraits): - x = traits.Float(0.0) - y = traits.Float(1.0) +class Path(HasTraits): + strokecolor = Color() -class MyC(C): - xy = traits.Float(0.0) - def __init__(self, c): - self.x = c.x - self.y = c.y +class Line(Path): + color = Alias('strokecolor') - c.sync_trait('x', self) - c.sync_trait('y', self) - - 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() -c.x = 1 -c.y = 1 - - - - - -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 - - - + def __init__(self, x, color='red'): + self.x = x + self.color = color + +line = Line(1) +print line.strokecolor This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |