Changing number of subplots while dash app is running

Dear Dash Python Community,

I created a Plotly subplot figure within my DashApp. I’m able to change the number of subplots by the help of the selection within a dropdown menu.
That works fine so far.
I have to ensure a square aspect ratio for all subplots.
The positioning and scaling of my subplots gets disturbed as soon as I’m using the update_xaxes function and fix the “scaleanchor” to the corresponding y axis.
The layout and the size of my individual subplot now depends on the number of subplots in the initial callback. I can change the inital number of subplot from my dropdown menu as I simply prevent the initial call. I have to reload my webbrowser/ DashApp to be able to change this behavior.
Is there a way to “reload” the initial state of the Callback function or is there any other way to ensure a square aspect ratio?
I highly appreciate any comments and help!

Plotly Version: 5.16.1
Dash Version: 2.12.1

Here comes the code:

app = Dash(__name__)

app.layout = html.Div([
    dcc.Dropdown(
        id='subplot-dropdown',
        options=[
            {'label': '1 Subplot', 'value': 1},
            {'label': '2 Subplots', 'value': 2},
            {'label': '3 Subplots', 'value': 3},
            {'label': '4 Subplots', 'value': 4}
        ],
        value = 1
    ),
    dcc.Graph(id='subplot-fig', style = {'width' : '80vw','height' : '80vh'},
                                config= {'responsive' : True} )
    ])

@app.callback(
    Output('subplot-fig', 'figure'),
    Input('subplot-dropdown', 'value'), 
    prevent_initial_call=True
)
def update_subplot_figure(selected_value):

# Define a dictionary to map selected_value to rows and cols
    subplots_mapping = {
        1: (1, 1,),
        2: (1, 2,),
        3: (2, 2,),
        4: (2, 2,)
    }
    rowsi, colsi = subplots_mapping[selected_value]

    subplots_position = {
            0: (1, 1),
            1: (1, 2),
            2: (2, 1),
            3: (2, 2)
        }

    fig = make_subplots(rows = rowsi, cols = colsi)
    # add traces to the subplot, dependend on the dropdwon value
    for i in range(selected_value):
        # defien the row and col for the subplot
        rowi, coli = subplots_position[i]
        fig.add_trace(go.Scatter(name = f'Legendtext {i}',
                    x = [0,1,1,0,0,1,1,2,2,3,3,2,2,3],  y = [0,0,1,1,3,3,2,2,3,3,1,1,0,0] ), 
                      row= rowi, 
                      col= coli,
                      )  
   # force a square aspect ratio for every subplot (could also do this in a loop)...here comes the problem
    fig.update_xaxes(scaleanchor = 'y1', scaleratio = 1, row = 1, col =1) 
    fig.update_xaxes(scaleanchor = 'y2', scaleratio = 1, row = 1, col =2) 
    fig.update_xaxes(scaleanchor = 'y3', scaleratio = 1, row = 2, col =1) 
    fig.update_xaxes(scaleanchor = 'y4', scaleratio = 1, row = 2, col =2) 

    return fig

if __name__ == '__main__':
    app.run_server(debug=True)

HI @cr_sws welcome to the forums.

Is there a reason you want to do this with subplots ore could you just return n figures to your layout?

So instead of adding subplots to your initial figure, add new figures witch the information you wan to add.

Hi AIMPED,
thank you for the fast response.
I quickly checked how to add multiple Figures to one dcc.Graph but could’nt find anything. I know how to add multiple traces but they will be shown in a single Figure.
I’m also not sure how or if it is possible to add dcc.Graphs to my layout while the dash app is running!?
May I ask you if you have any idea where I can find some more information about this?

The reason why I was using subplots is just because it was “recommended” by the plotly webpage and I could’nt find another solution (but to be fair I didn’t look for one…).

1 Like

Hi!

Thats not possible, you are right. You would need to create your app layout dynamically.

Yes, thats possible but requires intermediate knowledge of dash, I would say.

Fair enough :wink:

I actually do not like to use subplots as the arangement of legends, colorbars, titles and so on for each sublot is quite cumbersome IMHO. That’s the reason for me mentioning the different approach.

As for how to create content dynamically, here is an example:

Hi AIMPED,
thanks again for the suggestions. I’ll check the dash example you sent me!

1 Like

perfect, let us know if you need further assistance :raised_hands: