Show on /weather where the detected duct geometry traps each microwave band. Overview mode bins cells by their lowest trapped frequency (Bean & Dutton cutoff); band-picker mode masks cells whose duct doesn't reach the selected band. Cutoff is pre-computed per cell in both writers (Elixir derive + Rust derive_row reads best_duct_freq_ghz from CellValues), persisted to ScalarFile, and shipped to the JS hook via the existing binary cell pack. Also cleans up six pre-existing length/1 credo warnings in unrelated test files.
170 lines
5.8 KiB
Elixir
170 lines
5.8 KiB
Elixir
defmodule Microwaveprop.Weather.MapLayers do
|
||
@moduledoc false
|
||
|
||
@layers [
|
||
%{
|
||
id: "temperature",
|
||
label: "Temperature",
|
||
unit: "°C",
|
||
group: "Surface",
|
||
desc: "2m air temperature. Warm, humid air increases refractivity and ducting potential at lower frequencies."
|
||
},
|
||
%{
|
||
id: "dewpoint_depression",
|
||
label: "Td Depression",
|
||
unit: "°C",
|
||
group: "Surface",
|
||
desc:
|
||
"Temperature minus dewpoint. Small values (< 5°C) mean moist boundary layer — favorable for ducting at 10 GHz, but increases absorption above 24 GHz."
|
||
},
|
||
%{
|
||
id: "surface_rh",
|
||
label: "Humidity",
|
||
unit: "%",
|
||
group: "Surface",
|
||
desc:
|
||
"Relative humidity from surface T and Td. High RH supports refractivity gradients that bend microwave signals."
|
||
},
|
||
%{
|
||
id: "pwat",
|
||
label: "PWAT",
|
||
unit: "mm",
|
||
group: "Surface",
|
||
desc:
|
||
"Precipitable water — total moisture in the atmospheric column. High values signal rain fade risk for 24 GHz and above."
|
||
},
|
||
%{
|
||
id: "surface_refractivity",
|
||
label: "Refractivity",
|
||
unit: "N",
|
||
group: "Surface",
|
||
desc:
|
||
"Radio refractivity (N-units) at the surface. Typical values 280–380. Higher N means the atmosphere bends signals more toward the ground."
|
||
},
|
||
%{
|
||
id: "refractivity_gradient",
|
||
label: "N-Gradient",
|
||
unit: "N/km",
|
||
group: "Surface",
|
||
desc:
|
||
"Minimum refractivity gradient in the profile. Standard is −40 N/km. Below −157 N/km signals are trapped in a duct. More negative = stronger ducting."
|
||
},
|
||
%{
|
||
id: "bl_height",
|
||
label: "BL Height",
|
||
unit: "m",
|
||
group: "Surface",
|
||
desc:
|
||
"Planetary boundary layer height. Shallow BL (< 500m) concentrates moisture and heat near the surface, favoring temperature inversions and ducting."
|
||
},
|
||
%{
|
||
id: "temp_850mb",
|
||
label: "T @ 850mb",
|
||
unit: "°C",
|
||
group: "Upper Air",
|
||
desc:
|
||
"Temperature at 850 mb (~1500m altitude). Warm 850mb air over cool surface air indicates a capping inversion — a classic ducting setup."
|
||
},
|
||
%{
|
||
id: "dewpoint_850mb",
|
||
label: "Td @ 850mb",
|
||
unit: "°C",
|
||
group: "Upper Air",
|
||
desc:
|
||
"Dewpoint at 850 mb. A sharp moisture drop between the surface and 850mb creates an elevated refractivity gradient that can form ducts."
|
||
},
|
||
%{
|
||
id: "temp_700mb",
|
||
label: "T @ 700mb",
|
||
unit: "°C",
|
||
group: "Upper Air",
|
||
desc:
|
||
"Temperature at 700 mb (~3000m altitude). The classic capping diagnostic over the southern Plains: ≥10°C indicates a moderate cap, ≥12°C strong. Combined with warm 850 mb, signals a 'loaded gun' setup that suppresses convection until forcing arrives."
|
||
},
|
||
%{
|
||
id: "dewpoint_700mb",
|
||
label: "Td @ 700mb",
|
||
unit: "°C",
|
||
group: "Upper Air",
|
||
desc:
|
||
"Dewpoint at 700 mb. Wide depressions (T-Td > 10°C) signal the elevated mixed layer (EML) plume — a hallmark cap mechanism off the Mexican plateau."
|
||
},
|
||
%{
|
||
id: "lapse_rate",
|
||
label: "Lapse Rate",
|
||
unit: "°C/km",
|
||
group: "Upper Air",
|
||
desc:
|
||
"Temperature decrease per km from surface to 700mb. Low rates (< 5 °C/km) mean stable air that preserves inversions. High rates (> 8) mean convective mixing that destroys them."
|
||
},
|
||
%{
|
||
id: "mid_lapse_rate",
|
||
label: "Mid Lapse 850-700",
|
||
unit: "°C/km",
|
||
group: "Upper Air",
|
||
desc:
|
||
"Lapse rate across the 850→700 mb layer. Steep values (≥7 °C/km) above a warm moist boundary layer indicate an elevated mixed layer — the textbook cap structure that holds back convection until the inversion is broken."
|
||
},
|
||
%{
|
||
id: "inversion_strength",
|
||
label: "Inversion",
|
||
unit: "°C",
|
||
group: "Upper Air",
|
||
desc:
|
||
"Strongest temperature increase between adjacent levels. Inversions trap microwave signals. > 3°C is significant, > 5°C is strong."
|
||
},
|
||
%{
|
||
id: "inversion_base_m",
|
||
label: "Inv. Base",
|
||
unit: "m",
|
||
group: "Upper Air",
|
||
desc:
|
||
"Height (m AGL) where the strongest inversion begins. Surface-based inversions (< 200m) create surface ducts. Elevated inversions create elevated ducts."
|
||
},
|
||
%{
|
||
id: "ducting",
|
||
label: "Ducting",
|
||
unit: "",
|
||
group: "Ducting",
|
||
desc:
|
||
"Whether a trapping layer (modified refractivity decreasing with height) was detected in the profile. Green = duct present, signals can travel far beyond line of sight."
|
||
},
|
||
%{
|
||
id: "duct_base_m",
|
||
label: "Duct Base",
|
||
unit: "m",
|
||
group: "Ducting",
|
||
desc:
|
||
"Height of the lowest duct base. Surface ducts (< 100m) are most effective for ground-based stations. Elevated ducts require antennas near the duct height."
|
||
},
|
||
%{
|
||
id: "duct_strength",
|
||
label: "Duct Strength",
|
||
unit: "M",
|
||
group: "Ducting",
|
||
desc:
|
||
"Duct trapping strength in modified refractivity (M) units. > 10 M is moderate, > 20 M is strong. Stronger ducts trap a wider range of frequencies."
|
||
},
|
||
%{
|
||
id: "duct_cutoff_ghz",
|
||
label: "Duct Cutoff Band",
|
||
unit: "GHz",
|
||
group: "Ducting",
|
||
desc:
|
||
"Lowest microwave frequency the detected duct geometry can trap (Bean & Dutton waveguide cutoff). In Overview mode, cells are coloured by the highest amateur band the duct supports. Pick a band to mask cells that only support that band or lower."
|
||
}
|
||
]
|
||
|
||
@default_layer "temperature"
|
||
@valid_ids MapSet.new(Enum.map(@layers, & &1.id))
|
||
|
||
@spec all() :: [map()]
|
||
def all, do: @layers
|
||
|
||
@spec default_id() :: String.t()
|
||
def default_id, do: @default_layer
|
||
|
||
@spec valid_id?(term()) :: boolean()
|
||
def valid_id?(id) when is_binary(id), do: MapSet.member?(@valid_ids, id)
|
||
def valid_id?(_id), do: false
|
||
end
|