Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Generated report HTML: collapse in diffs, exclude from GitHub language stats.
tests/fixtures/golden/** linguist-generated=true
docs/source/_static/demo/** linguist-generated=true
97 changes: 81 additions & 16 deletions oceanarray/config/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
# ---------------------------------------------------------------------------
PACKAGE_NAME = "oceanarray"

#: Height (inches) of one gridded-section / time-series panel row at full width.
#: Matches the per-row height of the two-row "velocity at depth" figure (5" / 2),
#: so stacked grid panels and single-row section figures share one scale and do
#: not render over-tall.
GRID_PANEL_ROW_IN: float = 2.5

# ---------------------------------------------------------------------------
# Matplotlib style path (used by plotters via plt.style.use)
# ---------------------------------------------------------------------------
Expand All @@ -38,22 +44,9 @@
FIGURE_SIZE_WIDE = (14, 6) # multi-instrument overview (scatter / line)
FIGURE_SIZE_TALL = (12, 8) # stacked single-instrument panels

# ---------------------------------------------------------------------------
# Report figure slot widths (inches). The HTML report body is ~1150-1200px
# wide; figures display at full/two-thirds/half/third of that slot via the
# `.fig` CSS max-width caps. Rendering a figure at the matching slot WIDTH
# makes displayed font size depend only on figsize (font_px = pt/72 x
# display_px/fig_in) — independent of dpi — so mplstyle fonts appear at a
# consistent, readable size instead of the double-shrink that oversized (12-16
# in) figsizes caused at half/third slots. Set figure *width* to one of these;
# height is content-driven. (dpi is a separate size knob, set once in the
# mplstyle's savefig.dpi; report figure bytes are cut mainly by palette
# quantization in _fig_to_base64, not by dpi.)
# ---------------------------------------------------------------------------
W_FULL = 9.0 # full-slot figure (CSS max-width 100%)
W_TWOTHIRDS = 6.0 # two-thirds slot (~66%)
W_HALF = 4.5 # half slot (~50%)
W_THIRD = 3.0 # one-third slot (~33%)
# Report figure slot widths (W_FULL / W_TWOTHIRDS / W_HALF / W_THIRD, inches) now
# live in ``oceanarray.config.report_tokens`` as the single source of truth
# (derived from SLOTS; spec §11). Import them from there, not from here.

# ---------------------------------------------------------------------------
# Resampling
Expand Down Expand Up @@ -540,6 +533,57 @@
k: v["cmap"] for k, v in VARIABLES.items() if v.get("cmap") is not None
}

#: Colormaps for colouring *lines* (one per instrument, deep-first) — distinct
#: from the pcolormesh field maps in :data:`CMAPS_BY_VARIABLE`, because a field
#: map that is fine for a filled panel can be wrong for overlaid lines (e.g. a
#: diverging map's pale midpoint washes lines out). Sampled deep→shallow with
#: washed-out colours skipped by luminance (see
#: :func:`oceanarray.plotters.helpers.ordered_line_colors`). Directions are
#: chosen so the deepest instrument gets the darkest/most-saturated colour:
#: temperature blue(cold/deep)→red(warm/shallow); pressure dark→lighter blue
#: (bathymetry convention, deep = dark); salinity starts at the blue end.
LINE_CMAPS_BY_VARIABLE: dict[str, str] = {
"temperature": "RdBu_r",
"pressure": "Blues_r",
"salinity": "YlGnBu_r",
# Velocity lines are ordered by depth, so shade them like pressure (dark =
# deep) — the field map's red/blue diverging scale means north/south, which is
# meaningless for a per-instrument line ordering.
"east_velocity": "Blues_r",
"north_velocity": "Blues_r",
"up_velocity": "Blues_r",
}

#: One colourblind-safe colour per variable, for **single-instrument** panels
#: where each variable is drawn as one line (not the multi-instrument stack, which
#: uses :data:`LINE_CMAPS_BY_VARIABLE`). Physics use the Okabe-Ito palette (Wong,
#: Nature Methods 8:441, 2011); biogeochemistry uses the Paul Tol palette. Look up
#: with ``VAR_COLORS.get(var, "#000000")``. Mirrors ctdcast's ``VAR_COLORS``.
VAR_COLORS: dict[str, str] = {
# Physics — Okabe-Ito
"temperature": "#56B4E9", # sky blue
"conservative_temperature": "#56B4E9",
"salinity": "#E69F00", # orange
"absolute_salinity": "#E69F00",
"conductivity": "#44AA99", # teal (Paul Tol) — readable stand-in
"potential_density": "#009E73", # bluish green
"pressure": "#000000", # black
"depth": "#000000",
"n2": "#000000",
"east_velocity": "#D55E00", # vermillion (U)
"u": "#D55E00",
"north_velocity": "#0072B2", # blue (V)
"v": "#0072B2",
"up_velocity": "#CC79A7", # reddish purple (W)
"w": "#CC79A7",
"speed": "#D55E00",
# Biogeochemistry — Paul Tol
"dissolved_oxygen": "#332288", # indigo
"dissolved_oxygen_ml_l": "#332288",
"oxygen_saturation_pct": "#332288",
"turbidity": "#661100", # dark red
}


def vlabel(var: str, prefix: str = "") -> str:
"""Return a matplotlib axis label for *var* from the :data:`VARIABLES` registry.
Expand Down Expand Up @@ -567,3 +611,24 @@ def vlabel(var: str, prefix: str = "") -> str:
lbl = f"{prefix}{entry.get('label', var)}"
lu = entry.get("label_units", "")
return f"{lbl} ({lu})" if lu else lbl


def vunit(var: str) -> str:
"""Return the axis-label units string for *var* from :data:`VARIABLES`.

This is the ``label_units`` component alone (e.g. ``"°C"``, ``"dbar"``),
suitable for a units-only colorbar title. Returns an empty string for a
dimensionless quantity or an unknown variable.

Parameters
----------
var : str
Variable name (key in :data:`VARIABLES`).

Returns
-------
str
The unit string, or ``""`` when none is registered.

"""
return VARIABLES.get(var, {}).get("label_units", "")
33 changes: 33 additions & 0 deletions oceanarray/config/report_tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,39 @@
ANNOT_FS: int = 8 # in-axes annotation / panel-label text boxes
CAST_LABEL_FS: int = 6 # dense in-axes cast-number labels on maps and sections

# ---------------------------------------------------------------------------
# Figure line widths — GMT named pen-width ladder (points)
# ---------------------------------------------------------------------------
# matplotlib linewidths are in points, the same unit as GMT's pen widths, so
# plotters name line weights from GMT's ladder (``pen("thin")``) instead of
# hardcoding numbers. Values verified against the GMT line tutorial:
# https://www.generic-mapping-tools.org/gmt-examples/tutorials/basics/line.html
# The "no stray typography" test allow-lists the pen() helper.
GMT_PEN: dict[str, float] = {
"faint": 0.0,
"thinnest": 0.25,
"default": 0.25,
"thinner": 0.5,
"thin": 0.75,
"thick": 1.0,
"thicker": 1.5,
"thickest": 2.0,
"fat": 3.0,
"fatter": 6.0,
"fattest": 10.0,
"wide": 18.0,
}


def pen(name: str) -> float:
"""Return a matplotlib linewidth in points for a GMT pen-width *name*.

Borrows GMT's named pen ladder (``faint`` … ``wide``) so plotters name line
weights (``lw=pen("thin")``) rather than hardcoding numbers.
"""
return GMT_PEN[name]


# ---------------------------------------------------------------------------
# Spacing and radii (spec §15) [data; applied by emit_css() in rep/vis-system]
# ---------------------------------------------------------------------------
Expand Down
3 changes: 1 addition & 2 deletions oceanarray/plotters/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@

These three are the only remaining plotter.py entries — kept alive for the
CLI (``oceanarray plot`` / ``process --plot``) pending their redesign as a
file-oriented ``oceanarray plot <file>`` (§11). See the migration checklist
at .claude/plotters_update-20260718.md.
file-oriented ``oceanarray plot <file>`` (§11).

Future
------
Expand Down
Loading
Loading