Skip to content

Update 90º phase to match IHO convention#241

Draft
bkeepers wants to merge 1 commit intomainfrom
iho-phase
Draft

Update 90º phase to match IHO convention#241
bkeepers wants to merge 1 commit intomainfrom
iho-phase

Conversation

@bkeepers
Copy link
Contributor

Extracting this commit from #238 to review and discuss separately.

The 7th doodson number was negated in original neaps implementation to be consistent with the Schureman/NOAA equations, and that was preserved when adopting the IHO constituent definitions in #208. The problem with this change is that it actually makes the NOAA benchmarks worse. 😭

To quote Claude from Why the IHO List Has Duplicate Constituent Definitions:

The critical rule: whichever convention was used in analysis must be used in prediction. Consistency matters more than which specific formulation you pick.

I'm finally starting to understand why xtide embeds pre-computed equilibrium args and node factors in the TCD.

It was negated in original neaps implementation, and that was preserved when adopting the IHO implementation.
@bkeepers
Copy link
Contributor Author

Claude Prompt: This branch changes how the D7 number is used in the tide prediction algorithm. Perform a deep review of this change. Review for correctness. Compare the noaa benchmarks before and after this change, and analize the impact.


What the commit changes

Two coupled modifications to the tide prediction algorithm:

  1. D₇ sign convention (definition.ts:105): Changed from 5 - xdo[6] (negated) to xdo[6] - 5 (uniform offset), treating D₇ the same as D₂–D₆.

  2. Julian Day offset for T (astronomy/index.ts:172): Added +0.5 to JD before extracting the fractional day, shifting T from noon-epoch (Schureman convention) to midnight-epoch (claimed IHO convention).

Mathematical analysis of correctness

The two changes interact. For any constituent with species number d₁ and seventh XDO digit D₇:

  • The T shift contributes d₁ × 180° to V₀ (since 0.5 day = 180°)
  • The D₇ sign flip contributes 2(D₇ − 5) × 90° to V₀

The net change is (d₁ + D₇ − 5) × 180°. This is 0° mod 360° only when (d₁ + D₇ − 5) is even. I checked all 307 XDO-based constituents in the database:

  • 286 constituents: net change = 0° (the two changes cancel perfectly)
  • 21 constituents: net change = 180° (the two changes do NOT cancel)

The 21 affected constituents include: S1, M3, S3, MS1, MP1, M1C, SK1, SP1, MO1, MQ1, MPS2, MSP2, 2MS3, MS3, 3MS5, 2MS5, MSK5, M7, MA9, NK1, Sta. Most are minor, but M3 (third harmonic of M2) can be significant at some stations.

Which convention is correct?

This is the crux. Two internally-consistent conventions exist:

Old code (main) New code (iho-phase)
T epoch Noon (Schureman) Midnight (IHO)
D₇ 5 - xdo[6] (negated) xdo[6] - 5 (uniform)
For 286/307 constituents Same result Same result
For 21/307 constituents Different by 180° Different by 180°

The argument for the new code is that the IHO XDO system should uniformly apply offset-by-5 to all of D₂–D₇, and T should be from lower transit (midnight). The argument for the old code is that it produces better predictions against NOAA data.

Benchmark impact (3,368 NOAA stations, 3-day window)

Metric main iho-phase Change
Height MAE p50 0.0069 m 0.0120 m +74% worse
Height MAE p90 0.0168 m 0.0261 m +55% worse
Height MAE p95 0.0217 m 0.0287 m +32% worse
Timing p95 med|dt| 6.29 min 8.62 min +37% worse
Height bias (mean) 0.00124 m 0.00029 m Better bias
Timing bias (mean) -0.856 min -0.497 min Better bias
Missed events 286 305 +7%
Extra events 445 491 +10%

Per-station breakdown: 2,109 stations degraded, 453 improved, 805 unchanged. 590 stations had MAE increase >1 cm, vs only 2 improved >1 cm.

Interpretation

The iho-phase branch shows better bias (closer to zero mean error in both height and timing) but significantly worse MAE (more scatter). This pattern is consistent with a systematic 180° V₀ error in the 21 affected constituents — it shifts their contribution in a way that happens to reduce systematic bias while introducing random-looking errors.

The old code's convention — even though it appears inconsistent (negating D₇ while not negating D₂–D₆) — aligns more closely with how NOAA computes its published harmonic constants and predictions. NOAA uses Schureman-convention harmonics where T is measured from noon. The published phase values (κ) in the harmonic constants are referenced to this convention. Changing the V₀ computation convention without also adjusting the published phase values creates a systematic error.

Key concern: the tolerance widening

The test at packages/neaps/test/index.test.ts:222 widened the NOAA matching tolerance from 5 minutes to 8 minutes. Combined with the benchmark results showing p95 timing going from 6.3 to 8.6 minutes, this is masking a real accuracy regression.

Recommendation

The change should not be merged as-is. While the commit's reasoning about IHO convention consistency is plausible, the empirical evidence is clear: it makes predictions measurably worse against NOAA ground truth across 3,368 stations. The old "inconsistent" convention was actually correct for use with NOAA-published harmonic constants, because those constants were fitted using the Schureman convention (T from noon, negated D₇).

If you want to adopt the IHO convention in the future, the harmonic phase values (κ) from station data would need to be adjusted by 180° for the 21 affected constituents to compensate — otherwise you're mixing conventions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant