predict-idlab / plotly-resampler

Visualize large time series data with plotly.py
https://predict-idlab.github.io/plotly-resampler/latest
MIT License
1k stars 67 forks source link

Getting `ImportError` for `dash-extension` module `dash.enrich.ServersideOutput` #214

Closed darynwhite closed 9 months ago

darynwhite commented 1 year ago

When working to integrate the resampler into some dash apps, I'm now seeing the following:

> python testing_plotly-dash-resampler.py
Traceback (most recent call last):
  File "/Users/white/Repos/Dev/GTMBA-FlexProcessingDev/testing_plotly-dash-resampler.py", line 15, in <module>
    from dash_extensions.enrich import (
ImportError: cannot import name 'ServersideOutput' from 'dash_extensions.enrich' (/Users/white/conda/envs/tmba/lib/python3.11/site-packages/dash_extensions/enrich.py)

This is a local test of examples/dash_apps/02_minimal_cache.py so I can work out functionality. When I remove the import of ServersideOutput the plot no longer resamples.

jvdd commented 1 year ago

Hey @darynwhite

Thanks again for submitting an issue to this repo! :handshake:

Just had a look into this issue, and this seems to stem from dash_extensions making breaking changes in their 1.0.0 release (released 5 days ago) - dash-extensions changelog:

The syntax of the ServersideOutputTransform has been changed. Instead of using ServersideOutput in place of the Output, one must now wrap return values in Serverside objects

Utilizing any dash_extensions version < 1.0.0 seems to work!

The only action point for this issue is:

darynwhite commented 1 year ago

Thanks @jvdd! I hunted for a change log but wasn't able to find it with the time I had. Thanks for linking it!

darynwhite commented 1 year ago

Hi again!

I was wondering if there was any updates regarding the changes in dash-extensions? I have pinned my working environment to the previous version but try to avoid pins.

Thanks!

darynwhite commented 1 year ago

Curious if anyone has found a solution to these lines in the Dash examples:

https://github.com/predict-idlab/plotly-resampler/blob/7c3bc80246ba0d1332e931ca36dbfbf0b0e5ef55/examples/dash_apps/13_coarse_fine.py#L22-L26

srikiran-cpn commented 10 months ago

Yes, you should replace ServersideOutput with Serverside in your imports @darynwhite .

@app.callback(
    [
        Output("dashtable_currentvalues", "data"),
        Output("graph-id", "figure"),
        Output("store", "data"),
    ],
    Input("plot-button", "n_clicks"),
    # prevent_initial_call=True,
    # memoize=True,
)
def plot_graph(n_clicks):
    ctx = callback_context
    if not len(ctx.triggered) or "plot-button" not in ctx.triggered[0]["prop_id"]:
        return no_update
    fig: FigureResampler = FigureResampler(go.Figure())

    # Figure construction logic
    fig.add_trace(go.Scattergl(name="log"), hf_x=x, hf_y=noisy_sin * 0.9999995**x)
    # fig.add_trace(go.Scattergl(name="exp"), hf_x=x, hf_y=noisy_sin * 1.000002**x)
    ic(fig)

    joblib.dump(fig, "fig.joblib")
    cache.set("a", 23)
    with open("fig_working.json", "w") as f:
        f.write(fig.to_json())
    print(type(fig))
    df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
    return df.to_dict("records"), fig, Serverside(fig)

The key change is the callback signature (notice they are all Outputs, there is no ServersideOutput). And in the return value (use Serverside(fig)).

darynwhite commented 10 months ago

I'll take another look at this now. I ended up finding a way to use only plotly-resampler without the dash-extensions library.

Thanks @srikiran-cpn!

jonasvdd commented 10 months ago

@darynwhite @srikiran-cpn,

In #261, I tackle this issue by updating the dash extensions. I aim to merge this PR somewhere later this day! 🙏🏼

jonasvdd commented 10 months ago

The pull request is merged!

So if the issue is resolved, please feel free to close this! 😄

srikiran-cpn commented 10 months ago

@darynwhite what is the way you adopted? I am curious. I am able to run a demo app, but my main app keeps telling me that it can't serialize the FigureResampler object

dash.exceptions.InvalidCallbackReturnValue: The callback for `[<Output `dashtable_currentvalues.data`>, <Output `fig_timeseries.figure`>, <Output `store-fig.data`>]`
                returned a value having type `FigureResampler`
                which is not JSON serializable.

The value in question is either the only value returned,
or is in the top level of the returned list,

                and has string representation

Can't think of why this would happen. I pickled the figure objects from the main app and the example after making their data the same. The only difference between them is the UID (I compared the figure dictionary objects). I also dumped the Serverside(fig) from the main app and the example. Here too, I see they are the same except UID.

I think it has to do with some other aspect from my main app, like another library changing some settings around the cache. So your alternate method without using Dash Extentions seems interesting.

@jonasvdd : appreciate any ideas from you too :)

darynwhite commented 10 months ago

@srikiran-cpn I was able to adapt this example: examples/dash_apps/01_minimal_global.py

The app I'm developing is able to be called via CLI, so it is focused on local first. I generate all of the figures and then replace what is shown based on a dropdown input. I might be able to modify it into a simple example, but it is completely based on the example above.

@jonasvdd I'll try to test things this week and if I find it is working, I'll close this issue. Thanks!

jonasvdd commented 10 months ago

@darynwhite, sounds great!