# How to do 3D Plot surface with isolinies

**URL:** <https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256>\
**Category:** 📊 Plotly Python\
**Created:** [October 11, 2023, 5:50pm UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256 "2023-10-11T17:50:33Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![luxs](https://avatars.discourse-cdn.com/v4/letter/l/bc79bd/32.png) [@luxs](https://community.plotly.com/u/luxs)\
**Post date:** [October 11, 2023, 5:50pm UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/1 "2023-10-11T17:50:33Z")

</div>

Hi,  
I have a 3D domain with data and trying to visualize slices of data in 3D space.  
I can show the data by colours, but not by contours, What Im doing wrong?

```auto
import plotly.graph_objects as go
import numpy as np

d = [[-10,10,32], [-15,15,48], [-10,10,32]]
x_values = np.linspace(d[0][0], d[0][1], d[0][2])
y_values = np.linspace(d[1][0], d[1][1], d[1][2])
z_values = np.linspace(d[2][0], d[2][1], d[2][2])
X, Y, Z = np.meshgrid(x_values, y_values, z_values)
BB = np.sin(np.sqrt(X **2 + Y** 2 + Z**2))

idx = 10
z_plane = BB[:, :, idx]
sp_z = go.Surface(
            contours = {
                        "z": {"show": True, "start": BB.min(), "end": BB.max(), "size": 0.05, "color":"white"}
                       },
            x=X[:, :, idx], y=Y[:, :, idx], z=Z[:, :, idx],
            surfacecolor=z_plane,
            colorscale='Hot', showscale=False, opacity=0.7)
fig = go.Figure(data=[sp_z])
fig.show()

```

Any advice would be great!

---

<div class="post-metadata">

**Author:** ![farispriadi](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/farispriadi/32/26759_2.png) [@farispriadi](https://community.plotly.com/u/farispriadi)\
**Post date:** [October 12, 2023, 12:15am UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/2 "2023-10-12T00:15:03Z")

</div>

Hi @luxs ,

is `srf` variable is suppose to be `sp_z` ?

I haven’t explore much about 3D plot, but your contours don’t show up maybe affected by `z` values that have same values.

---

<div class="post-metadata">

**Author:** ![luxs](https://avatars.discourse-cdn.com/v4/letter/l/bc79bd/32.png) [@luxs](https://community.plotly.com/u/luxs)\
**Post date:** [October 12, 2023, 7:24am UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/3 "2023-10-12T07:24:45Z")

</div>

Hi

> > is `srf` variable is suppose to be `sp_z` ?  
> > Yes, you are right, this is just a typo. I’ve fixed it in the original post, but this does not change anything. The isolines are not plotted.

It looks like I have some problems with contours syntaxis, but can;t work out which one.

---

<div class="post-metadata">

**Author:** ![AIMPED](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/aimped/32/21758_2.png) [@AIMPED](https://community.plotly.com/u/AIMPED)\
**Post date:** [October 12, 2023, 9:07am UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/4 "2023-10-12T09:07:55Z")

</div>

Hi @luxs, welcome to the forums.

It seems that you are interested in the contours only. If this is the case, you can use `go.Contour()`.

> **[Contour](https://plotly.com/python/contour-plots/)**
>
> Over 14 examples of Contour Plots including changing color, size, log axes, and more in Python.

An example:

```python
import plotly.graph_objects as go
import numpy as np

d = [[-10,10,32], [-15,15,48], [-10,10,32]]
x_values = np.linspace(d[0][0], d[0][1], d[0][2])
y_values = np.linspace(d[1][0], d[1][1], d[1][2])
z_values = np.linspace(d[2][0], d[2][1], d[2][2])
X, Y, Z = np.meshgrid(x_values, y_values, z_values)
BB = np.sin(np.sqrt(X **2 + Y** 2 + Z**2))

idx = 10
z_plane = BB[:, :, idx]
sp_z = go.Contour(
    z=BB[:, :, idx],
    colorscale='Hot', 
    showscale=False, 
    opacity=0.7
)
fig = go.Figure(data=[sp_z])
fig.show()

```

 ![newplot(6)](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/e/d/eded21e27e92b81aa7ff163202fd41523bfb09d2.png)

---

<div class="post-metadata">

**Author:** ![AIMPED](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/aimped/32/21758_2.png) [@AIMPED](https://community.plotly.com/u/AIMPED)\
**Post date:** [October 12, 2023, 9:39am UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/5 "2023-10-12T09:39:31Z")

</div>

You are actually right. In order to make the contours work in a surface plot, the surface can’t be a plane parallel to the xy-plane:

```auto
import plotly.graph_objects as go
import numpy as np

x= np.linspace(0, 50, 2)
y= np.linspace(0, 50, 2)
z= 10 * np.array([[0,0],[0,0]])

data = go.Surface(
        x=x,
        y=y,
        z=z,
        opacity=0.3,
        showscale=False,
    )

fig.update_traces(
    contours_z=dict(
        show=True, 
        usecolormap=True,                        
        project_z=True
    )
)

fig = go.Figure(data)

```

won’t show contours.

Substituting

```python
z= 10 * np.array([[0,0],[0,0]])

```

with

```python
z= 10 * np.array([[0,0],[1,1]])

```

will show contours.  
mrep contours

---

<div class="post-metadata">

**Author:** ![luxs](https://avatars.discourse-cdn.com/v4/letter/l/bc79bd/32.png) [@luxs](https://community.plotly.com/u/luxs)\
**Post date:** [October 12, 2023, 10:00am UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/6 "2023-10-12T10:00:33Z")

</div>

Hi,  
This is a lovely picture and I would like to make the same, but this should be done on the plane within 3D coordinates because this contour plane is a part of a more complicated 3D image.

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [October 12, 2023, 10:05am UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/7 "2023-10-12T10:05:53Z")

</div>

If you are interested in just the function BB defined in the original post, then this code defines a slice and the lines, in each slice:

```auto
import numpy as np
import plotly.graph_objs as go

def get_the_slice(x,y,z, surfacecolor, colorscale="Hot", showscale=False):
    return go.Surface(x=x,# https://plot.ly/python/reference/#surface
                   y=y,
                   z=z,
                   surfacecolor=surfacecolor,
                   colorscale=colorscale,
                   showscale=showscale)

def get_lims_colors(surfacecolor):# color limits for a slice
    return np.min(surfacecolor), np.max(surfacecolor)

def circle(r):
    t=np.linspace(0, 2*np.pi, 100)
    return r*np.cos(t), r*np.sin(t)

BB=lambda x,y,z: x **2+y** 2+z**2 #x*np.exp(-x**2-y **2-z** 2)
h=0.45
x=np.linspace(-15,15, 200)
y=np.linspace(-15,15, 200)
x,y=np.meshgrid(x,y)
z=h*np.ones(x.shape) #Slice at the height z=0.45
surfcolor_z=BB(x,y,z)
sminz, smaxz=get_lims_colors(surfcolor_z)

slice_z=get_the_slice(x,y,z, surfcolor_z)
slice_z.update(cmin=sminz, cmax=smaxz, opacity=0.65, showscale=True)
fig=go.Figure(slice_z)

fig.update_layout(title_text='Slices in volumetric data', title_x=0.5,
         width=600,
         height=600,
                  showlegend=False,
         scene_zaxis_range=[-15,15]);

for rad in np.linspace(0, 13, 13):
    x, y= circle(rad)
    fig.add_trace(go.Scatter3d(x=x, y=y, z=(h+0.1)*np.ones(x.shape), mode="lines", line_color="white", line_width=2.5 ))

fig.show()

```

LE: The slice definition was inspired by that used in this old [notebook posted on chart-studio](https://chart-studio.plotly.com/~empet/14887/animating-slice-in-volumetric-data/#/)

---

<div class="post-metadata">

**Author:** ![luxs](https://avatars.discourse-cdn.com/v4/letter/l/bc79bd/32.png) [@luxs](https://community.plotly.com/u/luxs)\
**Post date:** [October 12, 2023, 10:22am UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/8 "2023-10-12T10:22:50Z")

</div>

Hi empet,  
The picture looks great!  
But it looks like you do not plot real isolines or contours according to BB values in the 3D domain, but the rater just draws the circles. If it is the only option available, it is ok, it is not a problem for me to calculate traces for isolines.  
I’ve seen this notebook and I do pretty similar things - this is a visualization of 3D magnetic field.

---

<div class="post-metadata">

**Author:** ![AIMPED](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/aimped/32/21758_2.png) [@AIMPED](https://community.plotly.com/u/AIMPED)\
**Post date:** [October 12, 2023, 10:35am UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/9 "2023-10-12T10:35:10Z")

</div>

Just to understand, you want to add the contour (lines) as trace in the existing 3d figure at a discrete z coordinate, right?

---

<div class="post-metadata">

**Author:** ![luxs](https://avatars.discourse-cdn.com/v4/letter/l/bc79bd/32.png) [@luxs](https://community.plotly.com/u/luxs)\
**Post date:** [October 12, 2023, 10:42am UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/10 "2023-10-12T10:42:26Z")

</div>

Hi AIMPED,  
I would like to make a contour plot, preferably independent from colours, on the 3D plane.  
Why independent? Because for making a nice picture, it is good to use a range of colours, but for clarity, it is enough to have only a few isolines, so the step for isolines should be created independently  
So basically, I would like to draw isolines on top of my coloured plane (or very close to it)

---

<div class="post-metadata">

**Author:** ![AIMPED](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/aimped/32/21758_2.png) [@AIMPED](https://community.plotly.com/u/AIMPED)\
**Post date:** [October 12, 2023, 10:43am UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/11 "2023-10-12T10:43:51Z")

</div>

Is that a yes?

---

<div class="post-metadata">

**Author:** ![luxs](https://avatars.discourse-cdn.com/v4/letter/l/bc79bd/32.png) [@luxs](https://community.plotly.com/u/luxs)\
**Post date:** [October 12, 2023, 10:46am UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/12 "2023-10-12T10:46:34Z")

</div>

Yes! You do understand correctly!

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [October 12, 2023, 11:34am UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/13 "2023-10-12T11:34:56Z")

</div>

By definition z- contourlines of a surface are the lines of intersection of the surface with the planes of eq z= const But in your case the surface itself is z= const. Could you write down mathematically what do you want to plot? The circles I plotted are not meaningless because the function BB takes constant values across the circles centered at the center of the plane z= 0.45 , and any other z= cst.

---

<div class="post-metadata">

**Author:** ![luxs](https://avatars.discourse-cdn.com/v4/letter/l/bc79bd/32.png) [@luxs](https://community.plotly.com/u/luxs)\
**Post date:** [October 12, 2023, 11:40am UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/14 "2023-10-12T11:40:02Z")

</div>

Hi empet  
If you have a look at my original post, you can see that I have 2 lines of code.

```auto
z_plane = BB[:, :, idx]
surfacecolor=z_plane

```

Now I want to draw isolines according to the values in z\_plane - which is a slice of my function values in the domain

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [October 12, 2023, 12:47pm UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/15 "2023-10-12T12:47:34Z")

</div>

This is exactly I have plotted. The locus of points where BB takes constant values are spheres These spheres intersected to planes z= cst are circles.

---

<div class="post-metadata">

**Author:** ![luxs](https://avatars.discourse-cdn.com/v4/letter/l/bc79bd/32.png) [@luxs](https://community.plotly.com/u/luxs)\
**Post date:** [October 12, 2023, 2:22pm UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/16 "2023-10-12T14:22:20Z")

</div>

Yes, it is related to this case, but you’ve plotted it because you know the answer. Which means that I need to manually calculate these isolines.  
So this is a really lovely idea of how to technically draw the lines, but It is not use Plotly ability to calculate them

With this small change, I will need to rewrite the code of line calculating.

```auto
BB=lambda x,y,z: (x+10) **2+y** 2+z**2 #x*np.exp(-x**2-y **2-z** 2)

```

But in the real task - these BB data are unknown - they are from somewhere else.

---

<div class="post-metadata">

**Author:** ![AIMPED](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/aimped/32/21758_2.png) [@AIMPED](https://community.plotly.com/u/AIMPED)\
**Post date:** [October 12, 2023, 7:21pm UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/17 "2023-10-12T19:21:54Z")

</div>

> [@luxs](#):
>
> …I need to manually calculate these isolines…but It is not use Plotly ability to calculate them

I think this is the thing. Plotly does this calculation in JS and it’s not accesible from the python side. Either you search for the corresponding functions in the plotly source code on github or you might get some inspiration from this post:

> [@Slicing 3D surface plot along a user selected axis](https://community.plotly.com/t/slicing-3d-surface-plot-along-a-user-selected-axis/40771/6):
>
> Hi @fk4517, To get the curve of intersection we need a bit of math. First the cutting plane is defined by a point M(x0, y0, 0), and two directions contained in this plane: v=[a, b, 0], w=[0, 0, 1]. We get the plane equation from the determinant: The equation of the surface is of the form z=f(x, y), and depending on the position of the plane (i.e. the direction of the vector v) the curve equation can be of the form: y =f(x, y0), y= f(x0, x) or y= f(x, h(x)). That’s why we gie cod…

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [October 12, 2023, 7:51pm UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/18 "2023-10-12T19:51:18Z")

</div>

I stressed when I posted the first time, above, that “If you are interested in just the function BB, defined in the original post, then this code defines a slice and the lines, in each slice”. I didn’t say that this method is generally applicable to any case.

---

<div class="post-metadata">

**Author:** ![luxs](https://avatars.discourse-cdn.com/v4/letter/l/bc79bd/32.png) [@luxs](https://community.plotly.com/u/luxs)\
**Post date:** [October 15, 2023, 12:58pm UTC](https://community.plotly.com/t/how-to-do-3d-plot-surface-with-isolinies/79256/19 "2023-10-15T12:58:05Z")

</div>

> [@AIMPED](#):
>
> I think this is the thing. Plotly does this calculation in JS and it’s not accesible from the python side. Either you search for the corresponding functions in the plotly source code on github or you might get some inspiration from this post:  
> [Slicing 3D surface plot along a user selected axis - #6 by empet](https://community.plotly.com/t/slicing-3d-surface-plot-along-a-user-selected-axis/40771/6)

I think I will try to convert my 3D case into the 2D plane - calculate isolines plotly and then try to convert them from 2D to 3D by adding one coordinate…
