示例#1
0
def build_network(settings):
    """
    Build a Pandana network from CSV files
    """

    logger.info('building pandana network')
    network_settings_file = settings['network_settings_file']
    if not network_settings_file:
        logger.error("Please specify 'network_settings_file' in settings")
        return

    network_settings = config.read_model_settings(network_settings_file)
    logger.debug('using settings %s' % network_settings)

    nodes = pd.read_csv(config.data_file_path(network_settings['nodes']))
    links = pd.read_csv(config.data_file_path(network_settings['links']))

    nodes.index = nodes[network_settings['nodes-id']]

    network = pdna.Network(nodes[network_settings['nodes-x']],
                           nodes[network_settings['nodes-y']],
                           links[network_settings['links-a']],
                           links[network_settings['links-b']],
                           links[[network_settings['links-impedance']]],
                           twoway=network_settings['twoway'])

    network.save_hdf5(config.output_file_path('pandana_network.h5'))

    return network
示例#2
0
 def build_networkwalk():
     nodeswalk = pd.read_csv(d + 'bayarea_walk_nodes.csv') \
         .set_index('osmid')
     edgeswalk = pd.read_csv(d + 'bayarea_walk_edges.csv')
     netwalk = pdna.Network(nodeswalk.x, nodeswalk.y, edgeswalk.u, \
                            edgeswalk.v, edgeswalk[['length']], twoway=True)
     netwalk.precompute(2500)
     return netwalk
示例#3
0
def build_networks(settings):
    name = settings['build_networks']['name']
    st = pd.HDFStore(os.path.join(misc.data_dir(), name), "r")
    nodes, edges = st.nodes, st.edges
    net = pdna.Network(nodes["x"], nodes["y"], edges["from"], edges["to"],
                       edges[["weight"]])
    net.precompute(settings['build_networks']['max_distance'])
    return net
示例#4
0
 def build_networksmall():
     nodessmall = pd.read_csv(d + 'bay_area_tertiary_strongly_nodes.csv') \
         .set_index('osmid')
     edgessmall = pd.read_csv(d + 'bay_area_tertiary_strongly_edges.csv')
     netsmall = pdna.Network(nodessmall.x, nodessmall.y, edgessmall.u, \
                             edgessmall.v, edgessmall[['length']], twoway=False)
     netsmall.precompute(25000)
     return netsmall
示例#5
0
 def build_networkbeam():
     nodesbeam = pd.read_csv(d + 'physsim-network-nodes.csv') \
         .set_index('id')
     edgesbeam = pd.read_csv(d + 'physsim-network-links.csv')
     netbeam = pdna.Network(
         nodesbeam['x'], nodesbeam['y'], edgesbeam['from'],
         edgesbeam['to'], edgesbeam[['travelTime']], twoway=False)
     netbeam.precompute(7200)
     return netbeam
示例#6
0
def build_networks(parcels, net_store):
    st = net_store
    nodes, edges = st.nodes, st.edges
    net = pdna.Network(nodes["x"], nodes["y"], edges["from"], edges["to"],
                       edges[["weight"]])
    net.precompute(3000)
    orca.add_injectable("net", net)

    p = parcels.to_frame(parcels.local_columns)
    p['node_id'] = net.get_node_ids(p['x'], p['y'])
    orca.add_table("parcels", p)
示例#7
0
def build_networks(parcels):
    st = pd.HDFStore(os.path.join(misc.data_dir(), "osm_sandag.h5"), "r")
    nodes, edges = st.nodes, st.edges
    net = pdna.Network(nodes["x"], nodes["y"], edges["from"], edges["to"],
                       edges[["weight"]])
    net.precompute(3000)
    orca.add_injectable("net", net)

    p = parcels.to_frame(parcels.local_columns)
    p['node_id'] = net.get_node_ids(p['x'], p['y'])
    orca.add_table("parcels", p)
示例#8
0
 def build_networkbeam(nodesbeam, edgesbeam):
     nodesbeam, edgesbeam = nodesbeam.to_frame(), edgesbeam.to_frame()
     print('Number of nodes is %s.' % len(nodesbeam))
     print('Number of edges is %s.' % len(edgesbeam))
     netbeam = pdna.Network(nodesbeam['lon'],
                            nodesbeam['lat'],
                            edgesbeam['from'],
                            edgesbeam['to'],
                            edgesbeam[['traveltime']],
                            twoway=False)
     netbeam.precompute(3600)
     return netbeam
示例#9
0
 def build_networkwalk(nodeswalk, edgeswalk):
     nodeswalk, edgeswalk = nodeswalk.to_frame(), edgeswalk.to_frame()
     print('Number of nodes is %s.' % len(nodeswalk))
     print('Number of edges is %s.' % len(edgeswalk))
     netwalk = pdna.Network(nodeswalk.x,
                            nodeswalk.y,
                            edgeswalk.u,
                            edgeswalk.v,
                            edgeswalk[['length']],
                            twoway=True)
     netwalk.precompute(5000)
     return netwalk
def graph_to_pandananet(gdf_edges, gdf_nodes):

    twoway = list(~gdf_edges['oneway'].values)

    pdnet = pdna.Network(gdf_nodes['x'],
                         gdf_nodes['y'],
                         gdf_edges['u'],
                         gdf_edges['v'],
                         gdf_edges[["time_to_traverse"]],
                         twoway=twoway)

    return pdnet
示例#11
0
def get_osm_network(geodataframe, maxdist=5000, quiet=True, **kwargs):
    """Download a street network from OSM.

    Parameters
    ----------
    geodataframe : geopandas.GeoDataFrame
        geopandas.GeoDataFrame of the study area.
        Coordinate system should be in WGS84
    maxdist : int
        Total distance (in meters) of the network queries you may need.
        This is used to buffer the network to ensure theres enough to satisfy
        your largest query, otherwise there may be edge effects.
    quiet: bool
        If True, diagnostic messages from urbanaccess will be suppressed
    **kwargs : dict
        additional kwargs passed through to
        urbanaccess.ua_network_from_bbox

    Returns
    -------
    pandana.Network
        A pandana Network instance for use in accessibility calculations or
        spatial segregation measures that include a distance decay

    """
    try:
        import pandana as pdna
        from urbanaccess.osm.load import ua_network_from_bbox
    except ImportError:
        raise ImportError(
            "You need pandana and urbanaccess to work with segregation's network module\n"
            "You can install them with  `pip install urbanaccess pandana` "
            "or `conda install -c udst pandana urbanaccess`")

    gdf = geodataframe.copy()
    gdf = gdf.to_crs(gdf.estimate_utm_crs())
    gdf = gdf.buffer(maxdist)
    bounds = gdf.to_crs(epsg=4326).total_bounds

    if quiet:
        print('Downloading data from OSM. This may take awhile.')
        with _HiddenPrints():
            net = ua_network_from_bbox(bounds[1], bounds[0], bounds[3],
                                       bounds[2], **kwargs)
    else:
        net = ua_network_from_bbox(bounds[1], bounds[0], bounds[3], bounds[2],
                                   **kwargs)
    print("Building network")
    network = pdna.Network(net[0]["x"], net[0]["y"], net[1]["from"],
                           net[1]["to"], net[1][["distance"]])

    return network
示例#12
0
def get_network(geodataframe, maxdist=5000, quiet=True, **kwargs):
    """Download a street network from OSM.

    Parameters
    ----------
    geodataframe : geopandas.GeoDataFrame
        geopandas.GeoDataFrame of the study area.
    maxdist : int
        Total distance (in meters) of the network queries you may need.
        This is used to buffer the network to ensure theres enough to satisfy
        your largest query, otherwise there may be edge effects.
    **kwargs : dict
        additional kwargs passed through to
        urbanaccess.ua_network_from_bbox

    Returns
    -------
    pandana.Network
        A pandana Network instance for use in accessibility calculations or
        spatial segregation measures that include a distance decay

    Examples
    -------
    Examples should be written in doctest format, and
    should illustrate how to use the function/class.
    >>>

    """
    gdf = geodataframe.copy()

    assert gdf.crs == {
        'init': 'epsg:4326'
    }, "geodataframe must be in epsg 4326"

    gdf = project_gdf(gdf)
    gdf = gdf.buffer(maxdist)
    bounds = gdf.to_crs(epsg=4326).total_bounds

    if quiet:
        print('Downloading data from OSM. This may take awhile.')
        with _HiddenPrints():
            net = ua_network_from_bbox(bounds[1], bounds[0], bounds[3],
                                       bounds[2], **kwargs)
    else:
        net = ua_network_from_bbox(bounds[1], bounds[0], bounds[3], bounds[2],
                                   **kwargs)
    print("Building network")
    network = pdna.Network(net[0]["x"], net[0]["y"], net[1]["from"],
                           net[1]["to"], net[1][["distance"]])

    return network
示例#13
0
def sample_osm(request):
    store = pd.HDFStore(
        os.path.join(os.path.dirname(__file__), 'osm_sample.h5'), "r")
    nodes, edges = store.nodes, store.edges
    net = pdna.Network(nodes.x, nodes.y, edges["from"], edges.to,
                       edges[["weight"]])

    net.precompute(500)

    def fin():
        store.close()
    request.addfinalizer(fin)

    return net
def distance_to_points(centroids, points_of_interest, output_filename):
    data_dir = "data"
    output_dir = "output"

    # OS Open Road Nodes and Links
    dfNodes = pd.read_csv(os.path.join(data_dir, "OS Open Road Nodes.csv"))
    dfLinks = pd.read_csv(os.path.join(data_dir, "OS Open Road Links.csv"))
    dfNodes.drop_duplicates(inplace=True)
    dfNodes.set_index('identifier', inplace=True)

    # ---- Compute Distances ----
    # Get largest connected component
    edges = dfLinks.loc[:,['startNode','endNode','length']].values
    G = nx.Graph()
    G.add_weighted_edges_from(edges)
    largest_connected_component = sorted(nx.connected_components(G), key = len, reverse=True)[0]

    # Clean up to save memory
    G = None
    edges = None

    # Create pandana network. It's much faster for nearest point-of-interest analysis
    # Filter nodes and edges to just include those in the largest connected componet
    dfLinksLCC = dfLinks.loc[(dfLinks['startNode'].isin(largest_connected_component)) & (dfLinks['endNode'].isin(largest_connected_component))]
    dfNodesLCC = dfNodes.loc[largest_connected_component]
    net=pdna.Network(dfNodesLCC["x"], dfNodesLCC["y"], dfLinksLCC["startNode"], dfLinksLCC["endNode"], dfLinksLCC[["length"]])

    # Get the nearest three points of interest
    search_distance = 200000
    net.set_pois("points", search_distance, 3, points_of_interest.geometry.x, points_of_interest.geometry.y)
    dfNear = net.nearest_pois(search_distance, "points", num_pois=3, include_poi_ids=True)

    # ---- LSOA Computations ----
    # Get just the LSOA centroids and their nearest points
    lsoa_nodes = net.get_node_ids(centroids.X, centroids.Y)
    lsoaComps = dfNear.loc[lsoa_nodes]

    # Include LSOA codes
    centroids['lsoa_nodes'] = lsoa_nodes

    # Merge network distances and LSOA data
    lsoaComps.reset_index(inplace=True)
    lsoaComps = pd.merge(lsoaComps, centroids, left_on = 'identifier', right_on = 'lsoa_nodes', how = 'outer', indicator = True)

    # Wrangle
    lsoaComps['mean_distance_nearest_three_points'] = lsoaComps.loc[:,[1,2,3]].mean(axis = 1)

    # Write
    lsoaComps.to_csv(os.path.join(output_dir, output_filename), index=False)
示例#15
0
def project_network(network, output_crs=None, input_crs=4326):
    """Reproject a pandana.Network object into another coordinate system

    Parameters
    ----------
    network : pandana.Network
        an instantiated pandana Network object
    input_crs : int, optional
        the coordinate system used in the Network.node_df dataframe. Typically
        these data are collected in Lon/Lat, so the default 4326
    output_crs : int, str, or pyproj.crs.CRS, required
        EPSG code or pyproj.crs.CRS object of the output coordinate system

    Returns
    -------
    pandana.Network
        an initialized pandana.Network with 'x' and y' values represented
        by coordinates in the specified CRS
    """
    try:
        import pandana as pdna
    except ImportError:
        raise ImportError(
            "You need pandana and urbanaccess to work with segregation's network module\n"
            "You can install them with  `pip install urbanaccess pandana` "
            "or `conda install -c udst pandana urbanaccess`"
        )

    assert output_crs, "You must provide an output CRS"

    #  take original x,y coordinates and convert into geopandas.Series, then reproject
    nodes = _reproject_osm_nodes(network.nodes_df, input_crs, output_crs)

    #  reinstantiate the network (needs to rebuild the tree)
    net = pdna.Network(
        node_x=nodes["x"],
        node_y=nodes["y"],
        edge_from=network.edges_df["from"],
        edge_to=network.edges_df["to"],
        edge_weights=network.edges_df[network.impedance_names],
        twoway=network._twoway,
    )
    return net
示例#16
0
def get_osm_network(zone_data, settings):
    """
    Retrieve Pandana network from Open Street Maps
    """

    logger.info('getting osm network')
    zones_df = zone_data.to_frame()

    miles = settings.get('distance_units') == 'miles'
    # distance to degrees: 111 km = 69 miles = 1 degree of long (y), 3mi = 0.043
    conversion = 69 if miles else 111 * 1000
    buffer = settings.get('max_dist') / conversion
    xmin = min(zones_df[settings['zones_lon']]) - buffer
    xmax = max(zones_df[settings['zones_lon']]) + buffer
    ymin = min(zones_df[settings['zones_lat']]) - buffer
    ymax = max(zones_df[settings['zones_lat']]) + buffer
    logger.debug('bounding box: %s, %s, %s, %s' %
                 (str(ymin), str(xmin), str(ymax), str(xmax)))

    # default type=walk, which excludes freeways
    nodes, edges = osm.network_from_bbox(lat_min=ymin,
                                         lng_min=xmin,
                                         lat_max=ymax,
                                         lng_max=xmax,
                                         two_way=True,
                                         network_type='walk')

    if miles:
        logger.info('converting network distance units to miles...')
        edges[['distance']] = edges[['distance']] / 1609.34

    network = pdna.Network(nodes['x'], nodes['y'], edges['from'], edges['to'],
                           edges[['distance']])

    print(edges.head())
    print(edges[['distance']])
    network.save_hdf5(config.output_file_path('pandana_network.h5'))

    return network
示例#17
0
def create_pdna_net(gdf_nodes, gdf_edges, predistance=500):
    """
    Create pandana network to prepare for calculating the accessibility to destinations
    The network is comprised of a set of nodes and edges.

    Parameters
    ----------
    gdf_nodes: GeoDataFrame
    gdf_edges: GeoDataFrame
    predistance: int
        the distance of search (in meters), default is 500 meters

    Returns
    -------
    pandana network
    """
    # Defines the x attribute for nodes in the network
    gdf_nodes["x"] = gdf_nodes["geometry"].apply(lambda x: x.x)
    # Defines the y attribute for nodes in the network (e.g. latitude)
    gdf_nodes["y"] = gdf_nodes["geometry"].apply(lambda x: x.y)
    # Defines the node id that begins an edge
    gdf_edges["from"] = gdf_edges["u"].astype(np.int64)
    # Defines the node id that ends an edge
    gdf_edges["to"] = gdf_edges["v"].astype(np.int64)
    # Define the distance based on OpenStreetMap edges
    gdf_edges["length"] = gdf_edges["length"].astype(float)

    gdf_nodes["id"] = gdf_nodes["osmid"].astype(np.int64)
    gdf_nodes.set_index("id", inplace=True, drop=False)
    # Create the transportation network in the city
    # Typical data would be distance based from OSM or travel time from GTFS transit data
    net = pdna.Network(gdf_nodes["x"], gdf_nodes["y"], gdf_edges["from"],
                       gdf_edges["to"], gdf_edges[["length"]])
    # Precomputes the range queries (the reachable nodes within this maximum distance)
    # so that aggregations don’t perform the network queries unnecessarily
    net.precompute(predistance + 10)
    return net
示例#18
0
    def construct_network(self):

        # Get all edges
        query = f"SELECT * FROM {self.schema}.{self.edge_table_name}"
        edge_gdf = self.db.query_as_geo_df(query)

        # Get all nodes
        node_query = f"""
            SELECT sw_node_id AS node_id,
                ST_X(st_transform(geom, 4326)) as x,
                ST_Y(st_transform(geom, 4326)) as y,
                geom
            FROM {self.schema}.sw_nodes
        """
        node_gdf = self.db.query_as_geo_df(node_query)

        # Force the ID columns in the edge gdf to integer
        for col in ["start_id", "end_id"]:
            edge_gdf[col] = edge_gdf[col].astype(int)

        # Set the index of the NODE gdf to the uid column
        node_gdf.set_index('node_id', inplace=True)

        # Build the pandana network
        network = pdna.Network(node_gdf["x"],
                               node_gdf["y"],
                               edge_gdf["start_id"],
                               edge_gdf["end_id"],
                               edge_gdf[["minutes"]],
                               twoway=True)

        network.precompute(self.max_minutes)

        # Save the network and geodataframes within the object
        self.network = network
        self.edge_gdf = edge_gdf
        self.node_gdf = node_gdf
示例#19
0
import geopandas as gpd
import pandana as pdna
roads = gpd.read_file("/home/cuip/edges/edges.shp")
stops = gpd.read_file("/home/cuip/Archive/Stops.shp")
net= pdna.Network(stops["Latitude"], stops["Longitude"], roads["from"], roads["to"],
                 roads[["length"]])
net.precompute(420)
net.set_pois(stops, 420, 10, stops.Latitude, stops.Longitude)
net.nearest_pois(420, stops, num_pois=10)
示例#20
0
def test_workflow():

    # helper functions
    def _parse_wkt(s):
        """Parse wkt and ewkt strings into shapely shapes.

        For ewkt (the PostGIS extension to wkt), the SRID indicator is removed.
        """
        if s.startswith('SRID'):
            s = s[s.index(';') + 1:]
        return shapely.wkt.loads(s)

    long_dash = ''.join(['-' for n in range(25)])
    def update_status(custom_note='', clarify=False):
        for item in ['\n', long_dash, custom_note]:
            print(item)


    # let's find transit providers in Madison, WI
    search_results = urbanaccess.gtfsfeeds.search(search_text='madison')

    # =============
    # Section break
    # =============
    update_status(('We just queried for transit providers with UA. '
                    'Next, we will specify a transit resource to download.'))

    # add a feed to the gtfs to include in the analysis
    feeds = urbanaccess.gtfsfeeds.feeds
    name = 'madison'
    # Note: query suggests: http://www.cityofmadison.com/metro/gtfs/mmt_gtfs.zip
    #       but this address is currently is 404'ing (04-16-2017)
    #       ...as a result, using link below which _does_ work in the meantime
    url = 'http://www.gtfs-data-exchange.com/agency/city-of-madison/latest.zip'
    new_feed =  {name:url}
    feeds.add_feed(new_feed)

    # download the feed, will be placed in folders within data/gtfsfeed_text
    # according to the dict key name
    urbanaccess.gtfsfeeds.download()

    # =============
    # Section break
    # =============
    update_status(('Next, we need to load the feeds into a Pandas DataFrame.'))

    # now that we have saved the raw gtfs data, we need to load it in
    gtfsfeed_path = None # use default gtfs save location
    validation = True
    verbose = True
    bbox = (-89.441414,43.047314,-89.325371,43.129553)
    remove_stops_outsidebbox = True
    append_definitions = True
    # updates these attributes: stops, routes, trips, stop_times, calendar,
    #                           calendar_dates, stop_times_int, headways
    loaded_feeds = urbanaccess.gtfs.load.gtfsfeed_to_df(
                                            gtfsfeed_path,
                                            validation,
                                            verbose,
                                            bbox,
                                            remove_stops_outsidebbox,
                                            append_definitions)

    # =============
    # Section break
    # =============
    update_status(('Next, we need to interpolate stop times data from GTFS.'))

    # what remains an empty dataframe is stop_times_int, which we still
    # need to generate before we can get to calculating headways
    columns = ['route_id', 'direction_id', 'trip_id', 'service_id', 
               'unique_agency_id']
    day = 'wednesday' # pick an arbitrary day of week
    tripschedualselector = urbanaccess.gtfs.network._trip_schedule_selector
    cal_selected_trips = tripschedualselector(
                                    loaded_feeds.trips[columns],
                                    loaded_feeds.calendar,
                                    loaded_feeds.calendar_dates,
                                    day)

    # approximate missing stop times via linear interpolation
    interpolatestoptimes = urbanaccess.gtfs.synthesize.interp_stop_times
    intermediate_interpolation = interpolatestoptimes(
                                    loaded_feeds.stop_times,
                                    cal_selected_trips,
                                    day)

    # now calculate the difference in top times in new column
    timedifference = urbanaccess.gtfs.synthesize.add_time_difference
    stop_times_int = timedifference(intermediate_interpolation)

    # now we can update loaded_feeds with this new dataframe
    loaded_feeds.stop_times_int = stop_times_int

    # =============
    # Section break
    # =============
    update_status(('Now we can calculate headways with the interpolated data.'))

    # now we need to calculate the headways, given the downloaded gtfs
    headway_timerange = ['07:00:00','10:00:00'] # approx a.m. peak
    # the below function updates loaded_feeds, so that headways is populated
    loaded_feeds = urbanaccess.gtfs.headways.headways(loaded_feeds,
                                                      headway_timerange)

    # =============
    # Section break
    # =============
    update_status(('At this point we are able to save/reload the data locally.'))

    # save the results from these initial processing steps locally
    filename = 'temp_network_analyzed.h5'
    urbanaccess.gtfs.network.save_processed_gtfs_data(loaded_feeds,
                                                      'data',
                                                      filename)
    # we can now reload from that save location if we want
    loaded_feeds = urbanaccess.gtfs.network.load_processed_gtfs_data('data',
                                                                     filename)

    # =============
    # Section break
    # =============
    update_status(('Next, we need to generate the transit and osm networks.'))

    # to proceed, we need to generate a network describing the transit data
    ua_network = urbanaccess.gtfs.network.create_transit_net(
                                    gtfsfeeds_dfs=loaded_feeds,
                                    day=day,
                                    timerange=headway_timerange,
                                    overwrite_existing_stop_times_int=False,
                                    use_existing_stop_times_int=True,
                                    save_processed_gtfs=False)

    update_status(('Transit feed downloaded, now we want OSM from bbox.'))
    # now we're ready to download OSM data, let's use same bbox from gtfs search
    bbox = (-89.871597,42.824365,-88.972778,43.307942) # big
    # bbox = (-89.395366,43.06663,-89.373479,43.082305) # small
    osm_nodes, osm_edges = urbanaccess.osm.load.ua_network_from_bbox(bbox=bbox)

    update_status(('Both networks downloaded, now can clean osm data.'))
    # clean up the osm edges, make them type string to allow concatenating
    osm_edges['from'] = osm_edges['from'].astype(str)
    osm_edges['to'] = osm_edges['to'].astype(str)
    osm_edges['id'] = osm_edges['from'].str.cat(osm_edges['to'])

    keep = ['id',
            'access',
            'bridge',
            'distance',
            'from',
            'hgv',
            'highway',
            'lanes',
            'maxspeed',
            'name',
            'oneway',
            'ref',
            'service',
            'to',
            'tunnel']

    # ensure that we have all the cols we need
    for col in keep:
        # make all missing but required cols empty
        if col not in osm_edges.columns.values:
            print('Missing column: ' + str(col))
            osm_edges[col] = ''

    osm_edges = osm_edges[keep]
    osm_edges.drop_duplicates(subset='id', keep='first', inplace=True)

    update_status(('Next, create an OSM network in Pandana ready format.'))
    # with osm data, we can create a network just as we did with the gtfs data
    ua_network = urbanaccess.osm.network.create_osm_net(
                                    osm_edges = osm_edges,
                                    osm_nodes = osm_nodes,
                                    travel_speed_mph = 3, # walk speed average
                                    network_type = 'walk')

    # =============
    # Section break
    # =============
    update_status(('Now we have all networks we need, '
                   'so we can integrate them.'))

    # result urbanaccess_nw vars is an object with the following attributes:
    #   osm_edges, osm_nodes,
    #   transit_edges, transit_nodes
    # and then returns the above, plus:
    #   net_connector_edges, net_edges, net_nodes
    urbanaccess_nw = urbanaccess.network.integrate_network(
                                    urbanaccess_network=ua_network,
                                    headways=True,
                                    urbanaccess_gtfsfeeds_df=loaded_feeds,
                                    headway_statistic='mean')

    # now to shift over to pandana's domain
    nod_x = urbanaccess_nw.net_nodes['x'].astype(float)
    nod_y = urbanaccess_nw.net_nodes['y'].astype(float)

    # use the integer representation of each from and to id
    # (pandana can't handle them as strings)
    fr_null = urbanaccess_nw.net_edges['from_int'].isnull()
    to_null = urbanaccess_nw.net_edges['to_int'].isnull()
    print('There are {} disconnected edges.'.format(
        urbanaccess_nw.net_edges[(fr_null | to_null)]))
    urbanaccess_nw.net_edges = urbanaccess_nw.net_edges[~(fr_null | to_null)]
    
    edg_fr = urbanaccess_nw.net_edges['from_int'].astype(int)
    edg_to = urbanaccess_nw.net_edges['to_int'].astype(int)
    edg_wt_df = urbanaccess_nw.net_edges[['weight']].astype(float)

    # insantiate a pandana network object
    # set twoway to false since UA networks are oneways
    p_net = pdna.Network(nod_x, nod_y, edg_fr, edg_to, edg_wt_df, twoway=False)

    # precompute step, requires a max 'horizon' distance
    horizon_dist = 60
    p_net.precompute(horizon_dist)

    # read in an example dataset
    blocks_df = pd.read_csv('./urbanaccess/tests/fixtures/blocks.csv')
    geometry = blocks_df['geometry'].map(_parse_wkt)
    blocks_df = blocks_df.drop('geometry', axis=1)
    crs = {'init': 'epsg:4326'}
    blocks_gdf = gpd.GeoDataFrame(blocks_df, crs=crs, geometry=geometry)

    # we need to extract the point lat/lon values
    blocks_gdf['x'] = blocks_gdf.centroid.map(lambda p: p.x)
    blocks_gdf['y'] = blocks_gdf.centroid.map(lambda p: p.y)

    #  set node_ids as an attribute on the geodataframe
    blocks_gdf['node_ids'] = p_net.get_node_ids(blocks_gdf['x'],
                                                blocks_gdf['y'])
    p_net.set(blocks_gdf['node_ids'],
              variable=blocks_gdf['emp'],
              name='emp')

    # let's just make sure it can run through at least one aggregation
    # without erroring in pandana and be happy with that for now

    # Note: the results will be very limited because the blocks do not overlap
    #       well with the network dataset from the bbox
    s = p_net.aggregate(15,
                        type='sum',
                        decay='flat',
                        imp_name='weight',
                        name='emp')
示例#21
0
bbox = (-117.157516, 32.715666, -117.095032, 32.767068)
west, south, east, north = bbox

new_store = pd.HDFStore('sandag_subset.h5', 'w', complib='zlib', complevel=1)
new_net_store = pd.HDFStore('osm_sandag_subset.h5',
                            'w',
                            complib='zlib',
                            complevel=1)

with pd.HDFStore('sandag.h5') as store:
    with pd.HDFStore('osm_sandag.h5') as net_store:

        print('Subset network and save to new store')

        nodes, edges = net_store.nodes, net_store.edges
        net = pdna.Network(nodes["x"], nodes["y"], edges["from"], edges["to"],
                           edges[["weight"]])
        net.precompute(3000)
        parcels = store.parcels
        parcels['node_id'] = net.get_node_ids(parcels['x'], parcels['y'])

        new_nodes = nodes.loc[(nodes.x > west)
                              & (nodes.x < east)
                              & (nodes.y > south)
                              & (nodes.y < north)]

        new_edges = edges.loc[(edges['from'].isin(new_nodes.index))
                              & (edges['to'].isin(new_nodes.index))]

        new_net_store.put('edges', new_edges)
        new_net_store.put('nodes', new_nodes)
        new_net_store.close()
示例#22
0
def multimodal_from_bbox(bbox,
                         gtfs_dir=None,
                         save_osm=None,
                         save_gtfs=None,
                         excluded_feeds=None,
                         transit_net_kwargs=None,
                         headways=False,
                         additional_feeds=None):
    """Generate a combined walk/transit pandana Network from a bounding box of latitudes and longitudes

    Parameters
    ----------
    bbox : tuple
        A bounding box formatted as (lng_max, lat_min, lng_min, lat_max). e.g. For a geodataframe
        stored in epsg 4326, this can be obtained with geodataframe.total_bounds
    gtfs_dir : str, optional
        path to directory for storing downloaded GTFS data. If None, the current directory will be used
    save_osm : str, optional
        Path to store the intermediate OSM Network as an h5 file
    save_gtfs : str, optional
        Path to store the intermediate GTFS Network as an h5 file
    excluded_feeds : list, optional
        list of feed names to exclude from the GTFS downloaded
    transit_net_kwargs : dict, optional
        additional keyword arguments to be passed to the urbanaccess GTFS network instantiator.
        defaults to {'day':"monday", 'timerange':["07:00:00", "10:00:00"]}
    headways : bool, optional
        Whether to include headway calculations for the combined network
    additional_feeds : dict, optional
        Dictionary of additional feed locations in case they are not hosted on transitland.
        Should be specified as {transitagencyname: url} 

    Returns
    -------
    pandana.Network
        a multimodal (walk/transit) Network object built from OSM and GTFS data that lie within the bounding box
    """
    try:
        import osmnet
        import pandana as pdna
        import urbanaccess as ua
    except ImportError:
        raise ImportError(
            "You must have osmnet, pandana, and urbanaccess installed to use this function"
        )

    assert bbox is not None, "You must provide a bounding box to collect network data"
    if not gtfs_dir:
        gtfs_dir = "./data/"

    if not transit_net_kwargs:
        transit_net_kwargs = dict(day="monday",
                                  timerange=["07:00:00", "10:00:00"],
                                  calendar_dates_lookup=None)

    # Get gtfs data
    feeds = feeds_from_bbox(bbox)

    if excluded_feeds:  # remove problematic feeds if necessary
        for feed in list(feeds.keys()):
            if feed in excluded_feeds:
                feeds.pop(feed)

    if len(ua.gtfsfeeds.feeds.to_dict()["gtfs_feeds"]) > 0:
        ua.gtfsfeeds.feeds.remove_feed(
            remove_all=True
        )  # feeds object is global so reset it if there's anything leftover

    ua.gtfsfeeds.feeds.add_feed(feeds)
    if additional_feeds:
        ua.gtfsfeeds.feeds.add_feed(additional_feeds)

    ua.gtfsfeeds.download(data_folder=gtfs_dir)

    loaded_feeds = ua.gtfs.load.gtfsfeed_to_df(f"{gtfs_dir}/gtfsfeed_text/",
                                               bbox=bbox,
                                               remove_stops_outsidebbox=True)
    if save_gtfs:
        ua_to_h5(loaded_feeds, f"{gtfs_dir}/{save_gtfs}")

    # Get OSM data
    nodes, edges = osmnet.network_from_bbox(bbox=bbox)
    osm_network = pdna.Network(nodes["x"], nodes["y"], edges["from"],
                               edges["to"], edges[["distance"]])
    if save_osm:
        osm_network.save_hdf5(save_osm)

    # Create the transit network
    ua.create_transit_net(gtfsfeeds_dfs=loaded_feeds, **transit_net_kwargs)
    osm_network.nodes_df['id'] = osm_network.nodes_df.index

    ua.create_osm_net(
        osm_edges=osm_network.edges_df,
        osm_nodes=osm_network.nodes_df,
        travel_speed_mph=3,
    )
    if headways:
        ua.gtfs.headways.headways(
            gtfsfeeds_df=loaded_feeds,
            headway_timerange=transit_net_kwargs["timerange"])
        ua.network.integrate_network(
            urbanaccess_network=ua.ua_network,
            headways=True,
            urbanaccess_gtfsfeeds_df=loaded_feeds,
            headway_statistic="mean",
        )
    else:
        ua.integrate_network(urbanaccess_network=ua.ua_network, headways=False)

    combined_net = pdna.Network(
        ua.ua_network.net_nodes["x"],
        ua.ua_network.net_nodes["y"],
        ua.ua_network.net_edges["from_int"],
        ua.ua_network.net_edges["to_int"],
        ua.ua_network.net_edges[["weight"]],
    )

    return combined_net
示例#23
0
def get_osm_network(geodataframe, maxdist=5000, quiet=True, output_crs=None, **kwargs):
    """Download a street network from OSM.

    Parameters
    ----------
    geodataframe : geopandas.GeoDataFrame
        geopandas.GeoDataFrame of the study area.
        Coordinate system should be in WGS84
    maxdist : int
        Maximum distance of the network queries you may need (this is used to buffer the
        network to ensure there's enough to satisfy your largest query, otherwise there
        may be edge effects. Distance is measured in the units of the geodataframe CRS. If
        the CRS is geographic, a UTM approximation is used, so the units are meters.
    quiet: bool
        If True, diagnostic messages from urbanaccess will be suppressed
    **kwargs : dict
        additional kwargs passed through to
        urbanaccess.ua_network_from_bbox

    Returns
    -------
    pandana.Network
        A pandana Network instance for use in accessibility calculations or
        spatial segregation measures that include a distance decay

    """
    assert geodataframe.crs, "The input geodataframe must have a valid CRS set"
    if not output_crs:
        output_crs = geodataframe.crs
    try:
        import pandana as pdna
        from urbanaccess.osm.load import ua_network_from_bbox
    except ImportError:
        raise ImportError(
            "You need pandana and urbanaccess to work with segregation's network module\n"
            "You can install them with  `pip install urbanaccess pandana` "
            "or `conda install -c udst pandana urbanaccess`"
        )

    gdf = geodataframe.copy()

    #  Need coordinates in 4326 to request from OSM, but need projected for measuring distance
    if geodataframe.crs.is_geographic:
        # this is lazy because UTM can be inaccurate in some places on the earth, but generally works fine
        warn(
            "The geodataframe passed into the function is stored in a geographic CRS."
            "Estimating maximum distance threshold using a UTM transformation"
        )
        gdf = gdf.to_crs(gdf.estimate_utm_crs())
        gdf = gdf.buffer(maxdist)
        bounds = gdf.to_crs(epsg=4326).total_bounds
    else:
        bounds = gdf.total_bounds

    nodes, edges = ua_network_from_bbox(
        bounds[1], bounds[0], bounds[3], bounds[2], **kwargs
    )
    nodes = _reproject_osm_nodes(nodes, 4326, output_crs)

    network = pdna.Network(
        nodes["x"], nodes["y"], edges["from"], edges["to"], edges[["distance"]]
    )

    return network
示例#24
0
G.add_weighted_edges_from(edges)
largest_connected_component = sorted(nx.connected_components(G),
                                     key=len,
                                     reverse=True)[0]

# Clean up to save memory
G = None
edges = None

# Create pandana network. It's much faster for nearest point-of-interest analysis
# Filter nodes and edges to just include those in the largest connected componet
dfLinksLCC = dfLinks.loc[
    (dfLinks['startNode'].isin(largest_connected_component))
    & (dfLinks['endNode'].isin(largest_connected_component))]
dfNodesLCC = dfNodes.loc[largest_connected_component]
net = pdna.Network(dfNodesLCC["x"], dfNodesLCC["y"], dfLinksLCC["startNode"],
                   dfLinksLCC["endNode"], dfLinksLCC[["length"]])

# Get the nearest three Food Banks
search_distance = 200000
net.set_pois("Food Banks", search_distance, 3, foodBank.geometry.x,
             foodBank.geometry.y)
dfNear = net.nearest_pois(search_distance,
                          "Food Banks",
                          num_pois=3,
                          include_poi_ids=True)

# ---- Ward Computations ----
# Select only the Wards centroids and their nearest foodbanks rather than every road node
"""
ward_road_nodes = net.get_node_ids(gdfWardsCent.geometry.x, gdfWardsCent.geometry.y)
wardComps = dfNear.loc[ward_road_nodes]
示例#25
0
 def _create_pandana_net(nodes, edges):
     return pdna.Network(nodes.x, nodes.y, edges['from'], edges['to'],
                         edges.xs('traveltime', axis=1, level=1))