radiens_qc.figures
Every figure the package draws, named once, so a caller asks for them by level or name.
The plotting modules each own one kind of drawing and know nothing about each other. This is the one place that knows they exist together: what each figure is called, which level of the data it shows, and which of the package's four objects it takes.
A caller wanting everything says so once::
specs = FIGURES
sources = fetch_figure_sources(vc, dataset, specs, report=report)
save_figures(render(specs, sources), Path("figures"))
Adding a figure is one row here. Nothing else changes -- not an __all__, not
a caller -- which is the point of a registry over a hand-written list at every
call site.
The division of labour this keeps: a figure decides how to draw, the registry decides what exists, and the caller decides what to render and where to put it.
Classes
FigureSources
dataclass
The objects the figures are drawn from, however the caller came by them.
Every field is optional because which ones are needed depends on what was
selected, and because a report read off disk carries no live recording.
:func:render skips a figure whose source is absent rather than failing:
drawing what a saved report can support is a normal thing to do.
FigureSpec
dataclass
One figure: what it is called, what it shows, and how to draw it.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Unique across the whole registry, not merely within a level -- selection and the rendered mapping are both keyed by it, so two figures sharing a name could not be asked for separately. |
level |
Level
|
Which level of the data the figure shows. |
source |
Source
|
Which of the package's objects :attr: |
build |
_Build
|
Draws the figure from a :class: |
caption |
str
|
One line saying what the reader is looking at. |
needs_waveforms |
bool
|
Whether the figure reports unit amplitude, which is
measured from spike waveforms and has no other source. What decides
whether :func: |
RenderOptions
dataclass
Drawing choices a run makes, for the figures that have one to make.
Reaches every figure; one with no choice to make ignores it. That is what keeps a run-wide choice from having to be repeated per row, and what lets a row be added without a caller learning a new argument.
Attributes:
| Name | Type | Description |
|---|---|---|
smooth_sec |
float | None
|
Gaussian time kernel, in seconds, for the figures drawn from
the report's window series -- the stability trend, The rasters deliberately do not take it. Their kernel is already fixed
in seconds rather than scaled to the span, so they need no pinning to
compare, and their panel exists to show bursts -- a width suiting a
drift readout smears the structure they are drawn for. A raster
bandwidth is set by calling :func: |
Functions:
fetch_figure_sources
fetch_figure_sources(
vc,
dataset,
specs,
*,
report,
detection=DEFAULT_DETECTION,
crossings_spikes_id=None,
units_spikes_id=None,
)
Fetch what specs need from the recording, each source at most once.
A source no selected figure asks for is not fetched: each is several requests
and tens of megabytes. Without crossings_spikes_id the events source is
left out and the raw traces carry no crossings; without units_spikes_id
the units source is left out. :func:render skips what is missing.
Waveforms are fetched with the units whenever a selected figure reports amplitude. There is no other source for it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
report
|
QualityReport
|
The measurement the report-backed figures are drawn from.
Computed by the caller, since how it is cached is the caller's
business -- see :func: |
required |
detection
|
DetectionSettings
|
Filters and threshold to read the raw signal and events at. Pass the settings the report was computed with, or the figures describe a differently-detected recording than the report beside them. |
DEFAULT_DETECTION
|
crossings_spikes_id
|
str | None
|
Detect-only fileset for the raw and events levels; see
:mod: |
None
|
units_spikes_id
|
str | None
|
Clustered fileset for the units level. |
None
|
render
Draw each figure whose source sources holds, in registry order.
A figure whose source is absent is skipped rather than raising, because
drawing what a saved report directory supports is a normal mode. The skip is
not silent by construction: the caller has the same predicate, so
[s for s in specs if not sources.has(s.source)] is what was left out.
options reaches every figure; one with no choice to make ignores it.
Keyed by the spec rather than by name so the level and the caption travel
with the figure; {s.name: f for s, f in rendered.items()} is the
one-liner when only names are wanted.
save_figures
Write each figure to <out_dir>/<level>/<name>.png and release it.
Cropped to content, since each figure is sized for what it draws rather than laid out on a fixed sheet. Figures are cleared once written: they are built outside pyplot and so are not registered anywhere, but a full run holds every one of them in memory at once otherwise.