Zmid issue with coloraxis in go.Heatmap subplots

Hi.

When doing subplots for heatmaps, zmid works when not sharing colorscales through the coloraxis option. But when, I share colorscales using coloraxis, then zmid ceases to work.

I believe this is an unexpected issue.

More details: As you may know, in order to share colorscales thorugh plots, you need to use the coloraxis option like ‘coloraxis’, ‘coloraxis2’, ‘coloraxis3’ and so on. Then, you need to customize the colorbars through the update_layout of the figure. In here, you can pass options such as your desired colorscale, colorbar options such as x padding and such. However, you can’t pass zmid here. zmid stays at the figure creation. So, when I do this, it seems zmid does not get recognized. Of course, I need to zmid continue working even when sharing colorscales through coloraxis: I want the middle of the colorscales to be the provided zmid value.

Meanwhile, any hack I can go around? @adamschroeder

Thank you if you can help.

hi @maulberto3
Welcome back :slight_smile: We haven’t seen you in a while.

That’s a good question. Can you please share MRE with us?

1 Like

Sure, something like this hopefully can help. As you can see, in one function I create the heatmaps, return them, and on another one, I create the subplots figure, consume them and then just return it to the predefined dcc.Graph Ouput. EDIT: I initially put an image, then changed it to text code for ease debugging.

def calc_sub_figs(z_pvs):
    figs = []
    for key, z_pv in z_pvs.items():
        fig = go.Heatmap(
            x=z_pv.columns.tolist(),
            y=z_pv.index.tolist(),
            z=z_pv.to_numpy(),
            xgap=4,
            ygap=4,
            coloraxis='coloraxis2' if key == 'M. Técn.' else 'coloraxis',
            # colorbar={'x': 1.1 if key == 'M. Técn.' else 1},
            # showscale=True if key == 'M. Técn.' else False,
            zmid=0 if key == 'M. Técn.' else None,
            zmax=z_pv.max().max(),
            zmin=z_pv.min().min(),
            # text=z_pv.round(2),
            # colorscale='RdYlGn' if key == 'M. Técn.' else 'Blues',
        )
        sub_cols = z_pv.shape[1]
        figs.append((key, fig, sub_cols))
    return figs

def create_fig(figs, linea_labels_tasas_rent):
    fig = make_subplots(
        rows=1,
        cols=len(figs),
        shared_xaxes=True,
        shared_yaxes=True,
        # subplot_titles=[key[:15] for key, _, _ in figs],
        column_widths=[0.1 * sub_cols for _, _, sub_cols in figs],
        # horizontal_spacing=0.095,
    )

    # adding figs
    for i, (key, fig_, sub_col) in enumerate(figs, start=1):
        fig.add_trace(fig_, 1, i)

    fig.update_layout(
        coloraxis=dict(colorscale='Blues', colorbar_x=1),
        coloraxis2=dict(colorscale='RdYlGn', colorbar_x=1.1),
        autosize=True,
        height=325 + 60 * (len(linea_labels_tasas_rent) - 3),
        width=1200,
        # margin_r=100
        )

    fig.update_xaxes(
        # visible=False,
        tickangle=45,
        side='top',
        # tickfont_size=15
        )

    return fig

oh no, that’s not the best way, @maulberto3 :slight_smile: It’s hard to copy everything from the image to our code editor.

Try to follow the instructions in this post.

Sorry for that, I edited as text now.

@maulberto3
When you define subplots of heatmaps and use coloraxis, don’t set zmin, zmid, zmax within heatmap definition, but cmin, cmid, cmax as coloraxis keys:

import plotly.graph_objects as go
import numpy as np

fig = go.Figure().set_subplots(rows=1, cols=2)
fig.add_trace(go.Heatmap(x=np.arange(5), y=np.arange(4), z=np.random.randint(2,7, (4,5)), coloraxis="coloraxis"), row=1, col=1)
fig.add_trace(go.Heatmap(x=np.arange(4), y=np.arange(4), z=np.random.randint(1, 8, (4,4)), coloraxis="coloraxis"), row=1, col=2)
fig.update_layout(width=700, height=400, coloraxis=dict(colorscale="matter_r", cmin=1, cmid=4, cmax= 7))

1 Like

Let me try that.

It does. Now I understand. Thank you @adamschroeder and @empet

1 Like