Commit graph

643 commits

Author SHA1 Message Date
57578dff4d Add native HRRR duct detection to hourly propagation scoring
The PropagationGridWorker now fetches native hybrid-sigma levels
(TMP, SPFH, HGT, PRES × 50 levels) alongside the standard surface
and pressure products. Native data provides 10-50m vertical spacing
vs 250m from pressure levels, detecting thin surface ducts invisible
to the standard product.

Key design: cell-by-cell reducer in Wgrib2.extract_grid_from_file_mapped
processes each of the 95k CONUS cells through a duct analysis function
inline, keeping only scalar metrics per cell. Peak memory ~86 MB
instead of ~1.8 GB for the full grid map.

Per-cell output: native_min_gradient, best_duct_freq_ghz,
max_duct_thickness_m, duct_count. The scorer prefers the native
gradient over the pressure-level gradient when available.

Native fetch is optional — if it fails, scoring continues with
pressure-level data only.
2026-04-11 13:30:48 -05:00
FluxCD
5a5b1481c9 chore: update prop image to git.mcintire.me/graham/prop:main-1775931628-0389269 [skip ci] 2026-04-11 18:22:07 +00:00
7d68d13dcc Recalibrate scoring weights from gradient descent on 5000 QSOs
Loss improved 72% (0.42 → 0.12). Key changes:
- rain: 0.08 → 0.136 (+70%) — strongest discriminator
- season: 0.08 → 0.111 (+39%)
- wind: 0.05 → 0.08 (+60%)
- refractivity: 0.08 → 0.105 (+31%)
- time_of_day: 0.10 → 0.050 (-50%) — was overweighted by contest bias
- pressure: 0.15 → 0.103 (-31%)
- humidity: 0.18 → 0.124 (-31%)

Validated by native profile backtest (11,431 profiles):
theta_e_jump strongest native discriminator, duct_usable_* and
bulk_richardson dropped as dead features.
2026-04-11 13:20:00 -05:00
FluxCD
664ffc9ef1 chore: update prop image to git.mcintire.me/graham/prop:main-1775931128-5724d7f [skip ci] 2026-04-11 18:15:05 +00:00
d49ec5d32e Drop dead backtest features, document consolidated results
Backtest on 11,431 native profiles (2026-04-11):
- Drop duct_usable_10/24/47ghz (always 1.0, no discrimination)
- Drop bulk_richardson (near-identical QSO vs baseline means)
- Document all feature results with signal strength assessment
- theta_e_jump is strongest native discriminator (44% lift)
- best_duct_freq and duct_thickness show clear physical signal
2026-04-11 13:11:39 -05:00
FluxCD
3077e102fc chore: update prop image to git.mcintire.me/graham/prop:main-1775930206-e873ffc [skip ci] 2026-04-11 17:57:03 +00:00
cebf6f3f69 Speed up rolling deploys: allow surge, reduce startup delay
- maxSurge 0→1: new pods start before old ones terminate
- minReadySeconds 10→5
- startupProbe: initialDelay 10→5s, period 5→3s
2026-04-11 12:56:26 -05:00
FluxCD
b7e0c3bc7a chore: update prop image to git.mcintire.me/graham/prop:main-1775929975-e6e1395 [skip ci] 2026-04-11 17:54:01 +00:00
72051fe5ee Guard against zero specific humidity in theta-e computation 2026-04-11 12:52:32 -05:00
FluxCD
9d5ebc650b chore: update prop image to git.mcintire.me/graham/prop:main-1775927046-d0d6d9a [skip ci] 2026-04-11 17:05:20 +00:00
b1226c6ba1 Update deps: credo, lazy_html, live_stash, fine 2026-04-11 12:03:43 -05:00
f8c78b7282 update deps 2026-04-11 12:03:43 -05:00
FluxCD
0a543e3fb8 chore: update prop image to git.mcintire.me/graham/prop:main-1775920772-8beba7b [skip ci] 2026-04-11 15:20:29 +00:00
c8127fbb02 Update algo.md to match current codebase
- Fix pressure scoring thresholds (finer granularity at <980-990 mb)
- Fix 10 GHz parameters (o2_db_km, h2o_coeff, seasonal Feb/Oct)
- Fix 24 GHz parameters (o2_db_km 0.02, h2o_coeff 0.002)
- Fix 47 GHz o2_db_km (0.04)
- Add 5 new UHF/microwave bands (902-5760 MHz)
- Add Part 12: HRRR native hybrid-sigma levels (50-level profiles)
- Add Part 13: Duct analysis (M-profile, trapped frequency)
- Add Part 14: Inversion analysis (Ri, theta-e, shear)
- Add Part 15: NEXRAD radar data integration
- Add Part 16: Backtest framework (21 features)
2026-04-11 10:19:08 -05:00
FluxCD
f4546ad1f3 chore: update prop image to git.mcintire.me/graham/prop:main-1775918982-3bb0660 [skip ci] 2026-04-11 14:50:55 +00:00
b5162daf89 Round lat/lon to 6 decimals everywhere, add commas to EIRP display
- Round grid-derived lat/lon in maybe_fill_latlon changeset step
- Format lat/lon to 6 decimal places on index table
- Migrate existing beacon data to 6 decimal precision
- Add comma separators to EIRP mW display (e.g. 10,000 mW)
- Extract shared add_commas helper for format_freq and format_mw
2026-04-11 09:49:12 -05:00
FluxCD
1a46020f6a chore: update prop image to git.mcintire.me/graham/prop:main-1775918703-838377d [skip ci] 2026-04-11 14:45:52 +00:00
2c1c221398 Change beacon height_ft from float to integer
Height in feet doesn't need decimal precision. Migrates the DB
column, updates schema type, and strips trailing .0 from form
input so the integer cast succeeds.
2026-04-11 09:44:42 -05:00
FluxCD
9b5880f01b chore: update prop image to git.mcintire.me/graham/prop:main-1775918528-1e0aaad [skip ci] 2026-04-11 14:42:51 +00:00
0059317043 Beacon page improvements: comma formatting, sorting, rounding
- Add CommaNumber JS hook for live comma formatting while typing
  frequency MHz in the beacon form
- Strip commas server-side before changeset validation
- Order beacon list by most recently added (desc inserted_at)
- Round lat/lon to 6 decimal places in changeset and display
- Round height_ft to integer in changeset and display
- Display coords at 6 decimal places on show page
2026-04-11 09:41:51 -05:00
FluxCD
9451b7f451 chore: update prop image to git.mcintire.me/graham/prop:main-1775918264-f6643e5 [skip ci] 2026-04-11 14:38:47 +00:00
8425edbdc4 Add comma separators to MHz frequencies on beacon pages
Formats frequencies like 10368.1 as "10,368.1" on both the
beacon list table and detail page (subtitle, map label, stat field).
2026-04-11 09:37:26 -05:00
FluxCD
6608e6105a chore: update prop image to git.mcintire.me/graham/prop:main-1775916293-ef44ae9 [skip ci] 2026-04-11 14:09:35 +00:00
ab819852ae Install Docker CLI in CI runner container 2026-04-11 09:04:22 -05:00
11c5d5fb43 Add -s flag to wgrib2 -lon extraction for inventory output
Without -s, wgrib2 -lon only outputs msg:offset:lon=X,lat=Y,val=Z
with no variable name or level. The -s flag adds the short inventory
(d=DATE:VAR:LEVEL:...) so the parser can identify which variable
each value belongs to.
2026-04-11 09:03:09 -05:00
FluxCD
0a970594a3 chore: update prop image to git.mcintire.me/graham/prop:main-1775916097-bb90bc8 [skip ci] 2026-04-11 14:02:34 +00:00
ac36441102 Remove grid squares toggle from rover planner page
The rover page now shows only: station markers, band selector,
propagation heatmap, and URL sharing. Grid overlay remains on
the main /map page.
2026-04-10 17:31:23 -05:00
FluxCD
1d76497db5 chore: update prop image to git.mcintire.me/graham/prop:main-1775859782-ceffcbc [skip ci] 2026-04-10 22:25:43 +00:00
669fe07bcf Replace buildx/login GitHub Actions with plain docker commands
setup-buildx-action downloads from GitHub Releases which is slow
and unreliable from the Forgejo runner. Plain docker build/push
works fine since Docker is already on the runner host.
2026-04-10 17:22:57 -05:00
b42b777150 Use wgrib2 -lon for native profile extraction instead of -lola grid
Points spread coast-to-coast created a ~476k cell bounding grid
(350 messages × 476k cells × 4 bytes ≈ 665 MB), causing OOM.

Switch to -lon which extracts values at specific lat/lon points
with text output. One wgrib2 call, one file scan, negligible
BEAM memory regardless of point geographic spread.
2026-04-10 17:12:11 -05:00
33fae7b7c9 Reduce memory pressure: Stream large collections, GC between phases
- Stream profile storage and score upsert instead of materializing
  full 20k+ item lists (propagation_grid_worker, propagation.ex)
- GC between forecast hours and store/compute phases to reclaim
  ~400 MB of grid data between steps
- Single-pass field extraction in scorer.ex path_integrated_conditions
  instead of 6 separate Enum traversals
- Eliminate intermediate merged map in fetch_grid by combining
  merge + profile build into one pipe
- Fix UUID bug: bingenerate → generate in native grid worker
  (same issue previously fixed in nexrad_worker)
2026-04-10 16:45:50 -05:00
FluxCD
2c9613ccc3 chore: update prop image to git.mcintire.me/graham/prop:main-1775856202-f89dfb0 [skip ci] 2026-04-10 21:24:54 +00:00
02467f96c4 Trigger CI: test runner fix with node 22 + docker group 2026-04-10 16:23:12 -05:00
a0baaf3151 Trigger CI build to test runner fix 2026-04-10 16:20:28 -05:00
2973fe978b Download HRRR ranges sequentially to prevent memory accumulation
The parallel download was holding all ~530MB of range responses in
memory before writing to disk. Now each range is fetched and written
one at a time, so only one chunk is in memory at a time.
2026-04-10 15:58:47 -05:00
FluxCD
525a63d246 chore: update prop image to git.mcintire.me/graham/prop:main-1775853912-221e06d [skip ci] 2026-04-10 20:46:38 +00:00
f2efdd4ece Stream HRRR native downloads to disk to prevent OOM
Instead of holding ~530MB GRIB binary in BEAM memory, download
ranges directly to a temp file and run wgrib2 on it. Peak memory
drops from ~530MB to just HTTP chunk buffers.
2026-04-10 15:44:36 -05:00
FluxCD
1c896ec676 chore: update prop image to git.mcintire.me/graham/prop:main-1775848424-575a9af [skip ci] 2026-04-10 19:15:22 +00:00
4487fc22e9 Fix NexradWorker UUID type: use generate() not bingenerate() for insert_all 2026-04-10 14:13:38 -05:00
FluxCD
1f8fc4d4aa chore: update prop image to git.mcintire.me/graham/prop:main-1775848082-4708df9 [skip ci] 2026-04-10 19:09:19 +00:00
0edb1bd95a Fix NexradWorker crash when minute key is missing from args
Jobs enqueued via backfill only have year/month/day/hour — default
minute to 0 instead of requiring it in the pattern match.
2026-04-10 14:07:55 -05:00
FluxCD
147ef7dd6b chore: update prop image to git.mcintire.me/graham/prop:main-1775847868-948cb6d [skip ci] 2026-04-10 19:05:19 +00:00
ea0c41ef50 Fix crash on /submit when LiveStash restores CSV tab without csv_result assign
Set all assigns before LiveStash recovery so reconnecting to the CSV
tab doesn't crash on missing :csv_result / :csv_preview keys.
2026-04-10 14:04:16 -05:00
FluxCD
d071b02cea chore: update prop image to git.mcintire.me/graham/prop:main-1775846284-76029d9 [skip ci] 2026-04-10 18:41:29 +00:00
0e3c06d040 Reduce hrrr queue to 1 per pod to prevent OOM
Native HRRR files are ~400MB each. At hrrr:5 per pod, 5 concurrent
downloads exceed the 4GB pod memory limit causing OOMKilled.
2026-04-10 13:37:37 -05:00
FluxCD
b5d33def74 chore: update prop image to git.mcintire.me/graham/prop:main-1775843322-3bd02fa [skip ci] 2026-04-10 17:51:50 +00:00
e7a7ae073d Phase 9.3, 9.4, and Phase 3 NEXRAD pipeline
Task 9.3 - Weight recalibration via gradient descent:
- Recalibrator module fits logistic regression weights using Nx
- Trains on QSO positives vs random baseline negatives
- Cross-validates by month, normalizes weights to sum to 1.0
- Mix task: mix recalibrate_scorer --sample 5000 --epochs 2000

Task 9.4 - Side-by-side scorer comparison:
- ScorerDiff.compare/3 re-scores grid with old vs new weights
- Reports mean diff, regressions, improvements, per-band breakdown
- Mix task: mix scorer_diff --new-weights '{...}'

Phase 3 - NEXRAD ingestion pipeline:
- NexradClient fetches IEM n0q composite PNGs, extracts per-point
  box statistics (mean/max dBZ, texture variance)
- NexradObservation schema with unique (lat, lon, observed_at)
- NexradWorker on :nexrad queue for background processing
- nexrad_texture backtest feature in Features module
- mix nexrad_backfill --limit 200

All tasks added to AdminTaskWorker and Release for production use.
1116 tests, 0 failures.
2026-04-10 12:48:36 -05:00
FluxCD
ae049dcb8f chore: update prop image to git.mcintire.me/graham/prop:main-1775841968-8f0a37c [skip ci] 2026-04-10 17:28:26 +00:00
01909dbe66 Run admin tasks as Oban jobs instead of blocking eval
Release.backtest_all, climatology, native_derive now enqueue an
AdminTaskWorker job on the new :admin queue and return immediately.
Progress visible in Oban Web at /admin/oban.
2026-04-10 12:26:01 -05:00
FluxCD
046bef6c17 chore: update prop image to git.mcintire.me/graham/prop:main-1775841362-c8237c7 [skip ci] 2026-04-10 17:17:23 +00:00