Spaces:
Sleeping
Sleeping
Upload 4 files
Browse filesAdded first version of Dashboard
andon.py
ADDED
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/book/EventTracker/11_Andon.ipynb.
|
2 |
+
|
3 |
+
# %% auto 0
|
4 |
+
__all__ = ['df', 'farms', 'selected_farms', 'filter_df', 'generate_discrete_colors', 'get_discrete_colormap', 'get_summary',
|
5 |
+
'get_event_metrics', 'get_algo_performance', 'get_pie', 'get_data', 'get_farms', 'kpi']
|
6 |
+
|
7 |
+
# %% ../../nbs/book/EventTracker/11_Andon.ipynb 2
|
8 |
+
import streamlit as st
|
9 |
+
import pandas as pd
|
10 |
+
import numpy as np
|
11 |
+
import pandas as pd
|
12 |
+
import matplotlib.pyplot as plt
|
13 |
+
import seaborn as sns
|
14 |
+
import plotly.express as px
|
15 |
+
|
16 |
+
# %% ../../nbs/book/EventTracker/11_Andon.ipynb 6
|
17 |
+
st.set_page_config(
|
18 |
+
page_title="Andon",
|
19 |
+
layout='wide'
|
20 |
+
)
|
21 |
+
|
22 |
+
# %% ../../nbs/book/EventTracker/11_Andon.ipynb 11
|
23 |
+
def generate_discrete_colors(n):
|
24 |
+
colors = px.colors.qualitative.Plotly
|
25 |
+
return [colors[i % len(colors)] for i in range(n)]
|
26 |
+
|
27 |
+
generate_discrete_colors(5)
|
28 |
+
|
29 |
+
# %% ../../nbs/book/EventTracker/11_Andon.ipynb 12
|
30 |
+
def get_discrete_colormap(classes):
|
31 |
+
colors = generate_discrete_colors(len(classes))
|
32 |
+
color_discrete_map = dict(zip(classes, colors))
|
33 |
+
return color_discrete_map
|
34 |
+
|
35 |
+
# %% ../../nbs/book/EventTracker/11_Andon.ipynb 13
|
36 |
+
def get_summary(df, col_a='Type of Alert', col_b='Ground Truth'):
|
37 |
+
cal_df = df[[col_a, col_b]].groupby([col_a, col_b]).value_counts().reset_index()
|
38 |
+
|
39 |
+
|
40 |
+
color_discrete_map = get_discrete_colormap(df[col_b].dropna().unique())
|
41 |
+
fig = px.bar(cal_df, y=col_a,
|
42 |
+
x='count',
|
43 |
+
color=col_b,
|
44 |
+
color_discrete_map=color_discrete_map,
|
45 |
+
orientation='h',
|
46 |
+
title=f'Summary: {col_a}|{col_b}')
|
47 |
+
|
48 |
+
fig.update_layout(
|
49 |
+
margin=dict(l=10, r=10, t=40, b=40),
|
50 |
+
yaxis=dict(automargin=True)
|
51 |
+
)
|
52 |
+
|
53 |
+
return fig
|
54 |
+
|
55 |
+
# %% ../../nbs/book/EventTracker/11_Andon.ipynb 16
|
56 |
+
def get_event_metrics(validated_df,
|
57 |
+
event_type_cols=['Heat', 'Missed Heat'],
|
58 |
+
event_type='Heat'):
|
59 |
+
val_event_df = validated_df[validated_df['Type of Alert'].isin(event_type_cols)]
|
60 |
+
a = val_event_df['Ground Truth'].value_counts()
|
61 |
+
|
62 |
+
recall = a.get('TRUE', 0)*100/(a.get('TRUE', 0)+a.get('MISSED', np.finfo(float).eps))
|
63 |
+
precision = a.get('TRUE', 0)*100/(a.get('TRUE', 0)+a.get('FALSE', np.finfo(float).eps))
|
64 |
+
|
65 |
+
return {
|
66 |
+
f'Validated_{event_type}_Recall': recall,
|
67 |
+
f'Validated_{event_type}_Precision': precision,
|
68 |
+
}
|
69 |
+
|
70 |
+
# %% ../../nbs/book/EventTracker/11_Andon.ipynb 17
|
71 |
+
def get_algo_performance(df):
|
72 |
+
confirmed_df = df[df['Ground Truth'].isin(['TRUE','FALSE', 'MISSED', 'EXCLUDE', 'OTHER'])]
|
73 |
+
validated_df = df[df['Ground Truth'].isin(['TRUE','FALSE', 'MISSED'])]
|
74 |
+
missed_df = df[df['Ground Truth'].isin(['MISSED'])]
|
75 |
+
heat_metrics = get_event_metrics(validated_df,
|
76 |
+
event_type_cols=['Heat', 'Missed Heat'],
|
77 |
+
event_type='Heat')
|
78 |
+
health_metrics = get_event_metrics(validated_df,
|
79 |
+
event_type_cols=['Health', 'Missed Health'],
|
80 |
+
event_type='Health')
|
81 |
+
|
82 |
+
data_coverage_metrics = {'Total':len(df),
|
83 |
+
'Confirmed': len(confirmed_df),
|
84 |
+
'Validated': len(validated_df),
|
85 |
+
'Missed': len(missed_df),
|
86 |
+
'Confirmed_Percentage': len(confirmed_df)*100/len(df),
|
87 |
+
'Validated_Percentage': len(validated_df)*100/len(df),
|
88 |
+
'Val_On_Confirm_Percentage': len(validated_df)*100/len(confirmed_df),
|
89 |
+
'Missed_On_Val_Percentage': len(missed_df)*100/len(validated_df) }
|
90 |
+
performance_metrics = {**data_coverage_metrics,**heat_metrics, **health_metrics}
|
91 |
+
return performance_metrics
|
92 |
+
|
93 |
+
# %% ../../nbs/book/EventTracker/11_Andon.ipynb 20
|
94 |
+
def get_pie(df, colname):
|
95 |
+
df_dist = df[colname].value_counts().reset_index()
|
96 |
+
fig = px.pie(df_dist, values='count',
|
97 |
+
names=colname,
|
98 |
+
title=f'{colname}',
|
99 |
+
color = colname,
|
100 |
+
color_discrete_map = get_discrete_colormap(df[colname].dropna().unique())
|
101 |
+
)
|
102 |
+
return fig
|
103 |
+
|
104 |
+
# %% ../../nbs/book/EventTracker/11_Andon.ipynb 35
|
105 |
+
def get_data(url="https://docs.google.com/spreadsheets/d/1TbqmmSzXtY8DwolVo9rN7M1QdZxLG30nro2cqrvn2CA/export?format=csv&#gid=294763682"):
|
106 |
+
df = pd.read_csv(url).dropna(how='all')
|
107 |
+
df['Alert Date'] = df['Alert Date'].str.replace("//", "-")
|
108 |
+
df = df.dropna(subset=['Alert Date'])
|
109 |
+
df['Type of Alert'] = df['Type of Alert'].str.strip()
|
110 |
+
return df
|
111 |
+
# colors
|
112 |
+
|
113 |
+
# %% ../../nbs/book/EventTracker/11_Andon.ipynb 36
|
114 |
+
def get_farms(df):
|
115 |
+
return df['Dairy Farm'].dropna().unique().tolist()
|
116 |
+
|
117 |
+
# %% ../../nbs/book/EventTracker/11_Andon.ipynb 39
|
118 |
+
def kpi(df, ncols = 7):
|
119 |
+
metrics = get_algo_performance(df)
|
120 |
+
dcols = st.columns(ncols)
|
121 |
+
for (i, (k, v)) in enumerate(metrics.items()):
|
122 |
+
with dcols[i%ncols]:
|
123 |
+
st.metric(k, np.round(v, 2))
|
124 |
+
|
125 |
+
# %% ../../nbs/book/EventTracker/11_Andon.ipynb 40
|
126 |
+
#|eval: false
|
127 |
+
df = get_data()
|
128 |
+
farms = get_farms(df)
|
129 |
+
selected_farms = st.sidebar.multiselect('Select farms', farms, max_selections=len(farms))
|
130 |
+
filter_df = df
|
131 |
+
if selected_farms:
|
132 |
+
str_farms = "|".join(selected_farms)
|
133 |
+
st.write(f"Selected_farms: {str_farms}")
|
134 |
+
filter_df = df[df['Dairy Farm'].isin(selected_farms)]
|
135 |
+
else:
|
136 |
+
st.write("Selected_farms: All")
|
137 |
+
# st.write(farms)
|
138 |
+
kpi(filter_df,ncols=4)
|
139 |
+
st.plotly_chart(get_pie(filter_df, colname = 'Type of Alert'))
|
140 |
+
st.plotly_chart(get_pie(filter_df, colname = 'Ground Truth'))
|
141 |
+
st.plotly_chart(get_pie(filter_df, colname = 'Dairy Farm'))
|
142 |
+
st.plotly_chart(get_summary(filter_df, col_a='Type of Alert', col_b='Ground Truth'))
|
143 |
+
st.plotly_chart(get_summary(filter_df, col_b='Type of Alert', col_a='Dairy Farm'))
|
144 |
+
st.plotly_chart(get_summary(filter_df, col_b='Ground Truth', col_a='Dairy Farm'))
|
145 |
+
#
|
app.py
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/book/EventTracker/10_App.ipynb.
|
2 |
+
|
3 |
+
# %% auto 0
|
4 |
+
__all__ = ['andon_page', 'master_page']
|
5 |
+
|
6 |
+
# %% ../../nbs/book/EventTracker/10_App.ipynb 3
|
7 |
+
import streamlit as st
|
8 |
+
|
9 |
+
# %% ../../nbs/book/EventTracker/10_App.ipynb 5
|
10 |
+
# def menu():
|
11 |
+
# st.sidebar.page_link(st.Page("andon.py", default=True), label="Andon")
|
12 |
+
# st.sidebar.page_link(st.Page("floating.py", url_path=".."), label="Floating")
|
13 |
+
# st.sidebar.page_link(st.Page("model.py", url_path=".."), label="Model")
|
14 |
+
# st.sidebar.page_link(st.Page("master.py", url_path=".."), label="Master")
|
15 |
+
# # st.sidebar.page_link("pages/2_mapping_demo.py", label="Mapping Demo")
|
16 |
+
# # st.sidebar.page_link("pages/3_dataframe_demo.py", label="Dataframe Demo")
|
17 |
+
|
18 |
+
|
19 |
+
andon_page = st.Page("andon.py", default=True, title="Andon")
|
20 |
+
master_page = st.Page("master.py", title="Master")
|
21 |
+
|
22 |
+
|
23 |
+
|
24 |
+
# %% ../../nbs/book/EventTracker/10_App.ipynb 6
|
25 |
+
#| eval: false
|
26 |
+
from fastcore.basics import in_notebook
|
27 |
+
if not in_notebook():
|
28 |
+
pg = st.navigation([andon_page, master_page])
|
29 |
+
pg.run()
|
master.py
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/book/EventTracker/12_MasterTable.ipynb.
|
2 |
+
|
3 |
+
# %% auto 0
|
4 |
+
__all__ = ['df', 'get_data']
|
5 |
+
|
6 |
+
# %% ../../nbs/book/EventTracker/12_MasterTable.ipynb 2
|
7 |
+
import streamlit as st
|
8 |
+
import pandas as pd
|
9 |
+
import numpy as np
|
10 |
+
import pandas as pd
|
11 |
+
import matplotlib.pyplot as plt
|
12 |
+
|
13 |
+
|
14 |
+
# %% ../../nbs/book/EventTracker/12_MasterTable.ipynb 6
|
15 |
+
st.set_page_config(
|
16 |
+
page_title="Master",
|
17 |
+
page_icon="👋",
|
18 |
+
layout='wide'
|
19 |
+
)
|
20 |
+
|
21 |
+
# %% ../../nbs/book/EventTracker/12_MasterTable.ipynb 7
|
22 |
+
# st.sidebar.success("Select a demo above.")
|
23 |
+
|
24 |
+
# %% ../../nbs/book/EventTracker/12_MasterTable.ipynb 9
|
25 |
+
def get_data(url="https://docs.google.com/spreadsheets/d/1TbqmmSzXtY8DwolVo9rN7M1QdZxLG30nro2cqrvn2CA/export?format=csv&#gid=294763682"):
|
26 |
+
df = pd.read_csv(url).dropna(how='all')
|
27 |
+
df['Alert Date'] = df['Alert Date'].str.replace("//", "-")
|
28 |
+
df = df.dropna(subset=['Alert Date'])
|
29 |
+
df['Type of Alert'] = df['Type of Alert'].str.strip()
|
30 |
+
return df
|
31 |
+
|
32 |
+
# %% ../../nbs/book/EventTracker/12_MasterTable.ipynb 10
|
33 |
+
#|eval: false
|
34 |
+
df = get_data()
|
35 |
+
st.write("# Master Table")
|
36 |
+
|
37 |
+
st.table(data=df)
|
requirements.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
fastcore
|
2 |
+
pandas
|
3 |
+
matplotlib
|
4 |
+
plotly
|
5 |
+
seaborn
|
6 |
+
openpyxl
|