Some plot properties ignored when used as traces/subplots

Hi,

I’m using two instances of px.imshow as traces for display in the same plot (side by side). It seems that some properties which I assign to each of them, get ignored when they are part of the overall plot.

When I .show() each of the two instances of px.imshow in isolation, all of their properties take effect exactly as expected. But when I combine them into one plot via make_subplots and add_trace, the following attributes of interest revert to their defaults in the actual figure being displayed:

  • color_continuous_scale
  • labels
  • (and the titles defined for the px.imshow subplots don’t show either, not sure I care about that detail though)

how should I be thinking about this? Is there a way to still have the axis labels and color scale defined while constructing the imshow subplots persist when they are placed as subplots?

Here’s my code building one of the figures:

plot = px.imshow(
            m,
            x=[str(i) for i in range(len(input_x))],
            y=[str(i) for i in range(len(input_y))],
            text_auto=False,
            title='foo',
            color_continuous_scale=['#00aa00', '#ffff00'] if mono_colorscale else 'Viridis',
            labels=dict(x='aaa', y='bbb'))
        plot.update_layout(coloraxis_showscale=False)
        plot.update(
            data=[{'hovertemplate':
                       'x : %{x}<br>'
                       'y : %{y}<br>'
                       'z : %{z}<extra></extra>'}])

And I’m providing it as a trace like follows:

fig.add_trace(plot.data[0], row=1, col=1)

Whereas I’m not sure about this way of adding a trace with the data[0] element as above, I can’t recall where I saw an example using this data[0] attribute, I might actually suspect that this is not the standard way to nest figures as subplots into a final figure at all.

Any idea how to nest (imshow) plots without losing the above mentioned attributes assigned to them?

I say nesting, because in some circumstances I show those imshow instances as their own plot, and so I’m looking for an elegant code strategy that would allow them to also be reused inside a multi-figure plot without losing the visual attributes assigned to them. I’m not sure whether plotly express api is designed for such compositionality or not, and would be happy to learn of non-hacky ways of accomplishing such nesting, if the python api allows.

Thanks!

Hi @matan3,

there is a major difference between the two approaches:

  • px.imshow() returns a figure object
  • make_subplots() expects trace objects to add to the figure object

You said it yourself:

Here you are extracting the first trace of the px.imshow() figure object.

You can do this, but remember that you are adding only the data (trace) to your figure object. Some of the layout of the individual figure object created by px.imshow() gets lost because it is stored in px.imshow()['layout']

In a nutshell: you will have to style your figure object (the one from make_subplots()) once you added all traces.

Please provide a MRE if you need further help.

Thanks @AIMPED

Is there a way to define an imshow and directly pass it along with its styling and headers to a figure housing multiple imshow objects? or is there no such modularity in the api, and we need to use a different subset of the plotly api in order to bestow such properties to a trace when it is a part of a multi-figure plot?

Hopefully I’m using the right terms, plots, figures, traces, a little hard to follow the terminology, i.e. is a subplot a trace? Is there documentation providing clarity on the entity relationships?

Kind regards,
Matan

Adding an MRE for the color scale …

import plotly.express as px
from plotly.subplots import make_subplots

data1 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
data2 = [[9, 8, 7], [6, 5, 4], [3, 2, 1]]

fig = make_subplots(rows=2, cols=1, subplot_titles=("Imshow 1", "Imshow 2"))
fig.add_trace(px.imshow(data1).data[0], row=1, col=1)

# the following line is being ignored, and I'm scratching my head as to how to introduce a value for
# the argument called in the case of `imshow`, "color_continuous_scale".
fig.data[0].update(continuous_colorscale=['#00aa00', '#ffff00'])

# the following is not permitted
fig.update(color_continuous_scale=['#00aa00', '#ffff00'])  # or "Viridis"

fig.show()

I am kind of stumped about how to accomplish this feat in a multi figure plot … and moreso concerned that navigating the documentation I’m unable to get it done myself.

Is it my insisting on using the plotly express subset of the api that’s making things harder or unsupported?

there’s no option to use type=‘imshow’ when passing a dictionary to add_trace, which would otherwise seem like a promising path for initializing the trace to carry over a value for continuous_color_scale …