handex commited on
Commit
91c499e
Β·
verified Β·
1 Parent(s): aed945d

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +84 -60
src/streamlit_app.py CHANGED
@@ -4,92 +4,116 @@ import numpy as np
4
  import pandas as pd
5
 
6
  # ------------------------------
7
- # Load model & scaler
8
  # ------------------------------
9
  MODEL_PATH = "src/voting_model.joblib"
10
  SCALER_PATH = "src/scaler.joblib"
11
 
12
  @st.cache_resource
13
- def load_model():
14
  try:
15
  model = joblib.load(MODEL_PATH)
16
  scaler = joblib.load(SCALER_PATH)
17
  return model, scaler
18
  except Exception as e:
19
- st.error(f"Error loading model or scaler: {e}")
20
  return None, None
21
 
22
- model, scaler = load_model()
23
-
24
- st.title("🧠 Stress Detection Model")
25
- st.write("Enter the required parameters and get the prediction.")
26
 
27
  # ------------------------------
28
- # Input feature names
29
- # These MUST match the training dataset exactly
30
  # ------------------------------
31
- FEATURES = [
32
- "Column fy Mpa",
33
- "Beam fy Mpa",
34
- "Columns 1-3 I mm4*10^6",
35
- "Columns 4-6 I mm4*10^6",
36
- "Columns 1-3 A mm2",
37
- "Columns 4-6 A mm2",
38
- "Beam I mm4*10^6",
39
- "Spans",
40
- "Number of floors",
41
- "Floor height m",
42
- "Span width m",
43
- "LLRS tributary width m",
44
- "Floor mass kg",
45
- "Facade Load kN/m",
46
- "PGA g",
47
- "Magnitude",
48
- "Distance to fault km",
49
- "Period s",
50
- "Final Dead Load",
51
- "Final Live Load",
52
- "soil_class__B",
53
- "soil_class__C",
54
- "stiffness_low",
55
- "stiffness_high",
56
- "stiffness_diff",
57
- "strength_ratio",
58
- "total_height",
59
- "total_width",
60
- "slenderness",
61
- "total_area_low",
62
- "seismic_power",
63
- "fault_attenuation",
64
- "total_mass",
65
- "base_shear"
66
- ]
67
 
68
  # ------------------------------
69
- # User input section
70
  # ------------------------------
71
- inputs = {}
72
- st.subheader("πŸ“Œ Input Features")
 
 
 
73
 
74
- for f in FEATURES:
75
- inputs[f] = st.number_input(f, value=0.0)
 
 
 
 
 
 
 
76
 
77
- # Convert to dataframe
78
- input_df = pd.DataFrame([inputs])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
  # ------------------------------
81
- # Prediction
82
  # ------------------------------
83
- if st.button("Predict"):
84
  if model is None or scaler is None:
85
- st.error("Model is not loaded!")
86
  else:
87
  try:
88
- scaled = scaler.transform(input_df)
89
- pred = model.predict(scaled)[0]
90
- label = "Stress" if pred == 1 else "No Stress"
 
 
 
 
91
 
92
- st.success(f"### 🎯 Prediction: **{label}**")
 
 
 
 
 
 
 
 
 
 
93
 
94
  except Exception as e:
95
- st.error(f"Processing error: {e}")
 
 
4
  import pandas as pd
5
 
6
  # ------------------------------
7
+ # 1. Load Model & Scaler
8
  # ------------------------------
9
  MODEL_PATH = "src/voting_model.joblib"
10
  SCALER_PATH = "src/scaler.joblib"
11
 
12
  @st.cache_resource
13
+ def load_artifacts():
14
  try:
15
  model = joblib.load(MODEL_PATH)
16
  scaler = joblib.load(SCALER_PATH)
17
  return model, scaler
18
  except Exception as e:
19
+ st.error(f"Error loading model: {e}")
20
  return None, None
21
 
22
+ model, scaler = load_artifacts()
 
 
 
23
 
24
  # ------------------------------
25
+ # 2. Feature Engineering Function
 
26
  # ------------------------------
27
+ def engineer_features(df):
28
+ data = df.copy()
29
+ epsilon = 1e-6
30
+
31
+ data['stiffness_low'] = data['Columns 1-3 I mm4*10^6'] / (data['Floor height m']**3 + epsilon)
32
+ data['stiffness_high'] = data['Columns 4-6 I mm4*10^6'] / (data['Floor height m']**3 + epsilon)
33
+ data['stiffness_diff'] = data['stiffness_low'] - data['stiffness_high']
34
+
35
+ data['strength_ratio'] = data['Column fy Mpa'] / (data['Beam fy Mpa'] + epsilon)
36
+
37
+ data['total_height'] = data['Number of floors'] * data['Floor height m']
38
+ data['total_width'] = data['Spans'] * data['Span width m']
39
+ data['slenderness'] = data['total_height'] / (data['total_width'] + epsilon)
40
+ data['total_area_low'] = data['Columns 1-3 A mm2'] * (data['Spans'] + 1)
41
+
42
+ data['seismic_power'] = data['PGA g'] * data['Magnitude']
43
+ data['fault_attenuation'] = data['Magnitude'] / np.log1p(data['Distance to fault km'])
44
+
45
+ data['total_mass'] = data['Floor mass kg'] * data['Number of floors']
46
+ data['base_shear'] = data['total_mass'] * data['PGA g']
47
+
48
+ data = data.replace([np.inf, -np.inf], 0)
49
+ return data
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
  # ------------------------------
52
+ # 3. User Input Section
53
  # ------------------------------
54
+ st.title("🏒 Seismic Building Safety Prediction")
55
+ st.write("""
56
+ This AI model predicts the **Maximum Interstorey Drift (mm)** a building might experience during an earthquake.
57
+ Lower drift values generally indicate safer buildings.
58
+ """)
59
 
60
+ RAW_INPUTS = [
61
+ "Column fy Mpa", "Beam fy Mpa",
62
+ "Columns 1-3 I mm4*10^6", "Columns 4-6 I mm4*10^6",
63
+ "Columns 1-3 A mm2", "Columns 4-6 A mm2", "Beam I mm4*10^6",
64
+ "Spans", "Number of floors", "Floor height m", "Span width m",
65
+ "LLRS tributary width m", "Floor mass kg", "Facade Load kN/m",
66
+ "PGA g", "Magnitude", "Distance to fault km", "Period s",
67
+ "Final Dead Load", "Final Live Load"
68
+ ]
69
 
70
+ input_data = {}
71
+
72
+ with st.form("input_form"):
73
+ c1, c2 = st.columns(2)
74
+
75
+ for i, col_name in enumerate(RAW_INPUTS):
76
+ if i % 2 == 0:
77
+ with c1:
78
+ input_data[col_name] = st.number_input(col_name, value=0.0, format="%.2f")
79
+ else:
80
+ with c2:
81
+ input_data[col_name] = st.number_input(col_name, value=0.0, format="%.2f")
82
+
83
+ soil_class = st.selectbox("Soil Class", ["A (Other)", "B", "C"])
84
+ input_data['soil_class__B'] = 1.0 if soil_class == "B" else 0.0
85
+ input_data['soil_class__C'] = 1.0 if soil_class == "C" else 0.0
86
+
87
+ submitted = st.form_submit_button("Predict Max Drift")
88
 
89
  # ------------------------------
90
+ # 4. Prediction Logic
91
  # ------------------------------
92
+ if submitted:
93
  if model is None or scaler is None:
94
+ st.error("Model could not be loaded!")
95
  else:
96
  try:
97
+ df_raw = pd.DataFrame([input_data])
98
+
99
+ df_engineered = engineer_features(df_raw)
100
+
101
+ X_scaled = scaler.transform(df_engineered)
102
+
103
+ log_pred = model.predict(X_scaled)
104
 
105
+ real_pred = np.expm1(log_pred)[0]
106
+
107
+ st.divider()
108
+ st.success(f"### 🎯 Predicted Drift: **{real_pred:.2f} mm**")
109
+
110
+ if real_pred < 10:
111
+ st.info("Risk: 🟒 Low (Safe)")
112
+ elif real_pred < 50:
113
+ st.warning("Risk: 🟑 Medium (Potential Damage)")
114
+ else:
115
+ st.error("Risk: πŸ”΄ High (Collapse Hazard)")
116
 
117
  except Exception as e:
118
+ st.error(f"Calculation error: {e}")
119
+ st.write("Please ensure all values are entered correctly.")