Recalibrate refractivity thresholds for HRRR gradient distribution
Previous thresholds (-500 to -60) were calibrated for radiosonde data. HRRR profiles have coarser vertical resolution, with gradients clustering between -40 and -130 N/km (median -70). Nearly all grid points were falling through to the default score of 42, wasting the refractivity factor. New thresholds (-200 to -40) spread across HRRR percentiles.
This commit is contained in:
parent
49cbe6789c
commit
c9112b9280
4 changed files with 31 additions and 54 deletions
51
algo.md
51
algo.md
|
|
@ -685,48 +685,21 @@ 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. Surface-based ducts (base=0) matter more than elevated ducts.
|
||||
Best predictor when available. Binary duct detection is useless (54% baseline rate). Use continuous gradient magnitude and BL depth instead.
|
||||
|
||||
From sounding data: avg gradient -389 N/km for ducting events vs -123 for non-ducting. From HRRR: BL depth < 200m correlates with avg gradient of -93.7 (approaching super-refraction).
|
||||
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.
|
||||
|
||||
```elixir
|
||||
def score_refractivity(sounding_or_hrrr, band_config) do
|
||||
cond do
|
||||
sounding_or_hrrr == nil -> 50 # No data — neutral
|
||||
| Gradient (N/km) | Beneficial Score | Harmful Score | Condition |
|
||||
|---|---|---|---|
|
||||
| < -200 | 98 | 85 | Strong ducting (HRRR p1) |
|
||||
| < -150 | 92 | 80 | Enhanced refraction (HRRR p5) |
|
||||
| < -100 | 82 | 72 | Above-average refraction (HRRR p25) |
|
||||
| < -75 | 68 | 62 | Near-median gradient (HRRR p50) |
|
||||
| < -55 | 55 | 55 | Below-median (HRRR p75) |
|
||||
| < -40 | 48 | 48 | Weak gradient (HRRR p95) |
|
||||
| ≥ -40 | 42 | 42 | Standard/sub-refractive |
|
||||
|
||||
sounding_or_hrrr.min_dn_dh < -500 ->
|
||||
# Strong ducting — gradient 3x non-ducting average
|
||||
case band_config.humidity_effect do
|
||||
:beneficial -> 98 # 10 GHz benefits most from ducting
|
||||
:harmful -> 85 # Higher bands benefit but absorption limits range
|
||||
end
|
||||
|
||||
sounding_or_hrrr.min_dn_dh < -300 ->
|
||||
# Moderate ducting — near ducting average of -389
|
||||
case band_config.humidity_effect do
|
||||
:beneficial -> 92
|
||||
:harmful -> 78
|
||||
end
|
||||
|
||||
sounding_or_hrrr.min_dn_dh < -200 ->
|
||||
80 # Enhanced refraction — above non-ducting average of -123
|
||||
|
||||
# BL depth signal: shallow BL at 12Z = strong surface duct potential
|
||||
sounding_or_hrrr.bl_depth_m != nil and
|
||||
sounding_or_hrrr.bl_depth_m < 300 ->
|
||||
82 # Very shallow BL — strong inversion cap (12Z signature)
|
||||
|
||||
sounding_or_hrrr.min_dn_dh < -100 ->
|
||||
65 # Mild enhancement
|
||||
|
||||
sounding_or_hrrr.min_dn_dh < -60 ->
|
||||
55 # Slightly enhanced — within the broad "Enhanced" HRRR regime
|
||||
|
||||
true ->
|
||||
42 # Standard/sub-refractive — HRRR shows only 5% of profiles here
|
||||
end
|
||||
end
|
||||
```
|
||||
Shallow BL fallback: when gradient is unavailable but BL depth < 300m, score 82 (strong inversion cap).
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -32,12 +32,15 @@ defmodule Microwaveprop.Propagation.BandConfig do
|
|||
@humidity_beneficial_thresholds [{4, 55}, {7, 70}, {10, 82}, {14, 90}, {18, 95}, {22, 88}]
|
||||
@humidity_beneficial_default 75
|
||||
|
||||
# Thresholds calibrated for HRRR-derived gradients (coarser than sounding data).
|
||||
# HRRR percentiles: p1=-230, p5=-162, p10=-130, p25=-94, p50=-70, p75=-53, p95=-40
|
||||
@refractivity_thresholds [
|
||||
{-500, 98, 85},
|
||||
{-300, 92, 78},
|
||||
{-200, 80, 80},
|
||||
{-100, 65, 65},
|
||||
{-60, 55, 55}
|
||||
{-200, 98, 85},
|
||||
{-150, 92, 80},
|
||||
{-100, 82, 72},
|
||||
{-75, 68, 62},
|
||||
{-55, 55, 55},
|
||||
{-40, 48, 48}
|
||||
]
|
||||
@refractivity_default {42, 42}
|
||||
@shallow_bl_threshold_m 300
|
||||
|
|
|
|||
|
|
@ -252,11 +252,12 @@ defmodule Microwaveprop.Propagation.BandConfigTest do
|
|||
thresholds = BandConfig.refractivity_thresholds()
|
||||
|
||||
assert thresholds == [
|
||||
{-500, 98, 85},
|
||||
{-300, 92, 78},
|
||||
{-200, 80, 80},
|
||||
{-100, 65, 65},
|
||||
{-60, 55, 55}
|
||||
{-200, 98, 85},
|
||||
{-150, 92, 80},
|
||||
{-100, 82, 72},
|
||||
{-75, 68, 62},
|
||||
{-55, 55, 55},
|
||||
{-40, 48, 48}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -227,14 +227,14 @@ defmodule Microwaveprop.Propagation.ScorerTest do
|
|||
assert Scorer.score_refractivity(-600, 500, @band_10g) == 98
|
||||
end
|
||||
|
||||
test "strong ducting gradient returns 85 for harmful" do
|
||||
# gradient < -500 -> 85 for harmful
|
||||
assert Scorer.score_refractivity(-600, 500, @band_24g) == 85
|
||||
test "strong gradient returns 85 for harmful" do
|
||||
# gradient < -200 -> 85 for harmful (HRRR-calibrated)
|
||||
assert Scorer.score_refractivity(-250, 500, @band_24g) == 85
|
||||
end
|
||||
|
||||
test "moderate gradient returns appropriate score" do
|
||||
# gradient < -300 but >= -500 -> 92 for beneficial
|
||||
assert Scorer.score_refractivity(-400, 500, @band_10g) == 92
|
||||
# gradient < -150 but >= -200 -> 92 for beneficial (HRRR-calibrated)
|
||||
assert Scorer.score_refractivity(-160, 500, @band_10g) == 92
|
||||
end
|
||||
|
||||
test "nil gradient returns 50" do
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue