Black Lives Matter. Please consider donating to Black Girls Code today.
Dash HoloViews is now available! Check out the docs.

Assign surface and traces to groups which may be toggled

I devised the following code to mix the features of a surface plot and mesh -

x=np.linspace(-np.pi,np.pi,50)
u,v = np.meshgrid(x,x)
data = []
line_marker = dict(color='#000000', width=2)
for index in range(3):
    w = np.sin((u**2+v**2)/(index+1))
    for i, j, k in zip(u,v,w):
        data.append(go.Scatter3d(x=i, y=j, z=k, mode='lines', line=line_marker,name="trace{}".format(index)))
    for i, j, k in zip(u.T,v.T,w.T):
        data.append(go.Scatter3d(x=i, y=j, z=k, mode='lines', line=line_marker,name="trace{}".format(index)))
    data.append(go.Surface(x=u,
                   y=v,
                   z=w,name="trace{}".format(index)))
fig = go.Figure(data=data)
iplot(fig)

The plot is online at this link. How can I add the following features? -

  1. The 3D mesh+surfaces need to be assigned to a group that can be toggled on or off.
  2. I want the color of the surface to be fixed, independent of z-value. This is because the mesh gives me enough visual information about the surface. I would also want to assign the solid surface colors to the toggle buttons. Also get rids of the colorbar.
  3. Get rid of the numerous trace legends populating the right hand side of the figure.

EDIT 1:
Added groups and showlegend optons to the code, but it got rid of the legends completely. Still do not know how to restrict the colorscale to a single color.

x=np.linspace(-np.pi,np.pi,50)
u,v = np.meshgrid(x,x)
data = []
line_marker = dict(color='#000000', width=2)
for index in range(3):
    w = np.sin((u**2+v**2)/(index+1))
    groupname="group{}".format(index)
    for i, j, k in zip(u,v,w):
        data.append(go.Scatter3d(x=i, y=j, z=k, mode='lines', 
                                 line=line_marker,
                                 showlegend=False,
                                 legendgroup=groupname))
    for i, j, k in zip(u.T,v.T,w.T):
        data.append(go.Scatter3d(x=i, y=j, z=k, mode='lines',
                                 line=line_marker,
                                 showlegend=False,
                                 legendgroup=groupname))
    data.append(go.Surface(x=u,y=v,z=w,
                           name="trace{}".format(index),
                           showlegend=True,
                           legendgroup=groupname))    
layout = go.Layout(
    legend=dict(x=0,y=1,traceorder='normal',)
)
fig = go.Figure(data=data,layout=layout)
iplot(fig)

Still do not know how to restrict the colorscale to a single color.

You just need to set the first and last color in colorscale to the same value:

fig['data'][-1]['colorscale'] = [[0, 'rgb(150, 150, 150)'],[1, 'rgb(150, 150, 150)']]

Turn off the colorbar by setting showscale to False:

You can find some of these things by searching the Python figure reference page:

Here’s a link to your modified figure: https://plot.ly/~jackp/18322

Note that you have 3 surface traces, so all of their colorscale attributes need to be converted.

It looks better IMO if you increase the specular attribute under lighting to 2 (max):

Here’s the Python code I used:

import plotly.plotly as py

fig = py.get_figure('https://plot.ly/~jackp/18313/')

for i in range(len(fig['data'])):
    if fig['data'][i]['type'] == 'surface':
        print(i, fig['data'][i]['type'])
        fig['data'][i]['colorscale'] = [[0, 'rgb(150, 150, 150)'],\
                                        [1, 'rgb(150, 150, 150)']]
        fig['data'][i]['lighting']['specular'] = 2

py.iplot(fig, filename='single-color-surface')

There should be some slight modification then you are good to go

import plotly.plotly as py
import plotly.graph_objs as go
mesh_size=50
x=np.linspace(-np.pi,np.pi,mesh_size)
u,v = np.meshgrid(x,x)
data = []
data_scatter=[]
data_surface=[]
line_marker = dict(color=’#000000’, width=2)
for index in range(3):
w = np.sin((u2+v2)/(index+1))
groupname=“group{}”.format(index)
for i, j, k in zip(u,v,w):
data_scatter.append(go.Scatter3d(x=i, y=j, z=k, mode=‘lines’,
line=line_marker,
showlegend=False,
legendgroup=groupname))
for i, j, k in zip(u.T,v.T,w.T):
data_scatter.append(go.Scatter3d(x=i, y=j, z=k, mode=‘lines’,
line=line_marker,
showlegend=False,
legendgroup=groupname))
data_surface.append(go.Surface(x=u,y=v,z=w,
name=“trace{}”.format(index),
showlegend=True,
legendgroup=groupname,colorscale=[[0, ‘rgb(150,150,150)’],
[1, ‘rgb(150,150,150)’]]))
layout = go.Layout(
legend=dict(x=0,y=1,traceorder=‘normal’,)
)
fig = go.Figure(data=data_scatter,layout=layout)
fig1 = go.Figure(data=data_surface,layout=layout)
#py.iplot(fig)
py.iplot(fig1)

I will specify the solutions of your questions respectively

  1. Create separate arrays for scatter and surface plots then you can plot them separately
  2. You can change the colorscales for surface plot as i have shown. The alternative method to do is to create a dictionary for colorscales and assign them for each w
  3. Colorbar texts can be handled by colorbar option. It is called ticktext

For more information, Please see the reference