navi/backend/services/navi_offroute
Matt e65c5b15f8 navi-offroute: numpy-pack TrailheadIndex (memory opt #2)
Apply the proven OSMParkingIndex (PR #31) memory-pack pattern to TrailheadIndex,
which the 2026-05-26 memory audit flagged at ~300-450 MB/worker using the old
list[dict]+list[Point] storage.

- mvum_transitions.py: store coords as packed float64 numpy arrays (_lats/_lons)
  and attributes as interned lists (_names/_road_classes); build candidate record
  dicts lazily via _record(i) in query_trailheads_near_line instead of holding
  740k dicts + 740k shapely Point objects. Points are built only to construct the
  STRtree, then released. Adds a records property (lazy, for tests/introspection)
  and tracks build_time_seconds + memory_estimate_mb (psutil RSS delta) like
  OSMParkingIndex. Query logic (coarse STRtree bbox + precise degree-distance
  check) unchanged.
- admin.py: GET /api/admin/trailhead/info -> {count, build_time_seconds,
  memory_estimate_mb}, mirroring /api/admin/osm-parking/info.

Tests: existing test updated (len(records)==count; the removed _points assertion)
plus a numpy-backing test (_lats/_lons dtype float64, len==count). Full offroute
suite: 83 passed.

Real-DB sanity (not deployed): index loads 740,430 entry points in ~4.8 s using
~285 MB RSS (down from the audit's inferred ~300-450 MB; same ~40% pack ratio as
parking), query returns 317 trailheads on a Redfish Lake corridor.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 22:44:10 +00:00
..
tests navi-offroute: numpy-pack TrailheadIndex (memory opt #2) 2026-05-26 22:44:10 +00:00
__init__.py Add navi-offroute service (extraction #8 — final) (#10) 2026-05-22 23:30:43 -06:00
admin.py navi-offroute: numpy-pack TrailheadIndex (memory opt #2) 2026-05-26 22:44:10 +00:00
app.py MVUM Layer 3b: OSM parking as multi-modal Auto transition candidates (#31) 2026-05-26 14:48:35 -06:00
astar.py fix(offroute): smooth max_grade penalty instead of hard cliff (DEM noise robustness) 2026-05-25 15:34:18 +00:00
barriers.py Add navi-offroute service (extraction #8 — final) (#10) 2026-05-22 23:30:43 -06:00
cost.py Rename mode constants: mtb→2w, atv→4w (#20) 2026-05-25 15:33:47 -06:00
friction.py Add navi-offroute service (extraction #8 — final) (#10) 2026-05-22 23:30:43 -06:00
mvum.py MVUM Layer 0: spatial index foundation (#22) 2026-05-25 18:53:58 -06:00
mvum_annotate.py MVUM Layer 1: per-edge annotation + accurate closure counts (#23) 2026-05-25 19:32:43 -06:00
mvum_exclude.py MVUM Layer 2c: exclude_polygons for closure-avoiding routing (#24) 2026-05-25 19:54:28 -06:00
mvum_parking.py MVUM Layer 3b: OSM parking as multi-modal Auto transition candidates (#31) 2026-05-26 14:48:35 -06:00
mvum_surface_change.py MVUM Layer 3c: surface-change transition candidates (#27) 2026-05-25 23:52:08 -06:00
mvum_transitions.py navi-offroute: numpy-pack TrailheadIndex (memory opt #2) 2026-05-26 22:44:10 +00:00
offroute_route.py MVUM Layer 3b: OSM parking as multi-modal Auto transition candidates (#31) 2026-05-26 14:48:35 -06:00
router.py MVUM Layer 3b: OSM parking as multi-modal Auto transition candidates (#31) 2026-05-26 14:48:35 -06:00
trails.py Add navi-offroute service (extraction #8 — final) (#10) 2026-05-22 23:30:43 -06:00