Skip to content

Commit 9c885cb

Browse files
authored
Merge pull request #219 from kaklise/inp_sections
Updates to support read/write of additional INP/RPT sections
2 parents 24673b5 + 26a04b6 commit 9c885cb

File tree

9 files changed

+512
-11
lines changed

9 files changed

+512
-11
lines changed

swmmio/core.py

+97-1
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,8 @@ def __init__(self, file_path):
600600
self._streets_df = None
601601
self._inlets_df = None
602602
self._inlet_usage_df = None
603+
self._patterns_df = None
604+
self._controls_df = None
603605

604606
SWMMIOFile.__init__(self, file_path) # run the superclass init
605607

@@ -644,6 +646,8 @@ def __init__(self, file_path):
644646
'[STREETS]',
645647
'[INLETS]',
646648
'[INLET_USAGE]',
649+
'[PATTERNS]',
650+
'[CONTROLS]',
647651
]
648652

649653
def save(self, target_path=None):
@@ -1452,7 +1456,7 @@ def inflows(self):
14521456
if self._inflows_df is not None:
14531457
return self._inflows_df
14541458
inf = dataframe_from_inp(self.path, 'INFLOWS', quote_replace='_!!!!_')
1455-
self._inflows_df = inf.replace('_!!!!_', np.nan)
1459+
self._inflows_df = inf.replace('_!!!!_', '""') # revert quote replace
14561460
return self._inflows_df
14571461

14581462
@inflows.setter
@@ -1508,6 +1512,98 @@ def timeseries(self, df):
15081512
"""Set inp.timeseries DataFrame."""
15091513
self._timeseries_df = df
15101514

1515+
@property
1516+
def patterns(self):
1517+
"""
1518+
Get/set patterns section of the model
1519+
1520+
:return: dataframe of patterns
1521+
1522+
>>> from swmmio.examples import pump_control
1523+
>>> # NOTE, only the first 5 columns are shown in the following example
1524+
>>> pump_control.inp.patterns.iloc[:,0:5] #doctest: +NORMALIZE_WHITESPACE
1525+
Type Factor1 Factor2 Factor3 Factor4
1526+
Name
1527+
DWF HOURLY 0.0151 0.01373 0.01812 0.01098
1528+
"""
1529+
1530+
if self._patterns_df is not None:
1531+
return self._patterns_df
1532+
self._patterns_df = dataframe_from_inp(self.path, '[PATTERNS]')
1533+
1534+
if self._patterns_df.shape[0] > 0:
1535+
# reformat, 1 row per pattern
1536+
pattern_entry_list = []
1537+
for name, pattern in self._patterns_df.groupby('Name'):
1538+
pattern_entry = {}
1539+
pattern_entry['Name'] = name
1540+
pattern_entry['Type'] = pattern['Type'].iloc[0]
1541+
if pattern.shape[0] > 1:
1542+
# shift pattern values to the right
1543+
pattern.iloc[1::, 1::] = pattern.iloc[1::, 0:-1].values
1544+
pattern['Factors'] = pattern['Factors'].astype(float)
1545+
values = pattern.iloc[:, 1:].values.flatten()
1546+
for i in range(len(values)):
1547+
pattern_entry['Factor'+str(i+1)] = values[i]
1548+
pattern_entry_list.append(pattern_entry)
1549+
1550+
self._patterns_df = pd.DataFrame(pattern_entry_list)
1551+
self._patterns_df.set_index('Name', inplace=True)
1552+
1553+
return self._patterns_df
1554+
1555+
@patterns.setter
1556+
def patterns(self, df):
1557+
"""Set inp.patterns DataFrame."""
1558+
self._patterns_df = df
1559+
1560+
@property
1561+
def controls(self):
1562+
"""
1563+
Get/set controls section of the model
1564+
1565+
:return: dataframe of controls
1566+
1567+
>>> from swmmio.examples import pump_control
1568+
>>> pump_control.inp.controls #doctest: +NORMALIZE_WHITESPACE
1569+
Control
1570+
Name
1571+
RULE PUMP1A IF NODE SU1 DEPTH >= 4 THEN PUMP PUMP1 status = ON PRIORITY 1
1572+
RULE PUMP1B IF NODE SU1 DEPTH < 1 THEN PUMP PUMP1 status = OFF PRIORITY 1
1573+
"""
1574+
1575+
if self._controls_df is None:
1576+
self._controls_df = dataframe_from_inp(self.path, "[CONTROLS]")
1577+
1578+
if self._controls_df.shape[0] > 0:
1579+
# reformat, 1 row per control
1580+
control_entry_list = []
1581+
control_entry = {}
1582+
controls = self._controls_df['[CONTROLS]']
1583+
# make sure the first entry starts with RULE
1584+
assert controls[0][0:5] == "RULE "
1585+
for row in controls:
1586+
if row[0:5] == 'RULE ': # new control
1587+
if len(control_entry) > 0: # add control to the list
1588+
control_entry_list.append(control_entry)
1589+
control_entry = {}
1590+
control_entry['Name'] = row.rstrip() # remove white space
1591+
control_entry['Control'] = ''
1592+
else:
1593+
control_entry['Control'] = control_entry['Control'] + row + ' '
1594+
if len(control_entry) > 0: # add last control to the list
1595+
control_entry_list.append(control_entry)
1596+
1597+
self._controls_df = pd.DataFrame(control_entry_list)
1598+
self._controls_df.set_index('Name', inplace=True)
1599+
1600+
return self._controls_df
1601+
1602+
@controls.setter
1603+
def controls(self, df):
1604+
"""Set inp.controls DataFrame."""
1605+
self._controls_df = df
1606+
15111607
@property
15121608
def tags(self):
15131609
"""

swmmio/defs/inp_sections.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ inp_file_objects:
7878
STREETS: [Name, Tcrown, Hcurb, Sx, nRoad, a, W, Sides, Tback, Sback, nBack]
7979
INLETS: [Name, Type, Param1, Param2, Param3, Param4, Param5]
8080
INLET_USAGE: [Link, Inlet, Node, Number, "%Clogged", Qmax, aLocal, wLocal, Placement]
81-
82-
81+
PATTERNS: [Name, Type, Factors]
82+
CONTROLS: [blob]
8383

8484
inp_section_tags:
8585
['[TITLE', '[OPTION', '[FILE', '[RAINGAGES', '[TEMPERATURE', '[EVAP',

swmmio/defs/section_headers.yml

+10
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@ rpt_sections:
132132
- SlopePerc
133133
- RainGage
134134
- Outlet
135+
Pumping Summary:
136+
- PercentUtilized
137+
- NumberOfStartUps
138+
- MinFlowCFS
139+
- AvgFlowCFS
140+
- MaxFlowCFS
141+
- TotalVolume(MG)
142+
- PowerUsage(kW-hr)
143+
- PercentTimeOffPumpCurveLow
144+
- PercentTimeOffPumpCurveHigh
135145

136146
swmm5_version:
137147
1.13:

swmmio/examples.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from swmmio import Model
22
from swmmio.tests.data import (MODEL_A_PATH, MODEL_EX_1, MODEL_FULL_FEATURES_XY,
33
MODEL_FULL_FEATURES__NET_PATH, MODEL_FULL_FEATURES_XY_B,
4-
MODEL_GREEN_AMPT, MODEL_TEST_INLET_DRAINS, MODEL_GROUNDWATER)
4+
MODEL_GREEN_AMPT, MODEL_TEST_INLET_DRAINS, MODEL_GROUNDWATER,
5+
MODEL_PUMP_CONTROL)
56

67
# example models
78
philly = Model(MODEL_A_PATH, crs="+init=EPSG:2817")
@@ -12,3 +13,4 @@
1213
green = Model(MODEL_GREEN_AMPT)
1314
streets = Model(MODEL_TEST_INLET_DRAINS)
1415
groundwater = Model(MODEL_GROUNDWATER)
16+
pump_control = Model(MODEL_PUMP_CONTROL)

0 commit comments

Comments
 (0)