Skip to content

Suite2p

pynapple.io.suite2p

⚠ DEPRECATED: This will be removed in version 1.0.0. Check nwbmatic or neuroconv instead.

Loader for Suite2P https://github.com/MouseLand/suite2p

Suite2P

Bases: BaseLoader

Loader for data processed with Suite2P.

Pynapple will try to look for data in this order :

  1. pynapplenwb/session_name.nwb

  2. suite2p/plane/.npy

Attributes:

Name Type Description
F TsdFrame

Fluorescence traces (timepoints x ROIs) for all planes

Fneu TsdFrame

Neuropil fluorescence traces (timepoints x ROIs) for all planes

spks TsdFrame

Deconvolved traces (timepoints x ROIS) for all planes

plane_info DataFrame

Contains plane identity of each cell

stats dict

dictionnay of statistics from stat.npy for each planes only for the neurons that were classified as cells (Can be smaller when loading from the NWB file)

ops dict

Parameters from Suite2p. (Can be smaller when loading from the NWB file)

iscell ndarray

Cell classification

Source code in pynapple/io/suite2p.py
class Suite2P(BaseLoader):
    """Loader for data processed with Suite2P.

    Pynapple will try to look for data in this order :

    1. pynapplenwb/session_name.nwb

    2. suite2p/plane*/*.npy


    Attributes
    ----------
    F : TsdFrame
        Fluorescence traces (timepoints x ROIs) for all planes
    Fneu : TsdFrame
        Neuropil fluorescence traces (timepoints x ROIs) for all planes
    spks : TsdFrame
        Deconvolved traces (timepoints x ROIS) for all planes
    plane_info : pandas.DataFrame
        Contains plane identity of each cell
    stats : dict
        dictionnay of statistics from stat.npy for each planes only for the neurons that were classified as cells
        (Can be smaller when loading from the NWB file)
    ops : dict
        Parameters from Suite2p. (Can be smaller when loading from the NWB file)
    iscell : numpy.ndarray
        Cell classification
    """

    def __init__(self, path):
        """

        Parameters
        ----------
        path : str
            The path of the session
        """
        self.basename = os.path.basename(path)

        super().__init__(path)

        self.load_suite2p_nwb(path)

    def load_suite2p_nwb(self, path):
        """
        Load suite2p data from NWB

        Parameters
        ----------
        path : str
            Path to the session
        """
        self.nwb_path = os.path.join(path, "pynapplenwb")
        if not os.path.exists(self.nwb_path):
            raise RuntimeError("Path {} does not exist.".format(self.nwb_path))

        self.nwbfilename = [f for f in os.listdir(self.nwb_path) if "nwb" in f][0]
        self.nwbfilepath = os.path.join(self.nwb_path, self.nwbfilename)

        io = NWBHDF5IO(self.nwbfilepath, "r")
        nwbfile = io.read()

        if "ophys" in nwbfile.processing.keys():
            ophys = nwbfile.processing["ophys"]

            #################################################################
            # STATS, OPS and ISCELL
            #################################################################
            dims = nwbfile.acquisition["TwoPhotonSeries"].dimension[:]
            self.ops = {"Ly": dims[0], "Lx": dims[1]}
            self.rate = nwbfile.acquisition[
                "TwoPhotonSeries"
            ].imaging_plane.imaging_rate

            self.stats = {0: {}}
            self.iscell = ophys["ImageSegmentation"]["PlaneSegmentation"][
                "iscell"
            ].data[:]

            info = pd.DataFrame(
                data=self.iscell[:, 0].astype("int"), columns=["iscell"]
            )

            #################################################################
            # ROIS
            #################################################################
            try:
                rois = nwbfile.processing["ophys"]["ImageSegmentation"][
                    "PlaneSegmentation"
                ]["pixel_mask"]
                multiplane = False
            except Exception:
                rois = nwbfile.processing["ophys"]["ImageSegmentation"][
                    "PlaneSegmentation"
                ]["voxel_mask"]
                multiplane = True

            idx = np.where(self.iscell[:, 0])[0]
            info["plane"] = 0

            for n in range(len(rois)):
                roi = pd.DataFrame(rois[n])
                if "z" in roi.columns:
                    pl = roi["z"][0]
                else:
                    pl = 0

                info.loc[n, "plane"] = pl

                if pl not in self.stats.keys():
                    self.stats[pl] = {}

                if n in idx:
                    self.stats[pl][n] = {
                        "xpix": roi["y"].values,
                        "ypix": roi["x"].values,
                        "lam": roi["weight"].values,
                    }

            #################################################################
            # Time Series
            #################################################################
            fields = np.intersect1d(
                ["Fluorescence", "Neuropil", "Deconvolved"],
                list(ophys.fields["data_interfaces"].keys()),
            )

            if len(fields) == 0:
                print(
                    "No " + " or ".join(["Fluorescence", "Neuropil", "Deconvolved"]),
                    "found in nwb {}".format(self.nwbfilepath),
                )
                return False

            keys = ophys[fields[0]].roi_response_series.keys()

            planes = [int(k[-1]) for k in keys if "plane" in k]

            data = {}

            if multiplane:
                keys = ophys[fields[0]].roi_response_series.keys()
                planes = [int(k[-1]) for k in keys if "plane" in k]
            else:
                planes = [0]

            for k, name in zip(
                ["F", "Fneu", "spks"], ["Fluorescence", "Neuropil", "Deconvolved"]
            ):
                tmp = []
                timestamps = []

                for i, n in enumerate(planes):
                    if multiplane:
                        pl = "plane{}".format(n)
                    else:
                        pl = name  # This doesn't make sense

                    tokeep = info["iscell"][info["plane"] == n].values == 1

                    d = np.transpose(ophys[name][pl].data[:][tokeep])

                    if ophys[name][pl].timestamps is not None:
                        t = ophys[name][pl].timestamps[:]
                    else:
                        t = (np.arange(0, len(d)) / self.rate) + ophys[name][
                            pl
                        ].starting_time

                    tmp.append(d)
                    timestamps.append(t)

                data[k] = nap.TsdFrame(t=timestamps[0], d=np.hstack(tmp))

            if "F" in data.keys():
                self.F = data["F"]
            if "Fneu" in data.keys():
                self.Fneu = data["Fneu"]
            if "spks" in data.keys():
                self.spks = data["spks"]

            self.plane_info = pd.DataFrame(
                data=info["plane"][info["iscell"] == 1].values, columns=["plane"]
            )

            io.close()
            return True
        else:
            io.close()
            return False

load_data

load_data(path)

Load NWB data saved with pynapple in the pynapplenwb folder

Parameters:

Name Type Description Default
path str

Path to the session folder

required
Source code in pynapple/io/loader.py
def load_data(self, path):
    """
    Load NWB data saved with pynapple in the pynapplenwb folder

    Parameters
    ----------
    path : str
        Path to the session folder
    """
    self.nwb_path = os.path.join(path, "pynapplenwb")
    if not os.path.exists(self.nwb_path):
        raise RuntimeError("Path {} does not exist.".format(self.nwb_path))
    self.nwbfilename = [f for f in os.listdir(self.nwb_path) if "nwb" in f][0]
    self.nwbfilepath = os.path.join(self.nwb_path, self.nwbfilename)

    io = NWBHDF5IO(self.nwbfilepath, "r+")
    nwbfile = io.read()

    position = {}
    acq_keys = nwbfile.acquisition.keys()
    if "CompassDirection" in acq_keys:
        compass = nwbfile.acquisition["CompassDirection"]
        for k in compass.spatial_series.keys():
            position[k] = pd.Series(
                index=compass.get_spatial_series(k).timestamps[:],
                data=compass.get_spatial_series(k).data[:],
            )
    if "Position" in acq_keys:
        tracking = nwbfile.acquisition["Position"]
        for k in tracking.spatial_series.keys():
            position[k] = pd.Series(
                index=tracking.get_spatial_series(k).timestamps[:],
                data=tracking.get_spatial_series(k).data[:],
            )
    if len(position):
        position = pd.DataFrame.from_dict(position)

        # retrieveing time support position if in epochs
        if "position_time_support" in nwbfile.intervals.keys():
            epochs = nwbfile.intervals["position_time_support"].to_dataframe()
            time_support = nap.IntervalSet(
                start=epochs["start_time"], end=epochs["stop_time"], time_units="s"
            )

        self.position = nap.TsdFrame(
            position, time_units="s", time_support=time_support
        )

    if nwbfile.epochs is not None:
        epochs = nwbfile.epochs.to_dataframe()
        # NWB is dumb and cannot take a single string for labels
        epochs["label"] = [epochs.loc[i, "tags"][0] for i in epochs.index]
        epochs = epochs.drop(labels="tags", axis=1)
        epochs = epochs.rename(columns={"start_time": "start", "stop_time": "end"})
        self.epochs = self._make_epochs(epochs)

        self.time_support = self._join_epochs(epochs, "s")

    io.close()

    return

save_nwb_intervals

save_nwb_intervals(iset, name, description='')

Add epochs to the NWB file (e.g. ripples epochs) See pynwb.epoch.TimeIntervals

Parameters:

Name Type Description Default
iset IntervalSet

The intervalSet to save

required
name str

The name in the nwb file

required
Source code in pynapple/io/loader.py
def save_nwb_intervals(self, iset, name, description=""):
    """
    Add epochs to the NWB file (e.g. ripples epochs)
    See pynwb.epoch.TimeIntervals

    Parameters
    ----------
    iset : IntervalSet
        The intervalSet to save
    name : str
        The name in the nwb file
    """
    io = NWBHDF5IO(self.nwbfilepath, "r+")
    nwbfile = io.read()

    epochs = iset.as_units("s")
    time_intervals = TimeIntervals(name=name, description=description)
    for i in epochs.index:
        time_intervals.add_interval(
            start_time=epochs.loc[i, "start"],
            stop_time=epochs.loc[i, "end"],
            tags=str(i),
        )

    nwbfile.add_time_intervals(time_intervals)
    io.write(nwbfile)
    io.close()

    return

save_nwb_timeseries

save_nwb_timeseries(tsd, name, description='')

Save timestamps in the NWB file (e.g. ripples time) with the time support. See pynwb.base.TimeSeries

Parameters:

Name Type Description Default
tsd TsdFrame

_

required
name str

_

required
description str

_

''
Source code in pynapple/io/loader.py
def save_nwb_timeseries(self, tsd, name, description=""):
    """
    Save timestamps in the NWB file (e.g. ripples time) with the time support.
    See pynwb.base.TimeSeries


    Parameters
    ----------
    tsd : TsdFrame
        _
    name : str
        _
    description : str, optional
        _
    """
    io = NWBHDF5IO(self.nwbfilepath, "r+")
    nwbfile = io.read()

    ts = TimeSeries(
        name=name,
        unit="s",
        data=tsd.values,
        timestamps=tsd.as_units("s").index.values,
    )

    time_support = TimeIntervals(
        name=name + "_timesupport", description="The time support of the object"
    )

    epochs = tsd.time_support.as_units("s")
    for i in epochs.index:
        time_support.add_interval(
            start_time=epochs.loc[i, "start"],
            stop_time=epochs.loc[i, "end"],
            tags=str(i),
        )
    nwbfile.add_time_intervals(time_support)
    nwbfile.add_acquisition(ts)
    io.write(nwbfile)
    io.close()

    return

load_nwb_intervals

load_nwb_intervals(name)

Load epochs from the NWB file (e.g. 'ripples')

Parameters:

Name Type Description Default
name str

The name in the nwb file

required
Source code in pynapple/io/loader.py
def load_nwb_intervals(self, name):
    """
    Load epochs from the NWB file (e.g. 'ripples')

    Parameters
    ----------
    name : str
        The name in the nwb file
    """
    io = NWBHDF5IO(self.nwbfilepath, "r")
    nwbfile = io.read()

    if name in nwbfile.intervals.keys():
        epochs = nwbfile.intervals[name].to_dataframe()
        isets = nap.IntervalSet(
            start=epochs["start_time"], end=epochs["stop_time"], time_units="s"
        )
        io.close()
        return isets
    else:
        io.close()
    return

load_nwb_timeseries

load_nwb_timeseries(name)

Load timestamps in the NWB file (e.g. ripples time)

Parameters:

Name Type Description Default
name str

_

required

Returns:

Type Description
Tsd

_

Source code in pynapple/io/loader.py
def load_nwb_timeseries(self, name):
    """
    Load timestamps in the NWB file (e.g. ripples time)

    Parameters
    ----------
    name : str
        _

    Returns
    -------
    Tsd
        _
    """
    io = NWBHDF5IO(self.nwbfilepath, "r")
    nwbfile = io.read()

    ts = nwbfile.acquisition[name]

    time_support = self.load_nwb_intervals(name + "_timesupport")

    tsd = nap.Tsd(
        t=ts.timestamps[:], d=ts.data[:], time_units="s", time_support=time_support
    )

    io.close()

    return tsd

__init__

__init__(path)

Parameters:

Name Type Description Default
path str

The path of the session

required
Source code in pynapple/io/suite2p.py
def __init__(self, path):
    """

    Parameters
    ----------
    path : str
        The path of the session
    """
    self.basename = os.path.basename(path)

    super().__init__(path)

    self.load_suite2p_nwb(path)

load_suite2p_nwb

load_suite2p_nwb(path)

Load suite2p data from NWB

Parameters:

Name Type Description Default
path str

Path to the session

required
Source code in pynapple/io/suite2p.py
def load_suite2p_nwb(self, path):
    """
    Load suite2p data from NWB

    Parameters
    ----------
    path : str
        Path to the session
    """
    self.nwb_path = os.path.join(path, "pynapplenwb")
    if not os.path.exists(self.nwb_path):
        raise RuntimeError("Path {} does not exist.".format(self.nwb_path))

    self.nwbfilename = [f for f in os.listdir(self.nwb_path) if "nwb" in f][0]
    self.nwbfilepath = os.path.join(self.nwb_path, self.nwbfilename)

    io = NWBHDF5IO(self.nwbfilepath, "r")
    nwbfile = io.read()

    if "ophys" in nwbfile.processing.keys():
        ophys = nwbfile.processing["ophys"]

        #################################################################
        # STATS, OPS and ISCELL
        #################################################################
        dims = nwbfile.acquisition["TwoPhotonSeries"].dimension[:]
        self.ops = {"Ly": dims[0], "Lx": dims[1]}
        self.rate = nwbfile.acquisition[
            "TwoPhotonSeries"
        ].imaging_plane.imaging_rate

        self.stats = {0: {}}
        self.iscell = ophys["ImageSegmentation"]["PlaneSegmentation"][
            "iscell"
        ].data[:]

        info = pd.DataFrame(
            data=self.iscell[:, 0].astype("int"), columns=["iscell"]
        )

        #################################################################
        # ROIS
        #################################################################
        try:
            rois = nwbfile.processing["ophys"]["ImageSegmentation"][
                "PlaneSegmentation"
            ]["pixel_mask"]
            multiplane = False
        except Exception:
            rois = nwbfile.processing["ophys"]["ImageSegmentation"][
                "PlaneSegmentation"
            ]["voxel_mask"]
            multiplane = True

        idx = np.where(self.iscell[:, 0])[0]
        info["plane"] = 0

        for n in range(len(rois)):
            roi = pd.DataFrame(rois[n])
            if "z" in roi.columns:
                pl = roi["z"][0]
            else:
                pl = 0

            info.loc[n, "plane"] = pl

            if pl not in self.stats.keys():
                self.stats[pl] = {}

            if n in idx:
                self.stats[pl][n] = {
                    "xpix": roi["y"].values,
                    "ypix": roi["x"].values,
                    "lam": roi["weight"].values,
                }

        #################################################################
        # Time Series
        #################################################################
        fields = np.intersect1d(
            ["Fluorescence", "Neuropil", "Deconvolved"],
            list(ophys.fields["data_interfaces"].keys()),
        )

        if len(fields) == 0:
            print(
                "No " + " or ".join(["Fluorescence", "Neuropil", "Deconvolved"]),
                "found in nwb {}".format(self.nwbfilepath),
            )
            return False

        keys = ophys[fields[0]].roi_response_series.keys()

        planes = [int(k[-1]) for k in keys if "plane" in k]

        data = {}

        if multiplane:
            keys = ophys[fields[0]].roi_response_series.keys()
            planes = [int(k[-1]) for k in keys if "plane" in k]
        else:
            planes = [0]

        for k, name in zip(
            ["F", "Fneu", "spks"], ["Fluorescence", "Neuropil", "Deconvolved"]
        ):
            tmp = []
            timestamps = []

            for i, n in enumerate(planes):
                if multiplane:
                    pl = "plane{}".format(n)
                else:
                    pl = name  # This doesn't make sense

                tokeep = info["iscell"][info["plane"] == n].values == 1

                d = np.transpose(ophys[name][pl].data[:][tokeep])

                if ophys[name][pl].timestamps is not None:
                    t = ophys[name][pl].timestamps[:]
                else:
                    t = (np.arange(0, len(d)) / self.rate) + ophys[name][
                        pl
                    ].starting_time

                tmp.append(d)
                timestamps.append(t)

            data[k] = nap.TsdFrame(t=timestamps[0], d=np.hstack(tmp))

        if "F" in data.keys():
            self.F = data["F"]
        if "Fneu" in data.keys():
            self.Fneu = data["Fneu"]
        if "spks" in data.keys():
            self.spks = data["spks"]

        self.plane_info = pd.DataFrame(
            data=info["plane"][info["iscell"] == 1].values, columns=["plane"]
        )

        io.close()
        return True
    else:
        io.close()
        return False