Beispiel #1
0
def load_graph(graph_name):
    folder_path = path.join('graphs', graph_name)

    graph_data = deserialize_dict(
        file_path=path.join(folder_path, 'graph_data.pkl.gz'))
    graph = ox.load_graphml(filename='graph.graphml', folder=folder_path)
    # graph = nx.MultiDiGraph(nx.read_graphml(path.join(folder_path, 'graph.graphml'), node_type=int))

    if not nx.is_strongly_connected(graph):
        graph = ox.get_largest_component(graph, strongly=True)

    node_mapping = {node: i for i, node in enumerate(sorted(graph.nodes()))}
    graph = nx.relabel_nodes(graph, node_mapping)

    # Ensure nodes and edges are ordered consistently
    G = nx.MultiDiGraph()
    for node, data in sorted(graph.nodes(data=True), key=lambda t: t[0]):
        data['demand'] = 0
        G.add_node(node, **data)

    for src, dst, data in sorted(graph.edges(data=True),
                                 key=lambda t: (t[0], t[1])):
        # Remove parallel edges and self-loops
        if src == dst or (src in G and dst in G[src]):
            continue

        # Dummy data for compatibility with plotter
        data['zero'] = 0
        G.add_edge(src, dst, key=0, **data)

    G.graph['crs'] = graph_data['crs']
    G.graph['name'] = graph_data['name']
    G = ox.project_graph(G, to_crs=graph_data['crs'])

    return G.to_directed()
Beispiel #2
0
def save_graph(target, graph_name, distance=1000, is_address=True):

    # Load graph from OSM
    if is_address:
        graph = ox.graph_from_address(address=target,
                                      distance=distance,
                                      network_type='drive')
    else:
        graph = ox.graph_from_place(query=target, network_type='drive')

    # Project graph
    graph_proj = ox.project_graph(graph)

    folder_path = path.join('graphs', graph_name)
    if not path.exists(folder_path):
        mkdir(folder_path)

    graph_data = graph_proj.graph
    serialize_dict(dictionary=graph_data,
                   file_path=path.join(folder_path, 'graph_data.pkl.gz'))

    # We make the graph strongly connected to ensure that any combination of source / sink
    # constitutes a valid problem
    graph_component = ox.get_largest_component(graph_proj,
                                               strongly=True).to_directed()

    # Save pictures of the graph
    plot_road_graph(graph_component,
                    graph_name=graph_name,
                    file_path=path.join(folder_path, 'graph'))

    # Save graph
    ox.save_graphml(graph_component,
                    filename='graph.graphml',
                    folder=folder_path,
                    gephi=True)

    # Save a selection of graph-wide stats.
    stats_file = path.join(folder_path, 'stats.csv')
    delete_if_exists(stats_file)

    n_nodes = graph_component.number_of_nodes()
    n_edges = graph_component.number_of_edges()
    avg_in_deg = np.average([d for _, d in graph_component.in_degree()])
    avg_out_deg = np.average([d for _, d in graph_component.out_degree()])
    diam = nx.diameter(graph_component)

    append_row_to_log(['Number of Nodes', n_nodes], stats_file)
    append_row_to_log(['Number of Edges', n_edges], stats_file)
    append_row_to_log(['Average In Degree', avg_in_deg], stats_file)
    append_row_to_log(['Average Out Degree', avg_out_deg], stats_file)
    append_row_to_log(['Diameter', diam], stats_file)

    cleaned_target = target.replace('\"', '').replace('\'',
                                                      '').replace(',', '')
    query = '{0}; Dist: {1}'.format(cleaned_target,
                                    distance) if is_address else cleaned_target
    append_row_to_log(['Query', query], stats_file)

    return graph_component
Beispiel #3
0
def create_graph(response_jsons,
                 name='unnamed',
                 retain_all=True,
                 bidirectional=False):
    """
    Create a networkx graph from Overpass API HTTP response objects.
    Parameters
    ----------
    response_jsons : list
        list of dicts of JSON responses from from the Overpass API
    name : string
        the name of the graph
    retain_all : bool
        if True, return the entire graph even if it is not connected
    bidirectional : bool
        if True, create bidirectional edges for one-way streets
    Returns
    -------
    networkx multidigraph
    """

    # make sure we got data back from the server requests
    elements = []

    elements.extend(response_jsons['elements'])
    if len(elements) < 1:
        raise ox.EmptyOverpassResponse(
            'There are no data elements in the response JSON objects')

    # create the graph as a MultiDiGraph and set the original CRS to default_crs
    G = nx.MultiDiGraph(name=name, crs=ox.settings.default_crs)

    # extract nodes and paths from the downloaded osm data
    nodes = {}
    paths = {}

    nodes_temp, paths_temp = parse_osm_nodes_paths(response_jsons)
    for key, value in nodes_temp.items():
        nodes[key] = value
    for key, value in paths_temp.items():
        paths[key] = value

    # add each osm node to the graph
    for node, data in nodes.items():
        G.add_node(node, **data)

    # add each osm way (aka, path) to the graph
    G = ox.add_paths(G, paths, bidirectional=bidirectional)

    # retain only the largest connected component, if caller did not
    # set retain_all=True
    if not retain_all:
        G = ox.get_largest_component(G)

    # add length (great circle distance between nodes) attribute to each edge to
    # use as weight
    if len(G.edges) > 0:
        G = ox.add_edge_lengths(G)

    return G
Beispiel #4
0
def simplify_graph_remove_unimportant_roads(G_original: nx.MultiDiGraph):
    '''
    Removes all unimportant roads.
    :param G_original: networkx graph object.
    :return: SImplified networkx graph object.
    '''
    G = G_original.copy()
    to_remove = []
    for e in list(G.edges(data=True, keys=True)):
        u, v, i, info = e
        highway_type = info['highway']
        if check_highway_type_is_to_be_removed(
                highway_type) and info['length'] < 1000:
            to_remove.append((u, v, i))

    G.remove_edges_from(to_remove)
    G = ox.remove_isolated_nodes(G)
    # print(get_all_types(G))

    G_component = ox.get_largest_component(G, strongly=True)

    print_graph_info(G_original)
    print_graph_info(G)
    print_graph_info(G_component)

    return G_component
# filter way types
types = [
    'motorway', 'motorway_link', 'trunk', 'trunk_link', 'primary',
    'primary_link', 'secondary', 'secondary_link', 'tertiary', 'tertiary_link',
    'unclassified', 'road'
]

minor_streets = [(u, v, k) for u, v, k, d in G.edges(keys=True, data=True)
                 if d['highway'] not in types]

# remove minor streets and retain only the largest connected component subgraph
G_ter = G
G_ter.remove_edges_from(minor_streets)
G_ter = ox.remove_isolated_nodes(G_ter)
G_ter_connected = ox.get_largest_component(G_ter, strongly=True)

# then simplify the graph now that we have only the edge types we want
G_ter_simp = ox.simplify_graph(G_ter_connected, strict=True)

# create a unique ID for each edge because osmid can
# hold multiple values due to topology simplification
i = 0
for u, v, k, d in G_ter_simp.edges(data=True, keys=True):
    d['uniqueid'] = i
    i += 1

# convert to two-way
H = ox.get_undirected(G_ter_simp)

# save graph as OSM