Skip to content

Commit 03bb331

Browse files
jonasvddjvdd
andauthored
💪 update dash-extensions (#261)
* 💪 update dash-extensions * 🖊️ code review --------- Co-authored-by: Jeroen Van Der Donckt <18898740+jvdd@users.noreply.github.com>
1 parent e841463 commit 03bb331

File tree

7 files changed

+38
-36
lines changed

7 files changed

+38
-36
lines changed

examples/dash_apps/02_minimal_cache.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Click on a button, and see a plotly-resampler graph of two noisy sinusoids.
44
No dynamic graph construction / pattern matching callbacks are needed.
55
6-
This example uses the dash-extensions its ServersideOutput functionality to cache
6+
This example uses the dash-extensions its ServerSide functionality to cache
77
the FigureResampler per user/session on the server side. This way, no global figure
88
variable is used and shows the best practice of using plotly-resampler within dash-apps.
99
@@ -12,14 +12,11 @@
1212
import numpy as np
1313
import plotly.graph_objects as go
1414
from dash import Input, Output, State, callback_context, dcc, html, no_update
15-
from dash_extensions.enrich import (
16-
DashProxy,
17-
ServersideOutput,
18-
ServersideOutputTransform,
19-
)
15+
from dash_extensions.enrich import DashProxy, Serverside, ServersideOutputTransform
2016
from trace_updater import TraceUpdater
2117

2218
from plotly_resampler import FigureResampler
19+
from plotly_resampler.aggregation import MinMaxLTTB
2320

2421
# Data that will be used for the plotly-resampler figures
2522
x = np.arange(2_000_000)
@@ -46,21 +43,22 @@
4643
# ------------------------------------ DASH logic -------------------------------------
4744
# The callback used to construct and store the FigureResampler on the serverside
4845
@app.callback(
49-
[Output("graph-id", "figure"), ServersideOutput("store", "data")],
46+
[Output("graph-id", "figure"), Output("store", "data")],
5047
Input("plot-button", "n_clicks"),
5148
prevent_initial_call=True,
52-
memoize=True,
5349
)
5450
def plot_graph(n_clicks):
5551
ctx = callback_context
5652
if len(ctx.triggered) and "plot-button" in ctx.triggered[0]["prop_id"]:
57-
fig: FigureResampler = FigureResampler(go.Figure())
53+
fig: FigureResampler = FigureResampler(
54+
go.Figure(), default_downsampler=MinMaxLTTB(parallel=True)
55+
)
5856

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

63-
return fig, fig
61+
return fig, Serverside(fig)
6462
else:
6563
return no_update
6664

examples/dash_apps/03_minimal_cache_dynamic.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,15 @@
2121
from dash import MATCH, Input, Output, State, dcc, html, no_update
2222
from dash_extensions.enrich import (
2323
DashProxy,
24-
ServersideOutput,
24+
Serverside,
2525
ServersideOutputTransform,
2626
Trigger,
2727
TriggerTransform,
2828
)
2929
from trace_updater import TraceUpdater
3030

3131
from plotly_resampler import FigureResampler
32+
from plotly_resampler.aggregation import MinMaxLTTB
3233

3334
# Data that will be used for the plotly-resampler figures
3435
x = np.arange(2_000_000)
@@ -78,22 +79,26 @@ def add_graph_div(n_clicks: int, div_children: List[html.Div]):
7879

7980
# This method constructs the FigureResampler graph and caches it on the server side
8081
@app.callback(
81-
ServersideOutput({"type": "store", "index": MATCH}, "data"),
8282
Output({"type": "dynamic-graph", "index": MATCH}, "figure"),
83+
Output({"type": "store", "index": MATCH}, "data"),
8384
State("add-chart", "n_clicks"),
8485
Trigger({"type": "interval", "index": MATCH}, "n_intervals"),
8586
prevent_initial_call=True,
8687
)
8788
def construct_display_graph(n_clicks) -> FigureResampler:
88-
fig = FigureResampler(go.Figure(), default_n_shown_samples=2_000)
89+
fig = FigureResampler(
90+
go.Figure(),
91+
default_n_shown_samples=2_000,
92+
default_downsampler=MinMaxLTTB(parallel=True),
93+
)
8994

9095
# Figure construction logic based on a state variable, in our case n_clicks
9196
sigma = n_clicks * 1e-6
9297
fig.add_trace(dict(name="log"), hf_x=x, hf_y=noisy_sin * (1 - sigma) ** x)
9398
fig.add_trace(dict(name="exp"), hf_x=x, hf_y=noisy_sin * (1 + sigma) ** x)
9499
fig.update_layout(title=f"<b>graph - {n_clicks}</b>", title_x=0.5)
95100

96-
return fig, fig
101+
return fig, Serverside(fig)
97102

98103

99104
@app.callback(

examples/dash_apps/11_sine_generator.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from dash import MATCH, Input, Output, State, callback_context, dcc, html, no_update
2121
from dash_extensions.enrich import (
2222
DashProxy,
23-
ServersideOutput,
23+
Serverside,
2424
ServersideOutputTransform,
2525
Trigger,
2626
TriggerTransform,
@@ -152,8 +152,8 @@ def add_or_remove_graph(add_graph, remove_graph, n, exp, gc_children):
152152

153153
# This method constructs the FigureResampler graph and caches it on the server side
154154
@app.callback(
155-
ServersideOutput({"type": "store", "index": MATCH}, "data"),
156155
Output({"type": "dynamic-graph", "index": MATCH}, "figure"),
156+
Output({"type": "store", "index": MATCH}, "data"),
157157
State("nbr-datapoints", "value"),
158158
State("expansion-factor", "value"),
159159
State("add-graph-btn", "n_clicks"),
@@ -180,7 +180,7 @@ def construct_display_graph(n, exp, n_added_graphs) -> FigureResampler:
180180
title_x=0.5,
181181
)
182182

183-
return fr, fr
183+
return fr, Serverside(fr)
184184

185185

186186
@app.callback(

examples/dash_apps/12_file_selector.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,10 @@
1212

1313
import dash_bootstrap_components as dbc
1414
import plotly.graph_objects as go
15-
from dash import Input, Output, State, callback_context, dcc, html, no_update
16-
from dash_extensions.enrich import (
17-
DashProxy,
18-
ServersideOutput,
19-
ServersideOutputTransform,
20-
)
15+
16+
from dash import callback_context, dcc, html, no_update
17+
from dash_extensions.enrich import Output, Input, State
18+
from dash_extensions.enrich import DashProxy, Serverside, ServersideOutputTransform
2119
from trace_updater import TraceUpdater
2220
from utils.callback_helpers import get_selector_states, multiple_folder_file_selector
2321
from utils.graph_construction import visualize_multiple_files
@@ -89,7 +87,7 @@ def serve_layout() -> dbc.Container:
8987

9088
# ------------------------------------ DASH logic -------------------------------------
9189
@app.callback(
92-
[Output("graph-id", "figure"), ServersideOutput("store", "data")],
90+
[Output("graph-id", "figure"), Output("store", "data")],
9391
[Input("plot-button", "n_clicks"), *get_selector_states(len(name_folder_list))],
9492
prevent_initial_call=True,
9593
)
@@ -102,12 +100,13 @@ def plot_graph(n_clicks, *folder_list):
102100
else:
103101
for file in files:
104102
file_list.append((Path(folder).joinpath(file)))
103+
print(file_list)
105104

106105
ctx = callback_context
107106
if len(ctx.triggered) and "plot-button" in ctx.triggered[0]["prop_id"]:
108107
if len(file_list):
109108
fig: FigureResampler = visualize_multiple_files(file_list)
110-
return fig, fig
109+
return fig, Serverside(fig)
111110
else:
112111
return no_update
113112

examples/dash_apps/13_coarse_fine.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,7 @@
1919
import dash_bootstrap_components as dbc
2020
import plotly.graph_objects as go
2121
from dash import Input, Output, State, callback_context, dcc, html, no_update
22-
from dash_extensions.enrich import (
23-
DashProxy,
24-
ServersideOutput,
25-
ServersideOutputTransform,
26-
)
22+
from dash_extensions.enrich import DashProxy, Serverside, ServersideOutputTransform
2723
from trace_updater import TraceUpdater
2824
from utils.callback_helpers import get_selector_states, multiple_folder_file_selector
2925
from utils.graph_construction import visualize_multiple_files
@@ -33,7 +29,7 @@
3329
# --------------------------------------Globals ---------------------------------------
3430
app = DashProxy(
3531
__name__,
36-
suppress_callback_exceptions=True,
32+
suppress_callback_exceptions=False,
3733
external_stylesheets=[dbc.themes.LUX],
3834
transforms=[ServersideOutputTransform()],
3935
)
@@ -114,7 +110,7 @@ def serve_layout() -> dbc.Container:
114110
[
115111
Output("coarse-graph", "figure"),
116112
Output("plotly-resampler-graph", "figure"),
117-
ServersideOutput("store", "data"),
113+
Output("store", "data"),
118114
],
119115
[Input("plot-button", "n_clicks"), *get_selector_states(len(name_folder_list))],
120116
prevent_initial_call=True,
@@ -155,7 +151,7 @@ def construct_plot_graph(n_clicks, *folder_list):
155151
)
156152
)
157153

158-
return coarse_fig, dynamic_fig, dynamic_fig
154+
return coarse_fig, dynamic_fig, Serverside(dynamic_fig)
159155
else:
160156
return no_update
161157

@@ -185,4 +181,4 @@ def update_dynamic_fig(coarse_grained_relayout, fine_grained_relayout, fr_fig):
185181

186182
# --------------------------------- Running the app ---------------------------------
187183
if __name__ == "__main__":
188-
app.run_server(debug=True, port=9023)
184+
app.run_server(debug=False, port=9023)

examples/dash_apps/utils/graph_construction.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from plotly.subplots import make_subplots
77

88
from plotly_resampler import FigureResampler
9+
from plotly_resampler.aggregation import MinMaxLTTB
910

1011

1112
# --------- graph construction logic + callback ---------
@@ -22,7 +23,10 @@ def visualize_multiple_files(file_list: List[Union[str, Path]]) -> FigureResampl
2223
Returns a view of the existing, global FigureResampler object.
2324
2425
"""
25-
fig = FigureResampler(make_subplots(rows=len(file_list), shared_xaxes=False))
26+
fig = FigureResampler(
27+
make_subplots(rows=len(file_list), shared_xaxes=False),
28+
default_downsampler=MinMaxLTTB(parallel=True),
29+
)
2630
fig.update_layout(height=min(900, 350 * len(file_list)))
2731

2832
for i, f in enumerate(file_list, 1):

examples/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
pyfunctional>=1.4.3
22
dash-bootstrap-components>=1.2.0
3-
dash-extensions>=0.1.4
3+
dash-extensions==1.0.1 # fixated on this version as more recent versions do not work
44
ipywidgets>=7.7.0
55
memory-profiler>=0.60.0
66
line-profiler>=3.5.1

0 commit comments

Comments
 (0)