Skip to content

caiman_loader.py

CaImAn

Parse the CaImAn output file

CaImAn results doc

Expecting the following objects
  • dims:
  • dview:
  • estimates: Segmentations and traces
  • mmap_file:
  • params: Input parameters
  • remove_very_bad_comps:
  • skip_refinement:
  • motion_correction: Motion correction shifts and summary images
Example

output_dir = '/subject1/session0/caiman'

loaded_dataset = caiman_loader.CaImAn(output_dir)

Attributes:

Name Type Description
alignment_channel

hard-coded to 0

caiman_fp

file path with all required files: "/motion_correction/reference_image", "/motion_correction/correlation_image", "/motion_correction/average_image", "/motion_correction/max_image", "/estimates/A",

cnmf

loaded caiman object; cm.source_extraction.cnmf.cnmf.load_CNMF(caiman_fp)

creation_time

file creation time

curation_time

file creation time

extract_masks dict

function to extract masks

h5f

caiman_fp read as h5py file

masks

dict result of extract_masks

motion_correction

h5f "motion_correction" property

params

cnmf.params

segmentation_channel

hard-coded to 0

Source code in element_interface/caiman_loader.py
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
class CaImAn:
    """Parse the CaImAn output file

    [CaImAn results doc](https://caiman.readthedocs.io/en/master/Getting_Started.html#result-variables-for-2p-batch-analysis)

    Expecting the following objects:
        - dims:
        - dview:
        - estimates:              Segmentations and traces
        - mmap_file:
        - params:                 Input parameters
        - remove_very_bad_comps:
        - skip_refinement:
        - motion_correction:      Motion correction shifts and summary images

    Example:
        > output_dir = '<imaging_root_data_dir>/subject1/session0/caiman'

        > loaded_dataset = caiman_loader.CaImAn(output_dir)

    Attributes:
        alignment_channel: hard-coded to 0
        caiman_fp: file path with all required files:
            "/motion_correction/reference_image",
            "/motion_correction/correlation_image",
            "/motion_correction/average_image",
            "/motion_correction/max_image",
            "/estimates/A",
        cnmf: loaded caiman object; cm.source_extraction.cnmf.cnmf.load_CNMF(caiman_fp)
        creation_time: file creation time
        curation_time: file creation time
        extract_masks: function to extract masks
        h5f: caiman_fp read as h5py file
        masks: dict result of extract_masks
        motion_correction: h5f "motion_correction" property
        params: cnmf.params
        segmentation_channel: hard-coded to 0
    """

    def __init__(self, caiman_dir: str):
        """Initialize CaImAn loader class

        Args:
            caiman_dir (str): string, absolute file path to CaIman directory

        Raises:
            FileNotFoundError: No CaImAn analysis output file found
            FileNotFoundError: No CaImAn analysis output found, missing required fields
        """
        # ---- Search and verify CaImAn output file exists ----
        caiman_dir = pathlib.Path(caiman_dir)
        if not caiman_dir.exists():
            raise FileNotFoundError("CaImAn directory not found: {}".format(caiman_dir))

        for fp in caiman_dir.glob("*.hdf5"):
            with h5py.File(fp, "r") as h5f:
                if all(s in h5f for s in _required_hdf5_fields):
                    self.caiman_fp = fp
                    break
        else:
            raise FileNotFoundError(
                "No CaImAn analysis output file found at {}"
                " containg all required fields ({})".format(
                    caiman_dir, _required_hdf5_fields
                )
            )

        # ---- Initialize CaImAn's results ----
        self.cnmf = cm.source_extraction.cnmf.cnmf.load_CNMF(self.caiman_fp)
        self.params = self.cnmf.params

        self.h5f = h5py.File(self.caiman_fp, "r")
        self.motion_correction = self.h5f["motion_correction"]
        self._masks = None

        # ---- Metainfo ----
        self.creation_time = datetime.fromtimestamp(os.stat(self.caiman_fp).st_ctime)
        self.curation_time = datetime.fromtimestamp(os.stat(self.caiman_fp).st_ctime)

    @property
    def masks(self):
        if self._masks is None:
            self._masks = self.extract_masks()
        return self._masks

    @property
    def alignment_channel(self):
        return 0  # hard-code to channel index 0

    @property
    def segmentation_channel(self):
        return 0  # hard-code to channel index 0

    def extract_masks(self) -> dict:
        """Extract masks from CaImAn object

        Raises:
            NotImplemented: Not yet implemented for 3D datasets

        Returns:
            dict: Mask attributes - mask_id, mask_npix, mask_weights,
                mask_center_x, mask_center_y, mask_center_z,
                mask_xpix, mask_ypix, mask_zpix, inferred_trace, dff, spikes
        """
        if self.params.motion["is3D"]:
            raise NotImplemented(
                "CaImAn mask extraction for volumetric data not yet implemented"
            )

        comp_contours = cm.utils.visualization.get_contours(
            self.cnmf.estimates.A, self.cnmf.dims
        )

        masks = []
        for comp_idx, comp_contour in enumerate(comp_contours):
            ind, _, weights = scipy.sparse.find(self.cnmf.estimates.A[:, comp_idx])
            if self.cnmf.params.motion["is3D"]:
                xpix, ypix, zpix = np.unravel_index(ind, self.cnmf.dims, order="F")
                center_x, center_y, center_z = comp_contour["CoM"].astype(int)
            else:
                xpix, ypix = np.unravel_index(ind, self.cnmf.dims, order="F")
                center_x, center_y = comp_contour["CoM"].astype(int)
                center_z = 0
                zpix = np.full(len(weights), center_z)

            masks.append(
                {
                    "mask_id": comp_contour["neuron_id"],
                    "mask_npix": len(weights),
                    "mask_weights": weights,
                    "mask_center_x": center_x,
                    "mask_center_y": center_y,
                    "mask_center_z": center_z,
                    "mask_xpix": xpix,
                    "mask_ypix": ypix,
                    "mask_zpix": zpix,
                    "inferred_trace": self.cnmf.estimates.C[comp_idx, :],
                    "dff": self.cnmf.estimates.F_dff[comp_idx, :],
                    "spikes": self.cnmf.estimates.S[comp_idx, :],
                }
            )
        return masks

__init__(caiman_dir)

Initialize CaImAn loader class

Parameters:

Name Type Description Default
caiman_dir str

string, absolute file path to CaIman directory

required

Raises:

Type Description
FileNotFoundError

No CaImAn analysis output file found

FileNotFoundError

No CaImAn analysis output found, missing required fields

Source code in element_interface/caiman_loader.py
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
def __init__(self, caiman_dir: str):
    """Initialize CaImAn loader class

    Args:
        caiman_dir (str): string, absolute file path to CaIman directory

    Raises:
        FileNotFoundError: No CaImAn analysis output file found
        FileNotFoundError: No CaImAn analysis output found, missing required fields
    """
    # ---- Search and verify CaImAn output file exists ----
    caiman_dir = pathlib.Path(caiman_dir)
    if not caiman_dir.exists():
        raise FileNotFoundError("CaImAn directory not found: {}".format(caiman_dir))

    for fp in caiman_dir.glob("*.hdf5"):
        with h5py.File(fp, "r") as h5f:
            if all(s in h5f for s in _required_hdf5_fields):
                self.caiman_fp = fp
                break
    else:
        raise FileNotFoundError(
            "No CaImAn analysis output file found at {}"
            " containg all required fields ({})".format(
                caiman_dir, _required_hdf5_fields
            )
        )

    # ---- Initialize CaImAn's results ----
    self.cnmf = cm.source_extraction.cnmf.cnmf.load_CNMF(self.caiman_fp)
    self.params = self.cnmf.params

    self.h5f = h5py.File(self.caiman_fp, "r")
    self.motion_correction = self.h5f["motion_correction"]
    self._masks = None

    # ---- Metainfo ----
    self.creation_time = datetime.fromtimestamp(os.stat(self.caiman_fp).st_ctime)
    self.curation_time = datetime.fromtimestamp(os.stat(self.caiman_fp).st_ctime)

extract_masks()

Extract masks from CaImAn object

Raises:

Type Description
NotImplemented

Not yet implemented for 3D datasets

Returns:

Name Type Description
dict dict

Mask attributes - mask_id, mask_npix, mask_weights, mask_center_x, mask_center_y, mask_center_z, mask_xpix, mask_ypix, mask_zpix, inferred_trace, dff, spikes

Source code in element_interface/caiman_loader.py
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
def extract_masks(self) -> dict:
    """Extract masks from CaImAn object

    Raises:
        NotImplemented: Not yet implemented for 3D datasets

    Returns:
        dict: Mask attributes - mask_id, mask_npix, mask_weights,
            mask_center_x, mask_center_y, mask_center_z,
            mask_xpix, mask_ypix, mask_zpix, inferred_trace, dff, spikes
    """
    if self.params.motion["is3D"]:
        raise NotImplemented(
            "CaImAn mask extraction for volumetric data not yet implemented"
        )

    comp_contours = cm.utils.visualization.get_contours(
        self.cnmf.estimates.A, self.cnmf.dims
    )

    masks = []
    for comp_idx, comp_contour in enumerate(comp_contours):
        ind, _, weights = scipy.sparse.find(self.cnmf.estimates.A[:, comp_idx])
        if self.cnmf.params.motion["is3D"]:
            xpix, ypix, zpix = np.unravel_index(ind, self.cnmf.dims, order="F")
            center_x, center_y, center_z = comp_contour["CoM"].astype(int)
        else:
            xpix, ypix = np.unravel_index(ind, self.cnmf.dims, order="F")
            center_x, center_y = comp_contour["CoM"].astype(int)
            center_z = 0
            zpix = np.full(len(weights), center_z)

        masks.append(
            {
                "mask_id": comp_contour["neuron_id"],
                "mask_npix": len(weights),
                "mask_weights": weights,
                "mask_center_x": center_x,
                "mask_center_y": center_y,
                "mask_center_z": center_z,
                "mask_xpix": xpix,
                "mask_ypix": ypix,
                "mask_zpix": zpix,
                "inferred_trace": self.cnmf.estimates.C[comp_idx, :],
                "dff": self.cnmf.estimates.F_dff[comp_idx, :],
                "spikes": self.cnmf.estimates.S[comp_idx, :],
            }
        )
    return masks