diff --git a/src/roiextractors/extractors/tiffimagingextractors/scanimagetiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/scanimagetiffimagingextractor.py index 14ee0a2d..089733c3 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/scanimagetiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/scanimagetiffimagingextractor.py @@ -293,7 +293,7 @@ def __init__( imaging_extractors = [] for plane in range(num_planes): imaging_extractor = ScanImageTiffSinglePlaneImagingExtractor( - file_path=file_path, channel_name=channel_name, plane=plane + file_path=file_path, channel_name=channel_name, plane_name=str(plane) ) imaging_extractors.append(imaging_extractor) super().__init__(imaging_extractors=imaging_extractors) @@ -309,11 +309,50 @@ class ScanImageTiffSinglePlaneImagingExtractor(ImagingExtractor): is_writable = True mode = "file" + @classmethod + def get_channel_names(cls, file_path): + """Get the channel names from a TIFF file produced by ScanImage. + + Parameters + ---------- + file_path : PathType + Path to the TIFF file. + + Returns + ------- + channel_names: list + List of channel names. + """ + metadata = extract_extra_metadata(file_path) + parsed_metadata = parse_metadata(metadata) + channel_names = parsed_metadata["channel_names"] + return channel_names + + @classmethod + def get_plane_names(cls, file_path): + """Get the plane names from a TIFF file produced by ScanImage. + + Parameters + ---------- + file_path : PathType + Path to the TIFF file. + + Returns + ------- + plane_names: list + List of plane names. + """ + metadata = extract_extra_metadata(file_path) + parsed_metadata = parse_metadata(metadata) + num_planes = parsed_metadata["num_planes"] + plane_names = [f"{i}" for i in range(num_planes)] + return plane_names + def __init__( self, file_path: PathType, - channel_name: Optional[str] = None, - plane: int = 0, + channel_name: str, + plane_name: str, ) -> None: """Create a ScanImageTiffImagingExtractor instance from a TIFF file produced by ScanImage. @@ -330,14 +369,13 @@ def __init__( ---------- file_path : PathType Path to the TIFF file. - channel_name : str, optional + channel_name : str Name of the channel for this extractor (default=None). - plane : int, optional - Index of the depth plane for this extractor (default=0). + plane_name : str + Name of the plane for this extractor (default=None). """ super().__init__() self.file_path = Path(file_path) - self.plane = plane self.metadata = extract_extra_metadata(file_path) parsed_metadata = parse_metadata(self.metadata) self._sampling_frequency = parsed_metadata["sampling_frequency"] @@ -345,14 +383,15 @@ def __init__( self._num_planes = parsed_metadata["num_planes"] self._frames_per_slice = parsed_metadata["frames_per_slice"] self._channel_names = parsed_metadata["channel_names"] - if channel_name is None: - channel_name = self._channel_names[0] + self._plane_names = [f"{i}" for i in range(self._num_planes)] self.channel_name = channel_name + self.plane_name = plane_name if channel_name not in self._channel_names: raise ValueError(f"Channel name ({channel_name}) not found in channel names ({self._channel_names}).") self.channel = self._channel_names.index(channel_name) - if plane >= self._num_planes: - raise ValueError(f"Plane index ({plane}) exceeds number of planes ({self._num_planes}).") + if plane_name not in self._plane_names: + raise ValueError(f"Plane name ({plane_name}) not found in plane names ({self._plane_names}).") + self.plane = self._plane_names.index(plane_name) if self._frames_per_slice != 1: warn( "Multiple frames per slice have not been tested and may produce incorrect output. " diff --git a/tests/test_scanimagetiffimagingextractor.py b/tests/test_scanimagetiffimagingextractor.py index 9fb5bf9c..583caa7c 100644 --- a/tests/test_scanimagetiffimagingextractor.py +++ b/tests/test_scanimagetiffimagingextractor.py @@ -34,18 +34,18 @@ def metadata_string_to_dict(metadata_string): @pytest.fixture(scope="module", params=file_paths) def scan_image_tiff_single_plane_imaging_extractor(request): - return ScanImageTiffSinglePlaneImagingExtractor(file_path=request.param) + return ScanImageTiffSinglePlaneImagingExtractor(file_path=request.param, channel_name="Channel 1", plane_name="0") @pytest.fixture( scope="module", params=[ - dict(channel_name="Channel 1", plane=0), - dict(channel_name="Channel 1", plane=1), - dict(channel_name="Channel 1", plane=2), - dict(channel_name="Channel 2", plane=0), - dict(channel_name="Channel 2", plane=1), - dict(channel_name="Channel 2", plane=2), + dict(channel_name="Channel 1", plane_name="0"), + dict(channel_name="Channel 1", plane_name="1"), + dict(channel_name="Channel 1", plane_name="2"), + dict(channel_name="Channel 2", plane_name="0"), + dict(channel_name="Channel 2", plane_name="1"), + dict(channel_name="Channel 2", plane_name="2"), ], ) # Only the adesnik file has many (>2) frames per plane and multiple (2) channels. def scan_image_tiff_single_plane_imaging_extractor_adesnik(request):