Skip to content

Commit 5adf8f0

Browse files
committed
infer bbox from input inside of add_deadhead_trips()
1 parent a0f6b7d commit 5adf8f0

2 files changed

Lines changed: 30 additions & 61 deletions

File tree

nrel/routee/transit/prediction/generate_deadhead_traces.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ def add_deadhead_trips(
163163
network_type: str = "drive",
164164
road_buffer_m: int = 2000,
165165
n_processes: int | None = None,
166-
bbox: tuple[float, float, float, float] | None = None,
167166
) -> pd.DataFrame:
168167
"""Compute deadhead route shapes between origin and destination.
169168
@@ -175,16 +174,24 @@ def add_deadhead_trips(
175174
"""
176175
# Require bbox: this function uses a single study-area graph for all routing.
177176
global GLOBAL_GRAPH
178-
if bbox is None:
179-
raise ValueError(
180-
"bbox is required: provide a study-area bounding box (minx, miny, maxx, maxy)"
181-
)
182-
if ox is None:
183-
raise ImportError("osmnx is required to fetch a global bbox graph")
184-
# bbox expected as (minx, miny, maxx, maxy)
185-
if len(bbox) != 4:
186-
raise ValueError("bbox must be a 4-tuple (minx, miny, maxx, maxy)")
187-
# ox.graph_from_bbox signature: (north, south, east, west)
177+
178+
# Create bounding box around for osmnx graph based on O/D geometry
179+
all_points = pd.concat(
180+
[df["geometry_origin"], df["geometry_destination"]]
181+
)
182+
lons = all_points.apply(lambda p: p.x)
183+
lats = all_points.apply(lambda p: p.y)
184+
min_lon, max_lon = lons.min(), lons.max() # Bounding box
185+
min_lat, max_lat = lats.min(), lats.max() # Bounding box
186+
buffer_deg_lat = 0.018 # Roughly 2 km buffer in degrees
187+
buffer_deg_lon = 0.022 # Roughly 2 km buffer in degrees
188+
bbox = (
189+
min_lon - buffer_deg_lon,
190+
min_lat - buffer_deg_lat,
191+
max_lon + buffer_deg_lon,
192+
max_lat + buffer_deg_lat,
193+
) # bounding box as (min_x, min_y, max_x, max_y)
194+
188195
GLOBAL_GRAPH = ox.graph_from_bbox(bbox, network_type="drive")
189196

190197
task_args = []

nrel/routee/transit/prediction/gtfs_feature_processing.py

Lines changed: 12 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,6 @@ def extend_trip_traces(
419419
logger.info("Finished attaching timestamps")
420420
return pd.concat(trips_with_timestamps_list)
421421

422-
423422
def build_routee_features_with_osm(
424423
input_directory: Union[str, Path],
425424
depot_directory: Union[str, Path],
@@ -466,64 +465,42 @@ def build_routee_features_with_osm(
466465
)
467466
stop_times_df = feed.stop_times
468467

469-
# **********---------------Add depot deadhead trips_df, shapes_df, and feed---------------**********
470-
# 1.1) Add depot deadhead trips, shapes, and update feed
468+
# 2) Create synthetic trips, shapes, and stop times for deadhead to and from depot
471469
# Create depot deadhead trips
472470
deadhead_trips_df = create_depot_deadhead_trips(trips_df)
471+
473472
# Create depot deadhead stop_times and stops
474473
first_stops_gdf, last_stops_gdf = add_depot_to_blocks(
475474
trips_df, feed, path_to_depots=Path(depot_directory) / "Transit_Depot.shp"
476475
)
477476
deadhead_stop_times_df, deadhead_stops_df = create_depot_deadhead_stops(
478477
first_stops_gdf, last_stops_gdf, deadhead_trips_df
479478
)
479+
480480
# Generate deadhead trip shapes for trips from depot to first stop
481-
all_points = pd.concat(
482-
[first_stops_gdf["geometry_origin"], first_stops_gdf["geometry_destination"]]
483-
)
484-
lons = all_points.apply(lambda p: p.x)
485-
lats = all_points.apply(lambda p: p.y)
486-
min_lon, max_lon = lons.min(), lons.max() # Bounding box
487-
min_lat, max_lat = lats.min(), lats.max() # Bounding box
488-
buffer_deg_lat = 0.018 # Roughly 2 km buffer in degrees
489-
buffer_deg_lon = 0.022 # Roughly 2 km buffer in degrees
490-
miny = min_lat - buffer_deg_lat
491-
maxy = max_lat + buffer_deg_lat
492-
minx = min_lon - buffer_deg_lon
493-
maxx = max_lon + buffer_deg_lon
494481
from_depot_deadhead_shapes_df = add_deadhead_trips(
495-
df=first_stops_gdf, n_processes=1, bbox=tuple([minx, miny, maxx, maxy])
496-
)
482+
df=first_stops_gdf, n_processes=1
483+
)
497484
from_depot_deadhead_shapes_df["shape_id"] = from_depot_deadhead_shapes_df[
498485
"shape_id"
499486
].apply(lambda x: "from_depot_" + x)
487+
500488
# Generate deadhead trip shapes for trips from last stop to depot
501-
all_points = pd.concat(
502-
[last_stops_gdf["geometry_origin"], last_stops_gdf["geometry_destination"]]
503-
)
504-
lons = all_points.apply(lambda p: p.x)
505-
lats = all_points.apply(lambda p: p.y)
506-
min_lon, max_lon = lons.min(), lons.max() # Bounding box
507-
min_lat, max_lat = lats.min(), lats.max() # Bounding box
508-
buffer_deg_lat = 0.018 # Roughly 2 km buffer in degrees
509-
buffer_deg_lon = 0.022 # Roughly 2 km buffer in degrees
510-
miny = min_lat - buffer_deg_lat
511-
maxy = max_lat + buffer_deg_lat
512-
minx = min_lon - buffer_deg_lon
513-
maxx = max_lon + buffer_deg_lon
514489
to_depot_deadhead_shapes_df = add_deadhead_trips(
515-
df=last_stops_gdf, n_processes=1, bbox=tuple([minx, miny, maxx, maxy])
490+
df=last_stops_gdf, n_processes=1
516491
)
517492
to_depot_deadhead_shapes_df["shape_id"] = to_depot_deadhead_shapes_df[
518493
"shape_id"
519494
].apply(lambda x: "to_depot_" + x)
495+
520496
# Combine all deadhead shapes
521497
deadhead_shapes_df = pd.concat(
522498
[from_depot_deadhead_shapes_df, to_depot_deadhead_shapes_df], ignore_index=True
523499
)
524500

525501
# Update trips_df, shapes_df, and feed
526-
# Before updating, update deadhead_trips_df as some blocks may have the same first and last stop therefore won't shown in deadhead_shapes_df
502+
# Before updating, update deadhead_trips_df as some blocks may have the same first
503+
# and last stop therefore won't shown in deadhead_shapes_df
527504
deadhead_trips_df = deadhead_trips_df[
528505
deadhead_trips_df["shape_id"].isin(deadhead_shapes_df["shape_id"].unique())
529506
]
@@ -536,9 +513,7 @@ def build_routee_features_with_osm(
536513
[feed.stop_times, deadhead_stop_times_df], ignore_index=True
537514
)
538515
feed.stops = pd.concat([feed.stops, deadhead_stops_df], ignore_index=True)
539-
# **********---------------End of adding depot deadhead trips_df, shapes_df, and feed---------------**********
540516

541-
# **********---------------Add between trip deadhead trips_df, shapes_df, and feed---------------**********
542517
# 1.2) Add between trip deadhead trips, shapes, and update feed
543518
# Create between trip deadhead trips
544519
betweenTrip_deadhead_trips_df = create_betweenTrip_deadhead_trips(
@@ -550,26 +525,13 @@ def build_routee_features_with_osm(
550525
betweenTrip_deadhead_stops_df,
551526
betweenTrip_ODs,
552527
) = create_betweenTrip_deadhead_stops(feed, betweenTrip_deadhead_trips_df)
553-
# Generate deadhead trip shapes for trips from depot to first stop
554-
all_points = pd.concat(
555-
[betweenTrip_ODs["geometry_origin"], betweenTrip_ODs["geometry_destination"]]
556-
)
557-
lons = all_points.apply(lambda p: p.x)
558-
lats = all_points.apply(lambda p: p.y)
559-
min_lon, max_lon = lons.min(), lons.max() # Bounding box
560-
min_lat, max_lat = lats.min(), lats.max() # Bounding box
561-
buffer_deg_lat = 0.018 # Roughly 2 km buffer in degrees
562-
buffer_deg_lon = 0.022 # Roughly 2 km buffer in degrees
563-
miny = min_lat - buffer_deg_lat
564-
maxy = max_lat + buffer_deg_lat
565-
minx = min_lon - buffer_deg_lon
566-
maxx = max_lon + buffer_deg_lon
528+
567529
# Remove ODs with same origin and destination
568530
betweenTrip_ODs = betweenTrip_ODs[
569531
betweenTrip_ODs.geometry_origin != betweenTrip_ODs.geometry_destination
570532
]
571533
betweenTrip_deadhead_shapes_df = add_deadhead_trips(
572-
df=betweenTrip_ODs, n_processes=1, bbox=tuple([minx, miny, maxx, maxy])
534+
df=betweenTrip_ODs, n_processes=1
573535
)
574536

575537
# Update trips_df, shapes_df, and feed

0 commit comments

Comments
 (0)