Interesting ! The lack of proper 3D plotting in scipy is a major problem in my eyes.
I would like to point out tvtk ( http://scipy.org/Cookbook/MayaVi/tvtk) that is a great framework for developing 3D plotting tools in python. One example is the new version of the famous Mayavi, but something "command line driven", like pylab, can be easily implemented, as the mlab module ( http://scipy.org/Cookbook/MayaVi/mlab ) demonstrates. These rely on the ETS (enthought tool suite) which is currently a very haevy dependency if you are not using the enthought python distribution, but enthought is working on repackaging this as eggs. I think that using tvtk as a backend will allow faster development than raw OpenGL, and code reuse with Mayavi2 and Co. A lot of very well thought work has gone in tvtk and it needs little work to come out as a useful plotting package. I coded such a package in a quick and dirty way for myself and have always wanted to find the time to polish it and propose its integration to tvtk. I send it as an example of what one can do in an afternoon with tvtk. (see https://mail.enthought.com/pipermail/enthought-dev/2006-July/002140.html for a discussion of this module) Best regards, Gaƫl ************************************************ import os os.environ['NUMERIX'] = 'numpy' from scipy import arange, ravel, amax, amin, zeros, column_stack, sqrt, ones from enthought.tvtk.tools import mlab class figure3d: """ A window for displaying 3D objects """ title = '' xlabel = 'x' ylabel = 'y' zlabel = 'z' objects = [] background = (1.0,1.0,1.0) foreground = (0.0,0.0,0.0) fig = None def update(self): """Updates the figure""" if self.fig: hasTitle=0 # Update the title for object in self.fig.objects: if str(type(object))=="<class 'enthought.tvtk.tools.mlab.Title'>": object.text = self.title object.text_actor.property.color=self.foreground hasTitle=1 if not self.title == '' and not hasTitle: t=mlab.Title() t.text=self.title t.text_actor.property.color=self.foreground self.fig.add(t) # Update the labels self.fig.objects[0].axis.x_label=self.xlabel self.fig.objects[0].axis.y_label=self.ylabel self.fig.objects[0].axis.z_label=self.zlabel # Update the colors self.fig.renwin.background=self.background for object in self.fig.objects[0].actors: object.property.color=self.foreground self.fig.renwin.render() def show(self): """ Shows the figure, if not already displayed """ if not self.fig: self.fig = mlab.figure(browser=False) self.fig.renwin.x_plus_view() self.fig.renwin.camera.azimuth(-62) self.fig.renwin.camera.elevation(19.5) self.update() def surf(self,z, transparency=0.0, transparent=0): """ Plot a 3d surface from a 2D array """ y=arange(0,z.shape[0]) x=arange(0,z.shape[1]) # Flatten the matrix z=ravel(z) Zmax=amax(z)-amin(z) XYmax=amax((amax(y)-amin(y),amax(x)-amin(y))) Zscale=XYmax/float(Zmax)*0.5 s=mlab.SurfRegular(x,y,z,scale=[1.0,1.0,Zscale]) s.scalar_bar.title='' s.show_scalar_bar=True s.scalar_bar.orientation="horizontal" s.scalar_bar.property.color=self.foreground # LUT means "Look-Up Table", it give the mapping between scalar value and # color s.lut_type='blue-red' transparency=1.0-transparency s.lut.alpha=transparency s.lut.alpha_range=(transparency,transparency) if transparent: s.lut.alpha_range=(0.0,1.0) if not self.fig: self.show() # Scale properly the box outline self.fig.objects[0].axis.set_ranges((amin(x),amax(x),amin(y),amax(y),amin(z),amax(z))) self.fig.objects[0].axis.use_ranges=1 self.fig.add(s) def plot3(self, x, y, z, color=(0,0.5,1.0), linewidth=1): """ Plot a 3D line from 3 sets of coordinates """ assert len(x)== len(y) and len(y)==len(z), "x,y,z must have same number of coordinates" x=ravel(x) y=ravel(y) z=ravel(z) size=max((amax(x)-amin(x),amax(y)-amin(y),amax(z)-amin(z))) pts = zeros((len(x), 3), 'd') pts[:,0], pts[:,1], pts[:,2] = x, y, z linewidth=0.05*linewidth/size l = mlab.Line3(pts,color=color, radius=linewidth) if not self.fig: self.show() self.fig.add(l) def edit_traits(self): self.fig.edit_traits() def quiver3d(self, x, y, z, vx, vy, vz, scalars=None, color=None, autoscale=1): """ Displays a plot of arrows located at x, y, z, and of coordinates vx, vy, vz""" assert len(x) == len(y) and len(y) == len(z) and len(z)== len(vx) and len(vx)==len(vy) and len(vy)==len(vz), "coordinate vectors must be of same length" x=ravel(x) y=ravel(y) z=ravel(z) vx=ravel(vx) vy=ravel(vy) vz=ravel(vz) positions = column_stack((x,y,z)) norms = vx**2 + vy**2 + vz**2 norms = sqrt(norms.astype(float)) normsmax = amax(norms) if autoscale: vx=vx.astype(float)/normsmax vy=vy.astype(float)/normsmax vz=vz.astype(float)/normsmax vectors = column_stack((vx,vy,vz)) if scalars is not None: # scalars overrides color color = (0.0,0.5,1.0) scalars = ravel(scalars) scalars = scalars + amin(scalars) scalars = scalars.astype(float)/amax(scalars) elif not color: scalars = norms/normsmax color = (0.0,0.5,1.0) g = mlab.Arrows(positions,vectors=vectors,scalars=scalars,color=color) g.glyph.scale_mode='scale_by_vector' if not self.fig: self.show() self.fig.add(g) def scatter3d(self, x, y, z, scalars=None, size=None, color=(0.0,0.5,1.0), autoscale=1): """ Displays a bunch of spheres given by their 3d position. Optional scalar matrix defines their color and optional size matrix their radius""" assert len(x) == len(y) and len(y) == len(z), "coordinate vectors must be of same length" x=ravel(x) y=ravel(y) z=ravel(z) positions = column_stack((x,y,z)) if scalars is not None: scalars = ravel(scalars) scalars = scalars + amin(scalars) scalars = scalars.astype(float)/amax(scalars) if size is not None: size=ravel(size) size = size + amin(size) if autoscale: size = 1.5*size.astype(float)/amax(size) vectors = column_stack((size,size,size)) else: vectors = None g = mlab.Spheres(positions,vectors=vectors,scalars=scalars,color=color) if size is not None: g.glyph.scale_mode='scale_by_vector' if not self.fig: self.show() self.fig.add(g) def savefig(self, filename, **kw_args): """Saves rendered scene to one of several image formats depending on the specified extension of the given filename. Any extra keyword arguments are passed along to the respective save method.""" self.fig.renwin.save(filename, **kw_args) def surf(z,transparency=0.0,transparent=0): """ Plot a 3d surface from a 2D array """ f = figure3d() f.surf(z,transparency=transparency,transparent=transparent) return f def plot3(x, y, z, color=(0,0.5,1.0), linewidth=0.2): """ Plot a 3D line from 3 sets of coordinates """ f = figure3d() f.plot3(x,y,z,color=color, linewidth=linewidth) return f def scatter3d(x, y, z, scalars=None, size=None, color=(0.0,0.5,1.0), autoscale=1): """ Displays a bunch of points given by their 3d position. Optional scalar matrix defines their color""" f = figure3d() f.scatter3d(x ,y ,z, scalars=scalars, size=size, color=color, autoscale=autoscale) return f def quiver3d(x, y, z, vx, vy, vz, scalars=None, color=None, autoscale=1): """ Displays a plot of arrows located at x, y, z, and of coordinates vx, vy, vz""" f = figure3d() f.quiver3d(x ,y ,z, vx, vy, vz, scalars=scalars, color=color, autoscale=autoscale) return f ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 _______________________________________________ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel