Utah Transit Authority#
In this example, we'll predict the energy consumption for some trips operated by the Utah Transit Authority (UTA) in Salt Lake City. This requires specifying the GTFS data we are analyzing, map-matching it to the road network, and running a RouteE-Compass model to produce energy estimates.
This example uses the GTFSEnergyPredictor class, which provides a clean,
extensible API for transit energy prediction.
from pathlib import Path
from routee.transit import GTFSEnergyPredictor, sample_inputs_path
# Specify input data location
input_directory = sample_inputs_path() / "saltlake/gtfs"
output_directory = Path("reports/saltlake")
Quick Start: Using the run() Method#
For most use cases, the run() method provides the simplest way to perform the
complete energy prediction workflow. This single method call chains together all
processing steps and returns trip-level energy predictions.
We'll analyze routes 806 and 807 on August 2nd, 2023, using the Battery Electric Bus model. We'll include deadhead trips and estimated HVAC energy.
predictor = GTFSEnergyPredictor(
gtfs_path=input_directory,
vehicle_models=["Transit_Bus_Battery_Electric"],
output_dir=output_directory,
)
trip_results = predictor.run(
date="2023/08/02",
routes=["806", "807"],
add_depot_deadhead=True,
add_mid_block_deadhead=True,
add_hvac=True,
save_results=False,
)
Downloaded: G4900350.csv
Downloaded: G4900490.csv
Downloaded: G4900450.csv
Downloaded: G4900110.csv
Downloaded: G4900570.csv
Downloaded: G4900030.csv
Downloaded: G4900430.csv
INFO:routee.transit.predictor:Initialized GTFSEnergyPredictor for /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/routee/transit/resources/sample_inputs/saltlake/gtfs
INFO:routee.transit.predictor:Loading GTFS data...
INFO:routee.transit.predictor:Feed includes 1 agencies: ['Utah Transit Authority']. Total trips: 12037, shapes: 238
INFO:routee.transit.predictor:Loaded 12037 trips and 199 shapes
INFO:routee.transit.predictor:Filtering trips (date=2023/08/02, routes=['806', '807'])...
INFO:routee.transit.predictor:Filtered to 16 trips and 4 shapes
INFO:routee.transit.predictor:Preparing mid-block deadhead trips...
INFO:routee.transit.predictor:Preparing depot deadhead trips...
INFO:routee.transit.predictor:Building CompassApp from bounding box: (-112.03101, 40.22523, -111.65814, 40.482409999999994)
INFO:nrel.routee.compass.io.generate_dataset:running pipeline import with phases: [['GRAPH', 'CONFIG', 'POWERTRAIN']]
INFO:nrel.routee.compass.io.generate_dataset:processing graph topology and speeds
INFO:nrel.routee.compass.io.generate_dataset:adding grade information
INFO:nrel.routee.compass.io.utils:downloading n41w113
INFO:nrel.routee.compass.io.utils:downloading n41w112
INFO:nrel.routee.compass.io.generate_dataset:processing vertices
INFO:nrel.routee.compass.io.generate_dataset:processing edges
INFO:nrel.routee.compass.io.generate_dataset:writing vertex files
INFO:nrel.routee.compass.io.generate_dataset:writing edge files
INFO:nrel.routee.compass.io.generate_dataset:writing edge attribute files
INFO:nrel.routee.compass.io.generate_dataset:copying default configuration TOML files
INFO:nrel.routee.compass.io.generate_dataset:downloading the default RouteE Powertrain models
INFO:nrel.routee.compass.io.generate_dataset:copying vehicle configuration files
INFO:nrel.routee.compass.io.generate_dataset:running 2 dataset generation hooks
INFO:gtfs_processing:Wrote 109260 stop-edge mappings to reports/saltlake/compass_app/gtfs_stops.csv
INFO:gtfs_processing:Copied transit_energy.toml to reports/saltlake/compass_app/transit_energy.toml
INFO:routee.transit.predictor:CompassApp initialized
graph edge list 0: /home/runner/work/routee-transit/routee-transit/docs/examples/reports/saltlake/compass_app/edges-compass.csv.gz: 46796it [00:00, 1781413.62it/s]
building adjacencies: 100%|██████████| 46796/46796 [00:00<00:00, 5749321.50it/s]
INFO:routee.transit.predictor:Routing mid-block deadhead trips...
INFO:routee.transit.deadhead_router:Deadhead routing: 7 trips reduced to 3 unique O-D pairs
applying input plugin 1: 100%|██████████| 3/3 [00:00<00:00, 9564.68it/s]
applying input plugin 2: 100%|██████████| 3/3 [00:00<00:00, 231356.53it/s]
search: 100%|██████████| 3/3 [00:00<00:00, 75.75it/s]
INFO:routee.transit.predictor:Added 7 mid-block deadhead trips
INFO:routee.transit.predictor:Routing depot deadhead trips...
INFO:routee.transit.deadhead_router:Deadhead routing: 9 trips reduced to 3 unique O-D pairs
applying input plugin 1: 100%|██████████| 3/3 [00:00<00:00, 38702.69it/s]
applying input plugin 2: 100%|██████████| 3/3 [00:00<00:00, 253614.00it/s]
search: 100%|██████████| 3/3 [00:00<00:00, 28.49it/s]
INFO:routee.transit.deadhead_router:Deadhead routing: 9 trips reduced to 3 unique O-D pairs
applying input plugin 1: 100%|██████████| 3/3 [00:00<00:00, 60129.88it/s]
applying input plugin 2: 100%|██████████| 3/3 [00:00<00:00, 249438.77it/s]
search: 100%|██████████| 3/3 [00:00<00:00, 57.59it/s]
INFO:routee.transit.predictor:Added 18 depot deadhead trips
INFO:routee.transit.predictor:Predicting energy for 1 vehicle model(s)...
INFO:routee.transit.predictor:Running map matching for 13 shapes...
map matching: 15%|█▅ | 2/13 [00:00<00:00, 16.50it/s]
map matching: 100%|██████████| 13/13 [00:01<00:00, 7.33it/s]
INFO:routee.transit.predictor:Running energy prediction via CompassApp for: Transit_Bus_Battery_Electric
calculating paths: 100%|██████████| 13/13 [00:00<00:00, 894.52it/s]
INFO:routee.transit.predictor:Adding HVAC energy impacts...
INFO:routee.transit.predictor:Energy prediction complete
The run() method automatically performs all these steps:
Loads the GTFS feed
Filters trips by date and routes
Adds mid-block deadhead trips (between consecutive trips)
Adds depot deadhead trips (to/from depot)
Matches shapes to OpenStreetMap road network and adds road grade (via RouteE-Compass)
Predicts energy consumption with RouteE-Compass
Adds estimated HVAC energy impacts
Saves results to CSV files
Let's examine the results. The columns include information about the energy predictions made (including any HVAC component) as well as GTFS fields that apply to each trip, and a description of the weather scenario considered:
trip_results.columns
trip_results[["trip_id", "vehicle", "scenario", "energy_used", "miles"]].head()
| trip_id | vehicle | scenario | energy_used | miles | |
|---|---|---|---|---|---|
| 0 | 5181298_to_5181301 | Transit_Bus_Battery_Electric | median | 16.967052 | 15.491856 |
| 1 | 5181298_to_5181301 | Transit_Bus_Battery_Electric | summer | 16.025047 | 15.491856 |
| 2 | 5181298_to_5181301 | Transit_Bus_Battery_Electric | winter | 44.538575 | 15.491856 |
| 3 | 5181297_to_5181299 | Transit_Bus_Battery_Electric | median | 12.599589 | 15.491856 |
| 4 | 5181297_to_5181299 | Transit_Bus_Battery_Electric | summer | 12.586869 | 15.491856 |
Analyze Energy Efficiency#
We can calculate energy efficiency in kWh per mile, including HVAC loads.
The results include a scenario column (summer/winter.median) for HVAC impacts.
Weather Impacts#
Let's see how energy efficiency in kWh/mi compares across different weather scenarios:
if "scenario" in trip_results.columns:
trip_results["kwh_per_mi"] = trip_results["energy_used"] / trip_results["miles"]
trip_results.groupby("scenario")["kwh_per_mi"].mean()
scenario
median 1.665196
summer 1.947711
winter 5.331571
Name: kwh_per_mi, dtype: float64
We can see that winter requires the greatest energy, since the cold climate in Utah requires a heavy HVAC load.
Efficiency by Route#
How does typical energy efficiency in the median scenario (meaning temperatures are taken from the day of a typical year with the median average temperature)?
We can check by filtering by scenario and then grouping by route:
# First, filter out any deadhead trips
median_results = trip_results[trip_results["trip_type"] == "service"].copy()
# Then, only include median weather impacts
median_results = median_results[median_results["scenario"] == "median"]
median_results.groupby("route_short_name")["kwh_per_mi"].mean().sort_values(
ascending=False
)
route_short_name
807 1.295723
806 1.020666
Name: kwh_per_mi, dtype: float64
Route 807 requires more energy on average.
Access Additional Results#
Besides trip-level results, you can also access link-level results. These detailed results can help you better understand differences in predictions across trips.
# Link-level predictions show energy for each road segment
link_results = predictor.get_link_predictions()
link_results.head()
| match_id | edge_index | edge_list_id | edge_id | battery_capacity | trip_elevation_loss | edge_grade | edge_time | edge_speed | trip_distance | ... | trip_soc | trip_energy_electric | edge_energy_electric | edge_distance | trip_elevation_gain | geometry | shape_id | vehicle | energy_used | energy_unit | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 30081 | 500.0 | 0.000000 | 0.034760 | 0.055813 | 27.326809 | 0.025420 | ... | 0.999840 | 0.080132 | 0.080132 | 0.025420 | 0.000884 | LINESTRING (-111.71143 40.27542, -111.71156 40... | -111.712,40.276->-111.895,40.426 | Transit_Bus_Battery_Electric | 12.359723 | kWh |
| 1 | 0 | 1 | 0 | 30082 | 500.0 | 0.000000 | 0.088317 | 0.082326 | 27.326809 | 0.055324 | ... | 0.999494 | 0.252983 | 0.172851 | 0.029904 | 0.003525 | LINESTRING (-111.71166 40.27568, -111.71109 40... | -111.712,40.276->-111.895,40.426 | Transit_Bus_Battery_Electric | 12.359723 | kWh |
| 2 | 0 | 2 | 0 | 246 | 500.0 | -0.006952 | -0.076052 | 0.359040 | 27.326809 | 0.146736 | ... | 0.999959 | 0.020278 | -0.232705 | 0.091411 | 0.003525 | LINESTRING (-111.71109 40.27571, -111.71139 40... | -111.712,40.276->-111.895,40.426 | Transit_Bus_Battery_Electric | 12.359723 | kWh |
| 3 | 0 | 3 | 0 | 40037 | 500.0 | -0.006952 | 0.001036 | 0.054291 | 27.326809 | 0.167667 | ... | 0.999906 | 0.047239 | 0.026962 | 0.020931 | 0.003546 | LINESTRING (-111.71275 40.27596, -111.71275 40... | -111.712,40.276->-111.895,40.426 | Transit_Bus_Battery_Electric | 12.359723 | kWh |
| 4 | 0 | 4 | 0 | 259 | 500.0 | -0.007189 | -0.013422 | 0.030526 | 34.665791 | 0.185304 | ... | 0.999897 | 0.051700 | 0.004460 | 0.017637 | 0.003546 | LINESTRING (-111.71305 40.27608, -111.7131 40.... | -111.712,40.276->-111.895,40.426 | Transit_Bus_Battery_Electric | 12.359723 | kWh |
5 rows × 22 columns