New 3d trace isosurface

Hey Plotly users,

Did you know that starting with version 3.6, Plotly provides a 3d trace, called 'isosurface'?

There are multiple combinations of attributes to define interesting isosurfaces, isocaps, slices and spaceframes within avolume.

These are a few notebooks that present various examples:

  1. A single isosurface - no slices or caps: https://plot.ly/~empet/15143
  2. Isosurface with inner and outer face: https://plot.ly/~empet/15142
  3. Two isosurfaces, caps and spaceframe: https://plot.ly/~empet/15161
  4. Brain and brain slices: https://plot.ly/~empet/15150
  5. Relationship between an isosurface and slices in the volume containing them: https://plot.ly/~empet/15144
  6. Isosurface, caps and slices with gaps: https://plot.ly/~empet/15147
2 Likes

Gives an error:

No module named ‘plotly.graph_objects’
module ‘plotly.graph_objs’ has no attribute ‘isosurface’

If I do

import plotly as ply
import plotly.graph_objs as go
from plotly import tools

there is still an error:

module ‘plotly.graph_objs’ has no attribute ‘isosurface’

@rshayduk I suspect that you have an old plotly version. Upgrade it with the following command:

pip install plotly --upgrade

1 Like

I have 3D data on a spherical mesh. Real xyz coordinates on polar grid equidistant in theta, phi, r. Plotly is very good in producing empty plots [0:1,0:1,0:1] with that. How can I convince it to plot my data? There is no error message or warning. (works fine on matplotlib 3D). Plotly doc suggests "uniform or non- uniform 3-D grid. ". Does also not work with Volume. Is there another trace that can do it? (Volume and Isosurface seem to produce the same kind of plot out of the same kind of data. What is the difference?)

In [113]: plotly.__version__
Out[113]: '4.10.0'

Hi @2sn,

Could you please give more information on your data? Do you parameterize the sphere, or do you read an obj, off, or ply file containing the mesh descpription of the sphere, or do you intend to define the sphere as an isosurface within a volume?

To get help, please paste here your code that displays only an empty plot

Hi @empet,

I am having a similar issue to @2sn. I have 3D data corresponding to an evenly spaced spherical grid in theta, phi, r generated using np.mgrid

theta, phi, r = np.mgrid[0:90:50j, -180:180:50j, 0:0.02:50j]

I can quite happliy produce a cartesian isofurace plot, but I would prefer to display it in spherical co-ordinates if possible. However if I try to convert theta, phi, r to xyz coordinates to do this (as there doesn’t appear to be an option to set a spherical projection - sorry if i’ve missed this I am new to plotly) I then get an empty plot. I’ve check my x, y, z arrays and they are the same shape as theta, phi, r and if i do a scatter plot the grid locations all look correct.
The code I use to (try) and make the spherical isosurface plot. theta, phi and radius are flattened in another function and pdf is my array of values (which has the same shape)

    x = radius * sin(theta) * cos(phi)
    y = radius * sin(theta) * sin(phi)
    z = radius * cos(theta)

    fig = go.Figure()
    fig.add_trace(go.Isosurface(
        x=x,
        y=y,
        z=z, 
        value=pdf,
        isomin=0,
        isomax=1
        ))
    fig.show()

(I am using plotly version 4.13.0)

Hi @seismojoe,

You can define a sphere as the parameteric surface, using your parameterization (given in the code posted here),
but with a constant radius, and theta, phi, given in radians, not degrees, because in Python, as in math,
the functions sin and cos are evaluated at radian arguments. The sphere can be colored according to the values of a function, C(x,y,z) (or pdf in your case), evaluaed at the surface points.

import numpy as np
from numpy import sin, cos, pi
import plotly.graph_objects as go
theta = np.linspace(0, pi, 50)
phi= np.linspace(-pi, pi, 100)
theta, phi = np.meshgrid(theta, phi)
r= 1
X = r * sin(theta) * cos(phi)
Y = r * sin(theta) * sin(phi)
Z = r * cos(theta)
coloringF= Z**2*Y+cos(X**3+Z)  # this the function C(X, Y, Z)

fig1= go.Figure(go.Surface(x=X, y=Y, z=Z, 
                           surfacecolor=coloringF,  
                           colorbar_thickness=23, 
                           colorbar_len=0.7))  
fig1.update_layout(width=700, height=700)

If you want to define it as an isosurface, carved within a volume, then you define a meshgrid over a cube of side slightly
greater that the sphere diameter. Within this volume is carved a sphere of equation x^2+y^2+z^2= R^2.
To carve it, plotly.js evaluates the function F(x,y,z) =x^2+y^2+z^2-R^2 at the points of the meshgrid, and by an algorithm
working behind the scene, it finds the isosurface F(x,y,z)=(isomin+isomax)/2. An isosurface is colored uniformly, namely with the color at the mid of the colorscale.
In this case you can define a constant colorscale:

x, y, z = np.mgrid[-1.5:1.5:30j, -1.5:1.5:30j, -1.5:1.5:30j ]  #meshgrid over the cube with center at the origin
value = x**2+y**2+z**2-1  #F(x,y, z)=x**2+y**2+z**2-1

fig = go.Figure()
fig.add_trace(go.Isosurface(
        x=x.flatten(),
        y=y.flatten(),
        z=z.flatten(), 
        value=value.flatten(),
        surface=dict(show=True, count=1, fill=0.9),
        colorscale=[[0, 'rgb(0, 215, 0)'], [1, 'rgb(0, 215, 0)']],
        showscale=False,
        isomin= -1, isomax =   1 # these settings ensure that plotly.js will  carve the sphere of eq F(x,y, z)=(-1+1)/2=0
        
        ))
fig.update_layout(width=700, height=700)
fig.show()

If you are interested to plot a distribution over the sphere (a deduced that from your value=pdf), then you
cannot do it on an isosurface. :frowning:

Thanks for your help. What i really wanted to do is plot the distribution over the sphere as you said.

I suppose I will have to calculate the isosurfaces and then just draw them with go.Surface as a work-around :slight_smile: