Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
87d903e
Assess Denver, and freeze the inventories so Stage 1 can be replicate…
jonfroehlich Jul 31, 2026
7279959
Sweep the geometry gate across all nine cities -- and correct the Den…
jonfroehlich Jul 31, 2026
259407c
Make the review sheet usable: toggleable overlay, 4x imagery, click-t…
jonfroehlich Jul 31, 2026
d482fef
Verify the review sheet is registered and scaled, rather than asserti…
jonfroehlich Jul 31, 2026
9251977
Put the review rubric inside the instrument, not in the reviewer's he…
jonfroehlich Jul 31, 2026
6058bf1
Prove the review sheet's page logic runs, not just that it contains s…
jonfroehlich Jul 31, 2026
1331e60
Say what the 2016 imagery choice costs, not just what it buys (#96)
jonfroehlich Jul 31, 2026
3f95381
Stop the per-corner comparison crying wolf on large corners (#96)
jonfroehlich Jul 31, 2026
f2b0599
Show the published records instead of judging them (#96)
jonfroehlich Jul 31, 2026
fb7128e
Stamp the sheet with a build id, and make the markers findable (#96)
jonfroehlich Jul 31, 2026
186a76b
Put the build id where it can be seen (#96)
jonfroehlich Jul 31, 2026
000a7a8
Hold the published data until BOTH of the chip's own numbers are reco…
jonfroehlich Jul 31, 2026
7ddd831
Record what the review sheet structurally cannot measure (#96)
jonfroehlich Jul 31, 2026
53239c2
Jon's Denver review, 58/59, and the reduction that makes it a number …
jonfroehlich Jul 31, 2026
022bc6d
Denver is Good: 92.3% of records within 1 m of the ramp (#96, #59)
jonfroehlich Jul 31, 2026
e53d225
Stage 1 uses only the BEARING, so the tolerance is angular (#96, #59)
jonfroehlich Jul 31, 2026
63cc7ca
Probe the basemaps for the two calibration cities (#96)
jonfroehlich Jul 31, 2026
b01a09c
Freeze Seattle, and catch its basemap problem before booking a review…
jonfroehlich Jul 31, 2026
dea603c
Seattle's offset is a SHIFT, not imprecision -- caught by Jon, now au…
jonfroehlich Jul 31, 2026
7a482b8
Seattle's 2.06 m is not a registration error -- both frames clear at …
jonfroehlich Jul 31, 2026
38bb0a3
Don't track the chips run's duplicate registration PNGs (#96)
jonfroehlich Jul 31, 2026
56db3e8
Stage 1 records its own registration error -- no gov files needed (#96)
jonfroehlich Aug 2, 2026
d17c5d6
Rebuild Charlotte's sheet: 1 of 60 chips becomes 60 of 60 (#96)
jonfroehlich Aug 2, 2026
e554c5e
Record the Charlotte 404 trap in the doc, not just the commit log (#96)
jonfroehlich Aug 2, 2026
c06da5c
Charlotte is Good, and its bad records carry a null date (#96)
jonfroehlich Aug 3, 2026
17f7f4c
Charlotte's review is HIGH confidence, and the value travels with the…
jonfroehlich Aug 3, 2026
3c9dc33
Grade a basemap where it will be USED, not at one downtown point (#96)
jonfroehlich Aug 3, 2026
78f0279
Sample the review sheet by install-date stratum, not by whatever a ci…
jonfroehlich Aug 3, 2026
af6a97d
Seattle's stratified 2025 sheet: 60 chips, 20 per date stratum (#96)
jonfroehlich Aug 3, 2026
3fe720c
Seattle is imprecise, not confounded -- and Charlotte's rule does not…
jonfroehlich Aug 3, 2026
c9ce711
Seattle's 2025 review is MEDIUM confidence (#96)
jonfroehlich Aug 3, 2026
479a436
Supply is not the constraint, and never was: ~2M candidate records (#96)
jonfroehlich Aug 3, 2026
d03c3e5
Write the 5n I promised, and file the tool as #103 (#96)
jonfroehlich Aug 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,61 @@ analysis_out/op/*
!analysis_out/op/*.csv
!analysis_out/op/*.json

# Stage 1's coordinate-tolerance result (#96): a few KB, and it is what converts an
# offset distribution into a decision. Re-derivable on CPU from the committed
# benchmark bundles plus any verdicts file.
!analysis_out/stage1_offset_tolerance.json
# Per-city tolerance runs (--verdicts <city>), e.g. charlotte-nc. Same few KB, and
# they are what turn a city's offset distribution into a labels-lost number.
!analysis_out/stage1_offset_tolerance_*.json

# Stage 1's realised bearing residual (#96): a few KB, and it is the null that makes
# any future city's registration number interpretable. Regenerating it needs a Hub
# fetch, so committing it keeps the 5j table checkable from a clean checkout.
!analysis_out/stage1_bearing_residual.json

# E1's result (#59): a few KB, and committing it makes the label-ceiling numbers
# checkable without re-running the Hub fetch the script needs to regenerate them.
!analysis_out/e1_stage1_label_recall.json
!analysis_out/miss_decomposition.json

# Per-ramp/per-corner geometry reports (#96): a few KB each, and they hold the exact
# numbers quoted in docs/curb_ramp_data_sourcing.md 5d, re-derivable on CPU from the
# committed snapshots under data/inventories/.
!analysis_out/inventory_geometry_*.json

# Location-precision review sheets (#96). The verdicts -- and the tile keys recording
# which imagery produced them -- are the irreplaceable part, so verdicts.json is tracked.
# review_sheet.html is not: it embeds basemap tiles under terms that do not permit
# re-hosting, and it regenerates from the committed script plus the recorded seed. The
# tile caches beside it are likewise someone else's imagery.
!analysis_out/review_*/
analysis_out/review_*/*
!analysis_out/review_*/verdicts.json
# summary.json too: it is the reduction quoted in 5f, a few KB, and committing it
# means a reader can check a figure in the prose against the table it came from
# without re-running anything. Regenerable from verdicts.json by
# scripts/analysis/inventory_review_summary.py.
!analysis_out/review_*/summary.json

# Georeference check (#96): the JSON is the evidence that the sheet's crosshair and
# rings are true, and the two PNGs are what a reader looks at to agree. Small, and
# the whole point is that a claim of correct registration is checkable rather than
# asserted. The tile cache beside them is someone else's imagery.
# One directory per city since §5i (georef_check_denver-co, georef_check_seattle-wa),
# plus the _chips variant that measures under a specific review's own verdicts.
!analysis_out/georef_check_*/
analysis_out/georef_check_*/*
!analysis_out/georef_check_*/georef_check.json
!analysis_out/georef_check_*/registration_*.png
# The _chips variant re-renders the SAME two visual sites as its city's run, so
# its PNGs are duplicates; only its JSON says anything new (the per-chip medians).
analysis_out/georef_check_*_chips/registration_*.png

# Ramps vs the city's own centrelines (§5i). Numbers only, no imagery — this is
# the leg that exonerated Seattle's coordinates, so it has to be checkable.
!analysis_out/centerline_offset_*.json

# Claude Code local state. settings.local.json is per-machine (absolute paths,
# session ids) and worktrees/ holds full repo checkouts -- gigabytes. Listed
# individually rather than ignoring all of .claude/, so a shared
Expand All @@ -64,3 +114,15 @@ benchmark/*/index.csv
# scripts/model_comparison/yolo_baseline/README.md, "Where the weights live").
*.pt
*.pth

# Cached parquet columns for scripts/analysis/stage1_bearing_residual.py.
# Derived from the published HF dataset on demand; regenerable with --refresh.
analysis_out/stage1_bearing_cache/

# At-the-sites basemap probes (#96): a few KB each, and they carry the paired
# vegetation/coverage numbers a tile-source choice is justified by.
!analysis_out/probe_sites_*.json

# Inventory discovery sweep (#96): the candidate list, with record counts. A few
# tens of KB, and it is the evidence that supply is not the constraint.
!analysis_out/inventory_discovery.json
114 changes: 114 additions & 0 deletions analysis_out/centerline_offset_denver-co.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
{
"centerline_paths": 7966,
"centerlines": "denver-co-centerlines-2026-07-31.jsonl.gz",
"city": "denver-co",
"interpretation": "Measures the ramp coordinates against the SAME publisher's street geometry, so it is blind to any error the two layers share. A shift near zero means the coordinates are consistent with their own city's road network: any offset the reviewer saw against imagery is then in the frame (datum, reprojection or basemap registration) and is a constant that can be subtracted. A shift matching the reviewer's means the defect is in the ramp layer itself and no constant fixes it.",
"inventory": "denver-co-2026-07-31.jsonl.gz",
"limits": "A centreline is a cartographic construct, not a survey of the pavement midline, and this estimator assumes only that it is unbiased BETWEEN the two sides of the street -- it never uses its absolute position, which is what makes it robust to that. It cannot see an error the ramp and centreline layers share, by construction; that is what verify_chip_georeference.py is for. Cluster overlap attenuates the estimate toward zero when the half-width is small relative to the spread, so a near-zero reading is weaker evidence than a large one.",
"max_dev_deg": 20.0,
"max_dist_m": 25.0,
"near_cardinal": {
"east_west": 38547,
"north_south": 36081
},
"ramps": 72770,
"result": {
"axes": {
"east": {
"half_width_m": 7.348486962728202,
"iqr_neg_m": [
-8.911230517551303,
-5.747113466262817
],
"iqr_pos_m": [
5.597882028669119,
8.774632066488266
],
"median_neg_m": -7.466750402003527,
"median_pos_m": 7.230223523452878,
"n": 49594,
"n_neg": 24807,
"n_pos": 24787,
"shift_ci95_m": [
-0.13743286952376366,
-0.09783872496336699
],
"shift_m": -0.11826343927532434
},
"north": {
"half_width_m": 7.459344879258424,
"iqr_neg_m": [
-9.21053040586412,
-5.859040271490812
],
"iqr_pos_m": [
5.8847334291785955,
9.200584521517158
],
"median_neg_m": -7.454281134530902,
"median_pos_m": 7.464408623985946,
"n": 49404,
"n_neg": 24644,
"n_pos": 24760,
"shift_ci95_m": [
-0.017781874863430858,
0.024741371627897024
],
"shift_m": 0.005063744727522135
}
},
"bearing_deg": 272.451764426082,
"half_width_band_m": [
3.0,
20.0
],
"half_width_plausible": true,
"resultant_m": 0.11837179807662734,
"shift_east_m": -0.11826343927532434,
"shift_north_m": 0.005063744727522135,
"sign_convention": "Positive east means the PUBLISHED RAMP POINT lies east of where the centreline geometry puts the street, i.e. the coordinate is east of the true ramp. This is the same sense the review sheet reports, so the two are directly comparable and must not be negated."
},
"segments": 114021,
"sweep": [
{
"max_dev_deg": 10.0,
"n_east": 47259,
"n_north": 46789,
"resultant_m": 0.12162942143892518,
"shift_east_m": -0.12154968967661262,
"shift_north_m": 0.004403305472806096
},
{
"max_dev_deg": 15.0,
"n_east": 48504,
"n_north": 48283,
"resultant_m": 0.12009124199139472,
"shift_east_m": -0.12005011225119233,
"shift_north_m": 0.003142761765047908
},
{
"max_dev_deg": 20.0,
"n_east": 49594,
"n_north": 49404,
"resultant_m": 0.11837179807662734,
"shift_east_m": -0.11826343927532434,
"shift_north_m": 0.005063744727522135
},
{
"max_dev_deg": 25.0,
"n_east": 51000,
"n_north": 50817,
"resultant_m": 0.11641682097028895,
"shift_east_m": -0.11626110132783651,
"shift_north_m": 0.0060193457175046206
},
{
"max_dev_deg": 30.0,
"n_east": 52417,
"n_north": 52392,
"resultant_m": 0.11152097366727215,
"shift_east_m": -0.11143287783488631,
"shift_north_m": 0.0044318512082099915
}
]
}
114 changes: 114 additions & 0 deletions analysis_out/centerline_offset_seattle-wa.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
{
"centerline_paths": 34484,
"centerlines": "seattle-wa-centerlines-2026-07-31.jsonl.gz",
"city": "seattle-wa",
"interpretation": "Measures the ramp coordinates against the SAME publisher's street geometry, so it is blind to any error the two layers share. A shift near zero means the coordinates are consistent with their own city's road network: any offset the reviewer saw against imagery is then in the frame (datum, reprojection or basemap registration) and is a constant that can be subtracted. A shift matching the reviewer's means the defect is in the ramp layer itself and no constant fixes it.",
"inventory": "seattle-wa-2026-07-31.jsonl.gz",
"limits": "A centreline is a cartographic construct, not a survey of the pavement midline, and this estimator assumes only that it is unbiased BETWEEN the two sides of the street -- it never uses its absolute position, which is what makes it robust to that. It cannot see an error the ramp and centreline layers share, by construction; that is what verify_chip_georeference.py is for. Cluster overlap attenuates the estimate toward zero when the half-width is small relative to the spread, so a near-zero reading is weaker evidence than a large one.",
"max_dev_deg": 20.0,
"max_dist_m": 25.0,
"near_cardinal": {
"east_west": 56178,
"north_south": 80645
},
"ramps": 38364,
"result": {
"axes": {
"east": {
"half_width_m": 6.241083346307278,
"iqr_neg_m": [
-8.479622146114707,
-4.798670271411538
],
"iqr_pos_m": [
4.738980691879988,
8.389321817085147
],
"median_neg_m": -6.241670722141862,
"median_pos_m": 6.240495970472693,
"n": 31430,
"n_neg": 15746,
"n_pos": 15684,
"shift_ci95_m": [
-0.0011285701766610146,
0.00015931949019432068
],
"shift_m": -0.0005873758345842361
},
"north": {
"half_width_m": 6.256053883582354,
"iqr_neg_m": [
-7.782055872492492,
-4.2723733792081475
],
"iqr_pos_m": [
4.224941612221301,
7.776318969205022
],
"median_neg_m": -6.256016336381435,
"median_pos_m": 6.256091430783272,
"n": 30809,
"n_neg": 15463,
"n_pos": 15346,
"shift_ci95_m": [
4.033325240015984e-06,
7.086689583957195e-05
],
"shift_m": 3.754720091819763e-05
}
},
"bearing_deg": 273.65757824963987,
"half_width_band_m": [
3.0,
20.0
],
"half_width_plausible": true,
"resultant_m": 0.0005885746879966207,
"shift_east_m": -0.0005873758345842361,
"shift_north_m": 3.754720091819763e-05,
"sign_convention": "Positive east means the PUBLISHED RAMP POINT lies east of where the centreline geometry puts the street, i.e. the coordinate is east of the true ramp. This is the same sense the review sheet reports, so the two are directly comparable and must not be negated."
},
"segments": 243912,
"sweep": [
{
"max_dev_deg": 10.0,
"n_east": 29547,
"n_north": 29555,
"resultant_m": 0.00035881514778370217,
"shift_east_m": -0.0003569074906408787,
"shift_north_m": 3.695068880915642e-05
},
{
"max_dev_deg": 15.0,
"n_east": 30709,
"n_north": 30292,
"resultant_m": 0.0004877114404616942,
"shift_east_m": -0.0004863874055445194,
"shift_north_m": 3.591296263039112e-05
},
{
"max_dev_deg": 20.0,
"n_east": 31430,
"n_north": 30809,
"resultant_m": 0.0005885746879966207,
"shift_east_m": -0.0005873758345842361,
"shift_north_m": 3.754720091819763e-05
},
{
"max_dev_deg": 25.0,
"n_east": 32136,
"n_north": 31331,
"resultant_m": 0.0006898383046268158,
"shift_east_m": -0.000688822939991951,
"shift_north_m": 3.7414487451314926e-05
},
{
"max_dev_deg": 30.0,
"n_east": 33009,
"n_north": 31854,
"resultant_m": 0.0007770327259020268,
"shift_east_m": -0.0007764431647956371,
"shift_north_m": 3.0263327062129974e-05
}
]
}
Loading
Loading