Skip to content

Commit c98a402

Browse files
committed
Improve weather ensemble
Signed-off-by: Kyle Corry <[email protected]>
1 parent 8b62e04 commit c98a402

File tree

2 files changed

+21
-13
lines changed

2 files changed

+21
-13
lines changed

app/src/main/java/com/kylecorry/trail_sense/tools/weather/infrastructure/subsystem/WeatherSubsystem.kt

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -334,33 +334,41 @@ class WeatherSubsystem private constructor(private val context: Context) : IWeat
334334
}
335335

336336
// TODO: Extract this to Sol (new forecaster)
337-
suspend fun getPressureForecast(): List<Reading<Pressure>> = onIO {
338-
val forecastLengthHours = 12f
337+
suspend fun getPressureForecast(): List<Reading<Pressure>> = onDefault {
338+
val forecastLengthHours = 6f
339339
val observations = getHistory()
340-
val start = observations.firstOrNull()?.time?.toEpochMilli() ?: return@onIO emptyList()
340+
val start = observations.firstOrNull()?.time?.toEpochMilli() ?: return@onDefault emptyList()
341341
val pressures = observations.map {
342342
val hours = (it.time.toEpochMilli() - start) / 3600000f
343343
Vector2(hours, it.pressure.hpa().value)
344344
}
345345
if (pressures.size <= 2) {
346-
return@onIO emptyList()
346+
return@onDefault emptyList()
347347
}
348348

349349
val recentPressures =
350350
observations.count { it.time > Instant.now().minus(Duration.ofHours(4)) }
351351

352-
val order = (recentPressures - 1).coerceAtMost(4)
352+
val order = (recentPressures - 1).coerceAtMost(2)
353353
val random = Random(1)
354-
val predictors = (0 until 100).map {
354+
var cachedFirstDerivative: List<Vector2>? = null
355+
var cachedSecondDerivative: List<Vector2>? = null
356+
val predictors = (0 until 50).map {
355357
val offset1 = randomValue(random, 0f, 0.2f, -1f, 1f)
356358
val offset2 = randomValue(random, 0f, 0.2f, -0.5f, 0.5f)
357359
DerivativePredictor(
358360
order, mapOf(
359361
1 to DerivativePredictor.DerivativePredictorConfig {
360-
DataUtils.smooth(it, 0.15f).map { it.copy(y = it.y + offset1) }
362+
if (cachedFirstDerivative == null) {
363+
cachedFirstDerivative = DataUtils.smooth(it, 0.15f)
364+
}
365+
cachedFirstDerivative.map { it.copy(y = it.y + offset1) }
361366
},
362367
2 to DerivativePredictor.DerivativePredictorConfig {
363-
DataUtils.smooth(it, 0.15f).map { it.copy(y = it.y + offset2) }
368+
if (cachedSecondDerivative == null) {
369+
cachedSecondDerivative = DataUtils.smooth(it, 0.15f)
370+
}
371+
cachedSecondDerivative.map { it.copy(y = it.y + offset2) }
364372
}
365373
)
366374
)
@@ -372,7 +380,7 @@ class WeatherSubsystem private constructor(private val context: Context) : IWeat
372380
val n = (forecastLengthHours / stepSizeHours).toInt()
373381
// TODO: If the pressure turns around, don't forecast further out than that (can't tell what the next pressure system will bring)
374382
// TODO: Return the CI or only include samples that are confident
375-
ensemble.predictNext(pressures, n, stepSizeHours).filter {
383+
ensemble.predictNext(pressures.takeLast(50), n, stepSizeHours).filter {
376384
val confidence = it.upper.y - it.lower.y
377385
confidence < 5f // hPa
378386
}.map {

app/src/main/java/com/kylecorry/trail_sense/tools/weather/ui/WeatherFragment.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,15 +217,15 @@ class WeatherFragment : BoundFragment<ActivityWeatherBinding>() {
217217
Duration.between(it.time, Instant.now()) <= prefs.weather.pressureHistory
218218
}
219219

220+
loadRawWeatherReadings()
221+
222+
weather = weatherSubsystem.getWeather()
223+
220224
if (prefs.weather.showPressureForecast) {
221225
pressureForecast = listOfNotNull(
222226
history.lastOrNull()?.pressureReading()
223227
) + weatherSubsystem.getPressureForecast()
224228
}
225-
226-
loadRawWeatherReadings()
227-
228-
weather = weatherSubsystem.getWeather()
229229
}
230230
}
231231
}

0 commit comments

Comments
 (0)