Plotly express scatter_3d keeps changing text size

I’m developing an app in Dash and Plotly which uses plotly.express.scatter_3d. The marker size is mapped to some data values, but I want the size of the text to remain unlinked to marker size. Currently, the text size is very tiny for some values.

I’ve tried various approaches. e.g.

fig.update_layout(uniformtext_minsize=14, uniformtext_mode='hide')

And:

fig.update_layout(
        font=dict(
            size=10,  # Set the font size here
        )
    )

However, neither are working. Both seem to work when the app is first loaded, but as soon as a callback it triggered, they stop working and the text is suddenly very small.

Here’s the app when it first loads:

And here is it after I trigger a callback:

Here’s the code I’m using to generate the plot:

def make_3d_scatter(pos,
                    topn,
                    smooth,
                    max_size,
                    symbol=None):
    pdat = dataframe()
    if isinstance(pos,str):
        pos = [pos]
    if len(pos) == 1:
        pos = pos[0]
        pdat = pdat.loc[pdat.alt_pos == pos,:].copy()
        pdat["weight_norm"] = _norm_data(pdat.weight.tolist(),smooth)
        symbol = None
        make_comb = False
    elif len(pos) > 1:
        pdat = pdat.loc[pdat.alt_pos.isin(pos),:].copy()
        pdat["weight_norm"] = _norm_data(pdat.weight.tolist(),smooth)
        symbol="alt_pos"
        make_comb = True
    if topn:
        pdat = pdat.sort_values(by="weight",ascending=False).\
            groupby(["label","id"]).\
            head(topn).\
            sort_values(by=["weight"],ascending=False).\
            reset_index(drop=True,inplace=False)
        
    title="3D scatter in RoBERTa output layer vector space, weighted (dot size) by LIME weights"
    
    fig = px.scatter_3d(
        pdat,
        x="X",
        y="Y",
        z="Z",
        text="lemma",
        size="weight_norm",
        # color_discrete_sequence=["#009E73","#56B4E9"],
        color="label",
        symbol=symbol,
        # labels=NAME_MAP,
        size_max=max_size,
        opacity=.6,
        title=title,
        hover_data=HOVER_MAP
    )
    #set text colour to marker colour
    fig.for_each_trace(lambda t: t.update(textfont_color=t.marker.color, textposition='top center'))
    
    #hard code height
    fig.update_layout(
        autosize=True,
        height=800,)
    
    # make friendly labels
    if make_comb:
        comb_map = {f"{cat}, {pos}":f"{cat_val}: {val}" for cat,cat_val in CAT_MAP.items() for pos,val in NAME_MAP.items()}
    else:
        comb_map = {**NAME_MAP,**{"AMYLOID_NEG": "Amyloid negative", "AMYLOID_POS": "Amyloid positive"}}
    fig.for_each_trace(lambda t: t.update(name = comb_map[t.name],
                                  legendgroup = comb_map[t.name],
                                  hovertemplate = t.hovertemplate.replace(t.name, comb_map[t.name])
                                 )
                      )
    
    # set text size
    # fig.update_layout(uniformtext_minsize=14, uniformtext_mode='hide')
    fig.update_layout(
        font=dict(
            size=10,  # Set the font size here
        )
    )
    fig.update_layout(template="plotly",
                      plot_bgcolor='rgba(0, 0, 0, 0)',
                      paper_bgcolor='rgba(0, 0, 0, 0)',
                     )
    return fig

The full app repo is here.

Does anyone know how to solve this? Is it a bug?

My guess world be, have you are returning a figure somewhere without using your custom layout.

I have to confess, that I did not look thru all your code.

Yeah, it’s not exactly a MRE. But the answer is no, I think. I only return the figure using that function. It’s just that it only seems to have an effect the first time the page loads. After that, it reverts to plotly defaults. I think it’s actually a bug.

Try changing your text size after the above lines. I think the templates might include references to text size.

Thanks for the suggestion! I’ve actually already tried that after posting. Doesn’t make a difference.

Do you think you could create a MRE for that?

I can but am very busy now. I’ll post again once I get a chance!