razaali10 commited on
Commit
565f251
Β·
verified Β·
1 Parent(s): a8cc368

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -128
app.py CHANGED
@@ -5,20 +5,19 @@ import pandas as pd
5
  import tempfile
6
  import zipfile
7
  import os
 
8
 
9
  st.set_page_config(layout="wide")
10
  st.title("🌊 EPANET INP β†’ Simulation β†’ Shapefiles")
11
 
12
  uploaded_file = st.file_uploader("Upload EPANET .inp file", type=["inp"])
13
 
14
-
15
  st.subheader("πŸ“₯ Or Import from Shapefiles")
16
 
17
  node_files = st.file_uploader("Upload all Node Shapefile components (.shp, .shx, .dbf, .prj)", accept_multiple_files=True)
18
  link_files = st.file_uploader("Upload all Link Shapefile components (.shp, .shx, .dbf, .prj)", accept_multiple_files=True)
19
 
20
- imported_node_gdf, imported_link_gdf = None, None
21
-
22
  def extract_shapefile(files, temp_dir, layer_name):
23
  shp_path = None
24
  for file in files:
@@ -33,41 +32,31 @@ def extract_shapefile(files, temp_dir, layer_name):
33
  if node_files and link_files:
34
  try:
35
  temp_shape_dir = tempfile.mkdtemp()
36
-
37
  node_shp_path = extract_shapefile(node_files, temp_shape_dir, "nodes")
38
  link_shp_path = extract_shapefile(link_files, temp_shape_dir, "links")
39
-
40
  node_gdf = gpd.read_file(node_shp_path)
41
  link_gdf = gpd.read_file(link_shp_path)
42
 
43
- wn = wntr.network.WaterNetworkModel() # Create empty model
44
-
45
  for _, row in node_gdf.iterrows():
46
- node_id = str(row['ID'])
47
- elev = float(row['elevation'])
48
- wn.add_junction(node_id, base_demand=0.0, elevation=elev, coordinates=(row.geometry.x, row.geometry.y))
49
-
50
  for _, row in link_gdf.iterrows():
51
- pipe_id = str(row['ID'])
52
- wn.add_pipe(pipe_id,
53
  start_node_name=str(row['Node1']),
54
  end_node_name=str(row['Node2']),
55
  length=float(row['length']),
56
  diameter=float(row['diameter']),
57
  roughness=float(row['roughness']),
58
- minor_loss=0.0,
59
- status='OPEN')
60
-
61
  st.success("Water network built from shapefiles!")
62
 
63
  sim = wntr.sim.WNTRSimulator(wn)
64
  results = sim.run_sim()
65
  st.success("Simulation from shapefile model complete.")
66
-
67
  except Exception as e:
68
  st.error(f"Error loading shapefiles: {e}")
69
 
70
-
71
  if uploaded_file:
72
  temp_dir = tempfile.mkdtemp()
73
  inp_path = os.path.join(temp_dir, uploaded_file.name)
@@ -80,127 +69,21 @@ if uploaded_file:
80
  wn = wntr.network.WaterNetworkModel(inp_path)
81
  sim = wntr.sim.EpanetSimulator(wn)
82
  results = sim.run_sim()
83
-
84
  st.success("Simulation complete.")
85
 
86
-
87
- st.subheader("⚠️ Pipe Criticality Analysis")
88
-
89
- if st.button("Run Criticality Analysis on Large Pipes"):
90
- try:
91
- wn.options.time.duration = 72 * 3600
92
- wn.options.hydraulic.demand_model = 'PDD'
93
- wn.options.hydraulic.required_pressure = 17.57
94
- wn.options.hydraulic.minimum_pressure = 0
95
-
96
- pipes = wn.query_link_attribute('diameter', np.greater_equal, 24 * 0.0254,
97
- link_type=wntr.network.model.Pipe)
98
- pipes = list(pipes.index)
99
-
100
- pressure_threshold = 14.06
101
- sim = wntr.sim.WNTRSimulator(wn)
102
- results = sim.run_sim()
103
- min_pressure = results.node['pressure'].loc[:, wn.junction_name_list].min()
104
- below_threshold_normal_conditions = set(min_pressure[min_pressure < pressure_threshold].index)
105
-
106
- junctions_impacted = {}
107
- for pipe_name in pipes:
108
- wn.reset_initial_values()
109
-
110
- pipe = wn.get_link(pipe_name)
111
- act = wntr.network.controls.ControlAction(pipe, 'status', wntr.network.LinkStatus.Closed)
112
- cond = wntr.network.controls.SimTimeCondition(wn, '=', '24:00:00')
113
- ctrl = wntr.network.controls.Control(cond, act)
114
- wn.add_control('close pipe ' + pipe_name, ctrl)
115
-
116
- try:
117
- sim = wntr.sim.WNTRSimulator(wn)
118
- results = sim.run_sim()
119
- min_pressure = results.node['pressure'].loc[:, wn.junction_name_list].min()
120
- below_threshold = set(min_pressure[min_pressure < pressure_threshold].index)
121
- junctions_impacted[pipe_name] = below_threshold - below_threshold_normal_conditions
122
- except:
123
- junctions_impacted[pipe_name] = set()
124
-
125
- wn.remove_control('close pipe ' + pipe_name)
126
-
127
- number_of_junctions_impacted = {k: len(v) for k, v in junctions_impacted.items()}
128
- st.write("Junctions impacted per pipe:", number_of_junctions_impacted)
129
-
130
- if number_of_junctions_impacted:
131
- worst_pipe = max(number_of_junctions_impacted, key=number_of_junctions_impacted.get)
132
- st.write(f"🚨 Most critical pipe: {worst_pipe} impacts {number_of_junctions_impacted[worst_pipe]} junctions")
133
-
134
- except Exception as e:
135
- st.error(f"Criticality analysis failed: {e}")
136
-
137
- if st.button("Run Criticality Analysis on Large Pipes"):
138
- try:
139
- wn.options.time.duration = 72 * 3600
140
- wn.options.hydraulic.demand_model = 'PDD'
141
- wn.options.hydraulic.required_pressure = 17.57
142
- wn.options.hydraulic.minimum_pressure = 0
143
-
144
- pipes = wn.query_link_attribute('diameter', np.greater_equal, 24 * 0.0254,
145
- link_type=wntr.network.model.Pipe)
146
- pipes = list(pipes.index)
147
-
148
- pressure_threshold = 14.06
149
-
150
- sim = wntr.sim.WNTRSimulator(wn)
151
- results = sim.run_sim()
152
- min_pressure = results.node['pressure'].loc[:, wn.junction_name_list].min()
153
- below_threshold_normal_conditions = set(min_pressure[min_pressure < pressure_threshold].index)
154
-
155
- junctions_impacted = {}
156
- for pipe_name in pipes:
157
- wn.reset_initial_values()
158
-
159
- pipe = wn.get_link(pipe_name)
160
- act = wntr.network.controls.ControlAction(pipe, 'status', wntr.network.LinkStatus.Closed)
161
- cond = wntr.network.controls.SimTimeCondition(wn, '=', '24:00:00')
162
- ctrl = wntr.network.controls.Control(cond, act)
163
- wn.add_control('close pipe ' + pipe_name, ctrl)
164
-
165
- try:
166
- sim = wntr.sim.WNTRSimulator(wn)
167
- results = sim.run_sim()
168
- min_pressure = results.node['pressure'].loc[:, wn.junction_name_list].min()
169
- below_threshold = set(min_pressure[min_pressure < pressure_threshold].index)
170
- junctions_impacted[pipe_name] = below_threshold - below_threshold_normal_conditions
171
- except:
172
- junctions_impacted[pipe_name] = set()
173
-
174
- wn.remove_control('close pipe ' + pipe_name)
175
-
176
- number_of_junctions_impacted = {k: len(v) for k, v in junctions_impacted.items()}
177
- st.write("Junctions impacted per pipe:", number_of_junctions_impacted)
178
-
179
- if number_of_junctions_impacted:
180
- worst_pipe = max(number_of_junctions_impacted, key=number_of_junctions_impacted.get)
181
- st.write(f"🚨 Most critical pipe: {worst_pipe} impacts {number_of_junctions_impacted[worst_pipe]} junctions")
182
-
183
- except Exception as e:
184
- st.error(f"Criticality analysis failed: {e}")
185
-
186
-
187
- # Extract GIS structure
188
  gis = wn.to_gis()
189
  node_gdf = pd.concat([gis.junctions, gis.tanks, gis.reservoirs])
190
  link_gdf = pd.concat([gis.pipes, gis.pumps, gis.valves])
191
 
192
- # Merge average results
193
  node_gdf["pressure"] = results.node["pressure"].mean(axis=0)
194
  node_gdf["demand"] = results.node["demand"].mean(axis=0)
195
 
196
  link_gdf["flow"] = results.link["flowrate"].mean(axis=0)
197
  link_gdf["velocity"] = results.link["velocity"].mean(axis=0)
198
 
199
- # Set geometry
200
  node_gdf = node_gdf.set_geometry("geometry")
201
  link_gdf = link_gdf.set_geometry("geometry")
202
 
203
- # Set CRS if missing
204
  if node_gdf.crs is None:
205
  crs_choice = st.selectbox("Select CRS for shapefiles", ["EPSG:4326", "EPSG:3857", "None"])
206
  if crs_choice != "None":
@@ -209,17 +92,15 @@ if st.button("Run Criticality Analysis on Large Pipes"):
209
  else:
210
  st.warning("No CRS selected β€” export may fail.")
211
 
212
- # Save shapefiles
213
  node_path = os.path.join(temp_dir, "nodes_with_results.shp")
214
  link_path = os.path.join(temp_dir, "links_with_results.shp")
215
  node_gdf.to_file(node_path, driver="ESRI Shapefile")
216
  link_gdf.to_file(link_path, driver="ESRI Shapefile")
217
 
218
- # Zip the shapefiles
219
  zip_path = os.path.join(temp_dir, "simulation_shapefiles.zip")
220
  with zipfile.ZipFile(zip_path, 'w') as zipf:
221
  for f in os.listdir(temp_dir):
222
- if f.endswith(".shp") or f.endswith(".shx") or f.endswith(".dbf") or f.endswith(".prj"):
223
  zipf.write(os.path.join(temp_dir, f), arcname=f)
224
 
225
  with open(zip_path, "rb") as f:
@@ -231,5 +112,54 @@ if st.button("Run Criticality Analysis on Large Pipes"):
231
  st.subheader("πŸ”— Preview of Link Results")
232
  st.dataframe(link_gdf[["flow", "velocity"]].head())
233
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  except Exception as e:
235
- st.error(f"Simulation failed: {e}")
 
5
  import tempfile
6
  import zipfile
7
  import os
8
+ import numpy as np
9
 
10
  st.set_page_config(layout="wide")
11
  st.title("🌊 EPANET INP β†’ Simulation β†’ Shapefiles")
12
 
13
  uploaded_file = st.file_uploader("Upload EPANET .inp file", type=["inp"])
14
 
15
+ # Allow multiple shapefile uploads
16
  st.subheader("πŸ“₯ Or Import from Shapefiles")
17
 
18
  node_files = st.file_uploader("Upload all Node Shapefile components (.shp, .shx, .dbf, .prj)", accept_multiple_files=True)
19
  link_files = st.file_uploader("Upload all Link Shapefile components (.shp, .shx, .dbf, .prj)", accept_multiple_files=True)
20
 
 
 
21
  def extract_shapefile(files, temp_dir, layer_name):
22
  shp_path = None
23
  for file in files:
 
32
  if node_files and link_files:
33
  try:
34
  temp_shape_dir = tempfile.mkdtemp()
 
35
  node_shp_path = extract_shapefile(node_files, temp_shape_dir, "nodes")
36
  link_shp_path = extract_shapefile(link_files, temp_shape_dir, "links")
 
37
  node_gdf = gpd.read_file(node_shp_path)
38
  link_gdf = gpd.read_file(link_shp_path)
39
 
40
+ wn = wntr.network.WaterNetworkModel()
 
41
  for _, row in node_gdf.iterrows():
42
+ wn.add_junction(str(row['ID']), base_demand=0.0, elevation=float(row['elevation']),
43
+ coordinates=(row.geometry.x, row.geometry.y))
 
 
44
  for _, row in link_gdf.iterrows():
45
+ wn.add_pipe(str(row['ID']),
 
46
  start_node_name=str(row['Node1']),
47
  end_node_name=str(row['Node2']),
48
  length=float(row['length']),
49
  diameter=float(row['diameter']),
50
  roughness=float(row['roughness']),
51
+ minor_loss=0.0, status='OPEN')
 
 
52
  st.success("Water network built from shapefiles!")
53
 
54
  sim = wntr.sim.WNTRSimulator(wn)
55
  results = sim.run_sim()
56
  st.success("Simulation from shapefile model complete.")
 
57
  except Exception as e:
58
  st.error(f"Error loading shapefiles: {e}")
59
 
 
60
  if uploaded_file:
61
  temp_dir = tempfile.mkdtemp()
62
  inp_path = os.path.join(temp_dir, uploaded_file.name)
 
69
  wn = wntr.network.WaterNetworkModel(inp_path)
70
  sim = wntr.sim.EpanetSimulator(wn)
71
  results = sim.run_sim()
 
72
  st.success("Simulation complete.")
73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  gis = wn.to_gis()
75
  node_gdf = pd.concat([gis.junctions, gis.tanks, gis.reservoirs])
76
  link_gdf = pd.concat([gis.pipes, gis.pumps, gis.valves])
77
 
 
78
  node_gdf["pressure"] = results.node["pressure"].mean(axis=0)
79
  node_gdf["demand"] = results.node["demand"].mean(axis=0)
80
 
81
  link_gdf["flow"] = results.link["flowrate"].mean(axis=0)
82
  link_gdf["velocity"] = results.link["velocity"].mean(axis=0)
83
 
 
84
  node_gdf = node_gdf.set_geometry("geometry")
85
  link_gdf = link_gdf.set_geometry("geometry")
86
 
 
87
  if node_gdf.crs is None:
88
  crs_choice = st.selectbox("Select CRS for shapefiles", ["EPSG:4326", "EPSG:3857", "None"])
89
  if crs_choice != "None":
 
92
  else:
93
  st.warning("No CRS selected β€” export may fail.")
94
 
 
95
  node_path = os.path.join(temp_dir, "nodes_with_results.shp")
96
  link_path = os.path.join(temp_dir, "links_with_results.shp")
97
  node_gdf.to_file(node_path, driver="ESRI Shapefile")
98
  link_gdf.to_file(link_path, driver="ESRI Shapefile")
99
 
 
100
  zip_path = os.path.join(temp_dir, "simulation_shapefiles.zip")
101
  with zipfile.ZipFile(zip_path, 'w') as zipf:
102
  for f in os.listdir(temp_dir):
103
+ if f.endswith((".shp", ".shx", ".dbf", ".prj")):
104
  zipf.write(os.path.join(temp_dir, f), arcname=f)
105
 
106
  with open(zip_path, "rb") as f:
 
112
  st.subheader("πŸ”— Preview of Link Results")
113
  st.dataframe(link_gdf[["flow", "velocity"]].head())
114
 
115
+ # ------------------------- Criticality Analysis -------------------------
116
+ st.subheader("⚠️ Pipe Criticality Analysis")
117
+ if st.button("Run Criticality Analysis on Large Pipes"):
118
+ try:
119
+ wn.options.time.duration = 72 * 3600
120
+ wn.options.hydraulic.demand_model = 'PDD'
121
+ wn.options.hydraulic.required_pressure = 17.57
122
+ wn.options.hydraulic.minimum_pressure = 0
123
+
124
+ pipes = wn.query_link_attribute('diameter', np.greater_equal, 24 * 0.0254,
125
+ link_type=wntr.network.model.Pipe)
126
+ pipes = list(pipes.index)
127
+ pressure_threshold = 14.06
128
+
129
+ sim = wntr.sim.WNTRSimulator(wn)
130
+ results = sim.run_sim()
131
+ min_pressure = results.node['pressure'].loc[:, wn.junction_name_list].min()
132
+ below_threshold_normal_conditions = set(min_pressure[min_pressure < pressure_threshold].index)
133
+
134
+ junctions_impacted = {}
135
+ for pipe_name in pipes:
136
+ wn.reset_initial_values()
137
+ pipe = wn.get_link(pipe_name)
138
+ act = wntr.network.controls.ControlAction(pipe, 'status', wntr.network.LinkStatus.Closed)
139
+ cond = wntr.network.controls.SimTimeCondition(wn, '=', '24:00:00')
140
+ ctrl = wntr.network.controls.Control(cond, act)
141
+ wn.add_control('close pipe ' + pipe_name, ctrl)
142
+
143
+ try:
144
+ sim = wntr.sim.WNTRSimulator(wn)
145
+ results = sim.run_sim()
146
+ min_pressure = results.node['pressure'].loc[:, wn.junction_name_list].min()
147
+ below_threshold = set(min_pressure[min_pressure < pressure_threshold].index)
148
+ junctions_impacted[pipe_name] = below_threshold - below_threshold_normal_conditions
149
+ except:
150
+ junctions_impacted[pipe_name] = set()
151
+
152
+ wn.remove_control('close pipe ' + pipe_name)
153
+
154
+ number_of_junctions_impacted = {k: len(v) for k, v in junctions_impacted.items()}
155
+ st.write("Junctions impacted per pipe:", number_of_junctions_impacted)
156
+
157
+ if number_of_junctions_impacted:
158
+ worst_pipe = max(number_of_junctions_impacted, key=number_of_junctions_impacted.get)
159
+ st.write(f"🚨 Most critical pipe: {worst_pipe} impacts {number_of_junctions_impacted[worst_pipe]} junctions")
160
+ except Exception as e:
161
+ st.error(f"Criticality analysis failed: {e}")
162
+ # ------------------------------------------------------------------------
163
+
164
  except Exception as e:
165
+ st.error(f"Simulation failed: {e}")