Skip to content

Commit

Permalink
add inscopix imaging extractor (#276)
Browse files Browse the repository at this point in the history
  • Loading branch information
bendichter authored May 13, 2024
1 parent fdf58b4 commit 22ccdad
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@

### Features

* Add InscopixImagingExtractor [#276](https://github.com/catalystneuro/roiextractors/pull/276)
* Updated testing workflows to include python 3.12, m1/intel macos, and dev tests to check neuroconv: [PR #317](https://github.com/catalystneuro/roiextractors/pull/317)

### Fixes

* Remove unecessary scipy import error handling [#315](https://github.com/catalystneuro/roiextractors/pull/315)

### Testing

* Updated testing workflows to include python 3.12, m1/intel macos, and dev tests to check neuroconv: [PR #317](https://github.com/catalystneuro/roiextractors/pull/317)
* Added daily testing workflow and fixed bug with python 3.12 by upgrading scanimage-tiff-reader version: [PR #321](https://github.com/catalystneuro/roiextractors/pull/321)

# v0.5.8
Expand Down
1 change: 1 addition & 0 deletions requirements-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ tifffile>=2018.10.18
scanimage-tiff-reader==1.4.1.4
neuroconv[video]>=0.4.6 # Uses the VideoCaptureContext class
natsort>=8.3.1
isx>=1.0.4
2 changes: 2 additions & 0 deletions src/roiextractors/extractorlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
MicroManagerTiffImagingExtractor,
)
from .extractors.sbximagingextractor import SbxImagingExtractor
from .extractors.inscopixextractors import InscopixImagingExtractor
from .extractors.memmapextractors import NumpyMemmapImagingExtractor
from .extractors.memmapextractors import MemmapImagingExtractor
from .extractors.miniscopeimagingextractor import MiniscopeImagingExtractor
Expand All @@ -50,6 +51,7 @@
NumpyMemmapImagingExtractor,
MemmapImagingExtractor,
VolumetricImagingExtractor,
InscopixImagingExtractor,
]

segmentation_extractor_full_list = [
Expand Down
3 changes: 3 additions & 0 deletions src/roiextractors/extractors/inscopixextractors/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Defines extactors for Inscopix data."""

from .inscopiximagingextractor import InscopixImagingExtractor
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""Inscopix Imaging Extractor."""

import warnings
from typing import Optional, Tuple

import numpy as np

from ...imagingextractor import ImagingExtractor
from ...extraction_tools import PathType


class InscopixImagingExtractor(ImagingExtractor):
"""Extracts imaging data from Inscopix recordings."""

extractor_name = "InscopixImaging"

def __init__(self, file_path: PathType):
"""
Create an InscopixImagingExtractor instance from a single .isx file.
Parameters
----------
file_path : PathType
Path to the Inscopix file.
"""
import isx

super().__init__(file_path=file_path)
self.movie = isx.Movie.read(str(file_path))

def get_image_size(self) -> Tuple[int, int]:
num_pixels = self.movie.spacing.num_pixels
return num_pixels

def get_num_frames(self) -> int:
return self.movie.timing.num_samples

def get_sampling_frequency(self) -> float:
return 1 / self.movie.timing.period.secs_float

def get_channel_names(self) -> list[str]:
warnings.warn("isx only supports single channel videos.")
return ["channel_0"]

def get_num_channels(self) -> int:
warnings.warn("isx only supports single channel videos.")
return 1

def get_video(
self, start_frame: Optional[int] = None, end_frame: Optional[int] = None, channel: int = 0
) -> np.ndarray:
start_frame = start_frame or 0
end_frame = end_frame or self.get_num_frames()
return np.array([self.movie.get_frame_data(i) for i in range(start_frame, end_frame)])

def get_dtype(self):
return self.movie.data_type
49 changes: 49 additions & 0 deletions tests/test_inscopiximagingextractor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import numpy as np
from numpy import dtype
from numpy.testing import assert_array_equal

from roiextractors import InscopixImagingExtractor

from tests.setup_paths import OPHYS_DATA_PATH


def test_inscopiximagingextractor_movie_128x128x100_part1():
file_path = OPHYS_DATA_PATH / "imaging_datasets" / "inscopix" / "movie_128x128x100_part1.isxd"
extractor = InscopixImagingExtractor(file_path=file_path)

assert extractor.get_num_frames() == 100
assert extractor.get_image_size() == (128, 128)
assert extractor.get_dtype() == dtype("float32")
assert extractor.get_sampling_frequency() == 10.0
assert extractor.get_channel_names() == ["channel_0"]
assert extractor.get_num_channels() == 1
assert extractor.get_video().shape == (100, 128, 128)
assert extractor.get_frames(frame_idxs=[0], channel=0).dtype == extractor.get_dtype()


def test_inscopiximagingextractor_movie_longer_than_3_min():
file_path = OPHYS_DATA_PATH / "imaging_datasets" / "inscopix" / "movie_longer_than_3_min.isxd"
extractor = InscopixImagingExtractor(file_path=file_path)

assert extractor.get_num_frames() == 1248
assert extractor.get_image_size() == (33, 29)
assert extractor.get_dtype() == dtype("uint16")
np.testing.assert_almost_equal(extractor.get_sampling_frequency(), 5.5563890139076415)
assert extractor.get_channel_names() == ["channel_0"]
assert extractor.get_num_channels() == 1
assert extractor.get_video().shape == (1248, 33, 29)
assert extractor.get_frames(frame_idxs=[0], channel=0).dtype == extractor.get_dtype()


def test_inscopiximagingextractor_movie_u8():
file_path = OPHYS_DATA_PATH / "imaging_datasets" / "inscopix" / "movie_u8.isxd"
extractor = InscopixImagingExtractor(file_path=file_path)

assert extractor.get_num_frames() == 5
assert extractor.get_image_size() == (3, 4)
assert extractor.get_dtype() == dtype("uint8")
np.testing.assert_almost_equal(extractor.get_sampling_frequency(), 20.0)
assert extractor.get_channel_names() == ["channel_0"]
assert extractor.get_num_channels() == 1
assert extractor.get_video().shape == (5, 3, 4)
assert extractor.get_frames(frame_idxs=[0], channel=0).dtype == extractor.get_dtype()

0 comments on commit 22ccdad

Please sign in to comment.