Two questions. Is the pole-detection method sound, and were the circuits traced from the utility sheet put in the right place on the map? Both were re-derived from the raw data rather than taken from the handoff note.
The idea and the implementation are right, and I reproduced every published number. The significance test leans on an idealised null; replacing it with the observed one drops the headline from 31 poles on 5 lines to 25 on 4.
The quoted 10 m accuracy is the training residual of the fit that produced it. Held out, the same procedure is about twice as bad. 74% of the delivered circuit vertices lie under 1 m from a road because they were snapped there.
A pole is a poor LiDAR target: it is vertical, the scanner looks down, and at 7.8 pts/m² one pole returns roughly 3 to 25 points. Detecting poles as objects fails, because "tall, dense, connected" describes a tree. The method instead detects the line: poles hold a near-constant setback from the road over hundreds of metres and trees do not. Candidates are found per road, runs sharing a common perpendicular offset are extracted, and each run is tested against a null built from that road's own candidate count. Surviving roads then go through Benjamini-Hochberg.
That chain is well-posed, and the code does what its docstrings claim. Re-running it from the LAZ reproduced all 16 candidate lines and their p-values to Monte Carlo noise (Adkinson Street 8 of 11; Factory Street 3 of 11 at p ≈ 0.61, both as documented). The criticisms below are about the null, not the idea.
Each test asks: scatter this road's candidates at random, how often does a run this
big appear? "At random" is implemented as offsets drawn from
Uniform(−20 m, +20 m). That is an assumption about where non-pole clutter
sits, and everything downstream — including the FDR correction — inherits it.
So the marginal is not grossly wrong. The problem is that the statistic is extremely sensitive to mild concentration: the run test counts candidates falling within a 3 m window, and modest crowding raises the chance of that a great deal. Substituting the observed offsets for the idealised ones is therefore worth doing, and it changes the answer.
| Pole line | poles / cands | p uniform | p empirical | At FDR 10% |
|---|
31 poles on 5 lines becomes 25 poles on 4. Claxton Avenue's 7 poles — 23% of the published count — rest on the uniform assumption. The four survivors are well clear of the cutoff and are not in doubt.
One bookkeeping note on the table above: its "p uniform" column is this audit's own re-run at 8,000 trials, which accepts six lines, not the five the shipped run accepted at 4,000. Simmons Street sits on the boundary and flips between the two. That instability is itself a finding, and it is the subject of the next section; the empirical column is stable across every variant tried.
Two things corroborate this. A null built only from roads that produced no run at all — so it cannot contain the signal — gives the identical four. And the handoff note itself records that "all lines confirmed on geometry alone" numbered four; Claxton entered only when the map prior was used to relax the threshold.
The BH boundary sits at p ≈ 0.03, and with a few thousand permutation trials a p-value there carries a standard error near 0.003. Re-running the same code with a different draw changes the published count:
| trials | lines | poles | run |
|---|
Anything with p between 0.02 and 0.05 is a coin flip. Raising the trial count and reporting a confidence interval on each p-value would fix this.
The colour sheet is separated in HSV: blue is the primary circuits, pink is the road right-of-way. The fit is anchored on pink, not blue, and that is the right call — circuits sit about 9 m off the centreline by construction, so fitting circuits to roads would bake that error in. A coarse scale/rotation search is followed by a local refinement: the sheet is hand-held paper, so block-wise cross-correlation of road ink against the OSM raster gives a shift per block and a thin-plate spline smooths them into a displacement field.
The reasoning is sound and the engineering is careful. The problem is the number attached to it.
The test the pipeline does not do: fit on half the road network and score on the half it never saw. Both fits below are scored against the same held-out raster, so the sparser-target effect is held constant and only generalisation differs.
And the 10 m describes the road ink, which is what was fitted. The circuits — the actual deliverable — sit at 41.2 m median from the nearest road under the same fit, with only 38% within 30 m.
After tracing, route vertices are snapped onto roads within 35 m. Measuring the GeoJSON the viewer draws:
circuits.geojsonSo the circuits follow the streets on screen because they were snapped to the streets, not because the georeferencing placed them there. The snap tolerance, 35 m, is over three times the claimed registration accuracy — the snapping is doing more work than the registration. The unsnapped quarter is where the true error is visible, and it is large.
Snapping is not itself wrong: distribution circuits really do follow roads, so it is a reasonable prior. But it destroys the ability to judge the registration from the result, and it should be reported as an assumption rather than absorbed silently.
| Where | What | Effect |
|---|---|---|
fuse_with_map.py |
Circuit coverage is stored per road segment ("Claxton Avenue|767") but
collapsed to the bare name with max(). Nine unnamed segments
spanning coverage 0.08–1.00 collapse to a single 1.00. |
latent Changes nothing here — 36 of 37 segments are energised anyway and the one that is not produced no run — but it is wrong, and would bite on a larger tile. |
requirements.txt |
No LAZ decompression backend, so laspy.read raises on the only input
detect_poles and road_circuits take. |
blocking Neither module could run as shipped. Fixed by
pinning laspy[lazrs]. |
detect_poles.py |
offset_runs() takes a line parameter it never uses. |
cosmetic Harmless; the null passes None. |
| Stated rationale | The map prior is justified as removing the multiple-comparison cost, but the handoff also records that 34 of 37 roads are energised. | reasoning The prior barely discriminates, yet it is what licenses relaxing a flat p < 0.01 to BH at 10%, which admits more lines. |
Nothing in the present data can validate the registration, because every available check reuses the roads the fit consumed. The handoff's own open question 5 — GPS for a sample of poles — is precisely the missing piece. A dozen surveyed positions would give an independent error estimate for the circuits and the LiDAR detections at once.
Three changes to the code follow from this audit:
fuse_with_map./data/datasets/OD/elba, not from the handoff. The detector was re-executed
from tile_2021.laz; the registration harness reproduces the pipeline's own
console output exactly before any change is made. Two errors in an earlier pass of this
audit were caught and corrected: candidates were first keyed by road name, which collapsed
segments sharing a name, and the first empirical null resampled with replacement, which
manufactures duplicate offsets and inflates null run sizes. Both are fixed in the numbers
above.