Update app.py
Browse files
app.py
CHANGED
|
@@ -0,0 +1,196 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# app.py
|
| 2 |
+
|
| 3 |
+
import streamlit as st
|
| 4 |
+
import pandas as pd
|
| 5 |
+
import numpy as np
|
| 6 |
+
|
| 7 |
+
# Set page title and layout
|
| 8 |
+
st.set_page_config(page_title="Water System Analysis", layout="centered")
|
| 9 |
+
st.title("Water Network Leak, Surge, and Gas Flow Analyzer")
|
| 10 |
+
|
| 11 |
+
# Allow user to upload an Excel or CSV file
|
| 12 |
+
uploaded_file = st.file_uploader("Upload Excel or CSV File", type=["xlsx", "csv"])
|
| 13 |
+
|
| 14 |
+
if uploaded_file:
|
| 15 |
+
try:
|
| 16 |
+
# Read the uploaded file into a pandas DataFrame
|
| 17 |
+
if uploaded_file.name.endswith('.xlsx'):
|
| 18 |
+
df = pd.read_excel(uploaded_file)
|
| 19 |
+
else:
|
| 20 |
+
df = pd.read_csv(uploaded_file)
|
| 21 |
+
st.success("Data loaded successfully!")
|
| 22 |
+
except Exception as e:
|
| 23 |
+
st.error(f"Error reading the file: {e}")
|
| 24 |
+
st.stop()
|
| 25 |
+
|
| 26 |
+
# Detect if a "Serial Number" column exists (case-insensitive)
|
| 27 |
+
serial_col = None
|
| 28 |
+
for col in df.columns:
|
| 29 |
+
if col.strip().lower().startswith("serial"):
|
| 30 |
+
serial_col = col
|
| 31 |
+
break
|
| 32 |
+
|
| 33 |
+
# If serial number column is found, let user select one
|
| 34 |
+
if serial_col:
|
| 35 |
+
serial_list = df[serial_col].unique().tolist()
|
| 36 |
+
selected_serial = st.selectbox(f"Select {serial_col}", serial_list)
|
| 37 |
+
df_filtered = df[df[serial_col] == selected_serial]
|
| 38 |
+
if df_filtered.empty:
|
| 39 |
+
st.warning("No data found for the selected serial number.")
|
| 40 |
+
st.stop()
|
| 41 |
+
else:
|
| 42 |
+
# If no serial number column, use the entire dataset
|
| 43 |
+
df_filtered = df
|
| 44 |
+
selected_serial = None
|
| 45 |
+
|
| 46 |
+
# Let the user select which parameter (column) to analyze
|
| 47 |
+
# Exclude the serial column itself from selection
|
| 48 |
+
columns = [col for col in df_filtered.columns if col != serial_col]
|
| 49 |
+
selected_column = st.selectbox("Select a parameter to analyze", columns)
|
| 50 |
+
|
| 51 |
+
if selected_column:
|
| 52 |
+
# Retrieve the value(s) for the selected parameter
|
| 53 |
+
# If only one row is present, get the scalar; otherwise get list of values
|
| 54 |
+
if len(df_filtered) == 1:
|
| 55 |
+
value = df_filtered[selected_column].iloc[0]
|
| 56 |
+
else:
|
| 57 |
+
value = df_filtered[selected_column].tolist()
|
| 58 |
+
rec = "" # This will hold the recommendation string
|
| 59 |
+
|
| 60 |
+
# Leak detection (Water Pressure)
|
| 61 |
+
if "water pressure" in selected_column.lower():
|
| 62 |
+
# Compute mean pressure if multiple readings, else use the single value
|
| 63 |
+
if isinstance(value, list):
|
| 64 |
+
mean_val = np.mean(value)
|
| 65 |
+
else:
|
| 66 |
+
mean_val = value
|
| 67 |
+
# Apply simple threshold rules
|
| 68 |
+
if mean_val < 20:
|
| 69 |
+
rec = ("π¨ **Alert:** The water pressure is significantly low. "
|
| 70 |
+
"This suggests a strong likelihood of a leak or supply issue. "
|
| 71 |
+
"Inspect the pipeline and valves immediately. ")
|
| 72 |
+
elif mean_val < 40:
|
| 73 |
+
rec = ("β οΈ The water pressure is on the lower side. "
|
| 74 |
+
"There may be a leak or high demand. "
|
| 75 |
+
"Monitor the system closely and check for any anomalies. ")
|
| 76 |
+
elif mean_val > 80:
|
| 77 |
+
rec = ("β οΈ The water pressure is very high. "
|
| 78 |
+
"Ensure the pressure-regulating devices are functioning. "
|
| 79 |
+
"High pressure can stress the pipes. ")
|
| 80 |
+
else:
|
| 81 |
+
rec = ("β
The water pressure is within normal range. "
|
| 82 |
+
"No immediate issues detected for leaks based on pressure. ")
|
| 83 |
+
|
| 84 |
+
# Surge detection (Transient Pressure)
|
| 85 |
+
elif "transient pressure" in selected_column.lower():
|
| 86 |
+
# Use the highest transient pressure to check for spikes
|
| 87 |
+
if isinstance(value, list):
|
| 88 |
+
peak_val = np.max(value)
|
| 89 |
+
else:
|
| 90 |
+
peak_val = value
|
| 91 |
+
if peak_val > 60:
|
| 92 |
+
rec = ("π¨ **Alert:** Detected a high transient pressure (pressure surge). "
|
| 93 |
+
"This could indicate water hammer or sudden valve closure. "
|
| 94 |
+
"Check surge protection devices and ensure valves operate smoothly. ")
|
| 95 |
+
else:
|
| 96 |
+
rec = ("β
Transient pressure levels are within a safe range. "
|
| 97 |
+
"No significant pressure surges detected. ")
|
| 98 |
+
|
| 99 |
+
# Gas flow analysis
|
| 100 |
+
elif "gas flow" in selected_column.lower():
|
| 101 |
+
if isinstance(value, list):
|
| 102 |
+
mean_flow = np.mean(value)
|
| 103 |
+
else:
|
| 104 |
+
mean_flow = value
|
| 105 |
+
if mean_flow > 150:
|
| 106 |
+
rec = ("β οΈ Gas flow rate is high. "
|
| 107 |
+
"This could indicate heavy usage or a potential leak. "
|
| 108 |
+
"Check the gas lines and usage patterns. ")
|
| 109 |
+
elif mean_flow < 50:
|
| 110 |
+
rec = ("β οΈ Gas flow rate is very low. "
|
| 111 |
+
"Ensure that valves are open or that the demand is correct. "
|
| 112 |
+
"No gas might indicate a supply issue. ")
|
| 113 |
+
else:
|
| 114 |
+
rec = ("β
Gas flow rate is within normal operating range. "
|
| 115 |
+
"No obvious anomalies detected in gas flow. ")
|
| 116 |
+
|
| 117 |
+
# Network Design Type advice
|
| 118 |
+
elif "network design" in selected_column.lower():
|
| 119 |
+
design = str(df_filtered[selected_column].iloc[0]).strip().lower()
|
| 120 |
+
if "grid" in design:
|
| 121 |
+
rec = ("β
A grid network provides redundancy and reliability. "
|
| 122 |
+
"Ensure maintenance of all loops for continuous supply. ")
|
| 123 |
+
elif "radial" in design:
|
| 124 |
+
rec = ("β οΈ A radial network is simpler but has less redundancy. "
|
| 125 |
+
"A failure in a main line may isolate downstream areas. "
|
| 126 |
+
"Consider backup routes if possible. ")
|
| 127 |
+
elif "ring" in design or "loop" in design:
|
| 128 |
+
rec = ("β
A ring (loop) network allows for good circulation and redundancy. "
|
| 129 |
+
"Keep valves balanced to maintain pressure. ")
|
| 130 |
+
else:
|
| 131 |
+
rec = ("β
The network design type is noted. "
|
| 132 |
+
"Regular inspection ensures reliability. ")
|
| 133 |
+
|
| 134 |
+
# Population Density advice
|
| 135 |
+
elif "population density" in selected_column.lower():
|
| 136 |
+
val = df_filtered[selected_column].iloc[0]
|
| 137 |
+
if val > 1500:
|
| 138 |
+
rec = ("β οΈ High population density indicates heavy demand on the water network. "
|
| 139 |
+
"Ensure the infrastructure is scaled properly to serve the community. "
|
| 140 |
+
"Consider capacity upgrades or demand management programs. ")
|
| 141 |
+
elif val > 800:
|
| 142 |
+
rec = ("β
Population density is moderate. "
|
| 143 |
+
"Maintain regular monitoring to meet demand and plan for growth. ")
|
| 144 |
+
else:
|
| 145 |
+
rec = ("β
Low population density suggests light demand. "
|
| 146 |
+
"Focus on efficient resource allocation and cost-effective maintenance. ")
|
| 147 |
+
|
| 148 |
+
# Average Water Usage advice
|
| 149 |
+
elif "water usage" in selected_column.lower():
|
| 150 |
+
val = df_filtered[selected_column].iloc[0]
|
| 151 |
+
if val > 200:
|
| 152 |
+
rec = ("β οΈ Very high per-capita water usage detected. "
|
| 153 |
+
"Promote water conservation measures and check for leaks in consumption systems. ")
|
| 154 |
+
elif val > 120:
|
| 155 |
+
rec = ("β
Average water usage is within a moderate range. "
|
| 156 |
+
"Continue to encourage efficient use of water. ")
|
| 157 |
+
else:
|
| 158 |
+
rec = ("β
Water usage per person is low. "
|
| 159 |
+
"This is efficient, but ensure basic needs are met. ")
|
| 160 |
+
|
| 161 |
+
# Available Water Resources advice
|
| 162 |
+
elif "available water" in selected_column.lower():
|
| 163 |
+
val = df_filtered[selected_column].iloc[0]
|
| 164 |
+
if val < 80:
|
| 165 |
+
rec = ("β οΈ Limited available water resources. "
|
| 166 |
+
"Implement conservation strategies and consider alternative sources. ")
|
| 167 |
+
elif val > 150:
|
| 168 |
+
rec = ("β
Ample water resources are available. "
|
| 169 |
+
"Still practice sustainable usage to maintain supply levels. ")
|
| 170 |
+
else:
|
| 171 |
+
rec = ("β
Water resource levels are moderate. "
|
| 172 |
+
"Monitor usage rates to avoid shortages. ")
|
| 173 |
+
|
| 174 |
+
# Pipe Sizes advice
|
| 175 |
+
elif "pipe sizes" in selected_column.lower():
|
| 176 |
+
val = df_filtered[selected_column].iloc[0]
|
| 177 |
+
if val < 30:
|
| 178 |
+
rec = ("β οΈ Small pipe diameter detected. "
|
| 179 |
+
"This may limit flow capacity. "
|
| 180 |
+
"Check for potential bottlenecks in the network. ")
|
| 181 |
+
elif val > 40:
|
| 182 |
+
rec = ("β
Pipe size is large. "
|
| 183 |
+
"Adequate flow capacity is available. "
|
| 184 |
+
"Ensure regular inspections for longevity. ")
|
| 185 |
+
else:
|
| 186 |
+
rec = ("β
Standard pipe size. "
|
| 187 |
+
"Flow capacity is adequate for normal operation. ")
|
| 188 |
+
|
| 189 |
+
else:
|
| 190 |
+
# Default case if the column is unrecognized
|
| 191 |
+
rec = ("β
No specific recommendations for the selected parameter. "
|
| 192 |
+
"Data value is noted and appears within expected range. ")
|
| 193 |
+
|
| 194 |
+
# Display the recommendations
|
| 195 |
+
st.markdown(f"### Recommendations for **{selected_column}**")
|
| 196 |
+
st.write(rec)
|