Skip to content

[FIX] Report figures: consistent fonts via figsize↔slot, smaller files, paginated multipanels, clock ±30 / stage1 - #70

Merged
eleanorfrajka merged 1 commit into
mainfrom
fix/report-figures
Aug 12, 2026
Merged

[FIX] Report figures: consistent fonts via figsize↔slot, smaller files, paginated multipanels, clock ±30 / stage1#70
eleanorfrajka merged 1 commit into
mainfrom
fix/report-figures

Conversation

@eleanorfrajka

Copy link
Copy Markdown
Collaborator

Summary

Report figures had small, inconsistent fonts and large files because there was no mapping between a figure's rendered width and its display slot: figures were drawn at arbitrary 12–14 in widths, then CSS capped them to max-width:50%/33%, so a half-slot figure downscaled ~0.43 (not the intended ~0.80) and a 12 pt label showed at ~8 px. This branch introduces a figsize↔slot convention so one font.size renders at one on-screen size everywhere, cuts figure bytes with palette-quantized PNGs, paginates tall multipanel figures so they stop overflowing PDF pages, and fixes several specific figure bugs (clock-alignment window, start/end window data source). It also removes one piece of dead plotting code.

Figure sizing and fonts

Added slot-width constants to oceanarray/config/parameters.pyW_FULL=9.0, W_TWOTHIRDS=6.0, W_HALF=4.5, W_THIRD=3.0 (inches; width only, height stays content-driven). Every figure now sets its width from the constant matching its CSS display slot, so display_px / png_in is constant across the report and fonts are consistent at every slot.

Swept ~24 hardcoded figsize= values across plotters/current.py, ts.py, spectrum.py, primitives.py, hydrography.py and diagnostic.py onto the slot constants, and removed scattered per-figure fontsize= overrides so the mplstyle governs type size.

Updated oceanarray/oceanarray.mplstyle to a single consistent type scale — axes.titlesize 12, axes.labelsize/xtick/ytick 10, font.size 10, legend.fontsize 9 — plus axes.linewidth 0.6 and explicit grid/contour line settings.

savefig.dpi: 150 is retained in the mplstyle as the single source of truth for figure dpi, and the previous REPORT_FIG_DPI = 110 override in _fig_to_base64 (which silently shadowed it — figures were rendering at 110, not 150) is gone. dpi is a size/crispness knob only; displayed font size is set by the figsize↔slot ratio and is dpi-independent.

Smaller figure files

_fig_to_base64 now composites each figure onto white and quantizes it to a 256-colour palette PNG. Report figures are few-colour by construction (line art plus discrete colorbars, which the project already mandates), so indexed PNG is ~visually lossless here and cuts figure bytes roughly 3×, the dominant lever on report and PDF size. Adds an explicit pillow>=9.0 entry to requirements.txt (matplotlib already pulls it in).

Paginated multipanel figures (report-figures #3 / #10)

Tall instrument figures were overflowing PDF pages (a single <img> cannot split across pages). _build_fig_from_ds now accepts a panels= subset; _make_instrument_fig returns a list of base64 PNGs, chunking panels into images of at most _MAX_TS_PANELS (5) each, and the instrument template loops over them. Per-panel height dropped 3.0 → 2.0 so a 5-panel image fits one page without vertical squish.

The same treatment was applied to the start/end windows figure: draw_windows gained a panels= subset arg and now renders at W_FULL with per-panel height 2.0; _make_windows_fig returns a paginated list; the template loops. Each row is a half-width "First 6 h" panel beside a half-width "Last 6 h" panel.

The img.fig { max-height: 22cm } print cap remains as a backstop for any figure that still exceeds a page.

Clock-alignment check (report-figures #4)

plot_clock_offset_check now centres its zoom windows on the deployment and recovery times (±30 min, was 10), and normalises each plotted instrument trace over the plotted window as (x − mean) / std so traces of different amplitude overlay comparably; the y-axis is labelled in standard deviations. The Tier-3 wrapper _make_clock_check_b64 default was corrected from 10 to 30 (it had been shadowing the plotter default).

Start/end windows use stage-1 data

MooringReport._clock_nc_paths and the windows figure now prefer the untrimmed _stage1.nc over stage2/3, falling back only if stage1 is absent. stage2/3 are trimmed to the deployment window, which removes exactly the pre-deploy / post-recover data the ±window check needs to show the deployment/recovery transient; raw clocks also expose the real inter-instrument offsets before correction.

Dead code removal

Removed draw_isopycnal_fig (an unwired time × pressure iso-sigma contour figure with no call site) together with its Tier-3 wrapper _make_isopycnal_fig_b64, the now-orphaned filter_sigma_tukey and pressure_axis imports, its three plotters/__init__.py export references, and stale migration notes in spectrum.py. The grid report's "Isopycnal height above seabed" section is unaffected — it is drawn by the separate, still-wired draw_isopycnal_ts_fig.

Testing

Full suite: 739 passed, 4 skipped. ruff check and ruff format clean. test_plot_guard.py updated so _make_instrument_fig and _make_windows_fig assert a non-empty list (they now paginate). Rendered the dune2 fixture to HTML + combined PDF and visually verified pagination, half-width window columns, and figure crispness.

Breaking changes

oceanarray.plotters.draw_isopycnal_fig removed. It was exported in plotters.__all__ but was dead code with no call site. Migration: none required; nothing called it. The wired isopycnal figure draw_isopycnal_ts_fig is unchanged.

Report HTML output changes shape: the instrument time-series and start/end-windows sections now emit one or more <img> per section (paginated) rather than a single image. Anything that scraped a fixed single figure per section must handle a list.

@eleanorfrajka
eleanorfrajka merged commit aa0c5f4 into main Aug 12, 2026
9 of 10 checks passed
@eleanorfrajka
eleanorfrajka deleted the fix/report-figures branch August 12, 2026 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant