From 1371a7002e3424fa68c0351693ed845160d171a9 Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Fri, 21 Apr 2023 18:31:33 +0200 Subject: [PATCH 01/22] add extractor for Micro-Manager OME-TIF format --- src/roiextractors/extractorlist.py | 7 +- .../tiffimagingextractors/__init__.py | 1 + .../micromanagertiffimagingextractor.py | 182 ++++++++++++++++++ 3 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py diff --git a/src/roiextractors/extractorlist.py b/src/roiextractors/extractorlist.py index b5faeea3..747fe2ff 100644 --- a/src/roiextractors/extractorlist.py +++ b/src/roiextractors/extractorlist.py @@ -12,7 +12,11 @@ ) from .extractors.simaextractor import SimaSegmentationExtractor from .extractors.suite2p import Suite2pSegmentationExtractor -from .extractors.tiffimagingextractors import TiffImagingExtractor, ScanImageTiffImagingExtractor +from .extractors.tiffimagingextractors import ( + TiffImagingExtractor, + ScanImageTiffImagingExtractor, + MicroManagerTiffImagingExtractor, +) from .extractors.sbximagingextractor import SbxImagingExtractor from .extractors.memmapextractors import NumpyMemmapImagingExtractor from .extractors.memmapextractors import MemmapImagingExtractor @@ -24,6 +28,7 @@ Hdf5ImagingExtractor, TiffImagingExtractor, ScanImageTiffImagingExtractor, + MicroManagerTiffImagingExtractor, NwbImagingExtractor, SbxImagingExtractor, NumpyMemmapImagingExtractor, diff --git a/src/roiextractors/extractors/tiffimagingextractors/__init__.py b/src/roiextractors/extractors/tiffimagingextractors/__init__.py index 7c863979..81da7b33 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/__init__.py +++ b/src/roiextractors/extractors/tiffimagingextractors/__init__.py @@ -1,2 +1,3 @@ from .tiffimagingextractor import TiffImagingExtractor from .scanimagetiffimagingextractor import ScanImageTiffImagingExtractor +from .micromanagertiffimagingextractor import MicroManagerTiffImagingExtractor diff --git a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py new file mode 100644 index 00000000..8a94e2aa --- /dev/null +++ b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py @@ -0,0 +1,182 @@ +import json +import re +from collections import Counter +from pathlib import Path +from types import ModuleType +from typing import Optional, Tuple + +from xml.etree import ElementTree +import numpy as np + +from ...imagingextractor import ImagingExtractor +from ...extraction_tools import PathType, get_package, DtypeType +from ...multiimagingextractor import MultiImagingExtractor + + +def _get_tiff_reader() -> ModuleType: + return get_package(package_name="tifffile", installation_instructions="pip install tifffile") + + +class MicroManagerTiffImagingExtractor(MultiImagingExtractor): + extractor_name = "MicroManagerTiffImaging" + installed = True + installation_mesg = "" + + def __init__(self, folder_path: PathType): + """ + The imaging extractor for the Micro-Manager TIF image format. + This format consists of multiple TIF image files in multipage OME-TIF format (.ome.tif files) + and 'DisplaySettings' JSON file. + + Parameters + ---------- + folder_path: PathType + The folder path that contains the multipage OME-TIF image files (.ome.tif files) and + the 'DisplaySettings' JSON file. + """ + self.tifffile = _get_tiff_reader() + self.folder_path = Path(folder_path) + + ome_tif_files = list(self.folder_path.glob("*.ome.tif")) + assert ome_tif_files, f"The TIF image files are missing from '{folder_path}'." + + # load the 'DisplaySettings.json' file that contains the sampling frequency of images + settings = self._load_settings_json() + self._sampling_frequency = float(settings["map"]["PlaybackFPS"]["scalar"]) + + # load the first tif + first_tif = self.tifffile.TiffFile(self.folder_path / ome_tif_files[0]) + + # extract metadata from Micro-Manager + self.micromanager_metadata = first_tif.micromanager_metadata + self._width = self.micromanager_metadata["Summary"]["Width"] + self._height = self.micromanager_metadata["Summary"]["Height"] + self._num_channels = self.micromanager_metadata["Summary"]["Channels"] + self._channel_names = self.micromanager_metadata["Summary"]["ChNames"] + + # extact metadata from OME XML + self._ome_metadata = first_tif.ome_metadata + ome_metadata_root = self._get_ome_xml_root() + + schema_name = re.findall("\{(.*)\}", ome_metadata_root.tag)[0] + pixels_element = ome_metadata_root.find(f"{{{schema_name}}}Image/{{{schema_name}}}Pixels") + self._num_frames = int(pixels_element.attrib["SizeT"]) + self._dtype = np.dtype(pixels_element.attrib["Type"]) + + # all the file names are repeated under the TiffData tag + # the number of occurences of each file path corresponds to the number of frames for a given TIF file + tiff_data_elements = pixels_element.findall(f"{{{schema_name}}}TiffData") + file_names = [element[0].attrib["FileName"] for element in tiff_data_elements] + + # count the number of occurrences of each file path and their names + file_counts = Counter(file_names) + # Initialize the private imaging extractors with the number of frames for each file + imaging_extractors = [] + # TODO make sure Counter returns the right order of image files + for file_path, num_frames_per_file in file_counts.items(): + extractor = _SubMicroManagerTiffImagingExtractor(self.folder_path / file_path) + extractor._num_frames = num_frames_per_file + imaging_extractors.append(extractor) + super().__init__(imaging_extractors=imaging_extractors) + + def _load_settings_json(self): + file_name = "DisplaySettings.json" + settings_json_file_path = self.folder_path / file_name + assert settings_json_file_path.exists(), f"'{file_name}' file not found at '{self.folder_path}'." + + with open(settings_json_file_path, "r") as f: + settings = json.load(f) + return settings + + def _get_ome_xml_root(self): + """ + Parses the OME-XML configuration from string format into element tree and returns the root of this tree. + """ + ome_metadata_element = ElementTree.fromstring(self._ome_metadata) + tree = ElementTree.ElementTree(ome_metadata_element) + return tree.getroot() + + def _check_consistency_between_imaging_extractors(self): + """Overrides the parent class method as none of the properties that are checked are from the sub-imaging extractors.""" + return True + + def get_image_size(self) -> Tuple[int, int]: + return self._height, self._width + + def get_sampling_frequency(self) -> float: + return self._sampling_frequency + + def get_num_frames(self) -> int: + return self._num_frames + + def get_channel_names(self) -> list: + return self._channel_names + + def get_num_channels(self) -> int: + return self._num_channels + + def get_dtype(self) -> DtypeType: + return self._dtype + + +class _SubMicroManagerTiffImagingExtractor(ImagingExtractor): + extractor_name = "_SubMicroManagerTiffImaging" + is_writable = True + mode = "file" + + IMAGE_SIZE_ERROR = "The {}Extractor does not support retrieving the image size." + SAMPLING_FREQ_ERROR = "The {}Extractor does not support retrieving the imaging rate." + CHANNEL_NAMES_ERROR = "The {}Extractor does not support retrieving the name of the channels." + DATA_TYPE_ERROR = "The {}Extractor does not support retrieving the data type." + + def __init__(self, file_path: PathType): + """ + The private imaging extractor for the WideField OME-TIF image format. + This extractor is not meant to be used as a standalone ImagingExtractor. + TODO: more explanation + + Parameters + ---------- + file_path : PathType + The path to the TIF image file (.ome.tif) + """ + self.tifffile = _get_tiff_reader() + self.file_path = file_path + + super().__init__() + + self.pages = self.tifffile.TiffFile(self.file_path).pages + self._num_frames = None + + def get_num_frames(self): + return self._num_frames + + def get_num_channels(self) -> int: + return 1 + + def get_image_size(self): + raise NotImplementedError(self.IMAGE_SIZE_ERROR.format(self.extractor_name)) + + def get_sampling_frequency(self): + raise NotImplementedError(self.SAMPLING_FREQ_ERROR.format(self.extractor_name)) + + def get_channel_names(self) -> list: + raise NotImplementedError(self.CHANNEL_NAMES_ERROR.format(self.extractor_name)) + + def get_dtype(self): + raise NotImplementedError(self.DATA_TYPE_ERROR.format(self.extractor_name)) + + def get_video( + self, start_frame: Optional[int] = None, end_frame: Optional[int] = None, channel: int = 0 + ) -> np.ndarray: + if channel != 0: + raise NotImplementedError( + f"The {self.extractor_name}Extractor does not currently support multiple color channels." + ) + if start_frame is not None and end_frame is not None and start_frame == end_frame: + page = self.pages[start_frame] + return page.asarray()[np.newaxis, ...] + + pages = self.pages[start_frame:end_frame] + frames = [page.asarray() for page in pages] + return np.stack(frames) From ed16f473304a0372fd1333bdb56064070ecf0bea Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Fri, 21 Apr 2023 18:32:18 +0200 Subject: [PATCH 02/22] fix image size for the MultiImagingExtractor in get_video --- src/roiextractors/multiimagingextractor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/roiextractors/multiimagingextractor.py b/src/roiextractors/multiimagingextractor.py index 3d0a0f61..df4fa119 100644 --- a/src/roiextractors/multiimagingextractor.py +++ b/src/roiextractors/multiimagingextractor.py @@ -127,7 +127,7 @@ def get_video( start_frame=relative_start, end_frame=relative_stop ) - video_shape = (stop - start,) + self._imaging_extractors[0].get_image_size() + video_shape = (stop - start,) + self.get_image_size() video = np.empty(shape=video_shape, dtype=self.get_dtype()) current_frame = 0 From 81741afd1fa034ff481a0f75a50c4c1e3b664abb Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Wed, 26 Apr 2023 14:13:41 +0200 Subject: [PATCH 03/22] modify get_video based on review --- .../micromanagertiffimagingextractor.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py index 8a94e2aa..502ab93e 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py @@ -1,6 +1,7 @@ import json import re from collections import Counter +from itertools import islice from pathlib import Path from types import ModuleType from typing import Optional, Tuple @@ -76,6 +77,7 @@ def __init__(self, folder_path: PathType): for file_path, num_frames_per_file in file_counts.items(): extractor = _SubMicroManagerTiffImagingExtractor(self.folder_path / file_path) extractor._num_frames = num_frames_per_file + extractor._image_size = (self._height, self._width) imaging_extractors.append(extractor) super().__init__(imaging_extractors=imaging_extractors) @@ -124,7 +126,6 @@ class _SubMicroManagerTiffImagingExtractor(ImagingExtractor): is_writable = True mode = "file" - IMAGE_SIZE_ERROR = "The {}Extractor does not support retrieving the image size." SAMPLING_FREQ_ERROR = "The {}Extractor does not support retrieving the imaging rate." CHANNEL_NAMES_ERROR = "The {}Extractor does not support retrieving the name of the channels." DATA_TYPE_ERROR = "The {}Extractor does not support retrieving the data type." @@ -147,6 +148,7 @@ def __init__(self, file_path: PathType): self.pages = self.tifffile.TiffFile(self.file_path).pages self._num_frames = None + self._image_size = None def get_num_frames(self): return self._num_frames @@ -155,7 +157,7 @@ def get_num_channels(self) -> int: return 1 def get_image_size(self): - raise NotImplementedError(self.IMAGE_SIZE_ERROR.format(self.extractor_name)) + return self._image_size def get_sampling_frequency(self): raise NotImplementedError(self.SAMPLING_FREQ_ERROR.format(self.extractor_name)) @@ -174,9 +176,11 @@ def get_video( f"The {self.extractor_name}Extractor does not currently support multiple color channels." ) if start_frame is not None and end_frame is not None and start_frame == end_frame: - page = self.pages[start_frame] - return page.asarray()[np.newaxis, ...] - - pages = self.pages[start_frame:end_frame] - frames = [page.asarray() for page in pages] - return np.stack(frames) + return self.pages[start_frame].asarray() + + end_frame = end_frame or self.get_num_frames() + start_frame = start_frame or 0 + video = np.zeros(shape=(end_frame - start_frame, *self.get_image_size())) + for page_ind, page in enumerate(islice(self.pages, start_frame, end_frame)): + video[page_ind] = page.asarray() + return video From 006b431c9921ef881e18f89be1160020b21f6a64 Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Wed, 26 Apr 2023 14:41:05 +0200 Subject: [PATCH 04/22] update init --- .../micromanagertiffimagingextractor.py | 58 +++++++++++++------ 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py index 502ab93e..15a479f4 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py @@ -4,7 +4,7 @@ from itertools import islice from pathlib import Path from types import ModuleType -from typing import Optional, Tuple +from typing import Optional, Tuple, Dict from xml.etree import ElementTree import numpy as np @@ -26,8 +26,9 @@ class MicroManagerTiffImagingExtractor(MultiImagingExtractor): def __init__(self, folder_path: PathType): """ The imaging extractor for the Micro-Manager TIF image format. - This format consists of multiple TIF image files in multipage OME-TIF format (.ome.tif files) - and 'DisplaySettings' JSON file. + The image file stacks are saved into multipage TIF files in OME-TIFF format (.ome.tif files), + each of which are up to around 4GB in size. + The 'DisplaySettings' JSON file contains the properties of Micro-Manager. Parameters ---------- @@ -38,24 +39,26 @@ def __init__(self, folder_path: PathType): self.tifffile = _get_tiff_reader() self.folder_path = Path(folder_path) - ome_tif_files = list(self.folder_path.glob("*.ome.tif")) - assert ome_tif_files, f"The TIF image files are missing from '{folder_path}'." + self._ome_tif_files = list(self.folder_path.glob("*.ome.tif")) + assert self._ome_tif_files, f"The TIF image files are missing from '{folder_path}'." # load the 'DisplaySettings.json' file that contains the sampling frequency of images settings = self._load_settings_json() - self._sampling_frequency = float(settings["map"]["PlaybackFPS"]["scalar"]) - - # load the first tif - first_tif = self.tifffile.TiffFile(self.folder_path / ome_tif_files[0]) + self._sampling_frequency = float(settings["PlaybackFPS"]["scalar"]) + first_tif = self.tifffile.TiffFile(self._ome_tif_files[0]) # extract metadata from Micro-Manager self.micromanager_metadata = first_tif.micromanager_metadata self._width = self.micromanager_metadata["Summary"]["Width"] self._height = self.micromanager_metadata["Summary"]["Height"] self._num_channels = self.micromanager_metadata["Summary"]["Channels"] + if self._num_channels > 1: + raise NotImplementedError( + f"The {self.extractor_name}Extractor does not currently support multiple color channels." + ) self._channel_names = self.micromanager_metadata["Summary"]["ChNames"] - # extact metadata from OME XML + # extact metadata from OME-XML specification self._ome_metadata = first_tif.ome_metadata ome_metadata_root = self._get_ome_xml_root() @@ -71,26 +74,30 @@ def __init__(self, folder_path: PathType): # count the number of occurrences of each file path and their names file_counts = Counter(file_names) + self._check_missing_files_in_folder(expected_list_of_files=list(file_counts.keys())) # Initialize the private imaging extractors with the number of frames for each file imaging_extractors = [] - # TODO make sure Counter returns the right order of image files for file_path, num_frames_per_file in file_counts.items(): - extractor = _SubMicroManagerTiffImagingExtractor(self.folder_path / file_path) + extractor = _MicroManagerTiffImagingExtractor(self.folder_path / file_path) extractor._num_frames = num_frames_per_file extractor._image_size = (self._height, self._width) imaging_extractors.append(extractor) super().__init__(imaging_extractors=imaging_extractors) - def _load_settings_json(self): + def _load_settings_json(self) -> Dict[str, Dict[str, str]]: + """ + Loads the 'DisplaySettings' JSON file. + """ file_name = "DisplaySettings.json" settings_json_file_path = self.folder_path / file_name assert settings_json_file_path.exists(), f"'{file_name}' file not found at '{self.folder_path}'." with open(settings_json_file_path, "r") as f: settings = json.load(f) - return settings + assert "map" in settings, "The Micro-Manager property 'map' key is missing." + return settings["map"] - def _get_ome_xml_root(self): + def _get_ome_xml_root(self) -> ElementTree: """ Parses the OME-XML configuration from string format into element tree and returns the root of this tree. """ @@ -98,6 +105,19 @@ def _get_ome_xml_root(self): tree = ElementTree.ElementTree(ome_metadata_element) return tree.getroot() + def _check_missing_files_in_folder(self, expected_list_of_files): + """ + Checks the presence of each TIF file that is expected to be found in the folder. + Raises an error when the files are not found with the name of the missing files. + """ + missing_files = [ + file_name for file_name in expected_list_of_files if + self.folder_path / file_name not in self._ome_tif_files + ] + assert ( + not missing_files + ), f"Some of the TIF image files at '{self.folder_path}' are missing. The list of files that are missing: {missing_files}" + def _check_consistency_between_imaging_extractors(self): """Overrides the parent class method as none of the properties that are checked are from the sub-imaging extractors.""" return True @@ -121,8 +141,8 @@ def get_dtype(self) -> DtypeType: return self._dtype -class _SubMicroManagerTiffImagingExtractor(ImagingExtractor): - extractor_name = "_SubMicroManagerTiffImaging" +class _MicroManagerTiffImagingExtractor(ImagingExtractor): + extractor_name = "_MicroManagerTiffImaging" is_writable = True mode = "file" @@ -132,9 +152,9 @@ class _SubMicroManagerTiffImagingExtractor(ImagingExtractor): def __init__(self, file_path: PathType): """ - The private imaging extractor for the WideField OME-TIF image format. + The private imaging extractor for OME-TIF image format produced by Micro-Manager, + which defines the get_video() method to return the requested frames from a given file. This extractor is not meant to be used as a standalone ImagingExtractor. - TODO: more explanation Parameters ---------- From 57e734322950ae4c94e1a96293c2b5aba528325b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 26 Apr 2023 12:49:28 +0000 Subject: [PATCH 05/22] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../tiffimagingextractors/micromanagertiffimagingextractor.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py index 15a479f4..34fd02e0 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py @@ -111,8 +111,7 @@ def _check_missing_files_in_folder(self, expected_list_of_files): Raises an error when the files are not found with the name of the missing files. """ missing_files = [ - file_name for file_name in expected_list_of_files if - self.folder_path / file_name not in self._ome_tif_files + file_name for file_name in expected_list_of_files if self.folder_path / file_name not in self._ome_tif_files ] assert ( not missing_files From d68eb6ee9737e0f7e04350a6a28d240e1c0a6e7c Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Wed, 26 Apr 2023 15:54:11 +0200 Subject: [PATCH 06/22] add fallback for micromanager metadata --- .../micromanagertiffimagingextractor.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py index 15a479f4..b5863522 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py @@ -1,6 +1,8 @@ import json +import logging import re from collections import Counter +from encodings.utf_8 import decode from itertools import islice from pathlib import Path from types import ModuleType @@ -18,6 +20,13 @@ def _get_tiff_reader() -> ModuleType: return get_package(package_name="tifffile", installation_instructions="pip install tifffile") +def filter_tiff_tag_warnings(record): + return not record.msg.startswith("") + + +logging.getLogger("tifffile.tifffile").addFilter(filter_tiff_tag_warnings) + + class MicroManagerTiffImagingExtractor(MultiImagingExtractor): extractor_name = "MicroManagerTiffImaging" installed = True @@ -48,7 +57,11 @@ def __init__(self, folder_path: PathType): first_tif = self.tifffile.TiffFile(self._ome_tif_files[0]) # extract metadata from Micro-Manager - self.micromanager_metadata = first_tif.micromanager_metadata + micromanager_metadata = first_tif.micromanager_metadata + if micromanager_metadata is None or "Summary" not in micromanager_metadata: + micromanager_metadata = first_tif.pages[0].tags["MicroManagerMetadata"].value + assert "Summary" in micromanager_metadata, "The 'Summary' field is not found in Micro-Manager metadata." + self.micromanager_metadata = micromanager_metadata self._width = self.micromanager_metadata["Summary"]["Width"] self._height = self.micromanager_metadata["Summary"]["Height"] self._num_channels = self.micromanager_metadata["Summary"]["Channels"] From e03b07481786e46c23d9240d541df2edbd69d035 Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Thu, 27 Apr 2023 11:08:31 +0200 Subject: [PATCH 07/22] remove unused import --- .../tiffimagingextractors/micromanagertiffimagingextractor.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py index b5863522..cf20bb85 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py @@ -2,7 +2,6 @@ import logging import re from collections import Counter -from encodings.utf_8 import decode from itertools import islice from pathlib import Path from types import ModuleType From 95cf6e9c175d664d33cb9689acd33a2370839ba3 Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Thu, 27 Apr 2023 22:31:57 +0200 Subject: [PATCH 08/22] update extractor --- .../micromanagertiffimagingextractor.py | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py index 8b129259..24cd27e8 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py @@ -19,17 +19,8 @@ def _get_tiff_reader() -> ModuleType: return get_package(package_name="tifffile", installation_instructions="pip install tifffile") -def filter_tiff_tag_warnings(record): - return not record.msg.startswith("") - - -logging.getLogger("tifffile.tifffile").addFilter(filter_tiff_tag_warnings) - - class MicroManagerTiffImagingExtractor(MultiImagingExtractor): extractor_name = "MicroManagerTiffImaging" - installed = True - installation_mesg = "" def __init__(self, folder_path: PathType): """ @@ -102,7 +93,7 @@ def _load_settings_json(self) -> Dict[str, Dict[str, str]]: """ file_name = "DisplaySettings.json" settings_json_file_path = self.folder_path / file_name - assert settings_json_file_path.exists(), f"'{file_name}' file not found at '{self.folder_path}'." + assert settings_json_file_path.exists(), f"The '{file_name}' file is not found at '{self.folder_path}'." with open(settings_json_file_path, "r") as f: settings = json.load(f) @@ -202,10 +193,6 @@ def get_dtype(self): def get_video( self, start_frame: Optional[int] = None, end_frame: Optional[int] = None, channel: int = 0 ) -> np.ndarray: - if channel != 0: - raise NotImplementedError( - f"The {self.extractor_name}Extractor does not currently support multiple color channels." - ) if start_frame is not None and end_frame is not None and start_frame == end_frame: return self.pages[start_frame].asarray() From 3174161c0381fcc2d09c68240987aa0a8ee2f02e Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Thu, 27 Apr 2023 22:33:47 +0200 Subject: [PATCH 09/22] add first tests --- .../test_micromanagertiffimagingextractor.py | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 tests/test_micromanagertiffimagingextractor.py diff --git a/tests/test_micromanagertiffimagingextractor.py b/tests/test_micromanagertiffimagingextractor.py new file mode 100644 index 00000000..2f959784 --- /dev/null +++ b/tests/test_micromanagertiffimagingextractor.py @@ -0,0 +1,85 @@ +import shutil +import tempfile +from pathlib import Path + +import numpy as np +from hdmf.testing import TestCase +from numpy.testing import assert_array_equal +from tifffile import tifffile + +from roiextractors import MicroManagerTiffImagingExtractor +from tests.setup_paths import OPHYS_DATA_PATH + + +class TestMicroManagerTiffExtractor(TestCase): + @classmethod + def setUpClass(cls): + folder_path = str( + OPHYS_DATA_PATH / "imaging_datasets" / "MicroManagerTif" / "TS12_20220407_20hz_noteasy_1" + ) + cls.folder_path = Path(folder_path) + file_paths = [ + "TS12_20220407_20hz_noteasy_1_MMStack_Default.ome.tif", + "TS12_20220407_20hz_noteasy_1_MMStack_Default_1.ome.tif", + "TS12_20220407_20hz_noteasy_1_MMStack_Default_2.ome.tif", + ] + cls.file_paths = file_paths + extractor = MicroManagerTiffImagingExtractor(folder_path=folder_path) + cls.extractor = extractor + cls.video = cls._get_test_video() + + # temporary directory for testing assertion when xml file is missing + test_dir = tempfile.mkdtemp() + cls.test_dir = test_dir + shutil.copy(Path(folder_path) / file_paths[0], Path(test_dir) / file_paths[0]) + + @classmethod + def _get_test_video(cls): + frames = [] + for file_path in cls.file_paths: + with tifffile.TiffFile(str(cls.folder_path / file_path)) as tif: + frames.append(tif.asarray(key=range(5))) + return np.concatenate(frames, axis=0) + + @classmethod + def tearDownClass(cls): + pass + # remove the temporary directory and its contents + #shutil.rmtree(cls.test_dir) + + def test_tif_files_are_missing_assertion(self): + folder_path = "not a tiff path" + exc_msg = f"The TIF image files are missing from '{folder_path}'." + with self.assertRaisesWith(AssertionError, exc_msg=exc_msg): + MicroManagerTiffImagingExtractor(folder_path=folder_path) + + def test_json_file_is_missing_assertion(self): + folder_path = self.test_dir + exc_msg = f"The 'DisplaySettings.json' file is not found at '{folder_path}'." + with self.assertRaisesWith(AssertionError, exc_msg=exc_msg): + MicroManagerTiffImagingExtractor(folder_path=folder_path) + + def test_micromanagertiffextractor_image_size(self): + self.assertEqual(self.extractor.get_image_size(), (1024, 1024)) + + def test_brukertiffextractor_num_frames(self): + self.assertEqual(self.extractor.get_num_frames(), 15) + + def test_brukertiffextractor_sampling_frequency(self): + self.assertEqual(self.extractor.get_sampling_frequency(), 20.0) + + def test_brukertiffextractor_channel_names(self): + self.assertEqual(self.extractor.get_channel_names(), ["Default"]) + + def test_brukertiffextractor_num_channels(self): + self.assertEqual(self.extractor.get_num_channels(), 1) + + def test_brukertiffextractor_dtype(self): + self.assertEqual(self.extractor.get_dtype(), np.uint16) + + def test_brukertiffextractor_get_video(self): + assert_array_equal(self.extractor.get_video(), self.video) + + def test_brukertiffextractor_get_single_frame(self): + assert_array_equal(self.extractor.get_frames(frame_idxs=[0]), + self.video[0][np.newaxis, ...]) From 74402c9b7e0af5fdc7fdfdc27035ee1274ad13b7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 27 Apr 2023 20:36:02 +0000 Subject: [PATCH 10/22] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_micromanagertiffimagingextractor.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/test_micromanagertiffimagingextractor.py b/tests/test_micromanagertiffimagingextractor.py index 2f959784..d5130f4b 100644 --- a/tests/test_micromanagertiffimagingextractor.py +++ b/tests/test_micromanagertiffimagingextractor.py @@ -14,9 +14,7 @@ class TestMicroManagerTiffExtractor(TestCase): @classmethod def setUpClass(cls): - folder_path = str( - OPHYS_DATA_PATH / "imaging_datasets" / "MicroManagerTif" / "TS12_20220407_20hz_noteasy_1" - ) + folder_path = str(OPHYS_DATA_PATH / "imaging_datasets" / "MicroManagerTif" / "TS12_20220407_20hz_noteasy_1") cls.folder_path = Path(folder_path) file_paths = [ "TS12_20220407_20hz_noteasy_1_MMStack_Default.ome.tif", @@ -45,7 +43,7 @@ def _get_test_video(cls): def tearDownClass(cls): pass # remove the temporary directory and its contents - #shutil.rmtree(cls.test_dir) + # shutil.rmtree(cls.test_dir) def test_tif_files_are_missing_assertion(self): folder_path = "not a tiff path" @@ -81,5 +79,4 @@ def test_brukertiffextractor_get_video(self): assert_array_equal(self.extractor.get_video(), self.video) def test_brukertiffextractor_get_single_frame(self): - assert_array_equal(self.extractor.get_frames(frame_idxs=[0]), - self.video[0][np.newaxis, ...]) + assert_array_equal(self.extractor.get_frames(frame_idxs=[0]), self.video[0][np.newaxis, ...]) From a6143feff9844d0c2e15d8f3713b6307c1ecfa3c Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Fri, 28 Apr 2023 12:06:37 +0200 Subject: [PATCH 11/22] add more tests --- .../micromanagertiffimagingextractor.py | 2 - .../test_micromanagertiffimagingextractor.py | 43 ++++++++++++++----- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py index 24cd27e8..ac5cf317 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py @@ -48,8 +48,6 @@ def __init__(self, folder_path: PathType): first_tif = self.tifffile.TiffFile(self._ome_tif_files[0]) # extract metadata from Micro-Manager micromanager_metadata = first_tif.micromanager_metadata - if micromanager_metadata is None or "Summary" not in micromanager_metadata: - micromanager_metadata = first_tif.pages[0].tags["MicroManagerMetadata"].value assert "Summary" in micromanager_metadata, "The 'Summary' field is not found in Micro-Manager metadata." self.micromanager_metadata = micromanager_metadata self._width = self.micromanager_metadata["Summary"]["Width"] diff --git a/tests/test_micromanagertiffimagingextractor.py b/tests/test_micromanagertiffimagingextractor.py index d5130f4b..06a5a4fa 100644 --- a/tests/test_micromanagertiffimagingextractor.py +++ b/tests/test_micromanagertiffimagingextractor.py @@ -41,9 +41,7 @@ def _get_test_video(cls): @classmethod def tearDownClass(cls): - pass - # remove the temporary directory and its contents - # shutil.rmtree(cls.test_dir) + shutil.rmtree(cls.test_dir) def test_tif_files_are_missing_assertion(self): folder_path = "not a tiff path" @@ -60,23 +58,48 @@ def test_json_file_is_missing_assertion(self): def test_micromanagertiffextractor_image_size(self): self.assertEqual(self.extractor.get_image_size(), (1024, 1024)) - def test_brukertiffextractor_num_frames(self): + def test_micromanagertiffextractor_num_frames(self): self.assertEqual(self.extractor.get_num_frames(), 15) - def test_brukertiffextractor_sampling_frequency(self): + def test_micromanagertiffextractor_sampling_frequency(self): self.assertEqual(self.extractor.get_sampling_frequency(), 20.0) - def test_brukertiffextractor_channel_names(self): + def test_micromanagertiffextractor_channel_names(self): self.assertEqual(self.extractor.get_channel_names(), ["Default"]) - def test_brukertiffextractor_num_channels(self): + def test_micromanagertiffextractor_num_channels(self): self.assertEqual(self.extractor.get_num_channels(), 1) - def test_brukertiffextractor_dtype(self): + def test_micromanagertiffextractor_dtype(self): self.assertEqual(self.extractor.get_dtype(), np.uint16) - def test_brukertiffextractor_get_video(self): + def test_micromanagertiffextractor_get_video(self): assert_array_equal(self.extractor.get_video(), self.video) - def test_brukertiffextractor_get_single_frame(self): + def test_micromanagertiffextractor_get_single_frame(self): assert_array_equal(self.extractor.get_frames(frame_idxs=[0]), self.video[0][np.newaxis, ...]) + + def test_private_micromanagertiffextractor_num_frames(self): + for sub_extractor in self.extractor._imaging_extractors: + self.assertEqual(sub_extractor.get_num_frames(), 5) + + def test_private_micromanagertiffextractor_num_channels(self): + self.assertEqual(self.extractor._imaging_extractors[0].get_num_channels(), 1) + + def test_private_micromanagertiffextractor_sampling_frequency(self): + sub_extractor = self.extractor._imaging_extractors[0] + exc_msg = f"The {sub_extractor.extractor_name}Extractor does not support retrieving the imaging rate." + with self.assertRaisesWith(NotImplementedError, exc_msg=exc_msg): + self.extractor._imaging_extractors[0].get_sampling_frequency() + + def test_private_micromanagertiffextractor_channel_names(self): + sub_extractor = self.extractor._imaging_extractors[0] + exc_msg = f"The {sub_extractor.extractor_name}Extractor does not support retrieving the name of the channels." + with self.assertRaisesWith(NotImplementedError, exc_msg=exc_msg): + self.extractor._imaging_extractors[0].get_channel_names() + + def test_private_micromanagertiffextractor_dtype(self): + sub_extractor = self.extractor._imaging_extractors[0] + exc_msg = f"The {sub_extractor.extractor_name}Extractor does not support retrieving the data type." + with self.assertRaisesWith(NotImplementedError, exc_msg=exc_msg): + self.extractor._imaging_extractors[0].get_dtype() From 197ff5d1d8b9be72a5809aec222b1fb87000e5f8 Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Fri, 28 Apr 2023 15:48:14 +0200 Subject: [PATCH 12/22] add more tests --- tests/test_micromanagertiffimagingextractor.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_micromanagertiffimagingextractor.py b/tests/test_micromanagertiffimagingextractor.py index 06a5a4fa..59e00a5e 100644 --- a/tests/test_micromanagertiffimagingextractor.py +++ b/tests/test_micromanagertiffimagingextractor.py @@ -55,6 +55,12 @@ def test_json_file_is_missing_assertion(self): with self.assertRaisesWith(AssertionError, exc_msg=exc_msg): MicroManagerTiffImagingExtractor(folder_path=folder_path) + def test_list_of_missing_tif_files_assertion(self): + shutil.copy(Path(self.folder_path) / "DisplaySettings.json", Path(self.test_dir) / "DisplaySettings.json") + exc_msg = f"Some of the TIF image files at '{self.test_dir}' are missing. The list of files that are missing: {self.file_paths[1:]}" + with self.assertRaisesWith(AssertionError, exc_msg=exc_msg): + MicroManagerTiffImagingExtractor(folder_path=self.test_dir) + def test_micromanagertiffextractor_image_size(self): self.assertEqual(self.extractor.get_image_size(), (1024, 1024)) From 2e0fe6b9cc49fc13e76f5764c5fb108a64e0907f Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Fri, 28 Apr 2023 17:56:10 +0200 Subject: [PATCH 13/22] try fix permission error for windows --- .../test_micromanagertiffimagingextractor.py | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tests/test_micromanagertiffimagingextractor.py b/tests/test_micromanagertiffimagingextractor.py index 59e00a5e..00f38919 100644 --- a/tests/test_micromanagertiffimagingextractor.py +++ b/tests/test_micromanagertiffimagingextractor.py @@ -28,9 +28,15 @@ def setUpClass(cls): # temporary directory for testing assertion when xml file is missing test_dir = tempfile.mkdtemp() - cls.test_dir = test_dir + cls.test_dir_1 = test_dir shutil.copy(Path(folder_path) / file_paths[0], Path(test_dir) / file_paths[0]) + # temporary directory for testing when some of the files are missing + test_dir = tempfile.mkdtemp() + cls.test_dir_2 = test_dir + shutil.copy(Path(folder_path) / file_paths[0], Path(test_dir) / file_paths[0]) + shutil.copy(Path(folder_path) / "DisplaySettings.json", Path(test_dir) / "DisplaySettings.json") + @classmethod def _get_test_video(cls): frames = [] @@ -41,7 +47,8 @@ def _get_test_video(cls): @classmethod def tearDownClass(cls): - shutil.rmtree(cls.test_dir) + shutil.rmtree(cls.test_dir_1) + shutil.rmtree(cls.test_dir_2) def test_tif_files_are_missing_assertion(self): folder_path = "not a tiff path" @@ -50,16 +57,14 @@ def test_tif_files_are_missing_assertion(self): MicroManagerTiffImagingExtractor(folder_path=folder_path) def test_json_file_is_missing_assertion(self): - folder_path = self.test_dir - exc_msg = f"The 'DisplaySettings.json' file is not found at '{folder_path}'." + exc_msg = f"The 'DisplaySettings.json' file is not found at '{self.test_dir_1}'." with self.assertRaisesWith(AssertionError, exc_msg=exc_msg): - MicroManagerTiffImagingExtractor(folder_path=folder_path) + MicroManagerTiffImagingExtractor(folder_path=self.test_dir_1) def test_list_of_missing_tif_files_assertion(self): - shutil.copy(Path(self.folder_path) / "DisplaySettings.json", Path(self.test_dir) / "DisplaySettings.json") - exc_msg = f"Some of the TIF image files at '{self.test_dir}' are missing. The list of files that are missing: {self.file_paths[1:]}" + exc_msg = f"Some of the TIF image files at '{self.test_dir_2}' are missing. The list of files that are missing: {self.file_paths[1:]}" with self.assertRaisesWith(AssertionError, exc_msg=exc_msg): - MicroManagerTiffImagingExtractor(folder_path=self.test_dir) + MicroManagerTiffImagingExtractor(folder_path=self.test_dir_2) def test_micromanagertiffextractor_image_size(self): self.assertEqual(self.extractor.get_image_size(), (1024, 1024)) From 5cbf1a15d612e407ee4d0266ab7f569d90db255f Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Fri, 28 Apr 2023 18:03:45 +0200 Subject: [PATCH 14/22] Revert "try fix permission error for windows" This reverts commit 2e0fe6b9cc49fc13e76f5764c5fb108a64e0907f. --- .../test_micromanagertiffimagingextractor.py | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/tests/test_micromanagertiffimagingextractor.py b/tests/test_micromanagertiffimagingextractor.py index 00f38919..59e00a5e 100644 --- a/tests/test_micromanagertiffimagingextractor.py +++ b/tests/test_micromanagertiffimagingextractor.py @@ -28,15 +28,9 @@ def setUpClass(cls): # temporary directory for testing assertion when xml file is missing test_dir = tempfile.mkdtemp() - cls.test_dir_1 = test_dir + cls.test_dir = test_dir shutil.copy(Path(folder_path) / file_paths[0], Path(test_dir) / file_paths[0]) - # temporary directory for testing when some of the files are missing - test_dir = tempfile.mkdtemp() - cls.test_dir_2 = test_dir - shutil.copy(Path(folder_path) / file_paths[0], Path(test_dir) / file_paths[0]) - shutil.copy(Path(folder_path) / "DisplaySettings.json", Path(test_dir) / "DisplaySettings.json") - @classmethod def _get_test_video(cls): frames = [] @@ -47,8 +41,7 @@ def _get_test_video(cls): @classmethod def tearDownClass(cls): - shutil.rmtree(cls.test_dir_1) - shutil.rmtree(cls.test_dir_2) + shutil.rmtree(cls.test_dir) def test_tif_files_are_missing_assertion(self): folder_path = "not a tiff path" @@ -57,14 +50,16 @@ def test_tif_files_are_missing_assertion(self): MicroManagerTiffImagingExtractor(folder_path=folder_path) def test_json_file_is_missing_assertion(self): - exc_msg = f"The 'DisplaySettings.json' file is not found at '{self.test_dir_1}'." + folder_path = self.test_dir + exc_msg = f"The 'DisplaySettings.json' file is not found at '{folder_path}'." with self.assertRaisesWith(AssertionError, exc_msg=exc_msg): - MicroManagerTiffImagingExtractor(folder_path=self.test_dir_1) + MicroManagerTiffImagingExtractor(folder_path=folder_path) def test_list_of_missing_tif_files_assertion(self): - exc_msg = f"Some of the TIF image files at '{self.test_dir_2}' are missing. The list of files that are missing: {self.file_paths[1:]}" + shutil.copy(Path(self.folder_path) / "DisplaySettings.json", Path(self.test_dir) / "DisplaySettings.json") + exc_msg = f"Some of the TIF image files at '{self.test_dir}' are missing. The list of files that are missing: {self.file_paths[1:]}" with self.assertRaisesWith(AssertionError, exc_msg=exc_msg): - MicroManagerTiffImagingExtractor(folder_path=self.test_dir_2) + MicroManagerTiffImagingExtractor(folder_path=self.test_dir) def test_micromanagertiffextractor_image_size(self): self.assertEqual(self.extractor.get_image_size(), (1024, 1024)) From ea285faecc6e3b71ce827b768c6c5a0df240812f Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Tue, 2 May 2023 11:27:01 +0200 Subject: [PATCH 15/22] try fix permission error for windows --- tests/test_micromanagertiffimagingextractor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_micromanagertiffimagingextractor.py b/tests/test_micromanagertiffimagingextractor.py index 59e00a5e..798017a9 100644 --- a/tests/test_micromanagertiffimagingextractor.py +++ b/tests/test_micromanagertiffimagingextractor.py @@ -41,6 +41,7 @@ def _get_test_video(cls): @classmethod def tearDownClass(cls): + Path(cls.folder_path / cls.file_paths[0]).unlink() shutil.rmtree(cls.test_dir) def test_tif_files_are_missing_assertion(self): From 8d101ec655509a1c2c896cbd6b3219126627a59f Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Tue, 2 May 2023 11:36:17 +0200 Subject: [PATCH 16/22] add filter for tiff tag warning --- .../micromanagertiffimagingextractor.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py index ac5cf317..7ab1db11 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/micromanagertiffimagingextractor.py @@ -15,6 +15,13 @@ from ...multiimagingextractor import MultiImagingExtractor +def filter_tiff_tag_warnings(record): + return not record.msg.startswith("") + + +logging.getLogger("tifffile.tifffile").addFilter(filter_tiff_tag_warnings) + + def _get_tiff_reader() -> ModuleType: return get_package(package_name="tifffile", installation_instructions="pip install tifffile") From b6020641d9afff3032c7d4fd53e3ff2c9fd2dd2e Mon Sep 17 00:00:00 2001 From: Cody Baker <51133164+CodyCBakerPhD@users.noreply.github.com> Date: Tue, 2 May 2023 10:30:30 -0400 Subject: [PATCH 17/22] Apply suggestions from code review --- tests/test_micromanagertiffimagingextractor.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/test_micromanagertiffimagingextractor.py b/tests/test_micromanagertiffimagingextractor.py index 798017a9..8ec8261d 100644 --- a/tests/test_micromanagertiffimagingextractor.py +++ b/tests/test_micromanagertiffimagingextractor.py @@ -1,6 +1,6 @@ import shutil import tempfile -from pathlib import Path +from warnings import warn import numpy as np from hdmf.testing import TestCase @@ -41,8 +41,11 @@ def _get_test_video(cls): @classmethod def tearDownClass(cls): - Path(cls.folder_path / cls.file_paths[0]).unlink() - shutil.rmtree(cls.test_dir) + try: + Path(cls.folder_path / cls.file_paths[0]).unlink() + shutil.rmtree(cls.test_dir) + except PermissionError: # Windows + warn(f"Unable to cleanup testing data at {cls.folder_path / cls.file_paths[0]}! Please remove them manually.") def test_tif_files_are_missing_assertion(self): folder_path = "not a tiff path" From 3e9dc0b5edde41ac8d01de44675f16cac0db6e45 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 2 May 2023 14:30:37 +0000 Subject: [PATCH 18/22] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_micromanagertiffimagingextractor.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_micromanagertiffimagingextractor.py b/tests/test_micromanagertiffimagingextractor.py index 8ec8261d..3ffa25e1 100644 --- a/tests/test_micromanagertiffimagingextractor.py +++ b/tests/test_micromanagertiffimagingextractor.py @@ -45,7 +45,9 @@ def tearDownClass(cls): Path(cls.folder_path / cls.file_paths[0]).unlink() shutil.rmtree(cls.test_dir) except PermissionError: # Windows - warn(f"Unable to cleanup testing data at {cls.folder_path / cls.file_paths[0]}! Please remove them manually.") + warn( + f"Unable to cleanup testing data at {cls.folder_path / cls.file_paths[0]}! Please remove them manually." + ) def test_tif_files_are_missing_assertion(self): folder_path = "not a tiff path" From b124c2506195819e04ce2157cb7e01272e004099 Mon Sep 17 00:00:00 2001 From: Cody Baker <51133164+CodyCBakerPhD@users.noreply.github.com> Date: Tue, 2 May 2023 10:36:34 -0400 Subject: [PATCH 19/22] Update tests/test_micromanagertiffimagingextractor.py --- tests/test_micromanagertiffimagingextractor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_micromanagertiffimagingextractor.py b/tests/test_micromanagertiffimagingextractor.py index 3ffa25e1..8895e253 100644 --- a/tests/test_micromanagertiffimagingextractor.py +++ b/tests/test_micromanagertiffimagingextractor.py @@ -1,5 +1,6 @@ import shutil import tempfile +from pathlib import Path from warnings import warn import numpy as np From e88b983ead92b9c534da0784a5bdaba9ae3040a9 Mon Sep 17 00:00:00 2001 From: weiglszonja Date: Tue, 2 May 2023 18:11:01 +0200 Subject: [PATCH 20/22] apply review suggestions --- src/roiextractors/multiimagingextractor.py | 2 +- tests/test_micromanagertiffimagingextractor.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/roiextractors/multiimagingextractor.py b/src/roiextractors/multiimagingextractor.py index df4fa119..3d0a0f61 100644 --- a/src/roiextractors/multiimagingextractor.py +++ b/src/roiextractors/multiimagingextractor.py @@ -127,7 +127,7 @@ def get_video( start_frame=relative_start, end_frame=relative_stop ) - video_shape = (stop - start,) + self.get_image_size() + video_shape = (stop - start,) + self._imaging_extractors[0].get_image_size() video = np.empty(shape=video_shape, dtype=self.get_dtype()) current_frame = 0 diff --git a/tests/test_micromanagertiffimagingextractor.py b/tests/test_micromanagertiffimagingextractor.py index 8895e253..ea77547f 100644 --- a/tests/test_micromanagertiffimagingextractor.py +++ b/tests/test_micromanagertiffimagingextractor.py @@ -43,11 +43,11 @@ def _get_test_video(cls): @classmethod def tearDownClass(cls): try: - Path(cls.folder_path / cls.file_paths[0]).unlink() + (Path(cls.test_dir) / cls.file_paths[0]).unlink() shutil.rmtree(cls.test_dir) except PermissionError: # Windows warn( - f"Unable to cleanup testing data at {cls.folder_path / cls.file_paths[0]}! Please remove them manually." + f"Unable to cleanup testing data at {cls.test_dir / cls.file_paths[0]}! Please remove them manually." ) def test_tif_files_are_missing_assertion(self): From 376333045f29e788aed563ee304c272425e24e9b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 2 May 2023 16:11:14 +0000 Subject: [PATCH 21/22] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_micromanagertiffimagingextractor.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test_micromanagertiffimagingextractor.py b/tests/test_micromanagertiffimagingextractor.py index ea77547f..7fee552f 100644 --- a/tests/test_micromanagertiffimagingextractor.py +++ b/tests/test_micromanagertiffimagingextractor.py @@ -46,9 +46,7 @@ def tearDownClass(cls): (Path(cls.test_dir) / cls.file_paths[0]).unlink() shutil.rmtree(cls.test_dir) except PermissionError: # Windows - warn( - f"Unable to cleanup testing data at {cls.test_dir / cls.file_paths[0]}! Please remove them manually." - ) + warn(f"Unable to cleanup testing data at {cls.test_dir / cls.file_paths[0]}! Please remove them manually.") def test_tif_files_are_missing_assertion(self): folder_path = "not a tiff path" From ab63342e7b09139e8b3dfadab0fd4962f48cb292 Mon Sep 17 00:00:00 2001 From: Cody Baker <51133164+CodyCBakerPhD@users.noreply.github.com> Date: Tue, 2 May 2023 12:34:53 -0400 Subject: [PATCH 22/22] Update tests/test_micromanagertiffimagingextractor.py --- tests/test_micromanagertiffimagingextractor.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_micromanagertiffimagingextractor.py b/tests/test_micromanagertiffimagingextractor.py index 7fee552f..804b7bfd 100644 --- a/tests/test_micromanagertiffimagingextractor.py +++ b/tests/test_micromanagertiffimagingextractor.py @@ -43,10 +43,9 @@ def _get_test_video(cls): @classmethod def tearDownClass(cls): try: - (Path(cls.test_dir) / cls.file_paths[0]).unlink() shutil.rmtree(cls.test_dir) except PermissionError: # Windows - warn(f"Unable to cleanup testing data at {cls.test_dir / cls.file_paths[0]}! Please remove them manually.") + warn(f"Unable to cleanup testing data at {cls.test_dir}! Please remove it manually.") def test_tif_files_are_missing_assertion(self): folder_path = "not a tiff path"