Fig.add_shape() implemented for partial updates?

Is it possible to add shapes to a figure using partial property updates with patched_fig[...]?

Hi @luggie.

Thats possible. The shapes are stored in a list in the figure layout:

figure['layout']['shapes']

So you can use the append like so:

patched_fig = Patch()

patched_fig['layout']['shapes'].append(new_shape)

Keep in mind, that new_shape is a dictionary, here an example:

1 Like

hi @luggie

@AIMPED 's answer is correct. To build on his answer, what I usually do to figure out how to use Patch() is I try to build the figure before hand and inspect it.

from dash import Dash, html, dcc, Input, Output, Patch
import plotly.express as px

df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length", color='petal_length')
fig.add_shape(type="rect",
    xref="x domain", yref="y domain",
    x0=0.6, x1=0.7, y0=0.8, y1=0.9,
)

print(fig['layout']['shapes'][0])

Playing around with it, I was able to access the shape added with the print statement above. This is the printout:

layout.Shape({
‘type’: ‘rect’, ‘x0’: 0.6, ‘x1’: 0.7, ‘xref’: ‘x domain’, ‘y0’: 0.8, ‘y1’: 0.9, ‘yref’: ‘y domain’
})

Since this is a dictionary, now I know that I can use the .update() method within Patch(). So now, I delete the top section and add a callback with the Patch()

from dash import Dash, html, dcc, Input, Output, Patch
import plotly.express as px

df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length", color='petal_length')
# fig.add_shape(type="rect",
#     xref="x domain", yref="y domain",
#     x0=0.6, x1=0.7, y0=0.8, y1=0.9,
# )
#
# print(fig['layout']['shapes'][0])

app = Dash(__name__)
app.layout = html.Div([
    html.H1("Adding Shapes with Patch()"),
    html.Button("Add my shape", n_clicks=0, id="my-button"),
    dcc.Graph(figure=fig, id="my-graph"),
])


@app.callback(
    Output("my-graph", "figure"),
    Input("my-button", "n_clicks"),
    prevent_initial_call=True,
)
def add_data_to_fig(n_clicks):
    patched_figure = Patch()
    patched_figure['layout']['shapes'][0].update({
        "type": "rect",
        "xref": "x domain",
        "yref": "y domain",
        "x0": 0.6,
        "x1": 0.7,
        "y0": 0.8,
        "y1": 0.9
    })
    return patched_figure


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

ared patch

2 Likes