Scene construction#

The scene layer is the mutable working state that pipeline steps read and write (canvas, movie, per-cell footprints). Most users never touch it directly; it is public so step authors and notebooks can. finalize() turns a built Scene into a Recording.

Scene#

class minisim.Scene(acq, rng, cells=<factory>, truth=<factory>, snapshots=<factory>, _fill=0.0, _margin_px=0, _movie=None)[source]#

Bases: object

The mutable working state a pipeline of steps mutates in place.

Holds the acquisition (which owns every µm↔px / s↔frame conversion), the RNG every stochastic step draws from, the movie being built, the per-cell records, the per-effect ground-truth side channel, and the optional per-stage snapshots. Unlike a Spec it is not frozen - mutation is the point.

The working movie is held in float64: effects accumulate additively and multiplicatively across ~10 steps in honest radiometric units, and only the final sensor step quantizes to integer counts. The downcast to Output.store_dtype happens in finalize(), not here.

Parameters:
property movie: DataArray#

The working movie, materialized on first access (lazy; see fields above).

property has_movie: bool#

Whether a movie buffer exists yet - True once a pixel step (or a .movie read) has materialized it. finalize uses this to skip the observed-movie cast for a cell-domain-only partial build.

property canvas_shape: tuple[int, int]#

The tissue-canvas (height, width) without materializing the movie.

Equals the movie’s spatial shape once one exists (so a hand-set oversized canvas is honored); otherwise the sensor FOV padded by the motion margin. Lets cell-domain steps (place_neurons, optics) size their grid without forcing the buffer into existence.

classmethod zeros(acq, rng=None, margin_px=0)[source]#

A blank scene whose movie is all zeros - the base for additive builds.

Parameters:
Return type:

Scene

classmethod ones(acq, rng=None, margin_px=0)[source]#

A scene whose movie is all ones - the substrate for multiplicative-field tests.

A vignette or leakage step applied to an all-ones movie yields the bare field, which is exactly what a single-step test inspects.

Parameters:
Return type:

Scene

Cell#

class minisim.Cell(center_um, footprint_planted=None, observed_sigma_px=None, observed_gain=None, trace=None, spikes=None, amplitude=None, bleach=None, in_focus=None, optical_brightness=None, detectable=None)[source]#

Bases: object

One simulated neuron - the per-cell record steps fill in, pre-composite.

The fields mirror the per-cell structural columns of the eventual GroundTruth output one-for-one, so finalize() can stack them with no remapping. Each is populated by the step that owns it and is None until then:

  • center_um - set by place_neurons (the cell exists once it has a location). Placement is now purely spatial; brightness is not set here.

  • footprint_planted - the sharp, peak-normalized soma mask, also from place_neurons; the ideal CNMF target.

  • trace / spikes / amplitude - the noise-free calcium trace C, spike train S, and the per-cell brightness/expression gain that scales the whole trace, all from cell_activity. The gain is biology (how much fluorescence this cell emits per spike); measurement noise, and hence any SNR, emerges later from optics and sensor, not here.

  • bleach - the intact-fluorophore envelope B(t) from the optional bleaching step; composite emits trace · bleach, leaving trace the clean calcium. None until/unless bleaching runs.

  • observed_sigma_px / observed_gain / in_focus / optical_brightness - from the optics step. The observed (optically degraded) footprint is not stored: it is a deterministic function gain · (planted Gaussian(sigma_px)) of the planted footprint (see minisim.footprint.degrade_footprint()), so the optics step keeps only the two scalars and composite / GroundTruth.A_observed regenerate the footprint on demand. in_focus is the geometric in-focus flag and optical_brightness the depth-driven peak-brightness scalar.

  • detectable is not an optics-only property and so is not set by the optics step: it is a whole-pipeline flag (optical brightness × illumination falloff, judged against the sensor noise floor) assembled in finalize().

center_um is (z, y, x) in µm (depth first); pixel coordinates are a conversion away via acq.um_to_px and are not stored, to avoid drift.

Parameters:
observed_footprint()[source]#

The optically degraded footprint, regenerated from the planted one.

Returns the planted footprint blurred + dimmed by the optics step’s scalars (observed_sigma_px/observed_gain), or the planted footprint unchanged when the optics step has not run, or None if the cell has no footprint yet. Regenerated, not stored: it is a deterministic function of the planted footprint (see minisim.footprint.degrade_footprint()), and deep cells’ observed footprints are near-full-canvas, so storing them would dominate memory. composite and GroundTruth.A_observed call this.

Return type:

Footprint | None

GroundTruthBuilder#

class minisim.GroundTruthBuilder(shifts=None, illumination=None, vignette=None, leakage=None, neuropil_temporal=None, neuropil_spatial=None, neuropil_population=None, vasculature_mask=None, focal_depth_um=None)[source]#

Bases: object

Per-effect ground-truth side channel - each non-cell step writes its own.

The per-cell truth lives on Scene.cells; this accumulator holds the per-effect fields that have no natural per-cell home. Each is None until the step that produces it runs, so a None value is the honest signal that the effect is absent from this recording:

  • shifts - rigid (dy, dx) per frame, from brain_motion.

  • illumination / vignette / leakage - the static (height, width) optical fields (excitation falloff, collection falloff, additive glow).

  • neuropil_temporal / neuropil_spatial - the diffuse-background components; neuropil_population - the (frame,) population driver that modulates them (None when no cells were active to drive it).

  • vasculature_mask - the static (height, width) vessel transmission mask from vasculature (None when the step is off / has no layers).

The steps that fill these slots live in minisim.steps, and finalize() reads them into the frozen GroundTruth.

Parameters: