Diagnostics · rebuilt with every publication
Diurnal structure of the error
Under the four common synoptic instants the models do not carry the same bias at every hour of the day. This page publishes that structure and nothing else: it is an observation about these measurements, not yet attributed to a cause. In the window this build covers, the models are furthest apart at 18Z — 3.49 °F between the two extremes — and closest together at 06Z, 1.98 °F apart.
What this page does and does not claim
The three figures below describe a pattern in these measurements. They are not yet attributed to any cause, because the analyses that would separate the candidates have not been run. Three explanations are all consistent with what is drawn here, and this page excludes none of them:
- Model diurnal amplitude — the models may genuinely produce a flatter or sharper daily temperature cycle, in which case the hour-by-hour bias is a property of the forecast system.
- The extreme-sampling penalty — four samples a day cannot see the true daily maximum or minimum, and the size of that penalty depends on the shape of the curve being sampled — the third table below measures it directly (METHODOLOGY §2.3).
- The initial conditions — the same architecture run from GFS and from IFS analyses differs by a large fraction of the effect, which points at near-surface temperature in the analysis rather than at the forecast model.
The full statement, and the ordered list of analyses that would settle it, is methodology §10.2. Until those exist, the correct sentence is that the afternoon bias differs between models and we have not separated model diurnal amplitude, sampling penalty and initial conditions.
| Instant | Local standard time | Roughly |
|---|---|---|
| 00Z | 16:00–19:00 | evening |
| 06Z | 22:00–01:00 | night |
| 12Z | 04:00–07:00 | early morning |
| 18Z | 10:00–13:00 | midday to afternoon |
A. Bias at each synoptic instantt2_00z … t2_18z
Each model is scored at a single instant against the observation at the same instant, so nothing in this figure depends on a model's own daily temperature range or on a definition of a daily extreme. Bars run from a shared zero; positive is too warm. Lead day 1, 90d window, 00Z initialization, bilinear interpolation, 23 stations pooled.
Source: CastCheck 0.3.3, methodology v0.3.1 · ECMWF open data, NOAA/NCEP GFS, NOAA/CIRA AIWP, NWS ASOS · data through 2026-10-28 · CC BY 4.0. Hover a bar for its value and sample size.
The same figure as a table
| Model | 00Z | 06Z | 12Z | 18Z | Spread |
|---|---|---|---|---|---|
| ECMWF IFS HRESifs_hres | −1.50n=87 | −0.69n=88 | −0.52n=88 | +0.19n=87 | 1.69 |
| ECMWF AIFS Singleaifs_single | −0.85n=87 | −1.58n=88 | −1.53n=88 | −0.04n=87 | 1.54 |
| NCEP GFSgfs | −0.34n=87 | +0.19n=88 | +0.68n=88 | +1.15n=87 | 1.50 |
| GraphCast (IFS init)graphcast_ifs | −2.81n=86 | −1.69n=87 | −0.97n=87 | −1.05n=86 | 1.84 |
| GraphCast (GFS init)graphcast_gfs | −3.26n=56 | −1.68n=56 | −0.87n=56 | −2.09n=56 | 2.39 |
| Pangu-Weather (IFS init)pangu_ifs | −2.86n=84 | −1.79n=85 | −0.83n=85 | +0.83n=84 | 3.68 |
| Pangu-Weather (GFS init)pangu_gfs | −2.68n=56 | −1.50n=56 | −0.34n=56 | +0.60n=56 | 3.29 |
| FourCastNet v2 (IFS init)fourcastnet_ifs | −0.97n=87 | −1.46n=88 | −1.45n=88 | −0.64n=87 | 0.82 |
| FourCastNet v2 (GFS init)fourcastnet_gfs | −1.21n=56 | −1.61n=56 | −1.61n=56 | −0.97n=56 | 0.64 |
| Aurora (IFS init)aurora_ifs | −2.58n=82 | −1.50n=83 | −0.87n=83 | −1.29n=82 | 1.70 |
| Aurora (GFS init)aurora_gfs | −3.28n=56 | −1.62n=56 | −0.85n=56 | −2.34n=56 | 2.43 |
| Persistence (baseline)persistence | +0.22n=89 | +0.21n=90 | +0.20n=90 | +0.19n=89 | 0.03 |
B. Bias against lead dayt2, pooled over the four instants
The same instantaneous variable, pooled over all four instants, at every lead day the record covers. A bias that is flat across leads is present in the first forecast hours; one that grows with lead accumulates as the forecast runs. Each line is named where it ends; the two initial-condition variants of one architecture share a colour and are told apart by the dashed stroke. 90d window, 00Z, bilinear.
Source: CastCheck 0.3.3, methodology v0.3.1 · data through 2026-10-28 · CC BY 4.0. Hover a point for its value.
Solid: the first initial-condition variant of a family Dashed: the second variant of the same architecture Grey dotted: the persistence baseline Every line is also labelled at its right-hand end
The same figure as a table
| Model | d1 | d2 | d3 | d4 | d5 | d6 | d7 | d8 | d9 |
|---|---|---|---|---|---|---|---|---|---|
| ECMWF IFS HRESifs_hres | −0.64n=87 | −0.59n=86 | −0.57n=85 | −0.60n=84 | −0.51n=83 | −0.33n=82 | −0.31n=81 | −0.26n=80 | −0.14n=79 |
| ECMWF AIFS Singleaifs_single | −1.00n=87 | −1.00n=86 | −0.96n=85 | −0.92n=84 | −0.81n=83 | −0.85n=82 | −1.16n=81 | −1.14n=80 | −0.51n=79 |
| NCEP GFSgfs | +0.41n=87 | +0.39n=86 | +0.49n=85 | +0.42n=84 | +0.33n=83 | +0.41n=82 | +0.35n=81 | +0.10n=80 | −0.60n=79 |
| GraphCast (IFS init)graphcast_ifs | −1.64n=86 | −1.71n=86 | −1.68n=86 | −1.67n=86 | −1.70n=86 | −1.63n=86 | −1.83n=86 | −1.95n=86 | −1.88n=86 |
| GraphCast (GFS init)graphcast_gfs | −1.97n=56 | −2.13n=55 | −2.24n=54 | −2.32n=55 | −2.18n=56 | −2.16n=55 | −2.16n=55 | −2.31n=55 | −2.45n=55 |
| Pangu-Weather (IFS init)pangu_ifs | −1.16n=84 | −1.34n=84 | −1.47n=84 | −1.56n=84 | −1.77n=84 | −1.86n=84 | −2.07n=84 | −2.15n=84 | −1.71n=84 |
| Pangu-Weather (GFS init)pangu_gfs | −0.98n=56 | −1.23n=55 | −1.40n=54 | −1.50n=55 | −1.59n=56 | −1.58n=55 | −1.67n=55 | −1.89n=55 | −1.66n=55 |
| FourCastNet v2 (IFS init)fourcastnet_ifs | −1.14n=87 | −1.14n=87 | −1.15n=87 | −1.13n=87 | −1.12n=87 | −1.18n=87 | −1.35n=87 | −1.45n=87 | −1.35n=87 |
| FourCastNet v2 (GFS init)fourcastnet_gfs | −1.34n=56 | −1.35n=55 | −1.32n=54 | −1.31n=55 | −1.37n=56 | −1.35n=55 | −1.37n=55 | −1.45n=55 | −1.37n=55 |
| Aurora (IFS init)aurora_ifs | −1.57n=82 | −1.72n=82 | −1.80n=82 | −1.84n=81 | −1.86n=81 | −1.66n=81 | −1.54n=81 | −1.50n=81 | −1.16n=81 |
| Aurora (GFS init)aurora_gfs | −2.02n=56 | −2.38n=55 | −2.67n=54 | −2.96n=55 | −3.17n=56 | −3.33n=55 | −3.47n=55 | −3.71n=55 | −3.82n=55 |
| Persistence (baseline)persistence | +0.20n=89 | +0.39n=89 | +0.60n=89 | +0.84n=89 | +1.03n=89 | +1.21n=89 | +1.40n=89 | +1.56n=89 | +1.79n=89 |
C. The sampling penalty, model by model
The like-for-like extreme tmax_s scores a model's four forecast samples against the highest of the four observations at the same instants; tmax_cli scores exactly the same four forecast samples against the true NWS daily maximum. The difference is the sampling penalty, in °F, at lead day 1.
How to read the last column. Both terms are formed from the same forecast value, so the forecast cancels and the difference is the gap between the two truth definitions over the days and stations that model was scored on. Read the level of each column for a model's own diurnal behaviour and the sample sizes for why the differences are not identical.
| Model | tmax_s vs tmax_cli | tmin_s vs tmin_cli | ||||||
|---|---|---|---|---|---|---|---|---|
| tmax_s | tmax_cli | Penalty | n | tmin_s | tmin_cli | Penalty | n | |
| NCEP GFSgfs | +0.57 | −2.17 | −2.73 | 87cli n=87 | +0.78 | +2.38 | +1.60 | 87cli n=87 |
| ECMWF AIFS Singleaifs_single | −0.42 | −3.15 | −2.73 | 87cli n=87 | −1.34 | +0.26 | +1.61 | 87cli n=87 |
| ECMWF IFS HRESifs_hres | −0.67 | −3.39 | −2.72 | 87cli n=87 | −0.38 | +1.23 | +1.61 | 87cli n=87 |
| FourCastNet v2 (IFS init)fourcastnet_ifs | −1.41 | −4.14 | −2.72 | 87cli n=87 | −1.08 | +0.54 | +1.62 | 87cli n=87 |
| FourCastNet v2 (GFS init)fourcastnet_gfs | −1.65 | −4.37 | −2.72 | 56cli n=56 | −1.21 | +0.37 | +1.59 | 56cli n=56 |
| Pangu-Weather (IFS init)pangu_ifs | −0.39 | −3.10 | −2.71 | 84cli n=84 | −0.83 | +0.80 | +1.63 | 84cli n=84 |
| Pangu-Weather (GFS init)pangu_gfs | −0.54 | −3.25 | −2.71 | 56cli n=56 | −0.42 | +1.17 | +1.59 | 56cli n=56 |
| Aurora (GFS init)aurora_gfs | −3.19 | −5.90 | −2.71 | 56cli n=56 | −0.59 | +0.99 | +1.58 | 56cli n=56 |
| GraphCast (GFS init)graphcast_gfs | −2.93 | −5.63 | −2.71 | 56cli n=56 | −0.63 | +0.96 | +1.58 | 56cli n=56 |
| GraphCast (IFS init)graphcast_ifs | −1.93 | −4.64 | −2.70 | 86cli n=86 | −0.82 | +0.79 | +1.61 | 86cli n=86 |
| Aurora (IFS init)aurora_ifs | −2.14 | −4.85 | −2.70 | 82cli n=82 | −0.69 | +0.92 | +1.62 | 82cli n=82 |
| Persistence (baseline)persistence | +0.20 | +0.19 | −0.01 | 89cli n=89 | +0.20 | +0.20 | +0.01 | 89cli n=89 |
This comparison scores four 6-hourly forecast samples against the true daily extreme, so it includes a sampling penalty. The size of that penalty depends on each model's own diurnal amplitude, which is one of the things this site measures, so these numbers are published for operational relevance and are never used for ranking.
These numbers move
Every figure and table on this page is rebuilt from scratch on each publication, over a rolling 90d window, so the sample behind it grows every day and the ordering of models can change. Nothing here is a fixed result: the record is short, the confidence intervals published on the leaderboard are wide, and a difference visible today may not survive another month of data. The JSON carries the same numbers with their sample sizes, and each row links to the model page where the intervals live. Next rebuild: .