Note
Go to the end to download the full example code.
Computing walking distance to transit stops#
In this example we show how to use Polaris-Studio to compute the distance to transit stops from each location.
The user can compute distances to arbitrary stops, or automatically select all stops for which there are BRT or rail services
Imports#
from pathlib import Path
import folium
import numpy as np
from polaris import Polaris
from polaris.network.tools.tod_distance import DistanceToTransit
from polaris.utils.database.db_utils import read_and_close
Data Sources#
# Open the demand database for analysis
model_fldr = "/tmp/Bloomington"
# model_fldr = r"C:\temp_container\Bloomington"
network = Polaris.from_dir(Path(model_fldr)).network
DtT = DistanceToTransit(path_to_file=network.path_to_file)
We can get the list of locations locations within a certain distance from a list of stops
locations = DtT.locations_within_distance(1000, [2000000000001])
print(locations)
euclidean_locations = DtT.locations_within_distance(1000, [2000000000001], use_routed_distance=False)
[41, 42, 61, 62, 63, 64, 197, 198, 285, 286, 419, 420, 471, 472, 979, 980, 981, 982, 983, 984, 1053, 1054, 1057, 1058, 1125, 1126, 1149, 1150, 1165, 1166, 1167, 1168, 1339, 1340, 2037, 2038, 2039, 2040, 2047, 2048, 2163, 2164, 2219, 2220, 2351, 2352, 2353, 2354, 2585, 2586, 2692, 2693, 2694, 2695, 2696, 2697, 2700, 2701, 2714]
We can also set the stops we are interested in, by providing a list, detecting BRT stops automatically, and/or detecting rail stops automatically
# For the example, we choose the stops for an arbitrary route
my_stops = np.array(
[
2000000000001,
2000000000002,
2000000000003,
2000000000004,
2000000000005,
2000000000006,
2000000000007,
2000000000008,
2000000000009,
2000000000010,
2000000000011,
],
np.int64,
)
DtT.set_tod_stops(tod_stops=my_stops, get_brt=False, get_rail=False)
# After setting the stops, the user can compute the distances from each location to their nearest "relevant" stop
distances = DtT.build_tod_distances()
# Some locations don' have any access to transit, so we can filter them out
distances = distances[distances.distance_to_tod < np.inf]
And we can plot this path on the network
data = network.data_tables
with read_and_close(network.path_to_file, spatial=True) as conn:
loc_layer = data.plotting_layer("Location", conn).merge(distances, on="location")
stops = data.plotting_layer("Transit_Stops", conn).query("stop_id in @my_stops")
Plotting results#
In this case, we will use a custom color ramp to show the data in a more meaningful way
Cusom color ramp
import branca.colormap as cm
mmin = distances.distance_to_tod.min()
mmax = distances.distance_to_tod.max()
step = (mmax - mmin) / 4
lin_scale = cm.LinearColormap(
["green", "yellow", "orange", "red"],
index=[mmin / mmax, (mmin + step) / mmax, (mmin + 3 * step) / mmax, mmax / mmax],
)
Plotting
tstops = folium.FeatureGroup("stops")
locations = folium.FeatureGroup("Locations")
for location_id, row in loc_layer.iterrows():
point = eval(row.geo.replace("POINT", "").replace(" ", ","))
point = (point[1], point[0])
_ = folium.vector_layers.CircleMarker(
point,
popup=f"<b>Location:{location_id}, Distance: {int(row.distance_to_tod):,}</b>",
color=lin_scale(row.distance_to_tod / mmax),
radius=2,
fill=True,
fillColor=lin_scale(row.distance_to_tod / mmax),
fillOpacity=1.0,
).add_to(locations)
for stop_id, row in stops.iterrows():
point = eval(row.geo.replace("POINT", "").replace(" ", ","))
point = (point[1], point[0])
_ = folium.vector_layers.CircleMarker(
point,
popup=f"<b>Stop: {stop_id}</b>",
color="black",
radius=6,
fill=True,
fillColor="black",
fillOpacity=1.0,
).add_to(tstops)
a, b = tstops.get_bounds()
map_center = list((np.array(a) + np.array(b)) / 2)
map_osm = folium.Map(location=map_center, zoom_start=12, tiles="cartodb positron")
locations.add_to(map_osm)
tstops.add_to(map_osm)
folium.LayerControl().add_to(map_osm)
map_osm
Total running time of the script: (0 minutes 3.113 seconds)