AjaykumarPilla commited on
Commit
b83e695
·
verified ·
1 Parent(s): fef5413

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +17 -80
app.py CHANGED
@@ -1,29 +1,14 @@
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
- # Create a date range for the last 60 days
22
  end_date = datetime.now()
23
  start_date = end_date - timedelta(days=len(usage_series) - 1)
24
  dates = [start_date + timedelta(days=i) for i in range(len(usage_series))]
25
-
26
- # Create Prophet-compatible DataFrame
27
  prophet_df = pd.DataFrame({
28
  'ds': dates,
29
  'y': usage_series
@@ -32,6 +17,7 @@ def prepare_prophet_data(usage_series):
32
 
33
  # Train or update Prophet model with user-provided usage series
34
  def train_model_with_usage(usage_series):
 
35
  prophet_df = prepare_prophet_data(usage_series)
36
  model = Prophet(
37
  yearly_seasonality=False,
@@ -46,7 +32,9 @@ def train_model_with_usage(usage_series):
46
  def make_forecast(model, periods):
47
  future = model.make_future_dataframe(periods=periods)
48
  forecast = model.predict(future)
49
- return round(forecast['yhat'].tail(periods).sum()) # Round to nearest integer
 
 
50
 
51
  # Function to validate input
52
  def validate_usage_series(usage_str):
@@ -63,110 +51,59 @@ def validate_usage_series(usage_str):
63
  # Main Streamlit app
64
  def main():
65
  st.title("SmartLab Consumables Forecast")
 
 
 
66
 
67
- # Load pre-trained models (optional, for reference)
68
- models = load_model()
69
-
70
- # Input form
71
  st.header("Input Parameters")
72
  consumable_type = st.selectbox("Consumable Type", ['Filters', 'Reagents', 'Vials'])
73
  usage_series = st.text_input("Last 60 Days Usage (comma-separated)", "")
74
  current_stock = st.number_input("Current Stock", min_value=0, value=0)
75
 
76
  if st.button("Generate Forecast"):
77
- # Validate inputs
78
  usage_list, error = validate_usage_series(usage_series)
79
  if error:
80
  st.error(error)
81
  return
 
82
 
83
- # Train a new model with the user-provided usage series
84
  try:
85
  model = train_model_with_usage(usage_list)
86
  except Exception as e:
87
  st.error(f"Error training model: {str(e)}")
88
  return
89
 
90
- # Forecast for 7, 14, and 30 days
91
  forecast_7 = make_forecast(model, 7)
92
  forecast_14 = make_forecast(model, 14)
93
  forecast_30 = make_forecast(model, 30)
94
 
95
- # Display forecasts
96
  st.header("Forecast Results")
97
  st.write(f"**7-Day Forecast**: {forecast_7} units")
98
  st.write(f"**14-Day Forecast**: {forecast_14} units")
99
  st.write(f"**30-Day Forecast**: {forecast_30} units")
100
 
101
- # Threshold alerting
102
  st.header("Threshold Alerts")
103
  if current_stock < forecast_7:
104
  st.warning(f"Alert: Current stock ({current_stock}) is below 7-day forecast ({forecast_7}). 🚩")
 
 
105
  if current_stock < forecast_14:
106
  st.warning(f"Alert: Current stock ({current_stock}) is below 14-day forecast ({forecast_14}). 🚩")
 
 
107
  if current_stock < forecast_30:
108
  st.warning(f"Alert: Current stock ({current_stock}) is below 30-day forecast ({forecast_30}). 🚩")
 
 
109
 
110
- # Order suggestions
111
  st.header("Order Suggestions")
112
- order_7 = max(0, round(forecast_7 - current_stock)) # Round to nearest integer
113
- order_14 = max(0, round(forecast_14 - current_stock)) # Round to nearest integer
114
- order_30 = max(0, round(forecast_30 - current_stock)) # Round to nearest integer
115
 
116
  st.write(f"**For 7 Days**: Order {order_7} additional units.")
117
  st.write(f"**For 14 Days**: Order {order_14} additional units.")
118
  st.write(f"**For 30 Days**: Order {order_30} additional units.")
119
-
120
- # Graphical representation for forecast
121
- st.header("Forecast Visualization")
122
- forecast_data = pd.DataFrame({
123
- 'Period': ['7 Days', '14 Days', '30 Days'],
124
- 'Units': [forecast_7, forecast_14, forecast_30]
125
- })
126
- fig_forecast = go.Figure()
127
- fig_forecast.add_trace(go.Scatter(
128
- x=forecast_data['Period'],
129
- y=forecast_data['Units'],
130
- mode='lines+markers',
131
- name='Forecasted Units',
132
- line=dict(color='blue'),
133
- marker=dict(size=10)
134
- ))
135
- fig_forecast.update_layout(
136
- title='Consumable Usage Forecast',
137
- xaxis_title='Time Period',
138
- yaxis_title='Units',
139
- template='plotly_white'
140
- )
141
- st.plotly_chart(fig_forecast)
142
-
143
- # Graphical representation for threshold alerts
144
- st.header("Threshold Alerts Visualization")
145
- alert_data = pd.DataFrame({
146
- 'Category': ['Current Stock', '7-Day Forecast', '14-Day Forecast', '30-Day Forecast'],
147
- 'Units': [current_stock, forecast_7, forecast_14, forecast_30],
148
- 'Alert': [
149
- False,
150
- current_stock < forecast_7,
151
- current_stock < forecast_14,
152
- current_stock < forecast_30
153
- ]
154
- })
155
- fig_alerts = go.Figure()
156
- fig_alerts.add_trace(go.Bar(
157
- x=alert_data['Category'],
158
- y=alert_data['Units'],
159
- marker_color=['green'] + ['red' if alert else 'blue' for alert in alert_data['Alert'][1:]],
160
- text=[f"🚩" if alert else "" for alert in alert_data['Alert']],
161
- textposition='auto'
162
- ))
163
- fig_alerts.update_layout(
164
- title='Stock vs Forecast with Alerts (🚩 indicates low stock)',
165
- xaxis_title='Category',
166
- yaxis_title='Units',
167
- template='plotly_white'
168
- )
169
- st.plotly_chart(fig_alerts)
170
 
171
  if __name__ == "__main__":
172
  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
 
7
  # Prepare data for Prophet
8
  def prepare_prophet_data(usage_series):
 
9
  end_date = datetime.now()
10
  start_date = end_date - timedelta(days=len(usage_series) - 1)
11
  dates = [start_date + timedelta(days=i) for i in range(len(usage_series))]
 
 
12
  prophet_df = pd.DataFrame({
13
  'ds': dates,
14
  'y': usage_series
 
17
 
18
  # Train or update Prophet model with user-provided usage series
19
  def train_model_with_usage(usage_series):
20
+ print("Training with changepoint_prior_scale=0.01, usage:", usage_series) # Debug
21
  prophet_df = prepare_prophet_data(usage_series)
22
  model = Prophet(
23
  yearly_seasonality=False,
 
32
  def make_forecast(model, periods):
33
  future = model.make_future_dataframe(periods=periods)
34
  forecast = model.predict(future)
35
+ daily_forecasts = forecast['yhat'].tail(periods).tolist()
36
+ print(f"Daily forecasts for {periods} days:", [round(y) for y in daily_forecasts]) # Debug
37
+ return round(sum(max(0, y) for y in daily_forecasts)) # Clip negative values
38
 
39
  # Function to validate input
40
  def validate_usage_series(usage_str):
 
51
  # Main Streamlit app
52
  def main():
53
  st.title("SmartLab Consumables Forecast")
54
+ if st.button("Clear Cache"):
55
+ st.cache_resource.clear()
56
+ st.write("Cache cleared!")
57
 
 
 
 
 
58
  st.header("Input Parameters")
59
  consumable_type = st.selectbox("Consumable Type", ['Filters', 'Reagents', 'Vials'])
60
  usage_series = st.text_input("Last 60 Days Usage (comma-separated)", "")
61
  current_stock = st.number_input("Current Stock", min_value=0, value=0)
62
 
63
  if st.button("Generate Forecast"):
 
64
  usage_list, error = validate_usage_series(usage_series)
65
  if error:
66
  st.error(error)
67
  return
68
+ st.write("Debug: Input usage series:", usage_list) # Debug
69
 
 
70
  try:
71
  model = train_model_with_usage(usage_list)
72
  except Exception as e:
73
  st.error(f"Error training model: {str(e)}")
74
  return
75
 
 
76
  forecast_7 = make_forecast(model, 7)
77
  forecast_14 = make_forecast(model, 14)
78
  forecast_30 = make_forecast(model, 30)
79
 
 
80
  st.header("Forecast Results")
81
  st.write(f"**7-Day Forecast**: {forecast_7} units")
82
  st.write(f"**14-Day Forecast**: {forecast_14} units")
83
  st.write(f"**30-Day Forecast**: {forecast_30} units")
84
 
 
85
  st.header("Threshold Alerts")
86
  if current_stock < forecast_7:
87
  st.warning(f"Alert: Current stock ({current_stock}) is below 7-day forecast ({forecast_7}). 🚩")
88
+ else:
89
+ st.write("No alert for 7-day forecast.")
90
  if current_stock < forecast_14:
91
  st.warning(f"Alert: Current stock ({current_stock}) is below 14-day forecast ({forecast_14}). 🚩")
92
+ else:
93
+ st.write("No alert for 14-day forecast.")
94
  if current_stock < forecast_30:
95
  st.warning(f"Alert: Current stock ({current_stock}) is below 30-day forecast ({forecast_30}). 🚩")
96
+ else:
97
+ st.write("No alert for 30-day forecast.")
98
 
 
99
  st.header("Order Suggestions")
100
+ order_7 = max(0, round(forecast_7 - current_stock))
101
+ order_14 = max(0, round(forecast_14 - current_stock))
102
+ order_30 = max(0, round(forecast_30 - current_stock))
103
 
104
  st.write(f"**For 7 Days**: Order {order_7} additional units.")
105
  st.write(f"**For 14 Days**: Order {order_14} additional units.")
106
  st.write(f"**For 30 Days**: Order {order_30} additional units.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
  if __name__ == "__main__":
109
  main()