MarcSkovMadsen commited on
Commit
c2f8440
1 Parent(s): 8ee3a1b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -89
app.py CHANGED
@@ -1,108 +1,95 @@
1
  import panel as pn
2
- import pandas as pd
3
- import hvplot.pandas
4
 
5
- pn.extension("tabulator")
6
 
7
- ACCENT="teal"
8
 
9
- styles = {
10
- "box-shadow": "rgba(50, 50, 93, 0.25) 0px 6px 12px -2px, rgba(0, 0, 0, 0.3) 0px 3px 7px -3px",
11
- "border-radius": "4px",
12
- "padding": "10px",
13
- }
14
 
15
- image = pn.pane.JPG("https://assets.holoviz.org/panel/tutorials/wind_turbines_sunset.png")
 
16
 
17
- # Extract Data
 
 
18
 
19
- @pn.cache() # only download data once
20
- def get_data():
21
- return pd.read_csv("https://assets.holoviz.org/panel/tutorials/turbines.csv.gz")
22
 
23
- # Transform Data
 
 
 
 
24
 
25
- source_data = get_data()
26
- min_year = int(source_data["p_year"].min())
27
- max_year = int(source_data["p_year"].max())
28
- top_manufacturers = (
29
- source_data.groupby("t_manu").p_cap.sum().sort_values().iloc[-10:].index.to_list()
30
- )
31
 
32
- def filter_data(t_manu, year):
33
- data = source_data[(source_data.t_manu == t_manu) & (source_data.p_year <= year)]
34
- return data
35
 
36
- # Filters
 
 
37
 
38
- t_manu = pn.widgets.Select(
39
- name="Manufacturer",
40
- value="Vestas",
41
- options=sorted(top_manufacturers),
42
- description="The name of the manufacturer",
43
- )
44
- p_year = pn.widgets.IntSlider(name="Year", value=max_year, start=min_year, end=max_year)
45
-
46
- # Transform Data 2
47
-
48
- df = pn.rx(filter_data)(t_manu=t_manu, year=p_year)
49
- count = df.rx.len()
50
- total_capacity = df.t_cap.sum()
51
- avg_capacity = df.t_cap.mean()
52
- avg_rotor_diameter = df.t_rd.mean()
53
-
54
- # Plot Data
55
-
56
- fig = (
57
- df[["p_year", "t_cap"]].groupby("p_year").sum() / 10**6
58
- ).hvplot.bar(
59
- title="Capacity Change",
60
- rot=90,
61
- ylabel="Capacity (MW)",
62
- xlabel="Year",
63
- xlim=(min_year, max_year),
64
- color=ACCENT,
65
- )
66
 
67
- # Display Data
68
-
69
- indicators = pn.FlexBox(
70
- pn.indicators.Number(
71
- value=count, name="Count", format="{value:,.0f}", styles=styles
72
- ),
73
- pn.indicators.Number(
74
- value=total_capacity / 1e6,
75
- name="Total Capacity (TW)",
76
- format="{value:,.1f}",
77
- styles=styles,
78
- ),
79
- pn.indicators.Number(
80
- value=avg_capacity/1e3,
81
- name="Avg. Capacity (MW)",
82
- format="{value:,.1f}",
83
- styles=styles,
84
- ),
85
- pn.indicators.Number(
86
- value=avg_rotor_diameter,
87
- name="Avg. Rotor Diameter (m)",
88
- format="{value:,.1f}",
89
- styles=styles,
90
- ),
91
- )
92
 
93
- plot = pn.pane.HoloViews(fig, sizing_mode="stretch_both", name="Plot")
94
- table = pn.widgets.Tabulator(df, sizing_mode="stretch_both", name="Table")
95
 
96
- # Layout Data
97
 
98
- tabs = pn.Tabs(
99
- plot, table, styles=styles, sizing_mode="stretch_width", height=500, margin=10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  )
101
 
102
- pn.template.FastListTemplate(
103
- title="Wind Turbine Dashboard",
104
- sidebar=[image, t_manu, p_year],
105
- main=[pn.Column(indicators, tabs, sizing_mode="stretch_both")],
106
- main_layout=None,
107
- accent=ACCENT,
 
 
 
 
 
 
 
 
 
 
 
 
108
  ).servable()
 
1
  import panel as pn
 
 
2
 
3
+ pn.extension(sizing_mode="stretch_width", design="material")
4
 
5
+ BUTTON_WIDTH = 125
6
 
7
+ # We use intslider to avoid teaching users pn.rx. Is that a good thing?
8
+ state_changed_count = pn.widgets.IntInput()
9
+ tasks = pn.Column()
 
 
10
 
11
+ def update_state_changed_count(*args):
12
+ state_changed_count.value += 1
13
 
14
+ def remove_task(task, *args):
15
+ index = tasks.index(task)
16
+ tasks.pop(index)
17
 
18
+ def remove_all_tasks(*args):
19
+ tasks.clear()
 
20
 
21
+ def create_task(text):
22
+ state = pn.widgets.Checkbox(align="center", sizing_mode="fixed")
23
+ content = pn.pane.Markdown(text)
24
+ remove = pn.widgets.Button(width=BUTTON_WIDTH, icon="trash", sizing_mode="fixed")
25
+ task = pn.Row(state, content, remove, sizing_mode="stretch_width")
26
 
27
+ pn.bind(remove_task, task, remove, watch=True)
28
+ # We have to bind the below after the above!
29
+ pn.bind(update_state_changed_count, state, remove, watch=True)
 
 
 
30
 
31
+ return task
 
 
32
 
33
+ def add_task(text, *args):
34
+ if not text:
35
+ return
36
 
37
+ new_task = create_task(text)
38
+ tasks.append(new_task)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
+ return tasks
41
+
42
+ def get_state(*args):
43
+ total_tasks = len(tasks)
44
+ completed_tasks = sum(check[0].value for check in tasks)
45
+ return f"{completed_tasks} of {total_tasks} tasks completed"
46
+
47
+ def can_add(value_input):
48
+ return not bool(value_input)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
+ def has_tasks(*args):
51
+ return len(tasks) > 0
52
 
 
53
 
54
+ add_task("Inspect the blades")
55
+ add_task("Inspect the nacelle")
56
+ add_task("Tighten the bolts")
57
+
58
+ text_input = pn.widgets.TextInput(name="Task", placeholder="Enter a task")
59
+
60
+ submit_task = pn.widgets.Button(
61
+ name="Add",
62
+ align="center",
63
+ button_type="primary",
64
+ width=BUTTON_WIDTH,
65
+ sizing_mode="fixed",
66
+ disabled=pn.bind(can_add, text_input.param.value_input)
67
+ )
68
+ clear = pn.widgets.Button(
69
+ name="Remove All",
70
+ button_type="primary",
71
+ button_style="outline",
72
+ width=BUTTON_WIDTH,
73
+ sizing_mode="fixed",
74
+ visible=pn.bind(has_tasks, state_changed_count)
75
  )
76
 
77
+ def reset_text_input(*args):
78
+ text_input.value = text_input.value_input = ""
79
+
80
+ pn.bind(add_task, text_input, submit_task, watch=True)
81
+ pn.bind(reset_text_input, text_input, submit_task, watch=True)
82
+ pn.bind(remove_all_tasks, clear, watch=True)
83
+ # We have to bind the below after the above!
84
+ pn.bind(update_state_changed_count, text_input, submit_task, clear, watch=True)
85
+
86
+ status_report = pn.bind(get_state, state_changed_count, tasks.param.objects)
87
+
88
+ pn.Column(
89
+ "## WTG Task List",
90
+ status_report,
91
+ pn.Row(text_input, submit_task),
92
+ tasks,
93
+ pn.Row(pn.Spacer(), clear),
94
+ max_width=500,
95
  ).servable()