Building applications on processed data#

Typical scenarios#

  • Aggregate the performance indices by intersection, corridor or region;

  • diagnose signal timing (offsets, splits, coordination) from trajectories and SPaT;

  • develop and evaluate signal control algorithms;

  • design offline signal plans.

Applications only need mtldp-meta-utils and the processed data of a region.

Step 1: Create the configuration file#

(mtldp) $ create_config_file -n my_corridor -c oakland -m application \
             -s 2025-03-03 -e 2025-03-09 -j 62590214,62590221
Configuration file generated at: `configs/my_corridor.json`

The dates become date_str_list and the junctions junction_id_list; both are the defaults used when loading trajectories. When the data comes from a sub-region of a processed master region, the sub-region configuration produced by the pipeline can be used directly instead (configs/<master>_subs/<tile>.json); its mode is preprocessing but AppRegion accepts it as long as the processed files exist.

Step 2: Create the directory tree#

(mtldp) $ create_region -c configs/my_corridor.json
Directory tree and template files generated.

For an application region only the processed tree is created:

processed_data/my_corridor/
├── calibration/cache
├── figures/pi
├── network/{csv,shapefile}
├── spat
├── tables/{pi,spat_est}
├── trajectories/{raw_pts,points,trajectories/cache}
└── ui

Step 3: Obtain the processed data#

Copy the processed files of the region into the tree: network/traffic_network.pickle (and the GeoJSON files), spat/spat.pickle and trajectories/trajectories/<date>_*.csv. Contact henryliu@umich.edu for access to the processed data sets.

When the region of interest is a corridor spread over several processed regions or sub-regions, copy_regions assembles it (see Command line tools of mtldp-meta-utils); the network then has to be rebuilt with build_traffic_network.

Step 4: Load the region in Python#

from mtldp.utils.config import AppRegion

region = AppRegion('configs/my_corridor.json')      # loads the signalized network and the SPaT

network = region.network                            # SignalizedNetwork
spat = region.spat                                  # HistoryRegionSPaT

# trajectories of the configured dates and junctions, as objects ...
trajs_dict = region.load_trajs_dict(signalized=True)
# ... or as one table
trajs_df = region.load_trajs_df(date_str_list=['2025-03-03'], junction_id_list=['62590214'],
                                signalized=True)

print(network, spat, trajs_dict)

load_trajs_dict caches each day as a pickle in trajectories/trajectories/cache/ on the first call, so that later runs start fast; pass overwrite_buffer=True after the trajectory files have been re-processed. load_points=False skips the per-point lists when only the indices are needed, and load_row_num loads a few rows for debugging.

From here the utilities of Utilities: mtldp.utils apply: mtldp.utils.filter to select trajectories, mtldp.utils.aggregation to aggregate the indices, mtldp.utils.visualizer to draw time-space diagrams with the signal timing, and the SPaT query methods of Data structures: mtldp.meta to get the plan in effect for a movement and a period.