diff --git a/swmmio/core.py b/swmmio/core.py index 44e4e32..23acc97 100644 --- a/swmmio/core.py +++ b/swmmio/core.py @@ -511,6 +511,7 @@ def __init__(self, file_path): self._files_df = None self._raingages_df = None self._evaporation_df = None + self._losses_df = None self._report_df = None self._conduits_df = None self._xsections_df = None @@ -526,6 +527,7 @@ def __init__(self, file_path): self._junctions_df = None self._outfalls_df = None self._storage_df = None + self._dividers_df = None self._coordinates_df = None self._dwf_df = None self._rdii_df = None @@ -535,6 +537,8 @@ def __init__(self, file_path): self._subcatchments_df = None self._subareas_df = None self._infiltration_df = None + self._aquifers_df = None + self._groundwater_df = None self._inp_section_details = None self._inflows_df = None self._curves_df = None @@ -551,6 +555,7 @@ def __init__(self, file_path): '[FILES]', '[RAINGAGES]', '[EVAPORATION]', + '[LOSSES]', '[REPORT]', '[CONDUITS]', '[XSECTIONS]', @@ -565,11 +570,14 @@ def __init__(self, file_path): '[WEIRS]', '[JUNCTIONS]', '[STORAGE]', + '[DIVIDERS]', '[OUTFALLS]', '[VERTICES]', '[SUBCATCHMENTS]', '[SUBAREAS]', '[INFILTRATION]', + '[AQUIFERS]', + '[GROUNDWATER]', '[CURVES]', '[COORDINATES]', '[DWF]', @@ -751,6 +759,30 @@ def evaporation(self, df): """Set inp.evaporation DataFrame.""" self._evaporation_df = df + @property + def losses(self): + """ + get/set losses section of model + + :return: dataframe of evaporation section in inp file + + >>> from swmmio.examples import spruce + >>> spruce.inp.losses #doctest: +NORMALIZE_WHITESPACE + Inlet Outlet Average Flap Gate SeepageRate + Link + C1:C2 0 0 0 YES 0 + C2.1 0 0 0 YES 0 + """ + if self._losses_df is not None: + return self._losses_df + self._losses_df = dataframe_from_inp(self.path, 'losses') + return self._losses_df + + @losses.setter + def losses(self, df): + """Set inp.losses DataFrame.""" + self._losses_df = df + @property def report(self): """ @@ -1100,6 +1132,29 @@ def storage(self, df): """Set inp.storage DataFrame.""" self._storage_df = df + @property + def dividers(self): + """ + Get/set dividers section of the INP file. + + :return: dividers section of the INP file + :rtype: pandas.DataFrame + + >>> from swmmio.examples import spruce + >>> spruce.inp.dividers #doctest: +NORMALIZE_WHITESPACE + Elevation Diverted Link Type Parameters + Name + NODE5 3.0 C6 CUTOFF 1.0 + """ + if self._dividers_df is None: + self._dividers_df = dataframe_from_inp(self.path, "[DIVIDERS]") + return self._dividers_df + + @dividers.setter + def dividers(self, df): + """Set inp.dividers DataFrame.""" + self._dividers_df = df + @property def subcatchments(self): """ @@ -1158,6 +1213,64 @@ def infiltration(self, df): """Set inp.infiltration DataFrame.""" self._infiltration_df = df + @property + def aquifers(self): + """ + Get/set the aquifers section of the INP file. + + >>> from swmmio.examples import groundwater + >>> groundwater.inp.aquifers.loc['1'] #doctest: +NORMALIZE_WHITESPACE + Por 0.500 + WP 0.150 + FC 0.300 + Ksat 0.100 + Kslope 12.000 + Tslope 15.000 + ETu 0.350 + ETs 14.000 + Seep 0.002 + Ebot 0.000 + Egw 3.500 + Umc 0.400 + Name: 1, dtype: float64 + """ + if self._aquifers_df is None: + self._aquifers_df = dataframe_from_inp(self.path, "aquifers") + return self._aquifers_df + + @aquifers.setter + def aquifers(self, df): + """Set inp.aquifers DataFrame.""" + self._aquifers_df = df + + @property + def groundwater(self): + """ + Get/set the groundwater section of the INP file. + + >>> from swmmio.examples import groundwater + >>> groundwater.inp.groundwater.loc['1'] #doctest: +NORMALIZE_WHITESPACE + Aquifer 1.0 + Node 2.0 + Esurf 6.0 + A1 0.1 + B1 1.0 + A2 0.0 + B2 0.0 + A3 0.0 + Dsw 0.0 + Egwt 4.0 + Name: 1, dtype: float64 + """ + if self._groundwater_df is None: + self._groundwater_df = dataframe_from_inp(self.path, "groundwater") + return self._groundwater_df + + @groundwater.setter + def groundwater(self, df): + """Set inp.groundwater DataFrame.""" + self._groundwater_df = df + @property def coordinates(self): """ @@ -1353,6 +1466,7 @@ def streets(self): Examples -------- Access the streets section of the inp file + >>> from swmmio.examples import streets >>> streets.inp.streets[['Tcrown', 'Hcurb']] #doctest: +NORMALIZE_WHITESPACE Tcrown Hcurb @@ -1382,6 +1496,7 @@ def inlets(self): Examples -------- Access the inlets section of the inp file + >>> from swmmio.examples import streets >>> streets.inp.inlets #doctest: +NORMALIZE_WHITESPACE Type Param1 Param2 Param3 @@ -1411,6 +1526,7 @@ def inlet_usage(self): Examples -------- Access the inlet usage section of the inp file + >>> from swmmio.examples import streets >>> streets.inp.inlet_usage[['Inlet', 'Node', 'Number', '%Clogged']] #doctest: +NORMALIZE_WHITESPACE Inlet Node Number %Clogged diff --git a/swmmio/defs/inp_sections.yml b/swmmio/defs/inp_sections.yml index bddf1e2..d719159 100644 --- a/swmmio/defs/inp_sections.yml +++ b/swmmio/defs/inp_sections.yml @@ -35,6 +35,8 @@ inp_file_objects: - SeepageRate CONDUITS: [Name, InletNode, OutletNode, Length, Roughness, InOffset, OutOffset, InitFlow, MaxFlow] INFILTRATION: [Subcatchment, Suction, HydCon, IMDmax] + AQUIFERS: [Name, Por, WP, FC, Ksat, Kslope, Tslope, ETu, ETs, Seep, Ebot, Egw, Umc, ETupat] + GROUNDWATER: [Subcatchment, Aquifer, Node, Esurf, A1, B1, A2, B2, A3, Dsw, Egwt, Ebot, Wgr, Umc] JUNCTIONS: [Name, InvertElev, MaxDepth, InitDepth, SurchargeDepth, PondedArea] DWF: columns: [Node, Parameter, AverageValue, TimePatterns] @@ -52,6 +54,7 @@ inp_file_objects: PUMPS: [Name, InletNode, OutletNode, PumpCurve, InitStatus, Depth, ShutoffDepth] STORAGE: [Name, InvertElev, MaxD, InitDepth, StorageCurve, Coefficient, Exponent, Constant, PondedArea, EvapFrac, SuctionHead, Conductivity, InitialDeficit] + DIVIDERS: [Name, Elevation, Diverted Link, Type, Parameters] SUBCATCHMENTS: [Name, Raingage, Outlet, Area, PercImperv, Width, PercSlope, CurbLength, SnowPack] SUBAREAS: [Name, N-Imperv, N-Perv, S-Imperv, S-Perv, PctZero, RouteTo, PctRouted] diff --git a/swmmio/examples.py b/swmmio/examples.py index 002f596..9a4b5da 100644 --- a/swmmio/examples.py +++ b/swmmio/examples.py @@ -1,7 +1,7 @@ from swmmio import Model from swmmio.tests.data import (MODEL_A_PATH, MODEL_EX_1, MODEL_FULL_FEATURES_XY, MODEL_FULL_FEATURES__NET_PATH, MODEL_FULL_FEATURES_XY_B, - MODEL_GREEN_AMPT, MODEL_TEST_INLET_DRAINS) + MODEL_GREEN_AMPT, MODEL_TEST_INLET_DRAINS, MODEL_GROUNDWATER) # example models philly = Model(MODEL_A_PATH, crs="+init=EPSG:2817") @@ -11,3 +11,4 @@ walnut = Model(MODEL_EX_1) green = Model(MODEL_GREEN_AMPT) streets = Model(MODEL_TEST_INLET_DRAINS) +groundwater = Model(MODEL_GROUNDWATER) diff --git a/swmmio/tests/data/__init__.py b/swmmio/tests/data/__init__.py index 23ea5c5..5682893 100644 --- a/swmmio/tests/data/__init__.py +++ b/swmmio/tests/data/__init__.py @@ -32,6 +32,7 @@ MODEL_INFILTRAION_PARSE_FAILURE = os.path.join(DATA_PATH, 'model-with-infiltration-parse-failure.inp') MODEL_EXTCNTRLMODEL = os.path.join(DATA_PATH, 'SWMMExtCntrlModel.inp') MODEL_TEST_INLET_DRAINS = os.path.join(DATA_PATH, 'test_inlet_drains.inp') +MODEL_GROUNDWATER = os.path.join(DATA_PATH, 'groundwater_model.inp') # test rpt paths RPT_FULL_FEATURES = os.path.join(DATA_PATH, 'model_full_features_network.rpt') diff --git a/swmmio/tests/data/groundwater_model.inp b/swmmio/tests/data/groundwater_model.inp new file mode 100644 index 0000000..cd9a3d2 --- /dev/null +++ b/swmmio/tests/data/groundwater_model.inp @@ -0,0 +1,147 @@ +[TITLE] +;;Project Title/Notes +A simple groundwater model. +See Groundwater_Model.txt for more details. + +[OPTIONS] +;;Option Value +FLOW_UNITS CFS +INFILTRATION HORTON +FLOW_ROUTING KINWAVE +LINK_OFFSETS DEPTH +MIN_SLOPE 0 +ALLOW_PONDING NO +SKIP_STEADY_STATE NO + +START_DATE 09/13/2014 +START_TIME 00:00:00 +REPORT_START_DATE 09/13/2014 +REPORT_START_TIME 00:00:00 +END_DATE 09/15/2014 +END_TIME 00:00:00 +SWEEP_START 01/01 +SWEEP_END 12/31 +DRY_DAYS 0 +REPORT_STEP 00:15:00 +WET_STEP 00:05:00 +DRY_STEP 00:05:00 +ROUTING_STEP 0:00:30 +RULE_STEP 00:00:00 + +INERTIAL_DAMPING PARTIAL +NORMAL_FLOW_LIMITED BOTH +FORCE_MAIN_EQUATION H-W +VARIABLE_STEP 0.75 +LENGTHENING_STEP 0 +MIN_SURFAREA 12.557 +MAX_TRIALS 8 +HEAD_TOLERANCE 0.005 +SYS_FLOW_TOL 5 +LAT_FLOW_TOL 5 +MINIMUM_STEP 0.5 +THREADS 1 + +[EVAPORATION] +;;Data Source Parameters +;;-------------- ---------------- +CONSTANT 0.0 +DRY_ONLY NO + +[RAINGAGES] +;;Name Format Interval SCF Source +;;-------------- --------- ------ ------ ---------- +1 INTENSITY 0:15 1.0 TIMESERIES Rainfall + +[SUBCATCHMENTS] +;;Name Rain Gage Outlet Area %Imperv Width %Slope CurbLen SnowPack +;;-------------- ---------------- ---------------- -------- -------- -------- -------- -------- ---------------- +1 1 2 5 0 140 0.5 0 + +[SUBAREAS] +;;Subcatchment N-Imperv N-Perv S-Imperv S-Perv PctZero RouteTo PctRouted +;;-------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- +1 0.01 0.1 0.05 0.05 25 OUTLET + +[INFILTRATION] +;;Subcatchment Param1 Param2 Param3 Param4 Param5 +;;-------------- ---------- ---------- ---------- ---------- ---------- +1 1.2 0.1 2 7 0 + +[AQUIFERS] +;;Name Por WP FC Ksat Kslope Tslope ETu ETs Seep Ebot Egw Umc ETupat +;;-------------- ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ +1 0.5 0.15 0.30 0.1 12 15.0 0.35 14.0 0.002 0.0 3.5 0.40 + +[GROUNDWATER] +;;Subcatchment Aquifer Node Esurf A1 B1 A2 B2 A3 Dsw Egwt Ebot Wgr Umc +;;-------------- ---------------- ---------------- ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ +1 1 2 6 0.1 1 0 0 0 0 4 + +[OUTFALLS] +;;Name Elevation Type Stage Data Gated Route To +;;-------------- ---------- ---------- ---------------- -------- ---------------- +2 0 FREE NO + +[TIMESERIES] +;;Name Date Time Value +;;-------------- ---------- ---------- ---------- +Rainfall 0:00 0.037 +Rainfall 0:15 0.111 +Rainfall 0:30 0.185 +Rainfall 0:45 0.259 +Rainfall 1:00 0.333 +Rainfall 1:15 0.407 +Rainfall 1:30 0.481 +Rainfall 1:45 0.556 +Rainfall 2:00 0.630 +Rainfall 2:15 0.644 +Rainfall 2:30 0.600 +Rainfall 2:45 0.556 +Rainfall 3:00 0.511 +Rainfall 3:15 0.467 +Rainfall 3:30 0.422 +Rainfall 3:45 0.378 +Rainfall 4:00 0.333 +Rainfall 4:15 0.289 +Rainfall 4:30 0.244 +Rainfall 4:45 0.200 +Rainfall 5:00 0.156 +Rainfall 5:15 0.111 +Rainfall 5:30 0.067 +Rainfall 5:45 0.022 +Rainfall 6:00 0 + +[REPORT] +;;Reporting Options +SUBCATCHMENTS ALL +NODES ALL +LINKS ALL + +[TAGS] + +[MAP] +DIMENSIONS 0.000 0.000 10000.000 10000.000 +Units None + +[COORDINATES] +;;Node X-Coord Y-Coord +;;-------------- ------------------ ------------------ +2 4556.338 3352.113 + +[VERTICES] +;;Link X-Coord Y-Coord +;;-------------- ------------------ ------------------ + +[Polygons] +;;Subcatchment X-Coord Y-Coord +;;-------------- ------------------ ------------------ +1 2964.789 4971.831 +1 6134.511 4986.413 +1 6134.511 7445.652 +1 2964.789 7450.704 + +[SYMBOLS] +;;Gage X-Coord Y-Coord +;;-------------- ------------------ ------------------ +1 4485.915 8197.183 + diff --git a/swmmio/tests/data/model_full_features_network.inp b/swmmio/tests/data/model_full_features_network.inp index 92880e8..28ae87a 100644 --- a/swmmio/tests/data/model_full_features_network.inp +++ b/swmmio/tests/data/model_full_features_network.inp @@ -88,6 +88,11 @@ J4 0 FREE NO ;;-------------- -------- ---------- ----------- ---------- ---------------------------- -------- -------- -------- -------- J1 13.392 15 0 FUNCTIONAL 1000 0 0 0 0 +[DIVIDERS] +;;Name Elev Link Type Parameters +;;----- ---- ---- ------ ---------- +NODE5 3.0 C6 CUTOFF 1.0 + [CONDUITS] ;;Name From Node To Node Length Roughness InOffset OutOffset InitFlow MaxFlow ;;-------------- ---------------- ---------------- ---------- ---------- ---------- ---------- ---------- ---------- @@ -121,6 +126,12 @@ C2.1 CIRCULAR 1 0 0 0 5 CIRCULAR 1 0 0 0 1 C3 RECT_OPEN 5 1 0 0 +[LOSSES] +;;Link Kentry Kexit Kavg Flap Gate Seepage +;;-------------- ---------- ---------- ---------- ---------- ---------- +C1:C2 0 0 0 YES 0 +C2.1 0 0 0 YES 0 + [INFLOWS] ;;Node Constituent Time Series Type Mfactor Sfactor Baseline Pattern ;;-------------- ---------------- ---------------- -------- -------- -------- -------- -------- diff --git a/swmmio/utils/text.py b/swmmio/utils/text.py index 9a6f866..470441b 100644 --- a/swmmio/utils/text.py +++ b/swmmio/utils/text.py @@ -62,13 +62,28 @@ def inline_comments_in_inp(filepath, overwrite=False): def extract_section_of_file(file_path, start_strings, end_strings, comment=';', **kwargs): """ - Extract a portion of a file found between one or more start strings and the first - encountered end string. - :param file_path: path to the source file - :param start_strings: string or list of strings from which to start extracting - :param end_strings: string or list of strings at which to stop extracting - :param comment: comment string used to ignore parts of source file - :return: string extracted from source file + Extract a portion of a file found between one or more start strings and the first encountered end string. + + Parameters + ---------- + file_path : str + Path to the source file. + start_strings : str or list of str + String or list of strings from which to start extracting. + end_strings : str or list of str + String or list of strings at which to stop extracting. + comment : str, optional + Comment string used to ignore parts of the source file. Defaults to ';'. + **kwargs + Other keyword arguments. + + Returns + ------- + str + String extracted from source file. + + Examples + -------- >>> from swmmio.tests.data import MODEL_FULL_FEATURES_XY >>> s = extract_section_of_file(MODEL_FULL_FEATURES_XY, '[EVAPORATI', '[', comment=None) >>> print(s.strip())