Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import numpy as np | |
| import joblib | |
| # Page configuration | |
| st.set_page_config( | |
| page_title="HDD Predictor", | |
| page_icon="π§", | |
| layout="centered", | |
| initial_sidebar_state="collapsed" | |
| ) | |
| # Ultra-minimal Canva-style CSS | |
| st.markdown(""" | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap'); | |
| /* Hide Streamlit elements */ | |
| #MainMenu {visibility: hidden;} | |
| footer {visibility: hidden;} | |
| header {visibility: hidden;} | |
| .stDeployButton {visibility: hidden;} | |
| /* Main background */ | |
| .main { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| min-height: 100vh; | |
| padding: 1rem 0; | |
| } | |
| /* Container */ | |
| .container { | |
| background: white; | |
| border-radius: 25px; | |
| padding: 2rem 1.5rem; | |
| margin: 1rem auto; | |
| max-width: 400px; | |
| box-shadow: 0 25px 50px rgba(0,0,0,0.15); | |
| text-align: center; | |
| } | |
| /* Typography */ | |
| .title { | |
| font-family: 'Poppins', sans-serif; | |
| font-size: 1.8rem; | |
| font-weight: 700; | |
| color: #2d3748; | |
| margin-bottom: 0.5rem; | |
| } | |
| .subtitle { | |
| font-family: 'Poppins', sans-serif; | |
| font-size: 0.9rem; | |
| color: #718096; | |
| margin-bottom: 2rem; | |
| font-weight: 400; | |
| } | |
| /* Inputs */ | |
| .stSelectbox label, .stSlider label { | |
| font-family: 'Poppins', sans-serif; | |
| font-weight: 600; | |
| color: #4a5568; | |
| font-size: 0.95rem; | |
| } | |
| .stSelectbox > div > div { | |
| border-radius: 15px; | |
| border: 2px solid #e2e8f0; | |
| font-family: 'Poppins', sans-serif; | |
| } | |
| .stSlider > div > div { | |
| border-radius: 15px; | |
| padding: 1rem; | |
| background: #f7fafc; | |
| } | |
| /* Button */ | |
| .stButton > button { | |
| background: linear-gradient(135deg, #667eea, #764ba2); | |
| color: white; | |
| border: none; | |
| border-radius: 20px; | |
| padding: 1rem 2rem; | |
| font-family: 'Poppins', sans-serif; | |
| font-weight: 600; | |
| font-size: 1rem; | |
| width: 100%; | |
| margin: 1.5rem 0; | |
| box-shadow: 0 10px 25px rgba(102, 126, 234, 0.3); | |
| transition: all 0.3s ease; | |
| } | |
| .stButton > button:hover { | |
| transform: translateY(-3px); | |
| box-shadow: 0 15px 35px rgba(102, 126, 234, 0.4); | |
| } | |
| /* Result */ | |
| .result { | |
| margin: 2rem 0; | |
| padding: 2rem; | |
| border-radius: 20px; | |
| text-align: center; | |
| } | |
| .solution-icon { | |
| font-size: 4rem; | |
| margin-bottom: 1rem; | |
| display: block; | |
| } | |
| .solution-title { | |
| font-family: 'Poppins', sans-serif; | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| color: white; | |
| margin-bottom: 0.5rem; | |
| } | |
| .solution-desc { | |
| font-family: 'Poppins', sans-serif; | |
| font-size: 1rem; | |
| color: rgba(255,255,255,0.9); | |
| font-weight: 400; | |
| } | |
| /* Solution colors */ | |
| .sol-a { background: linear-gradient(135deg, #48bb78, #38a169); } | |
| .sol-b { background: linear-gradient(135deg, #ed8936, #dd6b20); } | |
| .sol-c { background: linear-gradient(135deg, #ed64a6, #d53f8c); } | |
| .sol-d { background: linear-gradient(135deg, #9f7aea, #805ad5); } | |
| .sol-e { background: linear-gradient(135deg, #68d391, #48bb78); } | |
| /* Mobile logo styling */ | |
| .mobile-logo { | |
| text-align: center; | |
| margin-bottom: 1rem; | |
| padding: 0.5rem; | |
| background: rgba(255,255,255,0.1); | |
| border-radius: 15px; | |
| backdrop-filter: blur(10px); | |
| } | |
| .mobile-logo img { | |
| filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1)); | |
| margin: 0 0.5rem; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Load model | |
| def load_model(): | |
| try: | |
| model = joblib.load('decision_tree_model.pkl') | |
| le_soil = joblib.load('dt_soil_encoder.pkl') | |
| le_water = joblib.load('dt_water_encoder.pkl') | |
| le_solution = joblib.load('dt_solution_encoder.pkl') | |
| return model, le_soil, le_water, le_solution | |
| except FileNotFoundError: | |
| st.error("Model files not found!") | |
| return None, None, None, None | |
| def predict_solution(diameter, soil_type, high_water, model, le_soil, le_water, le_solution): | |
| try: | |
| soil_encoded = le_soil.transform([soil_type])[0] | |
| water_encoded = le_water.transform([high_water])[0] | |
| features = np.array([[diameter, soil_encoded, water_encoded]]) | |
| prediction_encoded = model.predict(features)[0] | |
| prediction = le_solution.inverse_transform([prediction_encoded])[0] | |
| return prediction | |
| except Exception as e: | |
| return f"Error: {str(e)}" | |
| def main(): | |
| # Logo section | |
| st.markdown('<div class="mobile-logo">', unsafe_allow_html=True) | |
| try: | |
| # Center the single MEA logo | |
| st.image('logo2.e8c5ff97.png', width=100) | |
| except FileNotFoundError: | |
| st.markdown(""" | |
| <div style="text-align: center; color: rgba(255,255,255,0.7); font-size: 0.8rem;"> | |
| π MEA Logo not found | |
| </div> | |
| """, unsafe_allow_html=True) | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| # Container start | |
| st.markdown('<div class="container">', unsafe_allow_html=True) | |
| # Header | |
| st.markdown('<div class="title">π§ HDD Predictor</div>', unsafe_allow_html=True) | |
| st.markdown('<div class="subtitle">Quick drilling solution recommendation</div>', unsafe_allow_html=True) | |
| # Load model | |
| model_data = load_model() | |
| if model_data[0] is None: | |
| st.stop() | |
| model, le_soil, le_water, le_solution = model_data | |
| # Inputs | |
| diameter = st.slider("Diameter (m)", 0.5, 2.0, 1.2, 0.1) | |
| soil_type = st.selectbox("Soil", ['clay', 'sand']) | |
| high_water = st.selectbox("High Water", ['no', 'yes']) | |
| # Predict | |
| if st.button("Get Solution"): | |
| prediction = predict_solution(diameter, soil_type, high_water, model, le_soil, le_water, le_solution) | |
| solutions = { | |
| 'A': {'icon': 'π‘οΈ', 'title': 'Enhanced Protection', 'desc': 'Sheetpile + Trench + Grouting', 'class': 'sol-a'}, | |
| 'B': {'icon': 'π°', 'title': 'Maximum Protection', 'desc': 'Full System + Casing', 'class': 'sol-b'}, | |
| 'C': {'icon': 'π¨', 'title': 'Moderate Protection', 'desc': 'Sheetpile + Trench', 'class': 'sol-c'}, | |
| 'D': {'icon': 'π§', 'title': 'Basic Protection', 'desc': 'Grouting Only', 'class': 'sol-d'}, | |
| 'E': {'icon': 'β ', 'title': 'Minimal Action', 'desc': 'No Additional Measures', 'class': 'sol-e'} | |
| } | |
| if prediction in solutions: | |
| sol = solutions[prediction] | |
| st.markdown(f''' | |
| <div class="result {sol['class']}"> | |
| <div class="solution-icon">{sol['icon']}</div> | |
| <div class="solution-title">Solution {prediction}</div> | |
| <div class="solution-title">{sol['title']}</div> | |
| <div class="solution-desc">{sol['desc']}</div> | |
| </div> | |
| ''', unsafe_allow_html=True) | |
| # Container end | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| if __name__ == "__main__": | |
| main() |