razaali10 commited on
Commit
5b74926
·
verified ·
1 Parent(s): 690d06d

Upload 3 files

Browse files
Files changed (3) hide show
  1. .huggingface.yaml +2 -0
  2. README.md +15 -0
  3. app.py +72 -0
.huggingface.yaml ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ sdk: fastapi
2
+ python_version: 3.10
README.md ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # EPANET Simulation API
2
+
3
+ This FastAPI app simulates EPANET water distribution models using WNTR.
4
+
5
+ ## Usage
6
+ POST `/simulate` endpoint with:
7
+ - `inp_file`: Upload your EPANET .inp file
8
+ - Optional query parameters for:
9
+ - simulation_duration (default 24 hrs)
10
+ - output_results: ["pressure", "flow"]
11
+ - nodes_to_report: List of node IDs
12
+ - links_to_report: List of link IDs
13
+ - generate_plot: true/false
14
+
15
+ Returns simulation statistics and optional plots.
app.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, File, UploadFile, HTTPException
2
+ from fastapi.responses import JSONResponse
3
+ from typing import List, Optional
4
+ import uvicorn
5
+ import tempfile
6
+ import os
7
+ import wntr
8
+ import matplotlib.pyplot as plt
9
+ import pandas as pd
10
+
11
+ app = FastAPI(title="EPANET Simulation API")
12
+
13
+ @app.post("/simulate")
14
+ async def simulate_epanet(
15
+ inp_file: UploadFile = File(...),
16
+ simulation_duration: Optional[int] = 24,
17
+ output_results: List[str] = ["pressure", "flow"],
18
+ nodes_to_report: Optional[List[str]] = None,
19
+ links_to_report: Optional[List[str]] = None,
20
+ generate_plot: Optional[bool] = True
21
+ ):
22
+ try:
23
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".inp") as temp_file:
24
+ temp_file.write(await inp_file.read())
25
+ inp_path = temp_file.name
26
+
27
+ wn = wntr.network.WaterNetworkModel(inp_path)
28
+ sim = wntr.sim.WNTRSimulator(wn)
29
+ results = sim.run_sim()
30
+
31
+ response_data = {}
32
+
33
+ if "pressure" in output_results:
34
+ pressures = results.node['pressure']
35
+ if nodes_to_report:
36
+ pressures = pressures[nodes_to_report]
37
+ response_data["pressure"] = pressures.describe().to_dict()
38
+
39
+ if "flow" in output_results:
40
+ flows = results.link['flowrate']
41
+ if links_to_report:
42
+ flows = flows[links_to_report]
43
+ response_data["flow"] = flows.describe().to_dict()
44
+
45
+ if generate_plot:
46
+ plot_dir = tempfile.mkdtemp()
47
+ plot_paths = []
48
+ if "pressure" in output_results and nodes_to_report:
49
+ for node in nodes_to_report:
50
+ plt.figure()
51
+ results.node['pressure'][node].plot(title=f"Pressure at {node}")
52
+ img_path = os.path.join(plot_dir, f"pressure_{node}.png")
53
+ plt.savefig(img_path)
54
+ plot_paths.append(img_path)
55
+ plt.close()
56
+ if "flow" in output_results and links_to_report:
57
+ for link in links_to_report:
58
+ plt.figure()
59
+ results.link['flowrate'][link].plot(title=f"Flow in {link}")
60
+ img_path = os.path.join(plot_dir, f"flow_{link}.png")
61
+ plt.savefig(img_path)
62
+ plot_paths.append(img_path)
63
+ plt.close()
64
+ response_data["plots"] = plot_paths
65
+
66
+ return JSONResponse(content=response_data)
67
+
68
+ except Exception as e:
69
+ raise HTTPException(status_code=500, detail=str(e))
70
+ finally:
71
+ if os.path.exists(inp_path):
72
+ os.remove(inp_path)