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

Make_subplots with 3d surfaces - how to set camera/scene

There seems to be no way to set the camera/eye angles when creating a chart with subplots of 3d surfaces. This apparently is because the ‘scene’ argument in the traces that you would append in make_subplots means something different than ‘scene’ would in a standalone plot. Is that right? Furthermore what does scene mean in this context?

This code:

camera=dict(
eye=dict(x=0,y=0,z=0.5))

swap_surface = dict(type=‘surface’
,x=x,y=y,z=z
,showscale=False
,cmin = zmin, cmax = zmax
,opacity = 0.9
,lighting = lighting, colorscale = colorscale,scene=dict(camera=camera))

x, y, z = yield_surface(lo=0,hi=100,aggfield=‘treas_yield’)
treas_surface = dict(type=‘surface’
,x=x,y=y,z=z
,showscale=False
,cmin = zmin, cmax = zmax
,opacity = 0.9
,lighting = lighting, colorscale = colorscale,scene=dict(camera=camera))

figz = tools.make_subplots(rows=2
,cols=1
,specs = [[{‘is_3d’:True}],[{‘is_3d’:True}]]
,vertical_spacing = 0.1, horizontal_spacing = 0
,subplot_titles = (‘US Treasury Curve’,‘Swap Curve’)
,shared_xaxes=True
)
figz.append_trace(swap_surface,1,1)
figz.append_trace(treas_surface,2,1)

Produces this error:
ValueError:
Invalid value of type ‘builtins.dict’ received for the ‘scene’ property of surface
Received value: {‘camera’: {‘eye’: {‘x’: 0, ‘y’: 0, ‘z’: 0.5}}}

The 'scene' property is an identifier of a particular
subplot, of type 'scene', that may be specified as the string 'scene'
optionally followed by an integer >= 1
(e.g. 'scene', 'scene1', 'scene2', 'scene3', etc.)

What are scene1, scene2, and scene3? None of the documentation online shows proper usage of this argument.
How do i simply give these 2 subplots a different starting eye angle setting?
Thanks

@datadrinkr, tools.make_subplots() doesn’t accept subplot_titles and shared_xaxes (no shared axes in general). When you append each trace to a subplot cell, it has assigned a scene. For the first cell it is scene1, for the second one, scene2.

To understand how it works, just run the code below:

import numpy as np
import plotly.graph_objs as go
from plotly import tools as tls

x=np.linspace(-1, 1, 100)
y=np.linspace(-1, 1, 100)
x, y=np.meshgrid(x, y)
z=x**2+y**3

trace=dict(type='surface',
          x=x,
          y=y,
          z=z,
          colorscale='Viridis',
          showscale=False)
figz = tls.make_subplots(rows=2 ,cols=1,
                           specs = [[{'is_3d':True}],[{'is_3d':True}]],
                           vertical_spacing = 0.02
                           )
                         
figz.append_trace(trace, 1, 1)
figz.append_trace(trace, 2, 1)
fw=go.FigureWidget(figz)
print(fw.layout)


with fw.batch_update():
    fw.layout.update(width=800, height=1000) 
    fw.layout.scene1.camera.eye=dict(x=0, y=0, z=2.15)   
fw    

Hence, camera is an attribute to go.Layout.scene, and cannot be set in the trace definition.

Thanks @empet , that helps clarify how to use camera. I’m trying to use that in Dash, will attempt to get figurewidget to display in a dcc.Graph placeholder.

To your other point - subplot_titles DOES work with tools.make_subplots, but ONLY if shared_axes is set to True. This is perhaps unintended but is a solution that I found online and actually works here. Otherwise, how would you add titles to each of these subplots (open to an alternative, more ‘correct’ solution on that one, but subplots absolutely need a title).

Thanks,

Another issue is that it appears that figurewidget does not accept dates in the axes.

/apps/valrs/tools/python/python3.6.1/lib/python3.6/site-packages/ipykernel/jsonutil.py in json_clean(obj)
195
196 # we don’t understand it, it’s probably an unserializable object
–> 197 raise ValueError(“Can’t clean for JSON: %r” % obj)

ValueError: Can’t clean for JSON: datetime.date(2018, 5, 1)

@datadrinkr, I converted figz to FigureWidget only to display it faster. You can avoid this conversion and perform the updates on figz(I refer here to my example):

figz.layout.update(width=800, height=`1000)
figz.layout.scene1.camera.eye=dict(x=0, y=0, z=2.15)

Hence you shouldn’t find a workaround for displaying a FigureWidget in Dash.

Could you write down here, please, your date example that fails?