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