コード例 #1
0
def graph_from_shapefile(path, custom_standards=None, name='unnamed', simplify=True):
    """
    Create Networkx Graph from the shapeFile provided.

    :param path: Path of the shapeFile.
    :param custom_standards: Dict object used to convert non standard properties attributes to standard
    example = {
        "LINK_ID": "osm_id",
        "DIRONSIGN":"oneway"
    }
    json format Key:Value
    where:
        Key is the Field Name from the shapeFile.
        Value is the standard to convert it to.
    See documentation for more.
    :param name: Name of the Graph to be created.(default = unnamed)
    :param simplify: Simplify the graph. (default = True)
    :return: Networkx MultiDiGraph
    """
    geojson = shp2geojson(path, custom_standards)
    json_data = geojson2osm_json(geojson)
    g = ox.create_graph(json_data, name)
    if simplify is True:
        g = ox.simplify_graph(g)
    return g
コード例 #2
0
def graph_from_shapefile(path,
                         in_crs=None,
                         custom_standards=None,
                         name='unnamed',
                         retain_all=False,
                         simplify=True):
    """
    Create Networkx Graph from the shapeFile provided.

    :param path: Path of the shapeFile.
    :param in_crs: CRS of the shapeFile. Should be a string in 'EPSG:{number}' format. (Default = 'EPSG:4326')
    :param custom_standards: Dict object used to convert non standard properties attributes to standard
    example = {
        "LINK_ID": "osm_id",
        "DIRONSIGN":"oneway"
    }
    json format Key:Value
    where:
        Key is the Field Name from the shapeFile.
        Value is the standard to convert it to.
    See documentation for more.
    :param name: Name of the Graph to be created.(default = unnamed)
    :param retain_all: if True, return the entire graph even if it is not connected
    :param simplify: Simplify the graph. (default = True)
    :return: Networkx MultiDiGraph
    """
    geojson = shp2geojson(path, custom_standards)
    if in_crs is not None:
        geojson = coordinate_transform(geojson, in_crs=in_crs)
    json_data = geojson2osm_json(geojson)
    g = ox.create_graph(json_data, name, retain_all=retain_all)
    if simplify is True:
        g = ox.simplify_graph(g)
    return g
コード例 #3
0
 def getRowJson(self, indexes):
     if len(indexes) > 0:
         result = copy.deepcopy(self.json)
         result["elements"] = copy.deepcopy(self.nodes)
         for i in indexes:
             result["elements"] += self.alt[i.row()][2]
         return ox.create_graph([result], retain_all=True)
     else:
         return None
コード例 #4
0
    def updateAlt(self):
        self.alt = []
        self.subgraphs = []

        try:
            G = ox.create_graph([self.json], retain_all=True)
            updatedHeader = frozenset([])
            for nodes in nx.weakly_connected_components(G):
                subgraph = nx.induced_subgraph(G, nodes)
                self.subgraphs.append(subgraph)

                altAppend = {}
                for key in self.allKeys:
                    values = []
                    edges = subgraph.edges(data=True)
                    for edge in edges:
                        values.append(edge[2].get(key))
                    altAppend[key] = frozenset(values)
                    if len(altAppend[key]) == 1 and values[0] is not None:
                        updatedHeader |= frozenset([key])
                self.alt.append(altAppend)
            self.headerItems = list(updatedHeader)
        except ox.errors.EmptyOverpassResponse:
            pass
コード例 #5
0
def graph_from_polygon(polygon,
                       network_type='drive',
                       simplify=True,
                       retain_all=False,
                       truncate_by_edge=False,
                       name='unnamed',
                       timeout=180,
                       memory=None,
                       max_query_area_size=50 * 1000 * 50 * 1000,
                       clean_periphery=True,
                       infrastructure='way["highway"]'):
    """
    Create a networkx graph from OSM data within the spatial boundaries of the
    passed-in shapely polygon.

    Parameters
    ----------
    polygon : shapely Polygon or MultiPolygon
        the shape to get network data within. coordinates should be in units of
        latitude-longitude degrees.
    network_type : string
        what type of street network to get
    simplify : bool
        if true, simplify the graph topology
    retain_all : bool
        if True, return the entire graph even if it is not connected
    truncate_by_edge : bool
        if True retain node if it's outside bbox but at least one of node's
        neighbors are within bbox
    name : string
        the name of the graph
    timeout : int
        the timeout interval for requests and to pass to API
    memory : int
        server memory allocation size for the query, in bytes. If none, server
        will use its default allocation size
    max_query_area_size : float
        max size for any part of the geometry, in square degrees: any polygon
        bigger will get divided up for multiple queries to API
    clean_periphery : bool
        if True (and simplify=True), buffer 0.5km to get a graph larger than
        requested, then simplify, then truncate it to requested spatial extent
    infrastructure : string
        download infrastructure of given type (default is streets (ie, 'way["highway"]') but other
        infrastructures may be selected like power grids (ie, 'way["power"~"line"]'))

    Returns
    -------
    networkx multidigraph
    """

    # verify that the geometry is valid and is a shapely Polygon/MultiPolygon
    # before proceeding
    if not polygon.is_valid:
        raise ValueError('Shape does not have a valid geometry')
    if not isinstance(polygon, (Polygon, MultiPolygon)):
        raise ValueError('Geometry must be a shapely Polygon or MultiPolygon')

    response_jsons = ox.osm_net_download(
        polygon=polygon,
        network_type=network_type,
        timeout=timeout,
        memory=memory,
        max_query_area_size=max_query_area_size,
        infrastructure=infrastructure)

    # create the graph from the downloaded data
    G = ox.create_graph(response_jsons,
                        name=name,
                        retain_all=True,
                        network_type=network_type)
    return G
コード例 #6
0
def graph_from_bbox(north,
                    south,
                    east,
                    west,
                    network_type='drive_main',
                    retain_all=False,
                    truncate_by_edge=False,
                    timeout=180,
                    memory=None,
                    max_query_area_size=50 * 1000 * 50 * 1000,
                    infrastructure='way["highway"]'):
    """
    Create a networkx graph from OSM data within some bounding box.

    Parameters
    ----------
    north : float
        northern latitude of bounding box
    south : float
        southern latitude of bounding box
    east : float
        eastern longitude of bounding box
    west : float
        western longitude of bounding box
    network_type : string
        what type of street network to get
    simplify : bool
        if true, simplify the graph topology
    retain_all : bool
        if True, return the entire graph even if it is not connected
    truncate_by_edge : bool
        if True retain node if it's outside bbox but at least one of node's
        neighbors are within bbox
    name : string
        the name of the graph
    timeout : int
        the timeout interval for requests and to pass to API
    memory : int
        server memory allocation size for the query, in bytes. If none, server
        will use its default allocation size
    max_query_area_size : float
        max size for any part of the geometry, in square degrees: any polygon
        bigger will get divided up for multiple queries to API
    clean_periphery : bool
        if True (and simplify=True), buffer 0.5km to get a graph larger than
        requested, then simplify, then truncate it to requested spatial extent
    infrastructure : string
        download infrastructure of given type (default is streets (ie, 'way["highway"]') but other
        infrastructures may be selected like power grids (ie, 'way["power"~"line"]'))

    Returns
    -------
    networkx multidigraph
    """

    # get the network data from OSM
    response_jsons = ox.osm_net_download(
        north=north,
        south=south,
        east=east,
        west=west,
        network_type=network_type,
        timeout=timeout,
        memory=memory,
        max_query_area_size=max_query_area_size,
        infrastructure=infrastructure)

    G = ox.create_graph(response_jsons,
                        retain_all=retain_all,
                        network_type=network_type)
    # with open('json_osm.txt', 'w') as outfile:
    #     json.dump(response_jsons, outfile)
    return G
コード例 #7
0
def graph_from_jsons(response_jsons,
                     network_type='all_private',
                     simplify=True,
                     retain_all=False,
                     truncate_by_edge=False,
                     name='unnamed',
                     timeout=180,
                     memory=None,
                     max_query_area_size=50 * 1000 * 50 * 1000,
                     clean_periphery=True,
                     infrastructure='way["highway"]'):
    """
    Create a networkx graph from OSM data within the spatial boundaries of the passed-in shapely polygon.
    This is a modified routine from osmnx
    Parameters
    ----------
    response_jsons : list of responses from osmnx
        the shape to get network data within. coordinates should be in units of
        latitude-longitude degrees.
    network_type : string
        what type of street network to get
    simplify : bool
        if true, simplify the graph topology
    retain_all : bool
        if True, return the entire graph even if it is not connected
    truncate_by_edge : bool
        if True retain node if it's outside bbox but at least one of node's
        neighbors are within bbox
    name : string
        the name of the graph
    timeout : int
        the timeout interval for requests and to pass to API
    memory : int
        server memory allocation size for the query, in bytes. If none, server
        will use its default allocation size
    max_query_area_size : float
        max size for any part of the geometry, in square degrees: any polygon
        bigger will get divided up for multiple queries to API
    clean_periphery : bool
        if True (and simplify=True), buffer 0.5km to get a graph larger than
        requested, then simplify, then truncate it to requested spatial extent
    infrastructure : string
        download infrastructure of given type (default is streets (ie, 'way["highway"]') but other
        infrastructures may be selected like power grids (ie, 'way["power"~"line"]'))
    Returns
    -------
    networkx multidigraph
    """

    if clean_periphery and simplify:

        g_buffered = ox.create_graph(response_jsons,
                                     name=name,
                                     retain_all=True,
                                     network_type=network_type)

        # simplify the graph topology
        g = ox.simplify_graph(g_buffered)

        # count how many street segments in buffered graph emanate from each
        # intersection in un-buffered graph, to retain true counts for each
        # intersection, even if some of its neighbors are outside the polygon
        g.graph['streets_per_node'] = ox.count_streets_per_node(
            g, nodes=g.nodes())

    else:

        # create the graph from the downloaded data
        g = ox.create_graph(response_jsons,
                            name=name,
                            retain_all=True,
                            network_type=network_type)

        # simplify the graph topology as the last step. don't truncate after
        # simplifying or you may have simplified out to an endpoint beyond the
        # truncation distance, in which case you will then strip out your entire
        # edge
        if simplify:
            g = ox.simplify_graph(g)

    return g
コード例 #8
0
def analyze_city(boundary, crs, local_edges):
    """Analyze correspondence between Local and OSM bikeways throughout a city.

    Parameters
    ----------
    boundary : :class:`shapely.geometry.Polygon`
        City boundary projected in WGS 84

    crs : epsg coordinate system 
        Local coordinate system in meters (e.g., UTM 10: {'init': 'epsg:26910'})

    local_edges : :class:`geopandas.GeoDataFrame`
        Output from `structure_bikeways_shapefile`

    Returns
    -------
    :obj:`tuple`
        * :class:`pandas.DataFrame`
            Output from `summarize_bikeway_correspondance`
        * :class:`geopandas.GeoDataFrame`
            OSM edges with OSM and local bikeway data attached
    """

    # Define OSM tag filter
    # Importantly, no paths with 'highway':'service' or 'highway':'motorway' tags will be returned
    tag_filter = (
        '["area"!~"yes"]["highway"!~"service|footway|motor|proposed|construction|abandoned|platform|raceway"]'
        '["bicycle"!~"no"]["access"!~"private"]')

    # Download the OSM data
    overpass_jsons = ox.osm_net_download(boundary, custom_filter=tag_filter)
    overpass_json = sp.merge_overpass_jsons(overpass_jsons)

    # Define bikeway columns and associated labels
    bikeway_types = [
        'off_street_path', 'bike_blvd', 'separated_bike_lane', 'bike_lane',
        'shoulder', 'sharrow', 'bike_route'
    ]

    # Parse Overpass JSON into bikeway types
    overpass_parsed = sp.parse_osm_tags(overpass_json,
                                        bikeway_types,
                                        true_value=1,
                                        false_value=0,
                                        none_value=np.nan)

    # Specify attributes to include in graph
    path_tags = (bikeway_types + ['highway'])
    ox.config(useful_tags_path=path_tags)
    # Convert json to graph
    G = ox.create_graph([overpass_parsed])
    # Simply graph by removing all nodes that are not intersections or dead ends
    G = ox.simplify_graph(G, strict=True)
    # Make graph undirected
    G = nx.to_undirected(G)
    # Convert graph to geodataframes
    osm_edges = ox.graph_to_gdfs(G, nodes=False)
    # Project to local coordinate system
    osm_edges = osm_edges.to_crs(crs)

    # Project city boundary to local coordinate system
    boundary, _ = ox.project_geometry(boundary, to_crs=crs)

    # Constrain edges to those intersecting the city boundary polygon
    osm_edges = sp.gdf_intersecting_polygon(osm_edges, boundary)

    # Summarize bikeway values stored in lists
    osm_edges[bikeway_types] = osm_edges[bikeway_types].applymap(
        lambda x: sp.nan_any(x, 1, np.nan))

    # Idenfity largest available highway type
    def largest_highway(highways):
        # Specify highway order,
        # largest (least bikable) to smallest (most bikable)
        highway_order = [
            'trunk', 'primary', 'secondary', 'tertiary', 'unclassified',
            'residential', 'living_street', 'cycleway'
        ]
        highways = sp.listify(highways)
        # Strip '_link' from tags
        highways = [x[:-5] if x[-5:] == '_link' else x for x in highways]
        # If list includes one of these tags, return the biggest one
        ranked_highways = [x for x in highways if x in highway_order]
        if len(ranked_highways) > 0:
            ranks = [highway_order.index(x) for x in ranked_highways]
            return highway_order[min(ranks)]
        # Otherwise, return 'other'
        else:
            return 'other'

    osm_edges['highway'] = osm_edges['highway'].apply(largest_highway)

    # Restrict edges to bikeable highway types
    bikable = [
        'primary', 'secondary', 'tertiary', 'unclassified', 'residential',
        'living_street', 'cycleway'
    ]
    osm_edges = osm_edges[osm_edges['highway'].isin(bikable)].copy()

    # Project local edges to local coordinate system
    local_edges = local_edges.to_crs(crs)

    # Restrict to local edges intersecting the city boundary
    local_edges = sp.gdf_intersecting_polygon(local_edges, boundary)

    # Match local edges to OSM edges
    analysis_columns = bikeway_types + ['geometry']
    # Match dataframes
    osm_matches = sp.match_lines_by_hausdorff(
        sp.select_columns(
            osm_edges, analysis_columns,
            suffix='_osm').rename(columns={'geometry_osm': 'geometry'}),
        sp.select_columns(
            local_edges, analysis_columns,
            suffix='_local').rename(columns={'geometry_local': 'geometry'}),
        constrain_target_features=True,
        distance_tolerance=20,
        azimuth_tolerance=20,
        match_fields=True)

    # Identify local and osm bikeway columns
    joint_bikeway_cols = [
        column for column in osm_matches.columns
        if any(bikeway in column for bikeway in bikeway_types)
    ]

    # Reduce lists to a single single binary value
    osm_matches[joint_bikeway_cols] = osm_matches[joint_bikeway_cols].applymap(
        lambda x: sp.nan_any(x, 1, np.nan))

    # Drop records without a bikeway in either dataset
    osm_matches = osm_matches.dropna(how='all', subset=joint_bikeway_cols)

    # Reclassify NaN values as 0
    osm_matches = osm_matches.fillna(0)

    # Function fo calculate composite bikeways
    def composite_columns(matches, columns, suffix):
        # Select relevent columns
        relevent_columns = sp.select_columns(matches,
                                             [x + suffix for x in columns])
        # Assess whether there are any values of 1 across each row
        return relevent_columns.apply(lambda x: sp.nan_any(x, 1, 0), axis=1)

    # Define exclusive and shared bikeway types
    exclusive_bikeways = ['bike_lane', 'separated_bike_lane']
    shared_bikeways = ['bike_blvd', 'sharrow', 'bike_route']

    # Calculate composite of exclusive bikeways
    osm_matches['exclusive_bikeway_osm'] = composite_columns(
        osm_matches, exclusive_bikeways, '_osm')
    osm_matches['exclusive_bikeway_local'] = composite_columns(
        osm_matches, exclusive_bikeways, '_local')

    # Calculate composite of shared bikeways
    osm_matches['shared_bikeway_osm'] = composite_columns(
        osm_matches, shared_bikeways, '_osm')
    osm_matches['shared_bikeway_local'] = composite_columns(
        osm_matches, shared_bikeways, '_local')

    # Calculate composite of all bikeways
    osm_matches['any_bikeway_osm'] = composite_columns(osm_matches,
                                                       bikeway_types, '_osm')
    osm_matches['any_bikeway_local'] = composite_columns(
        osm_matches, bikeway_types, '_local')

    # Calculate the length of each edge
    osm_matches['length'] = osm_matches['geometry'].apply(lambda x: x.length)

    # Add labels to bikeway types
    bikeway_labels = [
        'Off Street Path', 'Bike Boulevard', 'Separated Bike Lane',
        'Bike Lane', 'Shoulder', 'Sharrow', 'Bike Route'
    ]
    bikeway_labels = OrderedDict(zip(bikeway_types, bikeway_labels))
    # Add labels for composite bikeway types
    bikeway_labels.update({'exclusive_bikeway': 'Exclusive'})
    bikeway_labels.update({'shared_bikeway': 'Shared'})
    bikeway_labels.update({'any_bikeway': 'Any'})

    # Calculate summaries
    summaries = summarize_bikeway_correspondance(osm_matches, bikeway_labels)

    return summaries, osm_matches