— / live demo / 496 stations / 26 routes / real GTFS geometry
The whole system, and the one event it never reports.
There is no arrival event in the MTA feed. A train that reaches a platform simply stops being predicted for it, and the next snapshot is quietly shorter than the last. Everything this pipeline produces rests on reading that absence correctly — so here it is, running.
Simulation · the same inference as int_inferred_arrivals.sql
Loading the network…
02 / the part the pipeline cares about
Now watch one arrival happen.
The map above is the system. This is the mechanism underneath it, on a single line, slowed down enough to see: the feed publishing, the numbers converging, and a stop dropping off the list at the moment a train reaches it.
Starting the line…
What you are looking at.
- 01
The trains are real objects with real positions
Each one accelerates out of a platform, runs to the next, and dwells there for twenty-odd seconds. The simulation knows exactly where every train is at every instant — which is the one thing production can never know.
- 02
The feed is generated every 30 seconds
For each train it publishes predicted arrivals for its next six stops, with error that grows the further ahead the guess is. That is why the numbers in the table visibly converge as a train closes on a platform.
- 03
An arrival is a column going empty
When a train passes a platform, that stop leaves its prediction list. The pipeline takes the last value the prediction carried and calls it the arrival. Nothing else in the feed marks the event.
- 04
A vanish that was never due is thrown away
A prediction that disappears while still more than two minutes in the future is a cancellation or a re-route, not an arrival. Those are counted separately and dropped — treating them as arrivals would flatter the service exactly when riders are suffering most.
- 05
Then it becomes headway, and excess wait
Consecutive inferred arrivals at one station give headways; headways give excess wait, the time a rider spends beyond what the timetable promised. Press “delay a train” and watch bunching push it up.
- 06
And the error is checkable, here only
Because the simulation has ground truth, every inferred arrival can be compared against where the train actually was. In production that column does not exist, which is the whole reason the rule has to be stated rather than tuned.
The eight feeds this reads from.
Straight out of ingest/feeds.py. There are eight because that is how the MTA groups the lines — no key required for the subway feeds, refreshed roughly every thirty seconds.
- gtfs1 · 2 · 3 · 4 · 5 · 6 · 7 · S
- gtfs-aceA · C · E
- gtfs-bdfmB · D · F · M
- gtfs-gG
- gtfs-jzJ · Z
- gtfs-nqrwN · Q · R · W
- gtfs-lL
- gtfs-siSIR
Read the case studySee the pipeline diagramBack to selected work