Spaces:
Sleeping
Sleeping
| #this is the app.py file created for Hugging Face. If this causes problems, revert to app_local.py - which works fine | |
| import streamlit as st | |
| import uuid | |
| # --- 1. CONFIG MUST BE FIRST (CRITICAL FIX) --- | |
| st.set_page_config( | |
| page_title="Piranaware", | |
| layout="wide", | |
| page_icon="🛥️" | |
| ) | |
| import os | |
| from src.processing import train_mode_cloud, predict_health_cloud | |
| # --- 2. CSS STYLING (THEME) --- | |
| st.markdown(""" | |
| <style> | |
| /* Main Background - Pure black */ | |
| .stApp { | |
| background-color: #000000; | |
| } | |
| /* Text Color - Safety Yellow */ | |
| .stApp, .stMarkdown, p, label, h1, h2, h3, h4, h5, h6, .stTextInput > label { | |
| color: #FFD700 !important; | |
| } | |
| /* Input Fields (Text Input, etc) - Dark Grey Background */ | |
| .stTextInput > div > div > input { | |
| color: #FFD700; | |
| background-color: #111111; | |
| } | |
| /* Buttons - Black & Yellow */ | |
| div.stButton > button { | |
| background-color: #000000; | |
| color: #FFD700; | |
| border: 2px solid #FFD700; | |
| border-radius: 8px; | |
| font-weight: bold; | |
| } | |
| div.stButton > button:hover { | |
| background-color: #FFD700; | |
| color: #000000; | |
| border: 2px solid #FFD700; | |
| } | |
| /* Tabs */ | |
| button[data-baseweb="tab"] { | |
| color: #BDB76B !important; | |
| } | |
| button[data-baseweb="tab"][aria-selected="true"] { | |
| color: #FFD700 !important; | |
| border-bottom: 4px solid #FFD700 !important; | |
| } | |
| /* Result Boxes */ | |
| .result-box-healthy { | |
| background-color: #111111; | |
| border: 2px solid #00FF9C; | |
| border-left: 6px solid #00C781; | |
| padding: 15px; border-radius: 5px; | |
| color: #00FF9C; | |
| } | |
| .result-box-anomaly { | |
| background-color: #111111; | |
| border: 2px solid #FF5252; | |
| border-left: 6px solid #D32F2F; | |
| padding: 15px; border-radius: 5px; | |
| color: #FF5252; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # --- 3. LINUX TEMP PATH SETUP --- | |
| TEMP_AUDIO_PATH = "/tmp/input.wav" | |
| def save_audio(audio_value): | |
| """ | |
| Saves audio with a UNIQUE filename to prevent file locking errors. | |
| """ | |
| if audio_value is None: | |
| return None | |
| # Generate a random, unique name (e.g., "audio_4f9a2c.wav") | |
| unique_filename = f"audio_{uuid.uuid4().hex}.wav" | |
| save_path = os.path.join("/tmp", unique_filename) | |
| # Reset pointer and write | |
| audio_value.seek(0) | |
| with open(save_path, "wb") as f: | |
| f.write(audio_value.read()) | |
| return save_path | |
| # --- 4. SIDEBAR --- | |
| with st.sidebar: | |
| st.title("User Login") | |
| st.markdown("### Ensure to use your exact boat ID") | |
| boat_id = st.text_input("Enter Boat ID", value="DEMO_BOAT_01").upper().replace(" ", "_") | |
| st.caption("Training saved online on Google Cloud.") | |
| st.divider() | |
| st.info(f"Active Session:\n**{boat_id}**") | |
| # --- 5. MAIN APP --- | |
| st.title("Piranaware Boat Engine AI") | |
| tab_train, tab_test = st.tabs(["🛠️ Train Baseline", "🩺 Diagnostics"]) | |
| # --- TAB 1: TRAIN --- | |
| with tab_train: | |
| st.info(f"Training models for: **{boat_id}**. Ensure engine is HEALTHY.") | |
| c1, c2, c3 = st.columns(3) | |
| for col, mode in [(c1, "idle"), (c2, "slow"), (c3, "fast")]: | |
| with col: | |
| st.markdown(f"### {mode.upper()}") | |
| # Try/Except handles older Streamlit versions that lack st.audio_input | |
| try: | |
| audio = st.audio_input(f"Rec {mode}", key=f"rec_{mode}") | |
| except AttributeError: | |
| audio = st.file_uploader(f"Up {mode}", type=['wav'], key=f"rec_{mode}") | |
| if st.button(f"Train {mode.upper()}", key=f"btn_{mode}"): | |
| if audio: | |
| path = save_audio(audio) | |
| with st.spinner("Training & Uploading to Cloud..."): | |
| res = train_mode_cloud(path, mode, boat_id) | |
| st.success(res) | |
| else: | |
| st.error("No Audio") | |
| # --- TAB 2: DIAGNOSTICS --- | |
| with tab_test: | |
| st.divider() | |
| st.markdown(f"### Diagnostics for: **{boat_id}**") | |
| col_in, col_out = st.columns([1, 2]) | |
| with col_in: | |
| mode = st.selectbox("Select Mode", ["idle", "slow", "fast"]) | |
| try: | |
| test_audio = st.audio_input("Record", key="test") | |
| except AttributeError: | |
| test_audio = st.file_uploader("Upload", type=['wav'], key="test") | |
| btn = st.button("Run Diagnostics") | |
| with col_out: | |
| if btn and test_audio: | |
| path = save_audio(test_audio) | |
| with st.spinner("Downloading Model & Analyzing..."): | |
| report = predict_health_cloud(path, mode, boat_id) | |
| if "HEALTHY" in report: | |
| st.markdown(f'<div class="result-box-healthy">{report}</div>', unsafe_allow_html=True) | |
| elif "ANOMALY" in report: | |
| st.markdown(f'<div class="result-box-anomaly">{report}</div>', unsafe_allow_html=True) | |
| else: | |
| st.warning(report) |