MarcSkovMadsen commited on
Commit
62fa030
1 Parent(s): 52fed65

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +108 -133
app.py CHANGED
@@ -1,134 +1,109 @@
1
- import time
2
- from concurrent.futures import ThreadPoolExecutor
3
- from contextlib import contextmanager
4
-
5
- import numpy as np
6
  import panel as pn
7
- import param
8
- from asyncio import wrap_future
9
-
10
- class ProgressExtMod(pn.viewable.Viewer):
11
- """A custom component for easy progress reporting"""
12
-
13
- completed = param.Integer(default=0)
14
- bar_color = param.String(default="info")
15
- num_tasks = param.Integer(default=100, bounds=(1, None))
16
-
17
- # @param.depends('completed', 'num_tasks')
18
- @property
19
- def value(self) -> int:
20
- """Returns the progress value
21
-
22
- Returns:
23
- int: The progress value
24
- """
25
- return int(100 * (self.completed / self.num_tasks))
26
-
27
- def reset(self):
28
- """Resets the value and message"""
29
- # Please note the order matters as the Widgets updates two times. One for each change
30
- self.completed = 0
31
-
32
- def __panel__(self):
33
- return self.view
34
-
35
- @param.depends("completed", "bar_color")
36
- def view(self):
37
- """View the widget
38
- Returns:
39
- pn.viewable.Viewable: Add this to your app to see the progress reported
40
- """
41
- if self.value:
42
- return pn.widgets.Progress(
43
- active=True, value=self.value, align="center", sizing_mode="stretch_width"
44
- )
45
- return None
46
-
47
- @contextmanager
48
- def increment(self):
49
- """Increments the value
50
-
51
- Can be used as context manager or decorator
52
-
53
- Yields:
54
- None: Nothing is yielded
55
- """
56
- self.completed += 1
57
- yield
58
- if self.completed == self.num_tasks:
59
- self.reset()
60
-
61
- executor = ThreadPoolExecutor(max_workers=2) # pylint: disable=consider-using-with
62
- progress = ProgressExtMod()
63
-
64
-
65
- class AsyncComponent(pn.viewable.Viewer):
66
- """A component that demonstrates how to run a Blocking Background task asynchronously
67
- in Panel"""
68
-
69
- select = param.Selector(objects=range(10))
70
- slider = param.Number(2, bounds=(0, 10))
71
-
72
- run_blocking_task = param.Event(label="RUN")
73
- result = param.Number(0)
74
- view = param.Parameter()
75
-
76
- def __init__(self, **params):
77
- super().__init__(**params)
78
-
79
- self._layout = pn.Column(
80
- pn.pane.Markdown("## Blocking Task Running in Background"),
81
- pn.Param(
82
- self,
83
- parameters=["run_blocking_task", "result"],
84
- widgets={"result": {"disabled": True}, "run_blocking_task": {"button_type": "primary"}},
85
- show_name=False,
86
- ),
87
- progress,
88
- pn.pane.Markdown("## Other, Non-Blocked Tasks"),
89
- pn.Param(
90
- self,
91
- parameters=["select", "slider"],
92
- widgets={"text": {"disabled": True}},
93
- show_name=False,
94
- ),
95
- self.text
96
- )
97
-
98
- def __panel__(self):
99
- return self._layout
100
-
101
- @param.depends("slider", "select")
102
- def text(self):
103
- if self.select:
104
- select = self.select
105
- else:
106
- select = 0
107
- return f"{select} + {self.slider} = {select + self.slider}"
108
-
109
- @pn.depends("run_blocking_task", watch=True)
110
- async def _run_blocking_tasks(self, num_tasks=10):
111
- """Runs background tasks num_tasks times"""
112
- num_tasks = 20
113
- progress.num_tasks = num_tasks
114
- for _ in range(num_tasks):
115
- future = executor.submit(self._run_blocking_task)
116
- result = await wrap_future(future)
117
- self._update(result)
118
-
119
- @progress.increment()
120
- def _update(self, number):
121
- self.result += number
122
-
123
- @staticmethod
124
- def _run_blocking_task():
125
- time.sleep(np.random.randint(1, 2))
126
- return 5
127
-
128
- if pn.state.served:
129
- pn.extension()
130
-
131
- component = AsyncComponent()
132
- pn.template.FastListTemplate(
133
- site="Awesome Panel", site_url="https://awesome-panel.org", title="Async Tasks", main=[component], main_layout=None, main_max_width="400px"
134
- ).servable()
 
 
 
 
 
 
1
  import panel as pn
2
+ import pandas as pd
3
+ import altair as alt
4
+ import hvplot.pandas
5
+
6
+ pn.extension("tabulator", "vega")
7
+
8
+ ACCENT="teal"
9
+
10
+ styles = {
11
+ "box-shadow": "rgba(50, 50, 93, 0.25) 0px 6px 12px -2px, rgba(0, 0, 0, 0.3) 0px 3px 7px -3px",
12
+ "border-radius": "4px",
13
+ "padding": "10px",
14
+ }
15
+
16
+ image = pn.pane.JPG("https://assets.holoviz.org/panel/tutorials/wind_turbines_sunset.png")
17
+
18
+ # Extract Data
19
+
20
+ @pn.cache() # only download data once
21
+ def get_data():
22
+ return pd.read_csv("https://assets.holoviz.org/panel/tutorials/turbines.csv.gz")
23
+
24
+ # Transform Data
25
+
26
+ source_data = get_data()
27
+ min_year = int(source_data["p_year"].min())
28
+ max_year = int(source_data["p_year"].max())
29
+ top_manufacturers = (
30
+ source_data.groupby("t_manu").p_cap.sum().sort_values().iloc[-10:].index.to_list()
31
+ )
32
+
33
+ def filter_data(t_manu, year):
34
+ data = source_data[(source_data.t_manu == t_manu) & (source_data.p_year <= year)]
35
+ return data
36
+
37
+ # Filters
38
+
39
+ t_manu = pn.widgets.Select(
40
+ name="Manufacturer",
41
+ value="Vestas",
42
+ options=sorted(top_manufacturers),
43
+ description="The name of the manufacturer",
44
+ )
45
+ p_year = pn.widgets.IntSlider(name="Year", value=max_year, start=min_year, end=max_year)
46
+
47
+ # Transform Data 2
48
+
49
+ df = pn.rx(filter_data)(t_manu=t_manu, year=p_year)
50
+ count = df.rx.len()
51
+ total_capacity = df.t_cap.sum()
52
+ avg_capacity = df.t_cap.mean()
53
+ avg_rotor_diameter = df.t_rd.mean()
54
+
55
+ # Plot Data
56
+
57
+ fig = (
58
+ df[["p_year", "t_cap"]].groupby("p_year").sum() / 10**6
59
+ ).hvplot.bar(
60
+ title="Capacity Change",
61
+ rot=90,
62
+ ylabel="Capacity (MW)",
63
+ xlabel="Year",
64
+ xlim=(min_year, max_year),
65
+ color=ACCENT,
66
+ )
67
+
68
+ # Display Data
69
+
70
+ indicators = pn.FlexBox(
71
+ pn.indicators.Number(
72
+ value=count, name="Count", format="{value:,.0f}", styles=styles
73
+ ),
74
+ pn.indicators.Number(
75
+ value=total_capacity / 1e6,
76
+ name="Total Capacity (TW)",
77
+ format="{value:,.1f}",
78
+ styles=styles,
79
+ ),
80
+ pn.indicators.Number(
81
+ value=avg_capacity/1e3,
82
+ name="Avg. Capacity (MW)",
83
+ format="{value:,.1f}",
84
+ styles=styles,
85
+ ),
86
+ pn.indicators.Number(
87
+ value=avg_rotor_diameter,
88
+ name="Avg. Rotor Diameter (m)",
89
+ format="{value:,.1f}",
90
+ styles=styles,
91
+ ),
92
+ )
93
+
94
+ plot = pn.pane.HoloViews(fig, sizing_mode="stretch_both", name="Plot")
95
+ table = pn.widgets.Tabulator(df, sizing_mode="stretch_both", name="Table")
96
+
97
+ # Layout Data
98
+
99
+ tabs = pn.Tabs(
100
+ plot, table, styles=styles, sizing_mode="stretch_width", height=500, margin=10
101
+ )
102
+
103
+ pn.template.FastListTemplate(
104
+ title="Wind Turbine Dashboard",
105
+ sidebar=[image, t_manu, p_year],
106
+ main=[pn.Column(indicators, tabs, sizing_mode="stretch_both")],
107
+ main_layout=None,
108
+ accent=ACCENT,
109
+ ).servable()