Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -9,55 +9,6 @@ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image
|
|
| 9 |
from reportlab.lib.styles import getSampleStyleSheet
|
| 10 |
from reportlab.lib.units import inch
|
| 11 |
from io import BytesIO
|
| 12 |
-
import base64
|
| 13 |
-
# Removed FastAPI-related imports
|
| 14 |
-
# from fastapi import FastAPI, HTTPException
|
| 15 |
-
# from pydantic import BaseModel
|
| 16 |
-
# import uvicorn
|
| 17 |
-
# import nest_asyncio
|
| 18 |
-
|
| 19 |
-
# Commented out nest_asyncio and FastAPI setup
|
| 20 |
-
# nest_asyncio.apply()
|
| 21 |
-
# app = FastAPI()
|
| 22 |
-
|
| 23 |
-
# Commented out Pydantic model and API endpoint
|
| 24 |
-
# class ProjectInput(BaseModel):
|
| 25 |
-
# project_name: str
|
| 26 |
-
# phase: str
|
| 27 |
-
# task: str
|
| 28 |
-
# current_progress: float
|
| 29 |
-
# task_expected_duration: int
|
| 30 |
-
# task_actual_duration: int
|
| 31 |
-
# workforce_gap: float
|
| 32 |
-
# workforce_skill_level: str
|
| 33 |
-
# workforce_shift_hours: int
|
| 34 |
-
# weather_impact_score: int
|
| 35 |
-
# weather_forecast_date: str
|
| 36 |
-
|
| 37 |
-
# @app.post("/predict")
|
| 38 |
-
# async def predict(project_input: ProjectInput):
|
| 39 |
-
# input_data = project_input.dict()
|
| 40 |
-
# input_data["weather_condition"] = get_weather_condition(input_data["weather_impact_score"])
|
| 41 |
-
#
|
| 42 |
-
# error = validate_inputs(input_data)
|
| 43 |
-
# if error:
|
| 44 |
-
# raise HTTPException(status_code=400, detail=error)
|
| 45 |
-
#
|
| 46 |
-
# prediction = predict_delay(input_data)
|
| 47 |
-
#
|
| 48 |
-
# if "error" in prediction:
|
| 49 |
-
# raise HTTPException(status_code=500, detail=prediction["error"])
|
| 50 |
-
#
|
| 51 |
-
# fig = generate_heatmap(prediction['delay_probability'], f"{input_data['phase']}: {input_data['task']}")
|
| 52 |
-
#
|
| 53 |
-
# pdf_buffer = generate_pdf(input_data, prediction, fig)
|
| 54 |
-
# pdf_base64 = base64.b64encode(pdf_buffer.getvalue()).decode('utf-8')
|
| 55 |
-
# plt.close(fig)
|
| 56 |
-
#
|
| 57 |
-
# return {
|
| 58 |
-
# "prediction": prediction,
|
| 59 |
-
# "pdf_base64": pdf_base64
|
| 60 |
-
# }
|
| 61 |
|
| 62 |
# Streamlit app configuration
|
| 63 |
st.set_page_config(page_title="Delay 🚀", layout="wide")
|
|
@@ -78,15 +29,6 @@ if 'phase' not in st.session_state:
|
|
| 78 |
if 'task' not in st.session_state:
|
| 79 |
st.session_state.task = ""
|
| 80 |
|
| 81 |
-
# Function to format high_risk_phases with flag and alert
|
| 82 |
-
def format_high_risk_phases(high_risk_phases):
|
| 83 |
-
formatted = []
|
| 84 |
-
for phase in high_risk_phases:
|
| 85 |
-
flag = "🚩" if phase['risk'] > 75 else ""
|
| 86 |
-
alert = "[Alert]" if phase['risk'] > 75 else ""
|
| 87 |
-
formatted.append(f"{flag} {phase['phase']}: {phase['task']} (Risk: {phase['risk']:.1f}%) {alert}")
|
| 88 |
-
return formatted
|
| 89 |
-
|
| 90 |
# Function to generate PDF
|
| 91 |
def generate_pdf(input_data, prediction, heatmap_fig):
|
| 92 |
buffer = BytesIO()
|
|
@@ -108,6 +50,8 @@ def generate_pdf(input_data, prediction, heatmap_fig):
|
|
| 108 |
f"Task Expected Duration: {input_data['task_expected_duration']} days",
|
| 109 |
f"Task Actual Duration: {input_data['task_actual_duration']} days",
|
| 110 |
f"Workforce Gap: {input_data['workforce_gap']}%",
|
|
|
|
|
|
|
| 111 |
f"Weather Impact Score: {input_data['weather_impact_score']}",
|
| 112 |
f"Weather Condition: {input_data['weather_condition']}",
|
| 113 |
f"Weather Forecast Date: {input_data['weather_forecast_date']}"
|
|
@@ -118,10 +62,9 @@ def generate_pdf(input_data, prediction, heatmap_fig):
|
|
| 118 |
|
| 119 |
# Prediction Results
|
| 120 |
story.append(Paragraph("Prediction Results", styles['Heading2']))
|
| 121 |
-
high_risk_text = "<br/>".join(format_high_risk_phases(prediction['high_risk_phases']))
|
| 122 |
prediction_fields = [
|
| 123 |
f"Delay Probability: {prediction['delay_probability']:.2f}%",
|
| 124 |
-
f"High Risk Phases
|
| 125 |
f"AI Insights: {prediction['ai_insights']}",
|
| 126 |
f"Weather Condition: {prediction['weather_condition']}"
|
| 127 |
]
|
|
@@ -131,11 +74,13 @@ def generate_pdf(input_data, prediction, heatmap_fig):
|
|
| 131 |
|
| 132 |
# Heatmap
|
| 133 |
story.append(Paragraph("Delay Risk Heatmap", styles['Heading2']))
|
|
|
|
| 134 |
img_buffer = BytesIO()
|
| 135 |
heatmap_fig.savefig(img_buffer, format='png', bbox_inches='tight')
|
| 136 |
img_buffer.seek(0)
|
|
|
|
| 137 |
story.append(Image(img_buffer, width=6*inch, height=2*inch))
|
| 138 |
-
plt.close(heatmap_fig)
|
| 139 |
|
| 140 |
doc.build(story)
|
| 141 |
buffer.seek(0)
|
|
@@ -149,9 +94,10 @@ with st.form("project_form"):
|
|
| 149 |
project_name = st.text_input("Project Name")
|
| 150 |
phase = st.selectbox("Phase", [""] + ["Planning", "Design", "Construction"], index=0, key="phase_select")
|
| 151 |
|
|
|
|
| 152 |
if phase != st.session_state.phase:
|
| 153 |
st.session_state.phase = phase
|
| 154 |
-
st.session_state.task = ""
|
| 155 |
task_options_list = [""] + task_options.get(phase, []) if phase else [""]
|
| 156 |
task = st.selectbox("Task", task_options_list, index=0, key="task_select")
|
| 157 |
current_progress = st.number_input("Current Progress (%)", min_value=0.0, max_value=100.0, step=1.0)
|
|
@@ -162,8 +108,10 @@ with st.form("project_form"):
|
|
| 162 |
workforce_gap = st.number_input("Workforce Gap (%)", min_value=0.0, max_value=100.0, step=1.0)
|
| 163 |
workforce_skill_level = st.selectbox("Workforce Skill Level", ["Low", "Medium", "High"], index=1)
|
| 164 |
workforce_shift_hours = st.number_input("Workforce Shift Hours", min_value=0, step=1, value=8)
|
|
|
|
| 165 |
st.write(f"**Selected Shift Hours**: {workforce_shift_hours}")
|
| 166 |
weather_impact_score = st.number_input("Weather Impact Score (0-100)", min_value=0, max_value=100, step=1)
|
|
|
|
| 167 |
weather_condition = get_weather_condition(weather_impact_score)
|
| 168 |
st.write(f"**Weather Condition**: {weather_condition}")
|
| 169 |
weather_forecast_date = st.date_input("Weather Forecast Date", min_value=datetime(2025, 1, 1))
|
|
@@ -172,6 +120,7 @@ with st.form("project_form"):
|
|
| 172 |
|
| 173 |
# Process form submission
|
| 174 |
if submit_button:
|
|
|
|
| 175 |
input_data = {
|
| 176 |
"project_name": project_name,
|
| 177 |
"phase": phase,
|
|
@@ -187,27 +136,30 @@ if submit_button:
|
|
| 187 |
"weather_forecast_date": weather_forecast_date.strftime("%Y-%m-%d")
|
| 188 |
}
|
| 189 |
|
|
|
|
| 190 |
error = validate_inputs(input_data)
|
| 191 |
if error:
|
| 192 |
st.error(error)
|
| 193 |
else:
|
|
|
|
| 194 |
with st.spinner("Predicting..."):
|
| 195 |
prediction = predict_delay(input_data)
|
| 196 |
|
| 197 |
if "error" in prediction:
|
| 198 |
st.error(prediction["error"])
|
| 199 |
else:
|
|
|
|
| 200 |
st.subheader("Prediction Results")
|
| 201 |
st.write(f"**Delay Probability**: {prediction['delay_probability']:.2f}%")
|
| 202 |
-
st.write("**High Risk Phases**:")
|
| 203 |
-
for line in format_high_risk_phases(prediction['high_risk_phases']):
|
| 204 |
-
st.write(line)
|
| 205 |
st.write(f"**AI Insights**: {prediction['ai_insights']}")
|
| 206 |
st.write(f"**Weather Condition**: {prediction['weather_condition']}")
|
| 207 |
|
|
|
|
| 208 |
fig = generate_heatmap(prediction['delay_probability'], f"{phase}: {task}")
|
| 209 |
st.pyplot(fig)
|
| 210 |
|
|
|
|
| 211 |
pdf_buffer = generate_pdf(input_data, prediction, fig)
|
| 212 |
st.download_button(
|
| 213 |
label="Download Prediction Report (PDF)",
|
|
@@ -216,9 +168,6 @@ if submit_button:
|
|
| 216 |
mime="application/pdf"
|
| 217 |
)
|
| 218 |
|
|
|
|
| 219 |
st.session_state.prediction = prediction
|
| 220 |
-
st.session_state.input_data = input_data
|
| 221 |
-
|
| 222 |
-
# Commented out FastAPI server startup
|
| 223 |
-
# if __name__ == "__main__":
|
| 224 |
-
# uvicorn.run(app, host="0.0.0.0", port=8000, log_level="error")
|
|
|
|
| 9 |
from reportlab.lib.styles import getSampleStyleSheet
|
| 10 |
from reportlab.lib.units import inch
|
| 11 |
from io import BytesIO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
|
| 13 |
# Streamlit app configuration
|
| 14 |
st.set_page_config(page_title="Delay 🚀", layout="wide")
|
|
|
|
| 29 |
if 'task' not in st.session_state:
|
| 30 |
st.session_state.task = ""
|
| 31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
# Function to generate PDF
|
| 33 |
def generate_pdf(input_data, prediction, heatmap_fig):
|
| 34 |
buffer = BytesIO()
|
|
|
|
| 50 |
f"Task Expected Duration: {input_data['task_expected_duration']} days",
|
| 51 |
f"Task Actual Duration: {input_data['task_actual_duration']} days",
|
| 52 |
f"Workforce Gap: {input_data['workforce_gap']}%",
|
| 53 |
+
f"Workforce Skill Level: {input_data['workforce_skill_level']}",
|
| 54 |
+
f"Workforce Shift Hours: {input_data['workforce_shift_hours']}",
|
| 55 |
f"Weather Impact Score: {input_data['weather_impact_score']}",
|
| 56 |
f"Weather Condition: {input_data['weather_condition']}",
|
| 57 |
f"Weather Forecast Date: {input_data['weather_forecast_date']}"
|
|
|
|
| 62 |
|
| 63 |
# Prediction Results
|
| 64 |
story.append(Paragraph("Prediction Results", styles['Heading2']))
|
|
|
|
| 65 |
prediction_fields = [
|
| 66 |
f"Delay Probability: {prediction['delay_probability']:.2f}%",
|
| 67 |
+
f"High Risk Phases: {prediction['high_risk_phases']}",
|
| 68 |
f"AI Insights: {prediction['ai_insights']}",
|
| 69 |
f"Weather Condition: {prediction['weather_condition']}"
|
| 70 |
]
|
|
|
|
| 74 |
|
| 75 |
# Heatmap
|
| 76 |
story.append(Paragraph("Delay Risk Heatmap", styles['Heading2']))
|
| 77 |
+
# Save heatmap figure to BytesIO as PNG
|
| 78 |
img_buffer = BytesIO()
|
| 79 |
heatmap_fig.savefig(img_buffer, format='png', bbox_inches='tight')
|
| 80 |
img_buffer.seek(0)
|
| 81 |
+
# Embed image in PDF (scale to fit page width)
|
| 82 |
story.append(Image(img_buffer, width=6*inch, height=2*inch))
|
| 83 |
+
plt.close(heatmap_fig) # Close figure to free memory
|
| 84 |
|
| 85 |
doc.build(story)
|
| 86 |
buffer.seek(0)
|
|
|
|
| 94 |
project_name = st.text_input("Project Name")
|
| 95 |
phase = st.selectbox("Phase", [""] + ["Planning", "Design", "Construction"], index=0, key="phase_select")
|
| 96 |
|
| 97 |
+
# Update task options based on phase
|
| 98 |
if phase != st.session_state.phase:
|
| 99 |
st.session_state.phase = phase
|
| 100 |
+
st.session_state.task = "" # Reset task when phase changes
|
| 101 |
task_options_list = [""] + task_options.get(phase, []) if phase else [""]
|
| 102 |
task = st.selectbox("Task", task_options_list, index=0, key="task_select")
|
| 103 |
current_progress = st.number_input("Current Progress (%)", min_value=0.0, max_value=100.0, step=1.0)
|
|
|
|
| 108 |
workforce_gap = st.number_input("Workforce Gap (%)", min_value=0.0, max_value=100.0, step=1.0)
|
| 109 |
workforce_skill_level = st.selectbox("Workforce Skill Level", ["Low", "Medium", "High"], index=1)
|
| 110 |
workforce_shift_hours = st.number_input("Workforce Shift Hours", min_value=0, step=1, value=8)
|
| 111 |
+
# Debug output for shift hours
|
| 112 |
st.write(f"**Selected Shift Hours**: {workforce_shift_hours}")
|
| 113 |
weather_impact_score = st.number_input("Weather Impact Score (0-100)", min_value=0, max_value=100, step=1)
|
| 114 |
+
# Display computed weather condition
|
| 115 |
weather_condition = get_weather_condition(weather_impact_score)
|
| 116 |
st.write(f"**Weather Condition**: {weather_condition}")
|
| 117 |
weather_forecast_date = st.date_input("Weather Forecast Date", min_value=datetime(2025, 1, 1))
|
|
|
|
| 120 |
|
| 121 |
# Process form submission
|
| 122 |
if submit_button:
|
| 123 |
+
# Prepare input data
|
| 124 |
input_data = {
|
| 125 |
"project_name": project_name,
|
| 126 |
"phase": phase,
|
|
|
|
| 136 |
"weather_forecast_date": weather_forecast_date.strftime("%Y-%m-%d")
|
| 137 |
}
|
| 138 |
|
| 139 |
+
# Validate inputs
|
| 140 |
error = validate_inputs(input_data)
|
| 141 |
if error:
|
| 142 |
st.error(error)
|
| 143 |
else:
|
| 144 |
+
# Get prediction
|
| 145 |
with st.spinner("Predicting..."):
|
| 146 |
prediction = predict_delay(input_data)
|
| 147 |
|
| 148 |
if "error" in prediction:
|
| 149 |
st.error(prediction["error"])
|
| 150 |
else:
|
| 151 |
+
# Display results
|
| 152 |
st.subheader("Prediction Results")
|
| 153 |
st.write(f"**Delay Probability**: {prediction['delay_probability']:.2f}%")
|
| 154 |
+
st.write(f"**High Risk Phases**: {prediction['high_risk_phases']}")
|
|
|
|
|
|
|
| 155 |
st.write(f"**AI Insights**: {prediction['ai_insights']}")
|
| 156 |
st.write(f"**Weather Condition**: {prediction['weather_condition']}")
|
| 157 |
|
| 158 |
+
# Generate and display heatmap
|
| 159 |
fig = generate_heatmap(prediction['delay_probability'], f"{phase}: {task}")
|
| 160 |
st.pyplot(fig)
|
| 161 |
|
| 162 |
+
# Generate PDF with heatmap and provide download link
|
| 163 |
pdf_buffer = generate_pdf(input_data, prediction, fig)
|
| 164 |
st.download_button(
|
| 165 |
label="Download Prediction Report (PDF)",
|
|
|
|
| 168 |
mime="application/pdf"
|
| 169 |
)
|
| 170 |
|
| 171 |
+
# Store prediction in session state
|
| 172 |
st.session_state.prediction = prediction
|
| 173 |
+
st.session_state.input_data = input_data
|
|
|
|
|
|
|
|
|
|
|
|