Skip to content

Commit e2c549b

Browse files
committed
feat: make package compatible with python 3.9 and epanet export to database with Giswater 3.5
1 parent f8cfb94 commit e2c549b

File tree

4 files changed

+46
-30
lines changed

4 files changed

+46
-30
lines changed

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ classifiers = [
3838
]
3939
dependencies = [
4040
"pyswmm>=2.0.0",
41-
"swmm-api>=0.4.60",
42-
"wntr>=1.0.0",
41+
"swmm-api==0.4.31",
42+
"wntr==1.2.0",
4343
"psycopg[binary]>=3.1.0",
4444
"requests>=2.28.0",
45-
"pyproj>=3.7.0"
45+
"pyproj>=3.6.0"
4646
]
4747

4848
[project.optional-dependencies]

src/hydraulic_engine/epanet/bin_handler.py

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ def export_to_database(
4242
result_id: str,
4343
inp_handler: EpanetInpHandler,
4444
round_decimals: int = 2,
45-
dao: Optional[HePgDao] = None
45+
dao: Optional[HePgDao] = None,
46+
giswater_version: int = 4
4647
) -> bool:
4748
"""
4849
Export simulation results to Giswater database.
@@ -63,6 +64,7 @@ def export_to_database(
6364
:param inp_handler: INP handler to get coordinates
6465
:param round_decimals: Number of decimal places to round the results (default: 2)
6566
:param dao: Database access object (optional, uses global connection if not provided)
67+
:param giswater_version: Version of Giswater (default: 4)
6668
:return: True if export successful, False otherwise
6769
"""
6870
if not self.is_loaded():
@@ -84,12 +86,12 @@ def export_to_database(
8486

8587
# Step 1: Clean previous results for this result_id
8688
tools_log.log_info("Cleaning previous results...")
87-
if not _clean_previous_results(dao, result_id):
89+
if not _clean_previous_results(dao, result_id, giswater_version):
8890
return False
8991

9092
# Step 2: Insert time series data into rpt_node
9193
tools_log.log_info("Inserting node results...")
92-
node_count = _insert_node_results(dao, results, result_id, inp_handler, round_decimals)
94+
node_count = _insert_node_results(dao, results, result_id, inp_handler, round_decimals, giswater_version)
9395
tools_log.log_info(f"Inserted {node_count} node result records")
9496

9597
# Step 3: Insert time series data into rpt_arc
@@ -101,17 +103,18 @@ def export_to_database(
101103
tools_log.log_info("Post-processing arc results...")
102104
_post_process_arcs(dao, result_id)
103105

104-
# Step 5: Calculate and insert node statistics
105-
tools_log.log_info("Calculating node statistics...")
106-
_insert_node_stats(dao, result_id)
106+
if giswater_version > 3:
107+
# Step 5: Calculate and insert node statistics
108+
tools_log.log_info("Calculating node statistics...")
109+
_insert_node_stats(dao, result_id)
107110

108-
# Step 6: Calculate and insert arc statistics
109-
tools_log.log_info("Calculating arc statistics...")
110-
_insert_arc_stats(dao, result_id)
111+
# Step 6: Calculate and insert arc statistics
112+
tools_log.log_info("Calculating arc statistics...")
113+
_insert_arc_stats(dao, result_id)
111114

112115
# Step 8: Update rpt_cat_result and selectors
113116
tools_log.log_info("Updating result catalog and selectors...")
114-
_finalize_import(dao, result_id)
117+
_finalize_import(dao, result_id, giswater_version)
115118

116119
# Commit all changes
117120
dao.commit()
@@ -268,7 +271,7 @@ def _seconds_to_time_str(seconds: int) -> str:
268271
return f"{h}:{m:02d}:{s:02d}"
269272

270273

271-
def _clean_previous_results(dao: HePgDao, result_id: str) -> bool:
274+
def _clean_previous_results(dao: HePgDao, result_id: str, giswater_version: int = 4) -> bool:
272275
"""
273276
Clean previous results for the given result_id from all rpt tables.
274277
@@ -279,11 +282,12 @@ def _clean_previous_results(dao: HePgDao, result_id: str) -> bool:
279282
tables_to_clean = [
280283
'rpt_node',
281284
'rpt_arc',
282-
'rpt_node_stats',
283-
'rpt_arc_stats',
284285
'rpt_energy_usage',
285286
'rpt_hydraulic_status'
286287
]
288+
if giswater_version > 3:
289+
tables_to_clean.append('rpt_node_stats')
290+
tables_to_clean.append('rpt_arc_stats')
287291

288292
for table in tables_to_clean:
289293
sql = f"DELETE FROM {table} WHERE result_id = %s"
@@ -294,7 +298,7 @@ def _clean_previous_results(dao: HePgDao, result_id: str) -> bool:
294298
return True
295299

296300

297-
def _insert_node_results(dao: HePgDao, results: wntr.sim.SimulationResults, result_id: str, inp_handler: EpanetInpHandler, round_decimals: int = 2) -> int:
301+
def _insert_node_results(dao: HePgDao, results: wntr.sim.SimulationResults, result_id: str, inp_handler: EpanetInpHandler, round_decimals: int = 2, giswater_version: int = 4) -> int:
298302
"""
299303
Insert time series node results into rpt_node table.
300304
@@ -364,9 +368,11 @@ def _insert_node_results(dao: HePgDao, results: wntr.sim.SimulationResults, resu
364368

365369
records.append((result_id, node_id, time_str, top_elev, demand, head, pressure, quality))
366370

371+
elevation_column = 'elevation' if giswater_version == 3 else 'top_elev'
372+
367373
# Bulk insert using executemany
368-
sql = """
369-
INSERT INTO rpt_node (result_id, node_id, time, top_elev, demand, head, press, quality)
374+
sql = f"""
375+
INSERT INTO rpt_node (result_id, node_id, time, {elevation_column}, demand, head, press, quality)
370376
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
371377
"""
372378

@@ -615,7 +621,7 @@ def _insert_arc_stats(dao: HePgDao, result_id: str) -> None:
615621
dao.execute(sql, (result_id, result_id, result_id), commit=False)
616622

617623

618-
def _finalize_import(dao: HePgDao, result_id: str) -> None:
624+
def _finalize_import(dao: HePgDao, result_id: str, giswater_version: int = 4) -> None:
619625
"""
620626
Finalize the import process:
621627
- Update rpt_cat_result with execution metadata
@@ -626,13 +632,22 @@ def _finalize_import(dao: HePgDao, result_id: str) -> None:
626632
:param result_id: Result identifier
627633
"""
628634
# Update rpt_cat_result
629-
sql_update_result = """
630-
UPDATE rpt_cat_result
631-
SET exec_date = now(), cur_user = current_user, status = 2,
632-
expl_id = (SELECT array_agg(expl_id) FROM selector_expl WHERE cur_user = current_user AND expl_id > 0),
633-
sector_id = (SELECT array_agg(sector_id) FROM selector_sector WHERE cur_user = current_user AND sector_id > 0)
634-
WHERE result_id = %s
635-
"""
635+
if giswater_version == 3:
636+
sql_update_result = """
637+
UPDATE rpt_cat_result
638+
SET exec_date = now(), cur_user = current_user, status = 2,
639+
expl_id = (SELECT array_agg(expl_id) FROM selector_expl WHERE cur_user = current_user AND expl_id > 0)[1]
640+
WHERE result_id = %s
641+
"""
642+
else:
643+
sql_update_result = """
644+
UPDATE rpt_cat_result
645+
SET exec_date = now(), cur_user = current_user, status = 2,
646+
expl_id = (SELECT array_agg(expl_id) FROM selector_expl WHERE cur_user = current_user AND expl_id > 0),
647+
sector_id = (SELECT array_agg(sector_id) FROM selector_sector WHERE cur_user = current_user AND sector_id > 0)
648+
WHERE result_id = %s
649+
"""
650+
636651
dao.execute(sql_update_result, (result_id,), commit=False)
637652

638653
# Set result selector for current user

src/hydraulic_engine/epanet/runner.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -403,20 +403,21 @@ def export_result(
403403
self,
404404
to: ExportDataSource,
405405
result_id: str,
406-
batch_size: int = 50,
406+
batch_size: int = 10,
407407
max_workers: int = 4,
408408
crs_from: int = 25831,
409409
crs_to: int = 4326,
410410
start_time: Optional[datetime] = None,
411411
round_decimals: int = 2,
412412
client: Optional[HeFrostClient] = None,
413+
giswater_version: int = 4
413414
) -> bool:
414415
"""
415416
Export the result file to a specific datasource
416417
"""
417418

418419
if to == ExportDataSource.DATABASE:
419-
return self.bin.export_to_database(result_id=result_id, inp_handler=self.inp, round_decimals=round_decimals, dao=client)
420+
return self.bin.export_to_database(result_id=result_id, inp_handler=self.inp, round_decimals=round_decimals, dao=client, giswater_version=giswater_version)
420421
elif to == ExportDataSource.FROST:
421422
return self.bin.export_to_frost(
422423
inp_handler=self.inp,

src/hydraulic_engine/swmm/runner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ def export_result(
327327
self,
328328
to: ExportDataSource,
329329
result_id: str,
330-
batch_size: int = 50,
330+
batch_size: int = 10,
331331
max_workers: int = 4,
332332
crs_from: int = 25831,
333333
crs_to: int = 4326,

0 commit comments

Comments
 (0)