def test_subcatchments_dataframe_from_rpt(test_model_02): sub_ro_summary = dataframe_from_rpt(test_model_02.rpt.path, 'Subcatchment Runoff Summary') tot_ro = sub_ro_summary['TotalRunoffMG'].sum() assert tot_ro == pytest.approx(0.28, 0.001) # test retrieving timeseries results s1_results = dataframe_from_rpt(test_model_02.rpt.path, 'Subcatchment Results', 'S1') assert s1_results['RunoffCFS'].max() == pytest.approx(0.5526, 0.00001)
def conduits(self): """ collect all useful and available data related model conduits and organize in one dataframe. """ # check if this has been done already and return that data accordingly if self._conduits_df is not None: return self._conduits_df # parse out the main objects of this model inp = self.inp rpt = self.rpt # create dataframes of relevant sections from the INP conduits_df = dataframe_from_inp(inp.path, "CONDUITS") xsections_df = dataframe_from_inp(inp.path, "XSECTIONS") conduits_df = conduits_df.join(xsections_df) if rpt: # create a dictionary holding data from an rpt file, if provided link_flow_df = dataframe_from_rpt(rpt.path, "Link Flow Summary") conduits_df = conduits_df.join(link_flow_df) # add conduit coordinates xys = conduits_df.apply(lambda r: get_link_coords( r, self.inp.coordinates, self.inp.vertices), axis=1) df = conduits_df.assign(coords=xys.map(lambda x: x[0])) # add conduit up/down inverts and calculate slope elevs = self.nodes()[['InvertElev']] df = pd.merge(df, elevs, left_on='InletNode', right_index=True, how='left') df = df.rename(index=str, columns={"InvertElev": "InletNodeInvert"}) df = pd.merge(df, elevs, left_on='OutletNode', right_index=True, how='left') df = df.rename(index=str, columns={"InvertElev": "OutletNodeInvert"}) df['UpstreamInvert'] = df.InletNodeInvert + df.InOffset df['DownstreamInvert'] = df.OutletNodeInvert + df.OutOffset df['SlopeFtPerFt'] = (df.UpstreamInvert - df.DownstreamInvert) / df.Length df.InletNode = df.InletNode.astype(str) df.OutletNode = df.OutletNode.astype(str) self._conduits_df = df return df
def test_links_dataframe_from_rpt(test_model_02): link_flow_summary = dataframe_from_rpt(test_model_02.rpt.path, 'Link Flow Summary') # print(f'\n{link_flow_summary.to_string()}') s = ''' Name Type MaxQ MaxDay MaxHr MaxV MaxQPerc MaxDPerc C1:C2 CONDUIT 2.45 0 10:19 6.23 1.32 0.50 C2.1 CONDUIT 0.00 0 00:00 0.00 0.00 0.50 1 CONDUIT 2.54 0 10:00 3.48 1.10 0.89 2 CONDUIT 2.38 0 10:03 3.64 1.03 0.85 3 CONDUIT 1.97 0 09:59 2.92 0.67 1.00 4 CONDUIT 0.16 0 10:05 0.44 0.10 0.63 5 CONDUIT 0.00 0 00:00 0.00 0.00 0.50 C2 PUMP 4.33 0 10:00 0.22 NaN NaN C3 WEIR 7.00 0 10:00 0.33 NaN NaN ''' lfs_df = pd.read_csv(StringIO(s), index_col=0, delim_whitespace=True, skiprows=[0]) assert (lfs_df.equals(link_flow_summary))
def __call__(self): """ collect all useful and available data related to the conduits and organize in one dataframe. >>> model = swmmio.Model(MODEL_FULL_FEATURES__NET_PATH) >>> conduits_section = ModelSection(model, 'conduits') >>> conduits_section() """ # concat inp sections with unique element IDs headers = get_inp_sections_details(self.inp.path) dfs = [ dataframe_from_inp(self.inp.path, sect) for sect in self.inp_sections if sect.upper() in headers ] # return empty df if no inp sections found if len(dfs) == 0: return pd.DataFrame() df = pd.concat(dfs, axis=0, sort=False) # join to this any sections with matching IDs (e.g. XSECTIONS) for sect in self.join_sections: rsuffix = f"_{sect.replace(' ', '_')}" df = df.join(dataframe_from_inp(self.inp.path, sect), rsuffix=rsuffix) if df.empty: return df # if there is an RPT available, grab relevant sections if self.rpt: for rpt_sect in self.rpt_sections: df = df.join(dataframe_from_rpt(self.rpt.path, rpt_sect)) # add coordinates if self.geomtype == 'point': df = df.join(self.inp.coordinates[['X', 'Y']]) xys = df.apply(lambda r: nodexy(r), axis=1) df = df.assign(coords=xys) elif self.geomtype == 'linestring': # add conduit coordinates xys = df.apply(lambda r: get_link_coords(r, self.inp.coordinates, self.inp.vertices), axis=1) df = df.assign(coords=xys.map(lambda x: x[0])) # make inlet/outlet node IDs string type df.InletNode = df.InletNode.astype(str) df.OutletNode = df.OutletNode.astype(str) elif self.geomtype == 'polygon': p = self.inp.polygons # take stacked coordinates and orient in list of tuples, xys = p.groupby(by=p.index).apply( lambda r: [(xy['X'], xy['Y']) for ix, xy in r.iterrows()]) # copy the first point to the last position xys = xys.apply(lambda r: r + [r[0]]) df = df.assign(coords=xys) # confirm index name is string df = df.rename(index=str) # trim to desired columns if self.columns is not None: df = df[[c for c in self.columns if c in df.columns]] self._df = df return df
def fn(self): if private_df_name not in self.__dict__: self.__dict__[private_df_name] = dataframe_from_rpt( self.path, rpt_section) return self.__dict__[private_df_name]