[PLOTLY RESAMPLE] What can I do to choose how much plotly resample samples?

I have a couple of questions about the plotly resample component

  • What can I do to change the sampling rate? I am using plotly resample Welcome to plotly-resampler’s documentation! — plotly-resampler "0.8.2" documentation in a dash app. I tried using this function (un)wrapping plotly figures — plotly-resampler "0.8.2" documentation but I don’t see any options to determine how much it samples. The out of the box sampling samples a bit too sparsely for my particular use case.

  • If I go the manual route, where can I select the number of samples? It looks like it might be the default_n_shown_samples in the figure resampler function. In my case, I’m wrapping go.make_subplots() with the argument. I’m wondering if I can choose different numbers for n for different traces. The docs say “This can be overridden within the add_trace() method.” but it’s not clear what argument to pass to do that.

  • Can I turn off resampling if I go the manual route? I want to have an option on my dashboard that says “turn off resampling”. My best guess is to pass convert_existing_traces = False to the FigureResampler but it’s not clear how I can update that argument on an existing figure object.

  • Do I no longer include the standard x = and y = arguments in my traces? I have a callback that updates the x and y arguments of my traces using the extendData argument and I’m wondering if that breaks if I use hf_x and hf_y.

  • What can I do to use the auto-scaling the y axis part of plotly resample? I couldn’t find an example of this in the docs but the feature sounds really cool.

  • Where do I fire register_update_graph_callback? I have a Dash file that has the app object and then I have a file that gets called and has all of my traces, figure logic, etc. It sounds like the register_update_graph_callback should be placed in the same part of the script where the figure is defined, but I don’t have the app object there. I could pass it along to the file, but I want to make sure that’s the right place for this function.

2 Likes

Hi @ibenok,

Thank you for taking such an interest in our toolkit, these are all really good questions! I will discuss the ones I cannot answer yet with my codeveloper and couple back the results.

So far:

  1. Regarding the first two bullets:

    changing the sampling rate on a trace-level granularity

    I think looking at the basic_example.ipynb might help you with this. More specifically, the section: Different downsampler & number of shown samples per trace. i.e. you need to use the max_n_samples argument. (also stated here in the docs)

  2. Regarding bullet 3:

    turning off resampling

    I need to look into that.

  3. Regarding bullet 4:

    Extending existing scatter traces their data

    High-frequency streaming data can be supported with plotly-resampler (I’ve created a minimal working example). We are planning to add such an example in the near future. It boils down towards using the hf_data property of the FigureResampler instances. Example of a streaming data dash callback:

@app.callback(
    [Output("trace-updater", "updateData"), Output("ts_store", "data")],
    [Input("interval", "n_intervals"), Input("graph-id", "relayoutData")],
    State("store", "data"),  # The server side cached FigureResampler per session
    State("ts_store", "data"),
    prevent_initial_call=True,
)
def update_fig(n_intervals, relayoutdata, fig, ts_ref):
    if fig is None:
        return no_update

    # We extend the hf-data of the figure
    ctx = callback_context
    if len(ctx.triggered) and "interval.n_intervals" in [
        trg["prop_id"] for trg in ctx.triggered
    ]:
        if ts_ref is None:
            ts_ref = datetime.now().timestamp()

        # update the end timestamp within ts_list
        td_end = pd.Timedelta(seconds=datetime.now().timestamp() - ts_ref)
        ecg_slice = df_ecg.loc[:df_ecg.index[0] + td_end]["ECG"]

        fig.hf_data[0]["y"] = ecg_slice.values
        fig.hf_data[0]["x"] = ecg_slice.index

        # update the figure
        return fig.construct_update_data(relayoutdata), ts_ref
    return no_update
  1. Regarding bullet 5:

    Auto scaling the y-axis

    I am not entirely sure what you mean with this, could you elaborate on this?

  2. Regarding the last bullet

    The callback function

    I hope these dash app examples might help you. These should be elaborate enough for most use-cases. If you find that something Is missing, please don’t hesitate to create an issue on GitHub!

Kind regards,
Jonas

2 Likes

Hi Jonas, thanks for the thoughtful response. I’ll add some responses here-

I thought I read something on your website that said there’s a function that auto-scales the y axis. The default behavior to autosize the y axis is sorta wonky. I maybe completely misremembering, but I thought I might ask.

I hope these dash app examples might help you. These should be elaborate enough for most use-cases. If you find that something Is missing, please don’t hesitate to create an issue on GitHub!

The examples are great, and I’m still sorta unsure about where I should place the register function. Do I place it in the code where I generate the initial figure, the code where I update the figure with new data or the code where I set the layout for my dashboard? My concern is that the first two places doesn’t have the app object (though I can change the code to send it)