From 58a99de3cd6c4a8d780513bf306ed4e79555bb92 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sat, 11 Apr 2026 13:49:22 -0500 Subject: [PATCH] Fix map detail panel: update weights, add PWAT, show duct info - Update all 9 hardcoded weights to match recalibrated values - Add missing PWAT factor (11.3% weight) to FACTOR_META and FACTOR_ORDER - Reorder factors by weight (highest first) - Fix pressure explanation (low pressure is better, not rising) - Add PWAT factor explanation (beneficial vs harmful by band) - Show duct info panel when native data detects ducting layers (count, thickness, minimum trapped frequency) --- assets/js/propagation_map_hook.js | 56 +++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/assets/js/propagation_map_hook.js b/assets/js/propagation_map_hook.js index 88ac0c00..82d45e5a 100644 --- a/assets/js/propagation_map_hook.js +++ b/assets/js/propagation_map_hook.js @@ -1,21 +1,24 @@ import topbar from "../vendor/topbar" import { updateGridOverlay } from "./maidenhead_grid" +// Weights must match BandConfig.weights() in band_config.ex +// Recalibrated 2026-04-11 via gradient descent (loss 0.42 → 0.12) const FACTOR_META = { - humidity: { label: "Humidity", weight: 0.20, unit: "g/m\u00b3" }, - time_of_day: { label: "Time of Day", weight: 0.20, unit: "" }, - td_depression: { label: "Td Depression", weight: 0.12, unit: "\u00b0F" }, - refractivity: { label: "Refractivity", weight: 0.10, unit: "N/km" }, - sky: { label: "Sky Cover", weight: 0.10, unit: "%" }, - season: { label: "Season", weight: 0.10, unit: "" }, - rain: { label: "Rain", weight: 0.08, unit: "" }, - wind: { label: "Wind", weight: 0.06, unit: "kts" }, - pressure: { label: "Pressure", weight: 0.04, unit: "mb" } + rain: { label: "Rain", weight: 0.1362, unit: "" }, + humidity: { label: "Humidity", weight: 0.1243, unit: "g/m\u00b3" }, + pwat: { label: "PWAT", weight: 0.1128, unit: "mm" }, + season: { label: "Season", weight: 0.1112, unit: "" }, + refractivity: { label: "Refractivity", weight: 0.1049, unit: "N/km" }, + pressure: { label: "Pressure", weight: 0.1032, unit: "mb" }, + td_depression: { label: "Td Depression", weight: 0.0978, unit: "\u00b0F" }, + sky: { label: "Sky Cover", weight: 0.08, unit: "%" }, + wind: { label: "Wind", weight: 0.08, unit: "kts" }, + time_of_day: { label: "Time of Day", weight: 0.0496, unit: "" } } const FACTOR_ORDER = [ - "humidity", "time_of_day", "td_depression", "refractivity", - "sky", "season", "rain", "wind", "pressure" + "rain", "humidity", "pwat", "season", "refractivity", + "pressure", "td_depression", "sky", "wind", "time_of_day" ] function scoreTier(score) { @@ -90,10 +93,20 @@ function factorExplanation(key, score, detail) { if (score >= 90) return "No rain — no path attenuation" if (score >= 50) return "Light rain — minor attenuation" return "Heavy rain — significant path loss" + case "pwat": + if (beneficial) { + if (score >= 80) return "High column moisture — strong refractivity" + if (score >= 50) return "Moderate PWAT — some refractivity enhancement" + return "Low PWAT — limited moisture for ducting" + } else { + if (score >= 80) return "Low column moisture — minimal absorption" + if (score >= 50) return "Moderate PWAT" + return "High PWAT — significant absorption at this frequency" + } case "pressure": - if (score >= 70) return "Rising pressure — increasing stability favors inversions" - if (score >= 55) return "Steady pressure — stable conditions" - return "Falling pressure — instability weakens inversions" + if (score >= 70) return "Low pressure — frontal boundaries favor ducting" + if (score >= 45) return "Normal pressure — average conditions" + return "High pressure — stable ridge, inversions cap at wrong altitude" default: return "" } @@ -344,11 +357,26 @@ function buildPopupHTML(detail, viewshedLoading) {
Analysis
${explanations} + ${detail.factors.duct_info ? buildDuctInfoHTML(detail.factors.duct_info) : ""} ${detail.forecast ? buildForecastSvg(detail.forecast) : ""} ${viewshedStatus} ` } +function buildDuctInfoHTML(duct) { + const freq = duct.best_duct_freq_ghz != null ? `${duct.best_duct_freq_ghz.toFixed(1)} GHz` : "—" + const thick = duct.max_duct_thickness_m != null ? `${Math.round(duct.max_duct_thickness_m)} m` : "—" + return ` +
+
Ducting
+
+ ${duct.duct_count} layer${duct.duct_count !== 1 ? "s" : ""} + Thickness: ${thick} + Traps \u2265 ${freq} +
+
` +} + // --- Hook --- export const PropagationMap = {