j-ocean

Not an operational forecast system.

Beat 009: a forecast that was using measurements it could not have had

This beat was supposed to be about presentation: a second axis, so that staleness and lead time stop being conflated. It is, and that part works. But adding an issue-time control means asking what a forecast issued at a given instant is allowed to know, and the answer we had been giving was wrong.

The analysis was reading its own future

The recorded case issues its forecast at +24 h. Its XBT drops are at +6, +18, +30, +42, +54 and +66 h; its Argo profiles are spread across the whole period.

The analysis at +24 h was being handed all of them. A forecast made on the second of September was using a measurement taken on the fourth.

Nothing about this was subtle once the question was asked. It survived three beats because nothing ever asked it: the analysis consumed "the run's observations", the run produced one set of them, and the issue instant was a number that fixed where the integration started rather than a boundary on what could be known.

Fixing it is one line and a comment. The consequences are not one line:

Before After
Observations the analysis saw 31 2
Skill against persistence at 12 h 0.133 −0.067
Skill against persistence at 24 h 0.145 0.089
Skill against persistence at 96 h 0.155 −0.057

The corrected row is roughly no better than persistence: positive at two horizons, negative at three, zero at the first. Beat 006's engineering note now carries a correction pointing here, because a superseded figure left looking current is worse than no figure.

Two more consequences worth stating:

The two axes

That was the accident. Here is the feature.

The row issued at the default instant, with the issue-time control above it

The declared horizons are measured from the default issue instant, which fixes the six valid instants the row shows. Move the control back twelve hours and the panels do not move: each becomes a longer forecast of the same moment. Every panel says both — the horizon that names it, and the lead actually asked of the model.

The same row issued twelve hours earlier: same valid instants, longer leads, and the last panel outside validity

  +0 h  issued at default  0.000   issued 12 h earlier  -0.023
 +12 h  issued at default -0.067   issued 12 h earlier  -0.161
 +24 h  issued at default  0.089   issued 12 h earlier  -0.004
 +48 h  issued at default -0.070   issued 12 h earlier  -0.174
 +72 h  issued at default  0.024   issued 12 h earlier  -0.056
 +96 h  issued at default -0.057   issued 12 h earlier  outside validity

Worse at every horizon that can be compared, with nothing else changed. That is what twelve hours of staleness costs, and it is a different question from what four days of lead time costs — which is the whole reason the second axis exists.

The SRD asked whether the two axes needed a two-dimensional control. They do not: the row is one of the axes, so there is one scrubber, with the instants at which something was actually measured marked along it. A small inset draws the curves that have been scored, so the drop is visible as a shape and not only as twelve numbers.

The skill inset: two curves, labelled by the instant each was issued

The last panel, once the forecast is twelve hours older, has fallen outside its declared validity window. It says so and draws nothing. There is no field to give it that would not be an extrapolation, and an extrapolation drawn beside five forecasts would read as one.

The departure brief

Every panel now carries the departure brief's error beside its own: the quay-side analysis, held constant and never refreshed. Asserted by byte identity across an issue-time move — it is not re-analysed, and it is not re-integrated.

At the quay side of the recorded case nothing has reported yet, so the brief is the background blended with climatology. That makes it a generous baseline rather than a straw man, and the surface says so. It is also uncomfortably competitive:

  +0 h  brief 81.5 m   shore forecast 81.6 m
 +24 h  brief 81.3 m   shore forecast 74.8 m
 +48 h  brief 80.4 m   shore forecast 86.4 m
 +96 h  brief 83.4 m   shore forecast 83.7 m

A frozen field from the quay side is within a few metres of the shore forecast at every lead time and beats it at two of them. The test prints both figures and asserts neither wins, because which of them wins is a measurement.

What this beat is really about

Three beats of numbers were optimistic because nobody had asked what the forecast was allowed to know. The harness did not hide it — there was nothing to hide, only a question nobody had put — and the moment the question was put, the machinery for reporting the answer was already there: the figures are printed by tests, the caveats are attached to the figures, and the note that was wrong now says it was wrong.

That is the whole argument for building it this way.

Where it stands

227 headless tests, 26 shell tests, seven gates. Beat 010 next: the counterfactuals, where a reader gets to withhold the measurement and watch what it was worth.