Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import joblib | |
| import numpy as np | |
| import pandas as pd | |
| # ------------------------------ | |
| # 1. Load Model & Scaler | |
| # ------------------------------ | |
| MODEL_PATH = "src/voting_model.joblib" | |
| SCALER_PATH = "src/scaler.joblib" | |
| def load_artifacts(): | |
| try: | |
| model = joblib.load(MODEL_PATH) | |
| scaler = joblib.load(SCALER_PATH) | |
| return model, scaler | |
| except Exception as e: | |
| st.error(f"Error loading model: {e}") | |
| return None, None | |
| model, scaler = load_artifacts() | |
| # ------------------------------ | |
| # 2. Feature Engineering Function | |
| # ------------------------------ | |
| def engineer_features(df): | |
| data = df.copy() | |
| epsilon = 1e-6 | |
| data['stiffness_low'] = data['Columns 1-3 I mm4*10^6'] / (data['Floor height m']**3 + epsilon) | |
| data['stiffness_high'] = data['Columns 4-6 I mm4*10^6'] / (data['Floor height m']**3 + epsilon) | |
| data['stiffness_diff'] = data['stiffness_low'] - data['stiffness_high'] | |
| data['strength_ratio'] = data['Column fy Mpa'] / (data['Beam fy Mpa'] + epsilon) | |
| data['total_height'] = data['Number of floors'] * data['Floor height m'] | |
| data['total_width'] = data['Spans'] * data['Span width m'] | |
| data['slenderness'] = data['total_height'] / (data['total_width'] + epsilon) | |
| data['total_area_low'] = data['Columns 1-3 A mm2'] * (data['Spans'] + 1) | |
| data['seismic_power'] = data['PGA g'] * data['Magnitude'] | |
| data['fault_attenuation'] = data['Magnitude'] / np.log1p(data['Distance to fault km']) | |
| data['total_mass'] = data['Floor mass kg'] * data['Number of floors'] | |
| data['base_shear'] = data['total_mass'] * data['PGA g'] | |
| data = data.replace([np.inf, -np.inf], 0) | |
| return data | |
| # ------------------------------ | |
| # 3. User Input Section | |
| # ------------------------------ | |
| st.title("π’ Seismic Building Safety Prediction") | |
| st.write(""" | |
| This AI model predicts the **Maximum Interstorey Drift (mm)** a building might experience during an earthquake. | |
| Lower drift values generally indicate safer buildings. | |
| """) | |
| RAW_INPUTS = [ | |
| "Column fy Mpa", "Beam fy Mpa", | |
| "Columns 1-3 I mm4*10^6", "Columns 4-6 I mm4*10^6", | |
| "Columns 1-3 A mm2", "Columns 4-6 A mm2", "Beam I mm4*10^6", | |
| "Spans", "Number of floors", "Floor height m", "Span width m", | |
| "LLRS tributary width m", "Floor mass kg", "Facade Load kN/m", | |
| "PGA g", "Magnitude", "Distance to fault km", "Period s", | |
| "Final Dead Load", "Final Live Load" | |
| ] | |
| input_data = {} | |
| with st.form("input_form"): | |
| c1, c2 = st.columns(2) | |
| for i, col_name in enumerate(RAW_INPUTS): | |
| if i % 2 == 0: | |
| with c1: | |
| input_data[col_name] = st.number_input(col_name, value=0.0, format="%.2f") | |
| else: | |
| with c2: | |
| input_data[col_name] = st.number_input(col_name, value=0.0, format="%.2f") | |
| soil_class = st.selectbox("Soil Class", ["A (Other)", "B", "C"]) | |
| input_data['soil_class__B'] = 1.0 if soil_class == "B" else 0.0 | |
| input_data['soil_class__C'] = 1.0 if soil_class == "C" else 0.0 | |
| submitted = st.form_submit_button("Predict Max Drift") | |
| # ------------------------------ | |
| # 4. Prediction Logic | |
| # ------------------------------ | |
| if submitted: | |
| if model is None or scaler is None: | |
| st.error("Model could not be loaded!") | |
| else: | |
| try: | |
| df_raw = pd.DataFrame([input_data]) | |
| df_engineered = engineer_features(df_raw) | |
| X_scaled = scaler.transform(df_engineered) | |
| log_pred = model.predict(X_scaled) | |
| real_pred = np.expm1(log_pred)[0] | |
| st.divider() | |
| st.success(f"### π― Predicted Drift: **{real_pred:.2f} mm**") | |
| if real_pred < 10: | |
| st.info("Risk: π’ Low (Safe)") | |
| elif real_pred < 50: | |
| st.warning("Risk: π‘ Medium (Potential Damage)") | |
| else: | |
| st.error("Risk: π΄ High (Collapse Hazard)") | |
| except Exception as e: | |
| st.error(f"Calculation error: {e}") | |
| st.write("Please ensure all values are entered correctly.") |