euler314 commited on
Commit
f1448ba
·
verified ·
1 Parent(s): 204fbc1

Publish completed WeatherNext Cyclones Mini daily comparison and audited three-model chart

Browse files
docs/daily_storm_benchmark.md CHANGED
@@ -6,7 +6,9 @@ Mean track error is 798.4 km for 1.1 and 471.2 km for 1.2 (50-member mean); +120
6
 
7
  The completed [native pressure follow-up](intensity_benchmark.md) now provides a matched 1.1 comparison on 134 daily starts / 40 storms from the same frozen plan. JMA MAE is 13.53 / 12.84 hPa for 1.1 / 1.2; USA MAE is 12.84 / 12.55 hPa. Each uses exact common agency-specific labels. The 1,339 remaining issue inputs are unavailable to the frozen 1.1 intensity pipeline, never zero-scored or filled with future observations. Paired whole-storm intervals include zero. These are not all-270-storm pressure scores.
8
 
9
- On 1 October, `release_tools/build_release_benchmark.py` independently rechecked all forecast hashes, coordinate conversions and daily/storm route aggregates, reproduced the native pressure postprocessor and generated the [shared Site snapshot](../evaluation/released_daily/released_daily_benchmark.json) and [audit receipt](../evaluation/released_daily/released_daily_verification.json). No inference or weight changes were necessary. DeepMind has not been evaluated on this larger daily plan; an older cohort's score cannot be transferred into it.
 
 
10
 
11
  ## What counts as a case and a score
12
 
 
6
 
7
  The completed [native pressure follow-up](intensity_benchmark.md) now provides a matched 1.1 comparison on 134 daily starts / 40 storms from the same frozen plan. JMA MAE is 13.53 / 12.84 hPa for 1.1 / 1.2; USA MAE is 12.84 / 12.55 hPa. Each uses exact common agency-specific labels. The 1,339 remaining issue inputs are unavailable to the frozen 1.1 intensity pipeline, never zero-scored or filled with future observations. Paired whole-storm intervals include zero. These are not all-270-storm pressure scores.
8
 
9
+ On 1 October, `release_tools/build_release_benchmark.py` independently rechecked all forecast hashes, coordinate conversions and daily/storm route aggregates, reproduced the native pressure postprocessor and generated the [shared snapshot](../evaluation/released_daily/released_daily_benchmark.json) and [original Trackformer audit receipt](../evaluation/released_daily/released_daily_verification.json). No inference or weight changes were necessary.
10
+
11
+ The [completed WeatherNext Cyclones Mini comparison](deepmind_daily_benchmark.md) now covers exactly the same 1,473 starts / 270 storms. Mini's combined mean track error is 498.4 km, direction error 39.76°, and JMA pressure MAE 10.20 hPa on 134 shared intensity starts. Its recent-only mean track error is 288.5 km versus 477.2 km for 1.2. The [independent three-way publication audit](../evaluation/deepmind_daily/publication_audit.json) rechecks the CUDA archive, unchanged original Trackformer arrays and recomputed common-support scores; the older 1 October receipt remains the audit of the original two-model snapshot, not a hash receipt for the subsequently merged JSON. No older benchmark's DeepMind score has been transferred into this comparison.
12
 
13
  ## What counts as a case and a score
14
 
docs/deepmind_daily_benchmark.md CHANGED
@@ -1,8 +1,10 @@
1
- # Matched WeatherNext Cyclones Mini daily benchmark
2
 
3
  ## Model and frozen plan
4
 
5
- The reference is Google's official [WeatherNext Cyclones Mini](https://github.com/google-deepmind/weathernext), the released `<2024` checkpoint trained through 2023—not a custom imitation or full-sized WeatherNext. It runs one seeded member using the existing JAX CPU runtime on the Mac. This is a new benchmark; scores remain pending until saved forecasts and the full verification receipt exist.
 
 
6
 
7
  - Cohort: **1,473 daily starts / 270 Western Pacific storms**, identical to the frozen Trackformer 1.1/1.2 route comparison.
8
  - Forecast: twenty six-hour steps, **+6 to +120 h**, with the exact observed issue-time centre as the initialized-storm anchor.
@@ -10,6 +12,34 @@ The reference is Google's official [WeatherNext Cyclones Mini](https://github.co
10
  - Weights SHA-256: `a1bb151457077248d70a458b1a7b19deacd2926fbcb46eee4ff2691444e3596e`.
11
  - Cohort SHA-256: `965184f1e5ab3fcb52e304f39b38583a14f753870aa2295f2d01942a441dcfd6`.
12
  - Official code commit: `89c4b2a77a1c57b328b909c575550fd2e5aadc9c`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  ## Like-for-like scoring
15
 
@@ -23,21 +53,19 @@ The official six-hour direct tracker uses a frozen initialized-storm continuity
23
 
24
  ## Execution and verification
25
 
26
- The [resumable runner](../release_tools/deepmind_daily_benchmark.py) freezes source hashes, the cohort, original baseline forecast hashes and checkpoint identity. Workers save exact input-state hashes, twenty route points, central-pressure values/masks and twenty native WP grids. Future truth is read only **after** inference for scoring; Trackformer forecasts and weights are unchanged.
27
 
28
- Local output: `/Volumes/D/typhoon_predict/output/deepmind-daily-20261002`. `progress.json` records on-disk coverage; `logs/` holds diagnostics. `verification.json` is produced only after all 1,473 cases pass the final audit. These are local results, not automatically published Site API data. No score is uploaded before review.
29
 
30
- Existing Mac runtime and weights are reused without package installation. Earlier CPU rollouts suggest **several days** for the full run; retrieval and compilation affect the total. All generated states, caches and outputs stay on `/Volumes/D`. Cloud backfill, training and Site deployments are untouched.
31
 
32
- ```bash
33
- # Existing compatible WeatherNext environment and project assets required.
34
- python release_tools/deepmind_daily_benchmark.py prepare \
35
- --project /Volumes/D/typhoon_predict \
36
- --output /Volumes/D/typhoon_predict/output/deepmind-daily-20261002
37
 
38
- python release_tools/deepmind_daily_benchmark.py launch \
 
 
39
  --project /Volumes/D/typhoon_predict \
40
- --output /Volumes/D/typhoon_predict/output/deepmind-daily-20261002
41
  ```
42
 
43
- `prepare` is only for a fresh directory. `launch` refuses an active run; `run` resumes completed cases without repetition. Source retrieval has bounded retries and failures remain visible. Final completion requires all planned cases, exact leads, valid routes/fields, unchanged forecast hashes and the verification receipt—not a process exit or count alone.
 
1
+ # Completed WeatherNext Cyclones Mini daily benchmark
2
 
3
  ## Model and frozen plan
4
 
5
+ **Complete and verified:** all **1,473 daily forecasts / 270 Western Pacific storms** finished on an **NVIDIA GeForce RTX 3070 using JAX CUDA in Windows/WSL**. The final worker audit is dated **4 October 2026, 12:55 UTC**. Publication independently rechecked all returned case hashes, physical grids, unchanged Trackformer reference arrays and exact common-support scores. No new inference was performed during this review.
6
+
7
+ The reference is Google's official [WeatherNext Cyclones Mini](https://github.com/google-deepmind/weathernext#weathernext-cyclones-mini): **`WeatherNextCyclones_Mini_<2024`**, trained through 2023 at native **1° resolution**. The pinned [software package is v0.3.0](https://github.com/google-deepmind/weathernext/blob/89c4b2a77a1c57b328b909c575550fd2e5aadc9c/setup.py); the package version and checkpoint generation identify different things. This is not a custom imitation, full-sized WeatherNext 2/Cyclones, or a WeatherNext 3 checkpoint. Mini's scores do not stand in for those larger models.
8
 
9
  - Cohort: **1,473 daily starts / 270 Western Pacific storms**, identical to the frozen Trackformer 1.1/1.2 route comparison.
10
  - Forecast: twenty six-hour steps, **+6 to +120 h**, with the exact observed issue-time centre as the initialized-storm anchor.
 
12
  - Weights SHA-256: `a1bb151457077248d70a458b1a7b19deacd2926fbcb46eee4ff2691444e3596e`.
13
  - Cohort SHA-256: `965184f1e5ab3fcb52e304f39b38583a14f753870aa2295f2d01942a441dcfd6`.
14
  - Official code commit: `89c4b2a77a1c57b328b909c575550fd2e5aadc9c`.
15
+ - CUDA protocol SHA-256: `91b31582f24ffdd4f2309eddb0cc68498a2c31cab7cbabaf06f43dfbff413606`.
16
+ - Runtime: JAX/JAXlib 0.4.38, Python 3.12.3, highest float32 matmul precision, TF32 disabled.
17
+
18
+ ## Results
19
+
20
+ | Matched development metric | Trackformer 1.1 | Trackformer 1.2 · mean of 50 | Mini · one member | Coverage |
21
+ | --- | ---: | ---: | ---: | --- |
22
+ | Mean track error · km, lower is better | 798.41 | 471.20 | 498.37 | 1,473 days / 270 storms |
23
+ | +120 h track error · km, lower is better | 1,646.40 | 1,031.63 | 1,031.91 | 1,473 days / 270 storms |
24
+ | Direction error · degrees, lower is better | 51.58 | 34.96 | 39.76 | 1,473 days / 270 storms |
25
+ | Centred route-shape similarity · higher is better | 0.7544 | 0.8837 | 0.9010 | 1,473 days / 270 storms |
26
+ | JMA central-pressure MAE · hPa, lower is better | 13.53 | 12.84 | 10.20 | 134 days / 40 storms / 2,637 leads |
27
+ | JMA pressure-curve similarity · higher is better | 0.7074 | 0.7118 | 0.8088 | 134 days / 40 storms |
28
+ | USA central-pressure MAE · hPa, lower is better | 12.84 | 12.55 | 11.55 | 134 days / 40 storms / 2,325 leads |
29
+ | USA pressure-curve similarity · higher is better | 0.7237 | 0.6637 | 0.7445 | 131 days / 40 storms |
30
+
31
+ Pressure measures central-pressure intensity, not map-grid error. The lower USA curve count excludes flat/short curves; it is not zero-filled. All three models' pressure-curve case IDs were verified equal for each agency. DeepMind geographic path/Fréchet scores and whole-storm confidence intervals are not supplied by this export and remain unavailable.
32
+
33
+ ### Historical and recent groups
34
+
35
+ | Period | Daily starts / storms | Mean track error · 1.1 / 1.2 / Mini, km | Direction error · 1.1 / 1.2 / Mini, degrees |
36
+ | --- | --- | --- | --- |
37
+ | 1980–1999 | 1,336 / 230 | 780.50 / 470.17 / 534.86 | 51.36 / 35.01 / 41.26 |
38
+ | Storms beginning in 2024+ | 137 / 40 | 901.45 / 477.16 / 288.51 | 52.90 / 34.68 / 31.16 |
39
+
40
+ Mini has better recent-only track scores even though 1.2 has lower position/heading errors in the combined cohort. Mini also has lower JMA/USA pressure MAE and higher pressure-curve similarity. Historical fitting-year overlap, different weather inputs and different ensemble sizes prevent a general or equal-compute superiority claim. All pressure comparisons here belong to the recent group; no historical pressure score is inferred from missing native 1.1 inputs.
41
+
42
+ [Full results, period breakdowns and per-lead track errors](../evaluation/deepmind_daily/benchmark.json) · [Shared snapshot and existing 1.1/1.2 uncertainty](../evaluation/released_daily/released_daily_benchmark.json) · [Completion receipt](../evaluation/deepmind_daily/verification.json) · [Independent review](../evaluation/deepmind_daily/publication_audit.json)
43
 
44
  ## Like-for-like scoring
45
 
 
53
 
54
  ## Execution and verification
55
 
56
+ The original [Mac CPU runner and scoring definitions](../release_tools/deepmind_daily_benchmark.py) provided the frozen plan. The completed run used the separately pinned, resumable RTX 3070 CUDA package; the old CPU launch instructions are not the execution record of these results. The [frozen CUDA protocol](../evaluation/deepmind_daily/protocol.json), [2,946-file case manifest](../evaluation/deepmind_daily/case-manifest.json) and [CPU/CUDA canary](../evaluation/deepmind_daily/canary.json) identify the completed run.
57
 
58
+ The strict same-runtime CPU/CUDA canary passed unchanged 0.01 hPa mean / 0.1 hPa maximum field tolerances. Its older cross-runtime Mac comparison failed the maximum-field gate and remains explicitly recorded as failed; that diagnostic is not numerical-equivalence certification. No CPU forecast was counted or relabelled as a CUDA case.
59
 
60
+ The publication review checks all 1,473 IDs, original reference hashes, exact issue−6 h / issue input-time metadata and saved input hashes, all twenty output times, finite native pressure grids, and recomputed three-model route/pressure metrics. **Raw ERA5 input states are not in the returned result-only ZIP**: this review preserves the original workers' causal-input receipts and hashes, rather than claiming to independently reopen those raw states.
61
 
62
+ To repeat the read-only archive review, use the existing frozen project reference forecasts and intensity labels, NumPy, and the returned result archive. It does not run a model or download weather:
 
 
 
 
63
 
64
+ ```bash
65
+ python release_tools/import_deepmind_release_results.py \
66
+ --archive /path/to/DeepMind_RTX3070_results_20261004_125651_467960.zip \
67
  --project /Volumes/D/typhoon_predict \
68
+ --output /Volumes/D/typhoon_predict/remote_typhoon_predict_repo/evaluation/deepmind_daily
69
  ```
70
 
71
+ Completed scores are also exposed by the existing [public benchmark API](https://trackformer-weatherlab.rudin-euler-8253.chatgpt.site/api/benchmarks/released). Documentation publication does not replace immutable forecasts, change either model's weights, restart the benchmark, modify active training, or redeploy the website. The original two-model verification receipt remains unchanged; the new publication audit identifies the merged snapshot's exact hash.
evaluation/deepmind_daily/benchmark.json ADDED
@@ -0,0 +1,1007 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "schema": "deepmind-site-import-v1",
3
+ "status": "complete_verified",
4
+ "cohort": {
5
+ "storms": 270,
6
+ "daily_issues": 1473,
7
+ "sha256": "965184f1e5ab3fcb52e304f39b38583a14f753870aa2295f2d01942a441dcfd6",
8
+ "leads_hours": [
9
+ 6,
10
+ 12,
11
+ 18,
12
+ 24,
13
+ 30,
14
+ 36,
15
+ 42,
16
+ 48,
17
+ 54,
18
+ 60,
19
+ 66,
20
+ 72,
21
+ 78,
22
+ 84,
23
+ 90,
24
+ 96,
25
+ 102,
26
+ 108,
27
+ 114,
28
+ 120
29
+ ]
30
+ },
31
+ "models": [
32
+ {
33
+ "key": "v11",
34
+ "version": "1.1",
35
+ "member_count": null,
36
+ "member_policy": "Existing frozen weighted-route reference",
37
+ "checkpoint_sha256": null
38
+ },
39
+ {
40
+ "key": "v12",
41
+ "version": "1.2",
42
+ "member_count": 50,
43
+ "member_policy": "Existing 50-member mean",
44
+ "checkpoint_sha256": "f194a23d3f91ea76ad776dfad942fabd669eeae8b3fd665815463095367e9ee0"
45
+ },
46
+ {
47
+ "key": "deepmind",
48
+ "version": "deepmind",
49
+ "member_count": 1,
50
+ "member_policy": "One official Mini member, seed 0",
51
+ "checkpoint_sha256": "a1bb151457077248d70a458b1a7b19deacd2926fbcb46eee4ff2691444e3596e"
52
+ }
53
+ ],
54
+ "metrics": [
55
+ {
56
+ "key": "mean_track_error_km",
57
+ "title": "Track position error",
58
+ "unit": "km",
59
+ "higher_is_better": false,
60
+ "values": {
61
+ "1.1": 798.4143395733709,
62
+ "1.2": 471.2045276140213,
63
+ "deepmind": 498.3660837262175
64
+ },
65
+ "coverage": {
66
+ "1.1": {
67
+ "storms": 270
68
+ },
69
+ "1.2": {
70
+ "storms": 270
71
+ },
72
+ "deepmind": {
73
+ "storms": 270
74
+ }
75
+ }
76
+ },
77
+ {
78
+ "key": "direction_error_deg",
79
+ "title": "Track direction error",
80
+ "unit": "degrees",
81
+ "higher_is_better": false,
82
+ "values": {
83
+ "1.1": 51.58419207122625,
84
+ "1.2": 34.959947454592786,
85
+ "deepmind": 39.76380497312257
86
+ },
87
+ "coverage": {
88
+ "1.1": {
89
+ "storms": 270
90
+ },
91
+ "1.2": {
92
+ "storms": 270
93
+ },
94
+ "deepmind": {
95
+ "storms": 270
96
+ }
97
+ }
98
+ },
99
+ {
100
+ "key": "shape_similarity",
101
+ "title": "Track shape similarity",
102
+ "unit": "0-1",
103
+ "higher_is_better": true,
104
+ "values": {
105
+ "1.1": 0.7543824571538857,
106
+ "1.2": 0.8837028632459877,
107
+ "deepmind": 0.9010381186926554
108
+ },
109
+ "coverage": {
110
+ "1.1": {
111
+ "storms": 270
112
+ },
113
+ "1.2": {
114
+ "storms": 270
115
+ },
116
+ "deepmind": {
117
+ "storms": 270
118
+ }
119
+ }
120
+ },
121
+ {
122
+ "key": "pressure_JMA_hpa",
123
+ "title": "Central-pressure error (JMA)",
124
+ "unit": "hPa",
125
+ "higher_is_better": false,
126
+ "values": {
127
+ "1.1": 13.53233861138585,
128
+ "1.2": 12.837077366789085,
129
+ "deepmind": 10.197678417354012
130
+ },
131
+ "common_lead_points": 2637,
132
+ "coverage": {
133
+ "1.1": {
134
+ "storms": 40,
135
+ "daily_cases": 134
136
+ },
137
+ "1.2": {
138
+ "storms": 40,
139
+ "daily_cases": 134
140
+ },
141
+ "deepmind": {
142
+ "storms": 40,
143
+ "daily_cases": 134
144
+ }
145
+ }
146
+ },
147
+ {
148
+ "key": "pressure_JMA_curve_similarity",
149
+ "title": "Pressure-curve similarity (JMA)",
150
+ "unit": "0-1",
151
+ "higher_is_better": true,
152
+ "values": {
153
+ "1.1": 0.7074066420243609,
154
+ "1.2": 0.7118461112422476,
155
+ "deepmind": 0.8087969164941555
156
+ },
157
+ "common_lead_points": 2637,
158
+ "coverage": {
159
+ "1.1": {
160
+ "storms": 40,
161
+ "daily_cases": 134
162
+ },
163
+ "1.2": {
164
+ "storms": 40,
165
+ "daily_cases": 134
166
+ },
167
+ "deepmind": {
168
+ "storms": 40,
169
+ "daily_cases": 134
170
+ }
171
+ }
172
+ },
173
+ {
174
+ "key": "pressure_USA_hpa",
175
+ "title": "Central-pressure error (USA)",
176
+ "unit": "hPa",
177
+ "higher_is_better": false,
178
+ "values": {
179
+ "1.1": 12.835629459598886,
180
+ "1.2": 12.552942457392373,
181
+ "deepmind": 11.546903198440878
182
+ },
183
+ "common_lead_points": 2325,
184
+ "coverage": {
185
+ "1.1": {
186
+ "storms": 40,
187
+ "daily_cases": 134
188
+ },
189
+ "1.2": {
190
+ "storms": 40,
191
+ "daily_cases": 134
192
+ },
193
+ "deepmind": {
194
+ "storms": 40,
195
+ "daily_cases": 134
196
+ }
197
+ }
198
+ },
199
+ {
200
+ "key": "pressure_USA_curve_similarity",
201
+ "title": "Pressure-curve similarity (USA)",
202
+ "unit": "0-1",
203
+ "higher_is_better": true,
204
+ "values": {
205
+ "1.1": 0.7236794525870405,
206
+ "1.2": 0.6636769485468179,
207
+ "deepmind": 0.7445409788756472
208
+ },
209
+ "common_lead_points": 2325,
210
+ "coverage": {
211
+ "1.1": {
212
+ "storms": 40,
213
+ "daily_cases": 131
214
+ },
215
+ "1.2": {
216
+ "storms": 40,
217
+ "daily_cases": 131
218
+ },
219
+ "deepmind": {
220
+ "storms": 40,
221
+ "daily_cases": 131
222
+ }
223
+ }
224
+ }
225
+ ],
226
+ "aggregate_equal_complete_storm": {
227
+ "route": {
228
+ "1.1": {
229
+ "mean_track_error_km": {
230
+ "value": 798.4143395733709,
231
+ "storms": 270
232
+ },
233
+ "track_error_120h_km": {
234
+ "value": 1646.3960476448165,
235
+ "storms": 270
236
+ },
237
+ "direction_error_deg": {
238
+ "value": 51.58419207122625,
239
+ "storms": 270
240
+ },
241
+ "shape_similarity": {
242
+ "value": 0.7543824571538857,
243
+ "storms": 270
244
+ },
245
+ "track_error_by_lead_km": [
246
+ 66.10969036943266,
247
+ 133.4783672768527,
248
+ 202.3585175411488,
249
+ 273.2879621656292,
250
+ 346.90051929279923,
251
+ 419.8767857705207,
252
+ 493.5704476997114,
253
+ 568.0858703129328,
254
+ 644.1251568785259,
255
+ 722.6238658146501,
256
+ 803.5946300337959,
257
+ 886.616879788694,
258
+ 973.2847405022445,
259
+ 1060.5849499902793,
260
+ 1151.5785924519794,
261
+ 1244.9737736697598,
262
+ 1343.5921960496646,
263
+ 1443.1911582149028,
264
+ 1544.0566399990746,
265
+ 1646.396047644816
266
+ ]
267
+ },
268
+ "1.2": {
269
+ "mean_track_error_km": {
270
+ "value": 471.2045276140213,
271
+ "storms": 270
272
+ },
273
+ "track_error_120h_km": {
274
+ "value": 1031.633570368749,
275
+ "storms": 270
276
+ },
277
+ "direction_error_deg": {
278
+ "value": 34.959947454592786,
279
+ "storms": 270
280
+ },
281
+ "shape_similarity": {
282
+ "value": 0.8837028632459877,
283
+ "storms": 270
284
+ },
285
+ "track_error_by_lead_km": [
286
+ 48.276258844589,
287
+ 91.12774309041492,
288
+ 129.1208135780606,
289
+ 164.481223771445,
290
+ 199.06958720909273,
291
+ 234.93256251923398,
292
+ 272.48049128499,
293
+ 311.4789218238006,
294
+ 353.46861840507904,
295
+ 399.3840596538071,
296
+ 449.2708765186405,
297
+ 502.4908306263511,
298
+ 558.3174531497493,
299
+ 616.1753924353181,
300
+ 677.6609275099131,
301
+ 740.9340851986844,
302
+ 808.8023210064223,
303
+ 880.0772095202088,
304
+ 954.9076057658763,
305
+ 1031.633570368749
306
+ ]
307
+ },
308
+ "deepmind": {
309
+ "mean_track_error_km": {
310
+ "value": 498.3660837262175,
311
+ "storms": 270
312
+ },
313
+ "track_error_120h_km": {
314
+ "value": 1031.9091421404376,
315
+ "storms": 270
316
+ },
317
+ "direction_error_deg": {
318
+ "value": 39.76380497312257,
319
+ "storms": 270
320
+ },
321
+ "shape_similarity": {
322
+ "value": 0.9010381186926554,
323
+ "storms": 270
324
+ },
325
+ "track_error_by_lead_km": [
326
+ 105.79431937309762,
327
+ 136.30842390708193,
328
+ 168.8925890316698,
329
+ 208.95643055237963,
330
+ 243.63979975302811,
331
+ 278.11432944685924,
332
+ 316.6521861156824,
333
+ 357.1736913330865,
334
+ 392.8310729414844,
335
+ 436.5373191336134,
336
+ 478.075813984495,
337
+ 522.4673167277231,
338
+ 576.9905349536721,
339
+ 634.2907658367048,
340
+ 690.6818730442626,
341
+ 746.7391690084353,
342
+ 807.6243133903178,
343
+ 879.0423409543573,
344
+ 954.6002428959632,
345
+ 1031.909142140437
346
+ ]
347
+ }
348
+ },
349
+ "pressure": {
350
+ "JMA": {
351
+ "daily_cases": 134,
352
+ "storms": 40,
353
+ "common_lead_points": 2637,
354
+ "models": {
355
+ "1.1": {
356
+ "mae_hpa": {
357
+ "value": 13.53233861138585,
358
+ "storms": 40,
359
+ "daily_cases": 134
360
+ },
361
+ "curve_similarity": {
362
+ "value": 0.7074066420243609,
363
+ "storms": 40,
364
+ "daily_cases": 134
365
+ }
366
+ },
367
+ "1.2": {
368
+ "mae_hpa": {
369
+ "value": 12.837077366789085,
370
+ "storms": 40,
371
+ "daily_cases": 134
372
+ },
373
+ "curve_similarity": {
374
+ "value": 0.7118461112422476,
375
+ "storms": 40,
376
+ "daily_cases": 134
377
+ }
378
+ },
379
+ "deepmind": {
380
+ "mae_hpa": {
381
+ "value": 10.197678417354012,
382
+ "storms": 40,
383
+ "daily_cases": 134
384
+ },
385
+ "curve_similarity": {
386
+ "value": 0.8087969164941555,
387
+ "storms": 40,
388
+ "daily_cases": 134
389
+ }
390
+ }
391
+ }
392
+ },
393
+ "USA": {
394
+ "daily_cases": 134,
395
+ "storms": 40,
396
+ "common_lead_points": 2325,
397
+ "models": {
398
+ "1.1": {
399
+ "mae_hpa": {
400
+ "value": 12.835629459598886,
401
+ "storms": 40,
402
+ "daily_cases": 134
403
+ },
404
+ "curve_similarity": {
405
+ "value": 0.7236794525870405,
406
+ "storms": 40,
407
+ "daily_cases": 131
408
+ }
409
+ },
410
+ "1.2": {
411
+ "mae_hpa": {
412
+ "value": 12.552942457392373,
413
+ "storms": 40,
414
+ "daily_cases": 134
415
+ },
416
+ "curve_similarity": {
417
+ "value": 0.6636769485468179,
418
+ "storms": 40,
419
+ "daily_cases": 131
420
+ }
421
+ },
422
+ "deepmind": {
423
+ "mae_hpa": {
424
+ "value": 11.546903198440878,
425
+ "storms": 40,
426
+ "daily_cases": 134
427
+ },
428
+ "curve_similarity": {
429
+ "value": 0.7445409788756472,
430
+ "storms": 40,
431
+ "daily_cases": 131
432
+ }
433
+ }
434
+ }
435
+ }
436
+ }
437
+ },
438
+ "periods": {
439
+ "historical_1980_1999": {
440
+ "route": {
441
+ "1.1": {
442
+ "mean_track_error_km": {
443
+ "value": 780.4956251297209,
444
+ "storms": 230
445
+ },
446
+ "track_error_120h_km": {
447
+ "value": 1617.68537007603,
448
+ "storms": 230
449
+ },
450
+ "direction_error_deg": {
451
+ "value": 51.35513468466848,
452
+ "storms": 230
453
+ },
454
+ "shape_similarity": {
455
+ "value": 0.756462863476536,
456
+ "storms": 230
457
+ },
458
+ "track_error_by_lead_km": [
459
+ 63.95070387461008,
460
+ 129.56057152366327,
461
+ 196.91757281750267,
462
+ 266.29351479253165,
463
+ 337.4313487866377,
464
+ 408.5365624559959,
465
+ 480.4125299649792,
466
+ 554.0338033012117,
467
+ 628.3701179860931,
468
+ 704.556054381504,
469
+ 783.1646921434294,
470
+ 864.6586584087509,
471
+ 949.2682475583533,
472
+ 1035.1766032588005,
473
+ 1125.2495149384633,
474
+ 1218.047210654655,
475
+ 1315.6802847719387,
476
+ 1415.099441487216,
477
+ 1515.8196994120542,
478
+ 1617.6853700760307
479
+ ]
480
+ },
481
+ "1.2": {
482
+ "mean_track_error_km": {
483
+ "value": 470.1683227329181,
484
+ "storms": 230
485
+ },
486
+ "track_error_120h_km": {
487
+ "value": 1022.9686679865174,
488
+ "storms": 230
489
+ },
490
+ "direction_error_deg": {
491
+ "value": 35.008663500237326,
492
+ "storms": 230
493
+ },
494
+ "shape_similarity": {
495
+ "value": 0.880227238887145,
496
+ "storms": 230
497
+ },
498
+ "track_error_by_lead_km": [
499
+ 48.00936024802012,
500
+ 91.97411308450529,
501
+ 131.2279581683132,
502
+ 167.32238620520673,
503
+ 201.3545994142221,
504
+ 236.4041620555792,
505
+ 272.8634618572267,
506
+ 311.62044814780137,
507
+ 353.54628740878155,
508
+ 398.8030667186859,
509
+ 448.4963800108917,
510
+ 501.7638464578764,
511
+ 557.7134662207559,
512
+ 615.9415271471161,
513
+ 677.1770146233011,
514
+ 739.235914695639,
515
+ 804.7389191190093,
516
+ 874.8402182910024,
517
+ 947.3646567979115,
518
+ 1022.9686679865174
519
+ ]
520
+ },
521
+ "deepmind": {
522
+ "mean_track_error_km": {
523
+ "value": 534.8619522162429,
524
+ "storms": 230
525
+ },
526
+ "track_error_120h_km": {
527
+ "value": 1082.253921983746,
528
+ "storms": 230
529
+ },
530
+ "direction_error_deg": {
531
+ "value": 41.2608569444939,
532
+ "storms": 230
533
+ },
534
+ "shape_similarity": {
535
+ "value": 0.8933690501351934,
536
+ "storms": 230
537
+ },
538
+ "track_error_by_lead_km": [
539
+ 114.73579161496248,
540
+ 150.05176773716605,
541
+ 186.62578636599312,
542
+ 230.15185300349486,
543
+ 269.44361640486176,
544
+ 308.8927597927205,
545
+ 350.43195179308117,
546
+ 393.53364129433595,
547
+ 432.49137917943165,
548
+ 476.05487406828956,
549
+ 517.4587499637993,
550
+ 564.5613200677591,
551
+ 620.1750658120939,
552
+ 679.1636664565294,
553
+ 737.6134951348805,
554
+ 794.3707077948451,
555
+ 855.8112853459712,
556
+ 927.6904921578597,
557
+ 1005.7269183530368,
558
+ 1082.2539219837458
559
+ ]
560
+ }
561
+ },
562
+ "pressure": {
563
+ "JMA": {
564
+ "daily_cases": 0,
565
+ "storms": 0,
566
+ "common_lead_points": 0,
567
+ "models": {
568
+ "1.1": {
569
+ "mae_hpa": {
570
+ "value": null,
571
+ "storms": 0,
572
+ "daily_cases": 0
573
+ },
574
+ "curve_similarity": {
575
+ "value": null,
576
+ "storms": 0,
577
+ "daily_cases": 0
578
+ }
579
+ },
580
+ "1.2": {
581
+ "mae_hpa": {
582
+ "value": null,
583
+ "storms": 0,
584
+ "daily_cases": 0
585
+ },
586
+ "curve_similarity": {
587
+ "value": null,
588
+ "storms": 0,
589
+ "daily_cases": 0
590
+ }
591
+ },
592
+ "deepmind": {
593
+ "mae_hpa": {
594
+ "value": null,
595
+ "storms": 0,
596
+ "daily_cases": 0
597
+ },
598
+ "curve_similarity": {
599
+ "value": null,
600
+ "storms": 0,
601
+ "daily_cases": 0
602
+ }
603
+ }
604
+ }
605
+ },
606
+ "USA": {
607
+ "daily_cases": 0,
608
+ "storms": 0,
609
+ "common_lead_points": 0,
610
+ "models": {
611
+ "1.1": {
612
+ "mae_hpa": {
613
+ "value": null,
614
+ "storms": 0,
615
+ "daily_cases": 0
616
+ },
617
+ "curve_similarity": {
618
+ "value": null,
619
+ "storms": 0,
620
+ "daily_cases": 0
621
+ }
622
+ },
623
+ "1.2": {
624
+ "mae_hpa": {
625
+ "value": null,
626
+ "storms": 0,
627
+ "daily_cases": 0
628
+ },
629
+ "curve_similarity": {
630
+ "value": null,
631
+ "storms": 0,
632
+ "daily_cases": 0
633
+ }
634
+ },
635
+ "deepmind": {
636
+ "mae_hpa": {
637
+ "value": null,
638
+ "storms": 0,
639
+ "daily_cases": 0
640
+ },
641
+ "curve_similarity": {
642
+ "value": null,
643
+ "storms": 0,
644
+ "daily_cases": 0
645
+ }
646
+ }
647
+ }
648
+ }
649
+ }
650
+ },
651
+ "recent_2024_onward": {
652
+ "route": {
653
+ "1.1": {
654
+ "mean_track_error_km": {
655
+ "value": 901.4469476243576,
656
+ "storms": 40
657
+ },
658
+ "track_error_120h_km": {
659
+ "value": 1811.4824436653348,
660
+ "storms": 40
661
+ },
662
+ "direction_error_deg": {
663
+ "value": 52.90127204393345,
664
+ "storms": 40
665
+ },
666
+ "shape_similarity": {
667
+ "value": 0.7424201207986456,
668
+ "storms": 40
669
+ },
670
+ "track_error_by_lead_km": [
671
+ 78.52386271466261,
672
+ 156.0056928576924,
673
+ 233.6439497021143,
674
+ 313.5060345609392,
675
+ 401.3482497032272,
676
+ 485.08306982903804,
677
+ 569.2284746744191,
678
+ 648.8852556303291,
679
+ 734.7166305100175,
680
+ 826.5137815552425,
681
+ 921.0667729034061,
682
+ 1012.8766527233684,
683
+ 1111.3795749296182,
684
+ 1206.6829436962798,
685
+ 1302.9707881546994,
686
+ 1399.8015110066206,
687
+ 1504.0856858965933,
688
+ 1604.7185293991047,
689
+ 1706.4190483744474,
690
+ 1811.4824436653344
691
+ ]
692
+ },
693
+ "1.2": {
694
+ "mean_track_error_km": {
695
+ "value": 477.1627056803647,
696
+ "storms": 40
697
+ },
698
+ "track_error_120h_km": {
699
+ "value": 1081.4567590665797,
700
+ "storms": 40
701
+ },
702
+ "direction_error_deg": {
703
+ "value": 34.679830192136706,
704
+ "storms": 40
705
+ },
706
+ "shape_similarity": {
707
+ "value": 0.9036877033093333,
708
+ "storms": 40
709
+ },
710
+ "track_error_by_lead_km": [
711
+ 49.81092577486012,
712
+ 86.26111562439522,
713
+ 117.00473218410767,
714
+ 148.14453977731517,
715
+ 185.93076702959854,
716
+ 226.4708651852496,
717
+ 270.27841049462984,
718
+ 310.6651454607977,
719
+ 353.022021633789,
720
+ 402.7247690307546,
721
+ 453.72423143819543,
722
+ 506.6709895950815,
723
+ 561.790377991463,
724
+ 617.5201178424808,
725
+ 680.4434266079353,
726
+ 750.6985655911949,
727
+ 832.166881859046,
728
+ 910.1899090881452,
729
+ 998.2795623316731,
730
+ 1081.45675906658
731
+ ]
732
+ },
733
+ "deepmind": {
734
+ "mean_track_error_km": {
735
+ "value": 288.51483990857145,
736
+ "storms": 40
737
+ },
738
+ "track_error_120h_km": {
739
+ "value": 742.426658041413,
740
+ "storms": 40
741
+ },
742
+ "direction_error_deg": {
743
+ "value": 31.155756137737363,
744
+ "storms": 40
745
+ },
746
+ "shape_similarity": {
747
+ "value": 0.9451352628980612,
748
+ "storms": 40
749
+ },
750
+ "track_error_by_lead_km": [
751
+ 54.38085398237462,
752
+ 57.28419688409821,
753
+ 66.92670435931014,
754
+ 87.08275145846693,
755
+ 95.26785400498491,
756
+ 101.13835495815766,
757
+ 122.41853347063868,
758
+ 148.10397905590278,
759
+ 164.7843120732874,
760
+ 209.3113782592264,
761
+ 251.62393210349515,
762
+ 280.4267975225144,
763
+ 328.6794825177443,
764
+ 376.2715872727139,
765
+ 420.82504602320796,
766
+ 472.8578209865762,
767
+ 530.5492246453126,
768
+ 599.3154715342171,
769
+ 660.6218590177866,
770
+ 742.426658041413
771
+ ]
772
+ }
773
+ },
774
+ "pressure": {
775
+ "JMA": {
776
+ "daily_cases": 134,
777
+ "storms": 40,
778
+ "common_lead_points": 2637,
779
+ "models": {
780
+ "1.1": {
781
+ "mae_hpa": {
782
+ "value": 13.53233861138585,
783
+ "storms": 40,
784
+ "daily_cases": 134
785
+ },
786
+ "curve_similarity": {
787
+ "value": 0.7074066420243609,
788
+ "storms": 40,
789
+ "daily_cases": 134
790
+ }
791
+ },
792
+ "1.2": {
793
+ "mae_hpa": {
794
+ "value": 12.837077366789085,
795
+ "storms": 40,
796
+ "daily_cases": 134
797
+ },
798
+ "curve_similarity": {
799
+ "value": 0.7118461112422476,
800
+ "storms": 40,
801
+ "daily_cases": 134
802
+ }
803
+ },
804
+ "deepmind": {
805
+ "mae_hpa": {
806
+ "value": 10.197678417354012,
807
+ "storms": 40,
808
+ "daily_cases": 134
809
+ },
810
+ "curve_similarity": {
811
+ "value": 0.8087969164941555,
812
+ "storms": 40,
813
+ "daily_cases": 134
814
+ }
815
+ }
816
+ }
817
+ },
818
+ "USA": {
819
+ "daily_cases": 134,
820
+ "storms": 40,
821
+ "common_lead_points": 2325,
822
+ "models": {
823
+ "1.1": {
824
+ "mae_hpa": {
825
+ "value": 12.835629459598886,
826
+ "storms": 40,
827
+ "daily_cases": 134
828
+ },
829
+ "curve_similarity": {
830
+ "value": 0.7236794525870405,
831
+ "storms": 40,
832
+ "daily_cases": 131
833
+ }
834
+ },
835
+ "1.2": {
836
+ "mae_hpa": {
837
+ "value": 12.552942457392373,
838
+ "storms": 40,
839
+ "daily_cases": 134
840
+ },
841
+ "curve_similarity": {
842
+ "value": 0.6636769485468179,
843
+ "storms": 40,
844
+ "daily_cases": 131
845
+ }
846
+ },
847
+ "deepmind": {
848
+ "mae_hpa": {
849
+ "value": 11.546903198440878,
850
+ "storms": 40,
851
+ "daily_cases": 134
852
+ },
853
+ "curve_similarity": {
854
+ "value": 0.7445409788756472,
855
+ "storms": 40,
856
+ "daily_cases": 131
857
+ }
858
+ }
859
+ }
860
+ }
861
+ }
862
+ }
863
+ },
864
+ "interpretation": "Development comparison: 1.2 reference is 50-member input-perturbed mean; Mini is one member, different weather source. Historical fitting-year overlap; recent 2024+ reported separately.",
865
+ "aggregation": "Same frozen scorer: leads per day; days within storm; equal storms. Common three-way moving directions and pressure-valid leads; separate JMA/USA labels.",
866
+ "pressure_scope": "Native matched subset, common three-way leads. Missing is null, never zero.",
867
+ "verification_sha256": "8f29a767ab5db61cf6773f5806cc110789329b04db48361715e5b4c295545c89",
868
+ "case_manifest_sha256": "30d35cfb79e809227fd0d255f9b5173ad18e781c7450ed4bbf0211553f8e63bd",
869
+ "canary": {
870
+ "wp_pressure_mean_abs_difference_hpa": 0.00025739270264116574,
871
+ "wp_pressure_max_abs_difference_hpa": 0.04547119140625,
872
+ "wp_pressure_max_abs_difference_hpa_by_lead": [
873
+ 0.00030517578125,
874
+ 0.000244140625,
875
+ 0.000244140625,
876
+ 0.00018310546875,
877
+ 0.00030517578125,
878
+ 0.00054931640625,
879
+ 0.00079345703125,
880
+ 0.0009765625,
881
+ 0.002685546875,
882
+ 0.00341796875,
883
+ 0.0032958984375,
884
+ 0.0048828125,
885
+ 0.004638671875,
886
+ 0.0032958984375,
887
+ 0.00543212890625,
888
+ 0.00787353515625,
889
+ 0.00836181640625,
890
+ 0.023681640625,
891
+ 0.04547119140625,
892
+ 0.042724609375
893
+ ],
894
+ "field_gate_limits_hpa": {
895
+ "mean": 0.01,
896
+ "max": 0.1
897
+ },
898
+ "field_gate_passed": true,
899
+ "tracker_max_difference_km": 0.14586496919052705,
900
+ "central_pressure_max_abs_difference_hpa": 0.07400935954797205,
901
+ "pressure_masks_match": true,
902
+ "cpu_numerical_equivalence": true,
903
+ "status": "cuda_canary_passed",
904
+ "tested_at_utc": "2026-10-04T12:55:06.985459+00:00",
905
+ "validation_protocol": {
906
+ "id": "same-runtime-strict-fp32-cpu-cuda-v2",
907
+ "primary_reference": "One fresh CPU rollout in the same pinned WSL runtime and inference code path",
908
+ "legacy_reference": "Bundled Mac CPU output retained as a separate cross-runtime diagnostic, not the primary gate",
909
+ "field_gate_limits_hpa": {
910
+ "mean": 0.01,
911
+ "max": 0.1
912
+ },
913
+ "jax": "0.4.38",
914
+ "jaxlib": "0.4.38",
915
+ "case_index": 0,
916
+ "cpu_counts_as_benchmark": false,
917
+ "tolerances_changed": false
918
+ },
919
+ "runtime_match": true,
920
+ "input_bytes_match": true,
921
+ "protocol_match": true,
922
+ "case_index": 0,
923
+ "checkpoint_sha256": "a1bb151457077248d70a458b1a7b19deacd2926fbcb46eee4ff2691444e3596e",
924
+ "gpu_verified_steps": 20,
925
+ "protocol_sha256": "91b31582f24ffdd4f2309eddb0cc68498a2c31cab7cbabaf06f43dfbff413606",
926
+ "cpu_forecast_sha256": "a8700f10b93dcf76b20439ed0cf71c312274398813af4ef8c6df51cbc75b0964",
927
+ "cuda_forecast_sha256": "0338d2b907bf0f4a605883b4c778bf961fe7406b6916161317b25a39b66fa68c",
928
+ "cpu_metadata_identity": "a2b686e98309ebcda11482f521b68cc8657171d08606d24e0c303484c446cddb",
929
+ "cuda_metadata_identity": "5eb223c4c969f2df64b29289ef3e96a467b418721ee7071faa81e64c59fbb1a1",
930
+ "cpu_input_state_sha256": "f0e8ca0d826e52e76a2b090084a09845a58871d3e6e02b8513b7a4f9cbf8d6c2",
931
+ "cuda_input_state_sha256": "f0e8ca0d826e52e76a2b090084a09845a58871d3e6e02b8513b7a4f9cbf8d6c2",
932
+ "cpu_device": {
933
+ "backend": "cpu",
934
+ "device_kind": "cpu",
935
+ "platform": "cpu",
936
+ "platform_version": "cpu",
937
+ "jax": "0.4.38",
938
+ "jaxlib": "0.4.38",
939
+ "python": "3.12.3",
940
+ "gpu_matmul_verified": false,
941
+ "numerics": {
942
+ "matmul_precision": "highest",
943
+ "NVIDIA_TF32_OVERRIDE": "0",
944
+ "jax_enable_x64": false,
945
+ "jax_threefry_partitionable": true
946
+ }
947
+ },
948
+ "device": {
949
+ "backend": "cuda",
950
+ "device_kind": "NVIDIA GeForce RTX 3070",
951
+ "platform": "gpu",
952
+ "platform_version": "PJRT C API\ncuda 12030",
953
+ "jax": "0.4.38",
954
+ "jaxlib": "0.4.38",
955
+ "python": "3.12.3",
956
+ "gpu_matmul_verified": true,
957
+ "numerics": {
958
+ "matmul_precision": "highest",
959
+ "NVIDIA_TF32_OVERRIDE": "0",
960
+ "jax_enable_x64": false,
961
+ "jax_threefry_partitionable": true
962
+ }
963
+ },
964
+ "cpu_predictions_reused_as_cuda": false,
965
+ "legacy_cross_runtime_comparison": {
966
+ "wp_pressure_mean_abs_difference_hpa": 0.0074994690769043465,
967
+ "wp_pressure_max_abs_difference_hpa": 0.59765625,
968
+ "wp_pressure_max_abs_difference_hpa_by_lead": [
969
+ 0.03729248046875,
970
+ 0.00933837890625,
971
+ 0.0706787109375,
972
+ 0.03485107421875,
973
+ 0.0855712890625,
974
+ 0.05712890625,
975
+ 0.0518798828125,
976
+ 0.04205322265625,
977
+ 0.0977783203125,
978
+ 0.07293701171875,
979
+ 0.05584716796875,
980
+ 0.0611572265625,
981
+ 0.145751953125,
982
+ 0.1763916015625,
983
+ 0.19189453125,
984
+ 0.26953125,
985
+ 0.20556640625,
986
+ 0.29156494140625,
987
+ 0.5030517578125,
988
+ 0.59765625
989
+ ],
990
+ "field_gate_limits_hpa": {
991
+ "mean": 0.01,
992
+ "max": 0.1
993
+ },
994
+ "field_gate_passed": false,
995
+ "tracker_max_difference_km": 35.802407171684315,
996
+ "central_pressure_max_abs_difference_hpa": 1.597311381356235,
997
+ "pressure_masks_match": true,
998
+ "cpu_numerical_equivalence": false,
999
+ "gating": false,
1000
+ "reference_sha256": "982501139e39ebf6e6308c23d7abf3131c221f0ce489000400cafcaa65b06eb4",
1001
+ "input_bytes_match": true,
1002
+ "note": "The older Mac implementation/runtime differs. A failed legacy comparison remains failed; it is not numerical-equivalence certification."
1003
+ }
1004
+ },
1005
+ "published_to_site": false,
1006
+ "integration_note": "Import after independent review into the EXISTING site. The current frontend explicitly suppresses DeepMind until its verified import adapter is updated."
1007
+ }
evaluation/deepmind_daily/canary.json ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "wp_pressure_mean_abs_difference_hpa": 0.00025739270264116574,
3
+ "wp_pressure_max_abs_difference_hpa": 0.04547119140625,
4
+ "wp_pressure_max_abs_difference_hpa_by_lead": [
5
+ 0.00030517578125,
6
+ 0.000244140625,
7
+ 0.000244140625,
8
+ 0.00018310546875,
9
+ 0.00030517578125,
10
+ 0.00054931640625,
11
+ 0.00079345703125,
12
+ 0.0009765625,
13
+ 0.002685546875,
14
+ 0.00341796875,
15
+ 0.0032958984375,
16
+ 0.0048828125,
17
+ 0.004638671875,
18
+ 0.0032958984375,
19
+ 0.00543212890625,
20
+ 0.00787353515625,
21
+ 0.00836181640625,
22
+ 0.023681640625,
23
+ 0.04547119140625,
24
+ 0.042724609375
25
+ ],
26
+ "field_gate_limits_hpa": {
27
+ "mean": 0.01,
28
+ "max": 0.1
29
+ },
30
+ "field_gate_passed": true,
31
+ "tracker_max_difference_km": 0.14586496919052705,
32
+ "central_pressure_max_abs_difference_hpa": 0.07400935954797205,
33
+ "pressure_masks_match": true,
34
+ "cpu_numerical_equivalence": true,
35
+ "status": "cuda_canary_passed",
36
+ "tested_at_utc": "2026-10-04T12:55:06.985459+00:00",
37
+ "validation_protocol": {
38
+ "id": "same-runtime-strict-fp32-cpu-cuda-v2",
39
+ "primary_reference": "One fresh CPU rollout in the same pinned WSL runtime and inference code path",
40
+ "legacy_reference": "Bundled Mac CPU output retained as a separate cross-runtime diagnostic, not the primary gate",
41
+ "field_gate_limits_hpa": {
42
+ "mean": 0.01,
43
+ "max": 0.1
44
+ },
45
+ "jax": "0.4.38",
46
+ "jaxlib": "0.4.38",
47
+ "case_index": 0,
48
+ "cpu_counts_as_benchmark": false,
49
+ "tolerances_changed": false
50
+ },
51
+ "runtime_match": true,
52
+ "input_bytes_match": true,
53
+ "protocol_match": true,
54
+ "case_index": 0,
55
+ "checkpoint_sha256": "a1bb151457077248d70a458b1a7b19deacd2926fbcb46eee4ff2691444e3596e",
56
+ "gpu_verified_steps": 20,
57
+ "protocol_sha256": "91b31582f24ffdd4f2309eddb0cc68498a2c31cab7cbabaf06f43dfbff413606",
58
+ "cpu_forecast_sha256": "a8700f10b93dcf76b20439ed0cf71c312274398813af4ef8c6df51cbc75b0964",
59
+ "cuda_forecast_sha256": "0338d2b907bf0f4a605883b4c778bf961fe7406b6916161317b25a39b66fa68c",
60
+ "cpu_metadata_identity": "a2b686e98309ebcda11482f521b68cc8657171d08606d24e0c303484c446cddb",
61
+ "cuda_metadata_identity": "5eb223c4c969f2df64b29289ef3e96a467b418721ee7071faa81e64c59fbb1a1",
62
+ "cpu_input_state_sha256": "f0e8ca0d826e52e76a2b090084a09845a58871d3e6e02b8513b7a4f9cbf8d6c2",
63
+ "cuda_input_state_sha256": "f0e8ca0d826e52e76a2b090084a09845a58871d3e6e02b8513b7a4f9cbf8d6c2",
64
+ "cpu_device": {
65
+ "backend": "cpu",
66
+ "device_kind": "cpu",
67
+ "platform": "cpu",
68
+ "platform_version": "cpu",
69
+ "jax": "0.4.38",
70
+ "jaxlib": "0.4.38",
71
+ "python": "3.12.3",
72
+ "gpu_matmul_verified": false,
73
+ "numerics": {
74
+ "matmul_precision": "highest",
75
+ "NVIDIA_TF32_OVERRIDE": "0",
76
+ "jax_enable_x64": false,
77
+ "jax_threefry_partitionable": true
78
+ }
79
+ },
80
+ "device": {
81
+ "backend": "cuda",
82
+ "device_kind": "NVIDIA GeForce RTX 3070",
83
+ "platform": "gpu",
84
+ "platform_version": "PJRT C API\ncuda 12030",
85
+ "jax": "0.4.38",
86
+ "jaxlib": "0.4.38",
87
+ "python": "3.12.3",
88
+ "gpu_matmul_verified": true,
89
+ "numerics": {
90
+ "matmul_precision": "highest",
91
+ "NVIDIA_TF32_OVERRIDE": "0",
92
+ "jax_enable_x64": false,
93
+ "jax_threefry_partitionable": true
94
+ }
95
+ },
96
+ "cpu_predictions_reused_as_cuda": false,
97
+ "legacy_cross_runtime_comparison": {
98
+ "wp_pressure_mean_abs_difference_hpa": 0.0074994690769043465,
99
+ "wp_pressure_max_abs_difference_hpa": 0.59765625,
100
+ "wp_pressure_max_abs_difference_hpa_by_lead": [
101
+ 0.03729248046875,
102
+ 0.00933837890625,
103
+ 0.0706787109375,
104
+ 0.03485107421875,
105
+ 0.0855712890625,
106
+ 0.05712890625,
107
+ 0.0518798828125,
108
+ 0.04205322265625,
109
+ 0.0977783203125,
110
+ 0.07293701171875,
111
+ 0.05584716796875,
112
+ 0.0611572265625,
113
+ 0.145751953125,
114
+ 0.1763916015625,
115
+ 0.19189453125,
116
+ 0.26953125,
117
+ 0.20556640625,
118
+ 0.29156494140625,
119
+ 0.5030517578125,
120
+ 0.59765625
121
+ ],
122
+ "field_gate_limits_hpa": {
123
+ "mean": 0.01,
124
+ "max": 0.1
125
+ },
126
+ "field_gate_passed": false,
127
+ "tracker_max_difference_km": 35.802407171684315,
128
+ "central_pressure_max_abs_difference_hpa": 1.597311381356235,
129
+ "pressure_masks_match": true,
130
+ "cpu_numerical_equivalence": false,
131
+ "gating": false,
132
+ "reference_sha256": "982501139e39ebf6e6308c23d7abf3131c221f0ce489000400cafcaa65b06eb4",
133
+ "input_bytes_match": true,
134
+ "note": "The older Mac implementation/runtime differs. A failed legacy comparison remains failed; it is not numerical-equivalence certification."
135
+ }
136
+ }
evaluation/deepmind_daily/case-manifest.json ADDED
The diff for this file is too large to render. See raw diff
 
evaluation/deepmind_daily/protocol.json ADDED
The diff for this file is too large to render. See raw diff
 
evaluation/deepmind_daily/publication_audit.json ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "status": "complete_verified",
3
+ "reviewed_at_utc": "2026-10-05T05:18:43.939189+00:00",
4
+ "archive_sha256": "602425d3ff9284cce44fee4d3a75f50354b6e3f26f391f5402f72afabd762d45",
5
+ "verified_daily_cases": 1473,
6
+ "verified_storms": 270,
7
+ "hashed_case_files": 2946,
8
+ "verified_physical_pressure_grids": 29460,
9
+ "model": "Google DeepMind WeatherNext Cyclones Mini (<2024)",
10
+ "software_version": "0.3.0",
11
+ "software_commit": "89c4b2a77a1c57b328b909c575550fd2e5aadc9c",
12
+ "checkpoint_sha256": "a1bb151457077248d70a458b1a7b19deacd2926fbcb46eee4ff2691444e3596e",
13
+ "cohort_sha256": "965184f1e5ab3fcb52e304f39b38583a14f753870aa2295f2d01942a441dcfd6",
14
+ "members": 1,
15
+ "backend": "NVIDIA GeForce RTX 3070 / CUDA",
16
+ "all_route_and_pressure_scores_recomputed": true,
17
+ "exact_common_curve_case_ids": true,
18
+ "all_original_forecasts_sha256_verified": true,
19
+ "causal_input_metadata_and_saved_hashes_verified": true,
20
+ "raw_era5_states_in_return_zip": false,
21
+ "raw_input_audit_scope": "Original worker receipt and saved input hashes/times; raw ERA5 states were not returned in this result-only ZIP.",
22
+ "new_inference_performed": false,
23
+ "model_weights_changed": false,
24
+ "forecasts_modified": false,
25
+ "missing_results_scored_as_zero": 0,
26
+ "previous_snapshot_sha256": "79f67a5f4490150cf0ab24d73e5d3cdedb4884d37e86560cbadde1d4ecdafc43",
27
+ "snapshot_sha256": "adff1baa1dbc38a6b443cfdd436cd7d4893c04241355c9eaf5004f439ce469a4",
28
+ "imported_files_sha256": {
29
+ "benchmark.json": "85a0965b7a87d400ccad67b437d05b2ac651055b8f4a473ff30fdd85ac778645",
30
+ "verification.json": "8f29a767ab5db61cf6773f5806cc110789329b04db48361715e5b4c295545c89",
31
+ "protocol.json": "91b31582f24ffdd4f2309eddb0cc68498a2c31cab7cbabaf06f43dfbff413606",
32
+ "case-manifest.json": "30d35cfb79e809227fd0d255f9b5173ad18e781c7450ed4bbf0211553f8e63bd",
33
+ "canary.json": "c7c9724752aab3f2208b53aad31949580800c0c60e28b187bccbd5d0a3c5e075"
34
+ },
35
+ "period_coverage": {
36
+ "historical_1980_1999": {
37
+ "daily_issues": 1336,
38
+ "storms": 230
39
+ },
40
+ "recent_2024_onward": {
41
+ "daily_issues": 137,
42
+ "storms": 40
43
+ }
44
+ }
45
+ }
evaluation/deepmind_daily/verification.json ADDED
@@ -0,0 +1,1501 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "status": "complete_verified",
3
+ "verified_at_utc": "2026-10-04T12:55:16.370140+00:00",
4
+ "verified_daily_cases": 1473,
5
+ "verified_storms": 270,
6
+ "backend": "NVIDIA CUDA",
7
+ "members": 1,
8
+ "checkpoint_sha256": "a1bb151457077248d70a458b1a7b19deacd2926fbcb46eee4ff2691444e3596e",
9
+ "cohort_sha256": "965184f1e5ab3fcb52e304f39b38583a14f753870aa2295f2d01942a441dcfd6",
10
+ "bundle_manifest_sha256": "c9d43105989cb38622bb7b7549008c75aff49f089410312df1192a1102765bd9",
11
+ "protocol_sha256": "91b31582f24ffdd4f2309eddb0cc68498a2c31cab7cbabaf06f43dfbff413606",
12
+ "case_indices": [
13
+ 0,
14
+ 1,
15
+ 2,
16
+ 3,
17
+ 4,
18
+ 5,
19
+ 6,
20
+ 7,
21
+ 8,
22
+ 9,
23
+ 10,
24
+ 11,
25
+ 12,
26
+ 13,
27
+ 14,
28
+ 15,
29
+ 16,
30
+ 17,
31
+ 18,
32
+ 19,
33
+ 20,
34
+ 21,
35
+ 22,
36
+ 23,
37
+ 24,
38
+ 25,
39
+ 26,
40
+ 27,
41
+ 28,
42
+ 29,
43
+ 30,
44
+ 31,
45
+ 32,
46
+ 33,
47
+ 34,
48
+ 35,
49
+ 36,
50
+ 37,
51
+ 38,
52
+ 39,
53
+ 40,
54
+ 41,
55
+ 42,
56
+ 43,
57
+ 44,
58
+ 45,
59
+ 46,
60
+ 47,
61
+ 48,
62
+ 49,
63
+ 50,
64
+ 51,
65
+ 52,
66
+ 53,
67
+ 54,
68
+ 55,
69
+ 56,
70
+ 57,
71
+ 58,
72
+ 59,
73
+ 60,
74
+ 61,
75
+ 62,
76
+ 63,
77
+ 64,
78
+ 65,
79
+ 66,
80
+ 67,
81
+ 68,
82
+ 69,
83
+ 70,
84
+ 71,
85
+ 72,
86
+ 73,
87
+ 74,
88
+ 75,
89
+ 76,
90
+ 77,
91
+ 78,
92
+ 79,
93
+ 80,
94
+ 81,
95
+ 82,
96
+ 83,
97
+ 84,
98
+ 85,
99
+ 86,
100
+ 87,
101
+ 88,
102
+ 89,
103
+ 90,
104
+ 91,
105
+ 92,
106
+ 93,
107
+ 94,
108
+ 95,
109
+ 96,
110
+ 97,
111
+ 98,
112
+ 99,
113
+ 100,
114
+ 101,
115
+ 102,
116
+ 103,
117
+ 104,
118
+ 105,
119
+ 106,
120
+ 107,
121
+ 108,
122
+ 109,
123
+ 110,
124
+ 111,
125
+ 112,
126
+ 113,
127
+ 114,
128
+ 115,
129
+ 116,
130
+ 117,
131
+ 118,
132
+ 119,
133
+ 120,
134
+ 121,
135
+ 122,
136
+ 123,
137
+ 124,
138
+ 125,
139
+ 126,
140
+ 127,
141
+ 128,
142
+ 129,
143
+ 130,
144
+ 131,
145
+ 132,
146
+ 133,
147
+ 134,
148
+ 135,
149
+ 136,
150
+ 137,
151
+ 138,
152
+ 139,
153
+ 140,
154
+ 141,
155
+ 142,
156
+ 143,
157
+ 144,
158
+ 145,
159
+ 146,
160
+ 147,
161
+ 148,
162
+ 149,
163
+ 150,
164
+ 151,
165
+ 152,
166
+ 153,
167
+ 154,
168
+ 155,
169
+ 156,
170
+ 157,
171
+ 158,
172
+ 159,
173
+ 160,
174
+ 161,
175
+ 162,
176
+ 163,
177
+ 164,
178
+ 165,
179
+ 166,
180
+ 167,
181
+ 168,
182
+ 169,
183
+ 170,
184
+ 171,
185
+ 172,
186
+ 173,
187
+ 174,
188
+ 175,
189
+ 176,
190
+ 177,
191
+ 178,
192
+ 179,
193
+ 180,
194
+ 181,
195
+ 182,
196
+ 183,
197
+ 184,
198
+ 185,
199
+ 186,
200
+ 187,
201
+ 188,
202
+ 189,
203
+ 190,
204
+ 191,
205
+ 192,
206
+ 193,
207
+ 194,
208
+ 195,
209
+ 196,
210
+ 197,
211
+ 198,
212
+ 199,
213
+ 200,
214
+ 201,
215
+ 202,
216
+ 203,
217
+ 204,
218
+ 205,
219
+ 206,
220
+ 207,
221
+ 208,
222
+ 209,
223
+ 210,
224
+ 211,
225
+ 212,
226
+ 213,
227
+ 214,
228
+ 215,
229
+ 216,
230
+ 217,
231
+ 218,
232
+ 219,
233
+ 220,
234
+ 221,
235
+ 222,
236
+ 223,
237
+ 224,
238
+ 225,
239
+ 226,
240
+ 227,
241
+ 228,
242
+ 229,
243
+ 230,
244
+ 231,
245
+ 232,
246
+ 233,
247
+ 234,
248
+ 235,
249
+ 236,
250
+ 237,
251
+ 238,
252
+ 239,
253
+ 240,
254
+ 241,
255
+ 242,
256
+ 243,
257
+ 244,
258
+ 245,
259
+ 246,
260
+ 247,
261
+ 248,
262
+ 249,
263
+ 250,
264
+ 251,
265
+ 252,
266
+ 253,
267
+ 254,
268
+ 255,
269
+ 256,
270
+ 257,
271
+ 258,
272
+ 259,
273
+ 260,
274
+ 261,
275
+ 262,
276
+ 263,
277
+ 264,
278
+ 265,
279
+ 266,
280
+ 267,
281
+ 268,
282
+ 269,
283
+ 270,
284
+ 271,
285
+ 272,
286
+ 273,
287
+ 274,
288
+ 275,
289
+ 276,
290
+ 277,
291
+ 278,
292
+ 279,
293
+ 280,
294
+ 281,
295
+ 282,
296
+ 283,
297
+ 284,
298
+ 285,
299
+ 286,
300
+ 287,
301
+ 288,
302
+ 289,
303
+ 290,
304
+ 291,
305
+ 292,
306
+ 293,
307
+ 294,
308
+ 295,
309
+ 296,
310
+ 297,
311
+ 298,
312
+ 299,
313
+ 300,
314
+ 301,
315
+ 302,
316
+ 303,
317
+ 304,
318
+ 305,
319
+ 306,
320
+ 307,
321
+ 308,
322
+ 309,
323
+ 310,
324
+ 311,
325
+ 312,
326
+ 313,
327
+ 314,
328
+ 315,
329
+ 316,
330
+ 317,
331
+ 318,
332
+ 319,
333
+ 320,
334
+ 321,
335
+ 322,
336
+ 323,
337
+ 324,
338
+ 325,
339
+ 326,
340
+ 327,
341
+ 328,
342
+ 329,
343
+ 330,
344
+ 331,
345
+ 332,
346
+ 333,
347
+ 334,
348
+ 335,
349
+ 336,
350
+ 337,
351
+ 338,
352
+ 339,
353
+ 340,
354
+ 341,
355
+ 342,
356
+ 343,
357
+ 344,
358
+ 345,
359
+ 346,
360
+ 347,
361
+ 348,
362
+ 349,
363
+ 350,
364
+ 351,
365
+ 352,
366
+ 353,
367
+ 354,
368
+ 355,
369
+ 356,
370
+ 357,
371
+ 358,
372
+ 359,
373
+ 360,
374
+ 361,
375
+ 362,
376
+ 363,
377
+ 364,
378
+ 365,
379
+ 366,
380
+ 367,
381
+ 368,
382
+ 369,
383
+ 370,
384
+ 371,
385
+ 372,
386
+ 373,
387
+ 374,
388
+ 375,
389
+ 376,
390
+ 377,
391
+ 378,
392
+ 379,
393
+ 380,
394
+ 381,
395
+ 382,
396
+ 383,
397
+ 384,
398
+ 385,
399
+ 386,
400
+ 387,
401
+ 388,
402
+ 389,
403
+ 390,
404
+ 391,
405
+ 392,
406
+ 393,
407
+ 394,
408
+ 395,
409
+ 396,
410
+ 397,
411
+ 398,
412
+ 399,
413
+ 400,
414
+ 401,
415
+ 402,
416
+ 403,
417
+ 404,
418
+ 405,
419
+ 406,
420
+ 407,
421
+ 408,
422
+ 409,
423
+ 410,
424
+ 411,
425
+ 412,
426
+ 413,
427
+ 414,
428
+ 415,
429
+ 416,
430
+ 417,
431
+ 418,
432
+ 419,
433
+ 420,
434
+ 421,
435
+ 422,
436
+ 423,
437
+ 424,
438
+ 425,
439
+ 426,
440
+ 427,
441
+ 428,
442
+ 429,
443
+ 430,
444
+ 431,
445
+ 432,
446
+ 433,
447
+ 434,
448
+ 435,
449
+ 436,
450
+ 437,
451
+ 438,
452
+ 439,
453
+ 440,
454
+ 441,
455
+ 442,
456
+ 443,
457
+ 444,
458
+ 445,
459
+ 446,
460
+ 447,
461
+ 448,
462
+ 449,
463
+ 450,
464
+ 451,
465
+ 452,
466
+ 453,
467
+ 454,
468
+ 455,
469
+ 456,
470
+ 457,
471
+ 458,
472
+ 459,
473
+ 460,
474
+ 461,
475
+ 462,
476
+ 463,
477
+ 464,
478
+ 465,
479
+ 466,
480
+ 467,
481
+ 468,
482
+ 469,
483
+ 470,
484
+ 471,
485
+ 472,
486
+ 473,
487
+ 474,
488
+ 475,
489
+ 476,
490
+ 477,
491
+ 478,
492
+ 479,
493
+ 480,
494
+ 481,
495
+ 482,
496
+ 483,
497
+ 484,
498
+ 485,
499
+ 486,
500
+ 487,
501
+ 488,
502
+ 489,
503
+ 490,
504
+ 491,
505
+ 492,
506
+ 493,
507
+ 494,
508
+ 495,
509
+ 496,
510
+ 497,
511
+ 498,
512
+ 499,
513
+ 500,
514
+ 501,
515
+ 502,
516
+ 503,
517
+ 504,
518
+ 505,
519
+ 506,
520
+ 507,
521
+ 508,
522
+ 509,
523
+ 510,
524
+ 511,
525
+ 512,
526
+ 513,
527
+ 514,
528
+ 515,
529
+ 516,
530
+ 517,
531
+ 518,
532
+ 519,
533
+ 520,
534
+ 521,
535
+ 522,
536
+ 523,
537
+ 524,
538
+ 525,
539
+ 526,
540
+ 527,
541
+ 528,
542
+ 529,
543
+ 530,
544
+ 531,
545
+ 532,
546
+ 533,
547
+ 534,
548
+ 535,
549
+ 536,
550
+ 537,
551
+ 538,
552
+ 539,
553
+ 540,
554
+ 541,
555
+ 542,
556
+ 543,
557
+ 544,
558
+ 545,
559
+ 546,
560
+ 547,
561
+ 548,
562
+ 549,
563
+ 550,
564
+ 551,
565
+ 552,
566
+ 553,
567
+ 554,
568
+ 555,
569
+ 556,
570
+ 557,
571
+ 558,
572
+ 559,
573
+ 560,
574
+ 561,
575
+ 562,
576
+ 563,
577
+ 564,
578
+ 565,
579
+ 566,
580
+ 567,
581
+ 568,
582
+ 569,
583
+ 570,
584
+ 571,
585
+ 572,
586
+ 573,
587
+ 574,
588
+ 575,
589
+ 576,
590
+ 577,
591
+ 578,
592
+ 579,
593
+ 580,
594
+ 581,
595
+ 582,
596
+ 583,
597
+ 584,
598
+ 585,
599
+ 586,
600
+ 587,
601
+ 588,
602
+ 589,
603
+ 590,
604
+ 591,
605
+ 592,
606
+ 593,
607
+ 594,
608
+ 595,
609
+ 596,
610
+ 597,
611
+ 598,
612
+ 599,
613
+ 600,
614
+ 601,
615
+ 602,
616
+ 603,
617
+ 604,
618
+ 605,
619
+ 606,
620
+ 607,
621
+ 608,
622
+ 609,
623
+ 610,
624
+ 611,
625
+ 612,
626
+ 613,
627
+ 614,
628
+ 615,
629
+ 616,
630
+ 617,
631
+ 618,
632
+ 619,
633
+ 620,
634
+ 621,
635
+ 622,
636
+ 623,
637
+ 624,
638
+ 625,
639
+ 626,
640
+ 627,
641
+ 628,
642
+ 629,
643
+ 630,
644
+ 631,
645
+ 632,
646
+ 633,
647
+ 634,
648
+ 635,
649
+ 636,
650
+ 637,
651
+ 638,
652
+ 639,
653
+ 640,
654
+ 641,
655
+ 642,
656
+ 643,
657
+ 644,
658
+ 645,
659
+ 646,
660
+ 647,
661
+ 648,
662
+ 649,
663
+ 650,
664
+ 651,
665
+ 652,
666
+ 653,
667
+ 654,
668
+ 655,
669
+ 656,
670
+ 657,
671
+ 658,
672
+ 659,
673
+ 660,
674
+ 661,
675
+ 662,
676
+ 663,
677
+ 664,
678
+ 665,
679
+ 666,
680
+ 667,
681
+ 668,
682
+ 669,
683
+ 670,
684
+ 671,
685
+ 672,
686
+ 673,
687
+ 674,
688
+ 675,
689
+ 676,
690
+ 677,
691
+ 678,
692
+ 679,
693
+ 680,
694
+ 681,
695
+ 682,
696
+ 683,
697
+ 684,
698
+ 685,
699
+ 686,
700
+ 687,
701
+ 688,
702
+ 689,
703
+ 690,
704
+ 691,
705
+ 692,
706
+ 693,
707
+ 694,
708
+ 695,
709
+ 696,
710
+ 697,
711
+ 698,
712
+ 699,
713
+ 700,
714
+ 701,
715
+ 702,
716
+ 703,
717
+ 704,
718
+ 705,
719
+ 706,
720
+ 707,
721
+ 708,
722
+ 709,
723
+ 710,
724
+ 711,
725
+ 712,
726
+ 713,
727
+ 714,
728
+ 715,
729
+ 716,
730
+ 717,
731
+ 718,
732
+ 719,
733
+ 720,
734
+ 721,
735
+ 722,
736
+ 723,
737
+ 724,
738
+ 725,
739
+ 726,
740
+ 727,
741
+ 728,
742
+ 729,
743
+ 730,
744
+ 731,
745
+ 732,
746
+ 733,
747
+ 734,
748
+ 735,
749
+ 736,
750
+ 737,
751
+ 738,
752
+ 739,
753
+ 740,
754
+ 741,
755
+ 742,
756
+ 743,
757
+ 744,
758
+ 745,
759
+ 746,
760
+ 747,
761
+ 748,
762
+ 749,
763
+ 750,
764
+ 751,
765
+ 752,
766
+ 753,
767
+ 754,
768
+ 755,
769
+ 756,
770
+ 757,
771
+ 758,
772
+ 759,
773
+ 760,
774
+ 761,
775
+ 762,
776
+ 763,
777
+ 764,
778
+ 765,
779
+ 766,
780
+ 767,
781
+ 768,
782
+ 769,
783
+ 770,
784
+ 771,
785
+ 772,
786
+ 773,
787
+ 774,
788
+ 775,
789
+ 776,
790
+ 777,
791
+ 778,
792
+ 779,
793
+ 780,
794
+ 781,
795
+ 782,
796
+ 783,
797
+ 784,
798
+ 785,
799
+ 786,
800
+ 787,
801
+ 788,
802
+ 789,
803
+ 790,
804
+ 791,
805
+ 792,
806
+ 793,
807
+ 794,
808
+ 795,
809
+ 796,
810
+ 797,
811
+ 798,
812
+ 799,
813
+ 800,
814
+ 801,
815
+ 802,
816
+ 803,
817
+ 804,
818
+ 805,
819
+ 806,
820
+ 807,
821
+ 808,
822
+ 809,
823
+ 810,
824
+ 811,
825
+ 812,
826
+ 813,
827
+ 814,
828
+ 815,
829
+ 816,
830
+ 817,
831
+ 818,
832
+ 819,
833
+ 820,
834
+ 821,
835
+ 822,
836
+ 823,
837
+ 824,
838
+ 825,
839
+ 826,
840
+ 827,
841
+ 828,
842
+ 829,
843
+ 830,
844
+ 831,
845
+ 832,
846
+ 833,
847
+ 834,
848
+ 835,
849
+ 836,
850
+ 837,
851
+ 838,
852
+ 839,
853
+ 840,
854
+ 841,
855
+ 842,
856
+ 843,
857
+ 844,
858
+ 845,
859
+ 846,
860
+ 847,
861
+ 848,
862
+ 849,
863
+ 850,
864
+ 851,
865
+ 852,
866
+ 853,
867
+ 854,
868
+ 855,
869
+ 856,
870
+ 857,
871
+ 858,
872
+ 859,
873
+ 860,
874
+ 861,
875
+ 862,
876
+ 863,
877
+ 864,
878
+ 865,
879
+ 866,
880
+ 867,
881
+ 868,
882
+ 869,
883
+ 870,
884
+ 871,
885
+ 872,
886
+ 873,
887
+ 874,
888
+ 875,
889
+ 876,
890
+ 877,
891
+ 878,
892
+ 879,
893
+ 880,
894
+ 881,
895
+ 882,
896
+ 883,
897
+ 884,
898
+ 885,
899
+ 886,
900
+ 887,
901
+ 888,
902
+ 889,
903
+ 890,
904
+ 891,
905
+ 892,
906
+ 893,
907
+ 894,
908
+ 895,
909
+ 896,
910
+ 897,
911
+ 898,
912
+ 899,
913
+ 900,
914
+ 901,
915
+ 902,
916
+ 903,
917
+ 904,
918
+ 905,
919
+ 906,
920
+ 907,
921
+ 908,
922
+ 909,
923
+ 910,
924
+ 911,
925
+ 912,
926
+ 913,
927
+ 914,
928
+ 915,
929
+ 916,
930
+ 917,
931
+ 918,
932
+ 919,
933
+ 920,
934
+ 921,
935
+ 922,
936
+ 923,
937
+ 924,
938
+ 925,
939
+ 926,
940
+ 927,
941
+ 928,
942
+ 929,
943
+ 930,
944
+ 931,
945
+ 932,
946
+ 933,
947
+ 934,
948
+ 935,
949
+ 936,
950
+ 937,
951
+ 938,
952
+ 939,
953
+ 940,
954
+ 941,
955
+ 942,
956
+ 943,
957
+ 944,
958
+ 945,
959
+ 946,
960
+ 947,
961
+ 948,
962
+ 949,
963
+ 950,
964
+ 951,
965
+ 952,
966
+ 953,
967
+ 954,
968
+ 955,
969
+ 956,
970
+ 957,
971
+ 958,
972
+ 959,
973
+ 960,
974
+ 961,
975
+ 962,
976
+ 963,
977
+ 964,
978
+ 965,
979
+ 966,
980
+ 967,
981
+ 968,
982
+ 969,
983
+ 970,
984
+ 971,
985
+ 972,
986
+ 973,
987
+ 974,
988
+ 975,
989
+ 976,
990
+ 977,
991
+ 978,
992
+ 979,
993
+ 980,
994
+ 981,
995
+ 982,
996
+ 983,
997
+ 984,
998
+ 985,
999
+ 986,
1000
+ 987,
1001
+ 988,
1002
+ 989,
1003
+ 990,
1004
+ 991,
1005
+ 992,
1006
+ 993,
1007
+ 994,
1008
+ 995,
1009
+ 996,
1010
+ 997,
1011
+ 998,
1012
+ 999,
1013
+ 1000,
1014
+ 1001,
1015
+ 1002,
1016
+ 1003,
1017
+ 1004,
1018
+ 1005,
1019
+ 1006,
1020
+ 1007,
1021
+ 1008,
1022
+ 1009,
1023
+ 1010,
1024
+ 1011,
1025
+ 1012,
1026
+ 1013,
1027
+ 1014,
1028
+ 1015,
1029
+ 1016,
1030
+ 1017,
1031
+ 1018,
1032
+ 1019,
1033
+ 1020,
1034
+ 1021,
1035
+ 1022,
1036
+ 1023,
1037
+ 1024,
1038
+ 1025,
1039
+ 1026,
1040
+ 1027,
1041
+ 1028,
1042
+ 1029,
1043
+ 1030,
1044
+ 1031,
1045
+ 1032,
1046
+ 1033,
1047
+ 1034,
1048
+ 1035,
1049
+ 1036,
1050
+ 1037,
1051
+ 1038,
1052
+ 1039,
1053
+ 1040,
1054
+ 1041,
1055
+ 1042,
1056
+ 1043,
1057
+ 1044,
1058
+ 1045,
1059
+ 1046,
1060
+ 1047,
1061
+ 1048,
1062
+ 1049,
1063
+ 1050,
1064
+ 1051,
1065
+ 1052,
1066
+ 1053,
1067
+ 1054,
1068
+ 1055,
1069
+ 1056,
1070
+ 1057,
1071
+ 1058,
1072
+ 1059,
1073
+ 1060,
1074
+ 1061,
1075
+ 1062,
1076
+ 1063,
1077
+ 1064,
1078
+ 1065,
1079
+ 1066,
1080
+ 1067,
1081
+ 1068,
1082
+ 1069,
1083
+ 1070,
1084
+ 1071,
1085
+ 1072,
1086
+ 1073,
1087
+ 1074,
1088
+ 1075,
1089
+ 1076,
1090
+ 1077,
1091
+ 1078,
1092
+ 1079,
1093
+ 1080,
1094
+ 1081,
1095
+ 1082,
1096
+ 1083,
1097
+ 1084,
1098
+ 1085,
1099
+ 1086,
1100
+ 1087,
1101
+ 1088,
1102
+ 1089,
1103
+ 1090,
1104
+ 1091,
1105
+ 1092,
1106
+ 1093,
1107
+ 1094,
1108
+ 1095,
1109
+ 1096,
1110
+ 1097,
1111
+ 1098,
1112
+ 1099,
1113
+ 1100,
1114
+ 1101,
1115
+ 1102,
1116
+ 1103,
1117
+ 1104,
1118
+ 1105,
1119
+ 1106,
1120
+ 1107,
1121
+ 1108,
1122
+ 1109,
1123
+ 1110,
1124
+ 1111,
1125
+ 1112,
1126
+ 1113,
1127
+ 1114,
1128
+ 1115,
1129
+ 1116,
1130
+ 1117,
1131
+ 1118,
1132
+ 1119,
1133
+ 1120,
1134
+ 1121,
1135
+ 1122,
1136
+ 1123,
1137
+ 1124,
1138
+ 1125,
1139
+ 1126,
1140
+ 1127,
1141
+ 1128,
1142
+ 1129,
1143
+ 1130,
1144
+ 1131,
1145
+ 1132,
1146
+ 1133,
1147
+ 1134,
1148
+ 1135,
1149
+ 1136,
1150
+ 1137,
1151
+ 1138,
1152
+ 1139,
1153
+ 1140,
1154
+ 1141,
1155
+ 1142,
1156
+ 1143,
1157
+ 1144,
1158
+ 1145,
1159
+ 1146,
1160
+ 1147,
1161
+ 1148,
1162
+ 1149,
1163
+ 1150,
1164
+ 1151,
1165
+ 1152,
1166
+ 1153,
1167
+ 1154,
1168
+ 1155,
1169
+ 1156,
1170
+ 1157,
1171
+ 1158,
1172
+ 1159,
1173
+ 1160,
1174
+ 1161,
1175
+ 1162,
1176
+ 1163,
1177
+ 1164,
1178
+ 1165,
1179
+ 1166,
1180
+ 1167,
1181
+ 1168,
1182
+ 1169,
1183
+ 1170,
1184
+ 1171,
1185
+ 1172,
1186
+ 1173,
1187
+ 1174,
1188
+ 1175,
1189
+ 1176,
1190
+ 1177,
1191
+ 1178,
1192
+ 1179,
1193
+ 1180,
1194
+ 1181,
1195
+ 1182,
1196
+ 1183,
1197
+ 1184,
1198
+ 1185,
1199
+ 1186,
1200
+ 1187,
1201
+ 1188,
1202
+ 1189,
1203
+ 1190,
1204
+ 1191,
1205
+ 1192,
1206
+ 1193,
1207
+ 1194,
1208
+ 1195,
1209
+ 1196,
1210
+ 1197,
1211
+ 1198,
1212
+ 1199,
1213
+ 1200,
1214
+ 1201,
1215
+ 1202,
1216
+ 1203,
1217
+ 1204,
1218
+ 1205,
1219
+ 1206,
1220
+ 1207,
1221
+ 1208,
1222
+ 1209,
1223
+ 1210,
1224
+ 1211,
1225
+ 1212,
1226
+ 1213,
1227
+ 1214,
1228
+ 1215,
1229
+ 1216,
1230
+ 1217,
1231
+ 1218,
1232
+ 1219,
1233
+ 1220,
1234
+ 1221,
1235
+ 1222,
1236
+ 1223,
1237
+ 1224,
1238
+ 1225,
1239
+ 1226,
1240
+ 1227,
1241
+ 1228,
1242
+ 1229,
1243
+ 1230,
1244
+ 1231,
1245
+ 1232,
1246
+ 1233,
1247
+ 1234,
1248
+ 1235,
1249
+ 1236,
1250
+ 1237,
1251
+ 1238,
1252
+ 1239,
1253
+ 1240,
1254
+ 1241,
1255
+ 1242,
1256
+ 1243,
1257
+ 1244,
1258
+ 1245,
1259
+ 1246,
1260
+ 1247,
1261
+ 1248,
1262
+ 1249,
1263
+ 1250,
1264
+ 1251,
1265
+ 1252,
1266
+ 1253,
1267
+ 1254,
1268
+ 1255,
1269
+ 1256,
1270
+ 1257,
1271
+ 1258,
1272
+ 1259,
1273
+ 1260,
1274
+ 1261,
1275
+ 1262,
1276
+ 1263,
1277
+ 1264,
1278
+ 1265,
1279
+ 1266,
1280
+ 1267,
1281
+ 1268,
1282
+ 1269,
1283
+ 1270,
1284
+ 1271,
1285
+ 1272,
1286
+ 1273,
1287
+ 1274,
1288
+ 1275,
1289
+ 1276,
1290
+ 1277,
1291
+ 1278,
1292
+ 1279,
1293
+ 1280,
1294
+ 1281,
1295
+ 1282,
1296
+ 1283,
1297
+ 1284,
1298
+ 1285,
1299
+ 1286,
1300
+ 1287,
1301
+ 1288,
1302
+ 1289,
1303
+ 1290,
1304
+ 1291,
1305
+ 1292,
1306
+ 1293,
1307
+ 1294,
1308
+ 1295,
1309
+ 1296,
1310
+ 1297,
1311
+ 1298,
1312
+ 1299,
1313
+ 1300,
1314
+ 1301,
1315
+ 1302,
1316
+ 1303,
1317
+ 1304,
1318
+ 1305,
1319
+ 1306,
1320
+ 1307,
1321
+ 1308,
1322
+ 1309,
1323
+ 1310,
1324
+ 1311,
1325
+ 1312,
1326
+ 1313,
1327
+ 1314,
1328
+ 1315,
1329
+ 1316,
1330
+ 1317,
1331
+ 1318,
1332
+ 1319,
1333
+ 1320,
1334
+ 1321,
1335
+ 1322,
1336
+ 1323,
1337
+ 1324,
1338
+ 1325,
1339
+ 1326,
1340
+ 1327,
1341
+ 1328,
1342
+ 1329,
1343
+ 1330,
1344
+ 1331,
1345
+ 1332,
1346
+ 1333,
1347
+ 1334,
1348
+ 1335,
1349
+ 1336,
1350
+ 1337,
1351
+ 1338,
1352
+ 1339,
1353
+ 1340,
1354
+ 1341,
1355
+ 1342,
1356
+ 1343,
1357
+ 1344,
1358
+ 1345,
1359
+ 1346,
1360
+ 1347,
1361
+ 1348,
1362
+ 1349,
1363
+ 1350,
1364
+ 1351,
1365
+ 1352,
1366
+ 1353,
1367
+ 1354,
1368
+ 1355,
1369
+ 1356,
1370
+ 1357,
1371
+ 1358,
1372
+ 1359,
1373
+ 1360,
1374
+ 1361,
1375
+ 1362,
1376
+ 1363,
1377
+ 1364,
1378
+ 1365,
1379
+ 1366,
1380
+ 1367,
1381
+ 1368,
1382
+ 1369,
1383
+ 1370,
1384
+ 1371,
1385
+ 1372,
1386
+ 1373,
1387
+ 1374,
1388
+ 1375,
1389
+ 1376,
1390
+ 1377,
1391
+ 1378,
1392
+ 1379,
1393
+ 1380,
1394
+ 1381,
1395
+ 1382,
1396
+ 1383,
1397
+ 1384,
1398
+ 1385,
1399
+ 1386,
1400
+ 1387,
1401
+ 1388,
1402
+ 1389,
1403
+ 1390,
1404
+ 1391,
1405
+ 1392,
1406
+ 1393,
1407
+ 1394,
1408
+ 1395,
1409
+ 1396,
1410
+ 1397,
1411
+ 1398,
1412
+ 1399,
1413
+ 1400,
1414
+ 1401,
1415
+ 1402,
1416
+ 1403,
1417
+ 1404,
1418
+ 1405,
1419
+ 1406,
1420
+ 1407,
1421
+ 1408,
1422
+ 1409,
1423
+ 1410,
1424
+ 1411,
1425
+ 1412,
1426
+ 1413,
1427
+ 1414,
1428
+ 1415,
1429
+ 1416,
1430
+ 1417,
1431
+ 1418,
1432
+ 1419,
1433
+ 1420,
1434
+ 1421,
1435
+ 1422,
1436
+ 1423,
1437
+ 1424,
1438
+ 1425,
1439
+ 1426,
1440
+ 1427,
1441
+ 1428,
1442
+ 1429,
1443
+ 1430,
1444
+ 1431,
1445
+ 1432,
1446
+ 1433,
1447
+ 1434,
1448
+ 1435,
1449
+ 1436,
1450
+ 1437,
1451
+ 1438,
1452
+ 1439,
1453
+ 1440,
1454
+ 1441,
1455
+ 1442,
1456
+ 1443,
1457
+ 1444,
1458
+ 1445,
1459
+ 1446,
1460
+ 1447,
1461
+ 1448,
1462
+ 1449,
1463
+ 1450,
1464
+ 1451,
1465
+ 1452,
1466
+ 1453,
1467
+ 1454,
1468
+ 1455,
1469
+ 1456,
1470
+ 1457,
1471
+ 1458,
1472
+ 1459,
1473
+ 1460,
1474
+ 1461,
1475
+ 1462,
1476
+ 1463,
1477
+ 1464,
1478
+ 1465,
1479
+ 1466,
1480
+ 1467,
1481
+ 1468,
1482
+ 1469,
1483
+ 1470,
1484
+ 1471,
1485
+ 1472
1486
+ ],
1487
+ "cpu_predictions_reused_as_cuda": false,
1488
+ "cpu_numerical_equivalence": true,
1489
+ "case_manifest_sha256": "30d35cfb79e809227fd0d255f9b5173ad18e781c7450ed4bbf0211553f8e63bd",
1490
+ "canary_sha256": "c7c9724752aab3f2208b53aad31949580800c0c60e28b187bccbd5d0a3c5e075",
1491
+ "checks": [
1492
+ "all frozen IDs",
1493
+ "original references and official weights unchanged",
1494
+ "CUDA on every step",
1495
+ "exact two causal analyses and retained input SHA256",
1496
+ "20 exact +6..+120h leads",
1497
+ "unshifted finite routes",
1498
+ "20 physical native WP pressure fields",
1499
+ "recomputed original three-way masks and metrics"
1500
+ ]
1501
+ }
evaluation/released_daily/model_1_2_benchmark.json CHANGED
@@ -1,8 +1,8 @@
1
  {
2
  "source": "evaluation/released_daily/released_daily_benchmark.json",
3
- "source_sha256": "79f67a5f4490150cf0ab24d73e5d3cdedb4884d37e86560cbadde1d4ecdafc43",
4
  "chart": "evaluation/released_daily/model_1_2_benchmark.png",
5
- "chart_sha256": "3bd866eede33fc93d36a0a5373a3b1637bf0f56860938c3d5691b9b7dfe770b4",
6
  "metrics": [
7
  "pressure_JMA_hpa",
8
  "mean_track_error_km",
@@ -11,18 +11,43 @@
11
  "values": {
12
  "pressure_JMA_hpa": {
13
  "1.1": 13.53233861138585,
14
- "1.2": 12.837077366789085
 
15
  },
16
  "mean_track_error_km": {
17
  "1.1": 798.4143395733709,
18
- "1.2": 471.2045276140213
 
19
  },
20
  "direction_error_deg": {
21
  "1.1": 51.58419207122625,
22
- "1.2": 34.95994745459279
 
23
  }
24
  },
25
- "deepmind_score": null,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  "zero_fill": false,
27
- "model_forecasts_modified": false
 
28
  }
 
1
  {
2
  "source": "evaluation/released_daily/released_daily_benchmark.json",
3
+ "source_sha256": "adff1baa1dbc38a6b443cfdd436cd7d4893c04241355c9eaf5004f439ce469a4",
4
  "chart": "evaluation/released_daily/model_1_2_benchmark.png",
5
+ "chart_sha256": "a1aec843491af2c81c587410de9d9a478a7aae75c4b79ee4b95d2fd18ef9b2de",
6
  "metrics": [
7
  "pressure_JMA_hpa",
8
  "mean_track_error_km",
 
11
  "values": {
12
  "pressure_JMA_hpa": {
13
  "1.1": 13.53233861138585,
14
+ "1.2": 12.837077366789085,
15
+ "deepmind": 10.197678417354012
16
  },
17
  "mean_track_error_km": {
18
  "1.1": 798.4143395733709,
19
+ "1.2": 471.2045276140213,
20
+ "deepmind": 498.3660837262175
21
  },
22
  "direction_error_deg": {
23
  "1.1": 51.58419207122625,
24
+ "1.2": 34.95994745459279,
25
+ "deepmind": 39.76380497312257
26
  }
27
  },
28
+ "deepmind_status": "complete_verified",
29
+ "deepmind_model": {
30
+ "key": "deepmind",
31
+ "label": "Google DeepMind WeatherNext Cyclones Mini (<2024)",
32
+ "model_checkpoint": "WeatherNextCyclones_Mini_<2024",
33
+ "software_version": "0.3.0",
34
+ "software_commit": "89c4b2a77a1c57b328b909c575550fd2e5aadc9c",
35
+ "trained_through": 2023,
36
+ "resolution_degrees": 1,
37
+ "member_count": 1,
38
+ "member_policy": "One official Mini member, seed 0",
39
+ "checkpoint_sha256": "a1bb151457077248d70a458b1a7b19deacd2926fbcb46eee4ff2691444e3596e",
40
+ "method": "Official predictor and initialized-storm tracker; causal ERA5; RTX 3070 CUDA",
41
+ "status": "complete_verified"
42
+ },
43
+ "models": [
44
+ "1.1",
45
+ "1.2",
46
+ "deepmind"
47
+ ],
48
+ "bars_per_panel": 3,
49
+ "error_bars": false,
50
  "zero_fill": false,
51
+ "model_forecasts_modified": false,
52
+ "publication_audit_sha256": "52c767b46452a29341c024f24a774328ed6fd4169f5f28e923a81e01c641b222"
53
  }
evaluation/released_daily/model_1_2_benchmark.png CHANGED

Git LFS Details

  • SHA256: 3bd866eede33fc93d36a0a5373a3b1637bf0f56860938c3d5691b9b7dfe770b4
  • Pointer size: 131 Bytes
  • Size of remote file: 160 kB

Git LFS Details

  • SHA256: a1aec843491af2c81c587410de9d9a478a7aae75c4b79ee4b95d2fd18ef9b2de
  • Pointer size: 131 Bytes
  • Size of remote file: 203 kB
evaluation/released_daily/released_daily_benchmark.json CHANGED
The diff for this file is too large to render. See raw diff
 
release_tools/import_deepmind_release_results.py ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Audit the returned CUDA ZIP and merge documentation data, without inference.
2
+
3
+ Read immutable local reference forecasts and labels; never execute a model,
4
+ modify a forecast, publish a Site, or extract paths supplied by the archive.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import argparse
9
+ from collections import defaultdict
10
+ import copy
11
+ from datetime import datetime, timezone
12
+ import hashlib
13
+ import io
14
+ import json
15
+ from pathlib import Path, PurePosixPath
16
+ import re
17
+ import zipfile
18
+
19
+ import numpy as np
20
+
21
+ from deepmind_daily_benchmark import (
22
+ COHORT, WEIGHTS, CHECKPOINT, STEP_NS, aggregate, curve_similarity,
23
+ local, pressure_mask, route_metrics,
24
+ )
25
+
26
+ ROOT = Path(__file__).resolve().parents[1]
27
+ CODE_COMMIT = '89c4b2a77a1c57b328b909c575550fd2e5aadc9c'
28
+ MODEL_LABEL = 'Google DeepMind WeatherNext Cyclones Mini (<2024)'
29
+ LEADS = np.arange(6, 121, 6)
30
+
31
+
32
+ def require(condition, message):
33
+ if not condition:
34
+ raise ValueError(message)
35
+
36
+
37
+ def digest(content):
38
+ return hashlib.sha256(content).hexdigest()
39
+
40
+
41
+ def file_sha(path):
42
+ with Path(path).open('rb') as stream:
43
+ return hashlib.file_digest(stream, 'sha256').hexdigest()
44
+
45
+
46
+ def same(actual, expected, context):
47
+ """Compare nested scores without treating missing values as zero."""
48
+ if isinstance(expected, dict):
49
+ require(isinstance(actual, dict) and actual.keys() == expected.keys(), context)
50
+ for key in expected:
51
+ same(actual[key], expected[key], context + '/' + key)
52
+ elif isinstance(expected, list):
53
+ require(isinstance(actual, list) and len(actual) == len(expected), context)
54
+ for index, (a, b) in enumerate(zip(actual, expected)):
55
+ same(a, b, context + '/' + str(index))
56
+ elif expected is None or isinstance(expected, (str, bool)):
57
+ require(actual == expected, context)
58
+ else:
59
+ require(actual is not None and np.isfinite(actual)
60
+ and np.isclose(actual, expected, rtol=0, atol=1e-8), context)
61
+
62
+
63
+ def validate_identity(protocol, receipt, exported):
64
+ require(receipt['status'] == exported['status'] == 'complete_verified', 'Incomplete run')
65
+ require(receipt['verified_daily_cases'] == 1473 and receipt['verified_storms'] == 270,
66
+ 'Incomplete coverage')
67
+ require(receipt['case_indices'] == list(range(1473)), 'Missing or duplicate case IDs')
68
+ require([c['case_index'] for c in protocol['cases']] == list(range(1473)), 'Wrong plan IDs')
69
+ require(protocol['target_daily_cases'] == 1473 and protocol['target_storms'] == 270,
70
+ 'Wrong target scope')
71
+ require(protocol['leads_hours'] == LEADS.tolist(), 'Wrong lead schedule')
72
+ require(protocol['vendor_commit'] == CODE_COMMIT, 'Wrong official software commit')
73
+ require(protocol['resolution_degrees'] == 1 and protocol['trained_through'] == 2023,
74
+ 'Wrong Mini checkpoint generation')
75
+ require(protocol['reference_v12_checkpoint_sha256'] == CHECKPOINT,
76
+ 'Wrong Trackformer reference')
77
+ require(protocol['members'] == receipt['members'] == 1, 'Wrong member count')
78
+ require(protocol['checkpoint_sha256'] == receipt['checkpoint_sha256'] == WEIGHTS,
79
+ 'Wrong official checkpoint')
80
+ require(protocol['cohort_sha256'] == receipt['cohort_sha256']
81
+ == exported['cohort']['sha256'] == COHORT, 'Wrong daily cohort')
82
+ require(not receipt['cpu_predictions_reused_as_cuda'], 'CPU results relabelled as CUDA')
83
+ require(receipt['cpu_numerical_equivalence'], 'Same-runtime numerical gate did not pass')
84
+
85
+
86
+ def merge_snapshot(base, exported, receipt, pressures):
87
+ """Preserve every old 1.1/1.2 score and unsupported metric explicitly."""
88
+ result = copy.deepcopy(base)
89
+ require(all(base['cohort'][k] == v for k, v in exported['cohort'].items()),
90
+ 'Published baseline cohort differs')
91
+ rows = {row['key']: row for row in result['metrics']}
92
+ for row in exported['metrics']:
93
+ target = rows[row['key']]
94
+ for model in ('1.1', '1.2'):
95
+ same(target['values'][model], row['values'][model], 'Original score changed')
96
+ target['values']['deepmind'] = row['values']['deepmind']
97
+ if 'common_lead_points' in row:
98
+ target['coverage']['three_way_valid_issue_leads'] = row['common_lead_points']
99
+ rows['track_error_120h_km']['values']['deepmind'] = (
100
+ exported['aggregate_equal_complete_storm']['route']['deepmind']['track_error_120h_km']['value'])
101
+ model = next(m for m in result['models'] if m['key'] == 'deepmind')
102
+ model.clear()
103
+ model.update(key='deepmind', label=MODEL_LABEL, model_checkpoint='WeatherNextCyclones_Mini_<2024',
104
+ software_version='0.3.0', software_commit=CODE_COMMIT,
105
+ trained_through=2023, resolution_degrees=1, member_count=1,
106
+ member_policy='One official Mini member, seed 0', checkpoint_sha256=WEIGHTS,
107
+ method='Official predictor and initialized-storm tracker; causal ERA5; RTX 3070 CUDA',
108
+ status='complete_verified')
109
+ result['per_lead_track']['deepmind'] = (
110
+ exported['aggregate_equal_complete_storm']['route']['deepmind']['track_error_by_lead_km'])
111
+ for row in result['pressure_curves']:
112
+ row['forecasts']['deepmind'] = pressures[row['case_index']]
113
+ result.update(deepmind_verification=receipt, deepmind_periods=exported['periods'],
114
+ deepmind_interpretation=exported['interpretation'])
115
+ result['notes'].append('WeatherNext Cyclones Mini <2024, software v0.3.0: one member; '
116
+ 'not full-sized WeatherNext. Historic fitting-year overlap; '
117
+ 'recent 2024+ results are separate. DeepMind path/Frechet scores '
118
+ 'and confidence intervals are not supplied by this export.')
119
+ return result
120
+
121
+
122
+ def audit(archive, project, destination):
123
+ destination = destination.resolve()
124
+ require(destination.is_relative_to(Path('/Volumes/D')), 'Diagnostics must stay on D')
125
+ snapshot_path = ROOT / 'evaluation/released_daily/released_daily_benchmark.json'
126
+ base_bytes = snapshot_path.read_bytes()
127
+ base = json.loads(base_bytes)
128
+ groups = defaultdict(list)
129
+ pressures = {}
130
+ shapes = {agency: {m: set() for m in ('1.1', '1.2', 'deepmind')} for agency in ('JMA', 'USA')}
131
+ with zipfile.ZipFile(archive) as bundle:
132
+ require(len(bundle.namelist()) == len(set(bundle.namelist())), 'Duplicate ZIP entries')
133
+ require(bundle.testzip() is None, 'ZIP CRC failure')
134
+
135
+ def read(name):
136
+ require(not PurePosixPath(name).is_absolute() and '..' not in PurePosixPath(name).parts,
137
+ 'Unsafe ZIP path')
138
+ return bundle.read('results/' + name)
139
+
140
+ def load(name):
141
+ return json.loads(read(name))
142
+
143
+ receipt = load('verification.json')
144
+ exported = load('site_export/benchmark.json')
145
+ protocol = load('protocol.json')
146
+ validate_identity(protocol, receipt, exported)
147
+ require(digest(read('verification.json')) == exported['verification_sha256'], 'Receipt hash')
148
+ require(digest(read('protocol.json')) == receipt['protocol_sha256'], 'Protocol hash')
149
+ require(digest(read('case-manifest.json')) == receipt['case_manifest_sha256'], 'Case manifest hash')
150
+ canary = load('canary.json')
151
+ require(digest(read('canary.json')) == receipt['canary_sha256'], 'Canary hash')
152
+ require(canary['field_gate_passed'] and canary['runtime_match']
153
+ and canary['input_bytes_match'] and canary['protocol_match'], 'Canary did not pass')
154
+ require(canary['device']['device_kind'] == 'NVIDIA GeForce RTX 3070', 'Wrong GPU')
155
+ require(not canary['cpu_predictions_reused_as_cuda'], 'Wrong CPU/CUDA provenance')
156
+ case_manifest = load('case-manifest.json')
157
+ require({f['path'] for f in case_manifest['files']} == {
158
+ f'cases/{i:05d}.{ext}' for i in range(1473) for ext in ('npz', 'json')},
159
+ 'Case manifest is not the exact full archive')
160
+ for manifest in (case_manifest, load('site_export/manifest.json')):
161
+ for item in manifest['files']:
162
+ content = read(item['path'])
163
+ require(len(content) == item['bytes'] and digest(content) == item['sha256'],
164
+ 'Manifest mismatch: ' + item['path'])
165
+ for case in protocol['cases']:
166
+ index = case['case_index']
167
+ stem = f'{index:05d}'
168
+ record = load('cases/' + stem + '.json')
169
+ require(all(record.get(k) == v for k, v in case.items()), 'Case identity: ' + stem)
170
+ require(record['status'] == 'complete' and record['members'] == 1
171
+ and record['backend'] == 'cuda' and record['gpu_verified_steps'] == 20
172
+ and record['verified_device_steps'] == 20, 'CUDA/coverage: ' + stem)
173
+ require(record['device']['gpu_matmul_verified']
174
+ and record['device']['device_kind'] == 'NVIDIA GeForce RTX 3070', 'GPU: ' + stem)
175
+ require(record['checkpoint_sha256'] == WEIGHTS
176
+ and record['protocol_sha256'] == receipt['protocol_sha256'], 'Model: ' + stem)
177
+ require(record['input_time_ns'] == [case['issue_ns'] - STEP_NS, case['issue_ns']]
178
+ and not record['future_weather_used'] and not record['future_storm_labels_used'],
179
+ 'Input causality metadata: ' + stem)
180
+ require(re.fullmatch('[0-9a-f]{64}', record['input_state_sha256']) is not None,
181
+ 'Missing saved input hash: ' + stem)
182
+ content = read('cases/' + stem + '.npz')
183
+ require(digest(content) == record['forecast_sha256'], 'Forecast hash: ' + stem)
184
+ reference_content = (project / 'benchmark_daily_storms_1_2/cases' / (stem + '.npz')).read_bytes()
185
+ require(digest(reference_content) == case['original_forecast_sha256'], 'Baseline changed: ' + stem)
186
+ with np.load(io.BytesIO(content), allow_pickle=False) as fields, np.load(
187
+ io.BytesIO(reference_content), allow_pickle=False) as reference:
188
+ require(np.array_equal(fields['lead_hours'], LEADS) and np.array_equal(
189
+ fields['valid_time_ns'], case['issue_ns'] + LEADS * 3600 * 10**9), 'Lead times: ' + stem)
190
+ route = fields['route_lat_lon']
191
+ field = fields['wp_pressure_hpa']
192
+ require(route.shape == (20, 2) and np.isfinite(route).all(), 'Route missing: ' + stem)
193
+ require(field.shape == (20, 61, 81) and np.isfinite(field).all()
194
+ and field.min() >= 800 and field.max() <= 1100, 'Physical fields: ' + stem)
195
+ require(np.array_equal(np.sort(fields['latitude']), np.arange(61))
196
+ and np.array_equal(np.sort(fields['longitude']), np.arange(100, 181)),
197
+ 'Native one-degree grid: ' + stem)
198
+ p = fields['central_pressure_hpa'].copy()
199
+ valid = fields['pressure_valid'].astype(bool)
200
+ require(p.shape == valid.shape == (20,), 'Pressure schedule: ' + stem)
201
+ require(np.all(~valid | (np.isfinite(p) & (p >= 800) & (p <= 1100))),
202
+ 'Invalid pressure marked available: ' + stem)
203
+ require(np.all(valid | ~np.isfinite(p)), 'Unavailable pressure not masked: ' + stem)
204
+ routes = route_metrics({'1.1': reference['v11_local'], '1.2': reference['v12_local'],
205
+ 'deepmind': local(route, case['base_lat'], case['base_lon'])},
206
+ reference['truth_local'])
207
+ same(routes, record['route_metrics'], 'Route scoring: ' + stem)
208
+ source = json.loads((project / 'output/intensity-v12-v11-20261001/cases' / (stem + '.json')).read_bytes())
209
+ pressure_scores = {}
210
+ if source['v11'] is not None:
211
+ curves = {'1.1': np.array([r['central_pressure_hpa'] for r in source['v11']], dtype=float),
212
+ '1.2': np.array(source['v12_pressure_hpa'], dtype=float), 'deepmind': p}
213
+ for agency in ('JMA', 'USA'):
214
+ truth = np.array(source['truth']['pressure_' + agency + '_hpa'], dtype=float)
215
+ mask = pressure_mask(truth, curves)
216
+ pressure_scores[agency] = {'valid_leads': int(mask.sum()), 'models': {}}
217
+ for model, prediction in curves.items():
218
+ similarity = curve_similarity(prediction[mask], truth[mask])
219
+ if similarity is not None:
220
+ shapes[agency][model].add(index)
221
+ pressure_scores[agency]['models'][model] = {
222
+ 'mae_hpa': float(np.abs(prediction[mask] - truth[mask]).mean()) if mask.any() else None,
223
+ 'curve_similarity': similarity,
224
+ 'error_by_lead_hpa': [float(abs(prediction[i] - truth[i])) if mask[i] else None for i in range(20)]}
225
+ same(pressure_scores, record['pressure_metrics'], 'Pressure scoring: ' + stem)
226
+ pressures[index] = [float(value) if ok else None for value, ok in zip(p, valid)]
227
+ groups[case['storm_id']].append(dict(record, route_metrics=routes, pressure_metrics=pressure_scores))
228
+ require(len(groups) == 270 and sum(map(len, groups.values())) == 1473, 'Incomplete storms')
229
+ for agency, models in shapes.items():
230
+ require(models['1.1'] == models['1.2'] == models['deepmind'],
231
+ 'Pressure shape scores do not use the same cases: ' + agency)
232
+ same(aggregate(groups), exported['aggregate_equal_complete_storm'], 'Equal-storm aggregate')
233
+ for period, expected in exported['periods'].items():
234
+ same(aggregate({sid: days for sid, days in groups.items() if days[0]['period'] == period}),
235
+ expected, 'Period scoring: ' + period)
236
+ result = merge_snapshot(base, exported, receipt, pressures)
237
+ destination.mkdir(parents=True, exist_ok=True)
238
+ saved = {}
239
+ for target, original in (
240
+ ('benchmark.json', 'site_export/benchmark.json'), ('verification.json', 'verification.json'),
241
+ ('protocol.json', 'protocol.json'), ('case-manifest.json', 'case-manifest.json'),
242
+ ('canary.json', 'canary.json')):
243
+ content = read(original)
244
+ (destination / target).write_bytes(content)
245
+ saved[target] = digest(content)
246
+ snapshot_content = (json.dumps(result, indent=2, allow_nan=False) + '\n').encode()
247
+ review = dict(status='complete_verified', reviewed_at_utc=datetime.now(timezone.utc).isoformat(),
248
+ archive_sha256=file_sha(archive), verified_daily_cases=1473, verified_storms=270,
249
+ hashed_case_files=2946, verified_physical_pressure_grids=1473 * 20,
250
+ model=MODEL_LABEL, software_version='0.3.0', software_commit=CODE_COMMIT,
251
+ checkpoint_sha256=WEIGHTS, cohort_sha256=COHORT, members=1,
252
+ backend='NVIDIA GeForce RTX 3070 / CUDA',
253
+ all_route_and_pressure_scores_recomputed=True,
254
+ exact_common_curve_case_ids=True, all_original_forecasts_sha256_verified=True,
255
+ causal_input_metadata_and_saved_hashes_verified=True,
256
+ raw_era5_states_in_return_zip=False,
257
+ raw_input_audit_scope='Original worker receipt and saved input hashes/times; '
258
+ 'raw ERA5 states were not returned in this result-only ZIP.',
259
+ new_inference_performed=False, model_weights_changed=False,
260
+ forecasts_modified=False, missing_results_scored_as_zero=0,
261
+ previous_snapshot_sha256=digest(base_bytes), snapshot_sha256=digest(snapshot_content),
262
+ imported_files_sha256=saved,
263
+ period_coverage={period: dict(daily_issues=sum(len(d) for d in groups.values() if d[0]['period'] == period),
264
+ storms=sum(d[0]['period'] == period for d in groups.values())) for period in exported['periods']})
265
+ snapshot_path.write_bytes(snapshot_content)
266
+ (destination / 'publication_audit.json').write_text(json.dumps(review, indent=2) + '\n')
267
+ print(json.dumps(review, indent=2), flush=True)
268
+
269
+
270
+ if __name__ == '__main__':
271
+ parser = argparse.ArgumentParser(description=__doc__)
272
+ parser.add_argument('--archive', type=Path, required=True)
273
+ parser.add_argument('--project', type=Path, default=ROOT.parent)
274
+ parser.add_argument('--output', type=Path, default=ROOT / 'evaluation/deepmind_daily')
275
+ args = parser.parse_args()
276
+ audit(args.archive, args.project, args.output)
release_tools/plot_model_announcement.py CHANGED
@@ -1,10 +1,11 @@
1
- """Three release metrics from frozen scores; pending models have no fake bars."""
2
  import hashlib
3
  import json
4
  from pathlib import Path
5
  import matplotlib
6
  matplotlib.use('Agg')
7
  import matplotlib.pyplot as plt
 
8
 
9
  ROOT = Path(__file__).resolve().parents[1]
10
  SOURCE = ROOT/'evaluation/released_daily/released_daily_benchmark.json'
@@ -15,50 +16,54 @@ def main():
15
  source = json.loads(SOURCE.read_text())
16
  if source['status'] != 'complete_verified' or source['cohort']['daily_issues'] != 1473:
17
  raise ValueError('Chart requires verified daily-cohort results')
 
 
 
 
18
  metrics = {m['key']: m for m in source['metrics']}
 
19
  plt.rcParams.update({'font.family': 'DejaVu Sans', 'font.size': 11,
20
  'axes.spines.top': False, 'axes.spines.right': False,
21
  'axes.spines.left': False, 'axes.spines.bottom': False})
22
- fig, axes = plt.subplots(1, 3, figsize=(13.8, 5.7))
23
  fig.set_facecolor('#f6f8fc')
24
  specs = [('pressure_JMA_hpa', 'Pressure intensity', 'Central-pressure MAE · hPa', 18, 2),
25
  ('mean_track_error_km', 'Track position', 'Mean position error · km', 1050, 1),
26
  ('direction_error_deg', 'Track direction', 'Six-hour heading error · degrees', 65, 2)]
27
  for ax, (key, title, label, maximum, digits) in zip(axes, specs):
28
  row = metrics[key]
29
- values = [row['values'][k] for k in ('1.1', '1.2')]
 
 
30
  ax.set_facecolor('#f6f8fc')
31
  ax.set_axisbelow(True)
32
  ax.grid(axis='y', color='#dfe5ee', linewidth=.8)
33
- ax.bar([0, 1], values, width=.53, color=['#9aa9bc', '#3c67d6'], zorder=3)
34
- if key == 'pressure_JMA_hpa':
35
- intervals = [row['intervals'][k] for k in ('1.1', '1.2')]
36
- ax.errorbar([0, 1], values, yerr=[[v-low for v, (low, high) in zip(values, intervals)],
37
- [high-v for v, (low, high) in zip(values, intervals)]],
38
- fmt='none', color='#253853', capsize=5, linewidth=1.2, zorder=4)
39
  for x, value in enumerate(values):
40
- top = row['intervals'][('1.1', '1.2')[x]][1] if key == 'pressure_JMA_hpa' else value
41
- ax.text(x, top+maximum*.038, f'{value:,.{digits}f}', ha='center',
42
  fontsize=17, fontweight='bold', color='#21334c')
43
  ax.set_ylim(0, maximum)
44
- ax.set_xticks([0, 1], ['1.1', '1.2 · mean of 50'])
45
  ax.tick_params(axis='both', length=0, labelcolor='#53647c')
46
  ax.set_title(title, loc='left', fontsize=16, fontweight='bold', color='#21334c', pad=38)
47
  ax.text(0, 1.03, label, transform=ax.transAxes, color='#53647c', fontsize=10)
48
  coverage = row['coverage']
49
- ax.text(.5, -.16, f"{coverage['daily_issues']:,} daily starts / {coverage['storms']} storms",
50
  transform=ax.transAxes, ha='center', color='#53647c', fontsize=10)
51
- fig.text(.055, .945, 'Trackformer 1.2', fontsize=23, fontweight='bold', color='#182b45')
52
  fig.text(.055, .895, 'Matched five-day forecasts · equal weight per storm · lower is better', fontsize=12, color='#53647c')
53
- fig.text(.055, .095, 'Pressure: JMA reference; bars show 95% whole-storm intervals. Paired improvement is uncertain.', fontsize=10, color='#53647c')
54
- fig.text(.055, .057, 'DeepMind Mini: matched run in progress — no score yet. Different pipelines/member policies; development evidence.', fontsize=10, color='#53647c')
55
- fig.subplots_adjust(left=.055, right=.975, top=.735, bottom=.25, wspace=.36)
56
  fig.savefig(DEST, dpi=180, facecolor=fig.get_facecolor())
57
  plt.close(fig)
58
  receipt = {'source': SOURCE.relative_to(ROOT).as_posix(), 'source_sha256': hashlib.sha256(SOURCE.read_bytes()).hexdigest(),
59
  'chart': DEST.relative_to(ROOT).as_posix(), 'chart_sha256': hashlib.sha256(DEST.read_bytes()).hexdigest(),
60
  'metrics': [s[0] for s in specs], 'values': {k: metrics[k]['values'] for k, *_ in specs},
61
- 'deepmind_score': None, 'zero_fill': False, 'model_forecasts_modified': False}
 
 
 
62
  DEST.with_suffix('.json').write_text(json.dumps(receipt, indent=2)+'\n')
63
  print(json.dumps(receipt, indent=2))
64
 
 
1
+ """Three release metrics from the independently audited three-model cohort."""
2
  import hashlib
3
  import json
4
  from pathlib import Path
5
  import matplotlib
6
  matplotlib.use('Agg')
7
  import matplotlib.pyplot as plt
8
+ import numpy as np
9
 
10
  ROOT = Path(__file__).resolve().parents[1]
11
  SOURCE = ROOT/'evaluation/released_daily/released_daily_benchmark.json'
 
16
  source = json.loads(SOURCE.read_text())
17
  if source['status'] != 'complete_verified' or source['cohort']['daily_issues'] != 1473:
18
  raise ValueError('Chart requires verified daily-cohort results')
19
+ reference = next(m for m in source['models'] if m['key'] == 'deepmind')
20
+ audit = json.loads((ROOT/'evaluation/deepmind_daily/publication_audit.json').read_text())
21
+ if reference['status'] != 'complete_verified' or audit['snapshot_sha256'] != hashlib.sha256(SOURCE.read_bytes()).hexdigest():
22
+ raise ValueError('DeepMind bars require the matching independent publication audit')
23
  metrics = {m['key']: m for m in source['metrics']}
24
+ models = ('1.1', '1.2', 'deepmind')
25
  plt.rcParams.update({'font.family': 'DejaVu Sans', 'font.size': 11,
26
  'axes.spines.top': False, 'axes.spines.right': False,
27
  'axes.spines.left': False, 'axes.spines.bottom': False})
28
+ fig, axes = plt.subplots(1, 3, figsize=(15.2, 6.1))
29
  fig.set_facecolor('#f6f8fc')
30
  specs = [('pressure_JMA_hpa', 'Pressure intensity', 'Central-pressure MAE · hPa', 18, 2),
31
  ('mean_track_error_km', 'Track position', 'Mean position error · km', 1050, 1),
32
  ('direction_error_deg', 'Track direction', 'Six-hour heading error · degrees', 65, 2)]
33
  for ax, (key, title, label, maximum, digits) in zip(axes, specs):
34
  row = metrics[key]
35
+ values = [row['values'][k] for k in models]
36
+ if any(v is None or not np.isfinite(v) or v < 0 for v in values):
37
+ raise ValueError('Missing or invalid metric cannot become a zero bar')
38
  ax.set_facecolor('#f6f8fc')
39
  ax.set_axisbelow(True)
40
  ax.grid(axis='y', color='#dfe5ee', linewidth=.8)
41
+ ax.bar([0, 1, 2], values, width=.55, color=['#9aa9bc', '#3c67d6', '#9073cf'], zorder=3)
 
 
 
 
 
42
  for x, value in enumerate(values):
43
+ ax.text(x, value+maximum*.038, f'{value:,.{digits}f}', ha='center',
 
44
  fontsize=17, fontweight='bold', color='#21334c')
45
  ax.set_ylim(0, maximum)
46
+ ax.set_xticks([0, 1, 2], ['1.1', '1.2\nmean of 50', 'DeepMind Mini\none member'])
47
  ax.tick_params(axis='both', length=0, labelcolor='#53647c')
48
  ax.set_title(title, loc='left', fontsize=16, fontweight='bold', color='#21334c', pad=38)
49
  ax.text(0, 1.03, label, transform=ax.transAxes, color='#53647c', fontsize=10)
50
  coverage = row['coverage']
51
+ ax.text(.5, -.225, f"{coverage['daily_issues']:,} daily starts / {coverage['storms']} storms",
52
  transform=ax.transAxes, ha='center', color='#53647c', fontsize=10)
53
+ fig.text(.055, .945, 'Trackformer 1.2 · matched model comparison', fontsize=23, fontweight='bold', color='#182b45')
54
  fig.text(.055, .895, 'Matched five-day forecasts · equal weight per storm · lower is better', fontsize=12, color='#53647c')
55
+ fig.text(.055, .095, 'DeepMind: WeatherNext Cyclones Mini <2024 · software v0.3.0 · 1° · RTX 3070 CUDA · all 1,473 forecasts verified.', fontsize=10, color='#53647c')
56
+ fig.text(.055, .057, 'Mean errors, not significance claims. Mixed historical/recent cohort; Mini has better recent-only track scores. Different pipelines/member policies.', fontsize=10, color='#53647c')
57
+ fig.subplots_adjust(left=.055, right=.975, top=.735, bottom=.29, wspace=.36)
58
  fig.savefig(DEST, dpi=180, facecolor=fig.get_facecolor())
59
  plt.close(fig)
60
  receipt = {'source': SOURCE.relative_to(ROOT).as_posix(), 'source_sha256': hashlib.sha256(SOURCE.read_bytes()).hexdigest(),
61
  'chart': DEST.relative_to(ROOT).as_posix(), 'chart_sha256': hashlib.sha256(DEST.read_bytes()).hexdigest(),
62
  'metrics': [s[0] for s in specs], 'values': {k: metrics[k]['values'] for k, *_ in specs},
63
+ 'deepmind_status': 'complete_verified', 'deepmind_model': reference,
64
+ 'models': list(models), 'bars_per_panel': 3, 'error_bars': False,
65
+ 'zero_fill': False, 'model_forecasts_modified': False,
66
+ 'publication_audit_sha256': hashlib.sha256((ROOT/'evaluation/deepmind_daily/publication_audit.json').read_bytes()).hexdigest()}
67
  DEST.with_suffix('.json').write_text(json.dumps(receipt, indent=2)+'\n')
68
  print(json.dumps(receipt, indent=2))
69
 
release_tools/sync_public_model_cards.py CHANGED
@@ -40,6 +40,8 @@ SYNC_FILES = (
40
  'release_tools/plot_release_pressure_benchmark.py',
41
  'release_tools/plot_daily_storm_final.py',
42
  'release_tools/plot_model_announcement.py',
 
 
43
  'release_tools/build_mangkhut_gif.py',
44
  'release_tools/deepmind_daily_benchmark.py',
45
  'release_tools/test_deepmind_daily_benchmark.py',
@@ -60,6 +62,12 @@ SYNC_FILES = (
60
  'evaluation/released_daily/pressure_comparison.png',
61
  'evaluation/released_daily/model_1_2_benchmark.png',
62
  'evaluation/released_daily/model_1_2_benchmark.json',
 
 
 
 
 
 
63
  )
64
 
65
 
@@ -172,13 +180,13 @@ def run(output, publish=False):
172
  # immutable commit in the card. Never pin new bytes to the old movie
173
  # revision or let a missing future image render as a stale figure.
174
  assets = api.create_commit(repo_id=REPO, repo_type='model', parent_commit=parent,
175
- commit_message='Publish Trackformer 1.2 announcement assets and matched DeepMind benchmark protocol',
176
  operations=[CommitOperationAdd(path_in_repo=name, path_or_fileobj=str(ROOT/name)) for name in SYNC_FILES])
177
  card_path.write_text(render_card(original.read_text(), github, assets.oid))
178
  receipt['files']['README.md'] = sha(card_path)
179
  receipt['figure_revision'] = assets.oid
180
  committed = api.create_commit(repo_id=REPO, repo_type='model', parent_commit=assets.oid,
181
- commit_message='Introduce Trackformer 1.2 with a focused showcase and verified daily metrics',
182
  operations=[CommitOperationAdd(path_in_repo='README.md', path_or_fileobj=str(card_path))])
183
  for name, expected in receipt['files'].items():
184
  saved = hf_hub_download(REPO, name, revision=committed.oid, cache_dir=CACHE)
 
40
  'release_tools/plot_release_pressure_benchmark.py',
41
  'release_tools/plot_daily_storm_final.py',
42
  'release_tools/plot_model_announcement.py',
43
+ 'release_tools/import_deepmind_release_results.py',
44
+ 'release_tools/test_deepmind_release_results.py',
45
  'release_tools/build_mangkhut_gif.py',
46
  'release_tools/deepmind_daily_benchmark.py',
47
  'release_tools/test_deepmind_daily_benchmark.py',
 
62
  'evaluation/released_daily/pressure_comparison.png',
63
  'evaluation/released_daily/model_1_2_benchmark.png',
64
  'evaluation/released_daily/model_1_2_benchmark.json',
65
+ 'evaluation/deepmind_daily/benchmark.json',
66
+ 'evaluation/deepmind_daily/verification.json',
67
+ 'evaluation/deepmind_daily/publication_audit.json',
68
+ 'evaluation/deepmind_daily/protocol.json',
69
+ 'evaluation/deepmind_daily/case-manifest.json',
70
+ 'evaluation/deepmind_daily/canary.json',
71
  )
72
 
73
 
 
180
  # immutable commit in the card. Never pin new bytes to the old movie
181
  # revision or let a missing future image render as a stale figure.
182
  assets = api.create_commit(repo_id=REPO, repo_type='model', parent_commit=parent,
183
+ commit_message='Publish completed WeatherNext Cyclones Mini daily comparison and audited three-model chart',
184
  operations=[CommitOperationAdd(path_in_repo=name, path_or_fileobj=str(ROOT/name)) for name in SYNC_FILES])
185
  card_path.write_text(render_card(original.read_text(), github, assets.oid))
186
  receipt['files']['README.md'] = sha(card_path)
187
  receipt['figure_revision'] = assets.oid
188
  committed = api.create_commit(repo_id=REPO, repo_type='model', parent_commit=assets.oid,
189
+ commit_message='Update Trackformer 1.2 model card with completed DeepMind CUDA benchmark',
190
  operations=[CommitOperationAdd(path_in_repo='README.md', path_or_fileobj=str(card_path))])
191
  for name, expected in receipt['files'].items():
192
  saved = hf_hub_download(REPO, name, revision=committed.oid, cache_dir=CACHE)
release_tools/test_deepmind_release_results.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Offline publication regressions: no inference, network, or model imports."""
2
+ import copy
3
+ import hashlib
4
+ import json
5
+ import unittest
6
+
7
+ from import_deepmind_release_results import ROOT, merge_snapshot, same, validate_identity
8
+
9
+
10
+ class DeepMindReleaseTest(unittest.TestCase):
11
+ @classmethod
12
+ def setUpClass(cls):
13
+ folder = ROOT/'evaluation/deepmind_daily'
14
+ cls.protocol = json.loads((folder/'protocol.json').read_text())
15
+ cls.receipt = json.loads((folder/'verification.json').read_text())
16
+ cls.export = json.loads((folder/'benchmark.json').read_text())
17
+ cls.base = json.loads((ROOT/'evaluation/released_daily/released_daily_benchmark.json').read_text())
18
+
19
+ def test_exact_completed_model_and_cohort(self):
20
+ validate_identity(self.protocol, self.receipt, self.export)
21
+
22
+ def test_partial_run_cannot_be_published(self):
23
+ receipt = copy.deepcopy(self.receipt)
24
+ receipt['verified_daily_cases'] -= 1
25
+ with self.assertRaisesRegex(ValueError, 'Incomplete coverage'):
26
+ validate_identity(self.protocol, receipt, self.export)
27
+
28
+ def test_missing_and_duplicate_ids_are_rejected(self):
29
+ receipt = copy.deepcopy(self.receipt)
30
+ receipt['case_indices'][-1] = receipt['case_indices'][-2]
31
+ with self.assertRaisesRegex(ValueError, 'duplicate case IDs'):
32
+ validate_identity(self.protocol, receipt, self.export)
33
+
34
+ def test_checkpoint_substitution_is_rejected(self):
35
+ protocol = copy.deepcopy(self.protocol)
36
+ protocol['checkpoint_sha256'] = '0' * 64
37
+ with self.assertRaisesRegex(ValueError, 'official checkpoint'):
38
+ validate_identity(protocol, self.receipt, self.export)
39
+
40
+ def test_cpu_results_cannot_be_relabelled_gpu(self):
41
+ receipt = copy.deepcopy(self.receipt)
42
+ receipt['cpu_predictions_reused_as_cuda'] = True
43
+ with self.assertRaisesRegex(ValueError, 'CPU results relabelled'):
44
+ validate_identity(self.protocol, receipt, self.export)
45
+
46
+ def test_unavailable_does_not_equal_zero(self):
47
+ with self.assertRaises(ValueError):
48
+ same(0, None, 'unavailable')
49
+ with self.assertRaises(ValueError):
50
+ same(None, 0, 'unavailable')
51
+
52
+ def test_original_scores_cannot_change_on_import(self):
53
+ base = copy.deepcopy(self.base)
54
+ next(m for m in base['metrics'] if m['key'] == 'mean_track_error_km')['values']['1.2'] = 0
55
+ with self.assertRaisesRegex(ValueError, 'Original score changed'):
56
+ merge_snapshot(base, self.export, self.receipt, {})
57
+
58
+ def test_mean_of_fifty_and_mini_identity_remain_separate(self):
59
+ models = {m['key']: m for m in self.base['models']}
60
+ self.assertEqual(models['v12']['member_count'], 50)
61
+ self.assertEqual(models['deepmind']['member_count'], 1)
62
+ self.assertEqual(models['deepmind']['software_version'], '0.3.0')
63
+ self.assertEqual(models['deepmind']['model_checkpoint'], 'WeatherNextCyclones_Mini_<2024')
64
+
65
+ def test_audit_matches_imported_bytes_and_chart_snapshot(self):
66
+ folder = ROOT/'evaluation/deepmind_daily'
67
+ audit = json.loads((folder/'publication_audit.json').read_text())
68
+ for name, expected in audit['imported_files_sha256'].items():
69
+ self.assertEqual(hashlib.sha256((folder/name).read_bytes()).hexdigest(), expected)
70
+ self.assertEqual(hashlib.sha256((ROOT/'evaluation/released_daily/released_daily_benchmark.json').read_bytes()).hexdigest(),
71
+ audit['snapshot_sha256'])
72
+ self.assertFalse(audit['raw_era5_states_in_return_zip'])
73
+ self.assertEqual(audit['missing_results_scored_as_zero'], 0)
74
+
75
+ def test_all_published_values_are_actual_completed_export(self):
76
+ rows = {m['key']: m for m in self.base['metrics']}
77
+ for metric in self.export['metrics']:
78
+ self.assertEqual(rows[metric['key']]['values']['deepmind'], metric['values']['deepmind'])
79
+ self.assertNotIn('deepmind', rows['frechet_distance_km']['values'])
80
+ self.assertNotIn('deepmind', rows['path_similarity']['values'])
81
+
82
+
83
+ if __name__ == '__main__':
84
+ unittest.main()
release_tools/test_public_model_cards.py CHANGED
@@ -15,11 +15,15 @@ class PublicModelCardsTest(unittest.TestCase):
15
  self.assertTrue(rendered.startswith(self.header))
16
  for text in ('# Introducing Trackformer 1.2', '1,473 days / 270 storms',
17
  '134 days / 40 storms', '13.53', '12.84',
18
- 'scores are **pending**', 'no native wind-radius forecast head'):
 
19
  self.assertIn(text, rendered)
20
  self.assertNotIn('README revision', rendered)
21
  self.assertNotIn('Corrected pressure forecast', rendered)
22
  self.assertNotIn('Old model card', rendered)
 
 
 
23
 
24
  def test_one_pinned_featured_player(self):
25
  rendered = render_card(self.original, self.source)
@@ -65,7 +69,9 @@ class PublicModelCardsTest(unittest.TestCase):
65
  self.assertIn(path, SYNC_FILES)
66
  for path in ('docs/deepmind_daily_benchmark.md', 'docs/showcase_archive.md',
67
  'evaluation/released_daily/released_daily_benchmark.json',
68
- 'evaluation/released_daily/released_daily_verification.json'):
 
 
69
  self.assertIn(path, SYNC_FILES)
70
  self.assertNotIn('models/trackformer_1_2_field/weights.pt', SYNC_FILES)
71
  self.assertNotIn('paper/trackformer.tex', SYNC_FILES)
 
15
  self.assertTrue(rendered.startswith(self.header))
16
  for text in ('# Introducing Trackformer 1.2', '1,473 days / 270 storms',
17
  '134 days / 40 storms', '13.53', '12.84',
18
+ 'WeatherNext software v0.3.0', '10.20 hPa', '288.5 km',
19
+ 'no native wind-radius forecast head'):
20
  self.assertIn(text, rendered)
21
  self.assertNotIn('README revision', rendered)
22
  self.assertNotIn('Corrected pressure forecast', rendered)
23
  self.assertNotIn('Old model card', rendered)
24
+ self.assertNotIn('scores are **pending**', rendered)
25
+ self.assertIn('Mini, not the full-sized', rendered)
26
+ self.assertIn('recent-only track results favour Mini', rendered)
27
 
28
  def test_one_pinned_featured_player(self):
29
  rendered = render_card(self.original, self.source)
 
69
  self.assertIn(path, SYNC_FILES)
70
  for path in ('docs/deepmind_daily_benchmark.md', 'docs/showcase_archive.md',
71
  'evaluation/released_daily/released_daily_benchmark.json',
72
+ 'evaluation/released_daily/released_daily_verification.json',
73
+ 'evaluation/deepmind_daily/publication_audit.json',
74
+ 'evaluation/deepmind_daily/verification.json'):
75
  self.assertIn(path, SYNC_FILES)
76
  self.assertNotIn('models/trackformer_1_2_field/weights.pt', SYNC_FILES)
77
  self.assertNotIn('paper/trackformer.tex', SYNC_FILES)