AjaykumarPilla commited on
Commit
5ddefb1
Β·
verified Β·
1 Parent(s): a898965

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +61 -81
app.py CHANGED
@@ -1,21 +1,10 @@
1
  import streamlit as st
2
  import pandas as pd
3
- import pickle
4
  from prophet import Prophet
5
  from datetime import datetime, timedelta
6
  import numpy as np
7
  import plotly.graph_objects as go
8
 
9
- # Load the trained models (optional, for initialization or fallback)
10
- @st.cache_resource
11
- def load_model():
12
- try:
13
- with open('model.pkl', 'rb') as f:
14
- models = pickle.load(f)
15
- return models
16
- except FileNotFoundError:
17
- return None
18
-
19
  # Prepare data for Prophet
20
  def prepare_prophet_data(usage_series):
21
  end_date = datetime.now()
@@ -28,15 +17,24 @@ def prepare_prophet_data(usage_series):
28
  })
29
  return prophet_df
30
 
31
- # Train or update Prophet model with reduced sensitivity
32
- def train_model_with_usage(usage_series):
33
  prophet_df = prepare_prophet_data(usage_series)
 
 
 
 
 
 
 
 
 
34
  model = Prophet(
35
  yearly_seasonality=False,
36
  weekly_seasonality=True,
37
  daily_seasonality=True,
38
- changepoint_prior_scale=0.01, # πŸ‘ˆ Reduced sensitivity to recent changes
39
- changepoint_range=0.6 # πŸ‘ˆ Only look at early 60% of data for trend changes
40
  )
41
  model.fit(prophet_df)
42
  return model
@@ -45,7 +43,7 @@ def train_model_with_usage(usage_series):
45
  def make_forecast(model, periods):
46
  future = model.make_future_dataframe(periods=periods)
47
  forecast = model.predict(future)
48
- return round(forecast['yhat'].tail(periods).sum())
49
 
50
  # Function to validate input
51
  def validate_usage_series(usage_str):
@@ -62,99 +60,81 @@ def validate_usage_series(usage_str):
62
  # Main Streamlit app
63
  def main():
64
  st.title("SmartLab Consumables Forecast")
65
-
66
- models = load_model()
67
-
68
  st.header("Input Parameters")
69
  consumable_type = st.selectbox("Consumable Type", ['Filters', 'Reagents', 'Vials'])
70
  usage_series = st.text_input("Last 60 Days Usage (comma-separated)", "")
71
  current_stock = st.number_input("Current Stock", min_value=0, value=0)
72
-
 
73
  if st.button("Generate Forecast"):
74
  usage_list, error = validate_usage_series(usage_series)
75
  if error:
76
  st.error(error)
77
  return
78
-
79
  try:
80
- model = train_model_with_usage(usage_list)
81
  except Exception as e:
82
  st.error(f"Error training model: {str(e)}")
83
  return
84
-
85
- forecast_7 = make_forecast(model, 7)
86
- forecast_14 = make_forecast(model, 14)
87
- forecast_30 = make_forecast(model, 30)
88
-
89
  st.header("Forecast Results")
90
  st.write(f"**7-Day Forecast**: {forecast_7} units")
91
  st.write(f"**14-Day Forecast**: {forecast_14} units")
92
  st.write(f"**30-Day Forecast**: {forecast_30} units")
93
-
94
  st.header("Threshold Alerts")
95
  if current_stock < forecast_7:
96
- st.warning(f"Alert: Current stock ({current_stock}) is below 7-day forecast ({forecast_7}). 🚩")
97
  if current_stock < forecast_14:
98
- st.warning(f"Alert: Current stock ({current_stock}) is below 14-day forecast ({forecast_14}). 🚩")
99
  if current_stock < forecast_30:
100
- st.warning(f"Alert: Current stock ({current_stock}) is below 30-day forecast ({forecast_30}). 🚩")
101
-
102
  st.header("Order Suggestions")
103
- order_7 = max(0, forecast_7 - current_stock)
104
- order_14 = max(0, forecast_14 - current_stock)
105
- order_30 = max(0, forecast_30 - current_stock)
106
- st.write(f"**For 7 Days**: Order {order_7} additional units.")
107
- st.write(f"**For 14 Days**: Order {order_14} additional units.")
108
- st.write(f"**For 30 Days**: Order {order_30} additional units.")
109
-
110
- st.header("Forecast Visualization")
111
- forecast_data = pd.DataFrame({
112
- 'Period': ['7 Days', '14 Days', '30 Days'],
113
- 'Units': [forecast_7, forecast_14, forecast_30]
114
- })
115
- fig_forecast = go.Figure()
116
- fig_forecast.add_trace(go.Scatter(
117
- x=forecast_data['Period'],
118
- y=forecast_data['Units'],
119
- mode='lines+markers',
120
- name='Forecasted Units',
121
- line=dict(color='blue'),
122
- marker=dict(size=10)
123
  ))
124
- fig_forecast.update_layout(
125
- title='Consumable Usage Forecast',
126
- xaxis_title='Time Period',
127
- yaxis_title='Units',
128
  template='plotly_white'
129
  )
130
- st.plotly_chart(fig_forecast)
131
-
132
- st.header("Threshold Alerts Visualization")
133
- alert_data = pd.DataFrame({
134
- 'Category': ['Current Stock', '7-Day Forecast', '14-Day Forecast', '30-Day Forecast'],
135
- 'Units': [current_stock, forecast_7, forecast_14, forecast_30],
136
- 'Alert': [
137
- False,
138
- current_stock < forecast_7,
139
- current_stock < forecast_14,
140
- current_stock < forecast_30
141
- ]
142
  })
143
- fig_alerts = go.Figure()
144
- fig_alerts.add_trace(go.Bar(
145
- x=alert_data['Category'],
146
- y=alert_data['Units'],
147
- marker_color=['green'] + ['red' if alert else 'blue' for alert in alert_data['Alert'][1:]],
148
- text=[f"🚩" if alert else "" for alert in alert_data['Alert']],
149
- textposition='auto'
150
- ))
151
- fig_alerts.update_layout(
152
- title='Stock vs Forecast with Alerts (🚩 indicates low stock)',
153
- xaxis_title='Category',
154
- yaxis_title='Units',
155
  template='plotly_white'
156
  )
157
- st.plotly_chart(fig_alerts)
158
 
159
  if __name__ == "__main__":
160
  main()
 
1
  import streamlit as st
2
  import pandas as pd
 
3
  from prophet import Prophet
4
  from datetime import datetime, timedelta
5
  import numpy as np
6
  import plotly.graph_objects as go
7
 
 
 
 
 
 
 
 
 
 
 
8
  # Prepare data for Prophet
9
  def prepare_prophet_data(usage_series):
10
  end_date = datetime.now()
 
17
  })
18
  return prophet_df
19
 
20
+ # Train model with sensitivity option
21
+ def train_model_with_usage(usage_series, sensitivity):
22
  prophet_df = prepare_prophet_data(usage_series)
23
+
24
+ # Set changepoint_prior_scale based on selected sensitivity
25
+ if sensitivity == "Low":
26
+ cps = 0.01
27
+ elif sensitivity == "Medium":
28
+ cps = 0.1
29
+ else: # High
30
+ cps = 0.5
31
+
32
  model = Prophet(
33
  yearly_seasonality=False,
34
  weekly_seasonality=True,
35
  daily_seasonality=True,
36
+ changepoint_prior_scale=cps,
37
+ changepoint_range=0.6
38
  )
39
  model.fit(prophet_df)
40
  return model
 
43
  def make_forecast(model, periods):
44
  future = model.make_future_dataframe(periods=periods)
45
  forecast = model.predict(future)
46
+ return forecast, round(forecast['yhat'].tail(periods).sum())
47
 
48
  # Function to validate input
49
  def validate_usage_series(usage_str):
 
60
  # Main Streamlit app
61
  def main():
62
  st.title("SmartLab Consumables Forecast")
63
+
 
 
64
  st.header("Input Parameters")
65
  consumable_type = st.selectbox("Consumable Type", ['Filters', 'Reagents', 'Vials'])
66
  usage_series = st.text_input("Last 60 Days Usage (comma-separated)", "")
67
  current_stock = st.number_input("Current Stock", min_value=0, value=0)
68
+ sensitivity = st.selectbox("Forecast Sensitivity", ['Low', 'Medium', 'High'])
69
+
70
  if st.button("Generate Forecast"):
71
  usage_list, error = validate_usage_series(usage_series)
72
  if error:
73
  st.error(error)
74
  return
75
+
76
  try:
77
+ model = train_model_with_usage(usage_list, sensitivity)
78
  except Exception as e:
79
  st.error(f"Error training model: {str(e)}")
80
  return
81
+
82
+ forecast_df, forecast_7 = make_forecast(model, 7)
83
+ _, forecast_14 = make_forecast(model, 14)
84
+ _, forecast_30 = make_forecast(model, 30)
85
+
86
  st.header("Forecast Results")
87
  st.write(f"**7-Day Forecast**: {forecast_7} units")
88
  st.write(f"**14-Day Forecast**: {forecast_14} units")
89
  st.write(f"**30-Day Forecast**: {forecast_30} units")
90
+
91
  st.header("Threshold Alerts")
92
  if current_stock < forecast_7:
93
+ st.warning(f"⚠️ Stock ({current_stock}) is below 7-day forecast ({forecast_7})")
94
  if current_stock < forecast_14:
95
+ st.warning(f"⚠️ Stock ({current_stock}) is below 14-day forecast ({forecast_14})")
96
  if current_stock < forecast_30:
97
+ st.warning(f"⚠️ Stock ({current_stock}) is below 30-day forecast ({forecast_30})")
98
+
99
  st.header("Order Suggestions")
100
+ st.write(f"πŸ›’ **Order for 7 Days**: {max(0, forecast_7 - current_stock)} units")
101
+ st.write(f"πŸ›’ **Order for 14 Days**: {max(0, forecast_14 - current_stock)} units")
102
+ st.write(f"πŸ›’ **Order for 30 Days**: {max(0, forecast_30 - current_stock)} units")
103
+
104
+ # Forecast Trend Visualization
105
+ st.header("Forecast Curve")
106
+ fig_curve = go.Figure()
107
+ fig_curve.add_trace(go.Scatter(
108
+ x=forecast_df['ds'],
109
+ y=forecast_df['yhat'],
110
+ mode='lines',
111
+ name='Forecasted Usage',
112
+ line=dict(color='royalblue')
 
 
 
 
 
 
 
113
  ))
114
+ fig_curve.update_layout(
115
+ title='Forecast Trend (yhat)',
116
+ xaxis_title='Date',
117
+ yaxis_title='Predicted Usage',
118
  template='plotly_white'
119
  )
120
+ st.plotly_chart(fig_curve)
121
+
122
+ # Summary Bar Chart
123
+ st.header("Forecast Summary")
124
+ bar_data = pd.DataFrame({
125
+ 'Period': ['7 Days', '14 Days', '30 Days'],
126
+ 'Forecast Units': [forecast_7, forecast_14, forecast_30]
 
 
 
 
 
127
  })
128
+ fig_bar = go.Figure(data=[
129
+ go.Bar(x=bar_data['Period'], y=bar_data['Forecast Units'], marker_color='blue')
130
+ ])
131
+ fig_bar.update_layout(
132
+ title="Forecast Summary",
133
+ xaxis_title="Forecast Period",
134
+ yaxis_title="Units",
 
 
 
 
 
135
  template='plotly_white'
136
  )
137
+ st.plotly_chart(fig_bar)
138
 
139
  if __name__ == "__main__":
140
  main()