Beispiel #1
0
    def nodes(self, bbox=None, subset=None):
        """
        collect all useful and available data related model nodes and organize
        in one dataframe.
        """

        # check if this has been done already and return that data accordingly
        if self._nodes_df is not None and bbox == self.bbox:
            return self._nodes_df

        # parse out the main objects of this model
        inp = self.inp
        rpt = self.rpt

        # create dataframes of relevant sections from the INP
        juncs_df = create_dataframeINP(inp.path, "[JUNCTIONS]")
        outfalls_df = create_dataframeINP(inp.path, "[OUTFALLS]")
        storage_df = create_dataframeINP(inp.path, "[STORAGE]")

        # concatenate the DFs and keep only relevant cols
        all_nodes = pd.concat([juncs_df, outfalls_df, storage_df])
        cols = ['InvertElev', 'MaxDepth', 'SurchargeDepth', 'PondedArea']
        all_nodes = all_nodes[cols]

        if rpt:
            # add results data if a rpt file was found
            depth_summ = create_dataframeRPT(rpt.path, "Node Depth Summary")
            flood_summ = create_dataframeRPT(rpt.path, "Node Flooding Summary")

            # join the rpt data (index on depth df, suffixes for common cols)
            rpt_df = depth_summ.join(flood_summ,
                                     lsuffix='_depth',
                                     rsuffix='_flood')
            all_nodes = all_nodes.join(rpt_df)  # join to the all_nodes df

        all_nodes = all_nodes.join(self.inp.coordinates[['X', 'Y']])

        def nodexy(row):
            if math.isnan(row.X) or math.isnan(row.Y):
                return None
            else:
                return [(row.X, row.Y)]

        xys = all_nodes.apply(lambda r: nodexy(r), axis=1)
        all_nodes = all_nodes.assign(coords=xys)
        all_nodes = all_nodes.rename(index=str)
        self._nodes_df = all_nodes

        return all_nodes
Beispiel #2
0
    def nodes(self, bbox=None, subset=None):
        """
        collect all useful and available data related model nodes and organize
        in one dataframe.
        """

        # check if this has been done already and return that data accordingly
        if self._nodes_df is not None and bbox == self.bbox:
            return self._nodes_df

        # parse out the main objects of this model
        inp = self.inp
        rpt = self.rpt

        # create dataframes of relevant sections from the INP
        juncs_df = create_dataframeINP(inp.path, "[JUNCTIONS]")
        outfalls_df = create_dataframeINP(inp.path, "[OUTFALLS]")
        storage_df = create_dataframeINP(inp.path, "[STORAGE]")

        # concatenate the DFs and keep only relevant cols
        all_nodes = pd.concat([juncs_df, outfalls_df, storage_df])
        cols = ['InvertElev', 'MaxDepth', 'SurchargeDepth', 'PondedArea']
        all_nodes = all_nodes[cols]

        if rpt:
            # add results data if a rpt file was found
            depth_summ = create_dataframeRPT(rpt.path, "Node Depth Summary")
            flood_summ = create_dataframeRPT(rpt.path, "Node Flooding Summary")

            # join the rpt data (index on depth df, suffixes for common cols)
            rpt_df = depth_summ.join(
                flood_summ, lsuffix='_depth', rsuffix='_flood')
            all_nodes = all_nodes.join(rpt_df)  # join to the all_nodes df

        all_nodes = all_nodes.join(self.inp.coordinates[['X', 'Y']])

        def nodexy(row):
            if math.isnan(row.X) or math.isnan(row.Y):
                return None
            else:
                return [(row.X, row.Y)]

        xys = all_nodes.apply(lambda r: nodexy(r), axis=1)
        all_nodes = all_nodes.assign(coords=xys)
        all_nodes = all_nodes.rename(index=str)
        self._nodes_df = all_nodes

        return all_nodes
Beispiel #3
0
    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()
        """

        # create dataframes of relevant sections from the INP
        for ix, sect in enumerate(self.config['inp_sections']):
            if ix == 0:
                df = create_dataframeINP(self.inp.path, sect, comment_cols=False)
            else:
                df_other = create_dataframeINP(self.inp.path, sect, comment_cols=False)
                df = df.join(df_other)

        if self.rpt:
            for rpt_sect in self.config['rpt_sections']:
                df = df.join(create_dataframeRPT(self.rpt.path, rpt_sect))

        # 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)

        return df
Beispiel #4
0
    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()
        """

        # create dataframes of relevant sections from the INP
        for ix, sect in enumerate(self.config['inp_sections']):
            if ix == 0:
                df = create_dataframeINP(self.inp.path, sect, comment_cols=False)
            else:
                df_other = create_dataframeINP(self.inp.path, sect, comment_cols=False)
                df = df.join(df_other)

        if df.empty:
            return df

        # if there is an RPT available, grab relevant sections
        if self.rpt:
            for rpt_sect in self.config['rpt_sections']:
                df = df.join(create_dataframeRPT(self.rpt.path, rpt_sect))

        # 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)

        return df
Beispiel #5
0
    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 = create_dataframeINP(inp.path,
                                          "[CONDUITS]",
                                          comment_cols=False)
        xsections_df = create_dataframeINP(inp.path,
                                           "[XSECTIONS]",
                                           comment_cols=False)
        conduits_df = conduits_df.join(xsections_df)

        if rpt:
            # create a dictionary holding data from an rpt file, if provided
            link_flow_df = create_dataframeRPT(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.InletOffset
        df['DownstreamInvert'] = df.OutletNodeInvert + df.OutletOffset
        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
Beispiel #6
0
    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 = create_dataframeINP(inp.path, "[CONDUITS]", comment_cols=False)
        xsections_df = create_dataframeINP(inp.path, "[XSECTIONS]", comment_cols=False)
        conduits_df = conduits_df.join(xsections_df)

        if rpt:
            # create a dictionary holding data from an rpt file, if provided
            link_flow_df = create_dataframeRPT(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.InletOffset
        df['DownstreamInvert'] = df.OutletNodeInvert + df.OutletOffset
        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
Beispiel #7
0
    def subcatchments(self):
        """
        collect all useful and available data related subcatchments and organize
        in one dataframe.
        """
        subs = create_dataframeINP(self.inp.path, "[SUBCATCHMENTS]")
        subs = subs.drop([';', 'Comment', 'Origin'], axis=1)
        polygons_df = self.inp.polygons

        if self.rpt:
            flw = create_dataframeRPT(
                self.rpt.path, 'Subcatchment Runoff Summary')
            subs = subs.join(flw)

            # more accurate runoff calculations
            subs['RunoffAcFt'] = subs.TotalRunoffIn / 12.0 * subs.Area
            subs['RunoffMGAccurate'] = subs.RunoffAcFt / 3.06888785

        self._subcatchments_df = subs

        return subs
Beispiel #8
0
    def subcatchments(self):
        """
        collect all useful and available data related subcatchments and organize
        in one dataframe.
        """
        subs = create_dataframeINP(self.inp.path, "[SUBCATCHMENTS]")
        subs = subs.drop([';', 'Comment', 'Origin'], axis=1)
        polygons_df = self.inp.polygons

        if self.rpt:
            flw = create_dataframeRPT(self.rpt.path,
                                      'Subcatchment Runoff Summary')
            subs = subs.join(flw)

            # more accurate runoff calculations
            subs['RunoffAcFt'] = subs.TotalRunoffIn / 12.0 * subs.Area
            subs['RunoffMGAccurate'] = subs.RunoffAcFt / 3.06888785

        self._subcatchments_df = subs

        return subs
Beispiel #9
0
def timeseries_join(elements, *models):
    """
    Given a list of element IDs and Model objects, a dataframe is returned
    with the elements' time series data for each model.
    Example:
        df = timeseries_join(elements = ['P1, P2'], model1, model2)
        returns df with index = DateTime and cols = [model1_P1_FlowCFS, model1_P2_FlowCFS,
                                                    model2_P1_FlowCFS, model2_P2_FlowCFS]
    """
    # dfs = [[dataframes.create_dataframeRPT(m.rpt, 'Link Results', el)[['FlowCFS']]
    #         for el in elements] for m in models]
    param_name = 'FlowCFS'  #as named by our dataframe method
    section_name = 'Link Results'  #in the rpt
    dfs = [
        create_dataframeRPT(m.rpt, section_name, elem)[[
            param_name
        ]].rename(columns={
            param_name: '{}_{}_{}'.format(m.inp.name, elem, param_name)
        }) for m in models for elem in elements
    ]

    df = pd.concat(dfs, axis=1)
    return df
Beispiel #10
0
def model_to_networkx(model, drop_cycles=True):
    from swmmio.utils.dataframes import create_dataframeINP, create_dataframeRPT
    '''
    Networkx MultiDiGraph representation of the model
    '''
    from geojson import Point, LineString
    try:
        import networkx as nx
    except ImportError:
        raise ImportError('networkx module needed. get this package here: ',
                          'https://pypi.python.org/pypi/networkx')

    def multidigraph_from_edges(edges, source, target):
        '''
        create a MultiDiGraph from a dataframe of edges, using the row index
        as the key in the MultiDiGraph
        '''
        us = edges[source]
        vs = edges[target]
        keys = edges.index
        data = edges.drop([source, target], axis=1)
        d_dicts = data.to_dict(orient='records')

        G = nx.MultiDiGraph()

        G.add_edges_from(zip(us, vs, keys, d_dicts))

        return G

    # parse swmm model results with swmmio, concat all links into one dataframe
    nodes = model.nodes()
    if model.rpt is not None:
        inflow_cols = [
            'MaxLatInflow', 'MaxTotalInflow', 'LatInflowV', 'TotalInflowV',
            'FlowBalErrorPerc'
        ]
        flows = create_dataframeRPT(model.rpt.path,
                                    "Node Inflow Summary")[inflow_cols]
        nodes = nodes.join(flows)

    conduits = model.conduits()
    links = pd.concat(
        [conduits, model.orifices(),
         model.weirs(),
         model.pumps()], sort=True)
    links['facilityid'] = links.index

    # create a nx.MultiDiGraph from the combined model links, add node data, set CRS
    G = multidigraph_from_edges(links, 'InletNode', target='OutletNode')
    G.add_nodes_from(zip(nodes.index, nodes.to_dict(orient='records')))

    # create geojson geometry objects for each graph element
    for u, v, k, coords in G.edges(data='coords', keys=True):
        if coords:
            G[u][v][k]['geometry'] = LineString(coords)
    for n, coords in G.nodes(data='coords'):
        if coords:
            G.node[n]['geometry'] = Point(coords[0])

    if drop_cycles:
        # remove cycles
        cycles = list(nx.simple_cycles(G))
        if len(cycles) > 0:
            print('cycles detected and removed: {}'.format(cycles))
            G.remove_edges_from(cycles)

    G.graph['crs'] = model.crs
    return G
Beispiel #11
0
def model_to_networkx(model, drop_cycles=True):
    from swmmio.utils.dataframes import create_dataframeINP, create_dataframeRPT
    '''
    Networkx MultiDiGraph representation of the model
    '''
    from geojson import Point, LineString
    try:
        import networkx as nx
    except ImportError:
        raise ImportError('networkx module needed. get this package here: ',
                        'https://pypi.python.org/pypi/networkx')

    def multidigraph_from_edges(edges, source, target):
        '''
        create a MultiDiGraph from a dataframe of edges, using the row index
        as the key in the MultiDiGraph
        '''
        us = edges[source]
        vs = edges[target]
        keys = edges.index
        data = edges.drop([source, target], axis=1)
        d_dicts = data.to_dict(orient='records')

        G = nx.MultiDiGraph()

        G.add_edges_from(zip(us, vs, keys, d_dicts))

        return G

    # parse swmm model results with swmmio, concat all links into one dataframe
    nodes = model.nodes()
    if model.rpt is not None:
        inflow_cols = [
            'MaxLatInflow',
            'MaxTotalInflow',
            'LatInflowV',
            'TotalInflowV',
            'FlowBalErrorPerc']
        flows = create_dataframeRPT(
            model.rpt.path, "Node Inflow Summary")[inflow_cols]
        nodes = nodes.join(flows)

    conduits = model.conduits()
    links = pd.concat([conduits, model.orifices(), model.weirs(), model.pumps()])
    links['facilityid'] = links.index

    # create a nx.MultiDiGraph from the combined model links, add node data, set CRS
    G = multidigraph_from_edges(links, 'InletNode', target='OutletNode')
    G.add_nodes_from(zip(nodes.index, nodes.to_dict(orient='records')))

    # create geojson geometry objects for each graph element
    for u, v, k, coords in G.edges(data='coords', keys=True):
        if coords:
            G[u][v][k]['geometry'] = LineString(coords)
    for n, coords in G.nodes(data='coords'):
        if coords:
            G.node[n]['geometry'] = Point(coords[0])

    if drop_cycles:
        # remove cycles
        cycles = list(nx.simple_cycles(G))
        if len(cycles) > 0:
            print('cycles detected and removed: {}'.format(cycles))
            G.remove_edges_from(cycles)

    G.graph['crs'] = model.crs
    return G