Skip to content

Commit

Permalink
refactored init to manually accept args rather than automatically par…
Browse files Browse the repository at this point in the history
…sing from metadata to support old testing file
  • Loading branch information
pauladkisson committed Sep 15, 2023
1 parent be21dd7 commit 4819be2
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,46 @@ def extract_extra_metadata(
return extra_metadata


def parse_metadata(metadata):
"""Parse metadata dictionary to extract relevant information.
Notes
-----
SI.hChannels.channelsActive = '[1;2;...;N]' where N is the number of active channels.
SI.hChannels.channelName = "{'channel_name_1' 'channel_name_2' ... 'channel_name_M'}"
where M is the number of channels (active or not).
"""
sampling_frequency = float(metadata["SI.hRoiManager.scanVolumeRate"])
num_channels = len(metadata["SI.hChannels.channelsActive"].split(";"))
num_planes = int(metadata["SI.hStackManager.numSlices"])
frames_per_slice = int(metadata["SI.hStackManager.framesPerSlice"])
channel_names = metadata["SI.hChannels.channelName"].split("'")[1::2][:num_channels]
metadata_parsed = dict(
sampling_frequency=sampling_frequency,
num_channels=num_channels,
num_planes=num_planes,
frames_per_slice=frames_per_slice,
channel_names=channel_names,
)
return metadata_parsed


class ScanImageTiffImagingExtractor(ImagingExtractor):
"""Specialized extractor for reading TIFF files produced via ScanImage."""

extractor_name = "ScanImageTiffImaging"
is_writable = True
mode = "file"

def __init__(self, file_path: PathType) -> None:
def __init__(
self,
file_path: PathType,
sampling_frequency: float,
num_channels: Optional[int] = 1,
num_planes: Optional[int] = 1,
frames_per_slice: Optional[int] = 1,
channel_names: Optional[list] = None,
) -> None:
"""Create a ScanImageTiffImagingExtractor instance from a TIFF file produced by ScanImage.
The underlying data is stored in a round-robin format collapsed into 3 dimensions (frames, rows, columns).
Expand All @@ -62,24 +94,29 @@ def __init__(self, file_path: PathType) -> None:
----------
file_path : PathType
Path to the TIFF file.
sampling_frequency : float
Sampling frequency of each plane (scanVolumeRate) in Hz.
num_channels : int, optional
Number of active channels that were acquired (default=1).
num_planes : int, optional
Number of depth planes that were acquired (default=1).
frames_per_slice : int, optional
Number of frames per depth plane that were acquired (default=1).
channel_names : list, optional
Names of the channels that were acquired (default=None).
"""
super().__init__()
self.file_path = Path(file_path)
ScanImageTiffReader = _get_scanimage_reader()
extra_metadata = extract_extra_metadata(file_path)
# SI.hChannels.channelsActive = '[1;2;...;N]' where N is the number of active channels
self._num_channels = len(extra_metadata["SI.hChannels.channelsActive"].split(";"))
self._num_planes = int(extra_metadata["SI.hStackManager.numSlices"])
frames_per_slice = int(extra_metadata["SI.hStackManager.framesPerSlice"])
self._sampling_frequency = sampling_frequency
self.metadata = extract_extra_metadata(file_path)
self._num_channels = num_channels
self._num_planes = num_planes
if frames_per_slice != 1:
raise NotImplementedError(
"Extractor cannot handle multiple frames per slice. Please raise an issue to request this feature: "
"https://github.com/catalystneuro/roiextractors/issues "
)
self._sampling_frequency = float(extra_metadata["SI.hRoiManager.scanVolumeRate"])
# SI.hChannels.channelName = "{'channel_name_1' 'channel_name_2' ... 'channel_name_N'}"
# where N is the number of channels (active or not)
self._channel_names = extra_metadata["SI.hChannels.channelName"].split("'")[1::2][: self._num_channels]
self._channel_names = channel_names

valid_suffixes = [".tiff", ".tif", ".TIFF", ".TIF"]
if self.file_path.suffix not in valid_suffixes:
Expand All @@ -88,6 +125,7 @@ def __init__(self, file_path: PathType) -> None:
f"Suffix ({self.file_path.suffix}) is not of type {suffix_string}! "
f"The {self.extractor_name}Extractor may not be appropriate for the file."
)
ScanImageTiffReader = _get_scanimage_reader()
with ScanImageTiffReader(str(self.file_path)) as io:
shape = io.shape() # [frames, rows, columns]
if len(shape) == 3:
Expand Down
30 changes: 26 additions & 4 deletions tests/temp_test_scanimage.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,42 @@
# scratch file to test scanimage tiff extractor
from roiextractors import ScanImageTiffImagingExtractor
from roiextractors.extractors.tiffimagingextractors.scanimagetiffimagingextractor import (
extract_extra_metadata,
parse_metadata,
)


def main():
example_test = "/Users/pauladkisson/Documents/CatalystNeuro/ROIExtractors/ophys_testing_data/imaging_datasets/ScanImage/sample_scanimage_version_3_8.tiff"
example_holo = "/Volumes/T7/CatalystNeuro/NWB/MouseV1/raw-tiffs/2ret/20230119_w57_1_2ret_00001.tif"
example_single = "/Users/pauladkisson/Documents/CatalystNeuro/ROIExtractors/ophys_testing_data/imaging_datasets/ScanImage/scanimage_20220801_single.tif"
example_volume = "/Users/pauladkisson/Documents/CatalystNeuro/ROIExtractors/ophys_testing_data/imaging_datasets/ScanImage/scanimage_20220801_volume.tif"
example_multivolume = "/Users/pauladkisson/Documents/CatalystNeuro/ROIExtractors/ophys_testing_data/imaging_datasets/ScanImage/scanimage_20220801_multivolume.tif"

extractor = ScanImageTiffImagingExtractor(file_path=example_holo)
extractor = ScanImageTiffImagingExtractor(file_path=example_test, sampling_frequency=30.0)
print("Example test file loads!")

metadata = extract_extra_metadata(example_holo)
metadata_parsed = parse_metadata(metadata)
extractor = ScanImageTiffImagingExtractor(file_path=example_holo, **metadata_parsed)
print("Example holographic file loads!")
extractor = ScanImageTiffImagingExtractor(file_path=example_single)

metadata = extract_extra_metadata(example_single)
metadata_parsed = parse_metadata(metadata)
metadata_parsed["frames_per_slice"] = 1 # Multiple frames per slice is not supported yet
extractor = ScanImageTiffImagingExtractor(file_path=example_single, **metadata_parsed)
print("Example single-plane file loads!")
extractor = ScanImageTiffImagingExtractor(file_path=example_volume)

metadata = extract_extra_metadata(example_volume)
metadata_parsed = parse_metadata(metadata)
metadata_parsed["frames_per_slice"] = 1 # Multiple frames per slice is not supported yet
extractor = ScanImageTiffImagingExtractor(file_path=example_volume, **metadata_parsed)
print("Example volume file loads!")
extractor = ScanImageTiffImagingExtractor(file_path=example_multivolume)

metadata = extract_extra_metadata(example_multivolume)
metadata_parsed = parse_metadata(metadata)
metadata_parsed["frames_per_slice"] = 1 # Multiple frames per slice is not supported yet
extractor = ScanImageTiffImagingExtractor(file_path=example_multivolume, **metadata_parsed)
print("Example multivolume file loads!")


Expand Down
2 changes: 1 addition & 1 deletion tests/test_scan_image_tiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class TestScanImageTiffExtractor(TestCase):
def setUpClass(cls):
cls.file_path = OPHYS_DATA_PATH / "imaging_datasets" / "Tif" / "sample_scanimage.tiff"
cls.tmpdir = Path(mkdtemp())
cls.imaging_extractor = ScanImageTiffImagingExtractor(file_path=cls.file_path)
cls.imaging_extractor = ScanImageTiffImagingExtractor(file_path=cls.file_path, sampling_frequency=30.0)
with ScanImageTiffReader(filename=str(cls.imaging_extractor.file_path)) as io:
cls.data = io.data()

Expand Down

0 comments on commit 4819be2

Please sign in to comment.