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.

This dataclass describes the acquisition parameters of the input TIFF files, supporting both single-ROI (standard imaging) and multi-ROI (MROI line-scanning) 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. Use the is_mroi property to determine whether the data uses multi-ROI acquisition.

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, 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.

This class provides a container for the results of combining processed data from multiple imaging planes into a unified dataset. It holds DetectionData (combined images) and ExtractionData (combined ROI statistics, fluorescence traces, and classification results) along with metadata about the combined field of view.

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 = 0

The height of the combined field of view in pixels.

combined_width: int = 0

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.

classmethod load(root_path)

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

After calling this method, detection and extraction arrays can be loaded individually using the load_arrays() or memory_map_arrays() methods on each child (e.g., combined.detection.load_arrays( root_path)).

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 = 0

The number of planes that were combined.

plane_heights: ndarray[tuple[Any, ...], dtype[uint16]]

Per-plane frame heights in pixels.

plane_widths: ndarray[tuple[Any, ...], dtype[uint16]]

Per-plane frame widths in pixels.

plane_x_offsets: ndarray[tuple[Any, ...], dtype[int32]]

Per-plane x-axis displacement from compute_plane_offsets(), used to arrange planes in the combined view.

plane_y_offsets: ndarray[tuple[Any, ...], dtype[int32]]

Per-plane y-axis displacement from compute_plane_offsets(), 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 = None

Channel 2 registered binary file paths, one per plane. None when the recording is single-channel.

sampling_rate: float = 0.0

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.

This method saves all combined detection and extraction arrays to the root cindra directory. Metadata (plane count, dimensions) is saved to combined_metadata.npz.

Parameters:

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

Return type:

None

tau: float = 0.0

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 = 0.0

The aspect ratio of detected ROIs, computed as the ratio of vertical to horizontal diameter.

correlation_map: ndarray[tuple[Any, ...], dtype[float32]] | None = None

The pixel-wise correlation map used to identify regions with correlated activity for ROI detection.

correlation_map_channel_2: ndarray[tuple[Any, ...], dtype[float32]] | None = None

The pixel-wise correlation map for the second imaging channel.

enhanced_mean_image: ndarray[tuple[Any, ...], dtype[float32]] | None = None

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

enhanced_mean_image_channel_2: ndarray[tuple[Any, ...], dtype[float32]] | None = 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[tuple[Any, ...], dtype[float32]] | None = None

The maximum intensity projection across all frames, highlighting active structures.

maximum_projection_channel_2: ndarray[tuple[Any, ...], dtype[float32]] | None = None

The maximum intensity projection across all frames for the second imaging channel.

mean_image: ndarray[tuple[Any, ...], dtype[float32]] | None = None

The temporal mean of all registered frames, providing a static view of the imaging field.

mean_image_channel_2: ndarray[tuple[Any, ...], dtype[float32]] | None = None

The temporal mean of all registered frames for the second imaging channel.

memory_map_arrays(output_path)

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

Uses r+ mode to allow both reading and writing through the memory-mapped arrays. This avoids loading the full array contents into memory, which is useful when reusing previously-generated data (e.g., single-recording outputs consumed by the multi-recording pipeline).

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 = 0

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

roi_diameter_channel_2: int = 0

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 where to create the detection_data/ subdirectory.

Return type:

None

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[tuple[Any, ...], dtype[float32]] | None = None

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

cell_classification_channel_2: ndarray[tuple[Any, ...], dtype[float32]] | None = None

The cell classification results for channel 2.

cell_colocalization: ndarray[tuple[Any, ...], dtype[float32]] | None = None

The colocalization results indicating whether channel 1 ROIs are present in channel 2. Shape is (cells, 2) containing (probability, is_colocalized_boolean).

cell_fluorescence: ndarray[tuple[Any, ...], dtype[float32]] | None = None

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

cell_fluorescence_channel_2: ndarray[tuple[Any, ...], dtype[float32]] | None = None

The cell fluorescence traces for channel 2.

corrected_structural_mean_image: ndarray[tuple[Any, ...], dtype[float32]] | None = None

The bleed-through-corrected mean image for the structural channel, computed during intensity-based colocalization. The structural channel is whichever channel is not functional (channel 1 if only channel 2 is functional, or channel 2 if only channel 1 is functional). 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.

This method loads only ROI statistics and cell classification arrays, which are the extraction data needed during pipeline processing (specifically for multi-recording ROI selection and tracking). Fluorescence traces and colocalization data are not loaded because they are never needed during pipeline execution and consume significant memory. Use load_results() to load all result arrays when needed for analysis or visualization.

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.

This method loads fluorescence traces, classification results, and colocalization data. Classification arrays may already be loaded by load_arrays() (which loads them for multi-recording pipeline use), 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 and are not needed during pipeline execution. Call this method when result data is needed for analysis or visualization.

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.

This method mirrors load_arrays() but uses 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.

This method mirrors load_results() but uses 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 (e.g., single-recording outputs consumed by the multi-recording pipeline).

Parameters:

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

Return type:

None

neuropil_fluorescence: ndarray[tuple[Any, ...], dtype[float32]] | None = None

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

neuropil_fluorescence_channel_2: ndarray[tuple[Any, ...], dtype[float32]] | None = 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 memory_map_arrays() or load_arrays() to re-acquire the data on demand.

Return type:

None

roi_statistics: list[ROIStatistics] | None = None

The list of ROIStatistics instances containing spatial and shape statistics for each detected ROI.

roi_statistics_channel_2: list[ROIStatistics] | None = None

The list of ROIStatistics instances containing spatial and shape statistics for each detected ROI for channel 2 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 where to save the extraction data files.

Return type:

None

spikes: ndarray[tuple[Any, ...], dtype[float32]] | None = None

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

spikes_channel_2: ndarray[tuple[Any, ...], dtype[float32]] | None = None

The deconvolved spike traces for channel 2.

subtracted_fluorescence: ndarray[tuple[Any, ...], dtype[float32]] | None = None

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

subtracted_fluorescence_channel_2: ndarray[tuple[Any, ...], dtype[float32]] | None = 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 = None

The path to the root data directory containing the input TIFF files. The pipeline recursively searches this directory and all subdirectories for .tiff/.tif files to process.

ignored_file_names: tuple[str, ...] = ()

The tuple of file names to ignore when searching for and loading raw data. Any file whose name exactly matches one of the names 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 = 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 = False

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. This allows raw data to be relocated or updated without affecting other pipeline states. When False (default), existing binary files are used if present.

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 = 0

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

frame_height: int = 0

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

frame_width: int = 0

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 = 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 = 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 = None

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

plane_index: int | None = None

The zero-based index identifying this plane’s position in a multi-plane volumetric recording.

registered_binary_path: Path | None = None

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

registered_binary_path_channel_2: Path | None = None

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

sampling_rate: float = 0.0

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 (parallel workers, progress bars), see RuntimeSettings.

custom_classifier_path: Path | None = 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 = True

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 tuple of 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 = False

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 = 0.4

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 = False

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.

This class stores all user-configurable parameters that control how the pipeline processes data. These parameters are immutable during processing - the pipeline reads them but does not modify them.

Notes

This class is based on the reference implementation here: https://github.com/sprustonlab/multi_recording-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:

A MultiRecordingConfiguration instance populated with the loaded data.

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 (parallel workers, progress bars).

save(file_path)

Saves the configuration to a YAML file.

Parameters:

file_path (Path) – The path to the .yaml file where 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 = None

The path to this recording’s cindra single-recording pipeline output directory. This is the resolved cindra root that contains combined_metadata.npz and other single-recording outputs. Used to reload CombinedData on demand by downstream pipeline stages.

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 (e.g., {cindra_directory}/multi_recording/{dataset_name}/). Storing this tuple in every recording enables full dataset hierarchy reconstruction from any single recording’s serialized YAML file.

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 used to name output subdirectories and identify the recording in logs.

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[tuple[Any, ...], dtype[float32]] | None = None

The X-dimension displacement field computed by DiffeomorphicDemonsRegistration. Combined with deform_field_y, these fields can be used to construct a Deformation instance for warping images.

deform_field_y: ndarray[tuple[Any, ...], dtype[float32]] | None = None

The Y-dimension displacement field computed by DiffeomorphicDemonsRegistration. Combined with deform_field_x, these fields can be used to construct a Deformation instance for warping images.

deformed_roi_masks: list[ROIMask] | None = 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 = 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.

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 deformation fields 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_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 r+ mode.

This method mirrors load_arrays() but uses memory mapping for .npy files instead of eager loading. ROIMask .npz files are still 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 use the ROIStatistics variable-length serialization pattern and remain as .npz files saved directly into output_path.

Parameters:

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

Return type:

None

transformed_enhanced_mean_image: ndarray[tuple[Any, ...], dtype[float32]] | None = None

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

transformed_enhanced_mean_image_channel_2: ndarray[tuple[Any, ...], dtype[float32]] | None = None

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

transformed_maximum_projection: ndarray[tuple[Any, ...], dtype[float32]] | None = None

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

transformed_maximum_projection_channel_2: ndarray[tuple[Any, ...], dtype[float32]] | None = None

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

transformed_mean_image: ndarray[tuple[Any, ...], dtype[float32]] | None = None

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

transformed_mean_image_channel_2: ndarray[tuple[Any, ...], dtype[float32]] | None = 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

This class provides a unified interface for multi-recording pipeline functions to access user configuration (immutable) and per-recording runtime data (computed during processing). It replaces the legacy ops dictionary pattern used in the original multi-recording implementation with a type-safe structure.

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.

This method uses self.runtime.output_path as the save location. This directory is recording-specific.

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.

This method saves the immutable configuration to the first recording’s multi_recording directory. It should be called once at the start of processing.

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 fluorescence traces and classification fields.

io: MultiRecordingIOData

The per-recording I/O data including recording ID, recording directory, and dataset name.

classmethod load(output_path)

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

After calling this method, multi-recording arrays can be loaded using the load_arrays() or memory_map_arrays() convenience methods, or individually per-child dataclass. CombinedData must be loaded separately by the caller (e.g., runtime.combined_data = 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.

This is a convenience method that eagerly loads registration, tracking, and extraction arrays. CombinedData (single-recording data) is NOT loaded by this method and must be loaded separately by the caller. Use the individual load_arrays() / memory_map_arrays() methods on each child dataclass for fine-grained control over which arrays are loaded and how.

Return type:

None

memory_map_arrays()

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

This is a convenience method that memory-maps registration, tracking, and extraction arrays. CombinedData (single-recording data) is NOT loaded by this method and must be loaded separately by the caller. Use the individual load_arrays() / memory_map_arrays() methods on each child dataclass for fine-grained control over which arrays are loaded and how.

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 where 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.4', cindra_version='1.0.1')

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 = 0

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

cindra_version: str = '1.0.1'

The cindra library version used for processing this recording.

date_processed: str = ''

The timestamp when this recording’s processing completed.

deconvolution_time: int = 0

The spike deconvolution time for this recording in seconds.

extraction_time: int = 0

The fluorescence extraction time for this recording in seconds.

python_version: str = '3.14.4'

The Python interpreter version used for processing this recording.

registration_time: int = 0

The across-recording diffeomorphic demons registration time in seconds.

total_discovery_time: int = 0

The total discovery phase time in seconds.

total_extraction_time: int = 0

The total extraction phase time for this recording in seconds.

tracking_time: int = 0

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.

This method is identical to load_arrays() because template masks are stored as .npz archives, which do not support memory mapping. It exists for API consistency with sibling dataclasses.

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 where to save the tracking data files.

Return type:

None

template_diameter: int = 0

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 = 0

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 = 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 = 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] = (128, 128)

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 split into sub-regions with these dimensions and the registration is applied to each region independently.

enabled: bool = True

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 = 5.0

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

signal_to_noise_threshold: float = 1.2

The signal-to-noise ratio threshold. The phase correlation peak must be this many times higher than the noise level for the algorithm to accept the block offset and apply it to the output dataset.

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 = 40.0

The width, in pixels, of the tapering region at image edges. Pixel values are gradually reduced to zero within this border region to prevent edge artifacts during FFT-based phase correlation. Larger values provide smoother transitions but reduce the usable image area.

enabled: bool = False

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 = 0.0

The standard deviation, in pixels, for Gaussian smoothing applied before spatial high-pass filtering. 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 = 42

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, process, combine).

class cindra.dataclasses.ROIDetection(enabled=True, preclassification_threshold=0.5, threshold_scaling=2.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 = True

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 = False

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 = True

Determines whether to perform ROI detection and classification.

maximum_binned_frames: int = 5000

The maximum number of time-binned frames used for ROI detection. Temporal binning averages consecutive frames to improve signal-to-noise ratio for detection. Higher values provide better averaging but increase memory usage and processing time. The bin size is computed to produce at most this many binned frames.

maximum_iterations: int = 50

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 = 0.75

The maximum allowed fraction of overlapping pixels between two ROIs. When two ROIs share more than this fraction of pixels, the ROI with lower signal quality is discarded. Lower values enforce stricter separation between detected ROIs.

preclassification_threshold: float = 0.5

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.

spatial_highpass_window: int = 25

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 = 100

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 = 2.0

The scaling factor for the ROI detection threshold. The final threshold is computed as this value multiplied by the spatial scale factor. 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.

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

Lightweight spatial ROI data for pipeline processing.

Stores pixel coordinates, weights, and tracking metadata. Used as the working type throughout the multi-recording pipeline and as the on-disk format for spatial data in both single-recording and multi-recording outputs.

centroid: tuple[int, int]

The median (y, x) pixel position of the ROI, representing its approximate center.

property circle_pixels: tuple[ndarray[tuple[Any, ...], dtype[int32]], ndarray[tuple[Any, ...], dtype[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 a compressed .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[tuple[Any, ...], dtype[bool]] | None = None

The boolean mask indicating which pixels overlap with other ROIs. Transient; not persisted.

pixel_weights: ndarray[tuple[Any, ...], dtype[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[tuple[Any, ...], dtype[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 a compressed .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[tuple[Any, ...], dtype[int32]]

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

y_pixels: ndarray[tuple[Any, ...], dtype[int32]]

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

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).

This dataclass represents the complete set of properties computed for each detected ROI during the detection, extraction, and optional multi-recording processing stages. The fields are organized into required core properties (always present after detection), shape statistics (computed during ROI detection, with defaults for staged construction), optional extraction properties (added during signal extraction), multi-plane/multi-recording properties, and GUI visualization properties.

Notes

This dataclass replaces the legacy dictionary-based stat.npy format. 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 = 0.0

The ratio of ellipse axes, indicating ROI elongation.

compactness: float = 0.0

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

footprint: int = 0

The spatial scale (hop size) used during sparse detection for this ROI.

static load_list(masks_path, stats_path)

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

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

  • stats_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 statistics from the stats file.

mask: ROIMask

The underlying ROIMask containing pixel coordinates, weights, centroid, frame dimensions, and tracking metadata.

neuropil_mask: ndarray[tuple[Any, ...], dtype[int32]] | None = 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 = 0.0

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

pixel_count: int = 0

The total number of pixels in the complete ROI.

plane_index: int = 0

The index of the imaging plane this ROI belongs to. This field is not set during detection. It is populated by the IO layer during multi-plane combination, when ROIs from individual planes are merged into a single list.

static save_list(roi_list, masks_path, stats_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, extraction statistics, and GUI visualization fields are written to stats_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).

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

Return type:

None

skewness: float | None = None

The skewness of the baseline-subtracted fluorescence time series.

solidity: float = 0.0

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

soma_mask: ndarray[tuple[Any, ...], dtype[bool]] | None = None

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

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 intensity projection across all frames, highlighting active structures.

MEAN = 'mean'

The temporal mean of all registered frames, providing a static view of the imaging field.

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, 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 = True

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 = 1.0

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 (yrange, xrange) 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 = 100

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 = 0

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 = False

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.

maximum_offset_fraction: float = 0.1

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 = True

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 = 500

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 = 5

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 = False

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 = 1.15

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 = 0.0

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 = False

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[tuple[Any, ...], dtype[bool]] | None = 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 = False

Indicates whether bidirectional phase correction was applied during registration.

bidirectional_phase_offset: int = 0

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.

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 registration 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 to allow both reading and writing through the memory-mapped arrays. This avoids loading the full array contents into memory, which is useful when reusing previously-generated data (e.g., single-recording outputs consumed by the multi-recording pipeline).

Parameters:

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

Return type:

None

nonrigid_correlations: ndarray[tuple[Any, ...], dtype[float32]] | None = None

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

nonrigid_x_offsets: ndarray[tuple[Any, ...], dtype[float32]] | None = None

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

nonrigid_y_offsets: ndarray[tuple[Any, ...], dtype[float32]] | None = None

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

normalization_maximum: int = 0

The maximum intensity value used for normalizing frames during registration.

normalization_minimum: int = 0

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[tuple[Any, ...], dtype[float32]] | None = None

The mean images from frames at extreme ends of each principal component of the registered recording movie, with shape (2, num_components, height, width). Index 0 contains low-projection means, index 1 contains high-projection means. Used for visualizing registration quality in the GUI.

principal_component_projections: ndarray[tuple[Any, ...], dtype[float32]] | None = None

The projection of each frame onto the principal components of the registered recording movie, with shape (num_frames, num_components). Shows how each frame relates to the computed PCs over time.

principal_component_shift_metrics: ndarray[tuple[Any, ...], dtype[float32]] | None = None

The registration offset metrics computed by aligning PC extreme images of the registered recording movie, with shape (num_components, 3). Column 0 contains mean 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[tuple[Any, ...], dtype[float32]] | None = 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[tuple[Any, ...], dtype[float32]] | None = None

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

rigid_x_offsets: ndarray[tuple[Any, ...], dtype[int32]] | None = None

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

rigid_y_offsets: ndarray[tuple[Any, ...], dtype[int32]] | None = 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 where to create the registration_data/ subdirectory.

Return type:

None

valid_x_range: tuple[int, int] = (0, 0)

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

valid_y_range: tuple[int, int] = (0, 0)

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

This class provides a unified interface for pipeline functions to access user configuration (immutable), acquisition parameters (from input data), and runtime data (computed by pipeline). It replaces the legacy ops dictionary pattern with a type-safe structure.

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.

This method uses self.runtime.io.output_path as the save location. This directory is set during plane initialization and is plane-specific (e.g., plane_0/).

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.

This method derives the root path from self.configuration.file_io.output_path and creates the cindra subdirectory if it does not exist. It should be called once at pipeline initialization to save the static data shared across all planes.

Raises:

ValueError – If output_path is not configured in the configuration.

Return type:

None

class cindra.dataclasses.RuntimeSettings(parallel_workers=20, display_progress_bars=False)

Bases: object

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

This dataclass contains parameters that control execution behavior rather than data processing logic. Both pipelines use these settings to configure parallel processing and progress reporting.

display_progress_bars: bool = False

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.

parallel_workers: int = 20

The number of workers used to parallelize certain processing operations. This worker pool is used by numba when it parallelizes certain computations used during registration and ROI processing. There is generally no benefit from increasing this parameter above 20 cores per each processed recording or plane. On machines with a high number of cores, it is recommended to keep this value between 10 and 20 cores and to instead parallelize processing across recordings and planes. Setting this to -1 or 0 removes worker limits, forcing the pipeline to use all available CPU cores.

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 = False

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 = 500

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.

cell_probability_percentile: int = 50

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 = 0.5

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 = 0.65

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 = True

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

inner_neuropil_border_radius: int = 2

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 = 350

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.

This class stores all user-configurable parameters that control how the pipeline processes data. These parameters are immutable during processing - the pipeline reads them but does not modify them.

Notes

This class is based on the ‘default_ops’ dictionary from 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 input data location, format, and working and output directories.

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:

A SingleRecordingConfiguration instance populated with the loaded data.

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 (parallel workers, progress bars).

save(file_path)

Saves the configuration to a YAML file.

Parameters:

file_path (Path) – The path to the .yaml file where 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.

After calling this method, arrays can be loaded individually per-child dataclass using the load_arrays() or memory_map_arrays() methods on each child (registration, detection, extraction). Alternatively, the convenience load_arrays() / memory_map_arrays() methods on this class load all children at once.

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 all NumPy arrays from .npy files on disk into memory.

This method reads each array file in full and copies it into a contiguous in-memory buffer. Use this when the data will be generated or modified during pipeline processing.

Return type:

None

memory_map_arrays()

Memory-maps all NumPy arrays from .npy files on disk in r+ mode.

This method opens each .npy file as a read-write memory-mapped array, avoiding full materialization in RAM. Use this when reusing previously-generated data that does not need to be copied into memory (e.g., single-recording outputs consumed by the multi-recording pipeline).

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 .npy files.

This method saves all NumPy arrays as separate .npy files in the output directory, then creates a deep copy of the instance with arrays set to None and Path fields converted to strings before writing the YAML file.

Notes

This form of storing the data mitigates the use of pickle serialization in favor of using safer YAML and NumPy serialization.

Parameters:

output_path (Path) – The directory where to save the runtime_data.yaml file and .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 = 'maximin'

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 = 8.0

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 = 10.0

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 = 60.0

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 = True

Determines whether to deconvolve spike activity from the extracted fluorescence traces. When disabled, the pipeline still computes neuropil-corrected fluorescence (F - coefficient * F_neuropil) but skips the deconvolution step that estimates spike timing.

neuropil_coefficient: float = 0.7

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_plane_time=0, date_processed='', python_version='3.14.4', cindra_version='1.0.1')

Bases: object

Stores pipeline timing and version data.

All time durations are stored as integers representing seconds.

binarization_time: int = 0

The TIFF to binary conversion time in seconds.

cindra_version: str = '1.0.1'

cindra version used for processing.

classification_time: int = 0

The ROI classification time in seconds.

classification_time_channel_2: int = 0

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 = 0

The spike deconvolution time in seconds.

deconvolution_time_channel_2: int = 0

The channel 2 spike deconvolution time in seconds.

detection_time: int = 0

The ROI detection time in seconds.

detection_time_channel_2: int = 0

The channel 2 ROI detection time in seconds.

extraction_time: int = 0

The fluorescence extraction time in seconds.

extraction_time_channel_2: int = 0

The channel 2 fluorescence extraction time in seconds.

python_version: str = '3.14.4'

Python version used for processing.

registration_metrics_time: int = 0

The registration metrics computation time in seconds.

registration_time: int = 0

The registration step time in seconds.

total_plane_time: int = 0

The total plane processing time in seconds.

two_step_registration_time: int = 0

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 PipelineType member matching the pipeline_type value stored in the configuration file.

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.

Pipelines

Provides the processing pipeline orchestration logic for single-recording and multi-recording workflows.

class cindra.pipelines.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.pipelines.SingleRecordingJobNames(*values)

Bases: StrEnum

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

BINARIZE = 'binarization'

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

COMBINE = 'combination'

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

PROCESS = 'processing'

The generic name for the processing (step 2) processing job. During runtime, the processed plane is identified by the tracker’s specifier field using the format ‘plane_{plane_index}’.

cindra.pipelines.run_multi_recording_pipeline(configuration_path, job_id=None, *, discover=False, extract=False, target_recording=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.parallel_workers, runtime.display_progress_bars) into the configuration file before invoking this function. The pipeline reads these values from the file at configuration_path and does not accept them as direct parameters.

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.

Raises:
  • FileNotFoundError – If the multi-recording configuration data cannot be loaded from the specified file.

  • ValueError – If recording validation fails, recording_directories is empty, or the specified job_id does not match any available jobs.

Return type:

None

cindra.pipelines.run_single_recording_pipeline(configuration_path, job_id=None, *, binarize=False, process=False, combine=False, target_plane=-1)

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

The caller is responsible for writing all runtime overrides (file_io.data_path, file_io.output_path, runtime.parallel_workers, runtime.display_progress_bars) into the configuration file before invoking this function. The pipeline reads these values from the file at configuration_path and does not accept them as direct parameters.

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).

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

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

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

Raises:
  • FileNotFoundError – If the single-recording configuration data cannot be loaded from the specified file.

  • ValueError – If the recording’s data validation fails or the specified job_id does not match any available jobs.

Return type:

None

Registration

Provides algorithms for correcting within-recording motion and registering multiple recordings to the same reference field of view.

class cindra.registration.Deformation(field_y, field_x)

Bases: object

Represents a 2D image deformation using backward mapping.

A deformation maps pixel locations from a target image back to source locations, enabling image warping through interpolation. The class stores relative displacement fields (deltas) for each dimension.

Notes

Use Deformation.identity() to create identity (no-op) deformations. Use the regular constructor only for creating deformations from explicit displacement field arrays.

Parameters:
  • field_y (ndarray[tuple[Any, ...], dtype[float32]]) – The Y-dimension displacement field array.

  • field_x (ndarray[tuple[Any, ...], dtype[float32]]) – The X-dimension displacement field array.

_field_shape

The shape of the deformation field as (height, width).

_fields

List of displacement field arrays, one per dimension [Y, X].

add(other)

Combines two deformations by element-wise addition of their displacement fields.

Parameters:

other (Deformation) – The deformation to add to this one.

Return type:

Deformation

Returns:

A new Deformation with summed displacement fields.

apply_deformation(data, interpolation=3)

Applies this deformation to warp the input data.

Uses backward mapping to sample the source data at locations defined by the deformation field.

Parameters:
  • data (ndarray[tuple[Any, ...], dtype[float32]]) – The 2D array to deform.

  • interpolation (int, default: 3) – The interpolation order (0=nearest, 1=bilinear, 3=cubic).

Return type:

ndarray[tuple[Any, ...], dtype[float32]]

Returns:

The deformed data array with the same shape as the input.

compose(other)

Combines two deformations by composition (function composition).

Computes the deformation that results from applying self followed by the other. Uses backward composition where self is sampled at the locations defined by the other.

Parameters:

other (Deformation) – The deformation to compose with (applied second).

Return type:

Deformation

Returns:

A new Deformation representing the composed transformation.

copy()

Creates a deep copy of this deformation.

Return type:

Deformation

Returns:

A new Deformation instance with copied field arrays.

crop(origin, crop_size)

Creates a cropped view of the deformation field centered on the specified origin.

This method extracts a local region of the deformation field to reduce memory overhead when applying deformations to small regions such as individual ROI masks. The origin is automatically clamped to ensure the crop stays within valid field bounds. The returned Deformation contains views into the original arrays, not copies.

Parameters:
  • origin (tuple[int, int]) – The top-left corner of the crop region as (y, x) coordinates.

  • crop_size (tuple[int, int]) – The size of the crop region as (height, width).

Return type:

tuple[Deformation, tuple[int, int]]

Returns:

A tuple containing the cropped Deformation instance and the adjusted origin coordinates. The adjusted origin accounts for boundary clamping and can be used to map local coordinates back to global space.

property field_shape: tuple[int, ...]

Returns the shape of the deformation field as (height, width).

get_deformation_locations()

Computes absolute sample locations from the relative displacement fields.

Converts the relative displacement fields (deltas) to absolute pixel coordinates that can be used directly for interpolation.

Return type:

tuple[ndarray[tuple[Any, ...], dtype[float32]], ndarray[tuple[Any, ...], dtype[float32]]]

Returns:

A tuple of (samples_x, samples_y) arrays containing the absolute x and y coordinates.

get_field(dimension)

Returns the displacement field array for the specified dimension.

Parameters:

dimension (int) – The dimension index (0 for Y, 1 for X).

Return type:

ndarray[tuple[Any, ...], dtype[float32]]

Returns:

The displacement field array for that dimension.

classmethod identity(height, width)

Creates an identity (no-op) deformation with the specified dimensions.

An identity deformation represents no transformation, where each pixel maps to itself.

Parameters:
  • height (int) – The height of the deformation field in pixels.

  • width (int) – The width of the deformation field in pixels.

Return type:

Deformation

Returns:

A new identity Deformation instance.

inverse()

Computes the inverse of this deformation.

Uses forward projection (splatting) to approximate the inverse transformation. The result is only valid if the current deformation is diffeomorphic (invertible).

Return type:

Deformation

Returns:

A new Deformation representing the approximate inverse transformation.

property is_identity: bool

Returns whether this deformation represents an identity (no-op) transformation.

property ndim: int

Returns the number of dimensions of the deformation.

regularize(grid_sampling, injective=True, injective_factor=0.9, freeze_edges=True)

Regularizes the deformation using B-spline grid constraints.

Fits the deformation to a B-spline grid representation, which enforces smoothness. Optionally applies injectivity constraints to ensure the deformation remains diffeomorphic (invertible).

Parameters:
  • grid_sampling (float) – The B-spline grid spacing (knot spacing) in pixels.

  • injective (bool, default: True) – Determines whether to apply injectivity constraint to prevent grid folding.

  • injective_factor (float, default: 0.9) – Scaling factor for the injectivity limit (0 < factor <= 1).

  • freeze_edges (bool, default: True) – Determines whether to freeze edges to zero deformation.

Return type:

Deformation | None

Returns:

A new regularized Deformation instance, or None if the grid is too small for the requested constraints.

resize_field(new_height, new_width)

Creates a new Deformation with the field spatially resized without scaling displacement magnitudes.

Parameters:
  • new_height (int) – The target height in pixels.

  • new_width (int) – The target width in pixels.

Return type:

Deformation

Returns:

A new Deformation with resized fields, or self if already the correct size.

scale(factor)

Scales the deformation magnitude by the given factor.

Notes

The result is diffeomorphic only if the original is diffeomorphic and the factor is in range [-1, 1].

Parameters:

factor (float) – The scaling factor to apply to all displacement values.

Return type:

Deformation

Returns:

A new Deformation with scaled displacement fields.

class cindra.registration.DiffeomorphicDemonsRegistration(images, speed_factor=3.0, scale_sampling=30, grid_sampling_factor=1.0, final_scale=1.0, final_grid_sampling=16.0, smooth_scale=True, injective=True, freeze_edges=True, deformation_limit=1.0, noise_factor=1.0)

Bases: object

Provides the diffeomorphic Demons registration pipeline for groupwise alignment of 2D images.

Implements a variant of the Demons algorithm that produces diffeomorphic (smooth, invertible, topology-preserving) deformations using B-spline regularization. Uses backward mapping and groupwise registration to align all images to a common mean space.

Parameters:
  • images (list[ndarray[tuple[Any, ...], dtype[float32]]]) – Two or more 2D images to register. Images are converted to float32 if not already floating point.

  • speed_factor (float, default: 3.0) – The relative force of the deformation transform. This is the most important parameter to tune. For most cases, a value between 1 and 5 is reasonable.

  • scale_sampling (int, default: 30) – The number of iterations per scale level. Values between 20 and 30 are reasonable, but higher values yield better results. Algorithm speed scales linearly with this value.

  • grid_sampling_factor (float, default: 1.0) – Determines how B-spline grid sampling scales with image scale. Lower values allow more deformation at coarser scales. Must be between 0 and 1.

  • final_scale (float, default: 1.0) – The minimum scale (finest resolution) for the scale-space pyramid. Must be >= 0.5.

  • final_grid_sampling (float, default: 16.0) – The B-spline grid spacing at the final (finest) scale level.

  • smooth_scale (bool, default: True) – Determines whether to use smooth scale transitions between pyramid levels.

  • injective (bool, default: True) – Determines whether to enforce injectivity constraint to ensure diffeomorphic (invertible) deformations.

  • freeze_edges (bool, default: True) – Determines whether to freeze deformation values at image edges to prevent boundary artifacts.

  • deformation_limit (float, default: 1.0) – The maximum allowed deformation magnitude per grid cell, relative to grid spacing.

  • noise_factor (float, default: 1.0) – The regularization factor for intensity noise in the Demons force calculation.

_images

The processed images.

_speed_factor

Cached speed_factor parameter.

_scale_sampling

Cached scale_sampling parameter.

_grid_sampling_factor

Cached grid_sampling_factor parameter.

_final_scale

Cached final_scale parameter.

_final_grid_sampling

Cached final_grid_sampling parameter.

_smooth_scale

Cached smooth_scale parameter.

_injective

Cached injective parameter.

_freeze_edges

Cached freeze_edges parameter.

_deformation_limit

Cached deformation_limit parameter.

_noise_factor

Cached noise_factor parameter.

_deformations

Maps image indices to their computed Deformation objects.

_pyramids

Scale-space pyramids for each input image, initialized during registration.

_cache

Internal cache for intermediate computation results.

_interpolation_order

Current interpolation order used during registration (1 or 3).

get_deformation(image_index)

Returns the deformation for the specified image.

The deformation maps the image at the given index to the mean shape (groupwise registration result).

Parameters:

image_index (int) – The index of the image (0-based).

Return type:

Deformation

Returns:

The deformation that aligns the specified image to the common mean space.

register(progress=True)

Performs the multiscale registration process.

Iteratively computes deformations from coarse to fine scales, updating the groupwise alignment at each step.

Parameters:

progress (bool, default: True) – Determines whether to display a progress bar to report the registration progress.

Return type:

None

cindra.registration.project_templates_to_recordings(contexts)

Projects template masks from shared visual space back to each recording’s original coordinate system.

After ROI tracking produces template masks in the shared deformed space, this function applies the inverse deformation to map those masks back to each recording’s native coordinates. This enables fluorescence extraction using the original registered binary data.

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.

Return type:

None

cindra.registration.register_plane(context)

Registers (motion-corrects) all frames for a single imaging plane specified by the input runtime context.

This function is the primary entry point for frame registration. It 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 using the mean of registered frames as the reference.

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.

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.

Return type:

None

cindra.registration.register_recordings(contexts)

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

This is the entry point for multi-recording registration. It orchestrates the full registration workflow including deformation field computation, image transformation, and mask deformation. 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.

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.

Return type:

None

Detection

Provides algorithms for segmenting and describing ROIs from motion-corrected recordings.

cindra.detection.compute_block_smoothing_kernel(x_block_count: int, y_block_count: int) NDArray[np.float32]

Computes a normalized Gaussian kernel matrix for smoothing nonrigid block offsets.

Notes

Creates a kernel that weights neighboring blocks based on their spatial distance, used to enforce smoothness constraints in nonrigid registration. Results are cached since block counts don’t change during a recording.

Parameters:
  • x_block_count (int) – Number of blocks along the x-axis.

  • y_block_count (int) – Number of blocks along the y-axis.

Return type:

ndarray[tuple[Any, ...], dtype[float32]]

Returns:

The row-normalized Gaussian kernel matrix with shape (num_blocks, num_blocks).

cindra.detection.compute_median_pixel_position(y_pixels, x_pixels)

Computes the ROI centroid as the x and y coordinates of the pixel closest to the coordinate-wise median.

Parameters:
  • y_pixels (ndarray[tuple[Any, ...], dtype[int32]]) – The y-coordinates of the ROI’s pixels.

  • x_pixels (ndarray[tuple[Any, ...], dtype[int32]]) – The x-coordinates of the ROI’s pixels.

Return type:

tuple[int, int]

Returns:

The (y, x) coordinates of the pixel closest to the median position.

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 to provide approximately 50% overlap between adjacent blocks.

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[tuple[Any, ...], dtype[int32]]], list[ndarray[tuple[Any, ...], dtype[int32]]], tuple[int, int], tuple[int, int], ndarray[tuple[Any, ...], dtype[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 interpolating block offsets.

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

This function 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 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. Ignored in lightweight mode.

  • 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[tuple[Any, ...], dtype[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 during phase correlation. 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[tuple[Any, ...], dtype[float32]]

Returns:

The multiplicative taper mask with shape (height, width), values in range [0, 1].

cindra.detection.detect_plane_rois(context)

Detects ROIs from registered binary data and updates the runtime context in-place.

Notes

This function 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.

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.

Raises:

ValueError – If no ROIs are detected on either channel.

Return type:

None

cindra.detection.estimate_diameter_from_rois(rois, default_diameter=10)

Estimates the ROI diameter from the pixel counts of a list of ROIs.

This function computes the median pixel count across all ROIs and derives an equivalent circular diameter. This is useful when the original ROI diameter is unavailable or when ROI geometry has been transformed (e.g., after diffeomorphic registration or template mask generation).

Parameters:
  • rois (list[ROIMask]) – The list of ROIMask instances to analyze.

  • default_diameter (int, default: 10) – The fallback diameter to return if the ROI list is empty or all ROIs have zero pixels.

Return type:

int

Returns:

The estimated ROI diameter in pixels, computed as the diameter of a circle with area equal to the median ROI pixel count.

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 rather than square expansion. Each iteration adds one layer of cardinal (up, down, left, right) neighbors to the existing pixel set.

Parameters:
  • y_pixels (ndarray[tuple[Any, ...], dtype[int32]]) – The y-coordinates of the ROI pixels.

  • x_pixels (ndarray[tuple[Any, ...], dtype[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[tuple[Any, ...], dtype[int32]], ndarray[tuple[Any, ...], dtype[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.mean_centered_meshgrid(height, width)

Creates a mean-centered distance meshgrid of the specified dimensions.

Notes

Each coordinate value represents the absolute distance from the center of that axis. Used for creating spatial taper masks and Gaussian frequency filters.

Parameters:
  • height (int) – The height of the frames or images to generate the meshgrid for, in pixels.

  • width (int) – The width of the frames or images to generate the meshgrid for, in pixels.

Return type:

tuple[ndarray[tuple[Any, ...], dtype[float32]], ndarray[tuple[Any, ...], dtype[float32]]]

Returns:

A tuple of (column_distances, row_distances) arrays with shape (height, width), where each value represents the absolute distance from the center along that axis.

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

This function modifies the input contexts in-place, updating each context’s runtime.tracking.template_masks (and template_masks_channel_2 for dual-channel recordings) with the generated template ROIs.

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).

Return type:

None

Extraction

Provides algorithms for extracting the fluorescence from detected ROIs and determining ROI colocalization in multichannel recordings.

cindra.extraction.apply_oasis_deconvolution(cell_fluorescence, batch_size, time_constant, sampling_rate)

Applies the OASIS spike deconvolution algorithm to baseline-corrected ROI fluorescence traces.

Notes

The ROIs are processed in batches to limit peak memory usage, as the OASIS algorithm requires four workspace arrays per batch, each with shape (batch_count, frame_count). Within each batch, the Numba-parallelized kernel deconvolves all ROIs concurrently and writes the inferred spike amplitudes directly into the corresponding slice of the output array.

Parameters:
  • cell_fluorescence (ndarray[tuple[Any, ...], dtype[float32]]) – The baseline-corrected fluorescence traces with shape (roi_count, frame_count).

  • batch_size (int) – The number of ROIs to process per batch.

  • time_constant (float) – The exponential decay time constant of the calcium indicator, in seconds.

  • sampling_rate (float) – The imaging sampling rate for the processed recording plane, in Hz.

Return type:

ndarray[tuple[Any, ...], dtype[float32]]

Returns:

The deconvolved spike traces with shape (roi_count, frame_count).

cindra.extraction.compute_delta_fluorescence(cell_fluorescence, neuropil_fluorescence, neuropil_coefficient, baseline_method, baseline_window, baseline_sigma, baseline_percentile, sampling_rate)

Computes the baseline-corrected delta fluorescence (ΔF) for each ROI from raw fluorescence traces.

Notes

The correction is applied in two stages. First, the scaled neuropil fluorescence is subtracted from each ROI trace to remove contamination from surrounding tissue. Second, a baseline representing the resting fluorescence level is estimated and subtracted, isolating activity-dependent transients suitable for spike deconvolution.

Parameters:
  • cell_fluorescence (ndarray[tuple[Any, ...], dtype[float32]]) – The ROI fluorescence traces with shape (roi_count, frame_count).

  • neuropil_fluorescence (ndarray[tuple[Any, ...], dtype[float32]]) – The surrounding neuropil fluorescence traces with shape (roi_count, frame_count).

  • neuropil_coefficient (float) – The scaling factor applied to neuropil fluorescence before subtracting it from the ROI fluorescence. The corrected signal is computed as F_corrected = F_roi - coefficient * F_neuropil.

  • baseline_method (str) – The method for computing baseline fluorescence to subtract before deconvolution. Must be ‘maximin’, ‘constant’, or ‘constant_percentile’.

  • 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.

  • 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.

  • baseline_percentile (float) – The percentile of trace activity used as baseline for the ‘constant_percentile’ method. Lower values select points near the trace minimum, providing a robust estimate that ignores outliers.

  • sampling_rate (float) – The imaging sampling rate for the processed recording plane, in Hz.

Return type:

ndarray[tuple[Any, ...], dtype[float32]]

Returns:

The neuropil-and-baseline-corrected delta fluorescence traces with shape (roi_count, frame_count).

cindra.extraction.create_masks(roi_statistics, height, width, neuropil, include_overlap, cell_probability_percentile=50, inner_neuropil_border_radius=2, minimum_neuropil_pixels=350)

Creates pixel masks for the ROI and the surrounding neuropil region of each detected ROI.

Notes

The ‘ROI masks’ include both the flattened ROI mask pixel indices and the lambda weights associated with each mask pixel (the lambda weight masks). The neuropil region pixels are selected based on having sub-threshold lambda weights which are assumed to be 0. Therefore, the neuropil masks only include the flattened mask pixel indices.

Parameters:
  • roi_statistics (list[ROIStatistics]) – The ROI statistics for each ROI to be processed.

  • height (int) – The height of the imaged area in pixels.

  • width (int) – The width of the imaged area in pixels.

  • neuropil (bool) – Determines whether to create the masks for the surrounding neuropil region for each ROI.

  • include_overlap (bool) – Determines whether to include overlapping ROI pixels in the created ROI masks.

  • cell_probability_percentile (int, default: 50) – The percentile threshold for classifying pixels as belonging to a cell versus neuropil.

  • inner_neuropil_border_radius (int, default: 2) – The width, in pixels, of the exclusion zone between the cell ROI and its neuropil mask.

  • minimum_neuropil_pixels (int, default: 350) – The minimum number of pixels required for each neuropil mask.

Return type:

tuple[tuple[ndarray[tuple[Any, ...], dtype[int32]], ndarray[tuple[Any, ...], dtype[float32]], ndarray[tuple[Any, ...], dtype[int32]] | None], ...]

Returns:

A tuple of per-ROI mask data. Each element contains the flattened ROI pixel indices, the corresponding normalized lambda weights, and the flattened neuropil pixel indices (or None if neuropil processing is disabled).

cindra.extraction.extract_traces(context)

Extracts fluorescence traces, classifies ROIs, and deconvolves spikes from registered binary data.

Notes

Serves as the unified extraction entry point for both single-recording and multi-recording pipelines. It 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.

Parameters:

context (RuntimeContext | MultiRecordingRuntimeContext) – The runtime context for the recording being processed. Accepts either a single-recording RuntimeContext or a multi-recording MultiRecordingRuntimeContext. Modified in-place to store extraction outputs including fluorescence traces, deconvolved spikes, and colocalization data.

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.

Loads classifier training data from the specified .npz file, fits a logistic regression model, and uses it to predict whether detected ROIs represent real cells or artifacts based on their morphological features.

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 10ms for the default training set.

Parameters:
  • classifier_path (Path) – The path to a classifier .npz file containing training_labels and feature arrays.

  • feature_names (tuple[str, ...] | None, default: None) – The tuple of feature names to use for classification. Only these features will be loaded from the classifier file and used for model fitting. If None, all available features in the classifier file are used.

_classifier_path

The path to the loaded classifier file.

_available_features

The list of feature names used by the classifier.

_training_features

A dictionary mapping feature names to their training value arrays.

_training_labels

The boolean training labels array with shape (n_samples,).

_probability_grid

The grid boundaries computed from 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.

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 list of ROIStatistics instances that store the features of the ROIs to classify.

  • probability_threshold (float, default: 0.5) – The probability threshold above which an ROI is classified as a cell.

Return type:

ndarray[tuple[Any, ...], dtype[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.

Parameters:
  • file_path (Path) – The path where the classifier file will be saved. Should have .npz extension.

  • training_labels (ndarray[tuple[Any, ...], dtype[bool]]) – An array of binary labels (False for artifact, True for cell) with shape (n_samples,).

  • normalized_pixel_count (ndarray[tuple[Any, ...], dtype[float32]]) – An array of normalized pixel count values with shape (n_samples,).

  • compactness (ndarray[tuple[Any, ...], dtype[float32]]) – An array of compactness values with shape (n_samples,).

  • skewness (ndarray[tuple[Any, ...], dtype[float32]]) – An array of 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.

Loads classifier training data from the specified file (or the built-in classifier if no custom path is provided), fits a logistic regression model, and uses it to classify the input ROIs based on their morphological features.

Parameters:
  • roi_statistics (list[ROIStatistics]) – The list of ROIStatistics instances containing the morphological features of the ROIs to classify. 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[tuple[Any, ...], dtype[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.

File I/O

Provides assets for importing, converting, and combining multi-plane imaging data.

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 total number of frames in the file.

  • dtype (str, default: 'int16') – The data type to use for pixel values stored inside the file, specified as a NumPy datatype string (e.g.: “int16”).

  • 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.

This method groups the frames stored inside the file into bins of the size ‘bin_size’. Optionally, the method also rejects bad frames and crops good frames according to the provided x- and y-dimension ranges.

Parameters:
  • bin_size (int) – The size of each bin, in frames.

  • x_range (tuple[int, int] | None, default: None) – A tuple of two elements. The first element is the minimum, and the second element is the maximum x-index to include in the output binned dataset. If set to None, no cropping (x or y) is performed.

  • y_range (tuple[int, int] | None, default: None) – A tuple of two elements. The first element is the minimum, and the second element is the maximum y-index to include in the output binned dataset. If set to None, no cropping (x or y) is performed.

  • bad_frames (ndarray[tuple[Any, ...], dtype[bool]] | None, default: None) – A boolean one-dimensional NumPy array mask that has the same length as the number of frames stored inside the BinaryFile managed by this instance. The array should be True at each bad frame and False at each good frame.

  • reject_threshold (float, default: 0.5) – The minimum fraction of good frames to all frames inside the batch for bad frames to be discarded. If the fraction of good frames in the batch is less than this threshold, then both bad and good frames are kept and binned as part of the batch processing.

Return type:

ndarray[tuple[Any, ...], dtype[float32]]

Returns:

A 3-dimensional NumPy array that stores the binned movie. The first dimension specifies the bin number (an average of bin_size frames), the second specifies the height, and the third specifies the width. Overall, the returned data represents an average of bin_size frames at each consecutive time-point.

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 file, such as a .npz or .npy file, to a cindra binary.

Parameters:
  • source_file_name (Path) – The absolute path to the NumPy .npy or .npz 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.

Return type:

None

property data: ndarray[tuple[Any, ...], dtype[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.

This method selects frames at regular intervals to create a representative subset of the full recording. Unlike temporal binning which averages consecutive frames, subsampling preserves individual frame characteristics while reducing memory requirements.

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. If None, the full width is used.

  • y_range (tuple[int, int] | None, default: None) – A tuple of (start, end) indices for cropping frames along the y-axis. If None, the full height is used.

Return type:

ndarray[tuple[Any, ...], dtype[float32]]

Returns:

A 3D float32 array with shape (num_samples, height, width) containing the subsampled and optionally cropped frames.

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.

This method can be used to convert a subset of the movie stored in the BinaryFile into a .tiff file for further analysis or visualization purposes. Note, 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) – Slice object specifying which frames to export. If None, exports all frames.

  • y_range (slice | None, default: None) – Slice object specifying the y (height) range to crop. If None, uses full height.

  • x_range (slice | None, default: None) – Slice object specifying 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

Creates or opens a collection of cindra binaries (.bin) for reading image data across planes.

This class allows working with multiple imaging planes, each stored inside a separate cindra binary. It provides similar functionality to the BinaryFile class but extends it to handle multiple planes.

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[tuple[Any, ...], dtype[uint16]]) – A NumPy array that stores the heights of each plane (BinaryFile) managed by this instance.

  • plane_widths (ndarray[tuple[Any, ...], dtype[uint16]]) – A NumPy array that stores the widths of each plane (BinaryFile) managed by this instance.

  • plane_y_coordinates (ndarray[tuple[Any, ...], dtype[int32]]) – A NumPy array that stores 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[tuple[Any, ...], dtype[int32]]) – A NumPy array that stores 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, ...]) – A list or tuple that stores the absolute Path objects 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.

Raises:

ValueError – If the frame count is different across two or more opened BinaryFiles.

property byte_number: ndarray[tuple[Any, ...], dtype[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 total number of frames stored in each managed file, which is always the same across all files.

property shape: tuple[int, ndarray[tuple[Any, ...], dtype[uint16]], ndarray[tuple[Any, ...], dtype[uint16]]]

Returns the dimensions of the managed files as (frame_number, plane_heights, plane_widths), where frame_number is the same for all files and the arrays contain per-file plane dimensions.

cindra.io.combine_planes(plane_contexts)

Combines processed data from multiple planes into a unified dataset.

This function combines multi-plane and multi-ROI recording data into a unified dataset, reassembling the original recording from individually processed planes. The combined data is returned as a CombinedData instance containing detection images and extraction data for both channels.

Parameters:

plane_contexts (list[RuntimeContext]) – A list of RuntimeContext instances, one for each plane being combined.

Return type:

CombinedData

Returns:

A CombinedData instance containing the combined detection and extraction data.

Raises:

ValueError – If no valid planes with ROI statistics are found.

cindra.io.compute_plane_offsets(plane_contexts)

Computes the pixel displacement for each plane to arrange them in a combined view.

Handles three scenarios based on the recording type. For standard multi-plane recordings without MROI data, computes a simple grid layout where each plane is tiled sequentially. For MROI recordings with a single z-plane per ROI, uses the MROI offsets directly to preserve spatial relationships between ROIs. For MROI recordings with multiple z-planes per ROI, applies two-level tiling: ROI positions are preserved within each tile, and tiles are offset for each z-plane to prevent overlap.

Notes

The output of this function is used to properly arrange the data from multiple planes in the ‘shared’ recording space, re-assembling the recording from individually processed planes. This is used as part of outputting the cindra-processed data as a ‘combined’ dataset that integrates the data from all available planes.

Parameters:

plane_contexts (list[RuntimeContext]) – A list of RuntimeContext instances, one for each plane being processed.

Return type:

tuple[ndarray[tuple[Any, ...], dtype[int32]], ndarray[tuple[Any, ...], dtype[int32]]]

Returns:

A tuple of two elements. The first element is an array of y-displacement values, and the second element is an array of x-displacement values.

cindra.io.convert_tiffs_to_binary(contexts)

Converts TIFF files to cindra binary format for all planes.

This function performs TIFF to binary conversion using pre-initialized RuntimeContext instances. It discovers TIFF files in the data directory, reads them in batches, and writes the converted frames to binary files. The function handles both standard TIFF data and MROI (Multi-ROI) data automatically based on the acquisition parameters stored in the contexts.

Notes

This function modifies the provided contexts in place, populating frame dimensions, frame counts, and mean images in each context’s runtime data.

Parameters:

contexts (list[RuntimeContext]) – A list of RuntimeContext instances created by resolve_single_recording_contexts(). Each context must have valid configuration, acquisition parameters, and IOData with binary file paths configured.

Raises:
  • ValueError – If contexts is empty or data_path is not configured.

  • FileNotFoundError – If no TIFF files are found in the data directory.

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

This function adapts the multi-recording pipeline to directory structures where the unique recording identifier appears at different levels of the path hierarchy. For example, given paths like /data/day1/recording and /data/day2/recording, the function identifies day1 and day2 as the unique components (not recording, which is shared). 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.

Parameters:

paths (list[Path] | tuple[Path, ...]) – A list or tuple of Path objects.

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.

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.

This function performs the initial setup for multi-recording processing: it 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. This is the correct mode for single-threaded bootstrap (e.g., the prepare_multi_recording_batch_tool invocation).

With persist=False, no files are written. This mode is required for worker-thread entry (REMOTE mode) because the MCP executor dispatches multiple worker threads in the same process: if each worker bootstraps the shared configuration and every recording’s multi_recording_runtime_data.yaml on entry, concurrent open(file, "w") calls on the same paths race at the byte level and produce corrupted YAML that subsequent workers fail to parse. 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; raises FileNotFoundError if any expected runtime data file is missing. Worker entry points (REMOTE mode) must call with persist=False; the prepare_multi_recording_batch_tool owns bootstrap persistence in a single-threaded context.

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, or if recording paths do not contain unique identifying components.

  • ValueError – If target_recording_id does not match any resolved recording identifier.

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. Raw data and pipeline outputs may be nested at arbitrary depths below the root, but the root itself is essential for proper recording identification, display labels, and configuration paths. This function uses extract_unique_components to identify the first path component (from the end) that uniquely distinguishes each path, then truncates each path at that component to strip shared structural subdirectories without assuming a fixed directory hierarchy.

Parameters:

paths (list[Path] | tuple[Path, ...]) – Directories containing discovered marker files (e.g., parents of cindra_parameters.json or combined_metadata.npz). The pipeline resolves sub-paths to raw data and outputs internally; callers should always work with recording roots rather than implementation-specific subdirectories.

Return type:

tuple[Path, ...]

Returns:

A deduplicated tuple of recording root paths, one per unique recording.

Raises:

RuntimeError – If one or more paths do not contain unique components.

cindra.io.resolve_single_recording_contexts(configuration, *, persist=True)

Creates RuntimeContext instances for all imaging planes processed by the target single-recording pipeline.

This function performs the initial setup for single-recording processing: it finds acquisition parameters from the data directory, creates output directories, and initializes RuntimeContext instances for each of the recording’s plains.

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. This is the correct mode for single-threaded bootstrap (e.g., the prepare_single_recording_batch_tool invocation).

With persist=False, no files are written. This mode is required for worker-thread entry (REMOTE mode) because the MCP executor dispatches multiple worker threads in the same process: if each worker bootstraps the shared configuration and every plane’s runtime_data.yaml on entry, concurrent open(file, "w") calls on the same paths race at the byte level and produce corrupted YAML. 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.

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; raises FileNotFoundError if any expected runtime_data.yaml is missing. Worker entry points (REMOTE mode) must call with persist=False; the prepare_single_recording_batch_tool owns bootstrap persistence in a single-threaded context.

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 the acquisition parameters specify more than 2 channels.

  • FileNotFoundError – If neither processed data nor raw data with acquisition parameters is available, or if persist=False and any plane’s runtime_data.yaml does not already exist on disk.

cindra.io.select_recording_rois(contexts)

Selects ROIs from single-recording pipeline outputs that meet multi-recording tracking criteria.

This function 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).

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 using the same selection criteria. The output messages report ROI counts for both channels when channel 2 data is present.

Parameters:

contexts (list[MultiRecordingRuntimeContext]) – The list of MultiRecordingRuntimeContext instances 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

GUI Viewers

Provides the interactive GUIs for visualizing the processing outcomes of the single-recording and multi-recording pipelines.

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) – Optional 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 right-click reclassification.

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) – Optional 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) – Optional 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 group 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 where 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’.

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

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 –job-id is provided, only the matching job is executed and all step flags are ignored.

Usage

cindra run [OPTIONS]

Options

-i, --input-path <input_path>

Required The absolute path to the configuration .yaml file for the executed pipeline.

-w, --workers <workers>

The number of parallel workers to use when executing multiprocessing tasks. For machines with a large number of cores a value between 10 and 20 is optimal. Setting this to a value of -1 or 0 makes the system use all available cores to parallelize multiprocessing tasks.

-pb, --progress-bars

Determines whether to use progress bars during long-running tasks to visualize progress.

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

-p, --process

[Single-recording] Determines whether to process the target plane(s) to remove motion, discover ROIs, and extract their fluorescence (step 2). 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 3). Note, 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 PROCESS step (2). Setting this to ‘-1’ (default value) processes all available planes sequentially.

-dp, --data-path <data_path>

[Single-recording] The path to the root directory that stores the processed recording’s data. 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 where to create the cindra’s 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.

Use this command group to launch the ROI viewer, registration quality viewer, multi-recording tracking viewer, or other GUI tools.

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.

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.