# \`\`\`Graph.extend\`\`\` data property not working when used with patten matching callback

**URL:** <https://community.plotly.com/t/graph-extend-data-property-not-working-when-used-with-patten-matching-callback/59552>\
**Category:** Dash Python\
**Created:** [December 27, 2021, 10:04am UTC](https://community.plotly.com/t/graph-extend-data-property-not-working-when-used-with-patten-matching-callback/59552 "2021-12-27T10:04:18Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![supratik](https://avatars.discourse-cdn.com/v4/letter/s/e274bd/32.png) [@supratik](https://community.plotly.com/u/supratik)\
**Post date:** [December 27, 2021, 10:04am UTC](https://community.plotly.com/t/graph-extend-data-property-not-working-when-used-with-patten-matching-callback/59552/1 "2021-12-27T10:04:18Z")

</div>

So, I’m dynamically adding `dcc.graphs` to a `div` at the click of a button using pattern matching callbacks.

 ![1](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/0/6/067f06e78070cb67044c5a5bec5f5c226807dd38.png)  
so when I click the button highlighted in red, the entire blue portion gets added below it.

I am also using another callback like this

```auto
@app.callback(Output({'type':'graph-1','index':MATCH}, 'extendData'),
               Input({'type':'interval','index':MATCH}, 'n_intervals'))
def update_graph(graph):
    /*some logic*/
    return data /*[ideally should be on len 1 as it gets updated every 1 second]*/

```

What this callback does is update the graph every 1 second with real-time values when the sync toggle is turned on.  
This works fine and does the job that I want it to do. However, when I add/delete another blue plot to the main `div` component, the `update_graph` function gets messed up and gives this kind of output. (Based on correct values it should have been a straight line…similar to 0-8 on x axis).

**![](https://lh5.googleusercontent.com/p3THOfK1_JKV9YuzmEsusjRV7EKTwpZpVO7TtFXbQbgMGAstMz-0z_1xPrVNsfR-fPiYe0_mzYjAIQmeLpVbGSDwxT5W-5ptsGmi8ncbK6S5XY-bxel-esvT18Z3donOzFN-IA8i)**

PS. I can add/delete as many graphs as I want before starting the sync toggle on any graph. But, if I do it during/after the sync toggle then I get this kind of a result.

Also adding a few callbacks for more clarification

```auto
def new_time_sig_plot(idx):
  new_div = html.Div(id={'type':'t-plot','index':idx}, children=[
    html.Div(id={'type': 'time-sig-options','index':idx}, className='filters', children=[
      daq.ToggleSwitch(id={'type':'sync-toggle','index':idx}, label='SYNC', value=False, size=40, color='#2D6BCF'), 
      dcc.Dropdown( placeholder='group', id={'type': 'group-filter','index':idx}, className='input-attrs', options=group_options, value=None),
      dcc.Dropdown( placeholder='variable', id={'type': 'variable-filter','index':idx}, className='input-attrs', options=variable_options, value=None),
      dcc.Dropdown( placeholder='node', id={'type': 'node-filter','index': idx}, className='input-attrs', 
                  options=[dict(label=option,value=option) for option in nodes_options], value=nodes_options[-1]),
      dcc.Dropdown( placeholder='component', id={'type': 'component-filter','index':idx}, className='input-attrs', options=component_options, value=None),
      html.Button('⚙ Filter', id={'type': 'apply-time-filters', 'index':idx},className="filter-btn", n_clicks=0),
      html.Button('🗑️', id={'type': 'del-t-plt', 'index':idx},className='del'),
    ]),
    dcc.Dropdown(placeholder='Choose time signal',id={'type': 't-signal-selector', 'index':idx},options=all_time_signals,multi=True,value=[]),
    dcc.Graph(id={'type':'graph-1','index':idx}, figure=dict(data=[],layout=time_sig_layout), animate=True),
    dcc.Interval(id={'type':'interval','index':idx},interval=1*1000)
  ])
  return new_div

def new_node_sig_div(idx):
  #pretty similar to the above function but it doesn't use the update_graph callback so I'm skipping it
  return new_div

@app.callback(
  [Output('time-sig-div', 'children'), Output('node-sig-div', 'children')],
  [Input('new-t-plt', 'n_clicks'), Input({'type': 'del-t-plt','index': ALL}, 'n_clicks'),
   Input('new-n-plt', 'n_clicks'), Input({'type': 'del-n-plt','index': ALL}, 'n_clicks')],
  [State('time-sig-div', 'children'), State('node-sig-div', 'children')],
  prevent_initial_call = False)
def edit_time_div(add_time, del_time, add_node, del_node, time_div, node_div):
  global group_options; global variable_options; global component_options; global all_time_signals; global all_node_signals;
  triggered = [t["prop_id"] for t in dash.callback_context.triggered][0]

  add_time = add_time or 0; add_node = add_node or 0

  if triggered == 'new-t-plt.n_clicks' or triggered == '.':
    if len(time_div) == 5: return dash.no_update
    time_div.append(new_time_sig_plot(add_time))

  if triggered == 'new-n-plt.n_clicks' or triggered == '.':
    if len(node_div) == 5: return dash.no_update
    node_div.append(new_node_sig_div(add_node))
  
  if triggered[-20:-17] == 'del':
    ID = json.loads(triggered[0:-9])
    del_idx = ID["index"]

    if ID["type"] == 'del-t-plt':
      for div_idx, div in enumerate(time_div):
        if del_idx == div["props"]["id"]["index"]:
          del time_div[div_idx]
          break
    else:
      for div_idx, div in enumerate(node_div):
        if del_idx == div["props"]["id"]["index"]:
          del node_div[div_idx]
          break
  
  # print(time_div[0])
  return time_div, node_div

```

---

<div class="post-metadata">

**Author:** ![jlfsjunior](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jlfsjunior/32/16061_2.png) [@jlfsjunior](https://community.plotly.com/u/jlfsjunior)\
**Post date:** [December 27, 2021, 12:32pm UTC](https://community.plotly.com/t/graph-extend-data-property-not-working-when-used-with-patten-matching-callback/59552/2 "2021-12-27T12:32:36Z")

</div>

Hi @supratik,

Could you share the callback triggered by “Add Time Plot” (that creates the new `dcc.Graph` and `dcc.Interval` components)?

---

<div class="post-metadata">

**Author:** ![supratik](https://avatars.discourse-cdn.com/v4/letter/s/e274bd/32.png) [@supratik](https://community.plotly.com/u/supratik)\
**Post date:** [December 27, 2021, 12:59pm UTC](https://community.plotly.com/t/graph-extend-data-property-not-working-when-used-with-patten-matching-callback/59552/3 "2021-12-27T12:59:54Z")

</div>

hello jlfs, thanks for the response.

I’ve added the `edit_time_div` callback that you asked for in the original post.

---

<div class="post-metadata">

**Author:** ![jlfsjunior](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jlfsjunior/32/16061_2.png) [@jlfsjunior](https://community.plotly.com/u/jlfsjunior)\
**Post date:** [December 27, 2021, 1:28pm UTC](https://community.plotly.com/t/graph-extend-data-property-not-working-when-used-with-patten-matching-callback/59552/4 "2021-12-27T13:28:34Z")

</div>

Thanks! It makes sense that it is like this…

I suspect that the unusual behavior has to do with the updates in the `dcc.Interval` component. Every time you add/remove a graph, you are rewriting the entire div, including the specific `dcc.Interval` for existing graphs, then your “problematic” callback gets triggered with the original values (`n_intervals`and so on) in the moment the callback updating the div is done.

If that is the case, I would suggest you to have a global `dcc.Interval` that is never rewritten. Then you just need to change the `update_graph` callback to use `Output({'type':'graph-1','index': ALL}, 'extendData')` and update all graphs in the same component. This is much better in terms of performance as well, as this callback won’t be triggered more often than once in a second for all components.

---

<div class="post-metadata">

**Author:** ![supratik](https://avatars.discourse-cdn.com/v4/letter/s/e274bd/32.png) [@supratik](https://community.plotly.com/u/supratik)\
**Post date:** [December 30, 2021, 1:39pm UTC](https://community.plotly.com/t/graph-extend-data-property-not-working-when-used-with-patten-matching-callback/59552/5 "2021-12-30T13:39:21Z")

</div>

Hi, I tried to implement your suggestions but pretty much got the same results.  
If I have my sync toggle ON and then try to add a new plot, I get the error saying `gd.data must be a valid array`.

I can also turn off the sync button and then add a new plot, but then my graph gets messed up like this.

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/2/3/23340756eb7fdca13477218199160eea05638243.png)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/3/7/371e43d4d3ba45910f10efcb5c644f53f43ceca7.png)

Here is my update graph callback

```auto
@app.callback(Output({'type':'graph-1','index':ALL}, 'extendData'),
               Input('interval', 'n_intervals'),
              [State({'type':'graph-1','index':ALL}, 'figure'),
               State({'type': 't-signal-selector', 'index': ALL}, 'value'),
               State('hdf-filename', 'value'),
               State('time-sig-div', 'children')], prevent_initial_call=True)
def update_graph(interval, graphs, input_state, f5_file, time_div):
  output = []
  if len(graphs) == 0:
    return dash.no_update
  
  output = [0] * len(graphs)
  for idx, graph in enumerate(graphs):
    if not graph["data"] or len(input_state[idx])==0:
      print("early")
      output[idx] = {'x':[0],'y':[0]} 
      continue
        

    with h5py.File(f5_file, 'r', libver='latest', swmr=True) as f5:
      extended_time = []
      extended_data = []
###############################################################
      for l_idx, s_idx in enumerate(input_state[idx]):
        signal_dset = f5[signals.t[s_idx].table]
        time_dset = f5[signals.t[s_idx].timeline]
        
        h5_idx = len(time_dset) #last index of table
        graph_idx = len(graph['data'][l_idx]['y'])

        t = time_dset[graph_idx:h5_idx]
        new_data = signal_dset[signals.t[s_idx].coord][graph_idx:h5_idx]

        extended_time.append(t)
        extended_data.append(new_data)
#####################################################################
        # print(extended_data)
      output[idx] = (dict(x=extended_time, y=extended_data))
    print()
  print(output)
  return [output[i] for i in range(len(graphs))]

```

You can skip the portion between the ###### lines; That is just the creation of the extended traces.

Here is also the structure of my webpage so that you can understand my return statement in a better way.

 ![gp](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/c/0/c0ffe8d1a7ec5f18a2751e1ab6f46fcabdcef14a.png)

---

<div class="post-metadata">

**Author:** ![jlfsjunior](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jlfsjunior/32/16061_2.png) [@jlfsjunior](https://community.plotly.com/u/jlfsjunior)\
**Post date:** [December 30, 2021, 2:06pm UTC](https://community.plotly.com/t/graph-extend-data-property-not-working-when-used-with-patten-matching-callback/59552/6 "2021-12-30T14:06:13Z")

</div>

Could you share the output of the last `print(output)`, just before the return statement? I don’t think `extendData` is formatted as it should, that’s why you are getting this error.

Second, are you sure that the new points are chronologically ordered? Sometimes the weird lines you’re seen is because of unordered time-series…

---

<div class="post-metadata">

**Author:** ![supratik](https://avatars.discourse-cdn.com/v4/letter/s/e274bd/32.png) [@supratik](https://community.plotly.com/u/supratik)\
**Post date:** [December 31, 2021, 6:12am UTC](https://community.plotly.com/t/graph-extend-data-property-not-working-when-used-with-patten-matching-callback/59552/7 "2021-12-31T06:12:41Z")

</div>

I’v actually checked regarding the chronology of the dataset and so far it seems fine.

 ![otpt2](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/7/f/7fab980b4cc87ea89762ec73ba04df98a0301bd3.jpeg)

Everything before the red horizontal line works fine as there is only one graph.  
Then I add another plot and it stops updating, and the length of the ‘x’ and ‘y’ keeps increasing which should ideally be 1 as they get updated.  
The thing that you see in yellow is just a placeholder as I cannot send an empty dictionary as an output.

---

<div class="post-metadata">

**Author:** ![jlfsjunior](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jlfsjunior/32/16061_2.png) [@jlfsjunior](https://community.plotly.com/u/jlfsjunior)\
**Post date:** [December 31, 2021, 9:37am UTC](https://community.plotly.com/t/graph-extend-data-property-not-working-when-used-with-patten-matching-callback/59552/8 "2021-12-31T09:37:17Z")

</div>

Could you try replacing your placeholder for:

```auto
{"x": [[0]], "y": [[0]]}

```

I am quite sure that `updateData` expects a list of lists for each coordinate, where the outer list has the same length as the number of traces being updated. In your case you have just one trace per plot, but you might still need it… Note that this is the same format as your first element, where you have a list with one array.

The accumulation is expected, as `graph_idx` does not get updated if the callback fails.
