import streamlit as st import pandas as pd import numpy as np import joblib from huggingface_hub import hf_hub_download import os # --- Constants --- HF_MODEL_REPO_ID = "Narendranh/Narendran_PredictiveMaintenance-XGBoost-Model" HF_MODEL_FILENAME = "xgboost_model.pkl" INPUT_COLUMNS = [ 'Engine_RPM', 'Lub_Oil_Pressure', 'Fuel_Pressure', 'Coolant_Pressure', 'Lub_Oil_Temperature', 'Coolant_Temperature' ] # --- Function to Load Model from Hugging Face --- # Use an aggressive layout (wide mode) and custom styling st.set_page_config( page_title="Predictive App", layout="wide", initial_sidebar_state="expanded" ) # Custom CSS for a cleaner, modern look st.markdown(""" """, unsafe_allow_html=True) @st.cache_resource def load_model(): """Downloads the model artifact from the Hugging Face Hub and loads it.""" try: model_path = hf_hub_download( repo_id=HF_MODEL_REPO_ID, filename=HF_MODEL_FILENAME, repo_type="model", local_dir=".", local_dir_use_symlinks=False ) # st.success(f"Model '{HF_MODEL_FILENAME}' successfully loaded from {HF_MODEL_REPO_ID}!", icon="📦") # Suppress this successful message after the app is styled model = joblib.load(model_path) return model except Exception as e: st.error(f"Error loading model from Hugging Face Hub: {e}", icon="⚠️") st.stop() # --- Streamlit Application Layout --- st.title("⚙️ Predictive Engine Maintenance Dashboard") st.markdown("### Forecast potential engine failures using real-time sensor data.") # Load the trained model model = load_model() if model is not None: # --- Input Form for Sensor Readings --- st.markdown("---") st.header("Input Sensor Readings") # Dictionary to hold the user inputs input_data = {} # Define the input columns in a three-column layout col1, col2, col3 = st.columns(3) # Column 1: Speed and Pressure 1 with col1: st.markdown("#### Engine Speed") # Engine_RPM: Range from EDA was approx 61 to 2239 input_data['Engine_RPM'] = st.number_input( "RPM (Revolutions per Minute)", min_value=60, max_value=2500, value=790, step=10, key="rpm_input", help="Typical operating speed is 750-850 RPM." ) st.markdown("#### Oil & Fuel Pressures") # Lub_Oil_Pressure: Range was approx 0.003 to 7.26 input_data['Lub_Oil_Pressure'] = st.number_input( "Lub Oil Pressure (bar)", min_value=0.0, max_value=8.0, value=3.30, step=0.1, format="%.2f", key="oil_pressure_input", help="Pressure of the lubricating oil system." ) # Column 2: Pressures 2 with col2: st.markdown("#### Fuel & Coolant Pressures") # Fuel_Pressure: Range was approx 0.003 to 21.13 input_data['Fuel_Pressure'] = st.number_input( "Fuel Pressure (bar)", min_value=0.0, max_value=25.0, value=6.60, step=0.1, format="%.2f", key="fuel_pressure_input", help="Pressure applied to deliver fuel to the engine." ) # Coolant_Pressure: Range was approx 0.002 to 7.47 input_data['Coolant_Pressure'] = st.number_input( "Coolant Pressure (bar)", min_value=0.0, max_value=8.0, value=2.30, step=0.1, format="%.2f", key="coolant_pressure_input", help="Pressure within the engine cooling system." ) # Column 3: Temperatures with col3: st.markdown("#### Temperatures (°C)") # Lub_Oil_Temperature: Range was approx 71 to 89 input_data['Lub_Oil_Temperature'] = st.number_input( "Lub Oil Temperature (°C)", min_value=70.0, max_value=100.0, value=78.0, step=0.1, format="%.2f", key="oil_temp_input", help="Temperature of the circulating lubricating oil." ) # Coolant_Temperature: Range was approx 71 to 102 input_data['Coolant_Temperature'] = st.number_input( "Coolant Temperature (°C)", min_value=70.0, max_value=110.0, value=78.0, step=0.1, format="%.2f", key="coolant_temp_input", help="Temperature of the engine coolant." ) st.markdown("---") # --- Prediction Logic --- col_pred_btn, col_spacer = st.columns([1, 4]) with col_pred_btn: if st.button("Predict Engine Condition", type="primary", use_container_width=True): # 1. Get the inputs and save them into a dataframe input_df = pd.DataFrame([input_data]) # 2. Ensure the order of columns matches the training data (CRITICAL) input_df = input_df[INPUT_COLUMNS] # 3. Make Prediction try: # Predict probability for both classes (0 and 1) prediction_proba = model.predict_proba(input_df)[0] # Prediction is the class index (0 or 1) prediction = model.predict(input_df)[0] # 4. Display Result st.session_state['prediction'] = prediction st.session_state['proba_success'] = prediction_proba[0]*100 st.session_state['proba_failure'] = prediction_proba[1]*100 st.session_state['input_df'] = input_df except Exception as e: st.error(f"An error occurred during prediction. Full error: {e}") # --- Display Result Section --- st.markdown("
", unsafe_allow_html=True) st.header("Analysis & Status") if 'prediction' in st.session_state: prediction = st.session_state['prediction'] proba_success = st.session_state['proba_success'] proba_failure = st.session_state['proba_failure'] input_df = st.session_state['input_df'] # Use a container for a clean result card result_container = st.container() if prediction == 1: with result_container: st.markdown('
', unsafe_allow_html=True) st.markdown("## 🚨 FAULT PREDICTED - ACTION REQUIRED") col_status, col_details = st.columns([1, 2]) with col_status: st.metric(label="Risk of Failure", value=f"{proba_failure:.2f}%", delta="High Risk", delta_color="inverse") with col_details: st.warning("Immediate inspection and preventive maintenance are **strongly recommended** to avoid unexpected breakdown, costly repairs, and operational downtime.", icon="🛠️") st.markdown('
', unsafe_allow_html=True) else: with result_container: st.markdown('
', unsafe_allow_html=True) st.markdown("## ✅ NORMAL OPERATION - ALL CLEAR") col_status, col_details = st.columns([1, 2]) with col_status: st.metric(label="Confidence in Normalcy", value=f"{proba_success:.2f}%", delta="Low Risk", delta_color="normal") with col_details: st.info("The engine is operating within normal parameters. Continue with scheduled monitoring and maintenance protocol.", icon="👍") st.markdown('
', unsafe_allow_html=True) # Show the data that was fed to the model in an expander with st.expander("View Sensor Data Used for Prediction"): st.dataframe(input_df, hide_index=True, use_container_width=True) else: st.info("Click the 'Predict Engine Condition' button above to run the analysis.") else: st.warning("Cannot proceed without a successfully loaded model. Please ensure the model exists in the Hugging Face repo.")