Paper figures improvements - #258
Open
clairemerker wants to merge 28 commits into
Open
clairemerker wants to merge 28 commits into
clairemerker wants to merge 28 commits into
Conversation
A standalone "hero" figure for the paper: a nested zoom from the global forecast to Switzerland to Val Calanca, for 2 m temperature and 10 m wind speed. The global panel carries the high-resolution LAM data over the refined region; the Val Calanca panel renders the true ICON (R19B08) cell mesh via tripcolor. Includes zoom-callout locator boxes/connectors, thinned flow arrows, per-column continuous colorbars, and a --dark poster variant (black background, white text and glow). Runs standalone or via Snakemake: new publication.teaser config block (enabled, init_time, leadtime, dark, grid) drives the publication_teaser rule, added to the publication_all target. Also drop the stale data_download_eckit_geo_grids input from the meteogram rule; that rule was removed with the earthkit v1 upgrade and the dangling reference prevented the workflow from loading.
…s-add-teaser # Conflicts: # config/varda-single_paper_analysis.yaml
… comparison helper Rework notebooks/publication/meteogram.py around an explicit PANELS list: each panel places a param (or a station A-B difference, e.g. PMSL ALT-LUG) at a grid cell, with optional scale/unit/ylabel/zero_line and auto circular wind-direction markers. One render engine covers both single-station custom grids and the multi-station comparison (via a comparison_panels helper). Panel labels (a),(b), … shared legend, page-width aspect. Add the two short single-init inference configs (2025-03-21, 2025-06-27) whose manifests the figures read.
…ecards, scoremaps) Add a per-figure catalog under 'Rendering the figures' describing what each notebook shows, what data it needs, and the files it writes; add scorecards; correct the stored-filename table to the current names (publication_leadtime*, publication_meteogram*, publication_scorecard*, publication_scoremaps*).
- Fixed print widths via evalml.publication.style.figure_width(): 5.7in (2-column) for leadtime/meteogram, 3.35in (1-column) for scoremaps; height kept proportional. - One shared style for every figure (publication.mplstyle): Helvetica -> Liberation Sans fallback, absolute point sizes (8/7/6), thin data lines, thin solid grid, thin axes frame + ticks. Removed per-notebook font bumps so text is identical across figures. - Meteogram: panel-engine refinements - reading-order (row-major) (a)(b)(c) labels, temperatures in degC (per-param offset, skipped for A-B differences), init time in the x-axis label, station-name column subtitles (comparison), figure title moved into the saved filename.
Fix the region-mask spec API (list of shapefile specs), switch the Valais case to hourly deaggregated precip (TOT_PREC1) with a valid-time date axis and a black line, and label the truth as KENDA-CH1. Pin Liberation Sans and thin the shared frame/ticks (0.4/0.3). Document the standalone script and its invocation in the publication-figures guide.
Resolve the scoremaps.py conflict (drop the dead _make_figure builder, keep the fixed 1-column print width) and bring in the stations-scoremaps config.
…igure Add the standalone publication_teaser.py hero-figure renderer (global forecast + nested regional zooms, light/dark variants) as a by-hand CLI script, matching the decoupled plotting architecture. Keep Snakemake at manifest-only — the teaser is run standalone like the other publication figures, so the teaser Snakemake rules from that branch are intentionally not merged. Carry the PublicationTeaserConfig schema alongside the existing scorecards config.
Thin the map frame to the shared 0.4 pt black spine and re-assert the publication style after earthkit's Figure() resets rcParams (which had forced a grey 1.0 pt frame and non-shared fonts); thin the country borders (0.5) and coastlines (0.4). Drop the bold weight and the semi-transparent box on the (a)/(b)/(c) panel labels. Remove PDF export (a vectorised ~1M-point field ran to hundreds of MB); PNG only, at 250 dpi. Give the score column labels two lines with their symbols: 'MSE skill (S)' and 'Bias contribution to MSE skill (S_BIAS)'.
Match the shared style's figure.dpi (250) across the leadtime, meteogram and region figures' PNG exports (were 200).
Shrink the every-6h emphasis markers on the Varda-single and AIFS curves (markersize 5 -> 3) and move the rotated left-column row labels further out (x -0.25 -> -0.33) so they clear the y-tick numbers.
Use the shared publication style (re-asserted after earthkit's Figure() resets rcParams) and size the figure to the exact 2-column print width (5.7 in) by saving without earthkit's default tight bbox. Tie the caption fonts to the shared sizes, and fix the caption to show the initialisation time + lead time (it previously showed valid time + lead, double-counting the lead). Thin the map furniture (global coastlines 0.25, regional coastlines 0.4, region borders 0.4, locator box 0.7, zoom callouts 0.5). Drop PDF export (the ~1M-point forecast fields would balloon a vector PDF); PNG only at 250 dpi.
Pin text/label/tick colours to black and set mathtext.default=regular in the shared style, so earthkit's Figure() (which resets these to grey #333333 and leaves inline math in DejaVu) no longer makes the scoremaps/teaser text look different after the style is re-applied. Style the scoremaps (a)/(b)/(c) panel labels like the meteogram (bold, top-left, base size) and switch the teaser's caption colour to black for cross-figure consistency.
Drop bbox_inches="tight" (which trimmed each figure to a different width) and save at the fixed figsize instead, so every 2-column figure is exactly 5.7 in and every 1-column figure exactly 3.35 in — consistent font sizes when placed to scale. Reserve left margin on the leadtime figure so its rotated row labels stay inside the canvas, and reserve a bottom band on the scoremaps so the '… better' colorbar annotations aren't clipped.
Add an opt-in group_as_header path to the shared scorecard renderer: a (variable, None) sentinel row draws the variable name as a bold subtitle spanning above its metric rows (no dots), freeing the wide left margin the wrapped names used to need. Default stays off, so the operational workflow report is unchanged. Enable it in the publication notebook and retune for print: insert the header sentinels, stop wrapping variable names, drop the 5 in/panel width floor, and size col_width/margins/fonts for a compact 2-column-scale figure. Save at the exact figure size (no tight bbox) and auto-resolve the single candidate.
Set handlelength=3.0 (and handletextpad=0.5) on the shared legend so the dashed ICON-CH1/CH2-EPS-mean line styles are distinguishable from the solid ones.
The teaser runs standalone (CLI args), so it doesn't need a config block; revert this file to match paper-figures.
Switch off the Gridliner lines (child.xlines/ylines) in addition to its labels, so the maps show only the skill field + country/coastline outlines.
Tune the scorecard print layout: header subtitles at 7 pt, metric labels 6 pt, compact rows, tightened title/legend/region-title gaps, small inter-section padding, and wider lead columns (col_width 0.11) so the lead-time labels are legible — landing ~6.5 in wide (spacing all lead columns side-by-side needs a bit more than the 2-column width). Shorten the variable label to 'Tot. precipitation' (hourly / 6-hourly).
New standalone workflow/scripts/plot_region_map.py: shades the three forecast regions (Jura / Swiss Plateau / Alps) over a Copernicus-DEM hillshade and overlays the SwissMetNet stations used in the paper's verification, symbol-coded by observation completeness (all params / without pressure / precip only) with the four case-study sites ringed. The station set is read from the per-parameter station-verification result files (<PARAM>_<lt>_caa0.nc), i.e. the exact coordinates scored per parameter, rather than a raw jretrieve group query. The DEM and result store are read-only. Adds REGION_COLORS (Paul Tol light, colourblind-safe) and region_color() to the shared publication style, and documents the figure in docs/publication_figures.md.
Union the verified stations by their nat_abbr code (the `values` coordinate of the caa0 files) instead of by coordinate: a site logs its sensors a few metres apart, so coordinate matching split one station into two symbols. Union-by-code gives 294 distinct stations (all-params 59 = every pressure station, 134 without pressure, 101 precip-only). Switch the station symbols to open circle / open triangle / cross (black, thin outlines) for clearer shape distinction on the hillshade.
…llshade - Tint the region legend swatches to the on-map colour (fill over the mean relief brightness) so they no longer look pale next to the shaded map. - Case-study marker: drop the centre dot and shrink the ring so the map marker matches the legend exactly (a plain small red ring). - Cache the strided Copernicus DEM subset locally (output/.cache), keyed by extent, so the 5 GB store tile is read only once; re-renders are fast. - Rasterize the hillshade image so the vector PDF stays small (~260 KB) and writes quickly.
Add a 50 km scale bar (SW corner, drawn in the projection's metre units and verified against a geodesic), a north arrow (NE corner), and a light dashed 1-degree lat/lon graticule labelled on the bottom/left, drawn under the borders/stations so it stays subtle.
…ighter layout - Left-align metric/score labels with the parameter-name subtitles. - Grey dividers above and below each parameter name; break the (now grey) region separators across those header bands. - Non-uniform row spacing: tighter metric rows, more room around parameter names. - Trim padding (label-to-first-column gap, inter-card gap, right border) and squeeze column width so the figure hits the 5.7 in two-column target. - Bold parenthesised panel letters (a)/(b) to match the other figures. - Rename precipitation label to 'Total precipitation'.
Rename shared PARAM_LABELS: 'Wind Speed' -> '10m Wind Speed', 'Wind Direction' -> '10m Wind Direction', and 'Sea Level Pressure' -> 'Mean Sea-Level Pressure'. Applies across the scorecard, meteogram, scoremap and leadtime figures.
Add a second output, publication_teaser_comparison.png, placing the Varda-Single forecast next to the corresponding KENDA analysis (same valid time) and their difference, over the Switzerland cutout, for 2 m temperature, 10 m wind and 2 m dew point temperature. Forecast/analysis share one colour scale per field; the difference uses a symmetric diverging scale. Maps sit on a fixed equal-cell grid with colorbar insets so rows stay evenly spaced and the field colorbar clears the difference panel. Loads the regional Varda fields (incl. TD_2M) from the LAM GRIB and the matching KENDA-CH1 analysis step from the anemoi zarr; both render on the shared ICON mesh. Exposed via a --kenda option (defaults to the paper KENDA dataset; '' to skip).
jonasbhend
approved these changes
Sep 7, 2026
jonasbhend
left a comment
Contributor
There was a problem hiding this comment.
Hi @clairemerker. Thanks a lot for the many improvements. I have only minor comments and am happy to merge once these are addressed.
Comment on lines
10
to
12
Contributor
There was a problem hiding this comment.
Suggested change
| - 2025-03-21T00:00 |
I think this emphasizes that a single initialization is run.
Comment on lines
9
to
11
Contributor
There was a problem hiding this comment.
Suggested change
| - 2025-06-27T18:00 |
same as above
| **`scoremaps.py` — Spatial skill-score maps.** 2-D skill maps (MSE skill and the | ||
| bias contribution to it) for each parameter at chosen lead times, candidate vs | ||
| baseline; plus a per-season variant. | ||
| - *Needs:* a **gridded (zarr) truth** manifest with scoremap NC files (produced |
Contributor
There was a problem hiding this comment.
Suggested change
| - *Needs:* truth dataset manifest(s) with scoremap NC files (produced |
scoremaps.py also supports adding scores per station on top of map, or standalone map with just stations.
Contributor
There was a problem hiding this comment.
I am a bit worried that changes to the 'original' scorecard script affect the look of this? Have you checked if the standard scorecard still looks the same / acceptable?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.