forked from priyadivya24/Visualization_Project
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdashboard.py
139 lines (113 loc) · 5.15 KB
/
dashboard.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
"""Minimal dynamic dash app example.
Click on a button, and draw a new plotly-resampler graph of two noisy sinusoids.
This example uses pattern-matching callbacks to update dynamically constructed graphs.
The plotly-resampler graphs themselves are cached on the server side.
The main difference between this example and 02_minimal_cache.py is that here, we want
to cache using a dcc.Store that is not yet available on the client side. As a result we
split up our logic into two callbacks: (1) the callback used to construct the necessary
components and send them to the client-side, and (2) the callback used to construct the
actual plotly-resampler graph and cache it on the server side. These two callbacks are
chained together using the dcc.Interval component.
"""
from data import get_doocs_properties, load_parquet_data
from pathlib import Path
from datetime import datetime
from typing import List
import plotly.graph_objects as go
from dash import MATCH, Input, Output, State, dcc, html, no_update
from dash_extensions.enrich import (
DashProxy,
Serverside,
ServersideOutputTransform,
Trigger,
TriggerTransform,
)
from trace_updater import TraceUpdater
from plotly_resampler import FigureResampler
from plotly_resampler.aggregation import MinMaxLTTB
# Data that will be used for the plotly-resampler figures
online_data = {}
doocs_properties = get_doocs_properties(Path("C:/Users/Arne/Sources/Ml_data/daqdata/sorted"))
# --------------------------------------Globals ---------------------------------------
app = DashProxy(__name__, transforms=[ServersideOutputTransform(), TriggerTransform()])
app.layout = html.Div(
[
html.Div(children=[
dcc.Dropdown(doocs_properties, id="property-selecter", multi=True),
html.Button("load data and plot", id="load-plot")
]),
html.Div(id="container", children=[]),
]
)
# ------------------------------------ DASH logic -------------------------------------
@app.callback(
Output("container", "children"),
Input("load-plot", "n_clicks"),
State("property-selecter", "value"),
State("container", "children"),
prevent_initial_call=True,
)
def add_graph_div(_, selected_properties, div_children: List[html.Div] ):
if selected_properties is None:
return []
else:
props = [Path(prop) for prop in selected_properties]
loaded_data = load_parquet_data(props, datetime(2023, 10, 15, 17, 30), datetime(2023, 11, 15, 17, 30))
for key, item in loaded_data.items():
online_data[doocs_properties[str(key)]] = item
div_children = []
#### make the plots here
for dat in loaded_data:
uid = doocs_properties[str(dat)]
new_child = html.Div(
children=[
# The graph and its needed components to serialize and update efficiently
# Note: we also add a dcc.Store component, which will be used to link the
# server side cached FigureResampler object
dcc.Graph(id={"type": "dynamic-graph", "index": uid}, figure=go.Figure()),
dcc.Loading(dcc.Store(id={"type": "store", "index": uid})),
TraceUpdater(id={"type": "dynamic-updater", "index": uid}, gdID=f"{uid}"),
# This dcc.Interval components makes sure that the `construct_display_graph`
# callback is fired once after these components are added to the session
# its front-end
dcc.Interval(
id={"type": "interval", "index": uid}, max_intervals=1, interval=1
),
],
)
div_children.append(new_child)
return div_children
# This method constructs the FigureResampler graph and caches it on the server side
@app.callback(
Output({"type": "dynamic-graph", "index": MATCH}, "figure"),
Output({"type": "store", "index": MATCH}, "data"),
State("load-plot", "n_clicks"),
State({"type": "dynamic-graph", "index": MATCH}, "id"),
Trigger({"type": "interval", "index": MATCH}, "n_intervals"),
prevent_initial_call=True,
)
def construct_display_graph(n_clicks, analysis) -> FigureResampler:
fig = FigureResampler(
go.Figure(),
default_n_shown_samples=2_000,
default_downsampler=MinMaxLTTB(parallel=True),
)
data = online_data[analysis['index']]
sigma = n_clicks * 1e-6
fig.add_trace(dict(name="new"), hf_x=data["timestamp"], hf_y=data["data"])
fig.update_layout(title=f"<b>{analysis['index']}</b>", title_x=0.5)
return fig, Serverside(fig)
@app.callback(
Output({"type": "dynamic-updater", "index": MATCH}, "updateData"),
Input({"type": "dynamic-graph", "index": MATCH}, "relayoutData"),
State({"type": "store", "index": MATCH}, "data"),
prevent_initial_call=True,
memoize=True,
)
def update_fig(relayoutdata: dict, fig: FigureResampler):
if fig is not None:
return fig.construct_update_data(relayoutdata)
return no_update
# --------------------------------- Running the app ---------------------------------
if __name__ == "__main__":
app.run_server(debug=True, port=9023)