slv.measurements.mobile.transects#

TRAX transect matrices: obs[transect, point] over the 50-m network points.

Two generations of matrices:

  • Network matrices (this builder, 2026-09-24) — one matrix over the 50-m network points of load_trax_network_points() (1,397 points; shared track is one row of points), built from obs.parquet by build_network_transects(). Every transit of every line is a row, tagged with its line, direction and time, so pooling the lines is a concatenation and a source on the downtown trunk is scored once from all passes. Written per year by build_trax_transects() to $SLV_USER_DATA_DIR/trax/transects/network/ and read back by load_network_transects().

  • Archived per-line matrices (Logan Mitchell’s algorithm as rewritten in 2022; Dec 2014 – Apr 2023, single 9-s inlet lag, built from the duplicated-row parquet) — read by load_transects(). Provenance and cross-checks only.

The builder is Mitchell et al. (2018)’s algorithm on the generic pieces in lair.transects, with the TRAX specifics here:

  1. the on-track rows of obs.parquet (load_trax_obs(), so calibration provenance, the epoch offsets and the location classifier all apply);

  2. each sample is moved to where its air was taken in, lag_s earlier along the track (lair.transects.lag_positions()), with the lag of its instrument epoch (inlet_lag_seconds());

  3. samples snap to the nearest network point (60 m, like the STILT crossings);

  4. the line the train is on is resolved per sample by a vote among the letters of its own point: the line with the most single-line points hit within ±30 min (assign_lines());

  5. that line’s along-route coordinate is cut into one-way transits at reversals of travel and at gaps (lair.transects.split_transits()), and the samples are averaged onto [transit, point] with terminus dwells trimmed (lair.transects.transect_matrix()).

Coverage and short transits. Unlike the archived per-line matrices – built by chasing terminus polygons, so every row was (close to) a full end-to-end run – this builder keeps any one-way run of at least min_span_m, including short turns that never reach the line’s ends (a car shuttling Salt Lake Central <-> a few km out, real UTA service, ~15% of Red and ~29% of Green transits by span in the 2014-2026 record) and partial runs cut short by a mid-route reversal. Each transit’s coverage coordinate is its span over that line’s full known extent; a persistence metric that baselines a transit against its own low percentile (lair.transects.enhancement()) should filter on coverage first; a short loop that sits in a plume the whole way reads as background against itself. See sources/persistence/ for the filter in use.

Attributes

NETWORK_DIR

Sub-directory of $SLV_USER_DATA_DIR/trax/transects/ holding the network matrices.

Functions

assign_lines

The line letter each sample is on, resolved from the points around it in time.

build_network_transects

Build the [transect, point] matrix of one obs frame on the network points.

build_trax_transects

Build and write the network matrices, one NetCDF per calendar year.

load_network_transects

The network transect matrices of years (all on disk by default), concatenated along transect with a fresh 0..N-1 index.

load_transects

Concatenate the archived transect matrices for one TRAX line into an xarray Dataset.

network_transects_dir

The network transects folder: NETWORK_DIR under transects_dir, by default trax/transects in the user data directory.