Commit graph

150 commits

Author SHA1 Message Date
fd33eff8bc
Add required attribute to all single contact form fields 2026-04-01 15:56:25 -05:00
1b5cd19d6d
Skip already-backfilled HRRR points with sufficient level count 2026-04-01 15:52:35 -05:00
ff0ca89646
Add HRRR GRIB2 caching and backfill task for finer pressure levels
- Cache raw GRIB2 byte ranges to ~/hrrr in dev (never deleted)
- mix hrrr_backfill re-fetches QSO-linked HRRR profiles with 13 levels
- Supports --all (re-fetch everything) and --limit N flags
- Groups by HRRR hour to batch requests, 500ms rate limit
- AWS archive has full HRRR history, same URL pattern as live feed
2026-04-01 15:50:55 -05:00
bdaf74f5ef
Add intermediate HRRR pressure levels for duct detection
Fetch every 25mb from 1000-700mb (13 levels, up from 8). Gives ~80m
vertical spacing near the surface, enough to resolve ducting layers
that were previously invisible between the coarse 250m level spacing.
2026-04-01 15:46:22 -05:00
a25864bdcb
Sanitize and validate user-submitted contact fields
- Callsigns: strip whitespace, upcase, validate alphanumeric + /
- Grids: strip whitespace, upcase before Maidenhead validation
- Email: stricter regex, max 254 chars
- Callsign max length 20 chars
- Fix static_paths to include downloads directory
- Update show test for removed contact details section
2026-04-01 15:41:42 -05:00
ec388e4bf5
Use Timex for flexible CSV timestamp parsing with tests
- Add timex ~> 3.7, downgrade gettext to ~> 0.26 for compatibility
- Parse ISO 8601, US dates (M/D/YYYY), AM/PM, 24h, compact formats
- 22 tests covering all accepted timestamp formats and edge cases
- Integration tests for CSV import with US date and space-separated formats
2026-04-01 15:39:02 -05:00
05654289af
Accept various date/time formats in CSV import
Parse US dates (6/15/2024 2:30 PM), 24h (06/15/2024 14:30),
dashes (06-15-2024 14:30), compact (20240615 1430), date-only
(2024-06-15), and ISO 8601 — all normalized to UTC before insert.
2026-04-01 15:35:35 -05:00
bc70b38e93
Add info box about contact availability after submission 2026-04-01 15:32:44 -05:00
4e092a0cf5
Use bulleted list for CSV upload instructions 2026-04-01 15:31:38 -05:00
2b11b872d9
Restyle submit page tabs as segmented control 2026-04-01 15:31:09 -05:00
239bf707aa
Fix HRRR prune timeout: bound time range for partition pruning 2026-04-01 15:27:11 -05:00
bf90249a06
Format contact detail page via Styler 2026-04-01 15:06:02 -05:00
18a291555c
Add CSV bulk upload to /submit page
Adds a tabbed UI with single-contact form and CSV upload. Users can
download a sample CSV, upload their file, and get partial import with
per-row error reporting. Enrichment jobs enqueue for each imported contact.
2026-04-01 15:05:51 -05:00
86b6c0db31
Fix BadBooleanError when HRRR data is nil in propagation analysis 2026-04-01 14:06:49 -05:00
f02b111c1f
Disable auto HRRR backfill on contact detail page view 2026-04-01 13:57:23 -05:00
71091219f4
Add tidewave dev tool, taller elevation profile chart
- Install tidewave ~> 0.5 for dev MCP integration
- Increase elevation profile chart height from h-64 to h-96
2026-04-01 13:41:39 -05:00
dbc00989cd
Add propagation analysis with summary and factor breakdown
- Text summary explaining likely propagation mechanism (ducting,
  enhanced refraction, diffraction, troposcatter) based on terrain,
  HRRR, and sounding data
- 10-factor scoring table with per-factor notes, weights, contributions
- Composite score with tier badge
- Grid squares added back to path info line
- Analysis positioned between elevation chart and terrain profile
2026-04-01 13:38:10 -05:00
4aaa028ed1
Highlight likely propagation duct, improve contact detail layout
- Mark duct closest to endpoint elevations as likely signal path
- Likely duct drawn with solid borders, bold label, stronger fill
- Other ducts shown dimmed with dashed borders
- Fix path info layout: table columns prevent El wrapping
- Surface observations as compact table, limited to 5 nearest stations
2026-04-01 13:31:56 -05:00
5f8c689035
Improve duct detection and compact contact detail layout
- Use all HRRR profiles along path (start, mid, end) for duct detection
- Fall back to sounding ducts when HRRR too coarse to detect layers
- Merge overlapping ducts, show top 3 strongest with source labels
- Limit surface observations to 5 closest stations along path
- Compact solar conditions as inline row
- Compact band/mode/distance info line
- Fix button text to "Flag as Invalid"
2026-04-01 13:28:42 -05:00
7ba82f4601
Duct visualization, flag invalid contacts, fix HRRR pruning
- Overlay HRRR duct layers on elevation profile chart (green bands)
- Add flagged_invalid field to contacts with toggle button on detail page
- Fix prune_old_grid_profiles to only delete 0.125° grid profiles,
  preserving QSO-linked HRRR data at arbitrary positions
- Auto-enqueue HRRR fetch when viewing contact without HRRR data (<48h)
- Compact solar conditions and contact details layout
- Add band/mode/distance info line to elevation profile section
2026-04-01 13:09:09 -05:00
f7a753626d
Add interactive popups to contact map, dedup reciprocals, darken line colors 2026-04-01 12:39:02 -05:00
cd8d7a0f52
Add contact detail map, elevation profile chart, and UI improvements
- Leaflet map on contact detail pages showing both station locations
- SRTM elevation profile with Chart.js: terrain, LOS, Fresnel zone
- Path info: distance, azimuth, elevation angle in both directions
- Compact 4-column grid layout for contact details
- Contact map page with all contacts plotted
- Rename QSOs to Contacts in page header
- Wrap algo page in standard layout
2026-04-01 12:34:03 -05:00
ea96c93e2d
Rename QSO to Contact in UI, add higher bands, improve submit page
- All menus and UI text now say Contacts instead of QSOs
- Add 68, 122, 134, 241 GHz bands to submit form and validation
- Add info box on submit page explaining why contacts matter
- Larger submit button with icon
- Make HRRR partition migration idempotent for partial re-runs
2026-04-01 12:28:24 -05:00
2c16fd979d
Move ML deps to dev/test only, exclude from production build
- Nx, Axon, EXLA, Polaris deps restricted to only: [:dev, :test]
- model.ex and training mix tasks moved to lib_ml/ (compiled via
  elixirc_paths in dev/test only)
- load_ml_model uses Code.ensure_loaded? + apply/3 to avoid
  compile-time references to ML modules in production
- Verified: MIX_ENV=prod compiles clean with no ML warnings
2026-04-01 12:10:31 -05:00
254e64dedc
Rename qsos to contacts throughout codebase, keep DB table name
Rename all modules, functions, variables, routes, and UI text from
qso/qsos to contact/contacts. Database table stays as "qsos" to avoid
migration. Add /qsos -> /contacts redirects for old URLs.
2026-04-01 11:25:04 -05:00
bc529af392
Update algo.md Finding 10: corrected mode advantage, no SSB on rainscatter 2026-04-01 11:10:11 -05:00
b75516ff9f
Partition hrrr_profiles by valid_time for query performance
54M row table partitioned into date-range partitions. Queries with
valid_time filter only scan relevant partitions. Prune now uses
partition-aware DELETE. Fix tests for partitioned constraint behavior
and removed sort-click tests (grouped table uses URL params).
2026-04-01 11:03:33 -05:00
072c418cb3
Fix HRRR prune timeout: batch delete with 60s timeout instead of full table scan 2026-04-01 10:45:09 -05:00
b9aac6f688
Show grouped reciprocal QSOs on main listing, not just search 2026-04-01 10:43:41 -05:00
341a04190a
Show user_submitted column, remove committed column from QSO table 2026-04-01 10:41:25 -05:00
b86c822010
Add live UTC clock to map control panel 2026-04-01 10:38:02 -05:00
b46d592411
Fix callsign search input alignment 2026-04-01 10:35:10 -05:00
8f4f491a5e
Revert to algorithm scorer as primary, add propagation reach polygon
The ML model undervalues conditions outside Aug/Sep training data
(e.g. April with excellent factors scored 37/100). Algorithm's
physics-based factors handle unseen seasons correctly.

- Algorithm is primary scorer, ML infrastructure kept for iteration
- Remove unused ML grid worker code path
- Add client-side propagation reach: BFS flood-fill from clicked point
  through contiguous cells with score >= 50, drawn as convex hull polygon
2026-04-01 10:21:54 -05:00
02cb4fd67b
Integrate ML model into grid worker, QSO search, and UI improvements
ML Integration:
- Load trained model at app startup, cache compiled predict fn in persistent_term
- Grid worker uses batched ML prediction (10K chunks) when model loaded,
  falls back to algorithm scorer when not
- ML score replaces composite, algorithm factor scores preserved for detail view
- Fix process explosion: single EXLA call per chunk instead of per-grid-point

QSO Features:
- Callsign search (ILIKE on station1/station2) with trigram indexes
- Reciprocal QSO grouping (same pair, same band, same hour)
- Wider layout (max-w-7xl) for data table pages
- QSO Training Data link on map page

Infrastructure:
- Re-enable hourly propagation grid worker in dev
- Track ML model weights in git for Docker builds
- Add btree indexes on qsos (timestamp, band, distance_km)
- Remove nav icons from layout header
2026-04-01 10:14:22 -05:00
489e188956
Add --no-pretrain flag for direct QSO training comparison 2026-04-01 09:36:32 -05:00
9537c97d1d
20-feature model with solar indices, sounding stability, and ducting
Add SFI, Kp max (solar), K-index, lifted index (sounding stability),
and ducting_detected (HRRR) as model features. Training now joins to
solar_indices and nearest sounding (within 6 hours) for both phases.
Model can learn solar/geomagnetic effects if they exist in the data.
2026-04-01 09:31:54 -05:00
07558d17eb
Two-phase training: pretrain on algorithm scores, fine-tune on QSOs
- 15 features: add surface_refractivity and latitude
- Bigger network: 128→64→32 (3 hidden layers)
- Phase 1: pretrain on 500K stratified algorithm scores (all seasons/locations)
- Phase 2: fine-tune on 57K real QSO-HRRR matched data (percentile target)
- Lower LR (0.0003) for fine-tuning to preserve pretrained knowledge
- Model.train accepts :initial_state option for transfer learning
2026-04-01 09:27:27 -05:00
08e4b9abdd
Bigger network (128→64→32) and percentile-based training target
- 3 hidden layers instead of 2 for better feature interaction learning
- Target is within-band distance percentile (0-1) instead of raw
  normalized distance — reduces noise from operator/equipment variation
2026-04-01 09:17:36 -05:00
10cbbf47b3
Train ML model on real QSO-HRRR data instead of algorithm scores
Features: HRRR conditions averaged at both QSO endpoints + solar time
Target: distance_km normalized per-band (distance / p99_range, capped at 1.0)
This trains on actual propagation outcomes from 57K+ QSOs, not the
hand-tuned algorithm output.
2026-04-01 09:13:05 -05:00
69b5caf876
Normalize ML features to prevent NaN gradient explosion
Raw features had vastly different scales (pressure ~1013, sin/cos ~[-1,1])
causing gradient explosion. Normalize all atmospheric features to ~[0,1]
using known physical bounds. Add Polaris dep for optimizer.
2026-04-01 09:08:33 -05:00
5c9b43d619
Update analysis with solar time, refine algo.md time-of-day section
Solar time (longitude/15) replaces fixed CDT/CST offset for time-of-day
scoring. Correlation analysis shows dramatic improvement at higher
frequencies: 24 GHz rho jumps from 0.056 (UTC) to 0.188 (solar), and
75 GHz corrects from spurious -0.39 to physically correct +0.24.
2026-04-01 09:02:57 -05:00
c12f8cf5ed
Use local solar time for time-of-day scoring, add PWAT factor and pressure refinements
Score time-of-day per grid point using longitude/15 solar offset instead of
hardcoded CST/CDT. Add PWAT as 10th scoring factor. Refine pressure thresholds.
Update ML model and training pipeline to use local solar time.
2026-04-01 08:58:21 -05:00
b7fc195e82
Ensure stale scores get pruned even when HRRR fetch fails 2026-04-01 08:36:14 -05:00
4bf9d0b4b0
Add mix propagation.analyze task for QSO-HRRR correlation analysis 2026-04-01 08:34:04 -05:00
14e86c4ddb
Filter forecast graph to only show current and future hours 2026-04-01 08:14:29 -05:00
b11e0bac84
Always show at least the most recent valid_time in timeline 2026-03-31 17:49:19 -05:00
4151f7d314
Filter past hours from forecast timeline (30-min grace for current hour) 2026-03-31 17:47:16 -05:00
6dff6372ab
Default forecast timeline selection to closest hour to now 2026-03-31 17:45:54 -05:00
e028de51ae
Tighten HRRR grid profile retention from 48h to 24h 2026-03-31 17:20:46 -05:00
fe5228b306
Prevent duplicate PropagationGridWorker jobs via Oban unique constraint
Worker now uses unique: [period: 3600, states: [:available, :scheduled,
:executing, :retryable]] so Oban atomically prevents duplicates.
FreshnessMonitor simplified — no longer does manual oban_jobs query.
2026-03-31 17:16:40 -05:00