Microwave Propagation Algorithm — Unified

Overview

Propagation scoring and prediction for microwave amateur radio bands (10-241 GHz), calibrated against 57,488 tropospheric QSOs with distance data, validated against commercial terrestrial links at 11/24/68 GHz, and grounded in ITU-R atmospheric models.

The algorithm has two operating regimes:

  1. Beyond-LOS — Ham radio paths (50-1000+ km) where atmospheric ducting and refraction are essential. This is the primary use case. Terrain analysis confirms 97.2% of all QSO paths are terrain-blocked (average diffraction loss 36.2 dB), making atmospheric propagation mechanisms the sole enabler.
  2. LOS — Known fixed links or short paths with clear Fresnel clearance where gaseous absorption is the dominant variable.

The regime distinction matters because refractivity effects are inverted between the two: enhanced refraction extends beyond-LOS range but causes multipath fading on short LOS paths.

Calibration Dataset

QSO data: 58,282 total QSOs across 13+ bands (ARRL Microwave Contest, 1992-2024). 57,488 with tropospheric distance data after excluding 4 EME contacts (QRA64D/JT4F modes >3,000 km). Enriched with weather from 1,299 ASOS stations (58,398 surface observations), 112 RAOB stations (3,901 soundings), 4,522 HRRR model profiles, 3,675 IEMRE gridded hourly observations, and 58,276 terrain path profiles.

Link data: 7 commercial links near DFW (Princeton TX area) at 11/24/68 GHz, polled via SNMP at 5-minute intervals. All links use KTKI ASOS for weather correlation. Live polling is active; historical dataset from March 14-29 2026 (18,540 samples) was used for initial algorithm validation.

Terrain analysis: 58,276 QSO paths profiled — 56,658 BLOCKED (97.2%, avg 36.2 dB diffraction), 1,277 CLEAR (2.2%), 341 FRESNEL_PARTIAL (0.6%). Blocked paths average longer distances than clear paths (215 km vs 84 km at 10 GHz) because ducting enables beyond-LOS paths by definition.

Confirmed long-range contacts:

  • 47 GHz: 116.0 km (Nov 2025), 98.8 km (Jun 2024)
  • 24 GHz: 710.0 km (CW), 542.1 km (Sep 2002, longest confirmed tropo)
  • 10 GHz: 2,393 km (longest tropospheric in dataset)

Additional data sources (not yet integrated into scoring):

  • Solar indices: 9,586 daily values (1998-2026) — SFI, SSN, Ap/Kp. Not relevant for tropospheric microwave propagation but available for future VHF/sporadic-E extension.
  • IEMRE gridded hourly data: weather at QSO endpoint grid points (0.125° resolution) with percentage sky cover, soil temperature, wind components. More granular than nearest-ASOS matching.

Meteorological Foundations

This section documents the atmospheric physics and NWP integration underlying the propagation prediction system. The system forecasts tropospheric microwave propagation conditions (10–241 GHz) from HRRR model output, RAOB soundings, and ASOS surface observations. The primary mechanisms of interest are tropospheric ducting via refractivity gradients and frequency-dependent gaseous/hydrometeor attenuation.

Refractivity Framework

Radio refractivity N (ITU-R P.453-14):

N = 77.6·P/T + 3.73×10⁵·e/T²

P (hPa), T (K), e = water vapor pressure (hPa) via Buck equation from Td. The wet term contributes 20–40% of total N in the ABL. Modified refractivity M = N + 0.157·h (h in m AGL); ducting where dM/dh < 0.

The vertical gradient dN/dh governs ray curvature via the effective earth radius factor k = 1/(1 + R·dN/dh·10⁻⁶):

dN/dh (N/km)kRegime
> 0< 1Sub-refraction
0 to −791.0–1.33Standard
−79 to −1571.33–∞Super-refraction
< −157negativeDucting (ray curvature exceeds earth curvature)

Ducting Mechanisms

Four mechanisms produce the negative dN/dh gradients that enable beyond-LOS propagation. Each creates a sharp temperature increase and/or moisture decrease with height:

1. Radiation (Nocturnal) Ducts — Surface-based temperature inversion from radiative cooling under clear skies, light winds. Moisture trapped below the inversion cap. Forms 1–3h post-sunset, peaks pre-dawn, erodes within 1–2h of insolation. Typical depth 50–300m AGL, dN/dh −100 to −300 N/km. Primary mechanism in our dataset — operators target dawn windows specifically.

2. Advection Ducts — Warm, dry air mass overriding a cooler surface (SST discontinuity, lake, post-frontal cold ground). Strong temperature increase with moisture decreasing sharply at the air-mass interface. Persistent (hours to days), independent of diurnal cycle. Depth 50–500m, often elevated. dN/dh −200 to −500+ N/km. Dominant along Gulf Coast, California coast, Great Lakes.

3. Subsidence Ducts — Synoptic-scale subsidence inversion (ridge axis, subtropical high) with trapped moisture below the inversion base. Visible on soundings as sharp temperature increase at 800–900 hPa with coincident Td drop. Persistent with ridging. Depth 500–2000m AGL (elevated duct). dN/dh −100 to −200 N/km.

4. Frontal/Boundary Ducts — Mesoscale refractivity gradients along cold fronts (post-frontal moisture drop), warm fronts (overrunning moist air), outflow boundaries, and drylines. Transient. Our data confirms low-pressure systems correlate with extended propagation (262 km avg vs 196 km at 1025+ hPa for 10 GHz), consistent with frontal boundary structure.

NWP Integration (HRRR)

Primary atmospheric data source: NOAA HRRR v4 (3 km, hourly, 18h forecast cycle).

Extracted fields (GRIB2 via byte-range requests from AWS S3):

  • Surface: T₂ₘ, Td₂ₘ, Psfc, U₁₀ₘ/V₁₀ₘ, TCDC, APCP
  • ABL: HPBL (diagnosed PBL height), PWAT (column-integrated precipitable water)
  • Pressure levels: T, Td, Z at every 25 hPa from 1000–700 hPa (13 levels, ~80m vertical spacing below 900 hPa)

Derived products:

  1. N(h) profile at each pressure level → dN/dh minimum (primary ducting discriminant)
  2. M(h) profile → explicit duct detection (dM/dh < 0 layers with strength Δ M > 2 M-units)
  3. Surface N from Psfc, T₂ₘ, Td₂ₘ
  4. Absolute humidity ρ = 217·es(Td)/T
  5. Dynamic k-factor for terrain diffraction (ITU-R P.526-16)

Vertical resolution limitation: The 25 hPa pressure level spacing resolves features ≥100m thick. Thin surface ducts (50–100m) detectable by RAOB at ~10m resolution may be missed. Comparative statistics: HRRR gradients cluster −40 to −130 N/km (median −70); collocated RAOB gradients extend to −500+ N/km. Scoring thresholds are calibrated to HRRR-derived gradient distributions, with RAOB duct detections used as supplementary data where available (3,901 profiles from 112 stations).

Surface Observations (ASOS)

ASOS provides in-situ validation and additional parameters not in HRRR output:

  • T, Td → ρ(abs humidity), T-Td depression (inversion proxy)
  • Wind speed → mechanical mixing potential (light winds favor inversion persistence)
  • Sky condition → longwave radiation budget (CLR promotes nocturnal cooling)
  • Psfc → absolute N computation, barometric trend (pressure tendency)
  • Precipitation type/rate → hydrometeor attenuation (ITU-R P.838-3)

Frequency-Dependent Attenuation

The same thermodynamic state produces opposing propagation effects across the spectrum:

10 GHz (λ = 3 cm): Gaseous attenuation negligible (0.012 dB/km). Propagation governed entirely by refractivity structure. Increased ρ raises N, enhancing beam bending — moisture is beneficial. Rain attenuation mild (γR = 0.05 dB/km at 4 mm/hr).

24 GHz (λ = 1.25 cm): Proximal to the 22.235 GHz H₂O rotational line. H₂O absorption coefficient 0.012 dB/km per g/m³ (10× the 10 GHz rate). Moisture degrades path budget despite refractivity benefit — net effect is harmful. Rain attenuation 6× that of 10 GHz.

47–75 GHz: Transition regime. 47 GHz in a relative window (O₂ wing + mild H₂O). 68 GHz on the wing of the 60 GHz O₂ absorption complex (γO₂ = 0.9 dB/km). 75 GHz in a window band (γtotal ≈ 0.057 dB/km). Ducting is the sole mechanism enabling paths beyond ~20 km.

122–241 GHz: Dominated by gaseous absorption. 122 GHz on the 118.75 GHz O₂ line wing (0.8 dB/km). 134 GHz in the window between O₂ 118 and H₂O 183 lines. 241 GHz between H₂O 183 and 325 GHz lines (0.3 dB/km per g/m³). All contacts in the dataset above 122 GHz are CW mode — link budget is that tight.

ABL Diurnal Cycle

The ABL diurnal cycle is the most predictable propagation driver:

  1. Post-sunset → sunrise: Radiative cooling develops surface-based inversion. HPBL collapses from O(10³m) to O(10²m). Super-refractive/ducting conditions develop.
  2. Dawn (sunrise ± 1.5h): Peak inversion strength, minimum HPBL. Maximum ducting probability.
  3. Morning transition (+1.5 to +3h): Shortwave heating erodes inversion from below. Convective mixing deepens ABL.
  4. Afternoon (+6h): Fully convective ABL, maximum HPBL. Minimum propagation. Turbulent scattering dominates residual refractivity gradients.

Observed diurnal enhancement (night/dawn over afternoon baseline): +4% at 10 GHz, +28% at 24 GHz, +36% at 47 GHz, +360% at 75 GHz. At EHF, time of day dominates all other predictors. The system uses longitude-based solar time (hour + lon/15) rather than UTC for diurnal scoring — Spearman ρ with distance improves from 0.056 (UTC) to 0.188 (solar) at 24 GHz.

Seasonal Cycle

Ducting probability from 3,901 RAOB profiles (CONUS):

MonthDucting %Mean dN/dh minMean PWAT (mm)
Jun68.7%−32328.6
Jul76.5%−30127.6
Aug53.9%−26133.3
Sep56.4%−28726.2
Oct60.4%−31417.9
Mar10.8%−1136.6
Dec–Feb12–22%−1307–10

Peak Jun–Jul, secondary peak Oct–Nov (autumn radiative cooling with residual moisture). March minimum (frequent mixing events). At 24+ GHz the seasonal optimum inverts — winter minimizes H₂O absorption despite lower ducting probability. Band-specific seasonal weights account for this.

Known Limitations

  1. HRRR vertical resolution: 25 hPa spacing (recently improved from ~100 hPa) may still miss thin surface ducts <100m. RAOB data used as supplementary duct detection source.
  1. Sub-grid mesoscale: Sea breeze fronts, outflow boundaries, terrain-induced convergence zones — ducting features below the 3 km HRRR grid are not resolved.
  1. Hydrometeor attenuation: ITU-R P.838-3 coefficients applied but unvalidated against measured data. Rainscatter propagation (observed at 24 GHz via FM mode) is not modeled.
  1. Fog/cloud: Cloud cover percentage is used as a proxy; direct fog/cloud attenuation modeling is not implemented. Relevant above 47 GHz where dense fog adds 1–5 dB/km.
  1. Scintillation: Amplitude scintillation from refractive turbulence on long LOS paths is not modeled.
  1. Temporal resolution: Hourly HRRR updates. Rapidly evolving mesoscale features (convective outflows, sea breeze onset) may lag reality between analysis cycles.

Part 1: Atmospheric Physics

Absolute Humidity

The single most important weather variable. Temperature and relative humidity are proxies; absolute humidity (g/m^3) directly determines gaseous absorption.

rho = 217 * (RH/100) * e_s / T_kelvin

e_s = 6.112 * exp(17.67 * T_c / (T_c + 243.5))    # Magnus formula (hPa)

Surface Refractivity (ITU-R P.453-14)

N = 77.6 * P / T + 3.73e5 * e / T^2

P: pressure (hPa)
T: absolute temperature (K)
e: water vapor pressure (hPa) = 6.112 * exp(17.67 * Td_c / (Td_c + 243.5))

N is a compound variable: both dry air (pressure/temperature) and moisture contribute. At 10 GHz, higher N increases beam bending (beneficial for beyond-LOS). At 24+ GHz, higher N usually means more moisture = more absorption (harmful), though the refractivity benefit partially offsets this.

Modified Refractivity (M-units)

M = N + 0.157 * (h_agl)

h_agl: height above ground level (m)

Ducting occurs where dM/dh < 0 (M decreases with height). Duct strength = delta-M across the inversion layer.

Gaseous Absorption (ITU-R P.676-13)

Total absorption per km = O2 component (fixed) + H2O component (humidity-dependent):

Bandf (GHz)O2 (dB/km)H2O Coeff (dB/km per g/m^3)Total @ 7.5 g/m^3Dominant Constraint
10G10.3680.0080.00050.012Negligible absorption
24G24.1920.0150.0120.10522.235 GHz H2O line
47G47.0880.0450.0030.068O2 wing + mild H2O
68G68.0400.900.0070.9560 GHz O2 band wing
75G76.0320.0120.0060.057Window band
122G122.2500.800.0100.875118.75 GHz O2 wing
134G134.9280.080.0150.193Between O2 118 & H2O 183
142G142.0000.050.0250.238Approaching H2O 183
241G241.0000.080.302.33Between H2O 183 & H2O 325

The 11 GHz and 24 GHz coefficients are validated by commercial link measurements. The 68 GHz coefficient is directly measured (0.1 dB/km per g/m^3 increase on a 2.8 km path, consistent with ITU-R model when O2 wing contribution is included).

Rain Attenuation (ITU-R P.838-3)

gamma_R = k * R^alpha (dB/km), R = rain rate (mm/hr):

Bandk_Halpha_HLight 4mm/hrModerate 10mm/hrHeavy 25mm/hr
10G0.0101.280.050.190.56
24G0.0701.070.310.812.04
47G0.1870.930.681.583.69
68G0.3100.860.982.184.73
75G0.3450.841.072.405.18
122G0.4980.771.322.935.91
241G0.5500.701.302.765.20

Rain model is NOT validated by measured data (no rain events in link dataset). Coefficients are from ITU-R P.838-3 and interpolation.

Free-Space Path Loss (ITU-R P.525)

FSPL = 20 * log10(d_km) + 20 * log10(f_GHz) + 92.45    (dB)

Fresnel Zone Radius

r_fresnel = sqrt(lambda * d1 * d2 / (d1 + d2))

lambda = 0.3 / f_GHz    (meters)

Earth Bulge

bulge = (d1 * d2) / (2 * k * 6371000)

k: effective earth radius factor (standard = 4/3, dynamic from HRRR)

Effective K-Factor (ITU-R P.526-16 Section 2)

Computed from the HRRR refractivity gradient (dN/dh in N-units/km):

k = 1 / (1 + 6371 * dN_dh * 1e-6)
dN/dh (N/km)kCondition
01.0No refraction
−394/3Standard atmosphere
−100~2.7Enhanced refraction
−157Ray follows earth curvature
< −157negativeSuper-refraction / ducting

When HRRR data is available for a QSO, the actual refractivity gradient is used. Falls back to k=4/3 when unavailable. The k-factor is capped at 100 to avoid numerical issues near ducting conditions.


Part 2: Key Empirical Findings

These findings drive the scoring model's design. Each contradicts or refines assumptions from simpler models.

Finding 1: Humidity Effect Reverses by Frequency

The most important discovery. At 10 GHz, more moisture = longer paths (refractivity dominates, absorption negligible). At 24+ GHz, more moisture = shorter paths (absorption dominates).

10 GHz — humidity helps (N=53,013 QSOs):

Abs. HumidityAvg DistP90 Dist
5-8 g/m^3193 km342 km
11-14 g/m^3215 km383 km
17+ g/m^3230 km519 km

24 GHz — humidity hurts (N=3,639 QSOs):

Abs. HumidityAvg DistP90 Dist
5-8 g/m^3115 km154 km
11-14 g/m^3105 km174 km
17+ g/m^353 km103 km

47 GHz — humidity hurts, less severely (N=689 QSOs):

Abs. HumidityAvg DistP90 Dist
0-5 g/m^3191 km234 km
11-14 g/m^371 km114 km

Finding 2: Wind Penalty Is Overrated

Data shows no meaningful penalty for wind on achieved distance:

Wind10G Avg24G Avg47G Avg
Calm (0-3 kts)21684--
Light (3-7 kts)21410077
Moderate (7-12 kts)22011377

Wind may reduce inversion quality but also creates boundary-layer dynamics that can enhance propagation. Weight reduced from 18% to 8%.

Finding 3: Low Pressure Correlates with Longer Distances

Contradicts the common assumption that high pressure = good propagation:

Pressure10G Avg10G P9024G Avg47G Avg
<1010262506119111
1015-10202173839774
1025+196354122--

Low pressure systems bring frontal boundaries with strong temperature/moisture gradients that create inversions and ducts. The key is gradient structure, not absolute pressure.

Finding 4: Boundary Layer Depth — Time-Dependent Sweet Spot

Sounding data (3,901 profiles) reveals that BL depth interpretation depends on sounding time:

Sounding TimeAvg BL DepthDucting %Mechanism
00Z (evening)1,370m54.0%Elevated ducts within deep residual BL
12Z (morning)335m53.7%Surface/radiation ducts from shallow nocturnal BL

Ducting rate is identical at both times (~54%), but via different mechanisms. At 12Z, shallow BL (<500m) is the signature. At 00Z, the duct is typically elevated within a deeper residual boundary layer. A single BL depth threshold won't work across both regimes — use BL depth relative to expected diurnal range.

HRRR profile data (4,522 profiles) confirms the relationship is monotonic:

BL Depth BinCountAvg NAvg Min Gradient
0-200m1,096342.6-93.7
200-500m1,091346.6-81.5
500-1000m1,242337.0-70.1
1000-1500m735328.8-58.3
1500-2000m299325.2-51.0
2000m+60309.4-45.4

Finding 5: Binary Duct Detection Is Weak — Use Continuous Gradient

Ducting is the majority case in soundings: 2,099 ducting (53.8%) vs 1,800 non-ducting (46.2%). Binary detection has near-zero discriminating power.

DuctingCountAvg NAvg Min GradientAvg BL DepthAvg K-IndexAvg LI
No1,800327.4-123.4986m16.722.8
Yes2,099340.2-388.7738m12.725.3

The continuous gradient (-389 vs -123) is the real signal — a 3x magnitude difference. HRRR data shows 79% of profiles in "Enhanced" regime (gradient -40 to -100), so the scoring must discriminate within the enhanced category, not just between standard and enhanced.

Stability indices and ducting:

  • K-index is lower for ducting (12.7 vs 16.7) — stable atmosphere favors ducting, not convection
  • Lifted Index is higher for ducting (25.3 vs 22.8) — confirms stability correlation
  • Precipitable water is identical (28.0 mm) for both ducting and non-ducting — PWAT is NOT a useful ducting discriminator. It plateaus as a gradient predictor above ~15mm.

Finding 6: Diurnal Signal Variation Sets a Noise Floor

Commercial link data shows 1-5 dB daily variation even on perfectly clear, stable days. The algorithm should convey that even an "EXCELLENT" score has +/-2-3 dB inherent uncertainty.

Finding 7: LOS vs Beyond-LOS Regimes Are Inverted

On short LOS paths (3-7 km), sub-refractive conditions (dN/dh > -40/km) produce the best signal — minimal multipath, clean beam coupling. On long beyond-LOS paths (50-500+ km), enhanced refraction/ducting is essential. The algorithm must handle both regimes.

Finding 8: Time-of-Day Effect Scales with Frequency (Solar Time)

Night/dawn (22Z-10Z) enhancement vs afternoon baseline, from QSO distance data:

BandAfternoon AvgNight/Dawn AvgEnhancementP90 Boost
10 GHz209.7 km218.6 km+4%+8%
24 GHz93.8 km119.7 km+28%+16%
47 GHz63.5 km86.6 km+36%+42%
75 GHz38.1 km175.4 km+360%+237%

At 10 GHz the effect is modest. At 47+ GHz it is the dominant variable, more important than most weather parameters. The 75 GHz result is from only 20 night/dawn QSOs but the 4.6x multiplier is consistent with strong ducting being the only path at that frequency.

Update (April 2026): Switching from fixed CDT/CST timezone to longitude-based solar time (longitude / 15) dramatically improves the time-of-day correlation at higher frequencies. Spearman correlation with distance: UTC hour rho=0.056 vs solar hour rho=0.188 at 24 GHz (3.4x improvement). At 75 GHz the UTC correlation was confounded by geographic longitude — solar time corrects this from rho=-0.39 to rho=+0.24.

Finding 9: Ducting Peaks June-July, Not August

Monthly ducting probability from 3,901 soundings:

MonthSoundingsDucting %Avg NAvg Min GradientAvg PWAT (mm)
Jan3221.9%306.2-133.49.5
Feb5817.2%304.4-132.76.6
Mar3710.8%293.3-112.56.6
Apr6437.5%306.0-152.014.0
May6848.5%323.3-233.120.5
Jun13468.7%335.0-322.728.6
Jul8576.5%339.3-301.427.6
Aug1,70053.9%341.9-260.733.3
Sep1,56456.4%332.4-286.526.2
Oct4860.4%321.5-314.317.9
Nov5356.6%308.4-264.310.6
Dec5812.1%305.0-139.810.5

March is the worst month (10.8%), not winter. December-February averages ~17%. The sharp ramp April→July is nonlinear. Contest data (Aug-Sep) slightly undersamples the true ducting peak (Jun-Jul at 69-77%). Note: Aug/Sep have disproportionate sounding counts because data is enriched from QSO time windows during contest months.

Finding 10: Mode Matters — CW Advantage Scales with Frequency

Raw statistics show CW averaging 29% longer distances at 10 GHz, but this understates the true advantage due to contest strategy bias. The Great Lakes region generates 3.2x more PH contacts than CW via "firing squad" cross-lake SSB exchanges, inflating PH averages at every band. With cluster activity (EN, CM/DM grids) removed:

BandCW Advantage (corrected)Explanation
10 GHz+35%Ducting, moderate absorption
24 GHz+16%Ducting, high H2O absorption
47 GHz+48%Ducting, window band
75 GHz+221%Every dB counts at high absorption

CW advantage is monotonically increasing with frequency. The raw 24 GHz data shows PH winning (-8%) but this is entirely the Great Lakes firing squad — with manufactured contacts removed, CW leads by 16%.

SSB is not possible on rainscatter. FM is the mode used for rainscatter on 24 GHz.

At 75+ GHz, SSB is only viable for short-range contacts (median 13 km vs CW's 57 km). Above 122 GHz, 100% of contacts in the dataset are CW.

See docs/findings10.md for full regional breakdown and statistical analysis.

Finding 11: Regional Performance Varies but Is Not Algorithm-Correctable

10 GHz QSO distances by Maidenhead field (N≥20):

FieldRegionQSOsAvg kmP90 kmMax km
FMMid-Atlantic (DC/VA/MD)6643216061041
ELFlorida/Gulf Coast322314601609
CMN. California3,9352244111460
ENUpper Midwest (WI/MN/IL)18,7452173431223
FNNortheast (NY/NE)20,9572154181212
DMSoCal/Southwest6,3142033651448
EMSouth-Central (TX/OK)2,2041462721609
CNPacific Northwest11984192468

At 24 GHz, the ranking shifts — dry regions outperform because absorption dominates:

FieldRegionQSOsAvg kmP90 km
DMSoCal/Southwest279157227
CMN. California318129221
ENUpper Midwest1,13598178
FNNortheast1,64490144
EMSouth-Central2514383

Sounding data by region shows ducting frequency is broadly similar (52-62%), suggesting the atmosphere is not the primary driver of the 4x regional spread in QSO distances:

RegionStationsSoundingsDucting %Avg BL Depth
West Coast1763461.7%1043m
Southeast/Gulf291,35755.6%741m
Central371,23553.6%990m
Northeast/Mid-Atl1693052.3%558m

Why regional adjustments are NOT in the scoring model:

  1. Station density and operator skill dominate. The Mid-Atlantic's top ranking correlates with a dense cluster of experienced mountaintop operators, not unique atmospheric physics. Contest results reflect who showed up and where, not just propagation.
  2. Terrain is the confound. PNW (CN) underperforms due to Cascades blocking paths, not worse atmosphere. Terrain profiles handle this separately.
  3. The weather inputs already capture the physics. Coastal inversions (high humidity + refractivity), dry air (low absorption at 24G), and boundary layer depth are all in the scoring factors. If the Mid-Atlantic has better ducting conditions on a given day, it scores higher naturally.
  4. Overfitting risk. The QSO dataset is 97% Aug-Sep contests. Regional weights calibrated to contest patterns would break for non-contest conditions (winter, spring, nighttime).

The correct approach is to let the physics-based factors (humidity, refractivity gradient, BL depth, time of day) produce regional variation organically rather than applying static multipliers.


Part 2b: Data-Driven Refinements (April 2026)

This section documents findings from a systematic correlation analysis matching 57,248 QSOs to HRRR atmospheric conditions at both endpoints. Each QSO was joined to the nearest HRRR grid point (0.125° snap) at both station positions, using the profile valid at the hour of the contact. Spearman rank correlation (rho) measures monotonic association between each atmospheric variable and achieved distance — a nonparametric measure robust to outliers and non-linear relationships.

Correlation Rankings by Band

10 GHz (n=52,846):

Variablerhon_valid
Pressure (mb)-0.18052,846
Month0.10552,846
Dewpoint (°C)-0.05952,846
HPBL (m)0.04552,846
PWAT (mm)-0.03952,846
Refractivity Gradient-0.03452,347
Temperature (°C)0.03152,846
Surface Refractivity-0.02452,347
UTC Hour0.00752,846

24 GHz (n=3,621):

Variablerhon_valid
Dewpoint (°C)-0.3713,621
PWAT (mm)-0.3303,621
Surface Refractivity-0.3173,582
Month0.2723,621
Temperature (°C)-0.1793,621
Pressure (mb)-0.1723,621
Refractivity Gradient-0.0753,582
UTC Hour0.0563,621
HPBL (m)-0.0493,621

47 GHz (n=680):

Variablerhon_valid
Pressure (mb)-0.231680
PWAT (mm)-0.227680
Dewpoint (°C)-0.181680
Refractivity Gradient-0.139678
Month0.111680
Surface Refractivity-0.109678
Temperature (°C)0.037680
UTC Hour-0.024680
HPBL (m)0.004680

75 GHz (n=94):

Variablerhon_valid
Dewpoint (°C)-0.70394
PWAT (mm)-0.60894
Temperature (°C)-0.58994
Pressure (mb)-0.57094
Surface Refractivity-0.52694
UTC Hour-0.39294
HPBL (m)0.15094
Month0.14494
Refractivity Gradient-0.08294

Key Insights

1. Pressure was massively underweighted. It is the #1 correlator at 10 GHz (rho=-0.180) but was assigned only 4% weight. The binned analysis is unambiguous:

Pressure BinnMedian kmp25p75
<1005 mb47,669197.1121.2285.1
1005-1013 mb3,447151.3100.7289.2
1013-1020 mb1,254130.877.9239.2
>1020 mb476103.476.8191.3

Low pressure (<1005 mb) gives 197 km median vs 103 km for >1020 mb — a nearly 2x difference. The old scoring function scored high pressure higher, which was completely backwards for beyond-LOS propagation. Low pressure systems bring frontal boundaries, moisture gradients, and boundary-layer structures that create ducting conditions.

2. Time of day was overweighted at 10 GHz. UTC hour correlates at rho=0.007 — barely above zero. The binned data shows modest variation (181-210 km across 3-hour blocks) with no clear diurnal signal at 10 GHz. The 20% weight was far too high for this band. Time of day matters more at 24+ GHz (rho=0.056 at 24 GHz, -0.392 at 75 GHz), consistent with Finding 8 in Part 2, but the weight should scale with frequency rather than being uniform.

3. Refractivity gradient is weaker than expected. Correlation ranges from rho=-0.034 at 10 GHz to -0.139 at 47 GHz. The HRRR's 8-level vertical resolution is too coarse to resolve the thin ducting layers that produce the strongest gradients. The binned analysis at 10 GHz confirms: gradient <-300 gives 214 km median vs 192 km for >-100 — only an 11% improvement. Still useful but the 10% weight was generous given the data.

4. PWAT is a strong independent predictor not captured by any existing factor. Correlations range from rho=-0.039 at 10 GHz to -0.608 at 75 GHz. At 10 GHz, the relationship is non-monotonic with a sweet spot:

PWAT BinnMedian kmp25p75
<10 mm1,834160.696.8265.0
10-20 mm15,041193.8125.1280.7
20-30 mm17,788218.8129.9295.6
30-40 mm13,999173.9106.5289.6
>40 mm4,184155.284.5256.1

At 24 GHz, the relationship is monotonic — lower is always better: <10 mm gives 126 km median vs 45 km for >40 mm. PWAT integrates the full moisture column and captures information beyond surface-level humidity and Td depression.

5. Ducting detection is a non-discriminator at 10 GHz. Ducting YES: n=7,979, median 189 km. Ducting NO: n=44,867, median 192 km. The non-ducting group actually achieves slightly longer median distances. Binary ducting detection from HRRR profiles is useless for scoring — consistent with Finding 5 in Part 2, now confirmed with 10x the sample size using HRRR data rather than soundings.

6. Data is almost entirely Aug/Sep. Of 52,846 QSOs at 10 GHz, 26,813 are August and 26,024 are September. Only 9 QSOs fall outside these months. This limits seasonal conclusions but does not invalidate the atmospheric correlations within those months — pressure, PWAT, and temperature-dewpoint vary substantially within Aug-Sep due to synoptic weather patterns.

Interaction Effects (10 GHz)

The analysis tested whether atmospheric variables interact (i.e., does the effect of one variable depend on the value of another):

Refractivity Gradient x Time of Day: Strong gradients (avg < -100 N/km) improve night/morning distances by 20-30 km but have negligible or negative effect in the afternoon. At night, strong gradient gives 204 km vs 168 km for weak gradient. In the afternoon, the relationship inverts: weak gradient gives 198 km vs 190 km for strong. This suggests afternoon convective mixing disrupts duct structures regardless of gradient strength.

HPBL x Season: In summer, deeper BL correlates with longer distances (shallow 180 km, mid 207 km, deep 231 km). In fall, the relationship flattens (shallow 184 km, mid 194 km, deep 188 km). Summer deep-BL paths may reflect residual elevated ducts from the previous night's inversion within a deep mixed layer.


Part 3: Band Configuration

@band_configs %{
  10_000 => %{
    label: "10 GHz",
    o2_db_km: 0.008,
    h2o_coeff: 0.0005,
    humidity_effect: :beneficial,  # More moisture = more refractivity = longer paths
    humidity_penalty: 0.0,
    rain_k: 0.010, rain_alpha: 1.28,
    # Seasonal pattern INVERTED from 24+ GHz: ducting + humidity both help 10G
    # Ducting peaks Jun-Jul (69-77%), March worst (10.8%), Dec-Feb ~12-22%
    # Score tracks ducting probability scaled to 0-100
    seasonal_base: %{1 => 38, 2 => 32, 3 => 22, 4 => 55, 5 => 68,
                     6 => 90, 7 => 95, 8 => 75, 9 => 78, 10 => 82,
                     11 => 78, 12 => 25},
    seasonal_adj: %{},
    typical_range_km: 200,
    extended_range_km: 500,
    exceptional_range_km: 1000
  },
  24_000 => %{
    label: "24 GHz",
    o2_db_km: 0.015,
    h2o_coeff: 0.012,           # Validated by commercial link data
    humidity_effect: :harmful,   # 22.235 GHz H2O line shoulder
    humidity_penalty: 1.6,
    rain_k: 0.070, rain_alpha: 1.07,
    # 24G: humidity hurts, so best in dry months. But March is worst for ducting.
    # Balance: winter dry + some ducting > spring dry + no ducting
    seasonal_base: %{1 => 88, 2 => 84, 3 => 68, 4 => 62, 5 => 51,
                     6 => 34, 7 => 18, 8 => 18, 9 => 48, 10 => 68,
                     11 => 96, 12 => 88},
    seasonal_adj: %{5 => -4, 6 => -8, 7 => -10, 8 => -10, 9 => -4},
    typical_range_km: 100,
    extended_range_km: 250,
    exceptional_range_km: 500
  },
  47_000 => %{
    label: "47 GHz",
    o2_db_km: 0.045,
    h2o_coeff: 0.003,
    humidity_effect: :harmful,
    humidity_penalty: 1.0,       # Window band, moderate H2O sensitivity
    rain_k: 0.187, rain_alpha: 0.93,
    seasonal_base: %{1 => 90, 2 => 88, 3 => 78, 4 => 68, 5 => 55,
                     6 => 38, 7 => 22, 8 => 22, 9 => 48, 10 => 74,
                     11 => 96, 12 => 90},
    seasonal_adj: %{},
    typical_range_km: 70,
    extended_range_km: 150,
    exceptional_range_km: 300
  },
  68_000 => %{
    label: "68 GHz",
    o2_db_km: 0.90,             # 60 GHz O2 band wing — validated by link data
    h2o_coeff: 0.007,           # Measured: ~0.1 dB/km per g/m^3 on 2.8 km path
    humidity_effect: :harmful,
    humidity_penalty: 1.4,
    rain_k: 0.310, rain_alpha: 0.86,
    seasonal_base: %{1 => 90, 2 => 88, 3 => 78, 4 => 65, 5 => 50,
                     6 => 32, 7 => 18, 8 => 18, 9 => 44, 10 => 70,
                     11 => 92, 12 => 90},
    seasonal_adj: %{},
    typical_range_km: 40,
    extended_range_km: 80,
    exceptional_range_km: 150
  },
  75_000 => %{
    label: "75 GHz",
    o2_db_km: 0.012,
    h2o_coeff: 0.006,
    humidity_effect: :harmful,
    humidity_penalty: 1.2,
    rain_k: 0.345, rain_alpha: 0.84,
    seasonal_base: %{1 => 90, 2 => 90, 3 => 80, 4 => 68, 5 => 55,
                     6 => 38, 7 => 22, 8 => 22, 9 => 48, 10 => 74,
                     11 => 96, 12 => 90},
    seasonal_adj: %{},
    typical_range_km: 50,
    extended_range_km: 120,
    exceptional_range_km: 250
  },
  122_000 => %{
    label: "122 GHz",
    o2_db_km: 0.80,             # 118.75 GHz O2 wing — weather independent
    h2o_coeff: 0.010,
    humidity_effect: :harmful,
    humidity_penalty: 1.0,
    rain_k: 0.498, rain_alpha: 0.77,
    seasonal_base: %{1 => 92, 2 => 90, 3 => 78, 4 => 62, 5 => 45,
                     6 => 28, 7 => 15, 8 => 15, 9 => 38, 10 => 68,
                     11 => 92, 12 => 92},
    seasonal_adj: %{},
    typical_range_km: 30,
    extended_range_km: 80,
    exceptional_range_km: 140
  },
  134_000 => %{
    label: "134 GHz",
    o2_db_km: 0.08,
    h2o_coeff: 0.015,
    humidity_effect: :harmful,
    humidity_penalty: 1.3,
    rain_k: 0.520, rain_alpha: 0.75,
    seasonal_base: %{1 => 92, 2 => 90, 3 => 78, 4 => 65, 5 => 48,
                     6 => 30, 7 => 18, 8 => 18, 9 => 42, 10 => 70,
                     11 => 92, 12 => 92},
    seasonal_adj: %{},
    typical_range_km: 40,
    extended_range_km: 100,
    exceptional_range_km: 160
  },
  241_000 => %{
    label: "241 GHz",
    o2_db_km: 0.08,
    h2o_coeff: 0.30,            # Extreme H2O sensitivity (183/325 GHz lines)
    humidity_effect: :harmful,
    humidity_penalty: 3.0,
    rain_k: 0.550, rain_alpha: 0.70,
    seasonal_base: %{1 => 95, 2 => 92, 3 => 75, 4 => 55, 5 => 35,
                     6 => 15, 7 => 8, 8 => 8, 9 => 30, 10 => 65,
                     11 => 95, 12 => 95},
    seasonal_adj: %{},
    typical_range_km: 10,
    extended_range_km: 50,
    exceptional_range_km: 115
  }
}

Part 4: Scoring Functions (Beyond-LOS Regime)

All scores return 0-100. The beyond-LOS regime is the primary use case for ham radio propagation prediction.

1. Humidity Score — Frequency-Dependent

The critical insight: moisture helps at 10 GHz (refractivity) and hurts at 24+ GHz (absorption).

def score_humidity(abs_humidity_gm3, band_config) do
  case band_config.humidity_effect do
    :beneficial ->
      # 10 GHz: more moisture = higher surface N = more beam bending
      # Extreme humidity risks scintillation
      cond do
        abs_humidity_gm3 < 4  -> 55   # Very dry — poor refractivity
        abs_humidity_gm3 < 7  -> 70   # Dry
        abs_humidity_gm3 < 10 -> 82   # Moderate
        abs_humidity_gm3 < 14 -> 90   # Good refractivity
        abs_humidity_gm3 < 18 -> 95   # Excellent refractivity
        abs_humidity_gm3 < 22 -> 88   # High — scintillation onset
        true                  -> 75   # Tropical — scintillation risk
      end

    :harmful ->
      # 24+ GHz: H2O absorption dominates
      # Penalty factor scales by band (1.0 for 47G window, 1.6 for 24G near line, 3.0 for 241G)
      r = abs_humidity_gm3 * band_config.humidity_penalty
      cond do
        r <= 6  -> 100
        r <= 9  -> round(95 - (r - 6) / 3 * 20)
        r <= 13 -> round(75 - (r - 9) / 4 * 30)
        r <= 18 -> round(45 - (r - 13) / 5 * 35)
        true    -> max(0, round(10 - (r - 18) * 2))
      end
  end
end

2. Time of Day Score — Solar Time, Inversion Lifecycle

Uses longitude-based solar time (longitude / 15 offset) instead of a fixed timezone offset. This produces physically correct local time at every grid point across CONUS and dramatically improves correlation with QSO distance:

BandUTC Hour rhoSolar Hour rhoImprovement
10 GHz0.0070.0162.4x (still weak — 10G ducts form at all times)
24 GHz0.0560.1883.4x (now #5 predictor)
47 GHz-0.0240.152Sign corrected (UTC was confounded by longitude)
75 GHz-0.3920.239Sign corrected (western US at lower UTC ≠ better propagation)

The UTC hour correlation at 75 GHz was spuriously negative because western US stations (lower UTC hours) happened to have longer paths — a geographic confound, not physics. Solar time corrects this.

At 24 GHz, the solar hour bins show a clear physical pattern: 03-05 solar (pre-dawn) has worst distances (57 km median), evening/night (18-23 solar) has best (107-140 km median) — consistent with nocturnal inversion formation.

@sunrise_table [7.4, 7.3, 7.0, 6.7, 6.35, 6.25,
                6.35, 6.65, 6.9, 7.1, 7.35, 7.45]

def score_time_of_day(utc_hour, utc_minute, month, longitude) do
  offset = longitude / 15  # solar time offset from longitude
  local = rem(utc_hour + utc_minute / 60 + offset + 24, 24)
  sunrise = Enum.at(@sunrise_table, month - 1)
  d = local - sunrise  # hours relative to sunrise

  cond do
    d >= -1.5 and d <= 1.5 ->
      {100, "Peak — inversion maximum"}

    d > 1.5 and d <= 3.0 ->
      {78, "Good — inversion eroding"}

    d > -3.0 and d < -1.5 ->
      {82, "Pre-dawn — inversion building"}

    d > 3.0 and d <= 6.0 ->
      {38, "Marginal — boundary layer mixing"}

    local >= 20.0 or local <= 1.0 ->
      {72, "Evening — cooling, inversion reforming"}

    d > 6.0 ->
      {18, "Afternoon — full convective mixing"}

    true ->
      {55, "Night — gradual cooling"}
  end
end

3. Temperature-Dewpoint Depression — Frequency-Split

Large depression = dry aloft = favorable for 24+ GHz. Small depression = moist = favorable for 10 GHz refractivity (but near-saturation risks fog).

def score_td_depression(temp_f, dewpoint_f, band_config) do
  dep = temp_f - dewpoint_f

  case band_config.humidity_effect do
    :beneficial ->
      cond do
        dep < 3  -> 40   # Near saturation — fog/scattering risk
        dep < 8  -> 75   # Moist — good refractivity
        dep < 14 -> 85   # Moderate — balanced
        dep < 22 -> 70   # Dry — reduced refractivity
        true     -> 55   # Very dry — poor refractivity
      end

    :harmful ->
      cond do
        dep > 22 -> 96   # Very dry aloft
        dep > 14 -> 80   # Good stability
        dep > 8  -> 60   # Moderate
        dep > 4  -> 38   # Marginal
        true     -> 18   # Humid aloft
      end
  end
end

4. Sky Cover Score

Data shows modest impact at 24/47 GHz, near-zero at 10 GHz. VV (vertical visibility / fog) is a moderate penalty due to near-surface moisture content. Supports both METAR categories (from ASOS) and percentage sky cover (from IEMRE gridded data).

def score_sky(condition) when is_binary(condition) do
  # METAR category from ASOS
  case condition do
    c when c in ["CLR", "SKC"] -> 100
    "FEW" -> 88
    "SCT" -> 60
    "BKN" -> 25
    "OVC" -> 5
    "VV"  -> 5
    _     -> 50
  end
end

def score_sky(pct) when is_number(pct) do
  # Percentage sky cover from IEMRE (0-100%)
  cond do
    pct <= 6   -> 100  # CLR equivalent
    pct <= 25  -> 88   # FEW
    pct <= 50  -> 60   # SCT
    pct <= 87  -> 25   # BKN
    true       -> 5    # OVC
  end
end

5. Season Score

Per-band lookup with optional adjustments. 24 GHz gets additional summer penalties due to Gulf moisture.

def score_season(month, band_config) do
  base = Map.get(band_config.seasonal_base, month, 50)
  adj = Map.get(band_config.seasonal_adj, month, 0)
  max(0, min(100, base + adj))
end

6. Wind Score — Reduced Weight

Data shows minimal impact on achieved distance. Retain mild penalty only for very high winds (turbulent scintillation).

def score_wind(speed_kts) do
  cond do
    speed_kts < 5  -> 100
    speed_kts < 10 -> 90
    speed_kts < 15 -> 75
    speed_kts < 20 -> 55
    speed_kts < 25 -> 35
    true           -> 15
  end
end

7. Rain Score

Not validated by measured data. Based on ITU-R P.838-3 attenuation per km. At 10 GHz, moderate rain is tolerable. Above 75 GHz, even light rain effectively kills the path.

def score_rain(rain_rate_mmhr, band_config) do
  if rain_rate_mmhr == nil or rain_rate_mmhr == 0 do
    100
  else
    gamma = band_config.rain_k * :math.pow(rain_rate_mmhr, band_config.rain_alpha)
    cond do
      gamma < 0.1 -> 95
      gamma < 0.5 -> 75
      gamma < 1.0 -> 50
      gamma < 2.0 -> 25
      gamma < 5.0 -> 10
      true        -> 0
    end
  end
end

8. Pressure Score — Low Pressure Favors Beyond-LOS

Data from 57,248 QSO-HRRR matches shows pressure is the #1 correlator at 10 GHz (rho=-0.180). The relationship is monotonic and strong: <1005 mb gives 197 km median vs 103 km for >1020 mb. Low pressure systems bring frontal boundaries, moisture gradients, and boundary-layer structures that create ducting conditions. The previous function scored high pressure higher — completely backwards for beyond-LOS propagation.

When trend data is available, falling pressure (approaching front) scores highest because pre-frontal dynamics create the strongest refractive gradients.

def score_pressure(current_mb, previous_mb) do
  case previous_mb do
    nil ->
      # No trend — score on absolute value, low pressure = better
      cond do
        current_mb < 1005 -> 80   # Low — frontal activity, boundary ducts
        current_mb < 1010 -> 70   # Moderate low
        current_mb < 1015 -> 60   # Normal
        current_mb < 1020 -> 45   # Mild high — stable, less ducting
        true              -> 30   # Strong ridge — inversions cap at wrong altitude
      end

    prev ->
      delta = current_mb - prev
      cond do
        delta > 2.5  -> 80   # Rising rapidly — post-frontal clearing, residual ducts
        delta > 0.8  -> 70   # Rising — stabilizing
        delta > -0.5 -> 60   # Steady — neutral
        delta > -2.0 -> 65   # Falling slowly — approaching front
        true         -> 45   # Falling rapidly — active frontal dynamics, mixing
      end
  end
end

9. Refractivity Score — When Sounding/HRRR Data Available

Best predictor when available. Binary duct detection is useless (54% baseline rate). Use continuous gradient magnitude and BL depth instead.

Thresholds calibrated for HRRR-derived gradients which are coarser than radiosonde soundings. HRRR gradient distribution: p1=-230, p5=-162, p10=-130, p25=-94, p50=-70, p75=-53, p95=-40 N/km. Previous thresholds (-500 to -60) placed nearly all HRRR profiles in the default bucket.

Gradient (N/km)Beneficial ScoreHarmful ScoreCondition
< -2009885Strong ducting (HRRR p1)
< -1509280Enhanced refraction (HRRR p5)
< -1008272Above-average refraction (HRRR p25)
< -756862Near-median gradient (HRRR p50)
< -555555Below-median (HRRR p75)
< -404848Weak gradient (HRRR p95)
≥ -404242Standard/sub-refractive

Shallow BL fallback: when gradient is unavailable but BL depth < 300m, score 82 (strong inversion cap).

10. PWAT Score — Precipitable Water (NEW)

PWAT (precipitable water, total column integrated moisture in mm) is a strong independent predictor that was not previously a separate scoring factor. Correlation with distance ranges from rho=-0.039 at 10 GHz to -0.608 at 75 GHz. Unlike surface humidity and Td depression which measure conditions at ground level, PWAT integrates the full moisture column and captures elevated moisture layers relevant to duct formation and path absorption.

At 10 GHz (beneficial humidity), the relationship is non-monotonic: 20-30 mm PWAT gives the best median distances (219 km), with both very dry (<10 mm, 161 km) and very wet (>40 mm, 155 km) conditions performing worse. Moderate PWAT indicates sufficient moisture for refractivity enhancement without the atmospheric instability that accompanies very high moisture content.

At 24+ GHz (harmful humidity), lower PWAT is universally better. At 24 GHz: <10 mm gives 126 km median, >40 mm gives 45 km — a 2.8x difference.

def score_pwat(pwat_mm, band_config) do
  case band_config.humidity_effect do
    :beneficial ->
      # 10 GHz: sweet spot at moderate PWAT (20-30 mm)
      cond do
        pwat_mm < 10 -> 55   # Very dry — poor refractivity
        pwat_mm < 20 -> 75   # Moderate dry
        pwat_mm < 30 -> 90   # Optimal — best median distances
        pwat_mm < 40 -> 70   # High — beginning absorption penalty
        true         -> 50   # Very high — absorption dominates
      end

    :harmful ->
      # 24+ GHz: lower is better, scales by frequency via humidity_penalty
      cond do
        pwat_mm < 10 -> 95   # Very dry — minimal absorption
        pwat_mm < 20 -> 80   # Low — good conditions
        pwat_mm < 30 -> 60   # Moderate — noticeable absorption
        pwat_mm < 40 -> 35   # High — significant absorption
        true         -> 15   # Very high — severe absorption
      end
  end
end

Part 5: Composite Score

Weights

Revised April 2026 based on 57,248 QSO-HRRR correlation analysis. Key changes from previous weights:

  • Pressure: 4% → 15% — #1 correlator at 10 GHz (rho=-0.180); data shows low P (<1005 mb) gives 197 km median vs 103 km for >1020 mb. Previously scored backwards (high=good). Now the largest single-factor weight increase in algorithm history.
  • PWAT: 0% → 10% — New factor. Strong independent predictor across all bands (rho=-0.039 to -0.608). Captures column-integrated moisture not represented by surface humidity or Td depression.
  • Time of Day: 20% → 10% — rho=0.007 at 10 GHz; effect is real at 24+ GHz (rho=-0.392 at 75 GHz) but the 20% weight was unwarranted at the dominant 10 GHz band. Modest even at 24 GHz (rho=0.056).
  • Humidity: 20% → 18% — Still the strongest signal at 24+ GHz (dewpoint rho=-0.371 at 24 GHz, -0.703 at 75 GHz) but mixed/weak at 10 GHz (rho=-0.059).
  • Td Depression: 12% → 10% — Partially redundant with humidity and PWAT; retains value as a distinct atmospheric stability indicator.
  • Refractivity: 10% → 8% — Weaker than expected (rho=-0.034 to -0.139). HRRR vertical resolution too coarse for thin duct detection. Still useful for strong events.
  • Sky Cover: 10% → 8% — No direct measurement in this analysis; retained at reduced weight based on physical rationale (radiative cooling).
  • Season: 10% → 8% — Aug/Sep bias in dataset limits validation. Physics-based seasonal curves remain valid but cannot be tuned from this data.
  • Rain: 8% → 8% — Unchanged. ITU-R P.838-3 validated, critical for high-frequency paths.
  • Wind: 6% → 5% — Minimal impact confirmed (Finding 2, Part 2).
FactorOld WeightNew WeightRationale
Humidity20%18%Strong at 24+ GHz (dewpoint rho=-0.37 to -0.70); mixed signal at 10 GHz
Pressure4%15%#1 correlator at 10 GHz (rho=-0.18); low P = longer paths confirmed
Time of Day20%10%rho=0.007 at 10 GHz; modest even at 24 GHz
Td Depression12%10%Partially redundant with humidity/PWAT
PWAT10%NEW: strong independent predictor all bands (rho=-0.04 to -0.61)
Refractivity10%8%Weak correlation; HRRR too coarse for thin ducts
Sky Cover10%8%No direct measurement in analysis; physics still valid
Season10%8%Aug/Sep bias limits validation; physics-based curves retained
Rain8%8%ITU-R validated, critical for high freq
Wind6%5%Minimal impact confirmed
def composite_score(factors) do
  round(
    factors.humidity      * 0.18 +
    factors.pressure      * 0.15 +
    factors.time_of_day   * 0.10 +
    factors.td_depression * 0.10 +
    factors.pwat          * 0.10 +
    factors.refractivity  * 0.08 +
    factors.sky           * 0.08 +
    factors.season        * 0.08 +
    factors.rain          * 0.08 +
    factors.wind          * 0.05
  )
end

Score Tiers with Per-Band Range Estimates

Range estimates are for CW mode. For SSB/phone, reduce by ~25% at 10 GHz, ~15% at 24 GHz, ~50% at 47 GHz, ~70% at 75+ GHz. For FM, reduce by ~40%.

Database stats for reference: 10G avg=213 km, P90=383 km, max=2,393 km. 24G avg=98 km, P90=179 km, max=710 km. 47G avg=66 km, P90=122 km, max=343 km. 75G avg=64 km, P90=177 km, max=289 km.

ScoreLabel10G24G47G75G
80-100EXCELLENT400-2000+ km200-500 km120-300 km80-200+ km
65-79GOOD250-400 km120-200 km80-120 km50-80 km
50-64MARGINAL150-250 km70-120 km50-80 km30-50 km
33-49POOR80-150 km40-70 km25-50 km15-30 km
0-32NEGLIGIBLE<80 km<40 km<25 km<15 km
ColorHex
EXCELLENT#00ffa3
GOOD#7dffd4
MARGINAL#ffe566
POOR#ff9044
NEGLIGIBLE#ff4f4f

Part 6: LOS Regime Scoring

For known fixed links or short paths with confirmed Fresnel clearance. Key difference: sub-refraction is neutral/beneficial (minimal multipath), and gaseous absorption is the primary variable.

LOS Refractivity Score

def score_refractivity_los(dn_dh) do
  cond do
    dn_dh > 0     -> 60   # Strong sub-refraction — unusual but not harmful
    dn_dh > -30   -> 85   # Moderate sub-refraction — stable, clean signal
    dn_dh > -40   -> 75   # Near standard
    dn_dh > -80   -> 60   # Enhanced — multipath onset
    dn_dh > -157  -> 45   # Strong enhancement — multipath likely
    true          -> 30   # Super-refraction — significant multipath fading
  end
end

LOS Surface N Score

Higher N often means more moisture = more absorption at 24+ GHz. Validated by link data: N < 310 gave best 68 GHz signal, N > 340 gave worst.

def score_surface_n(n_value, band_config) do
  case band_config.humidity_effect do
    :beneficial ->
      cond do
        n_value > 350 -> 90
        n_value > 330 -> 80
        n_value > 315 -> 65
        n_value > 300 -> 50
        true          -> 35
      end

    :harmful ->
      cond do
        n_value < 300 -> 90
        n_value < 315 -> 80
        n_value < 330 -> 65
        n_value < 345 -> 50
        true          -> 35
      end
  end
end

LOS vs Beyond-LOS Selection

def compute_score(conditions, band_config, path_type \\ :beyond_los) do
  base_factors = %{
    humidity: score_humidity(conditions.abs_humidity, band_config),
    wind: score_wind(conditions.wind_speed_kts),
    sky: score_sky(conditions.sky_condition),
    time_of_day: score_time_of_day(conditions.utc_hour, conditions.utc_minute, conditions.month, conditions.longitude) |> elem(0),
    td_depression: score_td_depression(conditions.temp_f, conditions.dewpoint_f, band_config),
    season: score_season(conditions.month, band_config),
    pressure: score_pressure(conditions.slp, conditions.prev_slp),
    rain: score_rain(conditions.rain_rate, band_config),
    pwat: score_pwat(conditions.pwat_mm, band_config)
  }

  factors = case path_type do
    :beyond_los ->
      Map.put(base_factors, :refractivity,
        score_refractivity(conditions.sounding, band_config))

    :los ->
      Map.put(base_factors, :refractivity,
        score_refractivity_los(conditions.dn_dh))
  end

  %{score: composite_score(factors), factors: factors}
end

Part 7: Link Budget

For point-to-point path analysis with known station parameters.

EIRP

eirp_dbm = tx_power_dbm + tx_antenna_dbi - feed_loss_db

Receiver Sensitivity

sensitivity_dbm = -174 + noise_figure_db + 10 * log10(bandwidth_hz)

CW: bandwidth = 500 Hz
SSB: bandwidth = 2700 Hz

Total Path Loss

total_loss = FSPL + gaseous_absorption + rain_attenuation + diffraction_loss - duct_enhancement

gaseous_absorption = (o2_db_km + h2o_coeff * rho) * distance_km
rain_attenuation = gamma_R * distance_km * rain_effective_fraction

Duct Enhancement (Beyond-LOS Only)

Calibrated against confirmed contacts:

def duct_enhancement_db(prop_score) do
  cond do
    prop_score >= 80 -> -14   # 14 dB improvement
    prop_score >= 65 -> -10
    prop_score >= 50 -> -6
    prop_score >= 33 -> -2
    true             -> 0
  end
end

Knife-Edge Diffraction (ITU-R P.526-16 Eq. 31)

Single clean formula replacing the previous piecewise approximation:

J(ν) = 6.9 + 20·log10(√((ν−0.1)² + 1) + ν − 0.1)    for ν > −0.78
J(ν) = 0                                                 for ν ≤ −0.78

Diffraction parameter ν (P.526-16):

ν = h · √(2·(d1+d2) / (λ·d1·d2))

where h is the obstacle height above the direct ray (positive = blocked, negative = clear). At grazing (ν = 0), loss is ~6 dB. At 0.6× Fresnel clearance (ν ≈ −0.85), loss is negligible.

Deygout Multi-Edge Method (ITU-R P.526-16 Section 6)

For paths with multiple terrain obstacles, the Deygout 3-edge method is used instead of single-worst-obstacle:

  1. Find the principal edge — the point with the highest ν on the full T→R path
  2. Find subsidiary edge on the T→principal sub-path (highest ν)
  3. Find subsidiary edge on the principal→R sub-path (highest ν)
  4. Total diffraction loss = J(νmain) + J(νsub1) + J(ν_sub2)

This produces higher (more realistic) diffraction estimates for paths crossing multiple ridgelines. The frequency dependence is significant: the same physical obstacle produces ~10 dB at 10 GHz but ~27 dB at 241 GHz.

Success Probability

def margin_to_success(margin_db, prop_score) do
  margin_pct = cond do
    margin_db <= 0  -> 0
    margin_db <= 10 -> margin_db / 10 * 20
    margin_db <= 15 -> 20 + (margin_db - 10) / 5 * 20
    margin_db <= 20 -> 40 + (margin_db - 15) / 5 * 20
    margin_db <= 25 -> 60 + (margin_db - 20) / 5 * 20
    margin_db <= 30 -> 80 + (margin_db - 25) / 5 * 20
    true            -> 100
  end

  # Propagation modulation: score 100 -> x1.30, score 50 -> x1.00, score 0 -> x0.70
  prop_factor = 0.70 + (prop_score / 100) * 0.60
  max(0, min(99, round(margin_pct * prop_factor)))
end

Note: Antenna Height & Duct Coupling Geometry

Antenna height and dish elevation angle affect how efficiently a station couples into an atmospheric duct. This is a real physical effect but is second-order to duct characteristics at the ranges this model targets (50-1000+ km).

Why it's not in the scoring model:

  • At >300 km, the duct's own refractive gradient (k-factor) dominates over all antenna geometry. The required aim angle to graze a duct converges toward 0° regardless of antenna height.
  • Antenna height differences in the 15-21m range (typical amateur stations) shift beam geometry by ~0.001° at long range — well within the ±2-3 dB noise floor from diurnal variation.
  • The primary benefit of antenna height (50+ ft) is clearing local obstructions and ground clutter in the near field (0-20 km), not geometric coupling to the duct layer.
  • VE4MA (50 ft, flat prairie) and W5LUA (70 ft, suburban) achieve similar range classes, confirming duct geometry is the dominant term.

Where it matters — beamwidth vs frequency: At 10 GHz a typical 60cm dish has ~3° beamwidth, making elevation angle errors forgiving. At 24 GHz beamwidth shrinks to ~1.5°, at 47 GHz to <1°. A 0.3° aim error that is irrelevant at 10 GHz becomes a contact killer at 47 GHz. If station profiles (antenna height, dish size, elevation setting) are added in the future, a frequency-dependent beamwidth coupling penalty in margintosuccess would be the right integration point — penalizing paths where the required aim angle to the detected duct layer exceeds the antenna's half-power beamwidth.


Part 8: Short-Term Prediction Model

Approach

Extrapolate current conditions forward 1-6 hours using observed trends, diurnal models, and forecast data when available.

Prediction Confidence

Based on commercial link signal prediction accuracy:

HorizonObserved AccuracyConfidence
Current+/- 1 dB95%
+30 min+/- 1.5 dB90%
+1 hr+/- 2 dB85%
+2 hr+/- 3 dB75%
+3 hr+/- 4 dB60%
+6 hr+/- 5 dB40%

Diurnal Temperature Model

def project_temperature(current_temp_f, trend_per_hour, hours_ahead,
                        future_local_hour, month) do
  sunrise = Enum.at(@sunrise_table, month - 1)

  diurnal_rate = cond do
    future_local_hour < sunrise - 1 -> -0.5    # Pre-dawn: slow cooling
    future_local_hour < sunrise + 2 -> 0.0     # Sunrise transition
    future_local_hour < 15          -> 2.0     # Morning: warming
    future_local_hour < 18          -> 0.5     # Late afternoon
    future_local_hour < 21          -> -1.5    # Evening: cooling
    true                            -> -1.0    # Night: slow cooling
  end

  # Blend: current trend dominates short-term, diurnal model dominates long-term
  weight = min(1.0, hours_ahead / 4.0)
  blended_rate = trend_per_hour * (1.0 - weight) + diurnal_rate * weight
  current_temp_f + blended_rate * hours_ahead
end

Prediction Flow

def predict_scores(current_obs, obs_3hr_ago, forecast, band_config) do
  temp_trend = (current_obs.temp_f - obs_3hr_ago.temp_f) / 3
  dp_trend = (current_obs.dewpoint_f - obs_3hr_ago.dewpoint_f) / 3
  pressure_trend = (current_obs.slp - obs_3hr_ago.slp) / 3

  for hours_ahead <- 1..6 do
    future_time = DateTime.add(current_obs.observed_at, hours_ahead * 3600)
    month = future_time.month

    projected_temp = project_temperature(current_obs.temp_f, temp_trend,
                       hours_ahead, future_time.hour, month)
    projected_dp = current_obs.dewpoint_f + dp_trend * hours_ahead
    projected_slp = current_obs.slp + pressure_trend * hours_ahead
    projected_sky = forecast_value(forecast, :sky, hours_ahead) || current_obs.sky_condition
    projected_rain = forecast_value(forecast, :rain_rate, hours_ahead) || 0
    projected_wind = forecast_value(forecast, :wind_kts, hours_ahead) || current_obs.wind_speed_kts

    # Compute absolute humidity from projected values
    tc = (projected_temp - 32) * 5 / 9
    td_c = (projected_dp - 32) * 5 / 9
    es = 6.112 * :math.exp(17.67 * tc / (tc + 243.5))
    ed = 6.112 * :math.exp(17.67 * td_c / (td_c + 243.5))
    rh = min(100, ed / es * 100)
    abs_hum = 217 * (rh / 100) * es / (tc + 273.15)

    factors = %{
      humidity: score_humidity(abs_hum, band_config),
      wind: score_wind(projected_wind),
      sky: score_sky(projected_sky),
      time_of_day: score_time_of_day(future_time.hour, future_time.minute, month, longitude) |> elem(0),
      td_depression: score_td_depression(projected_temp, projected_dp, band_config),
      season: score_season(month, band_config),
      pressure: score_pressure(projected_slp, current_obs.slp),
      rain: score_rain(projected_rain, band_config),
      pwat: score_pwat(forecast_value(forecast, :pwat_mm, hours_ahead) || 50, band_config),
      refractivity: 50  # Cannot predict from surface obs alone
    }

    %{
      hours_ahead: hours_ahead,
      time: future_time,
      score: composite_score(factors),
      factors: factors,
      confidence: prediction_confidence(hours_ahead)
    }
  end
end

def prediction_confidence(hours_ahead) do
  case hours_ahead do
    1 -> 0.85
    2 -> 0.75
    3 -> 0.60
    4 -> 0.50
    5 -> 0.40
    6 -> 0.30
    _ -> 0.20
  end
end

Part 9: Sounding & Refractivity Analysis

Refractivity Profile from Sounding

def compute_refractivity_profile(levels, sfc_height_m) do
  Enum.map(levels, fn level ->
    t_k = level.temp_c + 273.15
    e = 6.1121 * :math.exp((18.678 - level.temp_c / 234.5) * (level.temp_c / (257.14 + level.temp_c)))
    e_actual = if level.dewpoint_c, do: 6.1121 * :math.exp((18.678 - level.dewpoint_c / 234.5) * (level.dewpoint_c / (257.14 + level.dewpoint_c))), else: 0

    n = 77.6 * level.pressure_hpa / t_k + 3.73e5 * e_actual / (t_k * t_k)
    h_agl = level.height_m - sfc_height_m
    m = n + 0.157 * h_agl

    %{height_agl: h_agl, n: n, m: m, temp_c: level.temp_c, dewpoint_c: level.dewpoint_c}
  end)
end

Duct Detection

Duct exists where dM/dh < 0. Filter for strength > 2 M-units.

def detect_ducts(profile) do
  profile
  |> Enum.chunk_every(2, 1, :discard)
  |> Enum.reduce({[], nil}, fn [below, above], {ducts, duct_start} ->
    dm = above.m - below.m

    cond do
      dm < 0 and duct_start == nil ->
        {ducts, %{base: below.height_agl, base_m: below.m}}

      dm >= 0 and duct_start != nil ->
        strength = duct_start.base_m - below.m
        if strength > 2 do
          duct = %{base: duct_start.base, top: below.height_agl, strength: strength}
          {[duct | ducts], nil}
        else
          {ducts, nil}
        end

      true ->
        {ducts, duct_start}
    end
  end)
  |> elem(0)
  |> Enum.reverse()
end

Inversion Detection

Temperature increasing with height. Merge adjacent inversions within 200m gap. Filter: strength >= 0.5C, base < 5000m AGL.

Stability Indices

K-Index = (T850 - T500) + Td850 - (T700 - Td700)

Lifted Index = T500 - (Tsfc - (h500 - h_sfc) * 0.00976)
  LI < 0: Unstable (convection likely, inversion destroyed)
  LI > 0: Stable (inversion maintained)

Precipitable Water = sum[(MR_i + MR_{i-1}) / 2 * dP / (9.81 * 10)]
  MR = 622 * e / (P - e)

Boundary Layer Depth

Find height where potential temperature (theta = T + 9.8 * h/1000) exceeds surface theta by 2C. The 500-1000m sweet spot indicates an elevated inversion — high enough to trap signals, not so deep that full mixing has occurred.


Part 10: Band-Specific Propagation Mechanisms

Coupling Sensitivity by Frequency

Duct coupling geometry becomes increasingly critical at higher frequencies due to narrower antenna beamwidths. A dish aimed 0.3° away from the optimal duct grazing angle:

  • 10 GHz (~3° beamwidth): Still within half-power beam — negligible loss
  • 24 GHz (~1.5° beamwidth): Approaching beam edge — moderate coupling loss
  • 47 GHz (<1° beamwidth): Outside half-power beam — potential contact killer
  • 75+ GHz (<0.5° beamwidth): Precision aim required — elevation error dominates

For surface ducts, the beam must arrive at <0.5° grazing incidence to be trapped. For elevated ducts (500-1500m AGL), the optimal elevation angle is path-distance dependent: slightly positive at close range, near-zero at the "sweet spot" distance, and slightly negative at extreme range due to Earth curvature.

10 GHz (3cm) — Tropospheric Ducting Band

Primary mechanisms: Ducting, enhanced refraction Key variable: Refractivity profile, NOT humidity absorption (0.012 dB/km total is negligible) Best conditions: Moderate-high humidity (12-20 g/m^3), temperature inversions, stable atmosphere, late evening through early morning Best months: June-July (ducting probability 69-77%). August contest data undersamples peak season. Worst month: March (10.8% ducting — worse than deep winter) Dataset: 53,013 QSOs, avg 213 km, P90 383 km, max 2,393 km. CW avg 232 km vs PH avg 187 km. Unique: Largely insensitive to rain. Can propagate through cloud decks. Marine ducting produces 1000+ km coastal paths. Frontal boundaries create strong refractive gradients. 97.2% of paths are terrain-blocked — ducting IS the propagation mechanism.

24 GHz (1.2cm) — Water Vapor Line Band

Primary mechanisms: Ducting (reduced by absorption), enhanced refraction Key variable: Absolute humidity (22.235 GHz H2O line makes this THE most humidity-sensitive band) Best conditions: Very dry air (<8 g/m^3), cold season (Nov-Mar), clear skies, pre-dawn through early morning Night enhancement: +28% avg distance, +16% P90 vs afternoon (119.7 km vs 93.8 km) Dataset: 3,639 QSOs, avg 98 km, P90 179 km, max 710 km (CW). Note: raw PH average exceeds CW at 24 GHz due to Great Lakes contest manufacturing — with cluster activity removed, CW leads by 16% (see Finding 10). Unique: 10x more sensitive to water vapor than 10 GHz. Summer Gulf moisture devastates range. Rain scatter is a viable alternative mechanism (710 km QSO documented). March is the worst ducting month (10.8%) but also has low humidity, creating a tension between ducting availability and absorption loss.

47 GHz (6mm) — Atmospheric Window

Primary mechanisms: Ducting (in atmospheric window), enhanced LOS Key variable: Balance of humidity and refractivity; very dry air dramatically helps Best conditions: Dry air (<8 g/m^3), clear skies, strong inversions, early morning Night enhancement: +36% avg distance, +42% P90 vs afternoon (86.6 km vs 63.5 km). Time-of-day is the dominant variable at this frequency. Dataset: 689 QSOs, avg 66 km, P90 122 km, max 343 km. Unique: Window between 22 GHz H2O and 60 GHz O2. O2 absorption ~0.045 dB/km is fixed. Ducting is the ONLY way beyond ~150 km.

68 GHz — V-Band Edge

Primary mechanisms: LOS only (O2 absorption limits range) Key variable: O2 wing absorption (~0.9 dB/km, weather-independent) + humidity Best conditions: Cold/dry air, no precipitation, short paths Unique: Validated by link data showing 3-5 dB diurnal fades on 2.8 km path. O2 absorption caps practical range regardless of conditions. Viable for short links (<5 km), very challenging for beyond-LOS.

75 GHz (4mm) — Window Band

Primary mechanisms: Rare ducting, enhanced LOS Key variable: Dry air + no precipitation Best conditions: Very dry (<5 g/m^3), no rain, strong inversions, winter, night/dawn Night enhancement: +360% avg distance vs afternoon (175.4 km vs 38.1 km). At this frequency, nighttime propagation is essentially a different regime. Daytime contacts are limited to ~40 km; nighttime contacts regularly exceed 150 km. Dataset: 104 QSOs, avg 64 km, P90 177 km, max 289 km. Unique: 289 km record (California marine duct). Rain attenuation severe (~1 dB/km at 4 mm/hr).

122 GHz (2.5mm) — O2 Line Wing

Primary mechanisms: Enhanced LOS, rare ducting Key variable: O2 absorption from 118.75 GHz line (~0.8 dB/km, cannot be improved by weather) Best conditions: Cold temperatures (reduce O2 line broadening), very dry, no rain Unique: 139 km record (California, February). Practically limited to ~50 km reliable paths.

134 GHz — Mini Window

Primary mechanisms: Enhanced LOS Key variable: Between O2 118 and H2O 183 lines Best conditions: Cold, dry, no precipitation Unique: 157 km record (Germany, March). Better than 122 GHz due to distance from O2 line.

241 GHz (1.2mm) — Submillimeter

Primary mechanisms: LOS only Key variable: H2O absorption dominates (~0.3 dB/km per g/m^3) Best conditions: Extremely dry (<3 g/m^3), winter-only in most US locations, high altitude stations Unique: 114 km record (Virginia, January). Total path loss at 100 km is ~410 dB without ducting. Realistic to display "viable / not viable" rather than a score.


Part 11: Data Flow & Implementation

Surface Observations (ASOS, every 5-20 min)
  -> temp, dewpoint, wind, pressure, sky, visibility, wx_codes
  -> compute: abs_humidity, Td depression
  -> per-band scoring functions
  -> composite score per band
  -> 6-hour prediction timeline

HRRR Model (hourly, per grid point)
  -> refractivity profile, dN/dh gradient, ducts, BL depth, PWAT, surface N
  -> refractivity score component (8% weight)
  -> PWAT score component (10% weight — strong independent predictor, rho=-0.04 to -0.61)
  -> 4,522 profiles in DB: 79% Enhanced, 15% Super, 5% Standard, 0.7% Ducting
  -> Key thresholds: gradient < -300 = moderate ducting, < -500 = strong ducting
  -> HPBL < 200m = strongest signal for enhanced propagation

Sounding Data (RAOB 00Z/12Z)
  -> 3,901 soundings from 112 stations
  -> Same derived params as HRRR but only twice daily
  -> 54% show ducting — binary flag useless, gradient magnitude is the signal
  -> K-index INVERSELY correlates with ducting (12.7 ducting vs 16.7 non-ducting)
  -> PWAT is NOT a ducting discriminator (identical 28.0 mm both cases)

IEMRE Gridded Data (hourly, 0.125° resolution)
  -> temp, dewpoint, sky_cover_pct, wind (u/v), precip at QSO endpoint locations
  -> More granular than nearest-ASOS matching
  -> 3,675 gridded observations in DB, enriched per-QSO

Terrain Data (SRTM + ITU-R P.526-16)
  -> path profile, Fresnel clearance, earth bulge with dynamic k-factor
  -> 97.2% of QSO paths are BLOCKED, 2.2% CLEAR, 0.6% FRESNEL_PARTIAL
  -> Blocked paths average LONGER distances (215 km) than clear paths (84 km)
  -> Determines LOS vs beyond-LOS regime
  -> P.526-16 Eq. 31 knife-edge loss, Deygout 3-edge method
  -> Dynamic k-factor from HRRR refractivity gradient (Section 2)

Commercial Link Data (SNMP polling, 5-min intervals)
  -> 7 links at 11/24/68 GHz near DFW
  -> rx_power_0, rx_power_1 (dual-chain MIMO on af11x), tx_power
  -> Signal variation scales with frequency: 68G > 24G > 11G
  -> Correlated with KTKI ASOS surface obs

Link Budget (point-to-point)
  -> FSPL + gaseous + rain + diffraction - duct enhancement
  -> margin = RX power - sensitivity
  -> success % = margin_to_success(margin, prop_score)
  -> Note: 36 dB avg diffraction > 14 dB max duct enhancement
     (gap closed by station EIRP + receiver sensitivity + troposcatter)

Display: Band Conditions Panel

For each band:

  • Current score (0-100, colored badge)
  • Estimated range (km, from score tier table, qualified by mode)
  • Key limiting factor ("High humidity: 16 g/m^3", "Strong inversion detected")
  • Trend arrow (improving/stable/degrading from last hour)
  • 6-hour prediction timeline with confidence shading

Constants Reference

ConstantValueSource
Earth radius6371 kmWGS-84 mean
Standard K-factor4/3Standard atmosphere
Standard surface N315ITU-R P.453
Standard dN/dh-40 /kmITU-R P.453
Humidity penalty 24 GHz1.6Near 22.235 GHz H2O peak
Humidity penalty 47 GHz1.0Atmospheric window
Humidity penalty 68 GHz1.460 GHz O2 wing + H2O
Humidity penalty 241 GHz3.0Between H2O 183 & 325
Duct M-unit threshold2Noise filter
Inversion min strength0.5CBelow is noise
Inversion height limit5000m AGLAbove irrelevant
BL depth shallow threshold<300mHRRR: avg gradient -93.7 at BL<200m
Ducting gradient threshold-300 N/kmSounding avg for ducting events: -389
Non-ducting gradient avg-123 N/kmSounding avg for non-ducting events
Ducting surface N threshold330Above this, ducting probability >50%
Signal prediction floor+/- 2-3 dBMeasured from link data
CW bandwidth advantage~7 dB10*log10(2700/500); 16-221% range increase depending on band
Pressure correlation (10 GHz)rho=-0.18057,248 QSO-HRRR analysis, Apr 2026
PWAT optimal range (10 GHz)20-30 mmBest median distance (219 km)
PWAT correlation (75 GHz)rho=-0.60857,248 QSO-HRRR analysis, Apr 2026

ITU-R Recommendations

The following ITU-R Recommendations provide the physics models underlying the scoring algorithm. All are publicly available from the ITU Radiocommunication Sector (https://www.itu.int/rec/R-REC-P/en).

RecommendationTitleUsed For
ITU-R P.453-14The radio refractive index: its formula and refractivity dataSurface refractivity N calculation, refractivity gradient
ITU-R P.525-4Calculation of free-space attenuationFree-space path loss baseline
ITU-R P.676-13Attenuation by atmospheric gases and related effectsO2 and H2O absorption coefficients per band
ITU-R P.838-3Specific attenuation model for rain for use in prediction methodsRain attenuation coefficients (k, alpha) per band
ITU-R P.526-16Propagation by diffractionKnife-edge loss (Eq. 31), Deygout 3-edge method (Section 6), dynamic k-factor (Section 2)
ITU-R P.452-17Prediction procedure for the evaluation of interference between stations on the surface of the EarthClear-air propagation modeling framework
ITU-R P.835-6Reference standard atmospheresStandard atmosphere profiles for baseline
ITU-R P.530-18Propagation data and prediction methods for terrestrial line-of-sight systemsMultipath fading and enhancement statistics

Data Sources

Primary QSO Dataset

ARRL Microwave Contest Results (1992-2024)

  • Source: Contest log submissions compiled from ARRL contest results
  • Volume: 58,282 total QSOs across 13+ bands (10 GHz through 403 GHz)
  • Usable subset: 57,488 tropospheric QSOs after filtering 4 EME contacts (QRA64D/JT4F modes >3,000 km)
  • Fields: station callsigns, Maidenhead grid squares, timestamp, mode (CW/SSB/FM/FT8), band
  • Grid-to-coordinate conversion: gridmap.org API for Maidenhead → lat/lon
  • Distance: Haversine great-circle calculation from grid square centers

Surface Weather Observations (ASOS)

Iowa Environmental Mesonet (IEM) — Automated Surface Observing System

  • API: https://mesonet.agron.iastate.edu/cgi-bin/request/asos.py
  • Network discovery: https://mesonet.agron.iastate.edu/api/1/network.py
  • Station count: 2,922 total, 1,299 with observations matched to QSOs
  • Observation count: 58,398 surface observations
  • Fields: temperature (°F), dewpoint (°F), relative humidity (%), wind speed (kts), wind direction (°), sea level pressure (mb), sky condition (CLR/FEW/SCT/BKN/OVC), precipitation (inches/hour), weather codes
  • Temporal matching: ±2 hours around QSO timestamp
  • Spatial matching: nearest station within 150 km of QSO path endpoints
  • No authentication required

Upper-Air Soundings (RAOB)

Iowa Environmental Mesonet (IEM) — Radiosonde Observations

  • API: https://mesonet.agron.iastate.edu/json/raob.py
  • Station count: 346 sounding stations total, 112 with data matched to QSOs
  • Sounding count: 3,901 vertical profiles
  • Standard times: 00Z and 12Z (bracketing QSO timestamps)
  • Spatial matching: nearest station within 300 km of QSO path
  • Raw profile: pressure, temperature, dewpoint, height per level
  • Derived parameters (computed at ingestion by SoundingParams.derive/1): - Surface refractivity (ITU-R P.453-14 formula) - Minimum refractivity gradient (N/km) — primary ducting indicator - Boundary layer depth (m) - Precipitable water (mm) - K-index, Lifted index — atmospheric stability - Ducting detection and duct characteristics (height, strength in M-units)

HRRR Model Data

NOAA High-Resolution Rapid Refresh (HRRR)

  • Source: AWS S3 public bucket https://noaa-hrrr-bdp-pds.s3.amazonaws.com
  • Format: GRIB2 files, hourly cadence, 3km horizontal resolution
  • Profile count: 4,522 profiles matched to QSO/grid locations
  • Pressure levels extracted: every 25 hPa from 1000–700 mb (13 levels: 1000, 975, 950, 925, 900, 875, 850, 825, 800, 775, 750, 725, 700)
  • Surface fields: temperature (°C), dewpoint (°C), pressure (mb), HPBL (boundary layer height, m), PWAT (precipitable water, mm), 10m wind components (u, v), cloud cover (%), precipitation (mm)
  • Per-level fields: temperature, dewpoint, geopotential height
  • Derived: refractivity profile, min gradient, ducting detection (same as sounding derivation)
  • Batch optimization: groups multiple grid points by HRRR hour to download GRIB2 once per time step

IEMRE Gridded Hourly Weather

Iowa Environmental Mesonet Reanalysis (IEMRE)

  • API: https://mesonet.agron.iastate.edu/iemre/hourly/{date}/{lat}/{lon}/json
  • Resolution: 0.125° (~14 km) gridded
  • Observation count: 3,675 gridded hourly observations
  • Fields per hour: air temperature (°F), dewpoint (°F), sky cover (%), wind components (u/v, m/s), hourly precipitation (inches), solar radiation
  • Used for: weather at QSO endpoint grid points, more granular than nearest-ASOS matching
  • Status: ingested but not yet integrated into scoring factors

Terrain Elevation Data

SRTM (Shuttle Radar Topography Mission)

  • Primary source: AWS S3 https://elevation-tiles-prod.s3.amazonaws.com/skadi (local tile cache)
  • Resolution: 90m (SRTM3, 3 arc-second)
  • Tile format: .hgt binary, 3601×3601 samples, 16-bit signed big-endian
  • Fallback APIs (when tiles unavailable): - Open-Meteo: https://api.open-meteo.com/v1/elevation - OpenTopography: https://api.opentopodata.org/v1/srtm90m
  • Profile method: 64 elevation samples per QSO path (great-circle interpolation)
  • Path count: 58,276 QSO paths profiled
  • Results: 56,658 BLOCKED (97.2%), 1,277 CLEAR (2.2%), 341 FRESNEL_PARTIAL (0.6%)
  • Analysis: ITU-R P.526-16 knife-edge diffraction (Eq. 31), Deygout 3-edge method for multiple obstacles, dynamic k-factor from HRRR refractivity gradient (falls back to k=4/3 when HRRR unavailable)

Commercial Link Validation Data

Ubiquiti airFiber and airFiber 60 links near Princeton, TX

  • Link count: 7 commercial microwave links
  • Frequencies: 11 GHz (AF11X, dual-chain), 24 GHz (AF11X), 68 GHz (AF60, single-chain)
  • Polling: SNMP at 5-minute intervals (rxpower0, rxpower1 for dual-chain; rx_power for single)
  • Weather correlation: KTKI ASOS station
  • Historical dataset: March 14-29, 2026 (18,540 samples)
  • Validated coefficients: 11 GHz and 24 GHz gaseous absorption, 68 GHz O2 band wing absorption (0.1 dB/km per g/m³ measured on 2.8 km path)
  • Live polling: active for ongoing validation

Solar Indices

GFZ German Research Centre for Geosciences

  • Source: https://kp.gfz.de/app/files/KpapApSNF107since1932.txt
  • Volume: 9,586 daily values (1998-2026)
  • Fields: Solar Flux Index (F10.7), adjusted SFI, sunspot number, Ap index, Kp values (3-hourly)
  • Status: ingested but NOT used in tropospheric scoring — reserved for potential VHF/sporadic-E extension

Live Scoring Data

Propagation Grid Scores

  • Coverage: CONUS grid at 0.125° resolution
  • Update cadence: hourly (HRRR-based via PropagationGridWorker) + 10-minute ASOS adjustments (AsosAdjustmentWorker)
  • Per grid point: composite score (0-100), 9 individual factor scores, valid_time
  • Bands scored: all configured bands (10, 24, 47, 68, 75, 122, 134, 142, 241 GHz)
  • Retention: 2 most recent valid_times kept, older data pruned automatically

Known Data Quality Issues

  • EME contamination: 4 QSOs >3,000 km remain in dataset (QRA64D/JT4F modes). Filter on distance_km < 3000 for tropospheric analysis.
  • Unmodeled bands: 142, 145, 288, 322, 403, 411 GHz have 1-4 QSOs each but no band_config entries. Too sparse for statistical analysis.
  • Sounding data recency: Latest soundings are from Sep 2024. Ingestion pipeline may need restart for live enrichment.
  • Surface obs density: Historical obs are sparse (~1 per 4.7 days per station) because they were fetched per-QSO-window. Live polling is now active for continuous coverage.
  • Weather codes (wxcodes): Stored in surfaceobservations but unused by scoring. Direct fog/thunderstorm/freezing-rain detection could supplement indirect inference from Td depression and sky condition.
  • Contest bias: 97% of QSOs are from August-September ARRL Microwave Contest. Seasonal and regional statistics may not generalize to year-round conditions.
  • Rain model unvalidated: ITU-R P.838-3 rain attenuation coefficients are theoretical — no rain events occurred in the commercial link validation dataset.