# use a colormap for implicit_plot3d

Here's a question I asked a while ago on sage-support, but never got answered, so I'll try it again here:

I've been trying to figure out how to plot a surface using implicit_plot3d, and color it according to a particular color map. I see that implicit_plot3d passes its arguments to

sage.plot.plot3d.implicit_plot3d.ImplicitSurface

but I can't figure out more than this . . . when I try

sage: sage.plot.plot3d.implicit_plot3d.ImplicitSurface??

I get

Error getting source: could not find class definition

and then a few more unhelpful details.

It seems like the two possible viewers are jMol and Tachyon, but I can't tell whether either of these support color maps.

Any ideas where else I should be looking?

Update: This is now Trac ticket 12212

edit retag close merge delete

Sort by » oldest newest most voted

This is now possible as follows.

var('x,y,z')
cm = colormaps.autumn
f = cos(z*4).function(x,y,z)
implicit_plot3d(x^2-y^2*z == 0,(x,-4,4),(y,-4,4),(z,-4,4), color=(f,cm))


where cm is a chosen colormap among those available. Beware that the coloring function f must take values between 0 and 1.

more

I have once managed to get plot3d use a colormap, see here:

import matplotlib.cm


lists you the colormaps, you can also create your own. Note, the cmsel list in the following snippet defines the actual colors.

var('r v')
cmsel = [matplotlib.cm.get_cmap('autumn')(_) for _ in sxrange(0,1,0.05)]
p = plot3d(0.2*(r**2 + v**2) + cos(2*r)*sin(2*v),(r,-2,2), (v,-2,2), adaptive=True, color=cmsel, plot_points=10, opacity=0.9)
p2 = sphere((0,0,0),1,color='black',opacity=0.5)
(p+p2).show(aspect_ratio=(1,1,1), figsize=[7,3])

more

OMFG this is *awesome*. I had no idea this was possible in Sage.

( 2010-08-19 06:54:56 -0500 )edit

I don't know how to comment on another answer, so I'll just post my comment here. You don't have to import matplotlib colormaps, since they are already imported in the sage colormaps object:

sage: var('r v')
sage: cmsel = [colormaps['autumn'](i) for i in sxrange(0,1,0.05)]
sage: p = plot3d(0.2*(r**2 + v**2) + cos(2*r)*sin(2*v),(r,-2,2), (v,-2,2), adaptive=True, color=cmsel, plot_points=10, opacity=0.9)
sage: p2 = sphere((0,0,0),1,color='black',opacity=0.5)
sage: (p+p2).show(aspect_ratio=(1,1,1), figsize=[7,3])


You can see the available colormaps by doing

sage: colormaps.keys()

more

You can't comment until you get enough karma.

( 2010-08-19 18:26:09 -0500 )edit

How hard would it be to implement colorbars for 3D plots?

( 2010-08-21 21:45:45 -0500 )edit

Apologies for the delay; I assumed the answers from schilly and jason-grout would work (sorry!) but I got around to testing it today and it doesn't work for implicit_plot3d (works fine for plot3d). And now I am remembering why I wanted to see where implicit_plot3d sends its arguments: it seems to be handling color in a different way than plot3d.

so the following is fine:

sage: var('x,y,z')
sage: implicit_plot3d(x^2+y^2+z^2==4, (x, -3, 3), (y, -3,3), (z, -3,3), color='red')


but this is not:

sage: cmsel = [colormaps['autumn'](i) for i in sxrange(0,1,0.05)]
sage: var('x,y,z')
sage: implicit_plot3d(x^2+y^2+z^2==4, (x, -3, 3), (y, -3,3), (z, -3,3), color=cmsel)
ERROR: An unexpected error occurred while tokenizing input
The following traceback may be corrupted or invalid
The error message is: ('EOF in multi-line statement', (49, 0))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
...
TypeError: 'NoneType' object is not iterable

more

Niles, did you ever get this to work? I need exactly the same functionality, but for parametric_plot3d, maybe you can open a ticket for this?

( 2011-12-20 10:16:04 -0500 )edit

No, I never did get it working. Instead I redesigned my project so that I didn't need it . . . the ticket is http://trac.sagemath.org/sage_trac/ti... .

( 2011-12-21 01:30:13 -0500 )edit

Great, thanks! I was sort of hoping that you had implemented this for your Hopf fibration video :)

( 2011-12-21 05:08:26 -0500 )edit

Thanks for the followup, Niles. This is a really annoying part of some things that are defined in .pyx files - ImplicitSurface is a cdef (Cython) function, and these don't always work well with introspection in my experience. Weirdly, I don't get the traceback you do in the notebook.

It turns out that **kwds (which would include color) end up in the init of IndexFaceSet which sends it to PrimitiveObject in plot3d/base.pyx which includes

    else:
self.texture = Texture(kwds)


And if you look at THAT you will see that that just goes through a whole slew of possible things the input could be to Texture. And I think that following this the bug is that parse_color does not take a multiplicity of colors.

This still doesn't answer how to GET the colormap, but hopefully tracks down some of why it isn't working.

more

And plot3d seems to also eventually end up at IndexFaceSet via ParametricSurface anyway, so this doesn't resolve the mystery at all, perhaps.

( 2010-08-21 15:41:20 -0500 )edit

But I did finally get the error message, and indeed the problem is in parse_color, where there isn't an else for info something other than a string or Color. But the fix would have to be in Texture or something. Why *does* it work with plot3d?

( 2010-08-21 15:44:22 -0500 )edit

Thanks for the help . . . I'll keep digging :)

( 2010-08-21 16:35:24 -0500 )edit