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!

Hi,
I have the same behaviour.
I am using a graph existing out of two figures.
One is a scatter3d for text only and the second is a mesh3d.
The first figure is like expected.
But when I manipulate the text content and redraw the figure, the manipulated text is very small. Text which was not changed remains at the first style until it is changed by another action.
I do not understand how the font size can be changed for one element of the list of text items.
I am using clientside_callback to redraw the figure and I am changing figure data in dcc.store only. No layout is changed. I am using the stored layout data from the first figure to redraw the new one.
It would be very nice to get some hints how to fix it.

Sorry for that post!
Meanwhile I found I can manipulate the Scatter3D textfont by changing the size.
But the first figure uses textfont-size “14” and I have to double it to “28” for each changed text item.
Not the best but it is working.

Hey @gerhard, welcome to the forums!

It usually helps a lot if you provide a small code snippet which we can copy&paste and run it on our side to reproduce the issue you are facing. :slight_smile: