Layout

Provides the on-disk contract of the cindra pipelines: the directory and file names every stage writes under a caller-supplied output root, and the pure resolvers that build a path from that root. This module imports nothing from cindra, so every layer from the configuration dataclasses upward reads the contract from one definition.

cindra.layout.ACQUISITION_PARAMETERS_FILENAME: str = 'acquisition_parameters.yaml'

The name of the resolved acquisition parameters file, written into the recording’s output directory.

cindra.layout.CHANNEL_1_BINARY_FILENAME: str = 'channel_1_data.bin'

The name of the binary holding the functional channel frames of one imaging plane.

cindra.layout.CHANNEL_2_BINARY_FILENAME: str = 'channel_2_data.bin'

The name of the binary holding the second channel frames of one imaging plane.

cindra.layout.COMBINED_METADATA_FILENAME: str = 'combined_metadata.npz'

The name of the archive holding the combined plane geometry, which doubles as the single-recording completion marker.

Notes

The combination stage writes this archive after its payload arrays and publishes it through an atomic write, so a consumer that finds it can rely on every array it describes already being on disk.

cindra.layout.DEFORMED_MASKS_FILENAME: str = 'registration_deformed_masks.npz'

The name of the archive holding the ROI masks deformed into the shared visual space.

cindra.layout.DETECTION_DATA_DIRECTORY_NAME: str = 'detection_data'

The name of the directory holding the mean, enhanced mean, maximum projection, and correlation images.

class cindra.layout.DetectionImages(*values)

Bases: StrEnum

Defines the names of the summary images the detection stage writes into its own subdirectory.

CORRELATION_MAP = 'correlation_map.npy'

The maximum activity of every pixel across the detection scale pyramid, zero outside the valid registration crop.

ENHANCED_MEAN_IMAGE = 'enhanced_mean_image.npy'

The mean image filtered at the detected ROI scale, filled with the enhanced interior’s minimum value outside the valid registration crop.

MAXIMUM_PROJECTION = 'maximum_projection.npy'

The maximum of every pixel across the temporally binned and high-pass filtered movie, zero outside the valid registration crop.

MEAN_IMAGE = 'mean_image.npy'

The mean of the temporally binned movie, which excludes the frames registration marked bad, zero outside the valid registration crop.

cindra.layout.MULTI_RECORDING_ARRAYS_DIRECTORY_NAME: str = 'registration_arrays'

The name of the directory holding the multi-recording deformation fields and transformed reference images.

cindra.layout.MULTI_RECORDING_CONFIGURATION_FILENAME: str = 'multi_recording_configuration.yaml'

The name of the multi-recording configuration file, written into the dataset directory of the main recording, which is the first of the dataset’s recordings after natural sorting.

cindra.layout.MULTI_RECORDING_DIRECTORY_NAME: str = 'multi_recording'

The name of the directory holding the multi-recording results, created inside a recording’s output directory.

cindra.layout.MULTI_RECORDING_RUNTIME_DATA_FILENAME: str = 'multi_recording_runtime_data.yaml'

The name of the multi-recording runtime data file, written into the tracked dataset’s directory.

cindra.layout.MULTI_RECORDING_TRACKER_FILENAME: str = 'multi_recording_tracker.yaml'

The name of the tracker file recording the state of every multi-recording job of one tracked dataset.

class cindra.layout.MultiRecordingArrays(*values)

Bases: StrEnum

Defines the names of the arrays the multi-recording registration stage writes into its own subdirectory.

DEFORM_FIELD_X = 'deform_field_x.npy'

The horizontal deformation carrying this recording into the shared visual space.

DEFORM_FIELD_Y = 'deform_field_y.npy'

The vertical deformation carrying this recording into the shared visual space.

TRANSFORMED_ENHANCED_MEAN_IMAGE = 'transformed_enhanced_mean_image.npy'

The recording’s enhanced mean image deformed into the shared visual space.

TRANSFORMED_MAXIMUM_PROJECTION = 'transformed_maximum_projection.npy'

The recording’s maximum projection deformed into the shared visual space.

TRANSFORMED_MEAN_IMAGE = 'transformed_mean_image.npy'

The recording’s mean image deformed into the shared visual space.

cindra.layout.OUTPUT_DIRECTORY_NAME: str = 'cindra'

The name of the directory every pipeline stage writes its output under, created inside the caller’s output root.

cindra.layout.PARAMETERS_FILENAME: str = 'cindra_parameters.json'

The name of the acquisition parameters file the pipeline reads from a recording’s raw imaging directory.

cindra.layout.PLANE_SPECIFIER_PREFIX: str = 'plane_'

The prefix of the specifier that identifies one virtual imaging plane, completed by the plane index.

Notes

The specifier names the plane’s output directory and identifies the plane a per-plane job processes on its tracker, so the directory a plane writes into and the specifier its job carries stay spelled the same way.

type cindra.layout.PipelineArray = RecordingArrays | DetectionImages | RegistrationArrays | MultiRecordingArrays

Any array name the pipelines write, which the array path resolver accepts from any of the four families.

cindra.layout.REGISTRATION_DATA_DIRECTORY_NAME: str = 'registration_data'

The name of the per-plane directory holding the registration offsets, the reference image, and the quality metrics.

class cindra.layout.RecordingArrays(*values)

Bases: StrEnum

Defines the names of the result arrays every extraction stage writes.

Notes

The same names are written into a recording’s output directory for the combined multi-plane results, into each plane’s directory for that plane’s results, and into a tracked dataset’s directory for the multi-recording results. One name therefore resolves against any of the three roots.

CELL_CLASSIFICATION = 'cell_classification.npy'

The classification of every ROI, holding its thresholded is-cell label in the first column and the probability that label was drawn from in the second.

CELL_COLOCALIZATION = 'cell_colocalization.npy'

The colocalization of every ROI with the recording’s second channel, measured against the structural channel when the second channel is structural and against the second functional channel’s own ROIs otherwise.

CELL_FLUORESCENCE = 'cell_fluorescence.npy'

The raw fluorescence trace of every ROI.

CORRECTED_STRUCTURAL_MEAN_IMAGE = 'corrected_structural_mean_image.npy'

The structural channel mean image with the functional channel bleed-through removed.

NEUROPIL_FLUORESCENCE = 'neuropil_fluorescence.npy'

The neuropil fluorescence trace surrounding every ROI.

ROI_MASKS = 'roi_masks.npz'

The pixel masks and weights of every ROI.

ROI_STATISTICS = 'roi_statistics.npz'

The per-ROI statistics, holding the shape descriptors alongside the soma, overlap, and neuropil masks and the trace skewness the extraction stage records.

SPIKES = 'spikes.npy'

The deconvolved spike trace of every ROI.

SUBTRACTED_FLUORESCENCE = 'subtracted_fluorescence.npy'

The delta fluorescence of every ROI, after both the scaled neuropil trace and the estimated resting baseline have been subtracted.

class cindra.layout.RegistrationArrays(*values)

Bases: StrEnum

Defines the names of the arrays the registration stage writes into its own subdirectory.

BAD_FRAMES = 'bad_frames.npy'

The mask marking the frames excluded from the valid-region crop and from detection’s temporal binning, which registration computes from its own offsets after registering every frame.

Notes

The same name identifies an optional input file the registration stage reads from the configured ‘file_io.data_path’ root, where it instead holds the indices of the frames to mark bad before the crop is computed. The stage joins the file name to that root directly, so the file belongs under the configured path even where the TIFF files sit in a subdirectory below it.

NONRIGID_CORRELATIONS = 'nonrigid_correlations.npy'

The phase correlation peak of every block’s nonrigid alignment.

NONRIGID_X_OFFSETS = 'nonrigid_x_offsets.npy'

The horizontal shift applied to every block of every frame.

NONRIGID_Y_OFFSETS = 'nonrigid_y_offsets.npy'

The vertical shift applied to every block of every frame.

PRINCIPAL_COMPONENT_EXTREME_IMAGES = 'principal_component_extreme_images.npy'

The low and high projection images of every retained principal component.

PRINCIPAL_COMPONENT_PROJECTIONS = 'principal_component_projections.npy'

The projection of every sampled frame onto every retained principal component.

PRINCIPAL_COMPONENT_SHIFT_METRICS = 'principal_component_shift_metrics.npy'

The residual shift measured between each principal component’s extreme images.

REFERENCE_IMAGE = 'reference_image.npy'

The reference image every frame is registered against, whose presence marks a plane as registered.

RIGID_CORRELATIONS = 'rigid_correlations.npy'

The phase correlation peak of every frame’s rigid alignment.

RIGID_X_OFFSETS = 'rigid_x_offsets.npy'

The horizontal rigid shift applied to every frame.

RIGID_Y_OFFSETS = 'rigid_y_offsets.npy'

The vertical rigid shift applied to every frame.

cindra.layout.SINGLE_RECORDING_CONFIGURATION_FILENAME: str = 'configuration.yaml'

The name of the single-recording configuration file, written into the recording’s output directory.

cindra.layout.SINGLE_RECORDING_RUNTIME_DATA_FILENAME: str = 'runtime_data.yaml'

The name of the per-plane runtime data file, written into each plane’s output directory.

cindra.layout.SINGLE_RECORDING_TRACKER_FILENAME: str = 'single_recording_tracker.yaml'

The name of the tracker file recording the state of every single-recording job of one recording.

cindra.layout.TRACKING_TEMPLATE_MASKS_FILENAME: str = 'tracking_template_masks.npz'

The name of the archive holding the tracked ROI template masks, which doubles as the multi-recording discovery completion marker.

cindra.layout.parse_plane_specifier(specifier)

Reads the virtual plane index a per-plane specifier carries.

Notes

Inverts resolve_plane_specifier. A specifier that names no plane resolves to None rather than raising, because a caller routing a mixed job set asks this of every specifier it holds.

Parameters:

specifier (str) – The specifier to read the plane index from.

Return type:

int | None

Returns:

The virtual plane index, or None when the specifier does not name a plane.

cindra.layout.resolve_array_name(array, *, second_channel=False)

Resolves the filename one pipeline array is written under.

Parameters:
Return type:

str

Returns:

The filename the array is written under.

cindra.layout.resolve_array_path(root_path, array, *, second_channel=False)

Resolves the path to one pipeline array under a recording, plane, or dataset directory.

Parameters:
  • root_path (Path) – The directory the array was written into. The result arrays are written into a recording output directory, a plane directory, or a dataset directory, while the detection, registration, and multi-recording arrays are written into their own subdirectory of one of those.

  • array (RecordingArrays | DetectionImages | RegistrationArrays | MultiRecordingArrays) – The array to resolve the path of, named by any of the four pipeline array families.

  • second_channel (bool, default: False) – Determines whether the second channel’s copy of the array is resolved instead of the functional channel’s copy.

Return type:

Path

Returns:

The path to the requested result array.

cindra.layout.resolve_binarization_marker_name(binary_name)

Resolves the name of the marker written beside a plane binary while binarization fills it.

Parameters:

binary_name (str) – The name of the plane binary being filled.

Return type:

str

Returns:

The name of the marker file guarding the conversion.

cindra.layout.resolve_channel_2_name(name)

Resolves the name of the second channel’s copy of a result file.

Parameters:

name (str) – The name of the functional channel’s copy of the file.

Return type:

str

Returns:

The name of the second channel’s copy, carrying the channel suffix before the extension.

cindra.layout.resolve_dataset_path(output_root, dataset_name)

Resolves the output directory of one tracked multi-recording dataset inside a recording’s output directory.

Notes

The dataset name is lowered here, matching the fold the multi-recording context resolver applies when it builds the directory, so a caller passing the configured name reaches the directory the pipeline wrote.

Parameters:
  • output_root (Path) – The output root the caller configured for the recording.

  • dataset_name (str) – The name of the tracked dataset, in any casing.

Return type:

Path

Returns:

The path to the dataset’s output directory inside the recording’s output directory.

cindra.layout.resolve_output_path(output_root)

Resolves the directory every pipeline stage writes its output under.

Parameters:

output_root (Path) – The output root the caller configured for the recording.

Return type:

Path

Returns:

The path to the recording’s cindra output directory.

cindra.layout.resolve_plane_path(output_root, plane_index)

Resolves the output directory of one virtual imaging plane.

Parameters:
  • output_root (Path) – The output root the caller configured for the recording.

  • plane_index (int) – The index of the virtual imaging plane.

Return type:

Path

Returns:

The path to the plane’s output directory.

cindra.layout.resolve_plane_specifier(plane_index)

Resolves the specifier that identifies one virtual imaging plane.

Parameters:

plane_index (int) – The index of the virtual imaging plane.

Return type:

str

Returns:

The specifier identifying the plane.

cindra.layout.resolve_registration_marker_name(binary_name)

Resolves the name of the marker written beside a plane binary while registration rewrites it.

Parameters:

binary_name (str) – The name of the plane binary being rewritten.

Return type:

str

Returns:

The name of the marker file guarding the rewrite.

Data Structures

Provides configuration and runtime data classes for the single-recording and multi-recording cindra pipelines.

class cindra.dataclasses.AcquisitionParameters(frame_rate, plane_number=1, channel_number=1, roi_number=1, roi_lines=(), roi_x_coordinates=(), roi_y_coordinates=())

Bases: YamlConfig

Stores the data acquisition parameters used by the system that recorded the processed ROI activity data.

Notes

For single-ROI data, only frame_rate, plane_number, and channel_number are required. For MROI data, additional fields describe the geometry of each ROI.

The pipeline expects a cindra_parameters.json file in the data directory containing these parameters.

channel_number: int = 1

The number of channels acquired per plane. Most recordings use either one or two channels. Currently, the processing only supports recordings with two or fewer channels.

frame_rate: float

The acquisition frame rate in Hz. For multi-plane recordings, this is the volume rate (rate at which all planes are acquired), not the rate per plane.

property is_mroi: bool

Returns True if this acquisition uses multi-ROI mode (roi_number > 1).

plane_number: int = 1

The number of imaging planes acquired per volume. For single-plane recordings, this is 1.

roi_lines: tuple[tuple[int, ...], ...] = ()

The line indices for each ROI in MROI acquisitions. Each inner tuple contains the row indices in the raw frame that belong to that ROI. The length of the outer tuple must equal roi_number. For single-ROI data, this field is empty.

roi_number: int = 1

The number of regions of interest (ROIs) acquired per plane. For standard imaging this is 1. For MROI line-scanning microscopes (e.g., 2-Photon Random Access Mesoscope), this can be greater than 1.

roi_x_coordinates: tuple[int, ...] = ()

The x-coordinates (in pixels) for positioning each ROI in MROI acquisitions. These define the horizontal position of each ROI’s top-left corner in the combined field of view. The length must equal roi_number. For single-ROI data, this field is empty.

roi_y_coordinates: tuple[int, ...] = ()

The y-coordinates (in pixels) for positioning each ROI in MROI acquisitions. These define the vertical position of each ROI’s top-left corner in the combined field of view. The length must equal roi_number. For single-ROI data, this field is empty.

property virtual_plane_count: int

Returns the total number of virtual planes (roi_number * plane_number), where each ROI x plane combination becomes a separate virtual plane for processing.

class cindra.dataclasses.BaselineMethod(*values)

Bases: StrEnum

Defines the supported methods for computing baseline fluorescence before spike deconvolution.

CONSTANT = 'constant'

Uses the global minimum of the Gaussian-smoothed trace as a single constant baseline for the entire recording.

CONSTANT_PERCENTILE = 'constant_percentile'

Uses a low percentile of the trace as a robust constant baseline, ignoring outliers.

MAXIMIN = 'maximin'

Applies Gaussian smoothing followed by minimum and maximum filters over a sliding window, tracking the lower envelope of slow signal fluctuations.

class cindra.dataclasses.CombinedData(detection, extraction, plane_count=0, frame_count=0, plane_frame_counts=<factory>, combined_height=0, combined_width=0, tau=0.0, sampling_rate=0.0, plane_heights=<factory>, plane_widths=<factory>, plane_y_offsets=<factory>, plane_x_offsets=<factory>, registered_binary_paths=(), registered_binary_paths_channel_2=None)

Bases: object

Stores combined multi-plane detection and extraction data.

Provides a container for the results of combining processed data from multiple imaging planes into a unified dataset.

Notes

Combined data is saved to the root cindra directory alongside configuration.yaml and acquisition_parameters.yaml. The same filenames are used as per-plane data, but stored at the root level rather than in plane subdirectories.

combined_height: int

The height of the combined field of view in pixels.

combined_width: int

The width of the combined field of view in pixels.

detection: DetectionData

The combined detection data including mean images, correlation maps, and maximum projections for both channels.

extraction: ExtractionData

The combined extraction data including ROI statistics, fluorescence traces, and classification results for both channels.

frame_count: int

The number of frames the combined traces span, which is the frame count of the shortest plane that contributed to them.

classmethod load(root_path)

Loads combined metadata from the root cindra directory without loading any arrays.

Parameters:

root_path (Path) – The root cindra output directory containing combined_metadata.npz.

Return type:

CombinedData

Returns:

A CombinedData instance with metadata loaded and empty detection/extraction containers. NumPy array fields remain None until explicitly loaded on the child dataclasses.

Raises:

FileNotFoundError – If the combined metadata file does not exist.

plane_count: int

The number of planes that were combined.

plane_frame_counts: NDArray[uint32]

The number of frames each plane’s binaries hold, which binarization makes identical for every plane of the recording.

plane_heights: NDArray[uint16]

Per-plane frame heights in pixels.

plane_widths: NDArray[uint16]

Per-plane frame widths in pixels.

plane_x_offsets: NDArray[int32]

Per-plane x-axis displacement used to arrange planes in the combined view.

plane_y_offsets: NDArray[int32]

Per-plane y-axis displacement used to arrange planes in the combined view.

registered_binary_paths: tuple[Path, ...]

Channel 1 registered binary file paths, one per plane.

registered_binary_paths_channel_2: tuple[Path, ...] | None

Channel 2 registered binary file paths, one per plane. None unless both channels are functional.

sampling_rate: float

The per-plane sampling rate in Hertz, cached from the single-recording runtime for use by the multi-recording extraction pipeline.

save(root_path)

Saves combined data to the root cindra directory.

Metadata (plane count, dimensions) is saved to combined_metadata.npz.

Notes

The combined_metadata.npz file doubles as the marker consumers check to decide whether the single-recording pipeline completed. It is therefore written after the arrays it describes, and it is published through the atomic writer so that it appears in one step. An interrupted run never leaves a marker that describes a payload which is not on disk.

Parameters:

root_path (Path) – The root cindra output directory containing configuration.yaml.

Return type:

None

tau: float

The timescale of the calcium indicator sensor in seconds, cached from the single-recording configuration for use by the multi-recording extraction pipeline.

class cindra.dataclasses.DetectionData(roi_diameter=0, aspect_ratio=0.0, mean_image=None, enhanced_mean_image=None, maximum_projection=None, correlation_map=None, roi_diameter_channel_2=0, mean_image_channel_2=None, enhanced_mean_image_channel_2=None, maximum_projection_channel_2=None, correlation_map_channel_2=None)

Bases: object

Stores runtime data from the detection stage.

aspect_ratio: float

The median normalized aspect ratio across detected ROIs, computed from the fitted ellipse semi-axes as 2*major/(major+minor), bounded between 0 and 2 where 1 indicates a circular shape.

correlation_map: NDArray[float32] | None

The maximum activity of every pixel across the detection scale pyramid, zero outside the valid registration crop.

correlation_map_channel_2: NDArray[float32] | None

The maximum activity of every pixel across the detection scale pyramid for the second imaging channel, zero outside the valid registration crop.

enhanced_mean_image: NDArray[float32] | None

The high-pass filtered mean image that enhances ROI boundaries for improved detection.

enhanced_mean_image_channel_2: NDArray[float32] | None

The high-pass filtered mean image for the second imaging channel.

load_arrays(output_path)

Loads detection arrays from individual .npy files in the detection_data/ subdirectory.

Parameters:

output_path (Path) – The directory containing the detection_data/ subdirectory.

Return type:

None

maximum_projection: NDArray[float32] | None

The maximum of every pixel across the temporally binned and high-pass filtered movie, zero outside the valid registration crop.

maximum_projection_channel_2: NDArray[float32] | None

The maximum of every pixel across the temporally binned and high-pass filtered movie for the second imaging channel, zero outside the valid registration crop.

mean_image: NDArray[float32] | None

The mean of the temporally binned movie, which excludes the frames registration marked bad, zero outside the valid registration crop.

mean_image_channel_2: NDArray[float32] | None

The mean of the temporally binned movie for the second imaging channel, which excludes the frames registration marked bad, zero outside the valid registration crop.

memory_map_arrays(output_path)

Memory-maps detection arrays from individual .npy files in the detection_data/ subdirectory.

Uses r mode, so the mapped arrays are read-only. This avoids loading the full array contents into memory, which is useful when reusing previously-generated data.

Parameters:

output_path (Path) – The directory containing the detection_data/ subdirectory.

Return type:

None

prepare_for_saving()

Sets all array fields to None for YAML serialization.

Return type:

None

release_arrays()

Releases all array fields to free memory.

Use memory_map_arrays() or load_arrays() to re-acquire the data on demand.

Return type:

None

roi_diameter: int

The estimated ROI diameter in pixels, automatically computed from the spatial scale during detection.

roi_diameter_channel_2: int

The estimated ROI diameter for the second imaging channel in pixels. Computed independently because channel 2 may label a different ROI population with different soma sizes.

save_arrays(output_path)

Saves detection arrays as individual .npy files inside a detection_data/ subdirectory.

Parameters:

output_path (Path) – The directory in which to create the detection_data/ subdirectory.

Return type:

None

class cindra.dataclasses.DiffeomorphicRegistration(image_type=ReferenceImageType.ENHANCED_MEAN, grid_sampling_factor=1, final_grid_sampling=16.0, scale_sampling=30, speed_factor=3, repeat_registration=False)

Bases: object

Stores parameters for diffeomorphic demons registration that aligns multiple recordings to the same visual (sampling) space.

final_grid_sampling: float

The spacing, in pixels, between the B-spline control points of the grid used at the finest scale level of the multi-scale registration. Registration requires the reference images to span more than twice this spacing along both dimensions. Lowering the value therefore supports smaller reference images and resolves finer local deformations, at the cost of a less constrained deformation field.

grid_sampling_factor: float

Controls how the B-spline grid spacing scales with image scale during the multi-scale registration process. Must be between 0 and 1. Lower values produce a relatively finer grid at coarser scales, allowing for more detailed deformations at those scales.

image_type: ReferenceImageType | str

The type of cindra-generated reference image to use for across-recording registration. This image is used to calculate the deformation fields that register all recordings to a common visual space.

repeat_registration: bool

Determines whether to repeat diffeomorphic registration when existing registration data is found. When True, the pipeline clears existing deformation fields, transformed images, and deformed ROI masks before re-running registration, and it additionally re-runs the dependent cross-recording tracking and template projection steps. When False (default), existing registration results, template masks, and projected ROI statistics are all reused if present.

scale_sampling: int

The number of registration iterations to perform at each scale level of the multi-scale pyramid. Values between 20 and 30 are reasonable for most recordings, but higher values yield better alignment at the cost of proportionally longer computation time.

speed_factor: float

The relative force of the deformation transform applied when registering the recordings to the same visual space. This is the most important parameter to tune. For most cases, a value between 1 and 5 is reasonable.

class cindra.dataclasses.ExtractionData(roi_statistics=None, cell_fluorescence=None, neuropil_fluorescence=None, subtracted_fluorescence=None, spikes=None, cell_classification=None, roi_statistics_channel_2=None, cell_fluorescence_channel_2=None, neuropil_fluorescence_channel_2=None, subtracted_fluorescence_channel_2=None, spikes_channel_2=None, cell_classification_channel_2=None, cell_colocalization=None, corrected_structural_mean_image=None)

Bases: object

Stores runtime data from the extraction stage.

cell_classification: NDArray[float32] | None

The cell classification results with shape (cells, 2) containing (is_cell_label, probability).

cell_classification_channel_2: NDArray[float32] | None

The cell classification results for channel 2.

cell_colocalization: NDArray[float32] | None

The colocalization results relating channel 1 ROIs to channel 2, with shape (cells, 2). When channel 2 is structural, column 0 holds the is-colocalized flag and column 1 the colocalization probability. When both channels are functional, column 0 holds the matched channel 2 ROI index (-1 when unmatched) and column 1 the pixel overlap score.

cell_fluorescence: NDArray[float32] | None

The cell fluorescence traces with shape (cells, frames).

cell_fluorescence_channel_2: NDArray[float32] | None

The cell fluorescence traces for channel 2.

corrected_structural_mean_image: NDArray[float32] | None

The bleed-through-corrected mean image for the structural channel, computed during intensity-based colocalization. The import layer always routes the functional data into channel 1, so the structural channel is always channel 2. This field is not computed when both channels are functional, as spatial colocalization is used instead.

load_arrays(output_path)

Loads ROI statistics and classification results from disk.

Fluorescence traces and colocalization data are excluded, because they consume significant memory and are acquired through load_results() or memory_map_results().

Parameters:

output_path (Path) – The directory containing the extraction data files.

Return type:

None

load_results(output_path)

Loads all extraction result arrays from disk.

Classification arrays may already be loaded by load_arrays(), in which case the guarded loading here is a no-op. Fluorescence traces and colocalization data are not loaded by load_arrays(), because they consume significant memory.

Parameters:

output_path (Path) – The directory containing the result .npy files.

Return type:

None

memory_map_arrays(output_path)

Memory-maps ROI statistics and classification results from disk.

Mirrors load_arrays() but uses read-only r memory mapping for .npy files instead of eager loading. ROI statistics (.npz) are still eagerly loaded because NumPy does not support memory mapping for .npz archives.

Parameters:

output_path (Path) – The directory containing the extraction data files.

Return type:

None

memory_map_results(output_path)

Memory-maps all extraction result arrays from disk.

Mirrors load_results() but uses read-only r memory mapping for all .npy files instead of eager loading. This avoids loading the full array contents into memory, which is useful when reusing previously-generated data.

Parameters:

output_path (Path) – The directory containing the result .npy files.

Return type:

None

neuropil_fluorescence: NDArray[float32] | None

The neuropil fluorescence traces with shape (cells, frames).

neuropil_fluorescence_channel_2: NDArray[float32] | None

The neuropil fluorescence traces for channel 2.

prepare_for_saving()

Sets all array and list fields to None for YAML serialization.

Return type:

None

release_arrays()

Releases all array and list fields to free memory.

Use load_arrays() or memory_map_arrays() to re-acquire the ROI statistics and classification results, and load_results() or memory_map_results() to re-acquire the fluorescence traces and colocalization arrays.

Return type:

None

roi_statistics: list[ROIStatistics] | None

The statistics of every ROI detected on channel 1.

roi_statistics_channel_2: list[ROIStatistics] | None

The statistics of every ROI detected on channel 2, present when both channels are functional.

save_arrays(output_path)

Saves all extraction arrays to .npy files and ROI statistics to .npz files.

Parameters:

output_path (Path) – The directory in which to save the extraction data files.

Return type:

None

spikes: NDArray[float32] | None

The deconvolved spike traces with shape (cells, frames).

spikes_channel_2: NDArray[float32] | None

The deconvolved spike traces for channel 2.

subtracted_fluorescence: NDArray[float32] | None

The baseline-and-neuropil-subtracted fluorescence traces with shape (cells, frames).

subtracted_fluorescence_channel_2: NDArray[float32] | None

The baseline-and-neuropil-subtracted fluorescence for channel 2.

class cindra.dataclasses.FileIO(data_path=None, output_path=None, ignored_file_names=(), repeat_binarization=False)

Bases: object

Stores the parameters that specify input data location, format, and output directories.

data_path: Path | None

The path to the root data directory containing the input TIFF files. The pipeline recursively searches this directory and all subdirectories for the cindra_parameters.json file, then loads the .tiff/.tif files from the single directory that holds it. TIFF discovery inside that directory is not recursive.

ignored_file_names: tuple[str, ...]

The file names, given without their extension, to ignore when searching for and loading raw data. Any file whose stem (the name with the extension stripped) exactly matches one of the entries in this tuple is excluded from processing even if it has the correct extension and is located inside the input data directory.

output_path: Path | None

The path to the root output directory where processing results are saved. This field is required for pipeline execution and must be explicitly configured before running any processing step. The pipeline creates a ‘cindra’ subdirectory under this path to store all output files.

repeat_binarization: bool

Determines whether to repeat the binarization step when processing. When True, the pipeline re-runs TIFF to binary conversion using the data_path from the current configuration, even if binary files already exist. A conversion replaces every plane binary, so it first deletes the registration, detection, and extraction outputs of every plane directory the output root holds, the recording’s combined dataset, and the ROI selections every multi-recording dataset holds for this recording. It also resets each plane’s recorded runtime sections. When False (default), an existing binary is reused when it carries no write marker, is sized to the frame geometry recorded for its plane, and is accompanied by the second channel binary a two-channel recording declares. Binarization refuses a binary that fails any of those checks and names this parameter as the remedy, because enabling it rebuilds every plane binary from the source TIFF files.

class cindra.dataclasses.IOData(frame_height=0, frame_width=0, frame_count=0, sampling_rate=0.0, registered_binary_path=None, registered_binary_path_channel_2=None, output_path=None, mroi_y_offset=None, mroi_x_offset=None, mroi_lines=(), plane_index=None)

Bases: object

Stores the Input / Output runtime data for all stages of the single-recording processing pipeline.

frame_count: int

The total number of frames written to the binary file during binarization.

frame_height: int

The height of each frame in pixels (Y dimension of the imaging field of view).

frame_width: int

The width of each frame in pixels (X dimension of the imaging field of view).

mroi_lines: tuple[int, ...]

The tuple of scan line indices used for extracting this ROI from raw multi-ROI data. Only used for MROI recordings.

mroi_x_offset: int | None

The horizontal offset in pixels for positioning this ROI within the full combined field of view. Only used for MROI recordings.

mroi_y_offset: int | None

The vertical offset in pixels for positioning this ROI within the full combined field of view. Only used for MROI recordings.

output_path: Path | None

The absolute path to the plane-specific output directory where all results are saved.

plane_index: int | None

The zero-based index of this virtual imaging plane. For single-ROI data it is the physical plane’s position in the volume. For MROI data it enumerates every ROI and physical plane combination, so the physical plane is this index modulo the acquisition plane count.

registered_binary_path: Path | None

The absolute path to the motion-corrected binary file for the primary imaging channel.

registered_binary_path_channel_2: Path | None

The absolute path to the motion-corrected binary file for the second imaging channel.

sampling_rate: float

The per-plane sampling rate in Hertz, derived from the acquisition frame rate divided by the number of imaging planes. This value is computed during binarization from the AcquisitionParameters.

class cindra.dataclasses.Main(two_channels=False, first_channel_functional=True, second_channel_functional=False, tau=0.4, ignored_flyback_planes=(), custom_classifier_path=None)

Bases: object

Stores the parameters that broadly affect the single-recording pipeline processing behavior.

Notes

For runtime behavior settings shared with the multi-recording pipeline (progress bars), see RuntimeSettings. Worker counts are explicit API parameters resolved through cindra.orchestration.

custom_classifier_path: Path | None

The absolute path to a custom classifier file used for ROI classification. When set, this classifier is used instead of the built-in classifier for both preclassification during detection and final classification after signal extraction. Leave as None to use the built-in classifier bundled with cindra.

first_channel_functional: bool

Determines whether the first channel is used for ROI detection and signal extraction. This field is only applicable when two_channels is True. When both first_channel_functional and second_channel_functional are True, the pipeline performs independent ROI detection on both channels.

ignored_flyback_planes: tuple[int, ...]

The flyback plane indices to ignore when processing the data. Flyback planes typically contain no valid imaging data, so it is common to exclude them from processing.

second_channel_functional: bool

Determines whether the second channel is used for ROI detection and signal extraction. This field is only applicable when two_channels is True. When both first_channel_functional and second_channel_functional are True, the pipeline performs independent ROI detection on both channels.

tau: float

The timescale of the sensor in seconds, used for computing the deconvolution kernel. The kernel is fixed to have this decay and is not fit to the data. The default value is optimized for GCaMP6f animals recorded with the Mesoscope and likely needs to be increased for most other use cases.

two_channels: bool

Determines whether the imaging data contains two channels per plane. When True, the algorithm expects images from both channels of the same plane to be saved sequentially (e.g.: plane 1 channel 1, plane 1 channel 2, plane 2 channel 1, etc.).

class cindra.dataclasses.MultiRecordingConfiguration(runtime=<factory>, recording_io=<factory>, roi_selection=<factory>, diffeomorphic_registration=<factory>, roi_tracking=<factory>, signal_extraction=<factory>, spike_deconvolution=<factory>)

Bases: YamlConfig

Aggregates the user-defined configuration parameters for the multi-recording cindra pipeline.

The pipeline reads these parameters and treats them as immutable for the duration of processing.

Notes

Mirrors the reference implementation at https://github.com/sprustonlab/multiday-suite2p-public.

For runtime data (computed by the pipeline), see MultiRecordingRuntimeData.

diffeomorphic_registration: DiffeomorphicRegistration

Stores parameters for diffeomorphic demons registration that aligns recordings to the same visual space.

classmethod load(file_path)

Loads configuration from a YAML file.

Parameters:

file_path (Path) – The path to the .yaml configuration file.

Return type:

MultiRecordingConfiguration

Returns:

The multi-recording configuration the YAML file stores.

pipeline_type: PipelineType = 'multi-recording'

Identifies this configuration as a multi-recording pipeline configuration.

recording_io: RecordingIO

Stores parameters that specify input recording locations and output directories.

roi_selection: ROISelection

Stores parameters for selecting single-recording-detected ROIs to be tracked across multiple recordings.

roi_tracking: ROITracking

Stores parameters for tracking ROIs across multiple registered recordings using spatial clustering.

runtime: RuntimeSettings

Stores runtime behavior settings shared with the single-recording pipeline (progress bar display).

save(file_path)

Saves the configuration to a YAML file.

Parameters:

file_path (Path) – The path to the .yaml file in which to save the configuration data.

Return type:

None

signal_extraction: SignalExtraction

Stores parameters for extracting fluorescence signals from ROIs and surrounding neuropil regions of the ROIs tracked across recordings.

spike_deconvolution: SpikeDeconvolution

Stores parameters for deconvolving fluorescence signals to infer spike trains.

class cindra.dataclasses.MultiRecordingIOData(recording_id='', data_path=None, dataset_name='', mroi_region_borders=(), dataset_output_paths=(), selected_roi_indices=(), selected_roi_indices_channel_2=())

Bases: object

Stores the Input / Output runtime data for all stages of the multi-recording processing pipeline.

data_path: Path | None

The path to this recording’s cindra single-recording pipeline output directory.

dataset_name: str

The name of the multi-recording dataset, used to create the output subdirectory structure.

dataset_output_paths: tuple[Path, ...]

The multi_recording output paths for every recording in the dataset, stored in natural-sorted order. Each entry points to a recording’s multi_recording output directory.

mroi_region_borders: tuple[int, ...]

The x-coordinates of MROI region borders, computed from acquisition parameters during initialization. For MROI recordings, these borders mark the boundaries between adjacent imaging regions in the combined field of view. ROIs near these borders are filtered out during ROI selection to avoid tracking ambiguities. This field is empty for non-MROI recordings.

recording_id: str

The unique identifier for this recording, derived from the distinguishing component of the recording directory path. This ID is the tracker specifier of the recording’s multi-recording extraction job, and it identifies the recording in status messages.

selected_roi_indices: tuple[int, ...]

The indices of channel 1 ROIs selected from CombinedData.extraction.roi_statistics for multi-recording tracking. These indices reference the original single-recording ROI list, avoiding duplication of ROI data.

selected_roi_indices_channel_2: tuple[int, ...]

The indices of channel 2 ROIs selected from CombinedData.extraction.roi_statistics_channel_2 for multi-recording tracking. Empty if channel 2 data is not available or no channel 2 ROIs were selected.

class cindra.dataclasses.MultiRecordingRegistrationData(deform_field_y=None, deform_field_x=None, transformed_mean_image=None, transformed_enhanced_mean_image=None, transformed_maximum_projection=None, transformed_mean_image_channel_2=None, transformed_enhanced_mean_image_channel_2=None, transformed_maximum_projection_channel_2=None, deformed_roi_masks=None, deformed_roi_masks_channel_2=None)

Bases: object

Stores runtime data from the registration stage.

clear()

Clears all registration data to prepare for re-registration.

Return type:

None

deform_field_x: NDArray[float32] | None

The X-dimension displacement field computed by DiffeomorphicDemonsRegistration.

deform_field_y: NDArray[float32] | None

The Y-dimension displacement field computed by DiffeomorphicDemonsRegistration.

deformed_roi_masks: list[ROIMask] | None

The channel 1 ROI spatial data after multi-recording registration deform offsets have been applied to the spatial coordinates of each ROI.

deformed_roi_masks_channel_2: list[ROIMask] | None

The channel 2 ROI spatial data after multi-recording registration deform offsets have been applied to the spatial coordinates of each ROI.

is_registered(output_path=None)

Checks whether registration data exists in memory or on disk.

Notes

The on-disk check requires the deformed mask archive alongside the deformation field, which mirrors the in-memory check. save_arrays writes the archive last and writes nothing for an empty mask list, so both checks answer True only once at least one deformed mask has landed beside the field.

Parameters:

output_path (Path | None, default: None) – The directory containing the registration_arrays/ subdirectory. When provided and arrays are not loaded in memory, checks for deformation field files on disk. The calling context is responsible for resolving the correct path.

Return type:

bool

Returns:

True if the deformation field and at least one deformed ROI mask are held in memory or exist on disk at the given output path, False otherwise.

load_arrays(output_path)

Loads registration arrays from individual .npy files in the registration_arrays/ subdirectory.

Parameters:

output_path (Path) – The directory containing the registration_arrays/ subdirectory.

Return type:

None

memory_map_arrays(output_path)

Memory-maps registration arrays from individual .npy files in read-only r mode.

ROIMask .npz files are eagerly loaded, because NumPy does not support memory mapping for .npz archives.

Parameters:

output_path (Path) – The directory containing the registration_arrays/ subdirectory.

Return type:

None

prepare_for_saving()

Sets array fields to None for YAML serialization.

Return type:

None

release_arrays()

Releases all array fields to free memory.

Use memory_map_arrays() or load_arrays() to re-acquire the data on demand.

Return type:

None

save_arrays(output_path)

Saves registration arrays as individual .npy files inside a registration_arrays/ subdirectory.

Notes

Deformed ROI masks are serialized by ROIMask.save_list using its variable-length pixel layout and remain as .npz files saved directly into output_path.

Parameters:

output_path (Path) – The directory in which to create the registration_arrays/ subdirectory.

Return type:

None

transformed_enhanced_mean_image: NDArray[float32] | None

The enhanced mean image transformed to the shared (deformed) visual space.

transformed_enhanced_mean_image_channel_2: NDArray[float32] | None

The channel 2 enhanced mean image transformed to the shared (deformed) visual space.

transformed_maximum_projection: NDArray[float32] | None

The maximum projection transformed to the shared (deformed) visual space.

transformed_maximum_projection_channel_2: NDArray[float32] | None

The channel 2 maximum projection transformed to the shared (deformed) visual space.

transformed_mean_image: NDArray[float32] | None

The mean image transformed to the shared (deformed) visual space.

transformed_mean_image_channel_2: NDArray[float32] | None

The channel 2 mean image transformed to the shared (deformed) visual space.

class cindra.dataclasses.MultiRecordingRuntimeContext(configuration, runtime)

Bases: object

Combines configuration and runtime data used in the multi-recording processing pipeline.

Notes

Each MultiRecordingRuntimeContext instance represents a single recording. The configuration is shared across all recording contexts, while the runtime field contains recording-specific data. This mirrors the RuntimeContext pattern where each instance represents a single plane.

configuration: MultiRecordingConfiguration

The user-defined processing configuration, which remains immutable during processing.

classmethod load(root_path, recording_index=-1)

Loads one or more previously-saved MultiRecordingRuntimeContext instances from a recording’s data directory.

Searches root_path recursively for a multi_recording_runtime_data.yaml file, loads that recording’s runtime data, then uses its stored dataset_output_paths to reconstruct the full dataset hierarchy. If the dataset was moved to a different location (e.g., transferred between machines), all cached absolute paths are automatically relocated to match the new directory structure.

Parameters:
  • root_path (Path) – The path to any dataset recording’s root processed data directory. The method searches recursively for the multi_recording_runtime_data.yaml file within this directory tree.

  • recording_index (int, default: -1) – The index of the recording to load. Use -1 to load all available recordings.

Return type:

MultiRecordingRuntimeContext | list[MultiRecordingRuntimeContext]

Returns:

A single MultiRecordingRuntimeContext if recording_index >= 0, or a list of all MultiRecordingRuntimeContext instances if recording_index is -1.

Raises:
  • FileNotFoundError – If no multi_recording_runtime_data.yaml is found, or configuration files are missing.

  • RuntimeError – If multiple multi_recording_runtime_data.yaml files are found under root_path.

  • IndexError – If recording_index is out of range.

runtime: MultiRecordingRuntimeData

The per-recording runtime data, which is computed and updated by pipeline stages.

save_runtime()

Saves this recording’s runtime data to its output directory.

Raises:

ValueError – If output_path is not set in the runtime data.

Return type:

None

save_shared()

Saves the shared configuration to the main recording’s output directory.

Raises:

ValueError – If output_path is not set in the runtime data.

Return type:

None

class cindra.dataclasses.MultiRecordingRuntimeData(output_path=None, io=<factory>, registration=<factory>, tracking=<factory>, extraction=<factory>, timing=<factory>, combined_data=None)

Bases: YamlConfig

Aggregates all runtime data for a single recording.

combined_data: CombinedData | None = None

The combined single-recording processing data for this recording, loaded from the recording directory. This field is not serialized to YAML and is loaded on-demand from the single-recording pipeline outputs.

extraction: ExtractionData

The runtime data from the extraction stage. After backward transformation, tracked ROI masks are stored as ROIStatistics in roi_statistics. Extraction then populates the fluorescence traces, the spike traces, and, for a dual-channel dataset, the cross-channel colocalization array. The classification fields stay unset, because the multi-recording pipeline reuses the single-recording classification.

io: MultiRecordingIOData

The per-recording I/O data including recording ID, single-recording output data path, and dataset name.

classmethod load(output_path)

Deserializes runtime data from a YAML file without loading any NumPy arrays or CombinedData.

The caller is responsible for assigning the combined_data field from CombinedData.load().

Parameters:

output_path (Path) – The directory containing the multi_recording_runtime_data.yaml file.

Return type:

MultiRecordingRuntimeData

Returns:

A MultiRecordingRuntimeData instance with all scalar fields deserialized. NumPy array fields and combined_data remain None until explicitly loaded.

load_arrays()

Eagerly loads all multi-recording NumPy arrays from disk into memory.

The caller loads CombinedData separately, because it references immutable single-recording outputs that this instance does not own.

Return type:

None

memory_map_arrays()

Memory-maps all multi-recording NumPy arrays from disk in read-only r mode.

The caller loads CombinedData separately, because it references immutable single-recording outputs that this instance does not own.

Return type:

None

output_path: Path | None = None

The path to the directory where runtime data and array files are stored.

registration: MultiRecordingRegistrationData

The runtime data from the registration stage (deformation fields, transformed images, deformed masks).

release_arrays()

Releases all array fields across registration, tracking, extraction, and combined_data to free memory.

Delegates to the release_arrays() method on each child dataclass. Also releases combined_data detection and extraction arrays if combined_data is loaded.

Return type:

None

save(output_path)

Saves the runtime data to a YAML file and arrays to .npz/.npy files.

Notes

The combined_data field is NOT saved since it references immutable single-recording outputs. It must be loaded separately by the caller after deserialization.

Parameters:

output_path (Path) – The directory in which to save the multi_recording_runtime_data.yaml file and array files.

Return type:

None

timing: MultiRecordingTimingData

The timing information for both discovery and extraction phases.

tracking: MultiRecordingTrackingData

The runtime data from the cross-recording ROI tracking stage (template masks in shared visual space).

class cindra.dataclasses.MultiRecordingTimingData(registration_time=0, tracking_time=0, backward_transform_time=0, total_discovery_time=0, extraction_time=0, deconvolution_time=0, total_extraction_time=0, date_processed='', python_version='3.14.7', cindra_version='2.0.0')

Bases: object

Stores pipeline timing and version data.

Notes

All time durations are stored as integers representing seconds. Discovery phase timing (registration, tracking, backward transform) is stored redundantly in each recording for simplicity. Extraction phase timing is recording-specific.

backward_transform_time: int

The backward across-recording ROI mask transformation time in seconds.

cindra_version: str

The cindra library version used for processing this recording.

date_processed: str

The timestamp captured when this recording’s multi-recording discovery phase completed. The extraction phase does not update this value.

deconvolution_time: int

The spike deconvolution time for this recording in seconds.

extraction_time: int

The fluorescence extraction time for this recording in seconds.

python_version: str

The Python interpreter version used for processing this recording.

registration_time: int

The across-recording diffeomorphic demons registration time in seconds.

total_discovery_time: int

The total discovery phase time in seconds.

total_extraction_time: int

The total extraction phase time for this recording in seconds.

tracking_time: int

The across-recording ROI tracking time in seconds.

class cindra.dataclasses.MultiRecordingTrackingData(template_masks=None, template_masks_channel_2=None, template_diameter=0, template_diameter_channel_2=0)

Bases: object

Stores template masks from cross-recording ROI tracking.

Notes

Template masks represent consensus ROIs that can be reliably identified across multiple recordings. They are generated by clustering deformed ROI masks in the shared visual space and extracting pixels that consistently appear across recordings.

load_arrays(output_path)

Loads template mask arrays from .npz files into this instance.

Parameters:

output_path (Path) – The directory containing the tracking data files.

Return type:

None

memory_map_arrays(output_path)

Loads template mask arrays from .npz files into this instance.

Delegates to load_arrays(), because template masks are stored as .npz archives, which do not support memory mapping.

Parameters:

output_path (Path) – The directory containing the tracking data files.

Return type:

None

prepare_for_saving()

Sets all list fields to None for YAML serialization.

Return type:

None

release_arrays()

Releases all list fields to free memory.

Use load_arrays() to re-acquire the data on demand.

Return type:

None

save_arrays(output_path)

Saves template mask arrays to .npz files.

Parameters:

output_path (Path) – The directory in which to save the tracking data files.

Return type:

None

template_diameter: int

The estimated ROI diameter in pixels for channel 1 template masks, derived from the median pixel count of the generated templates. A value of 0 indicates that no templates have been computed yet.

template_diameter_channel_2: int

The estimated ROI diameter in pixels for channel 2 template masks, derived from the median pixel count of the generated templates. A value of 0 indicates that no templates have been computed yet.

template_masks: list[ROIMask] | None

The template ROI masks in shared visual space coordinates. Each ROIMask represents an ROI that can be tracked across recordings, with pixel coordinates and weights derived from the clustering consensus.

template_masks_channel_2: list[ROIMask] | None

The channel 2 template ROI masks in shared visual space coordinates. Only present when tracking channel 2 ROIs independently in dual-channel recordings.

class cindra.dataclasses.NonrigidRegistration(enabled=True, block_size=(128, 128), signal_to_noise_threshold=1.2, maximum_block_offset=5.0)

Bases: object

Stores parameters for nonrigid registration, which is used to improve motion registration in complex datasets by dividing frames into subregions and shifting each subregion independently of other subregions.

block_size: tuple[int, int]

The block size, in pixels, for nonrigid registration, defining the dimensions of subregions used in the correction. It is recommended to keep this size a power of 2 and/or 3 for more efficient FFT computation. During processing, each frame is tiled with blocks of these dimensions that overlap by approximately 50%, and the registration is applied to each block independently. A dimension that matches or exceeds the corresponding frame dimension collapses to a single block spanning the whole frame.

enabled: bool

Determines whether to perform nonrigid registration to correct for local motion and deformation. This is primarily used for correcting non-uniform motion.

maximum_block_offset: float

The maximum allowed offset, in pixels, for each block relative to the rigid registration offset.

signal_to_noise_threshold: float

The signal-to-noise ratio threshold below which the block’s phase correlation surface receives additional smoothing from its neighboring blocks before the block offset is estimated. Block offsets are never rejected by this threshold. Higher values simply apply more smoothing. Typical values range from 1.0 to 1.5.

class cindra.dataclasses.OnePhotonRegistration(enabled=False, spatial_highpass_window=42, pre_smoothing_sigma=0.0, edge_taper_pixels=40.0)

Bases: object

Stores parameters for additional pre-registration processing used to improve the registration of 1-photon datasets.

edge_taper_pixels: float

The sigmoid falloff scale, in pixels, of the edge taper applied at image borders. The taper begins roughly 2 * this value inward from each edge and fades border pixels toward the image mean (not to zero) to prevent edge artifacts during FFT-based phase correlation. Larger values provide smoother transitions but reduce the usable image area.

enabled: bool

Determines whether to perform high-pass spatial filtering and tapering to improve one-photon image registration. For two-photon datasets, this should be set to False.

pre_smoothing_sigma: float

The window size, in pixels, of the uniform (box) filter applied before spatial high-pass filtering. The value is cast to an integer window and must be even, because odd windows are rejected by apply_spatial_smoothing(). This reduces high-frequency noise that would otherwise be amplified by the high-pass filter. Setting this to 0.0 disables pre-smoothing.

spatial_highpass_window: int

The window size, in pixels, for spatial high-pass filtering. This filter removes low-frequency spatial variations such as uneven illumination that are common in one-photon imaging. The filter subtracts a spatially smoothed version of the image (using this window size) from the original, preserving only high-frequency features useful for registration.

class cindra.dataclasses.PipelineType(*values)

Bases: StrEnum

Defines the supported cindra processing pipeline types.

MULTI_RECORDING = 'multi-recording'

The across-recording pipeline that tracks and extracts ROIs across multiple recordings (discover, extract).

SINGLE_RECORDING = 'single-recording'

The within-recording pipeline that processes a single recording (binarize, register, process, combine).

class cindra.dataclasses.ROIDetection(enabled=True, preclassification_threshold=0.0, threshold_scaling=1.0, spatial_highpass_window=25, maximum_overlap=0.75, temporal_highpass_window=100, maximum_iterations=50, maximum_binned_frames=5000, denoise=False, crop_to_soma=True)

Bases: object

Stores parameters for Region of Interest (ROI) detection.

crop_to_soma: bool

Determines whether to crop dendritic regions from detected ROIs before computing classification features. When enabled, the algorithm analyzes the radial distribution of fluorescence from each ROI’s centroid and excludes pixels beyond where fluorescence contribution drops significantly. This focuses classification on the cell body, improving accuracy for neurons with extensive dendritic arbors.

denoise: bool

Determines whether to apply PCA-based denoising to the binned movie before ROI detection. This can improve detection in noisy recordings by removing uncorrelated noise while preserving spatially coherent signals.

enabled: bool

Determines whether to perform ROI detection. When disabled, the plane’s whole processing stage is skipped, so no fluorescence traces are extracted, no ROIs are classified, and no spikes are deconvolved.

maximum_binned_frames: int

The maximum number of time-binned frames used for ROI detection. Temporal binning averages consecutive frames to improve signal-to-noise ratio for detection. The bin size is computed to produce at most this many binned frames, so a higher value keeps more binned frames, each averaging fewer source frames, at the cost of increased memory usage and processing time.

maximum_iterations: int

The iteration scaling factor for ROI extraction. The algorithm detects ROIs one at a time, subtracting each detected ROI’s contribution before searching for the next. The actual iteration limit is this value multiplied by 250 internally (e.g., 50 allows up to 12,500 iterations). Higher values allow detecting more ROIs but increase processing time.

maximum_overlap: float

The maximum allowed fraction of an ROI’s pixels that may be shared with any other ROI. ROIs are evaluated in reverse detection order, so when the fraction is exceeded the later-detected ROI is discarded, biasing retention toward earlier-detected (typically higher-quality) ROIs. Lower values enforce stricter separation between detected ROIs.

preclassification_threshold: float

The classifier probability threshold used to pre-filter ROIs before signal extraction. This is the minimum classifier confidence value (that the classified ROI is a cell) for the ROI to be processed further. Setting this to 0.0 keeps all detected ROIs, which is the default because the filter runs before any fluorescence is extracted and therefore judges a region on its shape alone, without the skewness of its trace. Small regions carry a low normalized pixel count and are discarded on that evidence, and the discard is permanent, so no later classification threshold can recover them. Raising this value trades recall for a smaller extraction workload.

spatial_highpass_window: int

The window size, in pixels, for spatial high-pass filtering used during neuropil subtraction. The algorithm subtracts a spatially smoothed version of each frame (using this window size) to remove diffuse neuropil fluorescence and isolate cell bodies.

temporal_highpass_window: int

The window size, in frames, for temporal high-pass filtering applied before ROI detection. This removes slow fluorescence drifts (such as photobleaching or baseline changes) by subtracting a running mean computed over this window. Larger values preserve slower transients but may retain more drift artifacts.

threshold_scaling: float

The scaling factor for the ROI detection threshold. The final threshold multiplies this value by a fixed base multiplier of 5.0 and by the selected pyramid scale index, which is clamped to a minimum of 1. The product is then multiplied by a recording-length factor, the binned frame count divided by 1200, also clamped to a minimum of 1. Higher values require ROIs to stand out more distinctly from background noise, resulting in fewer but more confident detections. Lower values detect more ROIs but may include false positives. The default of 1.0 leaves the base multiplier unscaled.

class cindra.dataclasses.ROIMask(y_pixels, x_pixels, pixel_weights, centroid, frame_width, radius=0.0, cluster_id=0, recording_count=0, overlap_mask=None)

Bases: object

Stores lightweight spatial ROI data for pipeline processing.

centroid: tuple[int, int]

detection stores the residual-variance peak (or the pixel nearest the coordinate-wise median when a component split fires), while multi-recording templates store the coordinate-wise median.

Type:

The representative (y, x) pixel position of the ROI

property circle_pixels: tuple[NDArray[int32], NDArray[int32]]

Computes unclipped (y_circle, x_circle) pixel coordinates of a circle with 1.25 * radius and 100 sample points around the ROI centroid.

cluster_id: int = 0

The multi-recording ROI cluster ID. Zero indicates unclustered, positive values indicate cluster membership.

frame_width: int

The width of the image frame in pixels, used to compute raveled pixel indices.

static load_list(file_path)

Loads a list of ROIMask instances from an uncompressed .npz file.

Parameters:

file_path (Path) – The path to the .npz file containing the serialized ROI masks.

Return type:

list[ROIMask]

Returns:

A list of ROIMask instances reconstructed from the file.

overlap_mask: NDArray[bool] | None = None

The boolean mask indicating which pixels overlap with other ROIs. Persisted through ROIStatistics.save_list(), which writes it into the statistics .npz file, but not by ROIMask.save_list().

pixel_weights: NDArray[float32]

The spatial filter weights (lambda values) for each pixel, indicating contribution to the ROI signal.

radius: float = 0.0

The fitted ellipse radius representing the approximate ROI size.

property raveled_pixels: NDArray[int32]

Computes raveled pixel indices (y * frame_width + x) on first access.

recording_count: int = 0

The number of recordings in which this ROI was detected during multi-recording tracking.

static save_list(mask_list, file_path)

Saves a list of ROIMask instances to an uncompressed .npz file without pickle.

Parameters:
  • mask_list (list[ROIMask]) – The list of ROIMask instances to save.

  • file_path (Path) – The path to the output .npz file.

Return type:

None

x_pixels: NDArray[int32]

The x-coordinates (column indices) of all pixels belonging to this ROI.

y_pixels: NDArray[int32]

The y-coordinates (row indices) of all pixels belonging to this ROI.

class cindra.dataclasses.ROISelection(probability_threshold=0.85, maximum_size=1000, mroi_region_margin=30, probability_threshold_channel_2=None, maximum_size_channel_2=None, mroi_region_margin_channel_2=None)

Bases: object

Stores parameters for selecting single-recording-detected ROIs to be tracked across multiple recordings.

maximum_size: int

The maximum allowed ROI size, in pixels. ROIs with a larger pixel size are excluded from processing. This parameter applies to channel 1 ROIs.

maximum_size_channel_2: int | None

The maximum allowed ROI size for channel 2, in pixels. When set to None (default), channel 2 ROIs use the same maximum_size as channel 1.

mroi_region_margin: int

The minimum required distance, in pixels, between the x-coordinate of the centroid the ROI carries, which detection sets to the residual-variance peak, and the MROI region border. ROIs that are too close to region borders are excluded from processing to avoid ambiguities associated with tracking ROIs that span multiple regions. This parameter is only used for MROI recordings where region borders are automatically computed from the acquisition parameters. This parameter applies to channel 1 ROIs.

mroi_region_margin_channel_2: int | None

The minimum required distance from MROI region borders for channel 2 ROIs, in pixels. When set to None (default), channel 2 ROIs use the same mroi_region_margin as channel 1.

probability_threshold: float

The minimum required cell probability score assigned to the ROI by the single-recording cindra classifier. ROIs with a lower classifier score are excluded from multi-recording processing. This parameter applies to channel 1 ROIs.

probability_threshold_channel_2: float | None

The minimum required cell probability score for channel 2 ROIs. When set to None (default), channel 2 ROIs use the same probability_threshold as channel 1.

class cindra.dataclasses.ROIStatistics(mask, footprint=0, compactness=0.0, solidity=0.0, pixel_count=0, soma_mask=None, aspect_ratio=0.0, normalized_pixel_count=0.0, skewness=None, neuropil_mask=None, plane_index=0)

Bases: object

Stores spatial and statistical properties for a single region of interest (ROI).

Represents the complete set of properties computed for each detected ROI during the detection, extraction, and optional multi-recording processing stages.

Notes

Shape statistics fields have default values to support staged construction where ROIStatistics is first created during detection with only core fields, then updated with computed shape statistics.

aspect_ratio: float

The ratio of ellipse axes, indicating ROI elongation.

compactness: float

The ratio of actual to expected mean radius, floored at 1.0, where values near 1 indicate compact circular ROIs.

footprint: int

The index of the multiscale detection level at which this ROI was found during sparse detection. Zero for tracked multi-recording ROIs, which bypass multiscale detection.

static load_list(masks_path, statistics_path)

Loads a list of ROIStatistics instances from companion masks and statistics .npz files.

Parameters:
  • masks_path (Path) – The path to the masks .npz file containing spatial pixel data.

  • statistics_path (Path) – The path to the statistics .npz file containing shape and extraction data.

Return type:

list[ROIStatistics]

Returns:

A list of ROIStatistics instances with pixel data from the masks file and shape data from the statistics file.

mask: ROIMask

The spatial data of the ROI these statistics describe.

neuropil_mask: NDArray[int32] | None

The raveled (flattened) pixel indices used for neuropil signal extraction. Each index refers to a pixel position in the row-major flattened representation of the imaging plane (height * width). Use np.unravel_index with the plane dimensions to recover 2D coordinates if needed.

normalized_pixel_count: float

The pixel count normalized by expected ROI size (soma region only).

pixel_count: int

The total number of pixels in the complete ROI.

plane_index: int

The index of the imaging plane this ROI belongs to. The IO layer populates this field during multi-plane combination, when ROIs from individual planes are merged into a single list.

static save_list(roi_list, masks_path, statistics_path)

Saves a list of ROIStatistics instances to two companion .npz files without pickle.

Spatial pixel data (coordinates, weights, centroid) is delegated to ROIMask.save_list and written to masks_path. Shape statistics and extraction statistics are written to statistics_path.

Parameters:
  • roi_list (list[ROIStatistics]) – The list of ROIStatistics instances to save.

  • masks_path (Path) – The path to the output masks .npz file (spatial data).

  • statistics_path (Path) – The path to the output statistics .npz file (shape and extraction data).

Return type:

None

skewness: float | None

The skewness of the neuropil-corrected fluorescence time series.

solidity: float

The ratio of soma pixels to convex hull area, measuring how solid/filled the ROI is.

soma_mask: NDArray[bool] | None

The boolean mask indicating which pixels belong to the soma region.

class cindra.dataclasses.ROITracking(threshold=0.75, mask_prevalence=50, pixel_prevalence=50, step_sizes=(200, 200), bin_size=50, maximum_distance=20, minimum_size=25)

Bases: object

Stores parameters for tracking ROIs across multiple registered recordings using spatial clustering.

bin_size: int

The extension, in pixels, added to each spatial bin boundary in both directions when collecting ROI masks for clustering. This overlap between neighboring bins ensures that ROIs near bin borders are clustered correctly.

mask_prevalence: int

The minimum percentage of registered recordings that must contain a given ROI for it to be included in the tracked ROI set. Clusters with members in fewer recordings than this threshold are discarded.

maximum_distance: int

The maximum centroid distance, in pixels, between two ROI masks for them to be considered a candidate pair. Only pairs that pass this spatial pre-filter proceed to the Jaccard overlap comparison controlled by threshold.

minimum_size: int

The minimum number of non-overlapping pixels a cross-recording template mask must contain after removing pixels shared with other templates. Templates below this size are discarded as too small to represent a valid ROI.

pixel_prevalence: int

The minimum percentage of a cluster’s member ROIs in which a pixel must appear for it to be included in the ROI’s cross-recording template mask. Pixels below this threshold are excluded, so only spatially stable regions of each tracked ROI contribute to the template used for fluorescence extraction across recordings.

step_sizes: tuple[int, int]

The block size, in pixels, as (height, width) used to partition the deformed visual space into spatial bins for clustering. Smaller blocks reduce memory usage but increase processing overhead. Both entries must hold the same value, because tracking bins the space with a single square step and rejects a configuration whose height and width differ.

threshold: float

The Jaccard distance threshold for the hierarchical clustering algorithm. Candidate ROI pairs that pass the maximum_distance pre-filter are compared by spatial overlap (Jaccard distance, 0 = identical, 1 = no overlap) and clustered together as the same ROI if their Jaccard distance is below this value.

class cindra.dataclasses.RecordingIO(recording_directories=(), dataset_name='', repeat_selection=False)

Bases: object

Stores the parameters that specify input recording locations and output directories.

dataset_name: str

Specifies the name of the multi_recording dataset. The name is lowercased and used to create the output directory under each recording’s cindra directory (e.g., recording/cindra/multi_recording/{dataset_name}/), and the tracker file for that dataset is written inside that same directory.

recording_directories: tuple[Path, ...]

Specifies the recordings to include in multi-recording processing as absolute paths to their root directories. Recordings are natural-sorted, and the first recording after sorting becomes the ‘main recording’ which stores the processing tracker file. Each recording directory is expected to contain the combined_metadata.npz file created by the single-recording processing pipeline.

repeat_selection: bool

Determines whether to repeat the ROI selection step when processing. When True, the pipeline re-runs ROI selection filtering using the current ROI selection parameters, even if selected ROIs already exist. This allows updated single-recording results or modified selection criteria to be integrated into multi-recording processing. When False (default), existing ROI selections are used if present.

class cindra.dataclasses.ReferenceImageType(*values)

Bases: StrEnum

Defines the supported reference image types for diffeomorphic registration across recordings.

ENHANCED_MEAN = 'enhanced_mean'

The high-pass filtered mean image that enhances ROI boundaries for improved registration.

MAXIMUM_PROJECTION = 'maximum_projection'

The maximum of every pixel across the temporally binned and high-pass filtered movie, zero outside the valid registration crop, highlighting active structures.

MEAN = 'mean'

The mean of the temporally binned movie, which excludes the frames registration marked bad and is zero outside the valid registration crop.

class cindra.dataclasses.Registration(repeat_registration=False, align_by_first_channel=True, reference_frame_count=500, batch_size=100, maximum_offset_fraction=0.1, spatial_smoothing_sigma=1.15, temporal_smoothing_sigma=0.0, two_step_registration=False, gpu_batch_size=0, bad_frame_threshold=1.0, normalize_frames=True, registration_metric_principal_components=5, compute_bidirectional_phase_offset=False, bidirectional_phase_offset_override=0)

Bases: object

Stores parameters for rigid registration, which is used to correct motion artifacts between frames by counter-shifting the entire frame.

align_by_first_channel: bool

Determines whether to use the first channel for frame alignment (registration). When False, the second channel is used instead. If the recording features both a functional and non-functional channel, it is recommended to use the non-functional channel for alignment. This field is only applicable when two_channels is True in the Main configuration.

bad_frame_threshold: float

The threshold for identifying frames with excessive motion or poor correlation quality. The algorithm computes a ratio of motion deviation to phase correlation quality for each frame. Frames exceeding this threshold (scaled by 100 internally) are marked as ‘bad’ and excluded when computing the valid pixel region (valid_y_range, valid_x_range) after registration. This prevents a few frames with extreme motion from unnecessarily shrinking the usable field of view. Bad frames may also be excluded during movie binning for ROI detection. Lower values are more strict and exclude more frames.

batch_size: int

The number of frames to keep in memory at the same time when registering them to the reference image. When processing data on fast (NVME) drives, increasing this parameter has minimal benefits and results in undue RAM use overhead. On slow drives, increasing this number may result in faster runtime, at the expense of increased RAM use.

bidirectional_phase_offset_override: int

Manual override for the bidirectional phase offset in line scanning 2-photon recordings. If set to any value besides 0, this offset is used instead of computing it automatically. If set to 0 and compute_bidirectional_phase_offset is True, the pipeline estimates the offset automatically from the initial reference frames.

compute_bidirectional_phase_offset: bool

Determines whether to compute the bidirectional phase offset for misaligned line scanning in two-photon recordings. This correction addresses misalignment between odd and even scan lines caused by bidirectional resonant scanning. Most recording software (including ScanImage) handles this correction during acquisition, so this option is rarely needed for properly configured systems.

gpu_batch_size: int

The number of frames to keep in device memory at the same time while registration runs on a CUDA device. This overrides batch_size for the alignment pass on that path, where the device memory budget bounds the batch instead of the host RAM budget, while the secondary channel pass reads batch_size. Setting this to 0 uses batch_size on the device as well.

maximum_offset_fraction: float

The maximum allowed offset during registration, given as a fraction of the frame size (e.g., 0.1 indicates 10%). This determines how much the algorithm is allowed to offset the entire frame to align it to the reference image.

normalize_frames: bool

Determines whether to clip pixel intensities to the 1st-99th percentile range during registration. This removes extreme outlier pixels from both the reference image and each frame before computing phase correlation, improving offset detection accuracy by reducing the influence of anomalously bright or dark pixels.

reference_frame_count: int

The number of frames to use to compute the reference image. During registration, each frame is registered to the reference image to remove motion artifacts. The algorithm automatically selects the most stable (correlated) set of frames when computing the reference image.

registration_metric_principal_components: int

The number of Principal Components (PCs) used to compute the registration quality metrics. These metrics are not used by the processing pipeline but are useful for assessing registration quality via the GUI. Computing metrics is a fairly expensive operation that can take as long as the registration itself. The time to compute scales with the number of computed PCs, so it is recommended to keep this as low as feasible. Set to 0 to disable registration metrics computation entirely.

repeat_registration: bool

Determines whether to re-register data that appears to already be registered. When False, the pipeline skips registration if the data is already registered. When True, the pipeline re-registers the data regardless of its current registration state.

spatial_smoothing_sigma: float

The standard deviation (in pixels) of the Gaussian filter used to spatially smooth the phase correlation surface between the reference image and each processed frame. Smoothing helps reduce noise in the correlation surface, improving the accuracy of sub-pixel offset detection. Higher values produce more smoothing but may reduce precision for detecting small offsets.

temporal_smoothing_sigma: float

The standard deviation (in frames) of the Gaussian filter used to temporally smooth the phase correlation surface across consecutive frames. This reduces frame-to-frame noise in correlation values and can improve registration stability for noisy recordings. Setting this to 0.0 disables temporal smoothing.

two_step_registration: bool

Determines whether to perform a two-step registration. This process consists of the initial registration (first step) followed by refinement (second step) registration. This procedure is helpful when working with low signal-to-noise data.

class cindra.dataclasses.RegistrationData(valid_y_range=(0, 0), valid_x_range=(0, 0), bad_frames=None, bidirectional_phase_offset=0, bidirectional_phase_corrected=False, normalization_minimum=0, normalization_maximum=0, reference_image=None, rigid_y_offsets=None, rigid_x_offsets=None, rigid_correlations=None, nonrigid_y_offsets=None, nonrigid_x_offsets=None, nonrigid_correlations=None, principal_component_extreme_images=None, principal_component_projections=None, principal_component_shift_metrics=None)

Bases: object

Stores runtime data from the registration stage.

bad_frames: NDArray[bool] | None

A boolean array with shape (num_frames,) marking frames with excessive motion or poor correlation. Computed during registration crop calculation and used during detection for temporal binning.

bidirectional_phase_corrected: bool

Determines whether bidirectional phase correction was applied during registration.

bidirectional_phase_offset: int

The phase offset in pixels used to correct bidirectional scanning artifacts.

clear()

Clears all registration data to prepare for re-registration.

Return type:

None

is_registered(output_path=None)

Checks whether registration data exists in memory or on disk.

Notes

The on-disk check requires the same three arrays the in-memory check requires. save_arrays writes each array as its own file, so an interrupted save leaves a subset of them behind, and accepting any single file would report a plane registered while the offsets every later stage reads are absent.

Parameters:

output_path (Path | None, default: None) – The directory containing the registration_data/ subdirectory. When provided and arrays are not loaded in memory, checks for registration files on disk. The calling context is responsible for resolving the correct path.

Return type:

bool

Returns:

True if the reference image and both rigid offset arrays are loaded in memory or exist on disk at the given output path, False otherwise.

load_arrays(output_path)

Loads registration arrays from individual .npy files in the registration_data/ subdirectory.

Parameters:

output_path (Path) – The directory containing the registration_data/ subdirectory.

Return type:

None

memory_map_arrays(output_path)

Memory-maps registration arrays from individual .npy files in the registration_data/ subdirectory.

Uses r mode, so the mapped arrays are read-only. This avoids loading the full array contents into memory, which is useful when reusing previously-generated data.

Parameters:

output_path (Path) – The directory containing the registration_data/ subdirectory.

Return type:

None

nonrigid_correlations: NDArray[float32] | None

The phase correlation values from nonrigid registration, indicating alignment quality per frame and block.

nonrigid_x_offsets: NDArray[float32] | None

The horizontal (X) translation offsets from nonrigid registration, per frame and per block.

nonrigid_y_offsets: NDArray[float32] | None

The vertical (Y) translation offsets from nonrigid registration, per frame and per block.

normalization_maximum: int

The maximum intensity value used for normalizing frames during registration.

normalization_minimum: int

The minimum intensity value used for normalizing frames during registration.

prepare_for_saving()

Sets all array fields to None for YAML serialization.

Return type:

None

principal_component_extreme_images: NDArray[float32] | None

The mean images from frames at extreme ends of each principal component of the registered recording movie, with shape (2, num_components, valid_height, valid_width), where the spatial dimensions are the border-cropped valid ranges. Index 0 contains low-projection means, index 1 contains high-projection means.

principal_component_projections: NDArray[float32] | None

The projection of each sampled frame onto the principal components of the registered recording movie, with shape (sampled_frames, num_components). The metrics stage subsamples evenly-spaced frames, so this holds one row per sampled frame rather than per recording frame.

principal_component_shift_metrics: NDArray[float32] | None

The registration offset metrics computed by aligning PC extreme images of the registered recording movie, with shape (num_components, 3). Column 0 contains the rigid offset magnitude, column 1 contains mean nonrigid offset magnitude, and column 2 contains maximum nonrigid offset magnitude. Large values indicate poor registration quality.

reference_image: NDArray[float32] | None

The template image used as the alignment target for motion correction.

release_arrays()

Releases all array fields to free memory.

Scalar fields (valid ranges, normalization bounds, etc.) are preserved. Use memory_map_arrays() or load_arrays() to re-acquire the data on demand.

Return type:

None

rigid_correlations: NDArray[float32] | None

The phase correlation values from rigid registration, indicating alignment quality per frame.

rigid_x_offsets: NDArray[int32] | None

The horizontal (X) translation offsets from rigid registration, one value per frame.

rigid_y_offsets: NDArray[int32] | None

The vertical (Y) translation offsets from rigid registration, one value per frame.

save_arrays(output_path)

Saves registration arrays as individual .npy files inside a registration_data/ subdirectory.

Parameters:

output_path (Path) – The directory in which to create the registration_data/ subdirectory.

Return type:

None

valid_x_range: tuple[int, int]

The valid X pixel range (start, end) defining the usable recording region after border cropping.

valid_y_range: tuple[int, int]

The valid Y pixel range (start, end) defining the usable recording region after border cropping.

class cindra.dataclasses.RuntimeContext(configuration, acquisition, runtime)

Bases: object

Combines configuration, acquisition parameters, and runtime data used in the single-recording processing pipeline.

Notes

Each RuntimeContext instance represents a single plane (or virtual plane for MROI data). The configuration and acquisition fields are shared across all planes, while the runtime field contains plane-specific data.

acquisition: AcquisitionParameters

The acquisition parameters loaded from the input data’s JSON file. This describes the recording setup including frame rate, plane count, channel count, and MROI geometry if applicable.

configuration: SingleRecordingConfiguration

The user-defined processing configuration, which remains immutable during processing.

classmethod load(root_path, plane_index=-1)

Loads one or more RuntimeContext instances from disk.

Searches root_path recursively for configuration.yaml to discover the cindra output directory, then loads shared configuration, acquisition parameters, and plane-specific runtime data. If the dataset was moved to a different location, stale output_path values in each plane’s runtime YAML are silently corrected so that array loading succeeds.

Parameters:
  • root_path (Path) – The path to the recording’s root processed data directory. The method searches recursively for configuration.yaml to locate the cindra output directory.

  • plane_index (int, default: -1) – The index of the plane to load. Use -1 to load all available planes.

Return type:

RuntimeContext | list[RuntimeContext]

Returns:

A single RuntimeContext if plane_index >= 0, or a list of all RuntimeContext instances if plane_index is -1.

Raises:
  • FileNotFoundError – If no configuration.yaml is found, or if required files are missing.

  • RuntimeError – If multiple configuration.yaml files are found under root_path.

runtime: SingleRecordingRuntimeData

The runtime data, which is computed and updated by pipeline stages.

save_runtime()

Saves this plane’s runtime data to its output directory.

Raises:

ValueError – If output_path is not set in the runtime IOData.

Return type:

None

save_shared()

Saves shared configuration and acquisition parameters to the root output directory.

Derives the root path from self.configuration.file_io.output_path and creates the cindra subdirectory if it does not exist.

Raises:

ValueError – If output_path is not configured in the configuration.

Return type:

None

class cindra.dataclasses.RuntimeSettings(display_progress_bars=False)

Bases: object

Stores runtime behavior settings shared between single-recording and multi-recording processing pipelines.

display_progress_bars: bool

Determines whether to display progress bars for certain processing steps. Only enable this option when running all processing steps sequentially. Having this enabled when running multiple recordings or planes in parallel may interfere with properly communicating progress via the terminal.

class cindra.dataclasses.SignalExtraction(extract_neuropil=True, allow_overlap=False, minimum_neuropil_pixels=350, inner_neuropil_border_radius=2, cell_probability_percentile=50, classification_threshold=0.5, batch_size=500, colocalization_threshold=0.65)

Bases: object

Stores parameters for extracting fluorescence signals from ROIs and surrounding neuropil regions.

allow_overlap: bool

Determines whether to include overlapping pixels (shared by multiple ROIs) in signal extraction. When disabled, pixels belonging to multiple ROIs are excluded from all of them to prevent signal contamination between neighboring ROIs. Enable this only if ROIs are sparse and overlap is minimal.

batch_size: int

The number of frames to process at the same time during fluorescence extraction. This controls memory usage during the extraction step. Larger values may improve throughput on fast storage but increase RAM consumption. This is independent of the registration batch size. The same value is reused as the number of ROIs per batch during OASIS spike deconvolution, where it bounds the four (batch, frames) workspace arrays that stage allocates.

cell_probability_percentile: int

The percentile threshold for classifying pixels as belonging to a cell versus neuropil. Each pixel has a probability weight indicating how likely it belongs to a cell. Pixels with weights above this percentile (computed locally) are excluded from neuropil masks. Higher values are more permissive, including more pixels in neuropil masks but risking cell contamination.

classification_threshold: float

The classifier probability threshold used to classify ROIs after signal extraction. This is the minimum classifier confidence value (that the classified ROI is a cell) for the ROI to be labeled as a cell. ROIs with probabilities below this threshold are labeled as non-cells but are still retained in the output data.

colocalization_threshold: float

The threshold for determining whether ROIs from one channel correspond to ROIs or signals in the other channel. When one channel is functional and the other is structural, this threshold applies to intensity-based colocalization: ROIs are marked as colocalized if their inside-to-total intensity ratio in the structural channel exceeds this value. When both channels are functional, this threshold applies to spatial colocalization: ROIs are matched if their pixel overlap fraction exceeds this value.

extract_neuropil: bool

Determines whether to extract neuropil activity. If disabled, neuropil fluorescence is assumed to be zero during spike deconvolution.

inner_neuropil_border_radius: int

The width, in pixels, of the exclusion zone between the cell ROI and its neuropil mask. This gap prevents contamination of the neuropil signal by the cell’s own fluorescence. Larger values provide better separation but reduce the neuropil sampling area near the cell.

minimum_neuropil_pixels: int

The minimum number of pixels required for each neuropil mask. The algorithm expands outward from the cell border until it accumulates at least this many non-cell pixels. Larger values provide more stable neuropil estimates but may include pixels from distant regions with different neuropil characteristics.

class cindra.dataclasses.SingleRecordingConfiguration(runtime=<factory>, main=<factory>, file_io=<factory>, registration=<factory>, one_photon_registration=<factory>, nonrigid_registration=<factory>, roi_detection=<factory>, signal_extraction=<factory>, spike_deconvolution=<factory>)

Bases: YamlConfig

Aggregates the user-defined configuration parameters for the single-recording cindra pipeline.

The pipeline reads these parameters and treats them as immutable for the duration of processing.

Notes

Derives from the ‘default_ops’ dictionary of the original suite2p package. The default parameters are tuned for working with GCaMP6F fluorescence data recorded using 2-Photon Random Access Mesoscope (2P-RAM).

For runtime data (computed by the pipeline), see SingleRecordingRuntimeData.

file_io: FileIO

Stores general I/O parameters that specify the input data location, the ignored input file names, and the output directory.

classmethod load(file_path)

Loads configuration from a YAML file.

Parameters:

file_path (Path) – The path to the .yaml configuration file.

Return type:

SingleRecordingConfiguration

Returns:

The single-recording configuration the YAML file stores.

main: Main

Stores global parameters that broadly define the cindra single-recording processing configuration.

nonrigid_registration: NonrigidRegistration

Stores parameters for nonrigid registration, which is used to improve motion registration in complex datasets.

one_photon_registration: OnePhotonRegistration

Stores parameters for additional pre-registration processing used to improve the registration of 1-photon datasets.

pipeline_type: PipelineType = 'single-recording'

Identifies this configuration as a single-recording pipeline configuration.

registration: Registration

Stores parameters for rigid registration, which is used to correct motion artifacts between frames by counter-shifting the entire frame.

roi_detection: ROIDetection

Stores parameters for ROI detection and extraction.

runtime: RuntimeSettings

Stores runtime behavior settings shared with the multi-recording pipeline (progress bar display).

save(file_path)

Saves the configuration to a YAML file.

Parameters:

file_path (Path) – The path to the .yaml file in which to save the configuration data.

Return type:

None

signal_extraction: SignalExtraction

Stores parameters for extracting fluorescence signals from ROIs and surrounding neuropil regions.

spike_deconvolution: SpikeDeconvolution

Stores parameters for deconvolving fluorescence signals to infer spike trains.

class cindra.dataclasses.SingleRecordingRuntimeData(output_path=None, io=<factory>, registration=<factory>, detection=<factory>, extraction=<factory>, timing=<factory>)

Bases: YamlConfig

Aggregates all runtime data for a single plane.

detection: DetectionData

The runtime data from the detection stage.

extraction: ExtractionData

The runtime data from the extraction and classification stages.

io: IOData

The runtime data from the IO/binarization stage.

classmethod load(output_path)

Deserializes runtime data from a YAML file without loading any NumPy arrays.

Parameters:

output_path (Path) – The directory containing the runtime_data.yaml file.

Return type:

SingleRecordingRuntimeData

Returns:

A SingleRecordingRuntimeData instance with all scalar fields deserialized. NumPy array fields remain None until explicitly loaded.

load_arrays()

Eagerly loads the registration, detection, and extraction arrays that the pipeline stages need.

Reads each array file in full and copies it into a contiguous in-memory buffer. Extraction fluorescence traces and colocalization arrays are excluded, and extraction.load_results() acquires them.

Return type:

None

memory_map_arrays()

Memory-maps the registration, detection, and extraction arrays the pipeline stages need, in r mode.

Opens each .npy file as a read-only memory-mapped array, avoiding full materialization in RAM. ROI statistics are eagerly loaded instead, because NumPy cannot memory-map .npz archives. Extraction fluorescence traces and colocalization arrays are excluded, and extraction.memory_map_results() maps them.

Return type:

None

output_path: Path | None = None

The path to the directory where runtime data and .npy files are stored.

registration: RegistrationData

The runtime data from the registration stage.

release_arrays()

Releases all array fields across registration, detection, and extraction to free memory.

Delegates to the release_arrays() method on each child dataclass. Scalar fields are preserved.

Return type:

None

save(output_path)

Saves the runtime data to a YAML file and arrays to .npz/.npy files.

Saves all NumPy arrays as separate .npz/.npy files in the output directory, then creates a shallow copy of the instance and of each child dataclass, with arrays set to None, before writing the YAML file. to_yaml() performs the Path-to-string conversion.

Notes

This storage form avoids pickle serialization in favor of safer YAML and NumPy serialization.

Parameters:

output_path (Path) – The directory in which to save the runtime_data.yaml file and .npz/.npy files.

Return type:

None

timing: TimingData

The pipeline timing information.

class cindra.dataclasses.SpikeDeconvolution(extract_spikes=True, neuropil_coefficient=0.7, baseline_method=BaselineMethod.MAXIMIN, baseline_window=60.0, baseline_sigma=10.0, baseline_percentile=8.0)

Bases: object

Stores parameters for deconvolving fluorescence signals to infer spike trains.

baseline_method: BaselineMethod | str

The method for computing baseline fluorescence to subtract before deconvolution. See BaselineMethod enumeration for available options: MAXIMIN tracks the lower envelope using sliding window filters, CONSTANT uses the global minimum, and CONSTANT_PERCENTILE uses a low percentile as a robust constant baseline.

baseline_percentile: float

The percentile of trace activity used as baseline for the ‘constant_percentile’ method. Lower values (e.g., 8) select points near the trace minimum, providing a robust estimate that ignores outliers. Only used when baseline_method is set to CONSTANT_PERCENTILE.

baseline_sigma: float

The standard deviation, in frames, of the Gaussian filter applied before baseline computation. Used by both ‘maximin’ and ‘constant’ methods to smooth the trace before finding minima. Larger values produce more aggressive smoothing.

baseline_window: float

The size of the sliding window, in seconds, for the ‘maximin’ baseline method. The minimum and maximum filters operate over this window to track slow baseline drifts while ignoring fast transients. Larger windows produce smoother baselines but may fail to track rapid baseline changes.

extract_spikes: bool

Determines whether to deconvolve spike activity from the extracted fluorescence traces. When disabled, the pipeline still extracts the raw cell and neuropil fluorescence, but both the neuropil-corrected (baseline-subtracted) traces and the spike traces are filled with zeros instead of being computed.

neuropil_coefficient: float

The scaling factor applied to neuropil fluorescence before subtracting it from cell fluorescence. The corrected signal is computed as F_corrected = F_cell - coefficient * F_neuropil. Values typically range from 0.5 to 1.0, with 0.7 being a common default. Higher values apply stronger neuropil correction but risk over-subtracting signal from cells with weak neuropil contamination.

class cindra.dataclasses.TimingData(binarization_time=0, registration_time=0, two_step_registration_time=0, registration_metrics_time=0, detection_time=0, extraction_time=0, classification_time=0, deconvolution_time=0, detection_time_channel_2=0, extraction_time_channel_2=0, classification_time_channel_2=0, deconvolution_time_channel_2=0, total_registration_time=0, total_processing_time=0, registration_workers=0, processing_workers=0, date_processed='', python_version='3.14.7', cindra_version='2.0.0')

Bases: object

Stores pipeline timing and version data.

Notes

All time durations are stored as integers representing seconds.

binarization_time: int

The TIFF to binary conversion time in seconds.

cindra_version: str

The cindra version used for processing.

classification_time: int

The ROI classification time in seconds.

classification_time_channel_2: int

The channel 2 ROI classification time in seconds.

date_processed: str

The timestamp when processing completed in ataraxis-time format (yyyy-mm-dd-hh-mm-ss-us).

deconvolution_time: int

The spike deconvolution time in seconds.

deconvolution_time_channel_2: int

The channel 2 spike deconvolution time in seconds.

detection_time: int

The ROI detection time in seconds.

detection_time_channel_2: int

The channel 2 ROI detection time in seconds.

extraction_time: int

The fluorescence extraction time in seconds.

extraction_time_channel_2: int

The channel 2 fluorescence extraction time in seconds.

processing_workers: int

The number of parallel workers allocated to the plane’s processing stage.

python_version: str

The Python version used for processing.

registration_metrics_time: int

The registration metrics computation time in seconds.

registration_time: int

The registration step time in seconds.

registration_workers: int

The number of parallel workers allocated to the plane’s registration stage.

total_processing_time: int

The total plane processing time in seconds, covering ROI detection, trace extraction, classification, and spike deconvolution.

total_registration_time: int

The total plane registration time in seconds, covering motion correction and the registration quality metrics computation.

two_step_registration_time: int

The second registration step time in seconds.

cindra.dataclasses.detect_pipeline_type(file_path)

Detects the pipeline type stored in the specified configuration YAML file.

Reads the pipeline_type discriminator field from the configuration file without loading the full configuration dataclass.

Parameters:

file_path (Path) – The path to the configuration YAML file to inspect.

Return type:

PipelineType

Returns:

The pipeline the configuration file’s pipeline_type field names.

Raises:
  • FileNotFoundError – If the configuration file does not exist or does not have a ‘.yaml’ extension.

  • ValueError – If the file does not contain a recognized pipeline_type value.

Orchestration

Provides the pipeline job model, the worker allocation, the batch execution engine, and the pipeline entry points.

class cindra.orchestration.GpuDevice(index, name, total_memory_mb, compute_capability)

Bases: object

Describes one CUDA device the host exposes.

compute_capability: str

The compute capability of the device, written as ‘major.minor’.

index: int

The zero-based index the registration backend uses to select this device.

name: str

The marketing name the driver reports for the device.

total_memory_mb: int

The total device memory, in megabytes.

class cindra.orchestration.GpuStatus(*values)

Bases: StrEnum

Defines the outcome of a request to resolve the CUDA devices the registration stage uses.

AVAILABLE = 'available'

At least one device is present and the runtime performs a transform on it.

LIBRARIES_MISSING = 'libraries_missing'

The CuPy distribution is present, and the CUDA math libraries it loads on first use are absent.

NO_DEVICES = 'no_devices'

The driver exposes no device the CUDA runtime reports, or the runtime library itself does not load.

RUNTIME_MISSING = 'runtime_missing'

The CuPy distribution is absent, so no device is reachable.

UNSUPPORTED_PLATFORM = 'unsupported_platform'

The host runs macOS, for which the CuPy distribution publishes no wheel.

class cindra.orchestration.GpuSummary(status, devices, detail)

Bases: object

Summarizes the CUDA devices the host exposes and whether the registration stage runs on them.

property available: bool

Returns True when the registration stage runs on a CUDA device of this host.

describe()

Builds a one-line human-readable summary of what the resolution found.

Return type:

str

Returns:

A compact description of the outcome.

detail: str

The reason the runtime is unusable, empty when the status is AVAILABLE.

devices: tuple[GpuDevice, ...]

The devices the backend uses, empty for every outcome other than AVAILABLE.

property remedy: str

Returns the command that resolves the runtime, empty when the runtime is already usable or when the host platform carries no CuPy wheel.

status: GpuStatus

The outcome of the resolution.

class cindra.orchestration.JobSizing(cores, memory_mb, device_memory_mb)

Bases: object

Describes the resources one job receives, as one sizing pass resolved them.

cores: int

The CPU cores the job occupies while it runs, as the stage’s default declares them.

device_memory_mb: int

The device memory the job occupies at its peak, in megabytes, which is zero for a job that holds no CUDA device.

memory_mb: int

The memory the job occupies at its peak, in megabytes.

class cindra.orchestration.MultiRecordingJobNames(*values)

Bases: StrEnum

Defines the job names for the multi-recording processing pipeline components.

DISCOVER = 'discovery'

The name for the ROI discovery (step 1) processing job.

EXTRACT = 'extraction'

The generic name for the fluorescence extraction (step 2) processing job. During runtime, the processed recording is identified by the tracker’s specifier field, which stores the recording ID string.

class cindra.orchestration.MultiRecordingJobs(dataset_name, recording_ids=(), universe=(), possible=(), resolved=False)

Bases: object

Describes the multi-recording jobs one tracked dataset declares and the subset whose inputs already exist.

dataset_name: str

The name of the tracked dataset, already lowered to the fold the output directory carries.

possible: tuple[tuple[str, str], ...]

The subset of the universe whose own input exists on disk right now.

recording_ids: tuple[str, ...]

The identifier of every recording the dataset spans.

resolved: bool

Determines whether the universe follows from the dataset spanning at least one recording.

universe: tuple[tuple[str, str], ...]

Every job the dataset declares, as job name and specifier pairs.

class cindra.orchestration.OpenMPStatus(*values)

Bases: StrEnum

Defines the outcome of a request to make the OpenMP runtime loadable.

AVAILABLE = 'available'

The runtime already loads, so nothing was changed.

LINKED = 'linked'

The discovered runtime was linked into a directory the dynamic loader searches.

PREVIEWED = 'previewed'

The link was resolved and reported as a dry run, so nothing was changed.

UNRESOLVED = 'unresolved'

No OpenMP runtime was found to link, so nothing was changed.

class cindra.orchestration.OpenMPSummary(status, unresolved_reason, runtime_path, link_path, searched_paths, loadable)

Bases: object

Summarizes a request to make the OpenMP runtime loadable, whether previewed as a dry run or carried out.

describe()

Builds a one-line human-readable summary of what the call resolved and what it changed.

Return type:

str

Returns:

A compact description of the outcome.

The absolute path to the link that makes the runtime loadable, or None when no runtime was found.

loadable: bool

Determines whether the OpenMP runtime loads from a fresh interpreter once the call returns.

runtime_path: Path | None

The absolute path to the discovered OpenMP runtime, or None when none was found.

searched_paths: tuple[Path, ...]

The candidate paths discovery walked, in the order it walks them, which stops at the first one holding a runtime.

status: OpenMPStatus

The outcome of the request.

unresolved_reason: str

The reason no OpenMP runtime was found, empty for every other outcome.

class cindra.orchestration.PendingJob(configuration_path, tracker_path, job_id, single_recording, resource_class, resolved_workers=None, assigned_device=None, memory_megabytes=0, device_memory_megabytes=0)

Bases: object

Describes a single pipeline job queued for batch execution.

assigned_device: int | None

The zero-based index of the CUDA device this job holds while it runs, taken from the session free list at dispatch time and returned to it when the job leaves the running set.

Notes

A job of a host-only class carries None for its whole life, which runs its registration on the host CPU. A device-backed job carries an index the session free list supplied, because a session holding no device admits no such job.

configuration_path: Path

The path to the pipeline configuration file for this job.

device_memory_megabytes: int

The device memory this job holds while it runs, as the caller’s sizing pass estimated it.

Notes

A value of zero states that the caller supplied no estimate, or that the job runs on the host CPU, and either case admits the job without reading the device. The figure bounds admission rather than concurrency, because the devices a session holds already bound how many device-backed jobs run at once.

property dispatch_key: tuple[str, str]

Returns the composite tracker path and job identifier pair that identifies this job across the batch.

job_id: str

The unique hexadecimal identifier for this job in the tracker.

memory_megabytes: int

The memory this job holds while it runs, as the caller’s sizing pass estimated it.

Notes

A value of zero states that the caller supplied no estimate, which leaves the job admitted on the core budget alone. Memory is carried per job rather than per resource class, because the memory one job holds follows the recording it processes rather than the stage it runs.

resolved_workers: int | None

The number of parallel workers to allocate to this job, assigned at dispatch time. A value of None makes the pipeline fall back to the default for the job’s stage.

resource_class: ResourceClass

The resource class that governs this job’s worker count and the concurrency of its queue.

single_recording: bool

Determines whether this job belongs to a single-recording or multi-recording pipeline.

tracker_path: Path

The path to the ProcessingTracker file that tracks this job.

class cindra.orchestration.PipelinePhase(job_name, per_specifier, prerequisite, prerequisite_scope)

Bases: object

Describes one phase of a cindra processing pipeline.

job_name: str

The tracker job name that identifies the phase.

per_specifier: bool

Determines whether the phase expands into one job per specifier instead of a single job.

prerequisite: str | None

The job name of the phase that must succeed before this phase runs, or None for the pipeline’s first phase.

prerequisite_scope: PrerequisiteScope

Determines which jobs of the preceding phase gate this phase’s jobs.

class cindra.orchestration.PlaneGeometry(height, width, frame_count, sampling_rate, index=0)

Bases: object

Describes the shape one virtual imaging plane will hold, as the acquisition metadata and the source file header fix it before the conversion runs.

frame_count: int

The frames the plane holds.

height: int

The height of the plane in pixels.

index: int

The position of the plane within the recording, which a per-plane job’s specifier names.

sampling_rate: float

The rate at which the recording sampled this plane.

width: int

The width of the plane in pixels.

class cindra.orchestration.PrerequisiteScope(*values)

Bases: StrEnum

Defines how a phase’s prerequisite jobs are selected from the phase that precedes it.

ALL_JOBS = 'all_jobs'

Every job of the preceding phase must succeed, whatever specifier it carries.

MATCHING_SPECIFIER = 'matching_specifier'

Only the preceding phase’s job that carries the same specifier must succeed.

class cindra.orchestration.RecordingGeometry(planes=(), raw_frame_pixels=0, source_element_bytes=2, combined_pixels=0, combined_frame_count=0, two_channels=False, region_count=0, resolved=False, acquisition_resolved=False, source_resolved=False)

Bases: object

Describes the shape of one recording as its own output and acquisition parameters report it.

acquisition_resolved: bool

Determines whether the recording’s acquisition parameters were readable, which the raw acquisition resolution alone reports.

combined_frame_count: int

The frames the combined view holds, trimmed to the shortest contributing plane.

combined_pixels: int

The pixels one combined multi-plane frame holds, which every multi-recording stage uses.

planes: tuple[PlaneGeometry, ...]

The geometry of every virtual imaging plane, ordered by plane index.

raw_frame_pixels: int

The pixels one unsliced acquisition frame holds, which the conversion stage reads in batches.

region_count: int

The regions the recording’s combined trace array holds, which the multi-recording stages read from the single-recording output they process.

resolved: bool

Determines whether the geometry follows from the recording’s own data rather than from its absence.

source_element_bytes: int

The width of one element of the recording’s source files.

source_resolved: bool

Determines whether the recording’s source files were readable, which the raw acquisition resolution alone reports.

two_channels: bool

Determines whether the recording carries a second channel, which both the combination and the tracked extraction stages process alongside the first inside one job.

class cindra.orchestration.ResourceClass(name, workers_per_job, maximum_workers_per_job, concurrency_limit, concurrency_reservation)

Bases: object

Describes the cores one class of pipeline jobs holds and the concurrency terms that bound the class.

concurrency_limit: int | None

The jobs of this class that may run at once regardless of the capacity the budgets could still supply, or None when the class is bounded by the budgets alone.

Notes

This is a hard ceiling. It counts a resource the CPU budget does not supply, which is the storage a conversion reads and the devices a registration uses, so spare capacity never lifts it.

concurrency_reservation: int | None

The jobs of this class that run at once while other work can still use the capacity the class gives up, or None when the class competes at its full derived width.

Notes

This is a soft counterpart to the ceiling. It exists to leave room for other jobs rather than because the class stops gaining from concurrency, so the dispatcher releases it over whatever capacity remains once every other runnable job has been offered that room.

maximum_workers_per_job: int | None

The most CPU cores one job of this class holds when the host has capacity to spare, or None when the class is not elastic and every one of its jobs runs at workers_per_job.

Notes

The ceiling is the width at which the stage stops converting cores into wall clock, so an allocation past it holds capacity another job would turn into throughput. A class carries None when its work waits on something the host cores do not supply, which covers the storage the conversion reads, the serial merge the combination stage performs, and the device a registration job holds.

name: str

The name of the resource class, used as the key of the per-class queues and of the reported allocation.

workers_per_job: int

The number of CPU cores each job of this class holds while the session dispatches at its full concurrency.

class cindra.orchestration.SingleRecordingJobNames(*values)

Bases: StrEnum

Defines the job names for the single-recording processing pipeline components.

Notes

The members are declared in execution order, and that order is rendered into the error messages that list the valid job names. The authoritative phase order and prerequisite graph live in SINGLE_RECORDING_PHASES.

BINARIZE = 'binarization'

The name for the binarization (step 1) processing job.

COMBINE = 'combination'

The name for the combination (step 4) processing job.

PROCESS = 'processing'

The generic name for the plane-processing (step 3) job, which discovers ROIs and extracts their fluorescence. During runtime, the processed plane is identified by the tracker’s specifier field using the format ‘plane_{plane_index}’.

REGISTER = 'registration'

The generic name for the plane-registration (step 2) job, which removes motion and computes the registration-quality principal components. During runtime, the registered plane is identified by the tracker’s specifier field using the format ‘plane_{plane_index}’.

class cindra.orchestration.SingleRecordingJobs(output_root, plane_count, universe=(), possible=(), resolved=False)

Bases: object

Describes the single-recording jobs one recording declares and the subset whose inputs already exist.

output_root: Path

The output root the universe resolution used.

plane_count: int

The virtual imaging planes the recording holds, which is zero when its parameters were not found.

possible: tuple[tuple[str, str], ...]

The subset of the universe whose own input exists on disk right now.

Notes

The conversion job is reported ready whenever the recording’s parameters resolve, which is the weakest of the four conditions, because its own input is the raw image set this record does not read.

resolved: bool

Determines whether the universe follows from the recording’s own parameters rather than from their absence.

universe: tuple[tuple[str, str], ...]

Every job the recording declares, as job name and specifier pairs.

Notes

This is a recording fingerprint rather than an invocation fingerprint, so every invocation aligns a tracker against the same set whatever subset it intends to run.

cindra.orchestration.cancel_execution_session()

Clears every queued job of the active session, leaving the running jobs to finish.

Notes

Cancellation empties the admission pool and every resource class queue, so the manager terminates once the running set drains. A job already dispatched keeps its worker process and the CUDA device it holds, since interrupting it partway would leave its output directory holding a partial result the tracker reports as running.

Return type:

tuple[int, int]

Returns:

The number of jobs cleared from the queues and the number of jobs left running, in that order.

cindra.orchestration.estimate_multi_recording_job_memory_mb(job_name, specifier, recording_directories, configuration, *, planned_roi_count=None)

Estimates the memory one multi-recording job occupies at its peak.

Notes

A discovery job spans every recording of the dataset, so it is estimated from all of them. An extraction job runs on one recording, which its specifier names, and is estimated from that recording alone.

The templates the tracking stage produces are the one figure the completed single-recording output does not report, and they do not exist when a plan covering the discovery stage is built. A caller that knows them passes them through planned_roi_count, and the bound the per-recording region counts provide covers them otherwise. Only the extraction stage reads the figure, because the discovery stage scales with the regions each recording reports rather than with the templates it produces.

Parameters:
  • job_name (MultiRecordingJobNames) – The pipeline stage the job runs.

  • specifier (str) – The job’s tracker specifier, which names a recording for the extraction stage.

  • recording_directories (Sequence[Path]) – The root directory of every recording the dataset spans, as the configuration’s recording_directories field holds them. Each is either the recording’s pipeline output directory or a directory containing it, matching the latitude the context resolver allows.

  • configuration (MultiRecordingConfiguration) – The dataset’s processing configuration.

  • planned_roi_count (int | None, default: None) – The tracked templates the plan covers, counting the dataset as a whole. Use None to accept the bound the per-recording region counts provide. Must be a positive integer when supplied.

Return type:

int

Returns:

The memory the job occupies in megabytes.

Raises:
  • FileNotFoundError – If the dataset names no recording directory, if any recording carries no combined metadata archive, or if any recording reports no regions in its combined trace array, in which case neither multi-recording stage can run.

  • ValueError – If planned_roi_count is supplied and is not a positive integer.

cindra.orchestration.estimate_single_recording_job_memory_mb(job_name, specifier, output_root, configuration, data_path=None, *, planned_roi_count=None, gpu_registration=False)

Estimates the memory one single-recording job occupies at its peak.

Notes

Every figure follows from the recording’s acquisition geometry, which the raw data fixes before any job runs, so a caller sizing a whole job graph up front receives the same answer at every point in the run. A per-plane job whose specifier does not resolve is charged the largest per-plane estimate, so an unmatched job never understates.

The regions detection will find are the one input the acquisition leaves open. A caller that knows them passes them through planned_roi_count, and the detection ceiling bounds them otherwise.

Parameters:
  • job_name (SingleRecordingJobNames) – The pipeline stage the job runs.

  • specifier (str) – The job’s tracker specifier, which names a plane for the per-plane stages and is empty otherwise.

  • output_root (Path) – The recording’s configured output root.

  • configuration (SingleRecordingConfiguration) – The recording’s processing configuration.

  • data_path (Path | None, default: None) – The recording’s configured raw imaging path, which is either the directory holding its source files or any parent of the directory that holds its acquisition parameters file. Every estimate reads the header of the first source file that directory holds.

  • planned_roi_count (int | None, default: None) – The regions the plan covers, counting every plane of the recording together. Use None to accept the ceiling the detection iteration bound provides. Must be a positive integer when supplied.

  • gpu_registration (bool, default: False) – Determines whether the registration jobs are planned for a CUDA device rather than the host CPU. Every other job name resolves the same figure whatever it holds.

Return type:

int

Returns:

The memory the job occupies in megabytes.

Raises:
  • FileNotFoundError – If the recording’s acquisition parameters were not readable or its raw imaging directory holds no readable source file, in which case no stage of it can run.

  • ValueError – If planned_roi_count is supplied and is not a positive integer, if both inputs were readable and still describe no whole imaging plane, or if a per-plane job’s specifier names an imaging plane the recording does not hold.

cindra.orchestration.execute_multi_recording_job(configuration_path, job_name, specifier, job_id, tracker, *, workers=None)

Executes one multi-recording job and records its state on a caller-provided tracker.

Notes

This is the tracker-injection entry point. The caller owns the tracker, aligns it with a universe that contains job_id, and passes both in, so cindra stages this job into a foreign tracker whose job names and granularity the caller controls. The job’s start, completion, and failure are recorded onto the provided tracker under job_id.

Every stage reads the shared bootstrap rather than writing it, so prime_dataset must have written it before any job runs. Priming is a separate call rather than a flag on this one, because a job that wrote the bootstrap while its peers ran would overwrite each peer recording’s runtime data with its own stale snapshot.

Parameters:
  • configuration_path (Path) – The path to the multi-recording configuration YAML file.

  • job_name (MultiRecordingJobNames) – The multi-recording job to run.

  • specifier (str) – The job specifier. For an EXTRACT job this is the recording identifier, and for a DISCOVER job it is an empty string.

  • job_id (str) – The unique hexadecimal identifier under which the job’s state is recorded on the provided tracker. It must already be present in the tracker’s aligned job set.

  • tracker (ProcessingTracker) – The caller-owned ProcessingTracker onto which this job’s start, completion, or failure is recorded.

  • workers (int | None, default: None) – The number of parallel workers to allocate to this job. Use None to accept the stage default and -1 to request every available core.

Raises:
  • FileNotFoundError – If the configuration file is missing, is not a .yaml file, or is not a valid multi-recording configuration.

  • ValueError – If the configuration specifies fewer than two recording directories or no dataset name, if job_name is not a recognized multi-recording job, or if workers is zero or a negative value other than -1.

Return type:

None

cindra.orchestration.execute_single_recording_job(configuration_path, job_name, specifier, job_id, tracker, *, workers=None, device=None)

Executes one single-recording job and records its state on a caller-provided tracker.

Notes

This is the tracker-injection entry point. The caller owns the tracker, aligns it with a universe that contains job_id, and passes both in, so cindra stages this job into a foreign tracker whose job names and granularity the caller controls. The job’s start, completion, and failure are recorded onto the provided tracker under job_id.

Every stage reads the shared bootstrap rather than writing it, so prime_recording must have written it before any job runs. Priming is a separate call rather than a flag on this one, because a job that wrote the bootstrap while its peers ran would overwrite each peer plane’s runtime data with its own stale snapshot.

Parameters:
  • configuration_path (Path) – The path to the single-recording configuration YAML file.

  • job_name (SingleRecordingJobNames) – The single-recording job to run.

  • specifier (str) – The job specifier. For a REGISTER or PROCESS job this encodes the plane index as ‘plane_{index}’, and for a BINARIZE or COMBINE job it is an empty string.

  • job_id (str) – The unique hexadecimal identifier under which the job’s state is recorded on the provided tracker. It must already be present in the tracker’s aligned job set.

  • tracker (ProcessingTracker) – The caller-owned ProcessingTracker onto which this job’s start, completion, or failure is recorded.

  • workers (int | None, default: None) – The number of parallel workers to allocate to this job. Use None to accept the stage default and -1 to request every available core. The combination job ignores this parameter.

  • device (int | None, default: None) – The zero-based index of the CUDA device a registration job uses. Use None to run the registration on the host CPU. Every other job ignores this parameter.

Raises:
  • FileNotFoundError – If the configuration file is missing, is not a .yaml file, or is not a valid single-recording configuration.

  • RuntimeError – If device names a CUDA device on a host that exposes no usable one.

  • ValueError – If the configuration does not configure an output path, or if job_name is not a recognized single-recording job. Also raised if specifier does not name an imaging plane for a REGISTER or PROCESS job, if workers is zero or a negative value other than -1, or if device names an index the host does not expose.

Return type:

None

cindra.orchestration.generate_job_ids(jobs)

Generates the processing job identifier of every job in a resolved job universe.

Notes

The identifier derives from the job name and specifier alone, and a tracker records each job under the same derivation.

Parameters:

jobs (Iterable[tuple[str, str]]) – The jobs for which to generate identifiers, as the (job name, specifier) pairs the job resolvers return.

Return type:

dict[tuple[str, str], str]

Returns:

The hexadecimal identifier of every job, keyed by its name and specifier.

Raises:

ValueError – If a job name or a specifier contains a colon.

cindra.orchestration.get_execution_state()

Returns the active batch processing execution state, or None when no session exists.

Return type:

JobExecutionState | None

cindra.orchestration.load_multi_recording_configuration(configuration_path)

Loads, validates, and runtime-configures a multi-recording configuration from a YAML file.

Parameters:

configuration_path (Path) – The path to the multi-recording configuration YAML file.

Return type:

MultiRecordingConfiguration

Returns:

The loaded MultiRecordingConfiguration with its progress display state applied.

Raises:
  • FileNotFoundError – If the configuration file is missing, is not a .yaml file, or is not a valid multi-recording configuration.

  • ValueError – If the configuration specifies fewer than two recording directories or no dataset name.

cindra.orchestration.load_single_recording_configuration(configuration_path)

Loads, validates, and runtime-configures a single-recording configuration from a YAML file.

Parameters:

configuration_path (Path) – The path to the single-recording configuration YAML file.

Return type:

tuple[SingleRecordingConfiguration, Path]

Returns:

A tuple of the loaded SingleRecordingConfiguration, with its progress display state applied, and its validated output path.

Raises:
  • FileNotFoundError – If the configuration file is missing, is not a .yaml file, or is not a valid single-recording configuration.

  • ValueError – If the configuration does not configure an output path.

cindra.orchestration.order_phases_by_execution(phase_names, *, single_recording)

Orders phase job names by the order the pipeline executes them.

Notes

Alphabetical order would render the single-recording chain as binarization, combination, processing, registration, which inverts the two middle phases relative to the order in which they run.

Parameters:
  • phase_names (Iterable[str]) – The phase job names to order.

  • single_recording (bool) – Determines whether to apply the single-recording or the multi-recording phase chain.

Return type:

list[str]

Returns:

The phase job names in pipeline execution order. Names outside the phase model are appended alphabetically.

cindra.orchestration.parse_plane_specifier(specifier)

Reads the virtual plane index a per-plane specifier carries.

Notes

Inverts resolve_plane_specifier. A specifier that names no plane resolves to None rather than raising, because a caller routing a mixed job set asks this of every specifier it holds.

Parameters:

specifier (str) – The specifier to read the plane index from.

Return type:

int | None

Returns:

The virtual plane index, or None when the specifier does not name a plane.

cindra.orchestration.prime_dataset(configuration_path)

Writes the shared multi-recording bootstrap and reports the recordings the dataset spans.

Notes

Every per-job entry point re-loads this bootstrap with persistence disabled, so this call must precede the first job dispatched against a configuration. Priming is single-threaded by contract, for the same reason the single-recording bootstrap is.

Parameters:

configuration_path (Path) – The path to the multi-recording configuration file.

Return type:

DatasetRecordings

Returns:

The dataset’s recording inventory.

Raises:
  • FileNotFoundError – If the configuration file is missing, is not a .yaml file, is not a valid multi-recording configuration, or if a recording holds no combined metadata archive.

  • ValueError – If the configuration names fewer than two recording directories or no dataset name.

  • RuntimeError – If a recording directory holds several combined metadata archives, if the recording paths carry no unique identifying component, or if a resolved identifying component contains a colon.

cindra.orchestration.prime_recording(configuration_path)

Writes the shared single-recording bootstrap and reports the planes the recording holds.

Notes

Every per-job entry point re-loads this bootstrap with persistence disabled, so this call must precede the first job dispatched against a configuration. Priming is single-threaded by contract, because it writes one runtime data file per plane and a peer job writing them concurrently would overwrite each other’s snapshot.

Parameters:

configuration_path (Path) – The path to the single-recording configuration file.

Return type:

RecordingPlanes

Returns:

The recording’s plane inventory.

Raises:
  • FileNotFoundError – If the configuration file is missing, is not a .yaml file, is not a valid single-recording configuration, or if no acquisition parameters file is found under the configured data path.

  • ValueError – If the configuration does not configure an output path, if the recording holds neither processed data nor a configured data path, or if the acquisition parameters file fails validation.

cindra.orchestration.read_tracked_recording_geometry(cindra_root)

Reads the geometry every multi-recording model reads from one recording of a tracked dataset.

Notes

Reads a recording’s processed output rather than its raw acquisition, so the caller has already run the single-recording pipeline over the recording to completion.

Covers the combined field extent, the combined frame count, the second channel the metadata archive records, and the regions the combined trace array’s own header reports. The per-plane geometry and the raw frame extent stay unread, because every multi-recording stage works at the combined view. Only headers are parsed, so a recording of any length costs a pair of small reads and no array is mapped.

The region count this reports is the regions one recording holds on its own. It is not the templates a tracked dataset holds, which only the cross-recording discovery stage produces. It therefore does not make the tracked count readable, and a caller planning a dataset whose discovery has not yet run must not read it as one.

Parameters:

cindra_root (Path) – The recording’s pipeline output directory, which carries the combined metadata archive.

Return type:

RecordingGeometry

Returns:

The recording’s geometry, whose resolved flag is False when the recording carries no combined output.

cindra.orchestration.resolve_downstream_phases(phase_names, *, single_recording)

Returns the requested phases together with every phase that depends on them.

Notes

Each pipeline runs its phases in a single chain, so every phase below the earliest requested one consumes output the requested phase produces. Resetting or cleaning a phase therefore invalidates all of them.

Parameters:
  • phase_names (Iterable[str]) – The job names of the phases the caller requested.

  • single_recording (bool) – Determines whether to apply the single-recording or the multi-recording phase chain.

Return type:

set[str]

Returns:

The set of phase job names on which to act.

cindra.orchestration.resolve_gpu_devices(device=None)

Resolves the CUDA devices the registration stage uses.

Probes the runtime by transforming a small array on one device, because CuPy resolves the cuFFT shared library on first use rather than at import.

Parameters:

device (int | None, default: None) – The zero-based index of the CUDA device that transforms the probe array. Use None to transform it on the device the runtime selects by default. An index the host does not expose falls back to that same device.

Return type:

GpuSummary

Returns:

The summary of the devices found and of the reason no device is usable.

cindra.orchestration.resolve_maximum_roi_count(plane_count, configuration)

Resolves the regions a recording can provably not exceed.

Notes

The sparse detection loop runs a bounded number of iterations and appends at most one region per iteration, and every step after the append can only remove regions. The product of the iteration multiplier, the configured iteration limit, and the plane count is therefore a ceiling rather than an observed maximum. A second functional channel is detected into its own arrays, which the trace models account for through their own channel factor.

Parameters:
  • plane_count (int) – The virtual imaging planes the recording holds.

  • configuration (SingleRecordingConfiguration) – The recording’s processing configuration.

Return type:

int

Returns:

The ceiling, counting every plane of the recording together.

cindra.orchestration.resolve_multi_recording_job_universe(recording_roots, dataset_name)

Resolves the multi-recording jobs one tracked dataset declares and the subset ready to run.

Notes

The discovery job is ready once every recording the dataset spans carries its single-recording output, which is what the cross-recording registration reads. An extraction job is ready once the discovery job has written the template masks its recording projects.

Parameters:
  • recording_roots (Sequence[Path]) – The output root of every recording the dataset spans.

  • dataset_name (str) – The name of the tracked dataset, in any casing.

Return type:

MultiRecordingJobs

Returns:

The dataset’s job universe.

cindra.orchestration.resolve_multi_recording_jobs(recording_ids)

Returns every job the multi-recording pipeline can execute for a dataset of the given recordings.

Parameters:

recording_ids (Sequence[str]) – The identifier of every recording the tracked dataset spans.

Return type:

list[tuple[str, str]]

Returns:

A list of (job name, specifier) pairs in execution order. The discovery job carries an empty specifier, and each extraction job carries its recording identifier.

cindra.orchestration.resolve_multi_recording_prerequisites(jobs)

Returns the jobs that must succeed before each multi-recording job can run.

Parameters:

jobs (Iterable[tuple[str, str]]) – The (job name, specifier) pairs for which to resolve the prerequisites, usually a dataset’s job universe.

Return type:

dict[tuple[str, str], tuple[tuple[str, str], ...]]

Returns:

A mapping of every input job to the tuple of jobs on which it depends. The tuple is empty for jobs that depend on nothing.

cindra.orchestration.resolve_openmp_runtime(*, runtime_path=None, link_path=None, execute=False, force=False)

Links a discovered OpenMP runtime into a directory the dynamic loader searches by default.

The link is what makes Numba’s OpenMP threading layer resolve on macOS, because the omppool extension shipped in the Numba wheel names its dependency through an rpath for which it carries no entries. A host whose runtime already loads is left alone unless the link is forced. Only macOS reaches the linking path, because every other platform runs the TBB threading layer and gains nothing from an OpenMP runtime.

Parameters:
  • runtime_path (Path | None, default: None) – The absolute path to the OpenMP runtime to link, or None to search the macOS package manager directories, the active conda environment, and the installed Python distributions for one.

  • link_path (Path | None, default: None) – The absolute path that receives the link, or None to derive it from the directory the loader searches by default.

  • execute (bool, default: False) – Determines whether to create the resolved link, where a dry run reports it and changes nothing.

  • force (bool, default: False) – Determines whether to link a runtime on a host whose runtime already loads.

Return type:

OpenMPSummary

Returns:

The summary describing the resolved runtime, the resolved link, and what the call changed.

Raises:

RuntimeError – If the host runs a platform other than macOS, if the resolved link path already holds the runtime itself, if the link directory cannot be created, or if the link cannot be written.

cindra.orchestration.resolve_pipeline_jobs(phases, specifiers)

Expands a pipeline’s phases into a job list over the given specifiers.

Parameters:
  • phases (tuple[PipelinePhase, ...]) – The ordered phases of the pipeline.

  • specifiers (Sequence[str]) – The specifiers over which the per-specifier phases expand.

Return type:

list[tuple[str, str]]

Returns:

A list of (job name, specifier) pairs in phase order. Phases that do not expand per specifier carry an empty specifier.

cindra.orchestration.resolve_plane_specifier(plane_index)

Resolves the specifier that identifies one virtual imaging plane.

Parameters:

plane_index (int) – The index of the virtual imaging plane.

Return type:

str

Returns:

The specifier identifying the plane.

cindra.orchestration.resolve_recording_geometry(output_root, data_path=None, ignored_file_names=())

Resolves the shape of one recording from the raw acquisition its conversion stage will read.

Notes

Reads the acquisition metadata and one source file header, which fix every shape the pipeline will write before any of it runs. A caller therefore sizes a whole job graph up front and receives the same answer at every point in the run. No frame is decoded and no array is mapped, so the cost stays flat as a recording grows.

Parameters:
  • output_root (Path) – The recording’s configured output root.

  • data_path (Path | None, default: None) – The recording’s configured raw imaging path, which is either the directory holding its source files or any parent of the directory that holds its acquisition parameters file. Every estimate reads the header of the first source file that directory holds.

  • ignored_file_names (tuple[str, ...], default: ()) – The source file stems the recording excludes from conversion.

Return type:

RecordingGeometry

Returns:

The recording’s geometry, whose resolved flag is False when the raw acquisition is unreadable and whose acquisition_resolved and source_resolved flags report which of its two inputs failed.

cindra.orchestration.resolve_registration_resource_class(*, gpu_registration)

Resolves the resource class that governs a registration job planned for a CUDA device or for the host CPU.

Parameters:

gpu_registration (bool) – Determines whether the registration jobs are planned for a CUDA device rather than the host CPU.

Return type:

ResourceClass

Returns:

The resource class that governs the job’s worker count and the concurrency of its queue.

cindra.orchestration.resolve_session_load()

Counts the jobs the active execution session still holds.

Return type:

tuple[int, int]

Returns:

The number of jobs awaiting dispatch and the number of jobs currently running, in that order. Both counts are zero when no session exists or the session has drained.

cindra.orchestration.resolve_single_recording_job_universe(output_root, data_path=None)

Resolves the single-recording jobs one recording declares and the subset ready to run.

Notes

The conversion job is ready whenever the recording’s parameters resolve. A registration job is ready once its plane carries the channel binary the conversion writes, and a processing job once its plane carries the reference image the registration writes. The combination job is ready once every plane carries the traces the processing stage writes, which are the arrays the combination stage concatenates.

Parameters:
  • output_root (Path) – The recording’s configured output root.

  • data_path (Path | None, default: None) – The raw imaging directory, consulted only when the recording carries no output yet.

Return type:

SingleRecordingJobs

Returns:

The recording’s job universe.

cindra.orchestration.resolve_single_recording_jobs(plane_count)

Returns every job the single-recording pipeline can execute for a recording with the given plane count.

Notes

The returned list covers every plane, independently of which planes a particular invocation intends to run.

Parameters:

plane_count (int) – The number of virtual imaging planes the recording holds.

Return type:

list[tuple[str, str]]

Returns:

A list of (job name, specifier) pairs in execution order. Jobs that do not expand per plane carry an empty specifier.

cindra.orchestration.resolve_single_recording_prerequisites(jobs)

Returns the jobs that must succeed before each single-recording job can run.

Parameters:

jobs (Iterable[tuple[str, str]]) – The (job name, specifier) pairs for which to resolve the prerequisites, usually a recording’s job universe.

Return type:

dict[tuple[str, str], tuple[tuple[str, str], ...]]

Returns:

A mapping of every input job to the tuple of jobs on which it depends. The tuple is empty for jobs that depend on nothing.

cindra.orchestration.resolve_stage_workers(job_name, requested_workers=None, *, gpu_registration=False)

Resolves the number of workers to allocate to the target pipeline stage.

Notes

A requested count of None resolves to the default for the stage. A requested count of -1 resolves to every available CPU core, minus the cores the ataraxis worker resolver holds back for system use. A positive requested count is honored exactly. A requested count of zero, or any negative count other than -1, is rejected.

The combination stage takes no worker argument of its own, so its default is the single core its serial merge occupies.

The registration stage default alone responds to gpu_registration, because it is the one stage that runs on a CUDA device. Every other stage resolves the same count whatever that flag holds.

Parameters:
  • job_name (SingleRecordingJobNames | MultiRecordingJobNames) – The single or multi-recording pipeline stage that receives the allocated workers.

  • requested_workers (int | None, default: None) – The number of workers the caller requests. Use None to accept the default for the stage and -1 to request every available core.

  • gpu_registration (bool, default: False) – Determines whether the registration jobs are planned for a CUDA device rather than the host CPU.

Return type:

int

Returns:

The number of workers to allocate to the stage, always at least 1.

Raises:

ValueError – If job_name does not name a pipeline stage, or if requested_workers is zero or is a negative value other than -1.

cindra.orchestration.run_multi_recording_pipeline(configuration_path, job_id=None, *, discover=False, extract=False, target_recording=None, discovery_workers=None, extraction_workers=None)

Executes the requested multi-recording processing pipeline steps for the target data.

The caller is responsible for writing all runtime overrides (recording_io.recording_directories, runtime.display_progress_bars) into the configuration file before invoking this function. The pipeline reads these values from the file at configuration_path. Each stage takes its worker count as a direct parameter, which keeps the configuration file immutable and therefore safe to share between concurrently dispatched jobs. An invocation that sets neither stage flag runs both stages in phase order.

Parameters:
  • configuration_path (Path) – The path to the multi-recording configuration YAML file. The configuration must include the recording_io.recording_directories list of recording paths and recording_io.dataset_name.

  • job_id (str | None, default: None) – The unique hexadecimal identifier for the processing job to execute. If provided, only the job matching this ID is executed. If not provided, all requested jobs are run sequentially.

  • discover (bool, default: False) – Determines whether to discover ROIs whose activity can be tracked across recordings (step 1).

  • extract (bool, default: False) – Determines whether to extract fluorescence from the ROIs tracked across multiple recordings (step 2).

  • target_recording (str | None, default: None) – The unique identifier of the recording to process when running the ‘extract’ job. If None, processes all recordings.

  • discovery_workers (int | None, default: None) – The number of parallel workers to allocate to the discovery stage. Use None to accept the stage default and -1 to request every available core.

  • extraction_workers (int | None, default: None) – The number of parallel workers to allocate to each per-recording extraction job. Use None to accept the stage default and -1 to request every available core.

Raises:
  • FileNotFoundError – If the multi-recording configuration data cannot be loaded from the specified file, or if a recording directory holds no combined_metadata.npz file. It is also raised when a job_id is supplied and a recording carries no multi_recording_runtime_data.yaml file, which prepare_multi_recording_batch_tool writes before any worker is dispatched.

  • RuntimeError – If the host is macOS and carries no loadable OpenMP runtime for the Numba threading layer. It is also raised when a recording directory holds multiple combined_metadata.npz files, when the recording paths do not contain unique identifying components, or when a resolved identifying component contains a colon.

  • ValueError – If recording validation fails, recording_directories names fewer than two recordings, target_recording does not name a resolved recording, or the specified job_id does not match any available jobs.

Return type:

None

cindra.orchestration.run_single_recording_pipeline(configuration_path, job_id=None, *, binarize=False, register=False, process=False, combine=False, target_plane=-1, binarization_workers=None, registration_workers=None, processing_workers=None, registration_device=None)

Executes the requested single-recording processing pipeline steps for the target data.

The caller is responsible for writing all path overrides (file_io.data_path, file_io.output_path) and the runtime.display_progress_bars flag into the configuration file before invoking this function. The pipeline reads these values from the file at configuration_path. Each stage takes its worker count as a direct parameter, which keeps the configuration file immutable and therefore safe to share between concurrently dispatched jobs. An invocation that sets none of the four stage flags runs every stage in phase order.

Parameters:
  • configuration_path (Path) – The path to the single-recording configuration YAML file.

  • job_id (str | None, default: None) – The unique hexadecimal identifier for the processing job to execute. If provided, only the job matching this ID is executed. If not provided, all requested jobs are run sequentially.

  • binarize (bool, default: False) – Determines whether to resolve the binary files for plane-specific processing (step 1).

  • register (bool, default: False) – Determines whether to register the target plane(s) to remove motion and compute the registration quality metrics (step 2).

  • process (bool, default: False) – Determines whether to process the target plane(s) to discover ROIs and extract their fluorescence (step 3).

  • combine (bool, default: False) – Determines whether to combine processed plane data into a uniform dataset (step 4).

  • target_plane (int, default: -1) – The index of the plane to register and process. Setting this to ‘-1’ processes all available planes sequentially.

  • binarization_workers (int | None, default: None) – The number of parallel workers to allocate to the binarization stage. Use None to accept the stage default and -1 to request every available core.

  • registration_workers (int | None, default: None) – The number of parallel workers to allocate to each plane-registration job. Use None to accept the stage default and -1 to request every available core.

  • processing_workers (int | None, default: None) – The number of parallel workers to allocate to each plane-processing job. Use None to accept the stage default and -1 to request every available core.

  • registration_device (int | None, default: None) – The zero-based index of the CUDA device on which each plane-registration job runs. Use None to register every plane on the host CPU.

Raises:
  • FileNotFoundError – If the single-recording configuration data cannot be loaded from the specified file.

  • RuntimeError – If the host is macOS and carries no loadable OpenMP runtime for the Numba threading layer, or if a registration device is named and the host exposes no usable CUDA device.

  • ValueError – If the recording’s data validation fails, the specified job_id does not match any available job, target_plane names a plane the recording does not hold, or registration_device names a CUDA device index the host does not expose.

Return type:

None

cindra.orchestration.set_execution_state(state)

Stores the active batch processing execution state, replacing any existing session reference.

Parameters:

state (JobExecutionState | None) – The execution state to store, or None to clear the active session.

Return type:

None

cindra.orchestration.size_multi_recording_job(job_name, specifier, recording_directories, configuration, *, planned_roi_count=None)

Sizes one multi-recording job from the dataset it processes.

Parameters:
  • job_name (MultiRecordingJobNames) – The pipeline stage the job runs.

  • specifier (str) – The job’s tracker specifier, which names a recording for the extraction stage.

  • recording_directories (Sequence[Path]) – The root directory of every recording the dataset spans, as the configuration’s recording_directories field holds them.

  • configuration (MultiRecordingConfiguration) – The dataset’s processing configuration.

  • planned_roi_count (int | None, default: None) – The tracked templates the plan covers, counting the dataset as a whole. Use None to accept the bound the per-recording region counts provide. Must be a positive integer when supplied.

Return type:

JobSizing

Returns:

The cores the job occupies and the memory it holds, alongside a device memory of zero, because no multi-recording stage runs on a CUDA device.

Raises:
  • FileNotFoundError – If the dataset names no recording directory, if any recording carries no combined metadata archive, or if any recording reports no regions in its combined trace array, in which case neither multi-recording stage can run.

  • ValueError – If planned_roi_count is supplied and is not a positive integer.

cindra.orchestration.size_single_recording_job(job_name, specifier, output_root, configuration, data_path=None, *, planned_roi_count=None, gpu_registration=False)

Sizes one single-recording job from the recording it processes.

Parameters:
  • job_name (SingleRecordingJobNames) – The pipeline stage the job runs.

  • specifier (str) – The job’s tracker specifier, which names a plane for the per-plane stages and is empty otherwise.

  • output_root (Path) – The recording’s configured output root.

  • configuration (SingleRecordingConfiguration) – The recording’s processing configuration.

  • data_path (Path | None, default: None) – The recording’s configured raw imaging path, which is either the directory holding its source files or any parent of the directory that holds its acquisition parameters file. Every estimate reads the header of the first source file that directory holds.

  • planned_roi_count (int | None, default: None) – The regions the plan covers, counting every plane of the recording together. Use None to accept the ceiling the detection iteration bound provides. Must be a positive integer when supplied.

  • gpu_registration (bool, default: False) – Determines whether the registration jobs are planned for a CUDA device rather than the host CPU. A job of any other stage reports no device memory whatever it holds.

Return type:

JobSizing

Returns:

The cores the job occupies, the memory it holds, and the device memory it holds.

Raises:
  • FileNotFoundError – If the recording’s acquisition parameters were not readable or its raw imaging directory holds no readable source file, in which case no stage of it can run.

  • ValueError – If planned_roi_count is supplied and is not a positive integer, if both inputs were readable and still describe no whole imaging plane, or if a per-plane job’s specifier names an imaging plane the recording does not hold.

cindra.orchestration.start_execution_session(all_jobs, workers_per_job, max_parallel_jobs, gpu_devices=None)

Resolves the per-class resource allocation of the queued jobs and starts the execution manager over them.

Notes

Every job enters the admission pool, and the manager decides admission from the tracked prerequisites.

Each job takes its worker count when the dispatcher submits it, and that count travels to the pipeline as a dispatch argument, so one configuration file serves every job dispatched concurrently against it. A session accepting the class defaults widens a job of an elastic class toward that class’s ceiling over the cores the host holds free. A session carrying a worker override gives every job of a class the budgets bound the width it requested.

Each class resolves its own concurrency cap, and the session CPU budget is recorded alongside those caps because every class dispatches during the same cycle. The dispatcher holds the sum of the cores committed by the running jobs of every class inside that budget, so the per-class caps cannot oversubscribe the machine between them.

The session also holds the CUDA devices its device-backed jobs use, one device per running job. It holds the devices the caller names, which leaves the rest of the host’s devices to the work running beside it, and a session naming none registers on the host CPU.

Parameters:
  • all_jobs (dict[tuple[str, str], PendingJob]) – All submitted jobs keyed by dispatch key, in the order the manager should consider them.

  • workers_per_job (int | None) – Requested CPU cores per job, -1 for every available core, or None to accept each resource class default.

  • max_parallel_jobs (int | None) – Requested maximum concurrent jobs per resource class, -1 to lift the caps, or None to accept the derived caps.

  • gpu_devices (list[int] | None, default: None) – The zero-based indices of the CUDA devices the session uses for registration. Use None to register on the host CPU, [-1] to name every device the host exposes, and an explicit list to name those devices.

Return type:

dict[str, object]

Returns:

A dictionary carrying the submitted job total under ‘total_jobs’, the session core budget under ‘cpu_budget’, and the session memory budget under ‘memory_budget_mb’. It also carries the device indices the session holds under ‘gpu_devices’, and the per-class worker count, concurrency cap, and job count under ‘resource_classes’.

Raises:

ValueError – If either override is zero or is a negative value other than -1. If gpu_devices is empty, names a device the host does not expose, or pairs the all-devices request with an explicit index. If a submitted job registers on a CUDA device while the session holds none, or if the session holds a device while a submitted registration job registers on the host CPU.

cindra.orchestration.validate_job_prerequisites(registry, job_id, *, single_recording, submitted_job_ids)

Validates that a job’s prerequisites either already succeeded or arrive with the same submission.

Notes

The tracker is the authoritative source for phase completion. Files on disk may be corrupt or incomplete even if they exist, and the tracker only marks SUCCEEDED when processing is confirmed complete. A prerequisite that is submitted alongside the dependent job passes validation because the execution manager admits the dependent job only after that prerequisite actually succeeds.

Parameters:
  • registry (Mapping[str, JobState]) – The point-in-time job registry of the tracker that owns the target job.

  • job_id (str) – The unique hexadecimal job identifier to validate.

  • single_recording (bool) – Determines whether to apply single-recording or multi-recording prerequisite rules.

  • submitted_job_ids (frozenset[str]) – The identifiers of every job submitted against this tracker in the same call.

Return type:

str | None

Returns:

None if all prerequisites are satisfied or pending in this submission, or an error message string describing the unmet prerequisite.

cindra.orchestration.gpu.GPU_REMEDY: str = "Install the CuPy build matching the CUDA version the local driver runs, as 'cupy-cuda13x[ctk]' for CUDA 13 or 'cupy-cuda12x[ctk]' for CUDA 12, and run 'cindra gpu' to report what the host exposes."

The remedy an unusable GPU runtime reports, named by every message that a CuPy installation would resolve.

Notes

The ‘ctk’ extra carries the CUDA math libraries CuPy resolves on first use. A bare CuPy installation imports and reports its devices, then raises at the first transform, so the extra is what separates a reachable device from an importable module.

cindra.orchestration.gpu.ALL_DEVICES_REQUEST: int = -1

The requested device index that asks for every CUDA device the host exposes.

cindra.orchestration.jobs.SINGLE_RECORDING_PHASES: tuple[PipelinePhase, ...] = (PipelinePhase(job_name=<SingleRecordingJobNames.BINARIZE: 'binarization'>, per_specifier=False, prerequisite=None, prerequisite_scope=<PrerequisiteScope.ALL_JOBS: 'all_jobs'>), PipelinePhase(job_name=<SingleRecordingJobNames.REGISTER: 'registration'>, per_specifier=True, prerequisite=<SingleRecordingJobNames.BINARIZE: 'binarization'>, prerequisite_scope=<PrerequisiteScope.ALL_JOBS: 'all_jobs'>), PipelinePhase(job_name=<SingleRecordingJobNames.PROCESS: 'processing'>, per_specifier=True, prerequisite=<SingleRecordingJobNames.REGISTER: 'registration'>, prerequisite_scope=<PrerequisiteScope.MATCHING_SPECIFIER: 'matching_specifier'>), PipelinePhase(job_name=<SingleRecordingJobNames.COMBINE: 'combination'>, per_specifier=False, prerequisite=<SingleRecordingJobNames.PROCESS: 'processing'>, prerequisite_scope=<PrerequisiteScope.ALL_JOBS: 'all_jobs'>))

The ordered phases of the single-recording pipeline.

cindra.orchestration.jobs.MULTI_RECORDING_PHASES: tuple[PipelinePhase, ...] = (PipelinePhase(job_name=<MultiRecordingJobNames.DISCOVER: 'discovery'>, per_specifier=False, prerequisite=None, prerequisite_scope=<PrerequisiteScope.ALL_JOBS: 'all_jobs'>), PipelinePhase(job_name=<MultiRecordingJobNames.EXTRACT: 'extraction'>, per_specifier=True, prerequisite=<MultiRecordingJobNames.DISCOVER: 'discovery'>, prerequisite_scope=<PrerequisiteScope.ALL_JOBS: 'all_jobs'>))

The ordered phases of the multi-recording pipeline.

cindra.orchestration.allocation.BINARIZATION_WORKERS: int = 4

The number of CPU cores one binarization job holds, which matches the TIFF decode ceiling so that the conversion reaches the widest decode that ceiling allows. A cold sweep over this stage peaks near this width and falls away above it, because the contention a wider decode adds on the storage outweighs the decompression it parallelizes.

cindra.orchestration.allocation.REGISTRATION_WORKERS: int = 8

The number of CPU cores one registration job holds while the session dispatches at its full concurrency.

cindra.orchestration.allocation.REGISTRATION_GPU_WORKERS: int = 2

The number of CPU cores one device-backed registration job holds. The job builds its reference image, computes its crop, and runs its median filters on the host, so it occupies cores alongside the device it uses.

cindra.orchestration.allocation.PROCESSING_WORKERS: int = 8

The number of CPU cores one processing job holds while the session dispatches at its full concurrency.

cindra.orchestration.allocation.COMBINATION_WORKERS: int = 1

The number of CPU cores one combination job holds. The stage takes no worker argument, so its jobs occupy one core whatever the budget supplies.

cindra.orchestration.allocation.DISCOVERY_WORKERS: int = 2

The number of CPU cores one multi-recording discovery job holds while the session dispatches at its full concurrency. The stage builds its deformation pool only while the allocation exceeds one core.

cindra.orchestration.allocation.EXTRACTION_WORKERS: int = 16

The number of CPU cores one multi-recording extraction job holds while the session dispatches at its full concurrency.

cindra.orchestration.allocation.REGISTRATION_MAXIMUM_WORKERS: int = 32

The most CPU cores one registration job holds when the host has capacity to spare.

cindra.orchestration.allocation.PROCESSING_MAXIMUM_WORKERS: int = 16

The most CPU cores one processing job holds when the host has capacity to spare. The extra cores reach the trace extraction, because the detection the stage runs first spends its budget through its own block pool.

cindra.orchestration.allocation.DISCOVERY_MAXIMUM_WORKERS: int = 8

The most CPU cores one multi-recording discovery job holds when the host has capacity to spare.

cindra.orchestration.allocation.EXTRACTION_MAXIMUM_WORKERS: int = 32

The most CPU cores one multi-recording extraction job holds when the host has capacity to spare.

cindra.orchestration.allocation.RESOURCE_CLASS_BY_JOB_NAME: dict[str, ResourceClass] = {SingleRecordingJobNames.BINARIZE: ResourceClass(name='binarization', workers_per_job=4, maximum_workers_per_job=None, concurrency_limit=4, concurrency_reservation=None), SingleRecordingJobNames.COMBINE: ResourceClass(name='combination', workers_per_job=1, maximum_workers_per_job=None, concurrency_limit=None, concurrency_reservation=None), MultiRecordingJobNames.DISCOVER: ResourceClass(name='discovery', workers_per_job=2, maximum_workers_per_job=8, concurrency_limit=None, concurrency_reservation=None), MultiRecordingJobNames.EXTRACT: ResourceClass(name='extraction', workers_per_job=16, maximum_workers_per_job=32, concurrency_limit=None, concurrency_reservation=None), SingleRecordingJobNames.PROCESS: ResourceClass(name='processing', workers_per_job=8, maximum_workers_per_job=16, concurrency_limit=None, concurrency_reservation=5), SingleRecordingJobNames.REGISTER: ResourceClass(name='registration', workers_per_job=8, maximum_workers_per_job=32, concurrency_limit=None, concurrency_reservation=4)}

Maps every pipeline job name to the resource class that governs its worker count and its concurrency cap.

cindra.orchestration.footprints.WORKER_MEMORY_MB: int = 384

The resident memory a worker process occupies before it runs any job, covering the interpreter and the import graph of this library. The term is charged once per job.

cindra.orchestration.footprints.SPAWNED_CHILD_MEMORY_MB: int = 200

The resident memory each child of a job’s own process pool occupies before it touches data.

Notes

Carried on the same scale as the sibling ataraxis libraries, so a scheduler composing a batch across them prices a child the same way. No cindra stage opens a process pool of its own, so no estimate here applies the term. It is exported for a scheduler that wraps a cindra job in a pool it owns.

cindra.orchestration.footprints.MEMORY_ESTIMATE_TOLERANCE: float = 1.15

The margin applied to every estimate before it is reported.

Notes

The margin covers the working sets a model does not enumerate and the variation between recordings of the same shape. Understating is the asymmetric failure, since a local batch overcommits its host and a scheduled job is killed outright, so every estimate rounds up. The value matches the margin ataraxis-video-system applies, which is what lets a scheduler weigh a cindra job against its jobs on one scale.

Pipelines

Provides the stage entry points that the single-recording and multi-recording pipelines dispatch.

cindra.pipelines.binarize_recording(configuration, *, workers)

Converts raw TIFF recording data into the internal binary format used by the processing pipeline.

Notes

The conversion is skipped when every plane already holds the channel binaries the recording declares and ‘repeat_binarization’ is disabled in the FileIO configuration section.

An existing output that disagrees with what the recording declares is refused rather than repaired. The refusals cover a binary an interrupted conversion or registration left marked, a plane of a two-channel recording holding no second channel binary, and a binary whose size disagrees with its plane’s recorded frame geometry. Enabling ‘repeat_binarization’ rebuilds the recording past all three, because that parameter is the caller asking for the conversion that replaces every binary those refusals name.

The conversion consumes whole plane and channel interleave cycles, so every plane and channel of the recording receives the same frame count and the frames of an incomplete final cycle are discarded.

A conversion replaces every plane binary of the recording, so it first deletes the registration, detection, and extraction outputs of every plane directory the output root holds, along with the recording’s combined dataset. The rebuilt binaries hold raw frames again, which voids every offset, image, and trace measured from the previous binaries, and deleting the registration output is what makes the registration stage run instead of skipping the plane. That deletion follows the conversion plan, so a recording whose TIFF files cannot be converted keeps its results.

Parameters:
  • configuration (SingleRecordingConfiguration) – The single-recording pipeline configuration.

  • workers (int) – The number of parallel workers allocated to this binarization job. Must be a positive integer, which the caller resolves before invoking this function.

Raises:
  • ValueError – If data_path or output_path is not configured, if the discovered TIFF files do not all hold frames of the same shape, or if the frames they hold do not fill one complete plane and channel interleave cycle.

  • RuntimeError – If a converted plane binary carries the marker of an interrupted write, if a converted plane of a two-channel recording holds no second channel binary, or if a binary’s size disagrees with the frame geometry recorded for its plane.

  • FileNotFoundError – If a plane’s runtime_data.yaml was not written by an earlier bootstrap step, or if no TIFF files are found in the data directory.

Return type:

None

cindra.pipelines.discover_multi_recording_cells(configuration, *, workers)

Discovers reliably identifiable ROIs and tracks them across the processed set of recordings.

Parameters:
  • configuration (MultiRecordingConfiguration) – The multi-recording pipeline configuration.

  • workers (int) – The number of parallel workers allocated to this discovery job. Must be a positive integer, which the caller resolves before invoking this function.

Return type:

None

cindra.pipelines.extract_multi_recording_fluorescence(configuration, recording_id, *, workers)

Extracts fluorescence data from ROIs tracked across imaging recordings for the specified recording.

Notes

The discovery phase must have completed before attempting extraction. Multiple recordings can be processed in parallel, but each recording may use significant memory and CPU resources.

Parameters:
  • configuration (MultiRecordingConfiguration) – The multi-recording pipeline configuration.

  • recording_id (str) – The unique identifier of the recording for which to extract fluorescence data. Must match one of the recording IDs assigned during context resolution.

  • workers (int) – The number of parallel workers allocated to this extraction job. Must be a positive integer, which the caller resolves before invoking this function.

Raises:
  • ValueError – If the target recording_id does not match any resolved recording context.

  • RuntimeError – If the combined single-recording data is not loaded, if backward-transformed ROI statistics are not available, indicating the discovery phase has not completed, or if an interrupted binarization or registration left one of the recording’s plane binaries marked. It is also raised when a recording directory holds multiple combined_metadata.npz files, when the recording paths do not contain unique identifying components, or when a resolved recording identifier contains a colon.

  • FileNotFoundError – If the recording’s multi_recording_runtime_data.yaml was not written by an earlier bootstrap step, or if no combined_metadata.npz file is found in a recording directory.

Return type:

None

cindra.pipelines.process_plane(configuration, plane_index, *, workers)

Detects ROIs and extracts their fluorescence traces for the target imaging plane.

Notes

Multiple planes can be processed in parallel, but each plane may use significant memory and CPU resources.

The plane must be registered before it is processed. Detection reads the valid pixel ranges computed during registration, and an unregistered plane carries the (0, 0) defaults for those ranges, which silently produce a zero-size binned movie instead of an error.

Parameters:
  • configuration (SingleRecordingConfiguration) – The single-recording pipeline configuration.

  • plane_index (int) – The index of the imaging plane to process.

  • workers (int) – The number of parallel workers allocated to this processing job. Must be a positive integer, which the caller resolves before invoking this function.

Raises:
  • ValueError – If output_path is not configured, or if the plane contains fewer frames than the processing minimum.

  • TypeError – If the runtime context loader returns multiple contexts for the target plane.

  • RuntimeError – If the target plane has not been registered.

Return type:

None

cindra.pipelines.register_recording_plane(configuration, plane_index, *, workers, device=None)

Removes motion from the target imaging plane and computes its registration quality metrics.

Notes

The stage writes the registration offsets, the valid pixel ranges, and the bad-frame mask to disk. Multiple planes can be registered in parallel, but each plane may use significant memory and CPU resources.

A plane that already holds its registration outputs is skipped unless ‘repeat_registration’ is enabled in the Registration configuration section. A skip runs no registration work, so it reports the plane as skipped and leaves the timing and the worker allocation an earlier run recorded in place.

Parameters:
  • configuration (SingleRecordingConfiguration) – The single-recording pipeline configuration.

  • plane_index (int) – The index of the imaging plane to register.

  • workers (int) – The number of parallel workers allocated to this registration job. Must be a positive integer, which the caller resolves before invoking this function.

  • device (int | None, default: None) – The zero-based index of the CUDA device on which this job registers the plane. Use None to register the plane on the host CPU.

Raises:
  • ValueError – If output_path is not configured, or if the plane contains fewer frames than the processing minimum.

  • RuntimeError – If one of the plane’s binaries carries the marker of an interrupted write.

  • TypeError – If the runtime context loader returns multiple contexts for the target plane.

Return type:

None

cindra.pipelines.save_combined_data(contexts)

Combines processed data from all imaging planes into a unified dataset and saves it to disk.

Parameters:

contexts (list[RuntimeContext]) – The plane contexts to combine, one per imaging plane. Each must carry the runtime data that the processing pipeline populates.

Raises:
  • ValueError – If no context is provided, if output_path is not configured, or if no plane carries ROI statistics.

  • RuntimeError – If a plane’s registered binary path (or channel 2 registered binary path, when the second channel is functional) is not set, indicating that registration did not complete successfully.

Return type:

None

Registration

Provides algorithms for correcting within-recording motion and registering recordings to a shared field of view.

cindra.registration.project_templates_to_recordings(contexts, *, workers)

Projects template masks from shared visual space back to each recording’s original coordinate system.

Applies the inverse deformation of each recording to map the template masks back to that recording’s native coordinates.

Notes

When every recording’s output directory already contains roi_statistics.npz and repeat_registration is False (default), the function echoes a skip message and returns without re-projecting the templates. The stage writes one archive per recording, so a run interrupted partway through the write loop leaves the recordings it never reached without an archive, and the next run re-projects them.

The worker budget is split between the thread pool width and each pool thread’s own Numba mask, since the Numba mask is thread-local and pool threads do not inherit the mask held by the submitting thread.

Parameters:
  • contexts (list[MultiRecordingRuntimeContext]) – The list of MultiRecordingRuntimeContext instances, one per recording. Each context must have deformation fields stored in runtime.registration from a prior call to register_recordings(), and template masks set in runtime.tracking from ROI tracking.

  • workers (int) – The number of parallel workers allocated to this discovery job. Must be a positive integer.

Return type:

None

cindra.registration.register_plane(context, *, workers, device=None)

Registers (motion-corrects) all frames for a single imaging plane specified by the input runtime context.

Computes registration offsets from the alignment channel (determined by config.registration.align_by_first_channel), then applies those offsets to both channels. If two-step registration is enabled, a refinement pass is performed, which recomputes the reference from a fresh sample of the registered frames and re-registers them against it.

All configuration is read from context.configuration, file paths from context.runtime.io, and results are stored in context.runtime.registration, context.runtime.detection, and context.runtime.timing. The registered frames are written back into the plane’s channel binaries in place. The runtime data is persisted with context.save_runtime() before returning, after which the registration arrays are released from memory, so consumers re-acquire them with memory_map_arrays() or load_arrays().

Notes

The worker count drives both the FFT thread pool used by phase correlation and the Numba thread mask used by the edge-taper, spectrum-normalization, and nonrigid kernels. The Numba mask is thread-local, so concurrently dispatched planes can hold different worker budgets inside a single process.

The device argument selects where both channels are registered, running the pass on a CUDA device when the caller names one and on the host CPU otherwise. Only the alignment channel resolves offsets against a reference, and the secondary channel receives those same offsets, so the two channels hold the same correction. The secondary channel reuses the device state the alignment pass built.

A ‘<binary>.registering’ marker guards every one of the plane’s channel binaries for the whole registration. Only the alignment channel is registered against a reference, and the secondary channel receives the offsets computed from that channel. The two binaries therefore agree about whether motion has been removed only once both rewrites have finished. The markers are cleared after the registration outputs that describe those rewrites are persisted, and an interrupted run leaves them behind for the binarization stage to handle.

Parameters:
  • context (RuntimeContext) – The RuntimeContext containing configuration, file paths, and mutable runtime data structures. Modified in-place to store registration outputs including reference image, offsets, mean images, and timing data.

  • workers (int) – The number of parallel workers allocated to this registration job. Must be a positive integer.

  • device (int | None, default: None) – The zero-based index of the CUDA device that registers this plane. Use None to register the plane on the host CPU.

Return type:

None

cindra.registration.register_recordings(contexts, *, workers)

Registers multiple recording reference images to a common visual space using diffeomorphic demons registration.

This function computes deformation fields that align all recordings to a shared coordinate system, then applies those deformations to transform reference images and ROI masks. The deformation fields and transformed data are stored in each recording’s runtime registration data.

Notes

The function modifies the runtime data in each context in-place.

When all recordings already have registration data (deformation fields and deformed ROI masks) and repeat_registration is False (default), the function returns early without re-running the expensive diffeomorphic registration. When repeat_registration is True, existing registration data is cleared before re-computing.

The groupwise registration runs on the calling thread and receives the full worker budget as its Numba thread mask. The per-recording deformation step then splits that budget between the thread pool width and each pool thread’s own Numba mask, since the Numba mask is thread-local and pool threads do not inherit it.

Parameters:
  • contexts (list[MultiRecordingRuntimeContext]) – The list of MultiRecordingRuntimeContext instances, one per recording. All contexts must share the same configuration. Each context’s runtime.combined_data must be loaded with single-recording detection results.

  • workers (int) – The number of parallel workers allocated to this discovery job. Must be a positive integer.

Return type:

None

Detection

Provides algorithms for segmenting and describing ROIs from motion-corrected recordings.

cindra.detection.compute_registration_blocks(height, width, block_size=(128, 128))

Computes overlapping blocks for nonrigid registration.

Notes

Divides the field of view into overlapping blocks that are registered independently. The blocks are arranged in a regular grid with positions computed so that adjacent blocks overlap by roughly a third of a block, reaching half a block only where the field is twice the block size.

Parameters:
  • height (int) – The imaging field height in pixels.

  • width (int) – The imaging field width in pixels.

  • block_size (tuple[int, int], default: (128, 128)) – The target block size as (height, width) in pixels. Actual block sizes may differ if the image dimensions are smaller than the requested block size.

Return type:

tuple[list[NDArray[int32]], list[NDArray[int32]], tuple[int, int], tuple[int, int], NDArray[float32]]

Returns:

A tuple of (y_blocks, x_blocks, block_counts, actual_block_size, smoothing_kernel). The y_blocks and x_blocks are lists of 2-element arrays specifying the start and end indices for each block. The block_counts tuple gives (y_count, x_count). The actual_block_size tuple gives the final block dimensions. The smoothing_kernel is used for SNR-based adaptive smoothing of correlation peaks across neighboring blocks.

cindra.detection.compute_roi_statistics(rois, frame_height, frame_width, aspect=None, diameter=None, maximum_overlap_fraction=None, *, crop=True, lightweight=False)

Computes shape statistics for a list of ROIStatistics instances in-place.

Notes

Computes statistics (compactness, solidity, radius, aspect ratio, etc.) for each input ROI and writes the computed values back to the ROIStatistics instances. If maximum_overlap_fraction is specified, ROIs exceeding the overlap threshold are removed from the list in-place. When lightweight is True, only the minimal statistics required for preclassification (compactness, pixel_count, soma_mask, and normalized_pixel_count) are computed, skipping the expensive ellipse fitting, convex hull solidity, and overlap computations.

Parameters:
  • rois (list[ROIStatistics]) – The list of ROIStatistics instances that define the ROIs to process. Modified in-place.

  • frame_height (int) – The height of the recording frames from which ROIs are segmented, in pixels.

  • frame_width (int) – The width of the recording frames from which ROIs are segmented, in pixels.

  • aspect (float | None, default: None) – The aspect ratio of the recording. If provided, adjusts ROI ellipse fitting. Ignored in lightweight mode.

  • diameter (int | None, default: None) – The expected ROI diameter in pixels. Used for ROI ellipse fitting normalization and for distance normalization in compactness. Applies in both full and lightweight modes.

  • maximum_overlap_fraction (float | None, default: None) – The maximum fraction of pixels that can overlap with other ROIs. If specified, ROIs exceeding this threshold are removed from the list in-place. Ignored in lightweight mode.

  • crop (bool, default: True) – Determines whether to crop processed ROIs to the soma region before computing statistics.

  • lightweight (bool, default: False) – Determines whether to compute only the minimal statistics needed for preclassification. When True, skips ellipse fitting, solidity, and overlap computations. The aspect and maximum_overlap_fraction parameters are ignored. The diameter is still used for distance normalization in compactness.

Raises:

ValueError – If the input rois list is empty.

Return type:

None

cindra.detection.compute_spatial_taper_mask(sigma: float, height: int, width: int) → NDArray[float32]

Creates a spatial taper mask with sigmoid falloff at the edges.

Notes

The mask smoothly transitions from 1.0 in the center to ~0 at the edges, suppressing border artifacts. The transition follows a sigmoid curve controlled by sigma. Results are cached since the same mask is reused across all frames in a recording.

Parameters:
  • sigma (float) – Controls the steepness of the edge falloff. Larger values produce a more gradual taper.

  • height (int) – The height of the frames to be processed with the generated taper mask, in pixels.

  • width (int) – The width of the frames to be processed with the generated taper mask, in pixels.

Return type:

NDArray[float32]

Returns:

The multiplicative taper mask with shape (height, width), values in range [0, 1].

cindra.detection.detect_plane_rois(context, *, workers)

Detects ROIs from registered binary data and updates the runtime context in-place.

Notes

Orchestrates the full detection pipeline for one or both functional channels. When both channels are functional (independent ROI detection), the pipeline runs independently on each channel since different ROI populations may have different soma sizes and spatial scales. Results are written into context.runtime.detection, context.runtime.extraction, and context.runtime.timing.

The worker count drives the PCA denoising thread pool. The linear-algebra backends that the detection loop uses run under the same budget. Movie binning IO and the serial detection loop bound this stage, so its runtime plateaus at the measured processing default.

Parameters:
  • context (RuntimeContext) – The RuntimeContext containing configuration, file paths, and mutable runtime data structures. Modified in-place to store detection outputs including ROI statistics, image projections, and timing data.

  • workers (int) – The number of parallel workers allocated to this processing job. Must be a positive integer.

Raises:
  • FileNotFoundError – If the configuration provides a custom classifier path that does not name an existing file.

  • RuntimeError – If the registered binary file path for channel 1 is not set.

  • ValueError – If no ROIs are detected on either channel, if preclassification rejects every detected ROI on either channel, or if ‘workers’ is not a positive integer while PCA denoising is enabled.

Return type:

None

cindra.detection.extend_roi(y_pixels, x_pixels, height, width, iterations=1)

Uniformly extends the input ROI by iteratively adding cardinal neighbors to all boundary pixels.

Notes

The expansion follows a Manhattan distance pattern, producing diamond-shaped growth.

Parameters:
  • y_pixels (NDArray[int32]) – The y-coordinates of the ROI pixels.

  • x_pixels (NDArray[int32]) – The x-coordinates of the ROI pixels.

  • height (int) – The height of the recording frame that contains the ROI.

  • width (int) – The width of the recording frame that contains the ROI.

  • iterations (int, default: 1) – The number of iterations to use for the ROI growth. Each iteration expands the ROI’s bounding box by 1 pixel in each direction.

Return type:

tuple[NDArray[int32], NDArray[int32]]

Returns:

A tuple of two arrays. The first array stores the extended ROI pixel y-coordinates. The second array stores the extended ROI pixel x-coordinates.

cindra.detection.track_rois_across_recordings(contexts)

Tracks ROIs across multiple recordings using Jaccard distance-based hierarchical clustering.

Clusters ROI masks from multiple recordings based on spatial overlap in the shared deformed visual space. ROIs that consistently appear in the same location across recordings are grouped together, and a template mask is created for each cluster representing the consensus ROI. When dual-channel data is present, each channel is processed independently.

Notes

Modifies the input contexts in-place, updating each context’s runtime.tracking.template_masks and runtime.tracking.template_diameter (and the template_masks_channel_2 and template_diameter_channel_2 fields for dual-channel recordings) with the generated template ROIs and their estimated diameter, and recording runtime.timing.tracking_time. When the first recording’s output directory already contains tracking_template_masks.npz and repeat_registration is disabled, tracking is skipped and each context’s stored tracking arrays are loaded from disk instead.

Parameters:

contexts (list[MultiRecordingRuntimeContext]) – The list of MultiRecordingRuntimeContext instances, one per recording. Each context must have completed diffeomorphic registration with deformed ROI masks available in runtime.registration.deformed_roi_masks (and optionally deformed_roi_masks_channel_2).

Raises:

ValueError – If the configured spatial binning step sizes are not uniform across both axes.

Return type:

None

Extraction

Provides algorithms for extracting fluorescence from detected ROIs and determining ROI colocalization.

cindra.extraction.extract_traces(context, *, workers)

Extracts fluorescence traces, classifies ROIs, and deconvolves spikes from registered binary data.

Notes

Dispatches to the appropriate internal handler based on the runtime context type. For single-recording contexts, the full extraction pipeline runs including classification and interleaved extraction statistics. For multi-recording contexts, backward-transformed tracked ROI masks are used without reclassification, and the extraction statistics are computed after the traces rather than between them.

Extraction and deconvolution run entirely inside Numba kernels, the extraction pair parallelized over frames and the deconvolution kernel over ROIs, so the worker count is applied as the Numba thread mask before dispatch and covers both branches. The mask is thread-local, so concurrently dispatched recordings can hold different worker budgets inside a single process.

Parameters:
  • context (RuntimeContext | MultiRecordingRuntimeContext) – The runtime context for the recording being processed. Modified in-place to store extraction outputs including fluorescence traces, deconvolved spikes, and colocalization data.

  • workers (int) – The number of parallel workers allocated to this extraction job. Must be a positive integer.

Return type:

None

Classification

Provides classification algorithms for distinguishing cells from artifacts.

class cindra.classification.Classifier(classifier_path, feature_names=None)

Bases: object

Provides logistic regression-based classification for identifying cell ROIs.

Notes

The classifier file format uses pickle-free npz serialization containing training_labels and feature arrays (normalized_pixel_count, compactness, skewness). The model is fitted on load, which takes approximately 10 ms for the default training set.

Parameters:
  • classifier_path (Path) – The path to a classifier .npz file containing training_labels and feature arrays. The file must hold at least _GRID_NODE_COUNT training samples, which is the number of nodes the fitted probability grid spans.

  • feature_names (tuple[str, ...] | None, default: None) – The feature names to use for classification. Only these features are read from the classifier file, and only those among them that are present in it, match the training label count, and carry at least one non-NaN value are used for model fitting. If None, the default classification feature set (_CLASSIFICATION_FEATURES: normalized_pixel_count, compactness, skewness) is used.

_classifier_path

The path to the loaded classifier file.

_available_features

The names of the features the classifier uses.

_training_features

The training values of every used feature.

_training_labels

The training labels with shape (n_samples,).

_probability_grid

The grid boundaries from the sorted training statistics with shape (n_nodes, n_features). Used to map input feature values to grid intervals for probability lookup during classification.

_grid_cell_probabilities

The Gaussian-smoothed probability that an ROI is a cell for each grid interval with shape (n_nodes - 1, n_features). Used to compute log probability ratios that serve as input features for the logistic regression model.

_model

The fitted LogisticRegression model.

Raises:
  • FileNotFoundError – If the classifier file does not exist.

  • ValueError – If the classifier file is unreadable, holds a column that does not cast to its numeric type, or is missing the training labels. It is also raised when the file holds fewer than _GRID_NODE_COUNT training samples, or supplies no requested feature column that both matches the training label count and carries at least one non-NaN value.

classify(roi_statistics, probability_threshold=0.5)

Classifies the ROIs as cells or non-cells based on their morphological features.

Parameters:
  • roi_statistics (list[ROIStatistics]) – The ROIs to classify, holding the morphological features the model reads.

  • probability_threshold (float, default: 0.5) – The probability threshold above which an ROI is classified as a cell.

Return type:

NDArray[float32]

Returns:

An array of shape (n_rois, 2) where each row contains [is_cell, probability]. The is_cell value is 1.0 if the ROI is classified as a cell (probability > threshold) and 0.0 otherwise.

Raises:

ValueError – If the input roi_statistics list is empty.

static create_training_dataset(file_path, training_labels, normalized_pixel_count, compactness, skewness)

Creates a new classifier training dataset file from the provided labels and features.

Notes

The Classifier fits a probability grid of _GRID_NODE_COUNT nodes over the dataset, so it rejects a file holding fewer samples than that when it loads the file.

Parameters:
  • file_path (Path) – The path the classifier file is saved to, which should carry the .npz extension.

  • training_labels (NDArray[bool]) – The label of every training sample, False for an artifact and True for a cell, with shape (n_samples,).

  • normalized_pixel_count (NDArray[float32]) – The normalized pixel count values with shape (n_samples,).

  • compactness (NDArray[float32]) – The compactness values with shape (n_samples,).

  • skewness (NDArray[float32]) – The skewness values with shape (n_samples,).

Raises:

ValueError – If feature arrays have mismatched lengths.

Return type:

None

cindra.classification.classify(roi_statistics, classification_threshold=0.5, custom_classifier_path=None, *, preclassification=False)

Classifies detected ROIs as cells or non-cells using a logistic regression model.

Parameters:
  • roi_statistics (list[ROIStatistics]) – The ROIs to classify, holding the morphological features the model reads. Must contain at least one ROI.

  • classification_threshold (float, default: 0.5) – The probability threshold above which an ROI is classified as a cell. ROIs with probabilities above this threshold are labeled as cells (1.0), others as non-cells (0.0).

  • custom_classifier_path (Path | None, default: None) – An optional path to a custom classifier .npz file. If None, the built-in classifier bundled with cindra is used.

  • preclassification (bool, default: False) – Determines whether to use a 2-feature model (normalized_pixel_count, compactness) suitable for early filtering during detection before signal extraction. When False, uses the full 3-feature model that includes skewness computed from extracted fluorescence traces.

Return type:

NDArray[float32]

Returns:

An array of shape (n_rois, 2) where each row contains [is_cell, probability]. The is_cell value is 1.0 if the ROI is classified as a cell (probability > threshold) and 0.0 otherwise.

Raises:
  • FileNotFoundError – If custom_classifier_path is provided but does not name an existing file.

  • ValueError – If the input roi_statistics list is empty. It is also raised when the resolved classifier file is unreadable, holds a column that does not cast to its numeric type, is missing the training labels, holds fewer than _GRID_NODE_COUNT training samples, or supplies no usable feature column.

File I/O

Provides assets for converting, reading, inventorying, and combining a recording’s imaging data on disk.

class cindra.io.BinaryFile(height, width, file_path, frame_number=0, dtype='int16', *, read_only=False)

Bases: object

Creates or opens a cindra binary (.bin) for reading and/or writing image data.

The file behaves like a memory-mapped NumPy array and can be converted between cindra binary and NumPy array format at any time with minimal call API changes.

Parameters:
  • height (int) – The height of each frame stored inside the file.

  • width (int) – The width of each frame stored inside the file.

  • file_path (str | Path) – The absolute path of the file to read from or write to.

  • frame_number (int, default: 0) – The number of frames a newly created file is sized to hold. The value is ignored when the file already exists, where the frame count is read from the file’s size instead.

  • dtype (str, default: 'int16') – The name of the NumPy data type to use for the pixel values stored inside the file.

  • read_only (bool, default: False) – Determines whether to open an existing file in read-only mode. When enabled, the file is memory-mapped without write access and __setitem__ raises a PermissionError.

height

Stores the height of each frame stored inside the file.

width

Stores the width of each frame stored inside the file.

file_path

Stores the absolute path to the file managed by this instance.

dtype

Stores the name of the datatype used by the file values.

_read_only

Stores whether the file was opened in read-only mode.

file

Stores the NumPy array instance used to memory-map the contents of the binary file.

Raises:
  • ValueError – If the number of frames is not provided when creating (writing) a new BinaryFile instance, or if read-only mode is requested for a file that does not exist.

  • PermissionError – If __setitem__ is called on a file opened in read-only mode.

bin_movie(bin_size, x_range=None, y_range=None, bad_frames=None, reject_threshold=0.5)

Bins the frames of the movie (frame sequence) stored inside the file wrapped by this instance.

Parameters:
  • bin_size (int) – The size of each bin, in frames.

  • x_range (tuple[int, int] | None, default: None) – A tuple of (start, end) indices for cropping frames along the x-axis, where the end index is exclusive. If set to None, no cropping (x or y) is performed.

  • y_range (tuple[int, int] | None, default: None) – A tuple of (start, end) indices for cropping frames along the y-axis, where the end index is exclusive. If set to None, no cropping (x or y) is performed.

  • bad_frames (NDArray[bool] | None, default: None) – A mask holding one element per frame stored inside the BinaryFile managed by this instance, True at each bad frame and False at each good frame.

  • reject_threshold (float, default: 0.5) – The fraction of good frames to all frames inside the batch that must be exceeded for bad frames to be discarded. If the fraction of good frames in the batch does not exceed this threshold, then both bad and good frames are kept and binned as part of the batch processing.

Return type:

NDArray[float32]

Returns:

The binned movie, shaped as (bin_number, height, width). Each bin holds the average of bin_size frames taken from one batch. A batch left with bin_size or fewer frames is averaged into a single bin instead, and the bad frames discarded from a batch are absent from the frames its bins average.

property byte_number: int

Returns the total number of bytes stored in the file.

property bytes_per_frame: int

Returns the memory size, in bytes, reserved by each frame stored inside the file.

close()

Closes the memory-mapped file view.

Return type:

None

static convert_numpy_file_to_binary(source_file_name, destination_file_name)

Converts a NumPy .npy file to a cindra binary.

Parameters:
  • source_file_name (Path) – The absolute path to the NumPy .npy file to convert to cindra binary format.

  • destination_file_name (Path) – The absolute path to the cindra .bin file to create using the data from the source file.

Raises:

FileNotFoundError – If the provided NumPy file does not exist, is not a regular file, or does not use the .npy extension.

Return type:

None

property data: NDArray[int16]

Returns all frames stored inside the file as a NumPy array.

property frame_number: int

Returns the total number of frames stored in the file.

property shape: tuple[int, int, int]

Returns the dimensions of the data in the file as (frame_number, height, width).

property size: int64

Returns the total number of pixels (values) stored inside the file.

subsample_movie(sample_count, x_range=None, y_range=None)

Subsamples the movie by selecting evenly-spaced frames across the recording.

Parameters:
  • sample_count (int) – The number of frames to sample from the movie. The actual number of returned frames is min(sample_count, frame_number).

  • x_range (tuple[int, int] | None, default: None) – A tuple of (start, end) indices for cropping frames along the x-axis. Cropping is applied only when both x_range and y_range are provided. If set to None, no cropping (x or y) is performed.

  • y_range (tuple[int, int] | None, default: None) – A tuple of (start, end) indices for cropping frames along the y-axis. Cropping is applied only when both x_range and y_range are provided. If set to None, no cropping (x or y) is performed.

Return type:

NDArray[float32]

Returns:

The subsampled and optionally cropped frames, shaped as (sample_count, height, width), where the leading dimension is capped at the file’s frame count.

write_tiff(file_name, frame_range=None, y_range=None, x_range=None)

Writes the contents of the BinaryFile wrapped by this instance into a .tiff file.

The output data is encoded into a single BigTiff stack.

Parameters:
  • file_name (Path) – The absolute path to the output .tiff file.

  • frame_range (slice | None, default: None) – The frames to export. If None, exports all frames.

  • y_range (slice | None, default: None) – The y (height) range to crop. If None, uses full height.

  • x_range (slice | None, default: None) – The x (width) range to crop. If None, uses full width.

Return type:

None

class cindra.io.BinaryFileCombined(height, width, plane_heights, plane_widths, plane_y_coordinates, plane_x_coordinates, file_paths)

Bases: object

Opens a collection of existing cindra binaries (.bin) for reading image data across planes.

Works with multiple imaging planes, each stored inside a separate cindra binary.

Notes

The combined view is capped at the shortest managed file’s frame count and a warning is emitted whenever the binaries disagree, which keeps every combined frame backed by real data on every plane.

Parameters:
  • height (int) – The height of the combined ROI, in pixels, obtained by combining all managed planes (BinaryFiles). This is the height of the ROI that would be drawn if all managed planes were combined into a single image.

  • width (int) – The width of the combined ROI, in pixels, obtained by combining all managed planes (BinaryFiles). This is the width of the ROI that would be drawn if all managed planes were combined into a single image.

  • plane_heights (NDArray[uint16]) – The height of each plane (BinaryFile) managed by this instance.

  • plane_widths (NDArray[uint16]) – The width of each plane (BinaryFile) managed by this instance.

  • plane_y_coordinates (NDArray[int32]) – The top-left-corner pixel y-coordinate of each managed plane, relative to the original image from which plane data was extracted.

  • plane_x_coordinates (NDArray[int32]) – The top-left-corner pixel x-coordinate of each managed plane, relative to the original image from which plane data was extracted.

  • file_paths (list[Path] | tuple[Path, ...]) – The absolute paths to the binary files from which to read the plane data.

height

Stores the combined height of all managed planes.

width

Stores the combined width of all managed planes.

plane_heights

Stores the heights of each plane managed by this instance.

plane_widths

Stores the widths of each plane managed by this instance.

plane_y_coordinates

Stores the top-left-corner pixel y-coordinates of each plane managed by this instance.

plane_x_coordinates

Stores the top-left-corner pixel x-coordinates of each plane managed by this instance.

file_paths

Stores the absolute paths to the BinaryFiles for each plane managed by this instance.

files

Stores opened (memory-mapped) BinaryFile instances for each plane managed by this instance.

_frame_number

Stores the number of frames spanned by the combined view, which is the frame count of the shortest managed file.

property byte_number: NDArray[int64]

Returns an array that stores the size of each managed BinaryFile, in bytes.

close()

Closes the memory-mapped file view for all managed plane files.

Return type:

None

property frame_number: int

Returns the number of frames the combined view spans, which is that of the shortest managed file.

property shape: tuple[int, NDArray[uint16], NDArray[uint16]]

Returns the dimensions of the managed files as (frame_number, plane_heights, plane_widths), where frame_number is the frame count of the shortest managed file and the arrays contain per-file plane dimensions.

class cindra.io.DatasetRecordings(dataset_name, recording_roots=(), recording_ids=(), dataset_paths=(), extracted_recordings=(), discovered=False)

Bases: object

Describes the recordings one tracked multi-recording dataset spans and how far the dataset has been processed.

dataset_name: str

The name of the tracked dataset, already lowered to the fold the output directory carries.

dataset_paths: tuple[Path, ...]

The dataset output directory inside every recording’s output directory.

discovered: bool

Determines whether the dataset carries the tracked template mask archive, which the clustering step writes before the projection back into each recording and which therefore marks the dataset as tracked rather than the discovery job as finished.

extracted_recordings: tuple[str, ...]

The identifiers of the recordings whose tracked fluorescence has already been extracted.

recording_ids: tuple[str, ...]

The identifier of every recording, derived from the component of its path that distinguishes it.

recording_roots: tuple[Path, ...]

The output root of every recording the dataset spans, in the order the caller supplied them.

class cindra.io.RecordingPlanes(output_root, plane_count, plane_paths=(), plane_specifiers=(), registered_planes=(), processed=False, resolved=False)

Bases: object

Describes the virtual imaging planes one recording holds and how far each of them has been processed.

output_root: Path

The output root this inventory describes.

plane_count: int

The number of virtual imaging planes the recording holds, which is zero when its parameters were not found.

plane_paths: tuple[Path, ...]

The output directory of every virtual plane, ordered by plane index.

plane_specifiers: tuple[str, ...]

The specifier identifying every virtual plane, ordered by plane index.

processed: bool

Determines whether the recording carries the combined metadata archive that marks its pipeline complete.

registered_planes: tuple[int, ...]

The indices of the planes carrying registration output, which are the planes the processing stage can run.

resolved: bool

Determines whether the recording’s own acquisition parameters supplied the plane count.

class cindra.io.SourceFrameGeometry(frame_height, frame_width, element_bytes, frame_count)

Bases: object

Describes the frames a recording’s source files hold, read from their headers alone.

element_bytes: int

The width of one source element in bytes.

frame_count: int

The frames the source files hold across every plane and channel.

frame_height: int

The height of one whole acquisition frame in pixels.

frame_width: int

The width of one whole acquisition frame in pixels.

cindra.io.clear_dataset_selection(dataset_path)

Clears the region selection one multi-recording dataset holds for one recording.

Notes

A selection names regions by their position in the recording’s own region list, so a detection run that rebuilds that list invalidates it. Clearing the selection makes the discovery stage select again for this recording, while the recording identity and dataset membership the same file carries stay in place.

Parameters:

dataset_path (Path) – The recording’s directory inside one dataset tree, which holds that dataset’s runtime data file.

Return type:

bool

Returns:

True when a selection was cleared, and False when the directory holds no runtime data file or no selection.

cindra.io.clear_recording_selections(cindra_root)

Clears the region selections every multi-recording dataset holds for one recording.

Parameters:

cindra_root (Path) – The recording’s cindra output directory, which parents its multi_recording directory.

Return type:

int

Returns:

The number of dataset selections cleared, which is zero when the recording belongs to no dataset.

cindra.io.clear_registration_marker(binary_path)

Clears the mid-registration mark from a binary, which declares its contents consistent again.

Notes

Clearing a marker that does not exist is not an error, so the registration stage can call this for every binary it finishes without first checking whether an earlier interrupted rewrite left one behind.

Parameters:

binary_path (Path) – The path to the binary whose mark is cleared.

Return type:

None

cindra.io.combine_planes(plane_contexts)

Combines processed data from multiple planes into a unified dataset.

The combined product carries the detection images, the extraction data of both channels, the per-plane geometry, the registered binary paths, tau, and the sampling rate. Planes that did not complete detection or extraction contribute no traces, ROI statistics, or summary images, while their frame geometry, frame count, and registered binary path still reach the product. The combined traces are trimmed to the frame count of the shortest contributing plane, which is stored as CombinedData.frame_count alongside each plane’s own count in CombinedData.plane_frame_counts.

Parameters:

plane_contexts (list[RuntimeContext]) – The runtime context of every plane being combined.

Return type:

CombinedData

Returns:

The combined detection and extraction data.

Raises:
  • ValueError – If no valid planes with ROI statistics are found.

  • RuntimeError – If a plane’s registered binary path (or channel 2 registered binary path, when the second channel is functional) is not set, indicating registration did not complete successfully.

cindra.io.convert_tiffs_to_binary(plan)

Converts the TIFF files a conversion plan names into cindra binary format for all planes.

Reads the planned source files in batches and writes the converted frames into each plane’s binary files. The function handles both standard TIFF data and MROI (Multi-ROI) data automatically based on the acquisition parameters stored in the planned contexts.

Notes

Modifies the planned contexts in place, populating frame dimensions, frame counts, and mean images in each context’s runtime data, and initializing each plane’s valid pixel ranges to the full frame. It also persists each plane’s runtime data through context.save_runtime() before any binarization mark is cleared, so the frame geometry the binaries were written against is durable on disk.

The conversion reads the leading frames the plan budgets, which span whole plane and channel interleave cycles alone, so the trailing frames of an incomplete final cycle are never decoded.

Every destination binary carries a mid-write mark for the duration of the conversion and is cleared of it once the frame accounting agrees and the file is closed. Each binary is sized to its full frame count when it is opened, so an interrupted conversion leaves a correctly sized file whose tail frames are zeros. The mark is what makes the binarization stage refuse that file instead of consuming it.

Parameters:

plan (TiffConversionPlan) – The conversion plan resolved by resolve_tiff_conversion_plan(), which names the source files, the destination binaries, and the number of frames each plane receives. Every one of those counts is positive, so opening a destination binary raises nothing the resolution has not already rejected.

Raises:

RuntimeError – If a plane receives a different number of frames than the count that sized its binary file.

Return type:

None

cindra.io.create_registration_marker(binary_path)

Marks a binary as being mid-registration, which declares its contents indeterminate until the mark is cleared.

Parameters:

binary_path (Path) – The path to the binary whose rewrite is about to begin.

Return type:

None

cindra.io.extract_unique_components(paths)

Extracts the first component from the end of each input path that uniquely identifies each path globally.

Notes

Adapts the multi-recording pipeline to directory structures where the unique recording identifier appears at different levels of the path hierarchy. This allows users to organize recordings using any naming convention, as long as each path contains at least one unique component somewhere in its hierarchy.

The returned components become the tracker specifiers of the multi-recording extraction jobs, and a specifier is hashed into its job identifier alongside the job name with a colon joining the two. A component carrying a colon would therefore collide with a differently split pair, so it is rejected here rather than at identifier generation, where the diagnostic no longer names the directory that produced it.

A directory listed twice shares every component with its duplicate, so it carries no unique component and is rejected, which keeps two jobs of the same dataset from collapsing onto one tracker record.

Parameters:

paths (list[Path] | tuple[Path, ...]) – The recording directories whose distinguishing components are resolved.

Return type:

tuple[str, ...]

Returns:

A tuple of unique components, one for each path, stored in the same order as the input paths.

Raises:

RuntimeError – If one or more paths do not contain unique components, or if a resolved component contains a colon.

cindra.io.find_cindra_directory(recording_directory)

Discovers the cindra output directory within a recording directory tree.

Searches recursively for the combined_metadata.npz file created by the single-recording pipeline’s combination step. The cindra directory may be nested at an arbitrary depth below the recording root.

Parameters:

recording_directory (Path) – The path to the recording’s root directory.

Return type:

Path

Returns:

The path to the cindra output directory that contains the combined_metadata.npz file.

Raises:
  • FileNotFoundError – If no combined_metadata.npz file is found under the recording directory.

  • RuntimeError – If multiple combined_metadata.npz files are found under the recording directory.

cindra.io.find_data_directory(data_path)

Recursively searches for the directory containing the acquisition parameters JSON file.

The matched directory is expected to also hold the recording’s TIFF files.

Parameters:

data_path (Path) – The root directory to search for the acquisition parameters file.

Return type:

Path

Returns:

The path to the directory containing the acquisition parameters JSON file.

Raises:
  • FileNotFoundError – If no acquisition parameters file is found in the data directory or its subdirectories.

  • ValueError – If the data_path is not a directory.

cindra.io.is_dataset_discovered(output_root, dataset_name)

Determines whether a tracked dataset’s discovery phase has completed.

Parameters:
  • output_root (Path) – The output root of the recording holding the dataset directory.

  • dataset_name (str) – The name of the tracked dataset, in any casing.

Return type:

bool

Returns:

True when the dataset carries the tracked template mask archive, which the clustering step writes partway through the discovery job.

cindra.io.is_plane_converted(output_root, plane_index)

Determines whether one virtual imaging plane carries the binary the conversion stage writes.

Parameters:
  • output_root (Path) – The recording’s configured output root.

  • plane_index (int) – The index of the virtual imaging plane.

Return type:

bool

Returns:

True when the plane carries its functional channel binary.

cindra.io.is_plane_processed(output_root, plane_index)

Determines whether one virtual imaging plane carries the traces the processing stage writes.

Notes

The traces are what the combination stage concatenates, so this is the condition under which a combination job’s own inputs exist.

Parameters:
  • output_root (Path) – The recording’s configured output root.

  • plane_index (int) – The index of the virtual imaging plane.

Return type:

bool

Returns:

True when the plane carries its extracted fluorescence trace.

cindra.io.is_plane_registered(output_root, plane_index)

Determines whether one virtual imaging plane carries registration output.

Parameters:
  • output_root (Path) – The recording’s configured output root.

  • plane_index (int) – The index of the virtual imaging plane.

Return type:

bool

Returns:

True when the plane carries the reference image the registration stage writes.

cindra.io.is_recording_extractable(output_root, dataset_name)

Determines whether one recording carries the tracked masks its own extraction job reads.

Notes

The discovery stage projects a template mask set back into every recording it spans, and the extraction stage refuses to run without that recording’s own projected statistics. The dataset-wide template archive marks the clustering step rather than the projection, so it does not gate an extraction job.

Parameters:
  • output_root (Path) – The recording’s configured output root.

  • dataset_name (str) – The name of the tracked dataset, in any casing.

Return type:

bool

Returns:

True when the recording carries its own projected ROI statistics.

cindra.io.is_recording_processed(output_root)

Determines whether a recording’s single-recording pipeline has completed.

Notes

Reads the combined metadata archive, which the combination stage publishes after its payload arrays through an atomic write, so its presence marks every array it describes as already on disk.

Parameters:

output_root (Path) – The recording’s configured output root.

Return type:

bool

Returns:

True when the recording carries the completion marker.

cindra.io.resolve_acquisition_parameters(output_root, data_path)

Resolves a recording’s acquisition parameters from its output directory or its raw imaging directory.

Parameters:
  • output_root (Path) – The recording’s configured output root.

  • data_path (Path | None) – The raw imaging directory, consulted only when the output directory carries no parameters.

Return type:

AcquisitionParameters | None

Returns:

The recording’s acquisition parameters, or None when neither directory carries them.

cindra.io.resolve_active_binary_marker(binary_path)

Returns the path of the phase marker sitting beside a plane binary, or None when the binary carries neither.

Notes

Binarization sizes a plane binary to its full frame count the moment it opens it, and registration then rewrites that binary in place. An interrupted run of either stage leaves a correctly sized binary holding an indeterminate mixture of frames, which nothing but the marker records. Both markers carry the same meaning for the pipeline, so every stage that consumes a binary asks this rather than testing one phase’s marker.

Parameters:

binary_path (Path) – The path to the binary that may carry a marker beside it.

Return type:

Path | None

Returns:

The path of the marker guarding the binary, or None when no stage left one there.

cindra.io.resolve_dataset_recordings(recording_roots, dataset_name)

Resolves the recordings one tracked dataset spans and how far the dataset has been processed.

Notes

The dataset is considered discovered when the first recording’s dataset directory carries the template mask archive, matching where the discovery stage writes it. A recording is considered extracted when its own dataset directory carries the tracked fluorescence trace, which only the extraction stage writes. Resolving costs a few small reads and creates nothing on disk.

Parameters:
  • recording_roots (Sequence[Path]) – The output root of every recording the dataset spans.

  • dataset_name (str) – The name of the tracked dataset, in any casing.

Return type:

DatasetRecordings

Returns:

The dataset’s recording inventory.

cindra.io.resolve_multi_recording_contexts(configuration, target_recording_id=None, *, persist=True)

Creates MultiRecordingRuntimeContext instances for recordings processed by the target multi-recording pipeline.

Performs the initial setup for multi-recording processing: discovers cindra output directories for each recording, derives multi_recording output paths, and initializes MultiRecordingRuntimeContext instances.

Notes

Each recording directory must contain exactly one cindra output directory with a combined_metadata.npz file from a completed single-recording pipeline run. The function extracts unique recording identifiers from the directory paths to distinguish recordings within the dataset.

With persist=True (the default), the shared dataset configuration and every recording’s runtime data file are saved to disk at the end of resolution, ensuring they reflect the current settings.

With persist=False, no files are written. This mode is required for worker entry (REMOTE mode), because this resolver builds a context for every recording rather than for the one recording the worker was dispatched to process. A persisting worker would therefore write each peer recording’s multi_recording_runtime_data.yaml from its own snapshot, overwriting whatever a peer had already recorded there with content that is whole and parsable but stale. Workers must therefore only load the bootstrap written by the earlier prepare step. When persist=False, any missing multi_recording_runtime_data.yaml is treated as a hard error because it indicates prepare_multi_recording_batch_tool was not run first.

ROI selection is performed as a separate step using select_recording_rois(), not during context resolution.

When target_recording_id is provided, only the matching recording’s CombinedData and runtime data are loaded. Non-matching recordings are skipped entirely. This avoids the overhead of loading large arrays for recordings that will not be used (e.g., during per-recording extraction).

Parameters:
  • configuration (MultiRecordingConfiguration) – The multi-recording pipeline configuration. Must have recording_directories and dataset_name configured in recording_io.

  • target_recording_id (str | None, default: None) – When provided, only resolves the context for the recording matching this identifier. The returned list contains a single element. When None (default), all recordings are resolved.

  • persist (bool, default: True) – When True (default), writes the shared configuration and every resolved context’s multi_recording_runtime_data.yaml at the end of resolution. When False, treats the call as load-only and raises FileNotFoundError if any expected runtime data file is missing.

Return type:

list[MultiRecordingRuntimeContext]

Returns:

A list of MultiRecordingRuntimeContext instances, one per recording (or one element when target_recording_id is set). Each context contains references to the shared configuration and a recording-specific MultiRecordingRuntimeData instance with MultiRecordingIOData fields initialized.

Raises:
  • FileNotFoundError – If no combined_metadata.npz file is found in a recording directory, or if persist=False and any resolved recording’s multi_recording_runtime_data.yaml does not already exist on disk.

  • RuntimeError – If multiple combined_metadata.npz files are found in a recording directory, if recording paths do not contain unique identifying components, or if a resolved recording identifier contains a colon.

  • ValueError – If target_recording_id does not match any resolved recording identifier.

cindra.io.resolve_recording_planes(output_root, data_path=None)

Resolves the virtual imaging planes one recording holds and how far each of them has been processed.

Notes

The plane count is read from the acquisition parameters the recording’s output directory carries, falling back to the parameters file in the raw imaging directory when the recording has not been processed yet. A recording offering neither resolves to an empty record whose plane count is zero and whose resolved flag is False, because an absent recording is an answer a caller plans around rather than a failure.

The plane count follows the same rule the context resolver applies, so the planes named here are the planes the pipeline creates. Resolving costs a few small reads and creates nothing on disk.

Parameters:
  • output_root (Path) – The recording’s configured output root.

  • data_path (Path | None, default: None) – The raw imaging directory, consulted only when the output directory carries no acquisition parameters. Use None when the recording has already been processed.

Return type:

RecordingPlanes

Returns:

The recording’s plane inventory.

cindra.io.resolve_recording_roots(paths)

Resolves a set of discovered marker-file directories to their recording root directories.

Recording roots are the meaningful top-level directories that uniquely identify each recording session. A marker directory that is itself a pipeline output directory resolves to its parent, which is the path every downstream status, cleaning, and preparation tool expects. Any other marker directory, whose depth below the recording root is user-defined, is truncated at its deepest distinguishing component, which strips a common structural subdirectory without assuming any particular name.

Notes

The output-directory roots are reported ahead of the roots inferred from the remaining directories, so the result follows those two groups rather than the order the paths arrived in. Each group is resolved by its own rule, and every consumer sorts the result before displaying it.

Parameters:

paths (list[Path] | tuple[Path, ...]) – Directories containing discovered marker files (e.g., parents of cindra_parameters.json or combined_metadata.npz).

Return type:

tuple[Path, ...]

Returns:

A deduplicated tuple of recording root paths, one per unique recording.

cindra.io.resolve_single_recording_contexts(configuration, *, persist=True)

Creates RuntimeContext instances for all imaging planes processed by the target single-recording pipeline.

Performs the initial setup for single-recording processing: finds acquisition parameters from the data directory, creates output directories, and initializes RuntimeContext instances for each of the recording’s planes.

Notes

For standard single-ROI data, one context is created per physical plane. For MROI (Multi-ROI) data, one context is created per virtual plane, where virtual planes are ROI x physical plane combinations.

With persist=True (the default), the shared configuration and acquisition parameters plus every plane’s runtime data file are saved to disk at the end of resolution, ensuring they reflect the current settings.

With persist=False, no files are written. This mode is required for worker entry (REMOTE mode), because this resolver builds a context for every plane rather than for the one plane the worker was dispatched to process. A persisting worker would therefore write each peer plane’s runtime_data.yaml from its own snapshot, overwriting whatever a peer had already recorded there with content that is whole and parsable but stale. Workers must therefore only load the bootstrap written by the earlier prepare step. When persist=False, any missing runtime_data.yaml is treated as a hard error because it indicates prepare_single_recording_batch_tool was not run first.

When loading previously processed data (e.g., data moved to a different machine), acquisition parameters are loaded from the saved output directory if available, allowing the pipeline to work without raw TIFF data. A plane record written before the recording declared its second channel receives that channel’s binary path here, so the conversion that the re-declaration requires has a destination for the new channel’s frames.

Parameters:
  • configuration (SingleRecordingConfiguration) – The single-recording pipeline configuration. Must have output_path configured in file_io. The data_path is only required when raw data needs to be processed (rebinarization) or when no processed data exists.

  • persist (bool, default: True) – When True (default), writes the shared configuration plus every plane’s runtime_data.yaml at the end of resolution. When False, treats the call as load-only and raises FileNotFoundError if any expected runtime_data.yaml is missing.

Return type:

list[RuntimeContext]

Returns:

A list of RuntimeContext instances, one per plane (or virtual plane for MROI data). Each context contains references to the shared configuration, acquisition parameters, and a plane-specific SingleRecordingRuntimeData instance with IOData fields initialized.

Raises:
  • ValueError – If output_path is not configured, or if no processed data exists at output_path while data_path is also not configured. Also raised when data_path is not a directory, when the acquisition parameters file omits a required field, when it carries a non-positive frame rate, plane count, channel count, or ROI count, or when it specifies more than 2 channels.

  • FileNotFoundError – If the acquisition parameters file is not found under data_path, or if persist=False and any plane’s runtime_data.yaml does not already exist on disk.

cindra.io.resolve_source_frame_geometry(data_directory, ignored_file_names=())

Reads the frame shape, element width, and frame count a recording’s source files hold.

Notes

Opens the header of the first source file alone, so the cost stays flat however many frames the recording holds. The frame count is that file’s page count multiplied by the file count, which is exact while every file is full and an upper bound once the final one is short. A memory estimate sized from it therefore never understates, which is the safe direction for an estimate to err.

Parameters:
  • data_directory (Path) – The directory holding the recording’s source TIFF files, which is scanned non-recursively.

  • ignored_file_names (tuple[str, ...], default: ()) – The file stems to exclude from discovery.

Return type:

SourceFrameGeometry

Returns:

The geometry the source files hold.

Raises:

FileNotFoundError – If the directory holds no TIFF file the discovery accepts.

cindra.io.resolve_tiff_conversion_plan(contexts, *, workers)

Resolves every source file the TIFF to binary conversion reads and every binary it writes.

Discovers the recording’s TIFF files, counts the frames each plane and channel receives, reads the frame geometry the source files hold, and names the destination binary of every plane.

Notes

The allocated workers become the TIFF image decode threads, capped at TIFF_DECODE_CEILING.

The plan budgets whole plane and channel interleave cycles alone, so every plane receives the same count on every channel and the frames of an incomplete final cycle are left out of the conversion.

This resolution runs every check that can reject the recording, down to the frame accounting that leaves the recording without one complete interleave cycle. A caller that must discard data derived from the recording’s previous binaries resolves a plan first, which leaves that data untouched when the recording cannot be converted.

Parameters:
  • contexts (list[RuntimeContext]) – The runtime context of every plane the conversion writes, in plane order. Each context must have valid configuration, acquisition parameters, and IOData with binary file paths configured.

  • workers (int) – The number of parallel workers allocated to this binarization job. Must be a positive integer, which the caller resolves before invoking this function.

Return type:

TiffConversionPlan

Returns:

The resolved conversion plan.

Raises:
  • ValueError – If contexts is empty, if data_path is not configured, if data_path is not a directory, or if a plane carries no destination binary path. Also raised if the first discovered TIFF file holds no pages, or if the discovered TIFF files do not all hold frames of the same shape. Raised as well if those frames do not fill one complete plane and channel interleave cycle.

  • FileNotFoundError – If no acquisition parameters file is found under data_path, or if no TIFF files are found in the data directory.

cindra.io.select_recording_rois(contexts)

Selects ROIs from single-recording pipeline outputs that meet multi-recording tracking criteria.

Performs ROI selection filtering on each recording using the ROI selection parameters from the configuration. The CombinedData for each recording is accessed from runtime.combined_data (loaded during context resolution), and the selected ROI indices are stored in runtime.io.selected_roi_indices (channel 1) and runtime.io.selected_roi_indices_channel_2 (channel 2, if available). Each processed recording’s runtime data file is written to disk after its selection completes.

Notes

Selection is an on-demand operation. When repeat_selection is False (default), recordings with existing ROI selections are skipped. When repeat_selection is True, selection is re-run for all recordings even if selections already exist.

For recordings with two functional channels, both channels are filtered independently. Channel 2 uses its own probability_threshold_channel_2, maximum_size_channel_2, and mroi_region_margin_channel_2 parameters when they are configured, and falls back to the channel 1 parameters otherwise. The output messages report ROI counts for both channels when channel 2 data is present.

Parameters:

contexts (list[MultiRecordingRuntimeContext]) – The recordings to process. Each context must have combined_data available in its runtime (set during context resolution).

Raises:

ValueError – If combined_data is not available in the runtime, does not contain ROI statistics, or does not contain classification results.

Return type:

None

cindra.io.tiff.TIFF_EXTENSIONS: tuple[str, ...] = ('tif', 'tiff', 'TIF', 'TIFF')

The supported TIFF file extensions.

cindra.io.tiff.TIFF_DECODE_CEILING: int = 4

The maximum number of TIFF decode threads, measured as the point where added decode threads stop shortening the conversion. The decode pool never exceeds this value regardless of how many cores the surrounding job holds.

cindra.io.context.MAXIMUM_CHANNEL_COUNT: int = 2

The maximum number of imaging channels supported by the pipeline.

GUI Viewers

Provides interactive GUIs for visualizing single-recording and multi-recording pipeline outputs.

cindra.gui.cleanup_state_file(state_path)

Removes the state file and any temporary file a killed writer left beside it.

Parameters:

state_path (Path) – The path to the state file to clean up.

Return type:

None

cindra.gui.generate_state_path(viewer_id)

Generates a temporary file path for viewer state exchange.

Parameters:

viewer_id (str) – The unique identifier for the viewer instance.

Return type:

str

Returns:

The absolute path string to the temporary state file.

cindra.gui.read_viewer_state(state_path)

Reads viewer state from a JSON file.

Parameters:

state_path (Path) – The path to the state file.

Return type:

dict[str, Any]

Returns:

The deserialized state dictionary.

cindra.gui.run_registration_viewer(recording_path, *, state_path=None)

Launches the standalone single-recording registration viewer.

Creates a QApplication, shows the BinaryPlayer and PCViewer windows, and enters the event loop. The binary viewer always displays the stitched multi-plane movie while the PC viewer receives an independent shallow copy of the data with its own plane selector.

Parameters:
  • recording_path (Path) – The path to a cindra-processed recording’s root data directory containing registration results.

  • state_path (Path | None, default: None) – Path to a state file for cross-process state exchange with the GUI MCP server. When provided, a StateWriter polls both viewers’ display states and writes the combined state to this file.

Return type:

None

cindra.gui.run_roi_viewer(recording_path, *, dataset=None, state_path=None)

Launches the standalone ROI viewer with click-based ROI selection and classifier-mode relabeling.

Creates a QApplication, loads pipeline data from the given recording directory, shows the ROIViewer window, and enters the event loop.

Parameters:
  • recording_path (Path) – Path to a cindra output directory to load on startup.

  • dataset (str | None, default: None) – Multi-recording dataset name to load. Stays in single-recording mode if not provided.

  • state_path (Path | None, default: None) – Path to a state file for cross-process state exchange with the GUI MCP server. When provided, a StateWriter polls the viewer’s display state and writes changes to this file.

Return type:

None

cindra.gui.run_tracking_viewer(recording_path, *, dataset=None, state_path=None)

Launches the standalone multi-recording tracking viewer.

Creates a QApplication, shows the TrackingViewer window, and enters the event loop. The viewer loads multi-recording tracking data from the provided directory on startup.

Parameters:
  • recording_path (Path) – The path to the root data directory for any cindra-processed recording that makes up the visualized multi-recording dataset. The loader uses that recording’s data to search and reconstruct the full dataset hierarchy.

  • dataset (str | None, default: None) – Multi-recording dataset name to load. Defaults to the first available dataset.

  • state_path (Path | None, default: None) – Path to a state file for cross-process state exchange with the GUI MCP server. When provided, a StateWriter polls the viewer’s display state and writes changes to this file.

Return type:

None

Main CLI

cindra

Provides the entry-point for all headless command-line interactions with the cindra library.

Usage

cindra [OPTIONS] COMMAND [ARGS]...

configure

Generates the configuration file for the specified processing pipeline.

Modifying the parameters stored in the generated file allows configuring all aspects of the target processing pipeline. Provide the path to the modified file to the ‘run’ CLI command to execute the desired pipeline with the parameters specified inside the file.

Usage

cindra configure [OPTIONS]

Options

-p, --pipeline <pipeline>

Required The type of processing pipeline to generate the configuration file for.

Options:

single-recording | sd | multi-recording | md

-od, --output-path <output_path>

Required The absolute path to the (existing) directory in which to generate the requested configuration file.

-n, --name <name>

The name to use for the generated configuration file. Defaults to ‘cindra_sd_conf’ or ‘cindra_md_conf’.

gpu

Reports the CUDA devices the registration stage runs on, and why it reaches none.

Single-recording planes register on a CUDA device through the CuPy runtime when the run names one. This reports every device the host exposes, together with its memory and compute capability, after transforming a small array on the device the runtime selects by default. That transform is what separates a reachable device from an importable module, because CuPy resolves the CUDA math libraries on first use rather than at import. A host that reaches no device reports the reason and the installation that resolves it, and exits with a non-zero status. Running the command on macOS reports that CuPy publishes no wheel for the platform, where registration runs on the host CPU.

Usage

cindra gpu [OPTIONS]

mcp

Starts the Model Context Protocol (MCP) server for agentic neural imaging data processing.

The MCP server exposes tools that enable AI agents to discover recording data, execute pipelines, monitor processing status, and manage batch operations for both single-recording and multi-recording workflows.

Usage

cindra mcp [OPTIONS]

Options

-t, --transport <transport>

The transport protocol to use for MCP communication.

Default:

'stdio'

Options:

stdio | sse | streamable-http

omp

Links the OpenMP runtime that the Numba threading layer loads on macOS into a directory the loader searches.

The Numba macOS wheel names its OpenMP dependency through an rpath that carries no entries, so the loader expands that name against the entries the running interpreter carries and reaches its library directory alone. This command finds an installed runtime and links it into that directory. A conda environment grants that write without sudo, while a system-wide interpreter needs it. Running the command on any other platform errors, because those platforms run the TBB threading layer instead.

Usage

cindra omp [OPTIONS]

Options

-s, --source <source>

The path to the OpenMP runtime to link. Omit to search the macOS package manager directories, the active conda environment, and the installed Python distributions for one.

-t, --target <target>

The path to write the link to. Omit to derive it from the directory the dynamic loader searches by default.

-f, --force

Determines whether to link a runtime on a host whose OpenMP runtime already loads.

-y, --yes

Determines whether to create the resolved link. Without this flag the command reports what it would do and changes nothing.

run

Runs the cindra processing pipeline using the specified configuration file.

The pipeline type (single-recording or multi-recording) is automatically detected from the configuration file. When no step flag is set, every step of the detected pipeline runs in phase order. When –job-id is provided, only the matching job is executed and all step flags are ignored. The combination step merges the per-plane result files with serial input and output.

Usage

cindra run [OPTIONS]

Options

-i, --input-path <input_path>

Required The absolute path to the configuration .yaml file for the executed pipeline.

-bw, --binarize-workers <binarize_workers>

[Single-recording] The number of parallel workers to allocate to the binarization step. When this option is omitted, the step receives its measured default allocation of 4 workers, which is the decode ceiling itself. A larger request is capped at that ceiling, because added decode threads stop shortening the conversion past that point. Setting this to -1 uses every available core, minus the cores reserved for system use.

-rw, --register-workers <register_workers>

[Single-recording] The number of parallel workers to allocate to each plane-registration step. When this option is omitted, the step receives its measured default allocation of 8 workers on the host CPU, or 2 workers when –register-device names a CUDA device. Setting this to -1 uses every available core, minus the cores reserved for system use.

-rd, --register-device <register_device>

[Single-recording] The zero-based index of the CUDA device that registers every plane of this run. When this option is omitted, every plane of the run registers on the host CPU.

-pw, --process-workers <process_workers>

[Single-recording] The number of parallel workers to allocate to each plane-processing step. When this option is omitted, the step receives its measured default allocation of 8 workers. Setting this to -1 uses every available core, minus the cores reserved for system use.

-dw, --discover-workers <discover_workers>

[Multi-recording] The number of parallel workers to allocate to the discovery step. When this option is omitted, the step receives its measured default allocation of 2 workers. Setting this to -1 uses every available core, minus the cores reserved for system use.

-ew, --extract-workers <extract_workers>

[Multi-recording] The number of parallel workers to allocate to each per-recording extraction step. When this option is omitted, the step receives its measured default allocation of 16 workers. Setting this to -1 uses every available core, minus the cores reserved for system use.

-np, --no-progress

Determines whether to suppress the progress bars displayed during long-running tasks. The progress bars are displayed by default.

Default:

False

-id, --job-id <job_id>

The unique hexadecimal identifier for this processing job. If provided, the pipeline type is inferred from the configuration file and only the matching job is executed (remote mode). All step flags are ignored.

-b, --binarize

[Single-recording] Determines whether to resolve the binary files for plane-specific processing (step 1). This step prepares the data for further processing during step 2.

Default:

False

-r, --register

[Single-recording] Determines whether to register the target plane(s) to remove motion and compute the registration quality metrics (step 2). This step must complete for a plane before that plane can be processed.

Default:

False

-p, --process

[Single-recording] Determines whether to process the target plane(s) to discover ROIs and extract their fluorescence (step 3). This step aggregates most data processing logic of the pipeline.

Default:

False

-c, --combine

[Single-recording] Determines whether to combine processed plane data into a uniform dataset (step 4). Note that this step is required to later process the data as part of a multi-recording pipeline.

Default:

False

-tp, --target-plane <target_plane>

[Single-recording] The index of the plane to process when running the REGISTER (2) or PROCESS (3) steps. Setting this to ‘-1’ (default value) processes all available planes sequentially.

-dp, --data-path <data_path>

[Single-recording] The path to the root directory containing the recording’s raw input TIFF files. When provided, this path overrides the matching field in the pipeline’s configuration file.

-s, --output-path <output_path>

[Single-recording] The path to the root directory in which to create the cindra output hierarchy and store the processed data. When provided, this path overrides the matching field in the pipeline’s configuration file. The output_path must be set either in the configuration file or via this flag.

-d, --discover

[Multi-recording] Determines whether to discover ROIs trackable across recordings (step 1). This step discovers the candidates for the fluorescence extraction performed during the second processing step.

Default:

False

-e, --extract

[Multi-recording] Determines whether to extract the fluorescence from ROIs tracked across recordings, identified during the first processing step.

Default:

False

-tr, --target-recording <target_recording>

[Multi-recording] The unique identifier of the recording to process when running the ‘extract’ step. If this argument is not provided, the pipeline processes all available recordings in the dataset.

-rp, --recording-path <recording_paths>

[Multi-recording] The path to the recording processed with the single-recording cindra pipeline to include in the processed multi-recording dataset. Specify this option multiple times to include multiple recordings (at least two required). When provided, these paths override the matching fields in the pipeline’s configuration file.

GUI CLI

cindra-gui

Launches cindra GUI applications for visualizing pipeline outputs.

Usage

cindra-gui [OPTIONS] COMMAND [ARGS]...

mcp

Starts the GUI MCP server for agentic viewer lifecycle management and display state queries.

Usage

cindra-gui mcp [OPTIONS]

Options

-t, --transport <transport>

The transport protocol to use for MCP communication.

Default:

'stdio'

Options:

stdio | sse | streamable-http

registration

Launches the registration quality viewer for inspecting motion correction results.

Usage

cindra-gui registration [OPTIONS]

Options

-r, --recording-path <recording_path>

Required Path to a cindra output directory containing registration results.

roi

Launches the ROI viewer for single-recording pipeline output.

Providing –dataset switches the viewer to the multi-recording tracked-ROI view for the named dataset.

Usage

cindra-gui roi [OPTIONS]

Options

-r, --recording-path <recording_path>

Required Path to a cindra output directory to load on startup.

-d, --dataset <dataset>

Multi-recording dataset name to load. Stays in single-recording mode if not provided.

tracking

Launches the multi-recording tracking quality viewer for inspecting across-recording ROI tracking results.

Usage

cindra-gui tracking [OPTIONS]

Options

-r, --recording-path <recording_path>

Required Path to any recording’s cindra output directory that is part of a multi-recording dataset.

-d, --dataset <dataset>

Multi-recording dataset name to load. Defaults to the first available dataset.