import streamlit as st import json import folium from streamlit_folium import folium_static, st_folium import pandas as pd import plotly.express as px import plotly.graph_objects as go import os from constants import zone_colors, ALL_ZONES # Set page title st.set_page_config(layout="wide") st.title("🌧️ Storm Water Drain Dashboard - Hyderabad") fSWDDetails = {} all_zones = [] # Load SWD details from JSON file file_path = "SWD_Details_Working.json" json_path = os.path.join(os.path.dirname(__file__), file_path) if os.path.exists(json_path): # st.success(f"Found file: {json_path}") with open(json_path, "r") as file: fSWDDetails = json.load(file) # st.write("Loaded JSON:") # st.json(fSWDDetails) else: st.error(f"File not found: {file_path}") def get_all_zones(): """Extract unique zones from SWD details.""" global all_zones if len(all_zones) == 0: # Step 1: Extract all zones for item in fSWDDetails: if item['Zone'] not in all_zones: all_zones.append(item['Zone']) all_zones.append("All Zones") all_zones.sort() return all_zones get_all_zones() selected_zone = st.sidebar.radio("Filter by Zone", options=all_zones) # avg_lat, avg_lon = 17.3850, 78.4867 # Default to Hyderabad center avg_lat, avg_lon = 17.4250, 78.5567 # Default to Hyderabad center zoom_level = 11.5 # Default zoom level # Step 3: Filter data filtered_data = fSWDDetails if selected_zone != ALL_ZONES: filtered_data = [item for item in fSWDDetails if item['Zone'] == selected_zone] zoom_level = 13 # Zoom in closer for specific zone avg_lat = sum(item['Latitude'] for item in filtered_data) / len(filtered_data) + 0.005 avg_lon = sum(item['Longitude'] for item in filtered_data) / len(filtered_data) + 0.035 selected_pit_id = st.sidebar.selectbox("Select Pit ID to View Details", ["None"] + [item['Id'] for item in filtered_data]) # Set layout with columns col1, col2 = st.columns([2, 1]) # Map on left (wider), details on right selected_pit = next((item for item in filtered_data if item['Id'] == selected_pit_id), None) if selected_pit: st.sidebar.write(f"Selected Pit: {selected_pit['Id']}") st.sidebar.write(f"Zone: {selected_pit['Zone']}") info = selected_pit['Details']['info'] with col1: st.header("Storm Water Pit Map") if selected_pit: zoom_level = 15 avg_lat = selected_pit['Latitude'] avg_lon = selected_pit['Longitude'] hydMap = folium.Map(location=[avg_lat, avg_lon], zoom_start=zoom_level) # Marker + Circle Highlight # Add SWD entries to the map for _, item in enumerate(filtered_data): color = zone_colors.get(item["Zone"], "gray") # default to gray if zone not found popup_info = f""" {item['Id']}
{item['Address']['Area']}
""" folium.Marker( [item['Latitude'], item['Longitude']], popup=popup_info, tooltip=popup_info, icon=folium.Icon(color=color, icon='info-sign') ).add_to(hydMap) if selected_pit: zoom_level = 15 folium.CircleMarker( location=[selected_pit["Latitude"], selected_pit["Longitude"]], radius=25, color='orange', fill=True, fill_color='yellow', fill_opacity=0.7, weight=3 ).add_to(hydMap) st_data = st_folium(hydMap, width=1500, height=600) with col2: if selected_pit is not None: st.header(f"Pit - {selected_pit['Id']}") address = selected_pit['Address'] address_str = address['Street'] + "\n" + address['Area'] + "\n" + address['Pin'] subcol1, subcol2 = st.columns(2) with subcol1: info = selected_pit["Details"]["info"] st.text_input("Debris Level", info['DebrisPitLevel'], disabled=True) st.text_input("Last Cleaned", info['LastCleaned'], disabled=True) st.text_input("Next Cleaning", info['NextScheduledCleaning'], disabled=True) st.text_input("Maintenance", info['MaintenanceStatus'], disabled=True) st.text_area("Address", address_str, height=110, disabled=True) with subcol2: st.text_input("Compression Enabled", info['CompressionEnabled'], disabled=True) latcol1, longcol2 = st.columns(2) with latcol1: st.text_input("Latitude", selected_pit['Latitude'], disabled=True) with longcol2: st.text_input("Longitude", selected_pit['Longitude'], disabled=True) st.text_input("Size", info['Size'], disabled=True) st.text_input("Phone", selected_pit['Phone'], disabled=True) st.text_area("Notes", info['Notes'], height=110, disabled=True) st.slider("Compression Distance", min_value=3, max_value=12, value=5, step=1) btnCol1, btnCol2 = st.columns(2) with btnCol1: st.button("Change Level", disabled=False, help="Coming Soon!", type="primary") with btnCol2: st.button("Raise Request", disabled=False, help="Coming Soon!", type="primary") # Sample data # if st.button("Show Storm Water Pit Level Trend"): if selected_pit and st.checkbox("Show Debris Level Chart"): st.subheader("Storm Water Pit Level Trend") debris_levels = selected_pit.get("Details", {}).get("DebrisLevels", []) if not debris_levels: st.warning("No debris level data available for this pit.") st.stop() # data = [ # {"Timestamp": "2025-10-01T10:00:00Z", "Level": 0.5, "Status": "Normal"}, # {"Timestamp": "2025-10-02T10:00:00Z", "Level": 0.6, "Status": "Normal"}, # {"Timestamp": "2025-10-03T10:00:00Z", "Level": 0.7, "Status": "High"}, # {"Timestamp": "2025-10-04T10:00:00Z", "Level": 0.8, "Status": "Critical"}, # {"Timestamp": "2025-10-05T10:00:00Z", "Level": 0.9, "Status": "Critical"}, # {"Timestamp": "2025-10-06T10:00:00Z", "Level": 0.95, "Status": "High"}, # {"Timestamp": "2025-10-07T10:00:00Z", "Level": 1.0, "Status": "Critical"}, # {"Timestamp": "2025-10-08T10:00:00Z", "Level": 1.0, "Status": "Critical"}, # {"Timestamp": "2025-10-09T10:00:00Z", "Level": 0.85, "Status": "High"}, # {"Timestamp": "2025-10-10T10:00:00Z", "Level": 0.2, "Status": "Normal"} # ] # Convert to DataFrame df = pd.DataFrame(debris_levels) df["Timestamp"] = pd.to_datetime(df["Timestamp"]) df["DateLabel"] = df["Timestamp"].dt.strftime("%b %d") # e.g., 'Oct 01' # Optional: Define color map for status status_color_map = { "Normal": "green", "High": "orange", "Critical": "red" } df["Color"] = df["Status"].map(status_color_map) # Calculate average level avg_level = df["Level"].mean() fig = go.Figure() # Plotly Bar Chart fig = go.Figure() fig.add_trace(go.Bar( x=df["DateLabel"], y=df["Level"], marker_color=df["Color"], text=df["Status"], textposition="outside" )) # Add average line fig.add_hline( y=avg_level, line_dash="dash", line_color="blue", annotation_text=f"Average: {avg_level:.2f}", annotation_position="top left" ) fig.update_layout( title="Storm Water Pit Level Trend", xaxis_title="Date", yaxis_title="Level (m)", yaxis_range=[0, 1.2], xaxis_tickangle=-30, height=500 ) # Display in Streamlit st.plotly_chart(fig, use_container_width=True)