예제 #1
0
def read_matsim_network(path_to_network: str, epsg: str):
    """
    Reads MATSim's network.xml to genet.Network object
    :param path_to_network: path to MATSim's network.xml file
    :param epsg: projection for the network, e.g. 'epsg:27700'
    :return: genet.Network object
    """
    n = core.Network(epsg=epsg)
    n.graph, n.link_id_mapping, duplicated_nodes, duplicated_links = \
        matsim_reader.read_network(path_to_network, n.transformer)
    n.graph.graph['name'] = 'Network graph'
    n.graph.graph['crs'] = n.epsg
    if 'simplified' not in n.graph.graph:
        n.graph.graph['simplified'] = False

    for node_id, duplicated_node_attribs in duplicated_nodes.items():
        for duplicated_node_attrib in duplicated_node_attribs:
            n.change_log.remove(
                object_type='node',
                object_id=node_id,
                object_attributes=duplicated_node_attrib
            )
    for link_id, reindexed_duplicated_links in duplicated_links.items():
        for duplicated_link in reindexed_duplicated_links:
            n.change_log.modify(
                object_type='link',
                old_id=link_id,
                old_attributes=n.link(duplicated_link),
                new_id=duplicated_link,
                new_attributes=n.link(duplicated_link)
            )
    return n
예제 #2
0
def read_json_network(network_path: str, epsg: str):
    """
    Reads Network graph from JSON file.
    :param network_path: path to json or geojson network file
    :param epsg: projection for the network, e.g. 'epsg:27700'
    :return: genet.Network object
    """
    logging.info(f'Reading Network from {network_path}')
    with open(network_path) as json_file:
        json_data = json.load(json_file)
    for node, data in json_data['nodes'].items():
        try:
            del data['geometry']
        except KeyError:
            pass

    for link, data in json_data['links'].items():
        try:
            data['geometry'] = spatial.decode_polyline_to_shapely_linestring(data['geometry'])
        except KeyError:
            pass
        try:
            data['modes'] = set(data['modes'].split(','))
        except KeyError:
            pass

    n = core.Network(epsg=epsg)
    n.add_nodes(json_data['nodes'])
    n.add_links(json_data['links'])
    n.change_log = change_log.ChangeLog()
    return n
예제 #3
0
def read_geojson_network(nodes_path: str, links_path: str, epsg: str):
    """
    Reads Network graph from JSON file.
    :param nodes_path: path to geojson network nodes file
    :param links_path: path to geojson network links file
    :param epsg: projection for the network, e.g. 'epsg:27700'
    :return: genet.Network object
    """
    logging.info(f'Reading Network nodes from {nodes_path}')
    nodes = gpd.read_file(nodes_path)
    nodes = nodes.drop('geometry', axis=1)
    nodes['id'] = nodes['id'].astype(int).astype(str)
    nodes = nodes.set_index('id', drop=False)
    if 'index' in nodes.columns:
        nodes = nodes.drop('index', axis=1)

    logging.info(f'Reading Network links from {links_path}')
    links = gpd.read_file(links_path).to_crs(epsg)
    links['modes'] = links['modes'].apply(lambda x: set(x.split(',')))
    links['id'] = links['id'].astype(int).astype(str)
    links = links.set_index('id', drop=False)
    if 'index' in links.columns:
        links = links.drop('index', axis=1)

    n = core.Network(epsg=epsg)
    n.add_nodes(nodes.T.to_dict())
    n.add_links(links.T.to_dict())
    n.change_log = change_log.ChangeLog()
    return n
예제 #4
0
def read_osm(osm_file_path, osm_read_config, num_processes: int = 1, epsg=None):
    """
    Reads OSM data into a graph of the Network object
    :param osm_file_path: path to .osm or .osm.pbf file
    :param osm_read_config: config file (see configs folder in genet for examples) which informs for example which
    highway types to read (in case of road network) and what modes to assign to them
    :param num_processes: number of processes to split parallelisable operations across
    :param epsg: projection for the output Network, e.g. 'epsg:27700'. If not provided, defaults to epsg:4326
    :return: genet.Network object
    """
    if epsg is None:
        epsg = 'epsg:4326'
    config = osm_reader.Config(osm_read_config)
    n = core.Network(epsg)
    nodes, edges = osm_reader.generate_osm_graph_edges_from_file(
        osm_file_path, config, num_processes)

    nodes_and_attributes = parallel.multiprocess_wrap(
        data=nodes,
        split=parallel.split_dict,
        apply=osm_reader.generate_graph_nodes,
        combine=parallel.combine_dict,
        epsg=epsg,
        processes=num_processes
    )
    reindexing_dict, nodes_and_attributes = n.add_nodes(nodes_and_attributes, ignore_change_log=True)

    edges_attributes = parallel.multiprocess_wrap(
        data=edges,
        split=parallel.split_list,
        apply=osm_reader.generate_graph_edges,
        combine=parallel.combine_list,
        reindexing_dict=reindexing_dict,
        nodes_and_attributes=nodes_and_attributes,
        config_path=osm_read_config,
        processes=num_processes
    )
    n.add_edges(edges_attributes, ignore_change_log=True)

    logging.info('Deleting isolated nodes which have no edges.')
    n.remove_nodes(list(nx.isolates(n.graph)))
    return n
예제 #5
0
def read_csv(path_to_network_nodes: str, path_to_network_links: str, epsg: str):
    """
    Reads CSV data into a genet.Network object
    :param path_to_network_nodes: CSV file describing nodes. Should at least include columns:
    - id: unique ID for the node
    - x: spatial coordinate in given epsg
    - y: spatial coordinate in given epsg
    :param path_to_network_links: CSV file describing links.
    Should at least include columns:
    - from - source Node ID
    - to - target Node ID
    Optional columns, but strongly encouraged
    - id - unique ID for link
    - length - link length in metres
    - freespeed - meter/seconds speed
    - capacity - vehicles/hour
    - permlanes - number of lanes
    - modes - set of modes
    :param epsg: projection for the network, e.g. 'epsg:27700'
    :return: genet.Network object
    """
    logging.info(f'Reading nodes from {path_to_network_nodes}')
    df_nodes = pd.read_csv(path_to_network_nodes)
    if {'index', 'id'}.issubset(set(df_nodes.columns)):
        df_nodes = df_nodes.drop('index', axis=1)
    elif 'id' not in df_nodes.columns:
        raise NetworkSchemaError('Expected `id` column in the nodes.csv is missing. This need to be the IDs to which '
                                 'links.csv refers to in `from` and `to` columns.')
    df_nodes['id'] = df_nodes['id'].astype(int).astype(str)
    df_nodes = df_nodes.set_index('id', drop=False)
    try:
        df_nodes = df_nodes.drop('geometry', axis=1)
    except KeyError:
        pass

    logging.info(f'Reading links from {path_to_network_nodes}')
    df_links = pd.read_csv(path_to_network_links)
    if {'index', 'id'}.issubset(set(df_links.columns)):
        df_links = df_links.drop('index', axis=1)
    elif 'id' not in df_links.columns:
        if 'index' in df_links.columns:
            if not df_links['index'].duplicated().any():
                df_links['id'] = df_links['index']
            else:
                df_links = df_links.drop('index', axis=1)
        else:
            df_links['id'] = range(len(df_links))

    df_links['id'] = df_links['id'].astype(int).astype(str)
    df_links['from'] = df_links['from'].astype(int).astype(str)
    df_links['to'] = df_links['to'].astype(int).astype(str)
    df_links = df_links.set_index('id', drop=False)
    # recover encoded geometry
    try:
        df_links['geometry'] = df_links['geometry'].apply(lambda x: spatial.decode_polyline_to_shapely_linestring(x))
    except KeyError:
        pass
    df_links['attributes'] = _literal_eval_col(df_links['attributes'])
    df_links['modes'] = _literal_eval_col(df_links['modes'])

    n = core.Network(epsg=epsg)
    n.add_nodes(df_nodes.T.to_dict())
    n.add_links(df_links.T.to_dict())
    n.change_log = change_log.ChangeLog()
    return n