Document antimeridian limitations of the ensemble scores#41
Merged
Conversation
The scores in score.py operate on raw [lon, lat] components: squared_error and energy_score via the default Euclidean l2_distance kernel, and dawid_sebastiani / variogram_score directly (sample covariance and cross-component differences). None is aware of the ±180° seam, so a pair straddling the dateline reads as ~358° apart, and a forecast and observation given in different longitude conventions are compared inconsistently — a real risk now that the solver leaves integrated longitude unbounded. Add an antimeridian warning to the module docstring and a per-function note to each score, pointing at the mitigations: a great-circle kernel (kernel=haversine or metric.separation_distance) for the kernel-based scores, and a single consistent longitude convention (e.g. via wrap_longitude) for all four. Documentation only — no behaviour change. The metrics in metric.py are already seam-safe (they route through haversine).
vadmbertr
marked this pull request as ready for review
July 9, 2026 11:17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
The scoring rules in
score.pyoperate on the raw[lon, lat]components and are not aware of the ±180° antimeridian:squared_error/energy_scoreuse the default Euclideanl2_distancekernel;dawid_sebastianitakes a sample covariance and Mahalanobis term in raw[lon, lat];variogram_scoretakes cross-component|X_i − X_j|differences on absolute longitude.So a pair straddling the dateline (e.g.
179°and−179°) reads as ~358° apart rather than ~2°, and a forecast and observation supplied in different longitude conventions (one wrapped to[-180, 180), the other carrying the solver's unbounded longitude) are compared inconsistently. This is a realistic failure mode now that the integrator leaves longitude unbounded.By contrast, everything in
metric.py(separation_distance,normalized_separation_distance,liu_index) is already seam-safe — it routes throughhaversine, which is periodic in longitude.Change
Documentation only — no behaviour change:
.. warning::inscore.pyexplaining the antimeridian/convention pitfall and the mitigations... note::on each of the four scores:squared_error/energy_score: pass a great-circle kernel (kernel=pastax.haversineorpastax.metric.separation_distance) and keep inputs in one convention. Forenergy_score, also note the propriety trade-off (Euclidean is strictly proper; geodesic is not guaranteed to be — a chordal distance is both seam-safe and strictly proper).dawid_sebastiani/variogram_score: no kernel hook, so they rely on keeping every input (ensemble members and observation) in one consistent longitude convention, away from the seam — e.g. normalized the same way withwrap_longitude.Tests
None added (docstring-only).
ruff check src testspasses;pytest tests/test_score.py→ 53 passed; the package imports cleanly.