# Recalibration Analysis Report — 2026-04-18 > Auto-generated by `scripts/recalibrate_algo.py`. This report is the > input for `algo.md` updates — diff against the prior dated section to > see what's actually moved. Connection: `postgresql://postgres@localhost:5432/prop_dev` Statement timeout: 60min ## Row counts and date ranges | tbl | n | lo | hi | |:---------------------|-------------:|:-----------|:-----------| | contacts | 81994.000 | 1991-05-04 | 2026-03-07 | | hrrr_native_profiles | 11472.000 | 2019-03-09 | 2025-09-21 | | hrrr_profiles | 18591740.000 | 2018-08-04 | 2026-04-05 | | iemre_observations | 28438.000 | | | | narr_profiles | 354.000 | 1991-05-04 | 2014-09-19 | | nexrad_observations | 7286.000 | 2019-08-17 | 2024-09-22 | | propagation_scores | nan | | | | rtma_observations | 0.000 | | | | soundings | 26933.000 | 1990-06-07 | 2026-04-18 | | surface_observations | 599046.000 | 1991-05-03 | 2026-04-18 | | terrain_profiles | 81994.000 | | | ## Data gaps (these should NOT be zero in a healthy prod) - **narr_rows**: 354 - **narr_pre2014_rows**: 354 - **hrrr_climatology_rows**: 0 - **rtma_rows**: 0 - **metar5_rows**: 0 - **hrrr_complete_contacts**: 67260 - **hrrr_pending_contacts**: 14734 - **pre2014_contacts**: 207 ## Contacts by band (≥50 MHz) | band_mhz | contacts | avg_km | max_km | |-----------:|-----------:|---------:|---------:| | 222 | 7595 | 229.000 | 2306.000 | | 432 | 9177 | 200.000 | 1752.000 | | 902 | 1794 | 171.000 | 915.000 | | 1296 | 2996 | 160.000 | 1752.000 | | 2304 | 749 | 153.000 | 655.000 | | 3400 | 351 | 151.000 | 643.000 | | 5760 | 328 | 125.000 | 505.000 | | 10000 | 54264 | 212.000 | 2393.000 | | 24000 | 3806 | 95.000 | 710.000 | | 47000 | 762 | 65.000 | 343.000 | | 75000 | 106 | 60.000 | 289.000 | | 122000 | 35 | 27.000 | 139.000 | | 134000 | 5 | 65.000 | 157.000 | | 142000 | 4 | 47.000 | 79.700 | | 145000 | 2 | 40.000 | 79.600 | | 241000 | 14 | 31.000 | 114.400 | | 288000 | 1 | 1.000 | 1.246 | | 322000 | 1 | 1.000 | 1.400 | | 403000 | 1 | 1.000 | 1.400 | | 411000 | 1 | 0.000 | 0.050 | ## Monthly sounding ducting | month | soundings | ducting_pct | avg_min_grad | avg_pwat | |--------:|------------:|--------------:|---------------:|-----------:| | 1 | 95 | 28.400 | -171.400 | 10.900 | | 2 | 131 | 29.000 | -163.100 | 7.900 | | 3 | 81 | 17.300 | -148.100 | 9.400 | | 4 | 134 | 31.300 | -175.600 | 13.500 | | 5 | 311 | 51.800 | -286.400 | 25.600 | | 6 | 380 | 69.500 | -355.900 | 32.000 | | 7 | 302 | 67.500 | -293.800 | 29.700 | | 8 | 5007 | 55.200 | -255.400 | 35.200 | | 9 | 2335 | 56.200 | -279.800 | 27.200 | | 10 | 155 | 57.400 | -307.100 | 19.300 | | 11 | 158 | 50.000 | -256.700 | 12.000 | | 12 | 140 | 25.700 | -185.200 | 10.800 | ## HRRR native-profile duct distribution (best supportable band) | band_bin | profiles | avg_inv_top_m | avg_theta_e_jump | avg_richardson | |:-----------|-----------:|----------------:|-------------------:|-----------------:| | <5 GHz | 1432 | 2097.000 | 5.400 | 18.420 | | 15-30 GHz | 10 | 2091.000 | 5.900 | 8.690 | | 30-75 GHz | 4 | 3860.000 | 5.000 | 12.120 | | 5-15 GHz | 98 | 4408.000 | 25.700 | 12.550 | | none | 9928 | 11497.000 | 80.500 | 38.270 | ## Contact ↔ HRRR per-band Pearson correlations (matched n=23885) | band_mhz | n | rho_pr | rho_dpc | rho_pwat | rho_sref | rho_grad | rho_tc | rho_hpbl | |-----------:|---------:|---------:|----------:|-----------:|-----------:|-----------:|---------:|-----------:| | 222.000 | 5392.000 | -0.038 | 0.063 | 0.077 | 0.077 | 0.057 | -0.086 | -0.033 | | 432.000 | 6583.000 | 0.058 | 0.137 | 0.124 | 0.136 | 0.041 | -0.089 | -0.066 | | 902.000 | 1317.000 | 0.044 | 0.096 | 0.049 | 0.079 | -0.014 | -0.060 | -0.010 | | 1296.000 | 2146.000 | 0.013 | 0.085 | 0.049 | 0.085 | -0.031 | -0.032 | -0.041 | | 2304.000 | 564.000 | -0.006 | 0.130 | 0.086 | 0.154 | -0.110 | -0.114 | -0.074 | | 3400.000 | 280.000 | -0.025 | 0.150 | 0.131 | 0.176 | 0.046 | -0.103 | -0.023 | | 5760.000 | 246.000 | 0.040 | 0.087 | 0.137 | 0.105 | 0.021 | -0.082 | -0.083 | | 10000.000 | 6675.000 | -0.066 | -0.028 | 0.017 | 0.031 | -0.024 | 0.043 | -0.025 | | 24000.000 | 613.000 | -0.178 | -0.208 | -0.172 | -0.103 | -0.251 | -0.007 | -0.201 | | 47000.000 | 53.000 | -0.423 | -0.518 | -0.149 | 0.510 | -0.154 | 0.222 | -0.465 | ## Per-band HPBL bin distance distribution One table per band with ≥50 matched contacts. A band-specific effect here means HPBL belongs in the scorer for that band. **222 MHz:** | bin | n | avg_km | p50_km | |:----------|-----:|---------:|---------:| | <200 | 956 | 273.500 | 210.000 | | 200-500 | 1131 | 215.500 | 164.000 | | 500-1000 | 1185 | 205.400 | 152.000 | | 1000-1500 | 948 | 220.600 | 156.000 | | 1500-2000 | 913 | 223.000 | 171.000 | | >=2000 | 259 | 246.900 | 192.000 | **432 MHz:** | bin | n | avg_km | p50_km | |:----------|-----:|---------:|---------:| | <200 | 1258 | 223.000 | 179.000 | | 200-500 | 1370 | 198.600 | 143.500 | | 500-1000 | 1413 | 183.700 | 131.000 | | 1000-1500 | 1124 | 198.000 | 145.000 | | 1500-2000 | 1129 | 187.100 | 142.000 | | >=2000 | 289 | 169.200 | 126.000 | **902 MHz:** | bin | n | avg_km | p50_km | |:----------|----:|---------:|---------:| | <200 | 215 | 205.300 | 165.000 | | 200-500 | 275 | 152.500 | 133.000 | | 500-1000 | 302 | 166.500 | 123.000 | | 1000-1500 | 259 | 175.300 | 137.000 | | 1500-2000 | 222 | 175.900 | 152.000 | | >=2000 | 44 | 158.700 | 131.000 | **1.296 GHz:** | bin | n | avg_km | p50_km | |:----------|----:|---------:|---------:| | <200 | 355 | 179.600 | 151.000 | | 200-500 | 484 | 159.300 | 129.500 | | 500-1000 | 479 | 145.600 | 107.000 | | 1000-1500 | 376 | 154.800 | 131.000 | | 1500-2000 | 380 | 153.600 | 122.000 | | >=2000 | 72 | 143.700 | 108.000 | **2.304 GHz:** | bin | n | avg_km | p50_km | |:----------|----:|---------:|---------:| | <200 | 72 | 188.000 | 160.000 | | 200-500 | 103 | 174.800 | 156.000 | | 500-1000 | 155 | 150.300 | 122.000 | | 1000-1500 | 121 | 151.600 | 136.000 | | 1500-2000 | 97 | 161.000 | 147.000 | | >=2000 | 16 | 144.800 | 140.500 | **3.4 GHz:** | bin | n | avg_km | p50_km | |:----------|----:|---------:|---------:| | <200 | 39 | 157.400 | 131.000 | | 200-500 | 57 | 162.500 | 140.000 | | 500-1000 | 64 | 153.500 | 111.000 | | 1000-1500 | 67 | 150.500 | 136.000 | | 1500-2000 | 39 | 150.300 | 122.000 | | >=2000 | 14 | 157.400 | 140.500 | **5.76 GHz:** | bin | n | avg_km | p50_km | |:----------|----:|---------:|---------:| | <200 | 24 | 174.500 | 138.500 | | 200-500 | 49 | 134.600 | 135.000 | | 500-1000 | 62 | 118.000 | 103.000 | | 1000-1500 | 54 | 125.000 | 133.000 | | 1500-2000 | 45 | 114.600 | 122.000 | | >=2000 | 12 | 142.700 | 140.500 | **10 GHz:** | bin | n | avg_km | p50_km | |:----------|-----:|---------:|---------:| | <200 | 1573 | 213.900 | 178.800 | | 200-500 | 2146 | 201.300 | 175.000 | | 500-1000 | 1663 | 211.800 | 158.100 | | 1000-1500 | 742 | 214.500 | 212.500 | | 1500-2000 | 410 | 179.400 | 173.000 | | >=2000 | 138 | 201.000 | 173.000 | **24 GHz:** | bin | n | avg_km | p50_km | |:----------|----:|---------:|---------:| | <200 | 115 | 120.600 | 110.000 | | 200-500 | 236 | 95.400 | 99.000 | | 500-1000 | 189 | 79.700 | 80.800 | | 1000-1500 | 44 | 103.800 | 99.000 | | 1500-2000 | 10 | 46.800 | 34.000 | | >=2000 | 19 | 69.200 | 23.200 | **47 GHz:** | bin | n | avg_km | p50_km | |:----------|----:|---------:|---------:| | <200 | 9 | 111.200 | 85.300 | | 200-500 | 19 | 82.200 | 58.500 | | 500-1000 | 16 | 55.600 | 27.600 | | 1000-1500 | 5 | 16.100 | 11.400 | | >=2000 | 4 | 31.800 | 31.800 | ## Per-band pressure bin distance distribution Surface pressure tends to proxy synoptic-scale stagnation, so we want to see longer distances under the 1015-1025 mb ridge at every band that ducts. **222 MHz:** | bin | n | avg_km | p50_km | |:----------|-----:|---------:|---------:| | <990 | 1967 | 228.800 | 177.000 | | 990-1000 | 1289 | 248.500 | 191.000 | | 1000-1010 | 1263 | 235.400 | 186.000 | | 1010-1020 | 778 | 183.300 | 141.000 | | >=1020 | 95 | 159.300 | 126.000 | **432 MHz:** | bin | n | avg_km | p50_km | |:----------|-----:|---------:|---------:| | <990 | 2548 | 189.600 | 140.000 | | 990-1000 | 1580 | 223.200 | 173.000 | | 1000-1010 | 1285 | 202.700 | 149.000 | | 1010-1020 | 1050 | 172.700 | 129.000 | | >=1020 | 120 | 144.800 | 84.500 | **902 MHz:** | bin | n | avg_km | p50_km | |:----------|----:|---------:|---------:| | <990 | 422 | 157.600 | 131.500 | | 990-1000 | 400 | 206.400 | 157.000 | | 1000-1010 | 241 | 189.200 | 147.000 | | 1010-1020 | 223 | 138.800 | 143.000 | | >=1020 | 31 | 72.000 | 32.000 | **1.296 GHz:** | bin | n | avg_km | p50_km | |:----------|----:|---------:|---------:| | <990 | 696 | 149.600 | 122.000 | | 990-1000 | 579 | 183.700 | 145.000 | | 1000-1010 | 451 | 161.600 | 108.000 | | 1010-1020 | 385 | 130.500 | 114.000 | | >=1020 | 35 | 112.700 | 112.000 | **2.304 GHz:** | bin | n | avg_km | p50_km | |:----------|----:|---------:|---------:| | <990 | 138 | 155.100 | 136.000 | | 990-1000 | 201 | 168.200 | 141.000 | | 1000-1010 | 97 | 178.500 | 117.000 | | 1010-1020 | 116 | 147.200 | 152.000 | | >=1020 | 12 | 126.300 | 137.000 | **3.4 GHz:** | bin | n | avg_km | p50_km | |:----------|----:|---------:|---------:| | <990 | 75 | 157.400 | 138.000 | | 990-1000 | 134 | 156.800 | 135.000 | | 1000-1010 | 34 | 179.700 | 131.000 | | 1010-1020 | 28 | 122.200 | 124.000 | | >=1020 | 9 | 114.600 | 131.000 | **5.76 GHz:** | bin | n | avg_km | p50_km | |:----------|----:|---------:|---------:| | <990 | 55 | 112.700 | 111.000 | | 990-1000 | 120 | 131.600 | 119.500 | | 1000-1010 | 27 | 128.000 | 100.000 | | 1010-1020 | 36 | 146.900 | 152.000 | | >=1020 | 8 | 123.000 | 135.000 | **10 GHz:** | bin | n | avg_km | p50_km | |:----------|-----:|---------:|---------:| | <990 | 3515 | 222.700 | 196.600 | | 990-1000 | 1620 | 189.700 | 152.700 | | 1000-1010 | 803 | 194.200 | 153.000 | | 1010-1020 | 651 | 182.900 | 133.900 | | >=1020 | 86 | 187.700 | 158.100 | **24 GHz:** | bin | n | avg_km | p50_km | |:----------|----:|---------:|---------:| | <990 | 282 | 97.300 | 98.700 | | 990-1000 | 200 | 97.900 | 99.000 | | 1000-1010 | 57 | 95.200 | 102.300 | | 1010-1020 | 70 | 70.600 | 80.800 | | >=1020 | 4 | 103.600 | 103.600 | **47 GHz:** | bin | n | avg_km | p50_km | |:----------|----:|---------:|---------:| | <990 | 19 | 80.500 | 43.900 | | 990-1000 | 25 | 62.600 | 31.800 | | 1000-1010 | 2 | 84.600 | 84.600 | | 1010-1020 | 7 | 56.400 | 58.500 | ## Contact ↔ NARR per-band Pearson correlations (pre-2014 only, matched n=201) Historical sanity check: if the HRRR-era signs and magnitudes survive on 30+ years of NARR reanalysis, the scoring factors are physical rather than HRRR-artefact. Diverging signs = flag it. | band_mhz | n | rho_pr | rho_dpc | rho_pwat | rho_sref | rho_grad | rho_tc | rho_hpbl | |-----------:|--------:|---------:|----------:|-----------:|-----------:|-----------:|---------:|-----------:| | 10000.000 | 103.000 | -0.402 | -0.402 | -0.402 | -0.220 | -0.248 | -0.402 | -0.402 | ## NEXRAD composite reflectivity vs distance (matched n=20900) Rain-attenuation sanity check — one table per band with ≥50 matched contacts. At rain-sensitive bands (24+ GHz) higher `max_dbz` should map to shorter contacts; at 10 GHz and below the effect should be barely detectable. **10 GHz:** | bin | n | avg_km | p50_km | |:-----------------|------:|---------:|---------:| | none (<5) | 14110 | 210.000 | 197.000 | | drizzle (5-20) | 1284 | 200.900 | 199.300 | | light (20-30) | 1736 | 211.800 | 197.100 | | moderate (30-45) | 1609 | 230.900 | 215.200 | | heavy (>=45) | 677 | 191.900 | 146.900 | **24 GHz:** | bin | n | avg_km | p50_km | |:-----------------|----:|---------:|---------:| | none (<5) | 869 | 90.900 | 83.700 | | drizzle (5-20) | 74 | 108.300 | 123.200 | | light (20-30) | 151 | 88.200 | 70.900 | | moderate (30-45) | 76 | 109.300 | 122.400 | | heavy (>=45) | 49 | 86.600 | 102.300 | **47 GHz:** | bin | n | avg_km | p50_km | |:-----------------|----:|---------:|---------:| | none (<5) | 186 | 52.400 | 56.000 | | light (20-30) | 30 | 59.300 | 66.300 | | moderate (30-45) | 9 | 75.100 | 81.600 | | heavy (>=45) | 15 | 71.400 | 82.800 | ## hrrr_native_profiles.best_duct_band_ghz vs distance (matched n=57669) Validates the 1.15× boost in `Scorer.score_refractivity/4`: contacts where the native duct supports the target band should run longer than those where it does not. One table per band with ≥50 matched contacts. **10 GHz:** | bin | n | avg_km | p50_km | |:----------|------:|---------:|---------:| | none | 45395 | 212.700 | 195.000 | | <5 GHz | 7151 | 200.500 | 171.800 | | 5-10 GHz | 444 | 200.600 | 174.200 | | 10-24 GHz | 146 | 203.300 | 225.200 | | 24-47 GHz | 5 | 177.200 | 133.300 | | >=47 GHz | 23 | 147.500 | 131.500 | **24 GHz:** | bin | n | avg_km | p50_km | |:----------|---------:|---------:|---------:| | none | 3188.000 | 95.000 | 92.600 | | <5 GHz | 477.000 | 94.900 | 83.900 | | 5-10 GHz | 36.000 | 97.500 | 113.700 | | 10-24 GHz | 2.000 | 44.700 | 44.700 | | >=47 GHz | 6.000 | 131.500 | 131.500 | **47 GHz:** | bin | n | avg_km | p50_km | |:---------|--------:|---------:|---------:| | none | 552.000 | 64.300 | 65.400 | | <5 GHz | 131.000 | 56.800 | 61.800 | | 5-10 GHz | 6.000 | 98.100 | 113.700 | **75 GHz:** | bin | n | avg_km | p50_km | |:-------|-------:|---------:|---------:| | none | 76.000 | 54.800 | 36.700 | | <5 GHz | 15.000 | 13.900 | 14.600 | ## Commercial-link rx_power degradation vs contemporaneous DFW contacts (matched n=0) _No DFW-zone contacts fall inside the commercial_samples date window yet. Expected to stay empty until the Aug/Sep contest season produces contacts that overlap with live SNMP polling._