Setting defaults once, with rcParams
I have typed
cmap="viridis"into eleven calls in this notebook. Is there one place I can say it instead?
There is: mnutils.rcParams, a single validated mapping of every
default MNUtils ships. It works the way matplotlib.rcParams does, deliberately — the muscle
memory transfers, including the escape hatches.
| Object | What it does here |
|---|---|
rcParams | the live mapping every MNUtils function reads its defaults from |
rc_context() | applies overrides for one block, then puts them back |
rcdefaults() | restores the built-ins |
rc_presets | named override bundles ("poster", "talk", "paper") |
display_images() | the grid whose panel size the last section retunes |
MRISeries | the anatomical series every example here displays |
get_display_zooms() | the physical (row, col) voxel spacing that keeps the render proportioned |
What is in there¶
import mnutils
from mnutils.GESeries import MRISeries
from mnutils.plotting.images import display_images
from mnutils.testing import build_fake_exam
from mnutils.utils.nifti import get_display_zooms
sorted(mnutils.rcParams)['grid.max_cols',
'grid.max_height',
'grid.panel_height',
'grid.panel_min_height',
'grid.panel_min_width',
'image.ax.xlabel',
'image.ax.xticks',
'image.ax.ylabel',
'image.ax.yticks',
'image.cmap',
'image.mask.colors',
'image.mask.linewidths',
'nifti.orientation',
'nifti.resample.cval',
'nifti.resample.mode',
'nifti.resample.order',
'save.bbox_inches',
'save.dpi',
'save.format',
'save.pad_inches',
'save.transparent',
'spectra.ticker_steps',
'spectra.xlabel',
'spectra.xlim',
'spectra.xticker_bins',
'spectra.ylabel',
'spectra.yticker_bins']Every example below displays one anatomical volume, from a fake exam built on the fly by
mnutils.testing.build_fake_exam -- the same fixtures
the GESeries page uses:
DATA_FOLDER = build_fake_exam("brain_mrs_mrsi_exam") / "data"
t1 = MRISeries(DATA_FOLDER, 2) # 002_3D_Ax_T1_BRAVO
anatomical = t1.images()
zooms = get_display_zooms(t1.nii)
anatomical.shape, zooms((256, 188, 186), (0.8799999952316284, 0.8799999952316284))The names are dotted and grouped by what they configure: image.* for how image panels are drawn,
grid.* for how big the display_images grid gets, spectra.* for spectral axes, nifti.* for
orientation and resampling, save.* for figure saving.
mnutils.rcParams["image.cmap"], mnutils.rcParams["nifti.orientation"]('magma', ('L', 'P', 'S'))Change it for the session¶
Assign, and every later call picks it up:
mnutils.rcParams["image.cmap"] = "viridis"
display_images(anatomical, zooms=zooms, fig_title="viridis, because rcParams says so")An anatomical scan wants "gray", of course -- which is what the next section is for.
Why this works at all — and why it didn’t before
A default that lives in a function signature is evaluated once, at import:
def display_images(..., cmap: str = DEFAULT_PARAMS["cmap"]): # ❌ frozenAssigning to DEFAULT_PARAMS after import mnutils then changes nothing — the signature already
captured the old string. Every MNUtils entry point instead takes None and resolves it in the
body, via resolve_rc():
def display_images(..., cmap: str | None = None): # ✅ read at call time
cmap = resolve_rc(cmap, "image.cmap")That is the whole reason rcParams is a module of its own rather than a dict per module.
Change it for one block¶
A session-wide assignment is the wrong tool when one figure needs different treatment.
rc_context() applies overrides and restores whatever was there
before, exception or not:
with mnutils.rc_context({"image.cmap": "gray"}):
print("inside :", mnutils.rcParams["image.cmap"])
print("outside:", mnutils.rcParams["image.cmap"])inside : gray
outside: viridis
rcdefaults() puts everything back, which is the fastest way out
of a notebook whose defaults have drifted:
mnutils.rcdefaults()
mnutils.rcParams["image.cmap"]'magma'The saving contexts are the same mechanism wearing a name. save_figure(..., context="poster")
applies the "poster" entry of rc_presets through
rc_context — there is no separate poster-parameters dict to keep in sync:
mnutils.rc_presets{'poster': {'save.dpi': 300},
'talk': {'save.transparent': True},
'paper': {'save.dpi': 300, 'save.pad_inches': 0.1}}A typo raises instead of doing nothing¶
Every assignment goes through a validator that owns that key, so the failure lands where the mistake is:
try:
mnutils.rcParams["image.cmpa"] = "gray"
except KeyError as err:
print(err)"'image.cmpa' is not a valid rcParam; did you mean 'image.cmap'?"
try:
mnutils.rcParams["nifti.orientation"] = ("L", "P", "Z")
except ValueError as err:
print(err)invalid value for rcParams['nifti.orientation']: expected three axis codes from AILPRS, got ('L', 'P', 'Z')
Bigger panels for an anatomical series¶
The default grid is tuned for a row of low-resolution multi-nuclear panels. A high-resolution
anatomical slice at that size throws away most of what is in the data — so grid.panel_height
exists, and so does a per-call argument for the one figure that needs it:
mnutils.rcParams["image.cmap"] = "gray"
display_images(anatomical, zooms=zooms, fig_title="default panel height")display_images(anatomical, zooms=zooms, panel_height="30rem", fig_title="panel_height='30rem'")Pass grid_max_height alongside it when the taller panels start scrolling inside their box, and
set mnutils.rcParams["grid.panel_height"] instead when every grid in the notebook should be
bigger.
Precedence runs in the order you would guess, and it is the same for every parameter in this page: