Methodology
A deliberately simple computer-vision and monitoring stack converted a fixed apartment view into directional traffic time series. This page separates what the system measured from what later analysis infers.
Measurement chain
Old iPhone video stream
↓
OpenCV motion segmentation within a fixed ROI
↓
Contour filtering and persistent object tracking
↓
Virtual counting-line crossing with stable left/right direction
↓
Prometheus counters, gauges, and detector-health metrics
↓
Grafana live dashboard
↓
Historical TSDB archive and static derived datasets
Directional counting
The tracker maintains recent object positions, establishes a stable horizontal direction, and counts an object once when it crosses the configured line. Camera-relative labels are presented as:
| Detector label | Site label |
|---|---|
left |
Oakland-bound |
right |
SF-bound |
This mapping describes the installation geometry. The canonical dataset retains
the original left/right labels so downstream users can audit the
interpretation.
Metrics used by this site
| Metric | Type | Meaning |
|---|---|---|
traffic_vehicles_total |
Counter | Algorithmic crossing detections by direction |
traffic_flow_rate_per_minute |
Gauge | Recent detections per minute by direction |
traffic_speed_current_pixels_per_second |
Gauge | Most recent tracked-object pixel speed |
traffic_speed_average_pixels_per_second |
Gauge | Rolling pixel-speed mean by direction/window |
motion_detector_fps |
Gauge | Detector processing performance |
tracked_objects_active |
Gauge | Objects currently held by the tracker |
system_status |
Gauge | Webcam/detector/tracker health flags |
Derived snapshot
The inspection site currently uses archive-v3, generated by read-only
Prometheus range queries at a five-minute step:
- Queries are split into 21-day chunks to remain below Prometheus resolution limits.
- Imported historical series are excluded from this preliminary direct-series
snapshot using
exported_job="". - UTC timestamps remain the unambiguous source key.
- Pacific time is added for calendar and day-of-week analysis.
- Hour buckets are formed in UTC before conversion, preserving the repeated hour during daylight-saving fallback.
- A direction-day is complete when it has at least 95% of expected samples.
- Expected sample counts account for 23-hour and 25-hour DST days.
- Counter totals use non-negative increments and record negative steps as resets.
- Weekday profiles use only complete direction-days.
- The day × half-hour activity grid uses real 30-minute UTC buckets, each containing up to six five-minute samples; UTC bucketing preserves repeated Pacific half-hours during daylight-saving fallback.
Raw archive plan
The browser snapshot is not the source archive. The exact release will be
produced from a consistency-safe immutable copy of the active TSDB using
promtool tsdb dump-openmetrics, then converted to metric/month Parquet shards.
That workflow preserves exact sample timestamps and all original labels,
including import provenance.
The native TSDB copy and the Parquet representation will both be retained:
- Native TSDB for maximum recovery fidelity.
- Raw Parquet for open analysis and streaming.
- Normalized Parquet for a stable user-facing schema.
- Derived CSV/Parquet for the static site.
Reproducibility
The derived snapshot preparation command is:
uv run python scripts/prepare_static_site_data.py \
--output-dir site/src/data/archive-v3
The exporter refuses to overwrite an existing versioned snapshot. Each snapshot contains:
- Source queries and time bounds
- Timezone and query step
- Row counts and file sizes
- SHA-256 checksums
- Explicit warning that the snapshot is derived rather than lossless
Bay Lights segmentation
The optical environment changed during the 2026 return of The Bay Lights. Snapshot v2 assigns every local date to one of three explicit regimes:
| Regime | Local dates | Interpretation |
|---|---|---|
| Pre-lights | Before 2026-02-19 | Preferred nighttime detector baseline |
| Commissioning | 2026-02-19 through 2026-03-19 | Burn-in, programming, and transition interval |
| Illuminated | 2026-03-20 onward | Official nightly operating era |
February 19 is an approximate analysis boundary: a February 26 contemporary report said all 48,000 LEDs had been twinkling 24/7 for about one week. The official Grand Lighting occurred March 20.
The dataset shows its strongest nighttime noise onset around March 8–12, inside the commissioning interval. The site therefore preserves commissioning as its own category instead of forcing a misleading binary split.
Night-noise diagnostics use a fixed 22:00–05:00 Pacific window. “Spike excess” is the nightly 95th percentile of the five-minute flow metric minus its nightly median. It is a detector-stability diagnostic, not a traffic statistic.
Interpretation boundary
The project supports comparisons across time and direction within one fixed detector. It does not establish absolute bridge throughput, classification by vehicle type, lane-level counts, occupancy, or physical vehicle speed. External transportation conclusions should be cross-checked against an official source.
External validation and calibration boundary
validation-v1 compares complete pre-lights camera days with public MTC and
Caltrans reference data. Caltrans 2024 AADT near Treasure Island reports about
115,000 Oakland-bound and 118,000 SF-bound vehicles per day. Against the
camera’s pre-lights daily means, these imply directional reference ratios of
approximately 2.45× and 1.36× respectively.
The immutable published datasets retain the raw detector values. Traffic count/flow plots default to a reversible presentation transform:
Oakland-bound estimate = raw left detections × 2.447544
SF-bound estimate = raw right detections × 1.356866
Each affected page provides a Raw algorithmic detections option. The factors combine different years and counting methods and cannot account for time-of-day, congestion, weather, occlusion, or lighting-dependent error. The unequal ratios establish that a single global factor would be misleading. The site therefore:
- Publishes raw algorithmic detections without an accuracy claim.
- Applies direction-specific scaling only in the browser presentation layer.
- Labels scaled axes and subtitles as
reference-scaled. - Does not scale coverage, pixel-speed, external-validation, or detector-noise diagnostics.
- Does not infer precision or recall without a manually labeled image sample.
Rebuild the additive validation snapshot with:
uv run python scripts/prepare_external_validation.py \
--output-dir site/src/data/validation-v2
The script downloads the cited public workbooks, records their URLs and checksums for its derived outputs, and refuses to overwrite an existing versioned directory.