Two subplots with union slider

Hey Guys,

Can you have a quick check at what I am doing wrong here. I am attempting two have two subplots controlled by the same slider with data from two different lists. I have already written some pipeline but can’t seem to get this working. Heatmap has a problem with scale (see images)

I have had a look at some of the other questions about this topic and cant seem to get it working.

import torch
import plotly.graph_objects as go
from plotly.subplots import make_subplots

epochs = [i for i in range(61)]
data = [torch.randn(10, 15) for i in range(61)]
flat_data = [tensor.flatten() for tensor in data]
fig = make_subplots(rows=1, cols=2)

fig.add_trace(go.Histogram(x=flat_data[0], histfunc="count"), row=1, col=1)
fig.add_trace(go.Heatmap(z=data[0], colorscale='RdBu_r', zmid=0), row=1, col=2)

steps = []
for i, epoch in enumerate(epochs):
  step = dict(
      method="restyle",
      args=[{"z": [data[i]], "x": [flat_data[i]]}],
      label=str(epoch)
  )
  steps.append(step)

sliders = [dict(
    active=0,
    currentvalue={"prefix":"Epoch: "},
    pad={"t": 50},
    steps=steps
)]
fig.update_layout(
    autosize=False,
    sliders=sliders,
    width=500,
    height=500,
)
fig.show()


Normal variant without slider

Hi @Munir ,

Unfortunately there is a bug when one of the subplots is a go.Heatmap. I added a few attributes to your original fig:

import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np

r, c = 8, 8  #10, 15
epochs = np.arange(5)
mydata = [np.random.randn(r, c) for _ in epochs]
flat_data = [tensor.flatten() for tensor in mydata]
fig = make_subplots(rows=1, cols=2)

fig.add_trace(go.Histogram(x=flat_data[0], histfunc="count"), row=1, col=1)
fig.add_trace(go.Heatmap(x=np.arange(c), y=np.arange(r), z=mydata[0], 
                         coloraxis='coloraxis', x0=0, dx=1, y0=0, dy=1),
                         row=1, col=2);

steps = [dict(method='restyle',
              args=[{ 'x': [flat_data[k]], 'z': [mydata[k]]}, 
                    {'traces': [0,1]}
                   ], 
              label=str(epoch)) for k, epoch in enumerate(epochs)]
sliders = [dict(active=0,
                currentvalue={'prefix':'Epoch: '},
                pad={'t': 50},
                steps=steps)]
fig.update_layout(title_text="Subplots with unique slider for restyle", 
                  width=800, height=550,  font_size=11,
                  coloraxis=dict(colorscale='RdBu_r', cmid=0), bargap=0.01,
                  xaxis_range=[-3,3],
                 sliders=sliders)
fig.show()

Since the xaxis2 (the axis the heatmap is referenced to) displays wrong ticks, starting from the second step, I updated the layout, as:

fig.update_layout(xaxis2_range=[-0.5, c-0.5], yaxis2_range=[-0.5, c-0.5])

Now the xaxis2 tick labels are preserved from step to step, but the heatmap is not drawn correctly.
Replacing the go.Heatmap definition, from row=1, col=2, by a go.Surface, it works:
https://chart-studio.plotly.com/~empet/16207. To check it, please download the notebook, because chart-studio does not display the slider.

As a conclusion, you should open an issue on plotly.js (not plotly.py), but set the r, and c as I did, because it is simpler to reproduce an issue with a reduced volume of data.
If you are asked to provide the json version of your figure, then with these lines of code:

import json
json_string=fig.to_json(pretty=True)
with open("myfig.json", "w") as outfile:
    outfile.write(json_string)

save it as a json file, and post it somewhere, to be downloaded.

2 Likes