Utah Transit Agency Example#
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, processing it to produce RouteE-Powertrain inputs, and running a RouteE-Powertrain model to produce energy estimates.
This example uses the GTFSEnergyPredictor class, which provides a clean,
extensible API for transit energy prediction.
import logging
import os
from routee.transit import GTFSEnergyPredictor, sample_inputs_path
# Set up logging: Clear any existing handlers
logging.getLogger().handlers.clear()
# Configure basic logging
logging.basicConfig(
level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s - %(message)s"
)
# Suppress GDAL/PROJ warnings, which flood the output when we run gradeit
os.environ["PROJ_DEBUG"] = "0"
# Specify input data location
input_directory = sample_inputs_path() / "saltlake/gtfs"
output_directory = "./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 with HVAC energy impacts included.
Note: depot_path is not specified, so the predictor will use default depot locations from the National Transit Database's "Public Transit Facilities and Stations - 2023" dataset (https://data.transportation.gov/stories/s/gd62-jzra).
predictor = GTFSEnergyPredictor(
gtfs_path=input_directory,
output_dir=output_directory,
vehicle_models=["Transit_Bus_Battery_Electric"],
)
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,
)
2026-03-05 00:46:01,550 [INFO] routee.transit.predictor - Initialized GTFSEnergyPredictor for /opt/hostedtoolcache/Python/3.11.14/x64/lib/python3.11/site-packages/routee/transit/resources/sample_inputs/saltlake/gtfs
2026-03-05 00:46:01,551 [INFO] routee.transit.predictor - Loading GTFS data...
2026-03-05 00:46:02,910 [INFO] routee.transit.predictor - Feed includes 1 agencies: ['Utah Transit Authority']. Total trips: 12037, shapes: 238
2026-03-05 00:46:02,919 [INFO] routee.transit.predictor - Loaded 12037 trips and 199 shapes
2026-03-05 00:46:02,920 [INFO] routee.transit.predictor - Filtering trips (date=2023/08/02, routes=['806', '807'])...
2026-03-05 00:46:02,958 [INFO] routee.transit.predictor - Filtered to 16 trips and 4 shapes
2026-03-05 00:46:02,989 [INFO] routee.transit.predictor - Preparing mid-block deadhead trips...
2026-03-05 00:46:03,081 [INFO] routee.transit.predictor - Preparing depot deadhead trips...
2026-03-05 00:46:03,226 [INFO] routee.transit.predictor - Building CompassApp from bounding box: (-112.03101, 40.22523, -111.65814, 40.482409999999994)
2026-03-05 00:47:28,952 [INFO] nrel.routee.compass.io.generate_dataset - running pipeline import with phases: [['GRAPH', 'CONFIG', 'POWERTRAIN']]
2026-03-05 00:47:28,953 [INFO] nrel.routee.compass.io.generate_dataset - processing graph topology and speeds
2026-03-05 00:47:29,509 [INFO] nrel.routee.compass.io.generate_dataset - adding grade information
2026-03-05 00:47:30,102 [INFO] nrel.routee.compass.io.utils - downloading n41w113
2026-03-05 00:47:30,879 [INFO] nrel.routee.compass.io.utils - downloading n41w112
2026-03-05 00:47:33,278 [INFO] nrel.routee.compass.io.generate_dataset - processing vertices
2026-03-05 00:47:33,281 [INFO] nrel.routee.compass.io.generate_dataset - processing edges
2026-03-05 00:47:36,831 [INFO] nrel.routee.compass.io.generate_dataset - writing vertex files
2026-03-05 00:47:37,538 [INFO] nrel.routee.compass.io.generate_dataset - writing edge files
2026-03-05 00:47:40,039 [INFO] nrel.routee.compass.io.generate_dataset - writing edge attribute files
2026-03-05 00:47:44,450 [INFO] nrel.routee.compass.io.generate_dataset - copying default configuration TOML files
2026-03-05 00:47:44,500 [INFO] nrel.routee.compass.io.generate_dataset - downloading the default RouteE Powertrain models
2026-03-05 00:48:58,740 [INFO] nrel.routee.compass.io.generate_dataset - copying vehicle configuration files
2026-03-05 00:48:58,746 [INFO] nrel.routee.compass.io.generate_dataset - running 2 dataset generation hooks
2026-03-05 00:49:19,885 [INFO] gtfs_processing - Wrote 119313 stop-edge mappings to reports/saltlake/compass_app/gtfs_stops.csv
2026-03-05 00:49:19,978 [INFO] gtfs_processing - Copied transit_energy.toml to reports/saltlake/compass_app/transit_energy.toml
graph edge list 0: /home/runner/work/routee-transit/routee-transit/docs/examples/reports/saltlake/compass_app/edges-compass.csv.gz: 46711it [00:00, 1660470.62it/s]2026-03-05 00:49:23,090 [INFO] routee.transit.predictor - CompassApp initialized
building adjacencies: 100%|██████████| 46711/46711 [00:00<00:00, 4233188.50it/s]
building adjacencies: 100%|██████████| 46711/46711 [00:00<00:00, 4224197.50it/s]
2026-03-05 00:49:23,091 [INFO] routee.transit.predictor - Routing mid-block deadhead trips...
2026-03-05 00:49:23,093 [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, 10635.92it/s]
applying input plugin 2: 100%|██████████| 3/3 [00:00<00:00, 112237.65it/s]
search: 100%|██████████| 3/3 [00:00<00:00, 94.01it/s]
2026-03-05 00:49:23,194 [INFO] routee.transit.predictor - Added 7 mid-block deadhead trips
2026-03-05 00:49:23,194 [INFO] routee.transit.predictor - Routing depot deadhead trips...
2026-03-05 00:49:23,197 [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, 52949.28it/s]
applying input plugin 2: 100%|██████████| 3/3 [00:00<00:00, 170019.84it/s]
search: 100%|██████████| 3/3 [00:00<00:00, 37.16it/s]
2026-03-05 00:49:23,299 [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, 53504.55it/s]
applying input plugin 2: 100%|██████████| 3/3 [00:00<00:00, 168133.16it/s]
search: 100%|██████████| 3/3 [00:00<00:00, 69.88it/s]
2026-03-05 00:49:23,392 [INFO] routee.transit.predictor - Added 18 depot deadhead trips
2026-03-05 00:49:23,393 [INFO] routee.transit.predictor - Predicting energy for 1 vehicle model(s)...
2026-03-05 00:49:24,738 [INFO] routee.transit.predictor - Running map matching for 13 shapes...
map matching: 15%|█▅ | 2/13 [00:00<00:00, 18.53it/s]
map matching: 31%|███▂ | 4/13 [00:00<00:00, 13.19it/s]
map matching: 62%|██████▃ | 8/13 [00:00<00:00, 13.71it/s]
map matching: 77%|███████▆ | 10/13 [00:00<00:00, 13.74it/s]
map matching: 85%|████████▅ | 11/13 [00:01<00:00, 10.82it/s]
map matching: 92%|█████████▃| 12/13 [00:01<00:00, 9.36it/s]
map matching: 100%|██████████| 13/13 [00:01<00:00, 8.49it/s]
2026-03-05 00:49:26,482 [INFO] routee.transit.predictor - Running energy prediction via CompassApp for: Transit_Bus_Battery_Electric
calculating paths: 100%|██████████| 13/13 [00:00<00:00, 875.24it/s]
2026-03-05 00:49:26,525 [INFO] routee.transit.predictor - Adding HVAC energy impacts...
Downloaded: G4900350.csv
Downloaded: G4900490.csv
Downloaded: G4900450.csv
Downloaded: G4900110.csv
Downloaded: G4900570.csv
Downloaded: G4900030.csv
Downloaded: G4900430.csv
2026-03-05 00:49:29,158 [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
Adds road grade information using USGS elevation data
Predicts energy consumption with RouteE-Powertrain
Adds estimated HVAC energy impacts
Saves results to CSV files
Let's examine the results:
print(trip_results.head())
energy_used miles vehicle energy_unit \
0 16.953909 15.492026 Transit_Bus_Battery_Electric kWh
1 16.011903 15.492026 Transit_Bus_Battery_Electric kWh
2 44.525431 15.492026 Transit_Bus_Battery_Electric kWh
3 12.586445 15.492026 Transit_Bus_Battery_Electric kWh
4 12.573726 15.492026 Transit_Bus_Battery_Electric kWh
trip_id route_id service_id block_id \
0 5181298_to_5181301 2152 4 1156079
1 5181298_to_5181301 2152 4 1156079
2 5181298_to_5181301 2152 4 1156079
3 5181297_to_5181299 2152 4 1156088
4 5181297_to_5181299 2152 4 1156088
shape_id route_short_name ... agency_id \
0 -111.712,40.276->-111.895,40.426 None ... NaN
1 -111.712,40.276->-111.895,40.426 None ... NaN
2 -111.712,40.276->-111.895,40.426 None ... NaN
3 -111.712,40.276->-111.895,40.426 None ... NaN
4 -111.712,40.276->-111.895,40.426 None ... NaN
trip_type start_time end_time trip_duration_minutes trip_count \
0 mid_block_deadhead 06:55:00 07:22:00 27.0 87
1 mid_block_deadhead 06:55:00 07:22:00 27.0 87
2 mid_block_deadhead 06:55:00 07:22:00 27.0 87
3 mid_block_deadhead 07:25:00 07:52:00 27.0 87
4 mid_block_deadhead 07:25:00 07:52:00 27.0 87
from_trip to_trip scenario hvac_energy_kWh
0 5181298 5181301 median 4.607329
1 5181298 5181301 summer 3.665324
2 5181298 5181301 winter 32.178852
3 5181297 5181299 median 0.239866
4 5181297 5181299 summer 0.227146
[5 rows x 22 columns]
Calculate Energy Efficiency Metrics#
We can calculate energy efficiency in kWh per mile, including HVAC loads. The results now include a 'scenario' column (summer/winter) for HVAC impacts.
if "scenario" in trip_results.columns:
trip_results["kwh_per_mi"] = trip_results["energy_used"] / trip_results["miles"]
print(trip_results.groupby("scenario")["kwh_per_mi"].mean())
scenario
median 1.668295
summer 1.957103
winter 5.350892
Name: kwh_per_mi, dtype: float64
Access Additional Results#
After running predictions, you can access link-level results and RouteE inputs:
# Link-level predictions show energy for each road segment
link_results = predictor.get_link_predictions()
print(link_results.head())
match_id edge_index edge_list_id edge_id edge_distance trip_distance \
0 0 0 0 30126 0.025420 0.025420
1 0 1 0 30127 0.029904 0.055324
2 0 2 0 246 0.091411 0.146736
3 0 3 0 40098 0.020931 0.167667
4 0 4 0 259 0.017637 0.185304
trip_soc trip_time edge_energy_electric edge_turn_delay ... \
0 0.999840 0.055813 0.080132 0.0 ...
1 0.999494 0.138138 0.172851 1.0 ...
2 0.999959 0.497176 -0.232710 9.5 ...
3 0.999906 0.551467 0.026962 0.5 ...
4 0.999897 0.582071 0.004460 0.0 ...
edge_speed battery_capacity trip_energy_electric trip_elevation_loss \
0 27.327045 500.0 0.080132 0.000000
1 27.327045 500.0 0.252983 0.000000
2 27.327045 500.0 0.020274 -0.006952
3 27.327045 500.0 0.047235 -0.006952
4 34.578084 500.0 0.051695 -0.007189
edge_grade geometry \
0 0.034760 LINESTRING (-111.71143 40.27542, -111.71156 40...
1 0.088317 LINESTRING (-111.71166 40.27568, -111.71109 40...
2 -0.076052 LINESTRING (-111.71109 40.27571, -111.71139 40...
3 0.001036 LINESTRING (-111.71275 40.27596, -111.71275 40...
4 -0.013422 LINESTRING (-111.71305 40.27608, -111.7131 40....
shape_id vehicle energy_used \
0 -111.712,40.276->-111.895,40.426 Transit_Bus_Battery_Electric 12.34658
1 -111.712,40.276->-111.895,40.426 Transit_Bus_Battery_Electric 12.34658
2 -111.712,40.276->-111.895,40.426 Transit_Bus_Battery_Electric 12.34658
3 -111.712,40.276->-111.895,40.426 Transit_Bus_Battery_Electric 12.34658
4 -111.712,40.276->-111.895,40.426 Transit_Bus_Battery_Electric 12.34658
energy_unit
0 kWh
1 kWh
2 kWh
3 kWh
4 kWh
[5 rows x 22 columns]