work on model training
This commit is contained in:
@@ -501,6 +501,40 @@ function buildRainProbabilitySeries(points) {
|
||||
return out;
|
||||
}
|
||||
|
||||
function buildRainProbabilitySeriesFromPredictions(points) {
|
||||
return points.map((p) => {
|
||||
const t = new Date(p.ts).getTime();
|
||||
if (Number.isNaN(t)) {
|
||||
return { x: null, y: null };
|
||||
}
|
||||
if (p.probability === null || p.probability === undefined) {
|
||||
return { x: t, y: null };
|
||||
}
|
||||
return {
|
||||
x: t,
|
||||
y: Math.round(Number(p.probability) * 1000) / 10,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function thresholdSeries(range, threshold) {
|
||||
if (!range || !range.axisStart || !range.axisEnd || threshold === null || threshold === undefined) {
|
||||
return [];
|
||||
}
|
||||
const y = Math.round(Number(threshold) * 1000) / 10;
|
||||
return [
|
||||
{ x: range.axisStart.getTime(), y },
|
||||
{ x: range.axisEnd.getTime(), y },
|
||||
];
|
||||
}
|
||||
|
||||
function predictionAgeMinutes(prediction) {
|
||||
if (!prediction || !prediction.ts) return null;
|
||||
const ts = new Date(prediction.ts).getTime();
|
||||
if (Number.isNaN(ts)) return null;
|
||||
return (Date.now() - ts) / (60 * 1000);
|
||||
}
|
||||
|
||||
function updateWeatherIcons(latest, rainProb) {
|
||||
const sunEl = document.getElementById("live-icon-sun");
|
||||
const cloudEl = document.getElementById("live-icon-cloud");
|
||||
@@ -693,10 +727,26 @@ function renderDashboard(data) {
|
||||
const obsFiltered = filterRange(obs, rangeStart, rangeEnd);
|
||||
const forecast = filterRange(forecastAll, rangeStart, rangeEnd);
|
||||
const forecastLine = extendForecastTo(forecast, rangeEnd);
|
||||
const rainPredictions = filterRange(data.rain_predictions || [], rangeStart, rangeEnd);
|
||||
const latestRainPrediction = data.latest_rain_prediction || null;
|
||||
const latestPredictionAgeMin = predictionAgeMinutes(latestRainPrediction);
|
||||
const modelPredictionFresh = latestPredictionAgeMin !== null && latestPredictionAgeMin <= 90;
|
||||
const lastPressureTrend = lastNonNull(obsFiltered, "pressure_trend_1h");
|
||||
const rainProb = computeRainProbability(latest);
|
||||
const modelRainProb = modelPredictionFresh && latestRainPrediction && latestRainPrediction.probability !== null && latestRainPrediction.probability !== undefined
|
||||
? {
|
||||
prob: Number(latestRainPrediction.probability),
|
||||
label: classifyRainProbability(Number(latestRainPrediction.probability)),
|
||||
source: "model",
|
||||
}
|
||||
: null;
|
||||
const heuristicRainProb = computeRainProbability(latest);
|
||||
const rainProb = modelRainProb || heuristicRainProb;
|
||||
if (rainProb) {
|
||||
updateText("live-rain-prob", `${Math.round(rainProb.prob * 100)}% (${rainProb.label})`);
|
||||
const sourceLabel = rainProb.source === "model" ? "model" : "heuristic";
|
||||
updateText("live-rain-prob", `${Math.round(rainProb.prob * 100)}% (${rainProb.label}, ${sourceLabel})`);
|
||||
} else if (latestRainPrediction && latestRainPrediction.probability !== null && latestRainPrediction.probability !== undefined) {
|
||||
const stalePct = Math.round(Number(latestRainPrediction.probability) * 100);
|
||||
updateText("live-rain-prob", `${stalePct}% (stale model)`);
|
||||
} else {
|
||||
updateText("live-rain-prob", "--");
|
||||
}
|
||||
@@ -901,13 +951,20 @@ function renderDashboard(data) {
|
||||
data: {
|
||||
datasets: [
|
||||
{
|
||||
label: "predicted rain probability (%)",
|
||||
data: buildRainProbabilitySeries(obsFiltered),
|
||||
label: rainPredictions.length ? "model rain probability (%)" : "heuristic rain probability (%)",
|
||||
data: rainPredictions.length ? buildRainProbabilitySeriesFromPredictions(rainPredictions) : buildRainProbabilitySeries(obsFiltered),
|
||||
borderColor: colors.rain,
|
||||
backgroundColor: "rgba(78, 168, 222, 0.18)",
|
||||
fill: true,
|
||||
yAxisID: "y",
|
||||
},
|
||||
{
|
||||
label: "decision threshold (%)",
|
||||
data: thresholdSeries(range, latestRainPrediction ? latestRainPrediction.threshold : null),
|
||||
borderColor: "#f4b942",
|
||||
borderDash: [6, 4],
|
||||
yAxisID: "y",
|
||||
},
|
||||
],
|
||||
},
|
||||
options: rainProbOptions,
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
</div>
|
||||
<div class="chart-card" data-chart="chart-rain-prob">
|
||||
<div class="chart-header">
|
||||
<div class="chart-title">Predicted Rain Probability (Observed Inputs)</div>
|
||||
<div class="chart-title">Predicted Rain Probability (Model)</div>
|
||||
<button class="chart-link" data-chart="chart-rain-prob" title="Copy chart link">Share</button>
|
||||
</div>
|
||||
<div class="chart-canvas">
|
||||
|
||||
Reference in New Issue
Block a user