84 lines
2.7 KiB
Python
84 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
from typing import Any
|
|
from uuid import uuid4
|
|
|
|
import pandas as pd
|
|
|
|
from app.algorithms.burst_location import run_burst_location
|
|
from app.services.tjnetwork import dump_inp
|
|
|
|
SeriesInput = pd.Series | dict[str, Any] | list[dict[str, Any]]
|
|
|
|
|
|
def _normalize_series(data: SeriesInput, field_name: str) -> pd.Series:
|
|
if isinstance(data, pd.Series):
|
|
series = data.copy()
|
|
elif isinstance(data, dict):
|
|
series = pd.Series(data, dtype=float)
|
|
elif isinstance(data, list):
|
|
if len(data) == 0:
|
|
return pd.Series(dtype=float)
|
|
frame = pd.DataFrame(data)
|
|
if not {"id", "value"}.issubset(frame.columns):
|
|
raise ValueError(f"{field_name} list item must include 'id' and 'value'.")
|
|
series = pd.Series(
|
|
frame["value"].values, index=frame["id"].astype(str).values, dtype=float
|
|
)
|
|
else:
|
|
raise ValueError(f"Unsupported data format for {field_name}.")
|
|
|
|
series.index = series.index.map(str)
|
|
return pd.to_numeric(series, errors="raise")
|
|
|
|
|
|
def run_burst_location_by_network(
|
|
*,
|
|
network: str,
|
|
pressure_scada_ids: list[str],
|
|
burst_pressure: SeriesInput,
|
|
normal_pressure: SeriesInput,
|
|
burst_leakage: float,
|
|
flow_scada_ids: list[str] | None = None,
|
|
burst_flow: SeriesInput | None = None,
|
|
normal_flow: SeriesInput | None = None,
|
|
min_dpressure: float = 2.0,
|
|
basic_pressure: float = 10.0,
|
|
) -> dict[str, Any]:
|
|
if not network:
|
|
raise ValueError("network is required.")
|
|
|
|
tmp_filename = f"burst_location_{network}_{uuid4().hex}.inp"
|
|
inp_path = Path.cwd() / tmp_filename
|
|
|
|
try:
|
|
dump_inp(network, tmp_filename)
|
|
|
|
burst_pressure_series = _normalize_series(burst_pressure, "burst_pressure")
|
|
normal_pressure_series = _normalize_series(normal_pressure, "normal_pressure")
|
|
burst_flow_series = (
|
|
_normalize_series(burst_flow, "burst_flow") if burst_flow is not None else None
|
|
)
|
|
normal_flow_series = (
|
|
_normalize_series(normal_flow, "normal_flow")
|
|
if normal_flow is not None
|
|
else None
|
|
)
|
|
|
|
return run_burst_location(
|
|
wn_inp_path=str(inp_path),
|
|
pressure_scada_ids=pressure_scada_ids,
|
|
burst_pressure=burst_pressure_series,
|
|
normal_pressure=normal_pressure_series,
|
|
burst_leakage=burst_leakage,
|
|
flow_scada_ids=flow_scada_ids,
|
|
burst_flow=burst_flow_series,
|
|
normal_flow=normal_flow_series,
|
|
min_dpressure=min_dpressure,
|
|
basic_pressure=basic_pressure,
|
|
)
|
|
finally:
|
|
if inp_path.exists():
|
|
inp_path.unlink()
|