[SciPy-User] creating a 3D surface plot from collected data

2,608 views
Skip to first unread message

URI

unread,
Feb 15, 2010, 9:17:07 AM2/15/10
to scipy...@scipy.org
I am trying to figure out how to create a 3D surface plot from some x,y,z data
that I have. I don't have any particular preference as to how to do it, but
from poking around on the web it seems like mplot3d should be able to do it,
based on what I see in the tutorial (look at the wireframe or surface plot
sections):

http://matplotlib.sourceforge.net/mpl_toolkits/mplot3d/tutorial.html

The problem I have is that none of the example source code is based on working
with numbers from actual data. The only thing I could find that addresses this
issue is at the very bottom of this page under the heading "Another Example":
http://www.scipy.org/Cookbook/Matplotlib/mplot3D

I've tried to duplicate this method but I get errors, and I don't really
understand it anyway. The place I get lost is here:

Z = numpy.zeros((len(Y), len(X)), 'Float32')
for d in data:
x, y, z = d
ix = int(x * 10)
iy = int(y * 10)
Z[iy, ix] = z


I don't understand how ix and iy are supposed to give me valid indeces for the Z
array (and Python doesn't seem to understand it either, it gives me an error at
that last line).

Can someone either explain this method to me, or point me in a different
direction?

_______________________________________________
SciPy-User mailing list
SciPy...@scipy.org
http://mail.scipy.org/mailman/listinfo/scipy-user

alexander baker

unread,
Feb 15, 2010, 11:47:18 AM2/15/10
to SciPy Users List
Example here that might help.

Regards

Alex Baker

http://www.alexfb.com/cgi-bin/twiki/view/PtPhysics/Spherical-Polar-Coordinates-Python

Mobile: 07788 872118
Blog: www.alexfb.com

--
All science is either physics or stamp collecting.

Joe Kington

unread,
Feb 15, 2010, 12:20:30 PM2/15/10
to SciPy Users List
Are your data already gridded? Or are they irregularly spaced?  Seeing as how you mentioned "real" data, I'm assuming they're irregularly spaced.

The iy, ix example assumes that you have a regular grid that has been exported as an x,y,z file instead of a grid of z coordinates.

If they're not already a regular grid, you'll need to interpolate them onto a regular grid before using any of the 3D surface plotting routines.

(I'll skip my "interpolation is an artform" rant, here...  For a quick look splines are fine.)

Look into using the various functions in sp.interpolate.  The example I threw together below uses a thin-plate spline, but there are lots of other options.

import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
import scipy.interpolate
from mpl_toolkits.mplot3d import Axes3D

x = np.random.random(10)
y = np.random.random(10)
z = np.random.random(10)

spline = sp.interpolate.Rbf(x,y,z,function='thin-plate')

xi = np.linspace(x.min(), x.max(), 50)
yi = np.linspace(y.min(), y.max(), 50)
xi, yi = np.meshgrid(xi, yi)

zi = spline(xi,yi)

fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(xi,yi,zi)
plt.show()

Hope that helps,
-Joe

Oz Nahum

unread,
Feb 15, 2010, 1:32:22 PM2/15/10
to scipy...@scipy.org
> The problem I have is that none of the example source code is based on working
with numbers from actual data.

This is my usual criticism to most of the scipy documentation which is
written to mathematicians not for users (check this in my blog
http://www.tabula0rasa.org/2008/07/crazy-matplotlib-tutorial/ )

In anycase -
here is any example with hydraulic head data which is easy to understand

http://www.tabula0rasa.org/2009/05/3d-plots-with-matplotlib/

let me know if the example works for you or not (I didn't check it for a while)

--
Oz Nahum
Graduate Student
Zentrum für Angewandte Geologie
Universität Tübingen

---

Imagine there's no countries
it isn't hard to do
Nothing to kill or die for
And no religion too
Imagine all the people
Living life in peace

Oz Nahum

unread,
Feb 15, 2010, 2:10:45 PM2/15/10
to scipy...@scipy.org
BTW,
the example give by Alex, is nice, but there is a small error:
The line
import matplotlib.axes3d as p3 # 3D axes class
should be
import mpl_toolkits.mplot3d as p3

And then it plot a lovely diamond ;-)

URI

unread,
Feb 16, 2010, 7:00:57 AM2/16/10
to scipy...@scipy.org
>Joe Kington <jkington <at> wisc.edu> writes:
>
>
>
> Are your data already gridded? Or are they irregularly spaced?  Seeing as how
you mentioned "real" data, I'm assuming they're irregularly spaced.The iy, ix

example assumes that you have a regular grid that has been exported as an x,y,z
file instead of a grid of z coordinates.If they're not already a regular grid,

you'll need to interpolate them onto a regular grid before using any of the 3D
surface plotting routines.(I'll skip my "interpolation is an artform" rant,
here...  For a quick look splines are fine.)Look into using the various

functions in sp.interpolate.  The example I threw together below uses a
thin-plate spline, but there are lots of other options.import numpy as npimport
scipy as spimport matplotlib.pyplot as pltimport scipy.interpolatefrom
mpl_toolkits.mplot3d import Axes3Dx = np.random.random(10)y =
np.random.random(10)z = np.random.random(10)spline =
sp.interpolate.Rbf(x,y,z,function='thin-plate')xi = np.linspace(x.min(),
x.max(), 50)yi = np.linspace(y.min(), y.max(), 50)xi, yi = np.meshgrid(xi, yi)zi
= spline(xi,yi)
> fig = plt.figure()ax = Axes3D(fig)ax.plot_surface(xi,yi,zi)plt.show()Hope that
helps,-Joe

Joe-

This is exactly what I'm looking for, thanks. The problem is that when I read
in my data I get these errors:

Traceback (most recent call last):
File "C:\Python26\Lib\site-packages\xy\plotscript_griddata.py", line 33, in
<module>
spline = sp.interpolate.Rbf(xlist,ylist,zlist,function='thin-plate')
File "C:\Python26\lib\site-packages\scipy\interpolate\rbf.py", line 138, in
__init__
self.nodes = linalg.solve(self.A, self.di)
File "C:\Python26\lib\site-packages\scipy\linalg\basic.py", line 151, in solve
raise LinAlgError, "singular matrix"
LinAlgError: singular matrix


The data I'm using is 2560 x,y,z grid points representing an anatomical contour
exported from a medical imaging program. None of the values are zero and it's
not some crazy shape - basically it looks like a kidney, so no spike or holes or
anything. I've found that if I chop the data down to 144 lines it will then
work (not that 144 is the exact cutoff, I just kept deleting chunks of lines
from the data file until it worked). This tells me that I've successfully
adapted your code and that I'm reading in the data properly as numpy arrays - I
was worried that I might just have some formatting problems.

Any idea why I can't run this with my entire data set? This is just a test run,
I will potentially need to process much larger datasets in the future.

P.S. Sorry for the bottom-post, the website won't let me submit unless I post my
message below yours. Seems stupid to me, I think it makes a lot more sense to
see the new information at the top instead of having to scroll through a bunch
of stuff I've already read.

Joe Kington

unread,
Feb 16, 2010, 9:23:54 AM2/16/10
to SciPy Users List
No worries about the bottom post. I actually think I'm breaking protocol by top-posting, but I use gmail, and it's just more natural to top-post.

Anyway, I think your problem is coming from the fact that you're working with an isosurface that fully encloses a volume. I assumed that you had scattered data points (say, elevation measurements) that you needed to interpolate between. 

The interpolation example I posted implicitly assumes that z = f(x,y). In other words, that there is only one z value for any given x and y.  If you're working with a 3D kidney-shape, this is clearly not the case. 

Therefore, you're getting a singluar matrix when you try to interpolate (more than one value of z for identical rows of x and y in the matrix).

The good news is that this may make the problem much simpler. (Your data is already in some sort of triangle-strip format if it's been exported from an imaging program. No need to interpolate.)

What happens when you just do:


fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(x,y,z)
plt.show()

Where x,y,z are your raw data?  There's a reasonable chance that the program you used to export the x,y,z isosurface left the verticies in the order that plot_surface expects them in...

On a side note, you might also look into Mayavi's mlab module for 3D plotting.  I prefer it to matplotlib's native 3D plotting.
If you have it installed, you'd just do:

from enthought.mayavi import mlab
s = mlab.mesh(x, y, z)
mlab.show()

Hope that helps some,
-Joe

denis

unread,
Feb 16, 2010, 9:29:40 AM2/16/10
to scipy...@scipy.org
URI,
can you try these --
spline = sp.interpolate.Rbf(x,y,z,function='thin-plate',
smooth=1 )
spline = sp.interpolate.Rbf(x,y,z,function='gaussian', smooth=1 )

pydoc scipy.interpolate.Rbf says
| smooth : float, optional
| Values greater than zero increase the smoothness of the
| approximation. 0 is for interpolation (default), the function
will
| always go through the nodal points in this case.

I have no idea if "smooth=1" is reasonable, but 0 is not a good
default -- Joe ?

cheers
-- denis

URI

unread,
Feb 16, 2010, 10:06:34 AM2/16/10
to scipy...@scipy.org
Joe Kington <jkington <at> wisc.edu> writes:

>
>
> No worries about the bottom post. I actually think I'm breaking protocol by

top-posting, but I use gmail, and it's just more natural to top-post.Anyway, I


think your problem is coming from the fact that you're working with an
isosurface that fully encloses a volume. I assumed that you had scattered data
points (say, elevation measurements) that you needed to interpolate between. 
The interpolation example I posted implicitly assumes that z = f(x,y). In other
words, that there is only one z value for any given x and y.  If you're working
with a 3D kidney-shape, this is clearly not the case.  Therefore, you're getting
a singluar matrix when you try to interpolate (more than one value of z for

identical rows of x and y in the matrix).The good news is that this may make the


problem much simpler. (Your data is already in some sort of triangle-strip
format if it's been exported from an imaging program. No need to

interpolate.)What happens when you just do:fig = plt.figure()ax =
Axes3D(fig)ax.plot_surface(x,y,z)plt.show()Where x,y,z are your raw data? 


There's a reasonable chance that the program you used to export the x,y,z
isosurface left the verticies in the order that plot_surface expects them

in...On a side note, you might also look into Mayavi's mlab module for 3D


plotting.  I prefer it to matplotlib's native 3D plotting. If you have it
installed, you'd just do:from enthought.mayavi import mlabs = mlab.mesh(x, y,
z)mlab.show()Hope that helps some,
> -Joe

I get these errors:

Traceback (most recent call last):

File "C:\Python26\Lib\site-packages\xy\plotscript_griddata.py", line 61, in
<module>
ax.plot_surface(x,y,z)
File "C:\Python26\lib\site-packages\mpl_toolkits\mplot3d\axes3d.py", line 573,
in plot_surface
rows, cols = Z.shape
ValueError: need more than 1 value to unpack

Maybe Mayavi is the way to go, I did come across it while researching this
problem. I was worried that I couldn't install it alongside my current
installation, these things always seems to conflict with each other when I try
to have multiple packages installed.

"it's just more natural to top-post" - I completely agree. I am using the web
interface to post so the admins have more control over what I'm doing. Maybe I
should start using an email interface.

Rob Clewley

unread,
Feb 16, 2010, 10:19:32 AM2/16/10
to SciPy Users List
Joe,

On Tue, Feb 16, 2010 at 9:23 AM, Joe Kington <jkin...@wisc.edu> wrote:
> The interpolation example I posted implicitly assumes that z = f(x,y). In
> other words, that there is only one z value for any given x and y. If
> you're working with a 3D kidney-shape, this is clearly not the case.
>

I too have some data that has multiple z values in the x,y domain.
Worse, my data is not remotely arranged in a proper grid as it is
temporal trajectory data from a 3D ODE that winds itself round and
round the surface, like a very carefully wrapped mummy. I.e., it
doesn't wrap back over itself.

I'm not familiar with 3D plotting techniques and trying to set up the
plot of my surface in mayavi or matplotlib is not working along the
lines of standard cookbook examples. I cannot find appropriate
information online on how to plot the surface if I can't run the
interpolator for data that's not a function of (x,y) and my data needs
"alignment".

But maybe I'm looking in the wrong place. Could you provide any pointers please?

-Rob

Gael Varoquaux

unread,
Feb 16, 2010, 11:07:27 AM2/16/10
to SciPy Users List
On Tue, Feb 16, 2010 at 10:19:32AM -0500, Rob Clewley wrote:
> I too have some data that has multiple z values in the x,y domain.
> Worse, my data is not remotely arranged in a proper grid as it is
> temporal trajectory data from a 3D ODE that winds itself round and
> round the surface, like a very carefully wrapped mummy. I.e., it
> doesn't wrap back over itself.

> I'm not familiar with 3D plotting techniques and trying to set up the
> plot of my surface in mayavi or matplotlib is not working along the
> lines of standard cookbook examples. I cannot find appropriate
> information online on how to plot the surface if I can't run the
> interpolator for data that's not a function of (x,y) and my data needs
> "alignment".

Would this example help:
http://code.enthought.com/projects/mayavi/docs/development/html/mayavi/auto/example_surface_from_irregular_data.html

Gaël

URI

unread,
Feb 16, 2010, 12:57:50 PM2/16/10
to scipy...@scipy.org
Joe Kington <jkington <at> wisc.edu> writes:

>
>
> No worries about the bottom post. I actually think I'm breaking protocol by

top-posting, but I use gmail, and it's just more natural to top-post.Anyway, I


think your problem is coming from the fact that you're working with an
isosurface that fully encloses a volume. I assumed that you had scattered data
points (say, elevation measurements) that you needed to interpolate between. 
The interpolation example I posted implicitly assumes that z = f(x,y). In other
words, that there is only one z value for any given x and y.  If you're working
with a 3D kidney-shape, this is clearly not the case.  Therefore, you're getting
a singluar matrix when you try to interpolate (more than one value of z for

identical rows of x and y in the matrix).The good news is that this may make the


problem much simpler. (Your data is already in some sort of triangle-strip
format if it's been exported from an imaging program. No need to

interpolate.)What happens when you just do:fig = plt.figure()ax =
Axes3D(fig)ax.plot_surface(x,y,z)plt.show()Where x,y,z are your raw data? 


There's a reasonable chance that the program you used to export the x,y,z
isosurface left the verticies in the order that plot_surface expects them

in...On a side note, you might also look into Mayavi's mlab module for 3D


plotting.  I prefer it to matplotlib's native 3D plotting. If you have it

installed, you'd just do:from enthought.mayavi import mlabs = mlab.mesh(x, y,
z)mlab.show()Hope that helps some,
> -Joe

I understand what you mean about assuming that z is a proper function of x and
y, but after looking again at the examples on the tutorial page
(http://matplotlib.sourceforge.net/mpl_toolkits/mplot3d/tutorial.html#getting-started)
I remember why I thought plot_surface was the proper function: the second
example under the plot_surface heading shows a spherical surface, so I figured
plot_surface didn't assume a 1-to-1 relationship.

Rob Clewley

unread,
Feb 16, 2010, 3:13:47 PM2/16/10
to SciPy Users List
Gael, maybe we misunderstand each other! My data is actually very
smooth, it's just that it's not aligned on a regular mesh already.
It's ordered temporally as a single curve that is wrapping itself
around a solid object's surface.

-Rob

Gael Varoquaux

unread,
Feb 16, 2010, 3:58:00 PM2/16/10
to SciPy Users List
On Tue, Feb 16, 2010 at 03:13:47PM -0500, Rob Clewley wrote:
> Gael, maybe we misunderstand each other! My data is actually very
> smooth, it's just that it's not aligned on a regular mesh already.
> It's ordered temporally as a single curve that is wrapping itself
> around a solid object's surface.

Yes, the example I point to shows how to reconstruct a surface from
unconnected point, so I would think that it applies to your problem.

HTH,

Gaël

> -Rob

> On Tue, Feb 16, 2010 at 11:07 AM, Gael Varoquaux
> <gael.va...@normalesup.org> wrote:
> > On Tue, Feb 16, 2010 at 10:19:32AM -0500, Rob Clewley wrote:
> >> I too have some data that has multiple z values in the x,y  domain.
> >> Worse, my data is not remotely arranged in a proper grid as it is
> >> temporal trajectory data from a 3D ODE that winds itself round and
> >> round the surface, like a very carefully wrapped mummy. I.e., it
> >> doesn't wrap back over itself.

> >> I'm not familiar with 3D plotting techniques and trying to set up the
> >> plot of my surface in mayavi or matplotlib is not working along the
> >> lines of standard cookbook examples. I cannot find appropriate
> >> information online on how to plot the surface if I can't run the
> >> interpolator for data that's not a function of (x,y) and my data needs
> >> "alignment".

_______________________________________________

David Baddeley

unread,
Feb 16, 2010, 4:16:10 PM2/16/10
to SciPy Users List
As I see it, Gael's example doesn't do any smoothing - it just uses the triangulation to do the interpolation and get around the irregular sampling, and seems like quite a reasonable way to attack the problem.

Correct me if I'm wrong, but as I read it you've got a number of x,y,z points which lie on the surface of a 3D volume, rather than on an essentially 2D 'rubber sheet'. In this case the 2D triangulation is not going to give you what you want, but you could apply the same principle and do a 3D triangularisation, which should give you triangles on the surface of your object. The problem is that it'll also give you triangles covering the surface of the entire convex hull and on the inside of the object, which you're somehow going to need to cull. This could be as simple as just culling everything which is larger than a certain cutoff. After this you're still left with the problem of displaying the triangles somehow (there's probably a patch function in matplotlib axes3d, and you're almost certain to be able to get triangles into mayavi.

I'm not sure if mayavi has 3D triangularisation, but there's a python wrapper around qhull which does. If you want to go this route I've got some code using qhull which does the triangularisation, large face culling, and internal face culling, as well as some very limited opengl code to draw the triangles. It's slow (practically limited to a couple of thousand points), poorly commented, buggy, and somewhat application specific, but might be useful as a template to try and write something better. It's definitely not a ready solution, but drop me a line if you want to give it a try.

cheers,
David

Gael Varoquaux

unread,
Feb 16, 2010, 4:30:27 PM2/16/10
to David Baddeley, SciPy Users List
On Tue, Feb 16, 2010 at 01:16:10PM -0800, David Baddeley wrote:
> I'm not sure if mayavi has 3D triangularisation,

It has, or rather VTK has, thus Mayavi has. It's just a question of
replacing the call to Delaunay2D by one to Delaunay3D. However, if a
surface is wanted, I believe that 2D triangulation is the way to go.

My 2 cents,

Rob Clewley

unread,
Feb 16, 2010, 6:13:23 PM2/16/10
to SciPy Users List
Yes, David, definitely a 3D surface, so we'll need 3D
triangularisation. I think by culling you are referring to removing
giant triangles that would cover the opening of the "horn" shape that
I know my data makes, because those triangles would be part of the
convex hull. If so, we can certainly cutoff by size. When you say
other triangles that are "inside" do you just mean the ones on the
surface of the horn's opening that are not on the convex hull? If we
get as far as a clean triangularisation then we will plot with mayavi.

So I guess I will try using Delauney3D. Thanks for the tips. I (or
rather my student who is doing this mostly) will look into this more
closely to see if we can leverage these examples more than previous
ones. I'll be back on this thread if I get stuck, so look out :)

Thanks,
Rob

Gael Varoquaux

unread,
Feb 16, 2010, 6:20:07 PM2/16/10
to SciPy Users List
On Tue, Feb 16, 2010 at 06:13:23PM -0500, Rob Clewley wrote:
> Yes, David, definitely a 3D surface, so we'll need 3D
> triangularisation.

I think we are having a communication problem here (but I may be wrong).
When you say a 3D surface, you mean a 2D surface embedded in a 3D space,
or a 3D volume? If it is the later, you will need Delaunay3D, as it
creates volumes. If it is the former, Delaunay2D is what you are looking
for : it creates 2D surfaces embedded in a 3D world by connecting dots
with 3D coordinnates using triangles.

Gaël

> Thanks,
> Rob

> > cheers,
> > David

> > -Rob

--
Gael Varoquaux
Research Fellow, INRIA
Laboratoire de Neuro-Imagerie Assistee par Ordinateur
NeuroSpin/CEA Saclay , Bat 145, 91191 Gif-sur-Yvette France
++ 33-1-69-08-78-35
http://gael-varoquaux.info

Robert Kern

unread,
Feb 16, 2010, 6:28:25 PM2/16/10
to SciPy Users List
On Tue, Feb 16, 2010 at 17:20, Gael Varoquaux
<gael.va...@normalesup.org> wrote:
> On Tue, Feb 16, 2010 at 06:13:23PM -0500, Rob Clewley wrote:
>> Yes, David, definitely a 3D surface, so we'll need 3D
>> triangularisation.
>
> I think we are having a communication problem here (but I may be wrong).
> When you say a 3D surface, you mean a 2D surface embedded in a 3D space,
> or a 3D volume? If it is the later, you will need Delaunay3D, as it
> creates volumes. If it is the former, Delaunay2D is what you are looking
> for : it creates 2D surfaces embedded in a 3D world by connecting dots
> with 3D coordinnates using triangles.

No, this is not true. Delaunay2D ignores the Z coordinate and returns
the 2D Delaunay triangulation of just the X,Y coordinates. When you
have an z=f(x,y) functional relationship, this usually does what you
want. It does not solve Rob's problem or that of the OP.

http://www.vtk.org/doc/release/5.4/html/a00404.html

Instead, they need the SurfaceReconstructionFilter:

http://www.vtk.org/doc/release/5.4/html/a01651.html

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless
enigma that is made terrible by our own mad attempt to interpret it as
though it had an underlying truth."
-- Umberto Eco

Gael Varoquaux

unread,
Feb 16, 2010, 6:36:24 PM2/16/10
to SciPy Users List
On Tue, Feb 16, 2010 at 05:28:25PM -0600, Robert Kern wrote:
> No, this is not true. Delaunay2D ignores the Z coordinate and returns
> the 2D Delaunay triangulation of just the X,Y coordinates. When you
> have an z=f(x,y) functional relationship, this usually does what you
> want. It does not solve Rob's problem or that of the OP.

> http://www.vtk.org/doc/release/5.4/html/a00404.html

Wow, I am bluffed. I was pretty sure of the contrary and didn't check.

> Instead, they need the SurfaceReconstructionFilter:

> http://www.vtk.org/doc/release/5.4/html/a01651.html

Rob and David, you can use it by replacing the call to
mlab.pipeline.delaunay2d by a call to:

mlab.pipeline.user_defined(obj, filter='SurfaceReconstructionFilter'),

as in the following example:
http://code.enthought.com/projects/mayavi/docs/development/html/mayavi/auto/example_image_cursor_filter.html

Thanks for the details, Robert.

Gaël

David Baddeley

unread,
Feb 16, 2010, 7:08:13 PM2/16/10
to SciPy Users List
The 3D triangularisation gives you a set of tetrahedra, each of which has 4 faces, some of the faces will lie on the surface of the object, but it'll also create tetrahedra within the object, which will probably have one face on the surface & 3 faces which are hidden within the volume. These are what I was refering to as internal faces. They're more of a problem for performance than for rendering unless you want to see the inside of the object.

That said, I suspect the surface reconstruction filter might be a better way to go.

URI

unread,
Feb 17, 2010, 9:54:10 AM2/17/10
to scipy...@scipy.org
Joe Kington <jkington <at> wisc.edu> writes:

>
>
> No worries about the bottom post. I actually think I'm breaking protocol by

top-posting, but I use gmail, and it's just more natural to top-post.Anyway, I


think your problem is coming from the fact that you're working with an
isosurface that fully encloses a volume. I assumed that you had scattered data
points (say, elevation measurements) that you needed to interpolate between. 
The interpolation example I posted implicitly assumes that z = f(x,y). In other
words, that there is only one z value for any given x and y.  If you're working
with a 3D kidney-shape, this is clearly not the case.  Therefore, you're getting
a singluar matrix when you try to interpolate (more than one value of z for

identical rows of x and y in the matrix).The good news is that this may make the


problem much simpler. (Your data is already in some sort of triangle-strip
format if it's been exported from an imaging program. No need to

interpolate.)What happens when you just do:fig = plt.figure()ax =
Axes3D(fig)ax.plot_surface(x,y,z)plt.show()Where x,y,z are your raw data? 


There's a reasonable chance that the program you used to export the x,y,z
isosurface left the verticies in the order that plot_surface expects them

in...On a side note, you might also look into Mayavi's mlab module for 3D


plotting.  I prefer it to matplotlib's native 3D plotting. If you have it

installed, you'd just do:from enthought.mayavi import mlabs = mlab.mesh(x, y,

z)mlab.show()Hope that helps some,
> -Joe
> On Tue, Feb 16, 2010 at 6:00 AM, URI <zallen <at>


urologicresearchinstitute.org> wrote:
> >Joe Kington <jkington <at> wisc.edu> writes:
>
> >

I tried using mlab.mesh from mayavi but apparently the x y z components need to
be 2D arrays (see
http://code.enthought.com/projects/mayavi/docs/development/html/mayavi/auto/mlab_helper_functions.html#enthought.mayavi.mlab.mesh).

I don't understand this, how can my list of the x-positions of the vertices be a
2D array?

I did try to use mlab.plot3d (see
http://code.enthought.com/projects/mayavi/docs/development/html/mayavi/auto/mlab_helper_functions.html#enthought.mayavi.mlab.plot3d)
and it gave me a nice line drawing of my shape, but an actual surface would be
much nicer.

Robert Kern

unread,
Feb 17, 2010, 10:56:40 AM2/17/10
to SciPy Users List
On Wed, Feb 17, 2010 at 08:54, URI <zal...@urologicresearchinstitute.org> wrote:

> I tried using mlab.mesh from mayavi but apparently the x y z components need to
> be 2D arrays (see
> http://code.enthought.com/projects/mayavi/docs/development/html/mayavi/auto/mlab_helper_functions.html#enthought.mayavi.mlab.mesh).
>
> I don't understand this, how can my list of the x-positions of the vertices be a
> 2D array?

It is for rectilinear grids of z=f(x,y) surfaces only.

> I did try to use mlab.plot3d (see
> http://code.enthought.com/projects/mayavi/docs/development/html/mayavi/auto/mlab_helper_functions.html#enthought.mayavi.mlab.plot3d)
> and it gave me a nice line drawing of my shape, but an actual surface would be
> much nicer.

Please see the previous posts about using the SurfaceReconstructionFilter.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless
enigma that is made terrible by our own mad attempt to interpret it as
though it had an underlying truth."
-- Umberto Eco

Joe Kington

unread,
Feb 18, 2010, 12:31:49 PM2/18/10
to SciPy Users List
Hi there,

I don't understand this, how can my list of the x-positions of the vertices be a
2D array?
 
mlab's mesh expects 2d grids of x,y, and z values so that it can infer how the points are connected. 

Because you just have lists of x,y,z verticies, there's no pre-defined way to connect them.  Therefore, you need some way to define how they connect into a surface.  (The program you exported them from probably stored them as triangle-strip mesh.  You have the verticies, but don't have the definition of how they link into individual triangles)
 
The surface reconstruction filter Robert mentioned is one way (and probably the best way) of doing this.  (Credit where it's due... I had no idea vtk had that particular filter before Robert mentioned it!)

It's slightly confusing, as it's not quite as simple as just replacing the delaunay2d in Gael's earlier example with a call to the SurfaceReconstructionFilter.

The surface reconstruction filter returns a volume that you need to extract an isosurface at a value of 0 from.  (It took me awhile to figure that out... Guess I should have read the vtk docs a bit closer!)

If this helps, here's a very artificial example using the surface reconstruction filter.  It will produce some artifacts, but it should (?) work for your data.... I think...  The first half just builds a set of points on the outside of a sphere.  (capital) X,Y,Z would be representative of your data.

from enthought.mayavi import mlab
import numpy as np

# First off, let's make 2d grids of phi and theta
phi = np.linspace(-np.pi, np.pi, 100)
theta = np.linspace(0, np.pi*2, 100)
phi, theta = np.meshgrid(phi, theta)

# Now lets make points on the outside of a sphere and
# put things back into cartesian coordinates
r = 1000
x = r * np.sin(phi) * np.cos(theta)
y = r * np.cos(phi)
z = r * np.sin(phi) * np.sin(theta)

# Since x,y,z are all regularly spaced 2d arrays, there's
# a defined way to link up each x,y,z coordinate into a
# surface (if that makes sense).  We can plot this using mesh
mlab.figure()
mlab.mesh(x,y,z)
mlab.title('The ideal surface')

# Now, lets "lose" the connectivity information by flattening the
# arrays.  This is more like what you have... A bunch of x,y,z
# coordinates of points on a surface with no clear definition
# of how to connect them.
X, Y, Z = [item.flatten() for item in [x,y,z]]

# Now we have to reconstruct how they connect into a surface
mlab.figure()
# Make a point source from the x,y,z coordinates
pts = mlab.pipeline.scalar_scatter(X,Y,Z,Z)

# This creates a volume of the distance to the reconstructed surface
vol = mlab.pipeline.user_defined(pts, filter='SurfaceReconstructionFilter')

# We can then extract an iso_surface at 0 that should be close to the
# original surface
mlab.pipeline.iso_surface(vol, contours=[0])
mlab.title('The reconstructed surface\nNotice the artifacts')
mlab.show()

Hope that helps,
-Joe
Reply all
Reply to author
Forward
0 new messages