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

Reply via email to