Dash Subplot TypeError: 'Patch' object is not callable

Hello, New to Dash. I’m trying to Patch a subplot to do things like adding an extra trace somewhere and such. It gives me this error when I use the add_trace() function to the patched_figure = Patch().

This is my code.

app = Dash(__name__)
subplot = subplots.make_subplots(figure=None)  # Define Subplot

app.layout = html.Div([
        html.Button("Update Sublot", id="update-trace"),
        dcc.Graph(figure=subplot, id="my-fig"),
])

@callback(Output("my-fig", "figure"), Input("update-trace", "n_clicks"))
def my_callback(n_clicks):
    # Defining a new random trace
    v = np.arange(-3, 5.1, 0.1) # x-axis
    i = []
    for each in v:
        i.append(1e-3*(2*random.random() - 1)) # y-axis

    # Creating a Patch object
    patched_figure = Patch()
    patched_figure.add_trace(go.Scatter(x=v, y=i, mode="lines"),
                row=(1), col=(1)) # Adds trace at column and row
    return patched_figure

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

Error:

patched_figure.add_trace(go.Scatter(x=v, y=i, mode=“lines”),
TypeError: ‘Patch’ object is not callable

I’ve searched and can only seem to find solutions that involve Patch()['data'].append(...) but I think I also need the row and col parameters from add_trace() to choose as well. Any ideas?

Hi @GaNick welcome to the forums.

You are on the right track. If you ant to use the Patch() you need to stick to the methods of it. With append you can add a trace.

Does your plot really have only one trace? If this was the case, you could do this:

import dash
from plotly.subplots import make_subplots
import plotly.graph_objects as go
from dash import Input, Output,Patch, callback, html, dcc
import numpy as np
import random

app = dash.Dash(__name__)
subplot = make_subplots(figure=None)  # Define Subplot

app.layout = html.Div([
        html.Button(
            "Update Sublot",
            id="update-trace"
        ),
        dcc.Graph(
            figure=subplot, 
            id="my-fig"
        ),
])


@callback(Output("my-fig", "figure"), Input("update-trace", "n_clicks"))
def my_callback(n_clicks):
    # Defining a new random trace
    v = np.arange(-3, 5.1, 0.1) # x-axis
    i = []
    for each in v:
        i.append(1e-3*(2*random.random() - 1)) # y-axis

    # Creating a Patch object
    patched_figure = Patch()
    patched_figure['data'].append(
        go.Scatter(x=v, y=i, mode="lines")
    )
    return patched_figure


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

If you have “real” subplots, you can choose where to add the traces via the corresponding axis:

import dash
from plotly.subplots import make_subplots
import plotly.graph_objects as go
from dash import Input, Output, Patch, callback, html, dcc, State
import numpy as np
import json


app = dash.Dash(__name__)
fig = make_subplots(rows=1, cols=2)

fig.add_trace(
    go.Scatter(x=[1, 2, 3], y=[4, 5, 6]),
    row=1, col=1
)

fig.add_trace(
    go.Scatter(x=[10, 20, 30], y=[40, 50, 60]),
    row=1, col=2
)

app.layout = html.Div([
    html.Button(
        "Update Sublot",
        id="update-trace"
    ),
    dcc.Graph(
        figure=fig,
        id="my-fig"
    ),
])


@callback(
    Output("my-fig", "figure"),
    Input("update-trace", "n_clicks"),
    prevent_initial_call=True
)
def my_callback(_):
    # Defining a new random trace
    v = np.arange(4)  # x-axis
    i = np.random.randint(4, 7, size=v.shape[0])

    # Creating a Patch object
    patched_figure = Patch()
    patched_figure['data'].extend(
        [
            go.Scatter(x=v*10, y=i*10, mode="lines", xaxis="x2", yaxis="y2"),
            go.Scatter(x=v, y=i, mode="lines")
        ]
    )
    return patched_figure


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

In this example it helps paying attention to the x-axis range to distinguish between the subplots. I used patch.extend() just for demonstration, you could obviously use append() too.

Peek 2024-05-15 21-50

mred patch

This will work!

1 Like