From c279aa8785fffb65dfdc6e21e638d054ff15e24d Mon Sep 17 00:00:00 2001 From: Alessandra Trapani <55453048+alessandratrapani@users.noreply.github.com> Date: Fri, 1 Dec 2023 16:26:41 +0100 Subject: [PATCH 01/21] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb075773..ed349ec2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Upcoming + +# v0.5.5 + ### Features * Updated `Suite2pSegmentationExtractor` to support multi channel and multi plane data. [PR #242](https://github.com/catalystneuro/roiextractors/pull/242) From b33f00c1adc7f36711616643838c9854c492c9ff Mon Sep 17 00:00:00 2001 From: Alessandra Trapani <55453048+alessandratrapani@users.noreply.github.com> Date: Fri, 1 Dec 2023 16:28:41 +0100 Subject: [PATCH 02/21] Update setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 91f0a9e3..521da240 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ setup( name="roiextractors", - version="0.5.5", + version="0.5.6", author="Heberto Mayorquin, Szonja Weigl, Cody Baker, Ben Dichter, Alessio Buccino", author_email="ben.dichter@gmail.com", description="Python module for extracting optical physiology ROIs and traces for various file types and formats", From 6d4a56493670ffe18d45055fc8dda81f0ff535fe Mon Sep 17 00:00:00 2001 From: Heberto Mayorquin Date: Tue, 5 Dec 2023 12:12:05 +0100 Subject: [PATCH 03/21] improve stream checking in Bruker --- .../brukertiffimagingextractor.py | 63 ++++++++++++++----- tests/test_brukertiffimagingextactor.py | 6 +- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py index e307d826..328869b8 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py @@ -65,9 +65,16 @@ def _determine_imaging_is_volumetric(folder_path: PathType) -> bool: is_volumetric: bool True if the imaging is volumetric (multiplane), False otherwise (single plane). """ - xml_root = _parse_xml(folder_path=folder_path) - z_device_element = xml_root.find(".//PVStateValue[@key='zDevice']") - is_volumetric = bool(int(z_device_element.attrib["value"])) + folder_path = Path(folder_path) + xml_file_path = folder_path / f"{folder_path.name}.xml" + assert xml_file_path.is_file(), f"The XML configuration file is not found at '{xml_file_path}'." + + is_volumetric = False + with open(xml_file_path, "r") as xml_file: + for event, elem in ElementTree.iterparse(xml_file, events=("start",)): + if elem.tag == "PVStateValue" and elem.attrib.get("key") == "zDevice": + is_volumetric = bool(int(elem.attrib["value"])) + break # Stop parsing as we've found the required element return is_volumetric @@ -107,25 +114,53 @@ def get_streams(cls, folder_path: PathType) -> dict: """ natsort = get_package(package_name="natsort", installation_instructions="pip install natsort") - xml_root = _parse_xml(folder_path=folder_path) - channel_names = [file.attrib["channelName"] for file in xml_root.findall(".//File")] - unique_channel_names = natsort.natsorted(set(channel_names)) + folder_path = Path(folder_path) + xml_file_path = folder_path / f"{folder_path.name}.xml" + assert xml_file_path.is_file(), f"The XML configuration file is not found at '{folder_path}'." + + channel_names = set() + channel_ids = set() + file_names = [] + + # Parse the XML file iteratively to find the first Sequence element + first_sequence_element = None + with open(xml_file_path, "r") as xml_file: + for _, elem in ElementTree.iterparse(xml_file, events=("end",)): + if elem.tag == "Sequence": + first_sequence_element = elem + break + + if first_sequence_element is None: + raise ValueError("No Sequence element found in the XML configuration file. Can't get streams") + + # Then in the first Sequence we find all the Frame elements + if first_sequence_element is not None: + # Iterate over all Frame elements within the first Sequence + frame_elements = first_sequence_element.findall(".//Frame") + for frame_elemenet in frame_elements: + # Iterate over all File elements within each Frame + for file_elem in frame_elemenet.findall("File"): + channel_names.add(file_elem.attrib["channelName"]) + channel_ids.add(file_elem.attrib["channel"]) + file_names.append(file_elem.attrib["filename"]) + + unique_channel_names = natsort.natsorted(channel_names) + unique_channel_ids = natsort.natsorted(channel_ids) + streams = dict(channel_streams=unique_channel_names) streams["plane_streams"] = dict() + if not _determine_imaging_is_volumetric(folder_path=folder_path): return streams - # The "channelName" can be any name that the experimenter sets (e.g. 'Ch1', 'Ch2', 'Green', 'Red') - # Use the identifier of a channel "channel" (e.g. 1, 2) to match it to the file name - channel_ids = [file.attrib["channel"] for file in xml_root.findall(".//File")] - unique_channel_ids = natsort.natsorted(set(channel_ids)) + for channel_id, channel_name in zip(unique_channel_ids, unique_channel_names): plane_naming_pattern = rf"(?PCh{channel_id}_\d+)" - plane_stream_names = [ - re.search(plane_naming_pattern, file.attrib["filename"])["stream_name"] - for file in xml_root.findall(f".//File") - ] + regular_expression_matches = [re.search(plane_naming_pattern, filename) for filename in file_names] + plane_stream_names = [matches["stream_name"] for matches in regular_expression_matches if matches] + unique_plane_stream_names = natsort.natsorted(set(plane_stream_names)) streams["plane_streams"][channel_name] = unique_plane_stream_names + return streams def __init__( diff --git a/tests/test_brukertiffimagingextactor.py b/tests/test_brukertiffimagingextactor.py index a1e5361b..05b28aa1 100644 --- a/tests/test_brukertiffimagingextactor.py +++ b/tests/test_brukertiffimagingextactor.py @@ -133,9 +133,9 @@ def setUpClass(cls): cls.test_video[..., 1] = second_plane_video def test_stream_names(self): - self.assertEqual( - BrukerTiffMultiPlaneImagingExtractor.get_streams(folder_path=self.folder_path), self.available_streams - ) + found_streams = BrukerTiffMultiPlaneImagingExtractor.get_streams(folder_path=self.folder_path) + expected_streams = self.available_streams + self.assertEqual(found_streams, expected_streams) def test_brukertiffextractor_image_size(self): self.assertEqual(self.extractor.get_image_size(), (512, 512, 2)) From a732796d693f10536d389d7b2a4ad6d9647005c4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Dec 2023 11:18:42 +0000 Subject: [PATCH 04/21] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_brukertiffimagingextactor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_brukertiffimagingextactor.py b/tests/test_brukertiffimagingextactor.py index 05b28aa1..a975a3c1 100644 --- a/tests/test_brukertiffimagingextactor.py +++ b/tests/test_brukertiffimagingextactor.py @@ -134,8 +134,8 @@ def setUpClass(cls): def test_stream_names(self): found_streams = BrukerTiffMultiPlaneImagingExtractor.get_streams(folder_path=self.folder_path) - expected_streams = self.available_streams - self.assertEqual(found_streams, expected_streams) + expected_streams = self.available_streams + self.assertEqual(found_streams, expected_streams) def test_brukertiffextractor_image_size(self): self.assertEqual(self.extractor.get_image_size(), (512, 512, 2)) From 02e03cfebe49258d8be1255d9795eb274ef4124f Mon Sep 17 00:00:00 2001 From: Heberto Mayorquin Date: Tue, 5 Dec 2023 12:27:22 +0100 Subject: [PATCH 05/21] windows no context manager --- .../brukertiffimagingextractor.py | 46 +++++++++---------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py index 328869b8..91197214 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py @@ -70,11 +70,10 @@ def _determine_imaging_is_volumetric(folder_path: PathType) -> bool: assert xml_file_path.is_file(), f"The XML configuration file is not found at '{xml_file_path}'." is_volumetric = False - with open(xml_file_path, "r") as xml_file: - for event, elem in ElementTree.iterparse(xml_file, events=("start",)): - if elem.tag == "PVStateValue" and elem.attrib.get("key") == "zDevice": - is_volumetric = bool(int(elem.attrib["value"])) - break # Stop parsing as we've found the required element + for event, elem in ElementTree.iterparse(xml_file_path, events=("start",)): + if elem.tag == "PVStateValue" and elem.attrib.get("key") == "zDevice": + is_volumetric = bool(int(elem.attrib["value"])) + break # Stop parsing as we've found the required element return is_volumetric @@ -124,25 +123,24 @@ def get_streams(cls, folder_path: PathType) -> dict: # Parse the XML file iteratively to find the first Sequence element first_sequence_element = None - with open(xml_file_path, "r") as xml_file: - for _, elem in ElementTree.iterparse(xml_file, events=("end",)): - if elem.tag == "Sequence": - first_sequence_element = elem - break - - if first_sequence_element is None: - raise ValueError("No Sequence element found in the XML configuration file. Can't get streams") - - # Then in the first Sequence we find all the Frame elements - if first_sequence_element is not None: - # Iterate over all Frame elements within the first Sequence - frame_elements = first_sequence_element.findall(".//Frame") - for frame_elemenet in frame_elements: - # Iterate over all File elements within each Frame - for file_elem in frame_elemenet.findall("File"): - channel_names.add(file_elem.attrib["channelName"]) - channel_ids.add(file_elem.attrib["channel"]) - file_names.append(file_elem.attrib["filename"]) + for _, elem in ElementTree.iterparse(xml_file_path, events=("end",)): + if elem.tag == "Sequence": + first_sequence_element = elem + break + + if first_sequence_element is None: + raise ValueError("No Sequence element found in the XML configuration file. Can't get streams") + + # Then in the first Sequence we find all the Frame elements + if first_sequence_element is not None: + # Iterate over all Frame elements within the first Sequence + frame_elements = first_sequence_element.findall(".//Frame") + for frame_elemenet in frame_elements: + # Iterate over all File elements within each Frame + for file_elem in frame_elemenet.findall("File"): + channel_names.add(file_elem.attrib["channelName"]) + channel_ids.add(file_elem.attrib["channel"]) + file_names.append(file_elem.attrib["filename"]) unique_channel_names = natsort.natsorted(channel_names) unique_channel_ids = natsort.natsorted(channel_ids) From 292b815bfcf7e2993000d0c9e0ab3e571c496351 Mon Sep 17 00:00:00 2001 From: Heberto Mayorquin Date: Tue, 5 Dec 2023 12:28:54 +0100 Subject: [PATCH 06/21] changelog add --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed349ec2..c894813b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Upcoming +### Improvements +* Improved xml parsing with Bruker [PR #267](https://github.com/catalystneuro/roiextractors/pull/267) + # v0.5.5 From 467bbb00c20d79ecdd383b39aa1ced2734fcb33e Mon Sep 17 00:00:00 2001 From: Heberto Mayorquin Date: Tue, 5 Dec 2023 13:13:26 +0100 Subject: [PATCH 07/21] avoid parsing the file twice --- .../tiffimagingextractors/brukertiffimagingextractor.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py index e307d826..f4f10180 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py @@ -159,17 +159,20 @@ def __init__( tif_file_paths = list(folder_path.glob("*.ome.tif")) assert tif_file_paths, f"The TIF image files are missing from '{folder_path}'." - assert _determine_imaging_is_volumetric(folder_path=folder_path), ( + streams = self.get_streams(folder_path=folder_path) + plane_streams = streams["plane_streams"] + + assert len(plane_streams) == 0 ( f"{self.extractor_name}Extractor is for volumetric imaging. " "For single imaging plane data use BrukerTiffSinglePlaneImagingExtractor." ) - streams = self.get_streams(folder_path=folder_path) if stream_name is None: if len(streams["channel_streams"]) > 1: raise ValueError( "More than one recording stream is detected! Please specify which stream you wish to load with the `stream_name` argument. " - "To see what streams are available, call `BrukerTiffMultiPlaneImagingExtractor.get_stream_names(folder_path=...)`." + "The following channel streams are available: \n" + f"{streams['channel_streams']}" ) channel_stream_name = streams["channel_streams"][0] stream_name = streams["plane_streams"][channel_stream_name][0] From 0d15c8920ded9afc0aa37ecf9296ba2d1e9ac25a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Dec 2023 12:15:46 +0000 Subject: [PATCH 08/21] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../tiffimagingextractors/brukertiffimagingextractor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py index f4f10180..bb26c5d2 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py @@ -162,7 +162,7 @@ def __init__( streams = self.get_streams(folder_path=folder_path) plane_streams = streams["plane_streams"] - assert len(plane_streams) == 0 ( + assert len(plane_streams) == 0( f"{self.extractor_name}Extractor is for volumetric imaging. " "For single imaging plane data use BrukerTiffSinglePlaneImagingExtractor." ) From 9156e8c8bca88f8dae9b9bf2d743545829fd1c77 Mon Sep 17 00:00:00 2001 From: Heberto Mayorquin Date: Tue, 5 Dec 2023 13:19:08 +0100 Subject: [PATCH 09/21] missed a comma --- .../tiffimagingextractors/brukertiffimagingextractor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py index bb26c5d2..7062d75e 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py @@ -162,7 +162,7 @@ def __init__( streams = self.get_streams(folder_path=folder_path) plane_streams = streams["plane_streams"] - assert len(plane_streams) == 0( + assert len(plane_streams) > 0, ( f"{self.extractor_name}Extractor is for volumetric imaging. " "For single imaging plane data use BrukerTiffSinglePlaneImagingExtractor." ) From dfda396a08ad7fa92eeb0a9d330d2606c9cd3455 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 20:40:41 +0000 Subject: [PATCH 10/21] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 23.11.0 → 23.12.0](https://github.com/psf/black/compare/23.11.0...23.12.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aec2195e..9397f80d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/psf/black - rev: 23.11.0 + rev: 23.12.0 hooks: - id: black exclude: ^docs/ From c5dedb243e6d56eecda6bc7aeafe615438c20625 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 25 Dec 2023 20:24:04 +0000 Subject: [PATCH 11/21] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 23.12.0 → 23.12.1](https://github.com/psf/black/compare/23.12.0...23.12.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9397f80d..0dadce9a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/psf/black - rev: 23.12.0 + rev: 23.12.1 hooks: - id: black exclude: ^docs/ From bd18e5b768686f3d6dbd57d4c37b8e6d4ecf64a9 Mon Sep 17 00:00:00 2001 From: Alessandra Trapani <55453048+alessandratrapani@users.noreply.github.com> Date: Fri, 5 Jan 2024 16:40:32 +0100 Subject: [PATCH 12/21] Extract roi indices from redcell.npy in Suite2pExtractor (#270) * extract roi indices from redcell.npy * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Cody Baker <51133164+CodyCBakerPhD@users.noreply.github.com> --- .../extractors/suite2p/suite2psegmentationextractor.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/roiextractors/extractors/suite2p/suite2psegmentationextractor.py b/src/roiextractors/extractors/suite2p/suite2psegmentationextractor.py index 5756a32f..070d132c 100644 --- a/src/roiextractors/extractors/suite2p/suite2psegmentationextractor.py +++ b/src/roiextractors/extractors/suite2p/suite2psegmentationextractor.py @@ -166,7 +166,12 @@ def __init__( self._load_npy(file_name="spks.npy", mmap_mode="r", transpose=True) if channel_name == "chan1" else None ) - self.iscell = self._load_npy("iscell.npy", mmap_mode="r") + # rois segmented from the iamging acquired with second channel (red/anatomical) that match the first channel segmentation + redcell = self._load_npy(file_name="redcell.npy", mmap_mode="r") + if channel_name == "chan2" and redcell is not None: + self.iscell = redcell + else: + self.iscell = self._load_npy("iscell.npy", mmap_mode="r") # The name of the OpticalChannel object is "OpticalChannel" if there is only one channel, otherwise it is # "Chan1" or "Chan2". From f407c4f433e8ef79d44b5e59e32326ddc312be91 Mon Sep 17 00:00:00 2001 From: Ben Dichter Date: Wed, 24 Jan 2024 12:41:02 -0500 Subject: [PATCH 13/21] Update bug_report.yml (#277) Remove Python 3.7 --- .github/ISSUE_TEMPLATE/bug_report.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index fa063e56..e402ce61 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -60,9 +60,11 @@ body: attributes: label: Python Version options: - - 3.7 - 3.8 - 3.9 + - 3.10 + - 3.11 + - 3.12 validations: required: true - type: textarea From 1a136a53e7eb33729f911a0edf3683fe5d05da6c Mon Sep 17 00:00:00 2001 From: Alessandra Trapani <55453048+alessandratrapani@users.noreply.github.com> Date: Wed, 24 Jan 2024 21:26:17 +0100 Subject: [PATCH 14/21] Add function to extract ROIs metadata from ScanImage tiff (#272) * add function to extract ROIs metadata from ScanImage tiff * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * implement requested changes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * update test_parse_metadata accordingly * correct wrong value for expected_metadata * update to work with versions v3.8.0 * minor fix --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../scanimagetiff_utils.py | 14 +- tests/test_scanimage_utils.py | 167 ++++++++++++++++++ 2 files changed, 179 insertions(+), 2 deletions(-) diff --git a/src/roiextractors/extractors/tiffimagingextractors/scanimagetiff_utils.py b/src/roiextractors/extractors/tiffimagingextractors/scanimagetiff_utils.py index 691722dc..7d9900d6 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/scanimagetiff_utils.py +++ b/src/roiextractors/extractors/tiffimagingextractors/scanimagetiff_utils.py @@ -1,5 +1,6 @@ """Utility functions for ScanImage TIFF Extractors.""" import numpy as np +import json from ...extraction_tools import PathType, get_package @@ -33,12 +34,16 @@ def extract_extra_metadata( io = ScanImageTiffReader(str(file_path)) extra_metadata = {} for metadata_string in (io.description(iframe=0), io.metadata()): - metadata_dict = { + system_metadata_dict = { x.split("=")[0].strip(): x.split("=")[1].strip() for x in metadata_string.replace("\n", "\r").split("\r") if "=" in x } - extra_metadata = dict(**extra_metadata, **metadata_dict) + extra_metadata = dict(**extra_metadata, **system_metadata_dict) + if "\n\n" in io.metadata(): + additional_metadata_string = io.metadata().split("\n\n")[1] + additional_metadata = json.loads(additional_metadata_string) + extra_metadata = dict(**extra_metadata, **additional_metadata) return extra_metadata @@ -115,12 +120,17 @@ def parse_metadata(metadata: dict) -> dict: channel_names = np.array(metadata["SI.hChannels.channelName"].split("'")[1::2]) channel_names = channel_names[channel_indices].tolist() num_channels = len(channel_names) + if "RoiGroups" in metadata.keys(): + roi_metadata = metadata["RoiGroups"] + else: + roi_metadata = None 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, + roi_metadata=roi_metadata, ) return metadata_parsed diff --git a/tests/test_scanimage_utils.py b/tests/test_scanimage_utils.py index fd55c671..3d1e60c0 100644 --- a/tests/test_scanimage_utils.py +++ b/tests/test_scanimage_utils.py @@ -63,6 +63,73 @@ def test_parse_matlab_vector_invalid(): "num_planes": 20, "frames_per_slice": 24, "channel_names": ["Channel 1"], + "roi_metadata": { + "imagingRoiGroup": { + "ver": 1, + "classname": "scanimage.mroi.RoiGroup", + "name": "Default Imaging ROI Group", + "UserData": None, + "roiUuid": "E9CD2A60E29A5EDE", + "roiUuiduint64": 1.684716838e19, + "rois": { + "ver": 1, + "classname": "scanimage.mroi.Roi", + "name": "Default Imaging Roi", + "UserData": { + "imagingSystem": "Imaging_RGG", + "fillFractionSpatial": 0.9, + "forceSquarePixelation": 1, + "forceSquarePixels": 1, + "scanZoomFactor": 1, + "scanAngleShiftFast": 0, + "scanAngleMultiplierSlow": 1, + "scanAngleShiftSlow": 0, + "scanRotation": 0, + "pixelsPerLine": 1024, + "linesPerFrame": 1024, + }, + "roiUuid": "1B54BED0B8A25D87", + "roiUuiduint64": 1.969408741e18, + "zs": 0, + "scanfields": { + "ver": 1, + "classname": "scanimage.mroi.scanfield.fields.RotatedRectangle", + "name": "Default Imaging Scanfield", + "UserData": None, + "roiUuid": "4309FD6B19453539", + "roiUuiduint64": 4.830670712e18, + "centerXY": [0, 0], + "sizeXY": [18, 18], + "rotationDegrees": 0, + "enable": 1, + "pixelResolutionXY": [1024, 1024], + "pixelToRefTransform": [ + [0.017578125, 0, -9.008789063], + [0, 0.017578125, -9.008789063], + [0, 0, 1], + ], + "affine": [[18, 0, -9], [0, 18, -9], [0, 0, 1]], + }, + "discretePlaneMode": 0, + "powers": None, + "pzAdjust": [], + "Lzs": None, + "interlaceDecimation": None, + "interlaceOffset": None, + "enable": 1, + }, + }, + "photostimRoiGroups": None, + "integrationRoiGroup": { + "ver": 1, + "classname": "scanimage.mroi.RoiGroup", + "name": "", + "UserData": None, + "roiUuid": "9FC266E57D28670D", + "roiUuiduint64": 1.151187673e19, + "rois": {"_ArrayType_": "double", "_ArraySize_": [1, 0], "_ArrayData_": None}, + }, + }, }, ), ( @@ -73,6 +140,106 @@ def test_parse_matlab_vector_invalid(): "num_planes": 2, "frames_per_slice": 2, "channel_names": ["Channel 1", "Channel 4"], + "roi_metadata": { + "imagingRoiGroup": { + "ver": 1, + "classname": "scanimage.mroi.RoiGroup", + "name": "MROI Imaging ROI Group", + "UserData": None, + "roiUuid": "4118A30BD7393EFF", + "roiUuiduint64": 4.690678283e18, + "rois": [ + { + "ver": 1, + "classname": "scanimage.mroi.Roi", + "name": "ROI 1", + "UserData": None, + "roiUuid": "8C08C657736FBC6C", + "roiUuiduint64": 1.009053304e19, + "zs": -11178.45, + "scanfields": { + "ver": 1, + "classname": "scanimage.mroi.scanfield.fields.RotatedRectangle", + "name": "", + "UserData": None, + "roiUuid": "2B42EE3A0B039B9E", + "roiUuiduint64": 3.117315825e18, + "centerXY": [0.2141430948, -6.019800333], + "sizeXY": [3.616638935, 3.521464226], + "rotationDegrees": 0, + "enable": 1, + "pixelResolutionXY": [256, 256], + "pixelToRefTransform": [ + [0.01412749584, 0, -1.601240121], + [0, 0.01375571963, -7.787410306], + [0, 0, 1], + ], + "affine": [ + [3.616638935, 0, -1.594176373], + [0, 3.521464226, -7.780532446], + [0, 0, 1], + ], + }, + "discretePlaneMode": 0, + "powers": None, + "pzAdjust": [], + "Lzs": None, + "interlaceDecimation": None, + "interlaceOffset": None, + "enable": 1, + }, + { + "ver": 1, + "classname": "scanimage.mroi.Roi", + "name": "ROI 2", + "UserData": None, + "roiUuid": "7C9E605DC6951B29", + "roiUuiduint64": 8.979720663e18, + "zs": -11178.45, + "scanfields": { + "ver": 1, + "classname": "scanimage.mroi.scanfield.fields.RotatedRectangle", + "name": "", + "UserData": None, + "roiUuid": "A02889BA5E5501AB", + "roiUuiduint64": 1.154062548e19, + "centerXY": [2.664891847, 6.376705491], + "sizeXY": [3.616638935, 3.759400998], + "rotationDegrees": 0, + "enable": 1, + "pixelResolutionXY": [256, 256], + "pixelToRefTransform": [ + [0.01412749584, 0, 0.8495086314], + [0, 0.01468516015, 4.489662412], + [0, 0, 1], + ], + "affine": [ + [3.616638935, 0, 0.8565723794], + [0, 3.759400998, 4.497004992], + [0, 0, 1], + ], + }, + "discretePlaneMode": 0, + "powers": None, + "pzAdjust": [], + "Lzs": None, + "interlaceDecimation": None, + "interlaceOffset": None, + "enable": 1, + }, + ], + }, + "photostimRoiGroups": None, + "integrationRoiGroup": { + "ver": 1, + "classname": "scanimage.mroi.RoiGroup", + "name": "", + "UserData": None, + "roiUuid": "1B4D989071535CF3", + "roiUuiduint64": 1.967396358e18, + "rois": {"_ArrayType_": "double", "_ArraySize_": [1, 0], "_ArrayData_": None}, + }, + }, }, ), ], From f49355ceeddb8ed60e73d351dbeaddf3979af588 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 15:22:40 -0500 Subject: [PATCH 15/21] [pre-commit.ci] pre-commit autoupdate (#279) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/psf/black: 23.12.1 → 24.1.1](https://github.com/psf/black/compare/23.12.1...24.1.1) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- src/roiextractors/__init__.py | 1 + src/roiextractors/example_datasets/__init__.py | 1 + src/roiextractors/example_datasets/toy_example.py | 1 + src/roiextractors/extraction_tools.py | 1 + src/roiextractors/extractorlist.py | 1 + src/roiextractors/extractors/caiman/__init__.py | 1 + .../extractors/caiman/caimansegmentationextractor.py | 1 + src/roiextractors/extractors/hdf5imagingextractor/__init__.py | 1 + .../extractors/hdf5imagingextractor/hdf5imagingextractor.py | 1 + src/roiextractors/extractors/memmapextractors/__init__.py | 1 + .../extractors/memmapextractors/memmapextractors.py | 1 + .../extractors/memmapextractors/numpymemampextractor.py | 1 + .../extractors/miniscopeimagingextractor/__init__.py | 1 + .../miniscopeimagingextractor/miniscopeimagingextractor.py | 1 + src/roiextractors/extractors/numpyextractors/__init__.py | 1 + src/roiextractors/extractors/numpyextractors/numpyextractors.py | 1 + src/roiextractors/extractors/nwbextractors/__init__.py | 1 + src/roiextractors/extractors/nwbextractors/nwbextractors.py | 1 + src/roiextractors/extractors/sbximagingextractor/__init__.py | 1 + .../extractors/sbximagingextractor/sbximagingextractor.py | 1 + src/roiextractors/extractors/schnitzerextractor/__init__.py | 1 + .../extractors/schnitzerextractor/cnmfesegmentationextractor.py | 1 + .../schnitzerextractor/extractsegmentationextractor.py | 1 + src/roiextractors/extractors/simaextractor/__init__.py | 1 + .../extractors/simaextractor/simasegmentationextractor.py | 1 + src/roiextractors/extractors/suite2p/__init__.py | 1 + .../extractors/suite2p/suite2psegmentationextractor.py | 1 + src/roiextractors/extractors/tiffimagingextractors/__init__.py | 1 + .../tiffimagingextractors/brukertiffimagingextractor.py | 1 + .../extractors/tiffimagingextractors/scanimagetiff_utils.py | 1 + .../tiffimagingextractors/scanimagetiffimagingextractor.py | 1 + .../extractors/tiffimagingextractors/tiffimagingextractor.py | 1 + src/roiextractors/imagingextractor.py | 1 + src/roiextractors/multiimagingextractor.py | 1 + src/roiextractors/multisegmentationextractor.py | 1 + src/roiextractors/segmentationextractor.py | 1 + src/roiextractors/testing.py | 1 + 38 files changed, 38 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0dadce9a..4818cc7e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/psf/black - rev: 23.12.1 + rev: 24.1.1 hooks: - id: black exclude: ^docs/ diff --git a/src/roiextractors/__init__.py b/src/roiextractors/__init__.py index 46c64c68..9b517e50 100644 --- a/src/roiextractors/__init__.py +++ b/src/roiextractors/__init__.py @@ -1,4 +1,5 @@ """Python-based module for extracting from, converting between, and handling recorded and optical imaging data from several file formats.""" + # Keeping __version__ accessible only to maintain backcompatability. # Modern appraoch (Python >= 3.8) is to use importlib try: diff --git a/src/roiextractors/example_datasets/__init__.py b/src/roiextractors/example_datasets/__init__.py index a1951668..4532ba9d 100644 --- a/src/roiextractors/example_datasets/__init__.py +++ b/src/roiextractors/example_datasets/__init__.py @@ -10,4 +10,5 @@ toy_example Create a toy example of an ImagingExtractor and a SegmentationExtractor. """ + from .toy_example import toy_example diff --git a/src/roiextractors/example_datasets/toy_example.py b/src/roiextractors/example_datasets/toy_example.py index e8a9a58d..f6dc99e6 100644 --- a/src/roiextractors/example_datasets/toy_example.py +++ b/src/roiextractors/example_datasets/toy_example.py @@ -5,6 +5,7 @@ toy_example Create a toy example of an ImagingExtractor and a SegmentationExtractor. """ + import numpy as np from ..extractors.numpyextractors import ( diff --git a/src/roiextractors/extraction_tools.py b/src/roiextractors/extraction_tools.py index 1ceed3d4..704be5db 100644 --- a/src/roiextractors/extraction_tools.py +++ b/src/roiextractors/extraction_tools.py @@ -5,6 +5,7 @@ VideoStructure A data class for specifying the structure of a video. """ + import sys import importlib.util from functools import wraps diff --git a/src/roiextractors/extractorlist.py b/src/roiextractors/extractorlist.py index 73d0bf6e..71feb655 100644 --- a/src/roiextractors/extractorlist.py +++ b/src/roiextractors/extractorlist.py @@ -1,4 +1,5 @@ """Listing of available formats for extraction.""" + from .extractors.caiman import CaimanSegmentationExtractor from .extractors.hdf5imagingextractor import Hdf5ImagingExtractor from .extractors.numpyextractors import ( diff --git a/src/roiextractors/extractors/caiman/__init__.py b/src/roiextractors/extractors/caiman/__init__.py index 866519c6..42ac0036 100644 --- a/src/roiextractors/extractors/caiman/__init__.py +++ b/src/roiextractors/extractors/caiman/__init__.py @@ -10,4 +10,5 @@ CaimanSegmentationExtractor A class for extracting segmentation from Caiman output. """ + from .caimansegmentationextractor import CaimanSegmentationExtractor diff --git a/src/roiextractors/extractors/caiman/caimansegmentationextractor.py b/src/roiextractors/extractors/caiman/caimansegmentationextractor.py index fa840a41..77eefb29 100644 --- a/src/roiextractors/extractors/caiman/caimansegmentationextractor.py +++ b/src/roiextractors/extractors/caiman/caimansegmentationextractor.py @@ -5,6 +5,7 @@ CaimanSegmentationExtractor A class for extracting segmentation from CaImAn output. """ + from pathlib import Path try: diff --git a/src/roiextractors/extractors/hdf5imagingextractor/__init__.py b/src/roiextractors/extractors/hdf5imagingextractor/__init__.py index ec01de58..e2b176e0 100644 --- a/src/roiextractors/extractors/hdf5imagingextractor/__init__.py +++ b/src/roiextractors/extractors/hdf5imagingextractor/__init__.py @@ -11,4 +11,5 @@ Hdf5ImagingExtractor An imaging extractor for HDF5. """ + from .hdf5imagingextractor import Hdf5ImagingExtractor diff --git a/src/roiextractors/extractors/hdf5imagingextractor/hdf5imagingextractor.py b/src/roiextractors/extractors/hdf5imagingextractor/hdf5imagingextractor.py index bd926820..d56fa5e3 100644 --- a/src/roiextractors/extractors/hdf5imagingextractor/hdf5imagingextractor.py +++ b/src/roiextractors/extractors/hdf5imagingextractor/hdf5imagingextractor.py @@ -5,6 +5,7 @@ Hdf5ImagingExtractor An imaging extractor for HDF5. """ + from pathlib import Path from typing import Optional, Tuple from warnings import warn diff --git a/src/roiextractors/extractors/memmapextractors/__init__.py b/src/roiextractors/extractors/memmapextractors/__init__.py index eb887aec..64351fe6 100644 --- a/src/roiextractors/extractors/memmapextractors/__init__.py +++ b/src/roiextractors/extractors/memmapextractors/__init__.py @@ -14,5 +14,6 @@ NumpyMemmapImagingExtractor The class for reading optical imaging data stored in a binary format with numpy.memmap. """ + from .memmapextractors import MemmapImagingExtractor from .numpymemampextractor import NumpyMemmapImagingExtractor diff --git a/src/roiextractors/extractors/memmapextractors/memmapextractors.py b/src/roiextractors/extractors/memmapextractors/memmapextractors.py index 450a5dc6..62e44e69 100644 --- a/src/roiextractors/extractors/memmapextractors/memmapextractors.py +++ b/src/roiextractors/extractors/memmapextractors/memmapextractors.py @@ -5,6 +5,7 @@ MemmapImagingExtractor The base class for memmapable imaging extractors. """ + from pathlib import Path import numpy as np diff --git a/src/roiextractors/extractors/memmapextractors/numpymemampextractor.py b/src/roiextractors/extractors/memmapextractors/numpymemampextractor.py index a2510c80..c3636132 100644 --- a/src/roiextractors/extractors/memmapextractors/numpymemampextractor.py +++ b/src/roiextractors/extractors/memmapextractors/numpymemampextractor.py @@ -5,6 +5,7 @@ NumpyMemmapImagingExtractor The class for reading optical imaging data stored in a binary format with numpy.memmap. """ + import os from pathlib import Path from typing import Tuple, Dict diff --git a/src/roiextractors/extractors/miniscopeimagingextractor/__init__.py b/src/roiextractors/extractors/miniscopeimagingextractor/__init__.py index 43661b3a..9cf2517c 100644 --- a/src/roiextractors/extractors/miniscopeimagingextractor/__init__.py +++ b/src/roiextractors/extractors/miniscopeimagingextractor/__init__.py @@ -10,4 +10,5 @@ MiniscopeImagingExtractor An ImagingExtractor for the Miniscope video (.avi) format. """ + from .miniscopeimagingextractor import MiniscopeImagingExtractor diff --git a/src/roiextractors/extractors/miniscopeimagingextractor/miniscopeimagingextractor.py b/src/roiextractors/extractors/miniscopeimagingextractor/miniscopeimagingextractor.py index d7d293ac..e619f8b2 100644 --- a/src/roiextractors/extractors/miniscopeimagingextractor/miniscopeimagingextractor.py +++ b/src/roiextractors/extractors/miniscopeimagingextractor/miniscopeimagingextractor.py @@ -5,6 +5,7 @@ MiniscopeImagingExtractor An ImagingExtractor for the Miniscope video (.avi) format. """ + import json import re from pathlib import Path diff --git a/src/roiextractors/extractors/numpyextractors/__init__.py b/src/roiextractors/extractors/numpyextractors/__init__.py index be6df5a4..f7d945dc 100644 --- a/src/roiextractors/extractors/numpyextractors/__init__.py +++ b/src/roiextractors/extractors/numpyextractors/__init__.py @@ -12,4 +12,5 @@ NumpySegmentationExtractor A Segmentation extractor specified by image masks and traces .npy files. """ + from .numpyextractors import NumpyImagingExtractor, NumpySegmentationExtractor diff --git a/src/roiextractors/extractors/numpyextractors/numpyextractors.py b/src/roiextractors/extractors/numpyextractors/numpyextractors.py index 42862268..0ed3c0df 100644 --- a/src/roiextractors/extractors/numpyextractors/numpyextractors.py +++ b/src/roiextractors/extractors/numpyextractors/numpyextractors.py @@ -7,6 +7,7 @@ NumpySegmentationExtractor A Segmentation extractor specified by image masks and traces .npy files. """ + from pathlib import Path from typing import Optional, Tuple diff --git a/src/roiextractors/extractors/nwbextractors/__init__.py b/src/roiextractors/extractors/nwbextractors/__init__.py index 0df342a9..87fb7d50 100644 --- a/src/roiextractors/extractors/nwbextractors/__init__.py +++ b/src/roiextractors/extractors/nwbextractors/__init__.py @@ -12,4 +12,5 @@ NwbSegmentationExtractor Extracts segmentation data from NWB files. """ + from .nwbextractors import NwbImagingExtractor, NwbSegmentationExtractor diff --git a/src/roiextractors/extractors/nwbextractors/nwbextractors.py b/src/roiextractors/extractors/nwbextractors/nwbextractors.py index 30c365b3..daf271a5 100644 --- a/src/roiextractors/extractors/nwbextractors/nwbextractors.py +++ b/src/roiextractors/extractors/nwbextractors/nwbextractors.py @@ -7,6 +7,7 @@ NwbSegmentationExtractor Extracts segmentation data from NWB files. """ + from pathlib import Path from typing import Union, Optional, Iterable, Tuple diff --git a/src/roiextractors/extractors/sbximagingextractor/__init__.py b/src/roiextractors/extractors/sbximagingextractor/__init__.py index 0671dd41..82897450 100644 --- a/src/roiextractors/extractors/sbximagingextractor/__init__.py +++ b/src/roiextractors/extractors/sbximagingextractor/__init__.py @@ -10,4 +10,5 @@ SbxImagingExtractor An ImagingExtractor for Scanbox Image files. """ + from .sbximagingextractor import SbxImagingExtractor diff --git a/src/roiextractors/extractors/sbximagingextractor/sbximagingextractor.py b/src/roiextractors/extractors/sbximagingextractor/sbximagingextractor.py index bfca09ed..008b35e4 100644 --- a/src/roiextractors/extractors/sbximagingextractor/sbximagingextractor.py +++ b/src/roiextractors/extractors/sbximagingextractor/sbximagingextractor.py @@ -5,6 +5,7 @@ SbxImagingExtractor An ImagingExtractor for Scanbox Image files. """ + from multiprocessing.sharedctypes import Value import os from pathlib import Path diff --git a/src/roiextractors/extractors/schnitzerextractor/__init__.py b/src/roiextractors/extractors/schnitzerextractor/__init__.py index e73a77f3..c2799ad2 100644 --- a/src/roiextractors/extractors/schnitzerextractor/__init__.py +++ b/src/roiextractors/extractors/schnitzerextractor/__init__.py @@ -18,6 +18,7 @@ LegacyExtractSegmentationExtractor Extractor for reading the segmentation data that results from calls to older versions of EXTRACT. """ + from .cnmfesegmentationextractor import CnmfeSegmentationExtractor from .extractsegmentationextractor import ( LegacyExtractSegmentationExtractor, diff --git a/src/roiextractors/extractors/schnitzerextractor/cnmfesegmentationextractor.py b/src/roiextractors/extractors/schnitzerextractor/cnmfesegmentationextractor.py index 300cb574..16397b2f 100644 --- a/src/roiextractors/extractors/schnitzerextractor/cnmfesegmentationextractor.py +++ b/src/roiextractors/extractors/schnitzerextractor/cnmfesegmentationextractor.py @@ -5,6 +5,7 @@ CnmfeSegmentationExtractor A segmentation extractor for CNMF-E ROI segmentation method. """ + from pathlib import Path try: diff --git a/src/roiextractors/extractors/schnitzerextractor/extractsegmentationextractor.py b/src/roiextractors/extractors/schnitzerextractor/extractsegmentationextractor.py index 689966b3..3923df06 100644 --- a/src/roiextractors/extractors/schnitzerextractor/extractsegmentationextractor.py +++ b/src/roiextractors/extractors/schnitzerextractor/extractsegmentationextractor.py @@ -9,6 +9,7 @@ LegacyExtractSegmentationExtractor Extractor for reading the segmentation data that results from calls to older versions of EXTRACT. """ + from abc import ABC from pathlib import Path from typing import Optional diff --git a/src/roiextractors/extractors/simaextractor/__init__.py b/src/roiextractors/extractors/simaextractor/__init__.py index a8c1581f..62957c71 100644 --- a/src/roiextractors/extractors/simaextractor/__init__.py +++ b/src/roiextractors/extractors/simaextractor/__init__.py @@ -10,4 +10,5 @@ SimaSegmentationExtractor A segmentation extractor for Sima. """ + from .simasegmentationextractor import SimaSegmentationExtractor diff --git a/src/roiextractors/extractors/simaextractor/simasegmentationextractor.py b/src/roiextractors/extractors/simaextractor/simasegmentationextractor.py index 2060c43f..71905a2c 100644 --- a/src/roiextractors/extractors/simaextractor/simasegmentationextractor.py +++ b/src/roiextractors/extractors/simaextractor/simasegmentationextractor.py @@ -5,6 +5,7 @@ SimaSegmentationExtractor A segmentation extractor for Sima. """ + import os import pickle import re diff --git a/src/roiextractors/extractors/suite2p/__init__.py b/src/roiextractors/extractors/suite2p/__init__.py index fb8d97f5..4da2a048 100644 --- a/src/roiextractors/extractors/suite2p/__init__.py +++ b/src/roiextractors/extractors/suite2p/__init__.py @@ -10,4 +10,5 @@ Suite2pSegmentationExtractor A segmentation extractor for Suite2p. """ + from .suite2psegmentationextractor import Suite2pSegmentationExtractor diff --git a/src/roiextractors/extractors/suite2p/suite2psegmentationextractor.py b/src/roiextractors/extractors/suite2p/suite2psegmentationextractor.py index 070d132c..b7ade533 100644 --- a/src/roiextractors/extractors/suite2p/suite2psegmentationextractor.py +++ b/src/roiextractors/extractors/suite2p/suite2psegmentationextractor.py @@ -5,6 +5,7 @@ Suite2pSegmentationExtractor A segmentation extractor for Suite2p. """ + import shutil from pathlib import Path from typing import Optional diff --git a/src/roiextractors/extractors/tiffimagingextractors/__init__.py b/src/roiextractors/extractors/tiffimagingextractors/__init__.py index 3f3a3618..4de3eb70 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/__init__.py +++ b/src/roiextractors/extractors/tiffimagingextractors/__init__.py @@ -28,6 +28,7 @@ MicroManagerTiffImagingExtractor Specialized extractor for reading TIFF files produced via Micro-Manager. """ + from .tiffimagingextractor import TiffImagingExtractor from .scanimagetiffimagingextractor import ( ScanImageTiffImagingExtractor, diff --git a/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py index 751f08a3..780ce4eb 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/brukertiffimagingextractor.py @@ -7,6 +7,7 @@ BrukerTiffMultiPlaneImagingExtractor A MultiImagingExtractor for TIFF files produced by Bruker with multiple planes. """ + import logging import re from collections import Counter diff --git a/src/roiextractors/extractors/tiffimagingextractors/scanimagetiff_utils.py b/src/roiextractors/extractors/tiffimagingextractors/scanimagetiff_utils.py index 7d9900d6..bf559573 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/scanimagetiff_utils.py +++ b/src/roiextractors/extractors/tiffimagingextractors/scanimagetiff_utils.py @@ -1,4 +1,5 @@ """Utility functions for ScanImage TIFF Extractors.""" + import numpy as np import json from ...extraction_tools import PathType, get_package diff --git a/src/roiextractors/extractors/tiffimagingextractors/scanimagetiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/scanimagetiffimagingextractor.py index fea05b62..9ed34d8c 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/scanimagetiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/scanimagetiffimagingextractor.py @@ -5,6 +5,7 @@ ScanImageTiffImagingExtractor Specialized extractor for reading TIFF files produced via ScanImage. """ + from pathlib import Path from typing import Optional, Tuple, List, Iterable from warnings import warn diff --git a/src/roiextractors/extractors/tiffimagingextractors/tiffimagingextractor.py b/src/roiextractors/extractors/tiffimagingextractors/tiffimagingextractor.py index 1cd21cc7..9ae0a09d 100644 --- a/src/roiextractors/extractors/tiffimagingextractors/tiffimagingextractor.py +++ b/src/roiextractors/extractors/tiffimagingextractors/tiffimagingextractor.py @@ -5,6 +5,7 @@ TiffImagingExtractor A TIFF imaging extractor for TIFF files. """ + from pathlib import Path from typing import Optional from warnings import warn diff --git a/src/roiextractors/imagingextractor.py b/src/roiextractors/imagingextractor.py index a74503f7..44a1d39e 100644 --- a/src/roiextractors/imagingextractor.py +++ b/src/roiextractors/imagingextractor.py @@ -7,6 +7,7 @@ FrameSliceImagingExtractor Class to get a lazy frame slice. """ + from abc import ABC, abstractmethod from typing import Union, Optional, Tuple from copy import deepcopy diff --git a/src/roiextractors/multiimagingextractor.py b/src/roiextractors/multiimagingextractor.py index ddd6c6e0..a0a09bd4 100644 --- a/src/roiextractors/multiimagingextractor.py +++ b/src/roiextractors/multiimagingextractor.py @@ -5,6 +5,7 @@ MultiImagingExtractor This class is used to combine multiple ImagingExtractor objects by frames. """ + from collections import defaultdict from typing import Tuple, List, Iterable, Optional diff --git a/src/roiextractors/multisegmentationextractor.py b/src/roiextractors/multisegmentationextractor.py index 57706c5a..d4720552 100644 --- a/src/roiextractors/multisegmentationextractor.py +++ b/src/roiextractors/multisegmentationextractor.py @@ -5,6 +5,7 @@ MultiSegmentationExtractor This class is used to combine multiple SegmentationExtractor objects by frames. """ + import numpy as np from .segmentationextractor import SegmentationExtractor diff --git a/src/roiextractors/segmentationextractor.py b/src/roiextractors/segmentationextractor.py index e5d85dda..a1f310d3 100644 --- a/src/roiextractors/segmentationextractor.py +++ b/src/roiextractors/segmentationextractor.py @@ -9,6 +9,7 @@ FrameSliceSegmentationExtractor Class to get a lazy frame slice. """ + from abc import ABC, abstractmethod from typing import Union, Optional, Tuple, Iterable, List diff --git a/src/roiextractors/testing.py b/src/roiextractors/testing.py index 47d694d9..941881a4 100644 --- a/src/roiextractors/testing.py +++ b/src/roiextractors/testing.py @@ -1,4 +1,5 @@ """Testing utilities for the roiextractors package.""" + from collections.abc import Iterable from typing import Tuple, Optional From 4c75116f3bff79a08f7419fb42a61b2ceb49856f Mon Sep 17 00:00:00 2001 From: Ben Dichter Date: Thu, 1 Feb 2024 15:52:54 -0500 Subject: [PATCH 16/21] Fix HDF5 and NWB get_frames behavior (#174) * for HDF5: * fix get_frames. It was previously assuming contiguous frames * improve get_video. It was previously reading frame-by-frame, which is not optimal for HDF5 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added integer handling to default get_frames method * added squeeze logic to get_frames * specify axis for squeeze * inverted if so that squeeze occurs in the int section * removed np.newaxis so that bruker tests expect squeezing behavior on single frame * removed np.newaxis so that micromanager tests expect squeezing behavior on single frame * added squeeze logic to multiimaging extractor * reverted imagingextractor changes * reverted multiimagingextractor and testing.py changes * reverted test_brukertiffimagingextractor changes * reverted test_micromanagertiffimagingextractor changes * reverted test_brukertiffimagingextractor changes * added get_frames to hdf5imagingextractor * added test for non-cts frames * fixed nwb get_frames --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Heberto Mayorquin Co-authored-by: Paul Adkisson --- .../hdf5imagingextractor.py | 19 ++++++++----------- .../extractors/nwbextractors/nwbextractors.py | 18 +++++++----------- src/roiextractors/testing.py | 5 +++++ 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/roiextractors/extractors/hdf5imagingextractor/hdf5imagingextractor.py b/src/roiextractors/extractors/hdf5imagingextractor/hdf5imagingextractor.py index d56fa5e3..6f13d1da 100644 --- a/src/roiextractors/extractors/hdf5imagingextractor/hdf5imagingextractor.py +++ b/src/roiextractors/extractors/hdf5imagingextractor/hdf5imagingextractor.py @@ -122,25 +122,22 @@ def __del__(self): self._file.close() def get_frames(self, frame_idxs: ArrayType, channel: Optional[int] = 0): - # Fancy indexing is non performant for h5.py with long frame lists - if frame_idxs is not None: - slice_start = np.min(frame_idxs) - slice_stop = min(np.max(frame_idxs) + 1, self.get_num_frames()) - else: - slice_start = 0 - slice_stop = self.get_num_frames() - - frames = self._video.lazy_slice[slice_start:slice_stop, :, :, channel].dsetread() + squeeze_data = False if isinstance(frame_idxs, int): + squeeze_data = True + frame_idxs = [frame_idxs] + elif isinstance(frame_idxs, np.ndarray): + frame_idxs = frame_idxs.tolist() + frames = self._video.lazy_slice[frame_idxs, :, :, channel].dsetread() + if squeeze_data: frames = frames.squeeze() - return frames def get_video(self, start_frame=None, end_frame=None, channel: Optional[int] = 0) -> np.ndarray: return self._video.lazy_slice[start_frame:end_frame, :, :, channel].dsetread() def get_image_size(self) -> Tuple[int, int]: - return (self._num_rows, self._num_cols) + return self._num_rows, self._num_cols def get_num_frames(self): return self._num_frames diff --git a/src/roiextractors/extractors/nwbextractors/nwbextractors.py b/src/roiextractors/extractors/nwbextractors/nwbextractors.py index daf271a5..8f73285f 100644 --- a/src/roiextractors/extractors/nwbextractors/nwbextractors.py +++ b/src/roiextractors/extractors/nwbextractors/nwbextractors.py @@ -181,18 +181,14 @@ def make_nwb_metadata( ) def get_frames(self, frame_idxs: ArrayType, channel: Optional[int] = 0): - # Fancy indexing is non performant for h5.py with long frame lists - if frame_idxs is not None: - slice_start = np.min(frame_idxs) - slice_stop = min(np.max(frame_idxs) + 1, self.get_num_frames()) - else: - slice_start = 0 - slice_stop = self.get_num_frames() - - data = self.photon_series.data - frames = data[slice_start:slice_stop, ...].transpose([0, 2, 1]) - + squeeze_data = False if isinstance(frame_idxs, int): + squeeze_data = True + frame_idxs = [frame_idxs] + elif isinstance(frame_idxs, np.ndarray): + frame_idxs = frame_idxs.tolist() + frames = self.photon_series.data[frame_idxs].transpose([0, 2, 1]) + if squeeze_data: frames = frames.squeeze() return frames diff --git a/src/roiextractors/testing.py b/src/roiextractors/testing.py index 941881a4..d975e30d 100644 --- a/src/roiextractors/testing.py +++ b/src/roiextractors/testing.py @@ -406,6 +406,11 @@ def assert_get_frames_return_shape(imaging_extractor: ImagingExtractor): assert_msg = "get_frames does not work correctly with frame_idxs=np.arrray([0, 1])" assert frames_with_array.shape == (2, image_size[0], image_size[1]), assert_msg + frame_idxs = [0, 2] + frames_with_array = imaging_extractor.get_frames(frame_idxs=frame_idxs, channel=0) + assert_msg = "get_frames does not work correctly with frame_idxs=[0, 2]" + assert frames_with_array.shape == (2, image_size[0], image_size[1]), assert_msg + def check_imaging_return_types(img_ex: ImagingExtractor): """Check that the return types of the imaging extractor are correct.""" From c2e6554c954806925213a5c41ff15d5daea9376e Mon Sep 17 00:00:00 2001 From: Paul Adkisson Date: Mon, 5 Feb 2024 13:31:19 -0500 Subject: [PATCH 17/21] Update Readme (#280) * Update README.md * Update support list * Update README.md to mirror NeuroConv's format * add license to toc * removed developer guide * Update contribute.rst with developer guide info from the readme * Update supported formats to live table * specify ophys tab in support table link * rollback compatible.rst * rollback contribute.rst --- README.md | 167 +++++++++++++++--------------------------------------- 1 file changed, 45 insertions(+), 122 deletions(-) diff --git a/README.md b/README.md index 31e54759..d1f7b201 100644 --- a/README.md +++ b/README.md @@ -5,141 +5,64 @@ [![documentation](https://readthedocs.org/projects/roiextractors/badge/?version=latest)](https://roiextractors.readthedocs.io/en/latest/) [![License](https://img.shields.io/pypi/l/pynwb.svg)](https://github.com/catalystneuro/roiextractors/license.txt) -# ROI Extractors -Python-based module for extracting from, converting between, and handling recorded and optical imaging data from several file formats. Inspired by [SpikeExtractors](https://github.com/SpikeInterface/spikeextractors). - -Developed by [CatalystNeuro](http://catalystneuro.com/). - -## Getting Started: -#### Installation: -`pip install roiextractors` - -## Usage: -### Supported file types: -#### Imaging -1. HDF5 -2. TIFF -3. STK -4. FLI -5. SBX - -#### Segmentation -1. [calciumImagingAnalysis](https://github.com/bahanonu/calciumImagingAnalysis) (CNMF-E, EXTRACT) -2. [SIMA](http://www.losonczylab.org/sima/1.3.2/) -3. [NWB](https://pynwb.readthedocs.io/en/stable/) -4. [suite2p](https://github.com/MouseLand/suite2p) -45. Numpy (a data format for manual input of optical physiology data as various numpy datasets) - -#### Functionality: -Interconversion amongst the various data formats as well as conversion to the NWB format and back. - -#### Features: -1. SegmentationExtractor object: - * `seg_obj.get_channel_names()` : - List of optical channel names - * `seg_obj.get_num_channels()` : - Number of channels - * `seg_obj.get_movie_framesize()`: - (height, width) of raw movie - * `seg_obj.get_movie_location()`: - Location of storage of movie/tiff images - * `seg_obj.get_image_masks(self, roi_ids=None)`: - Image masks as (ht, wd, num_rois) with each value as the weight given during segmentation operation. - * `seg_obj.get_pixel_masks(roi_ids=None)`: - Get pixel masks as (total_pixels(ht*wid), no_rois) - * `seg_obj.get_traces(self, roi_ids=None, start_frame=None, end_frame=None)`: - df/F trace as (num_rois, num_frames) - * `seg_obj.get_sampling_frequency()`: - Sampling frequency of movie/df/F trace. - * `seg_obj.get_roi_locations()`: - Centroid pixel location of the ROI (Regions Of Interest) as (x,y). - * `seg_obj.get_num_rois()`: - Total number of ROIs after segmentation operation. - * `seg_obj.get_roi_ids()`: - Any integer tags associated with an ROI, defaults to `0:num_of_rois` - -#### SegmentationExtractor object creation: -```python -import roiextractors -import numpy as np - -seg_obj_cnmfe = roiextractors.CnmfeSegmentationExtractor('cnmfe_filename.mat') # cnmfe -seg_obj_extract = roiextractors.ExtractSegmentationExtractor('extract_filename.mat') # extract -seg_obj_sima = roiextractors.SimaSegmentationExtractor('sima_filename.sima') # SIMA -seg_obj_numpy = roiextractors.NumpySegmentationExtractor( - filepath = 'path-to-file', - masks=np.random.rand(movie_size[0],movie_size[1],no_rois), - signal=np.random.randn(num_rois,num_frames), - roi_idx=np.random.randint(no_rois,size=[1,no_rois]), - no_of_channels=None, - summary_image=None, - channel_names=['Blue'], -) # Numpy object -seg_obj_nwb = roiextractors.NwbSegmentationExtractor( - filepath_of_nwb, optical_channel_name=None, # optical channel to extract and store info from - imaging_plane_name=None, image_series_name=None, # imaging plane to extract and store data from - processing_module_name=None, - neuron_roi_response_series_name=None, # roi_response_series name to extract and store data from - background_roi_response_series_name=None) # nwb object -``` -#### Data format conversion: SegmentationExtractor to NWB: -```python -roiextractors.NwbSegmentationExtractor.write_segmentation(seg_obj, saveloc, - propertydict=[{'name': 'ROI feature 1, - 'description': 'additional attribute of each ROI', - 'data': np.random.rand(1,no_rois), - 'id': seg_obj.get_roi_ids()}, - {'name': 'ROI feature 2, - 'description': 'additional attribute of each ROI', - 'data': np.random.rand(1,no_rois), - 'id': seg_obj.get_roi_ids()}], - nwbfile_kwargs={'session_description': 'nwbfiledesc', - 'experimenter': 'experimenter name', - 'lab': 'test lab', - 'session_id': 'test sess id'}, - emission_lambda=400.0, excitation_lambda=500.0) -``` -## Example Datasets: -Example datasets are maintained at https://gin.g-node.org/CatalystNeuro/ophys_testing_data. - -To download test data on your machine, +# ROIExtractors +

+

Automatically read optical imaging/segmentation data into a common API

+

+

+ Explore our documentation » +

-1. Install the gin client (instructions [here](https://gin.g-node.org/G-Node/Info/wiki/GIN+CLI+Setup#linux)) -2. Use gin to download data. -```shell -gin get CatalystNeuro/ophys_testing_data -cd ophys_testing_data -gin get-content -``` + -3. Change the file at `roiextractors/tests/gin_test_config.json` to point to the path of this test data +## Table of Contents -To update data later, `cd` into the test directory and run `gin get-content` +- [About](#about) +- [Installation](#installation) +- [Documentation](#documentation) +- [Funding](#funding) +- [License](#license) +## About -## Class descriptions: +ROIExtractors provides a common API for various optical imaging and segmentation formats to streamline conversion and data analysis. ROI stands for Region Of Interest, which is the region in a set of acquired fluorescence images which the segmentation software has determined as a neuron. -* **SegmentationExtractor:** An abstract class that contains all the meta-data and output data from the ROI segmentation operation when applied to the pre-processed data. It also contains methods to read from and write to various data formats ouput from the processing pipelines like SIMA, CaImAn, Suite2p, CNNM-E. +Features: -* **NumpySegmentationExtractor:** Contains all data coming from a file format for which there is currently no support. To construct this, all data must be entered manually as arguments. +* Reads data from 10+ popular optical imaging and segmentation data formats into a common API. +* Extracts relevant metadata from each format. +* Provides a handy set of methods to analyze data such as `get_roi_locations()` -* **CnmfeSegmentationExtractor:** This class inherits from the SegmentationExtractor class, having all its funtionality specifically applied to the dataset output from the 'CNMF-E' ROI segmentation method. +## Installation -* **ExtractSegmentationExtractor:** This class inherits from the SegmentationExtractor class, having all its funtionality specifically applied to the dataset output from the 'EXTRACT' ROI segmentation method. +To install the latest stable release of **roiextractors** though PyPI, type: +```shell +pip install roiextractors +``` -* **SimaSegmentationExtractor:** This class inherits from the SegmentationExtractor class, having all its funtionality specifically applied to the dataset output from the 'SIMA' ROI segmentation method. +For more flexibility we recommend installing the latest version directly from GitHub. The following commands create an environment with all the required dependencies and the latest updates: -* **NwbSegmentationExtractor:** Extracts data from the NWB data format. Also implements a static method to write any format specific object to NWB. +```shell +git clone https://github.com/catalystneuro/roiextractors +cd roiextractors +conda env create roiextractors_env +conda activate roiextractors_env +pip install -e . +``` +Note that this will install the package in [editable mode](https://pip.pypa.io/en/stable/cli/pip_install/#editable-installs). -* **Suite2PSegmentationExtractor:** Extracts data from suite2p format. +Finally, if you prefer to avoid `conda` altogether, the following commands provide a clean installation within the current environment: +```shell +pip install git+https://github.com/catalystneuro/roiextractors.git@main +``` -## Troubleshooting -##### Installing SIMA with python>=3.7: -Will need a manual installation for package dependency **SIMA** since it does not currently support python 3.7: -1. Download SIMA wheels distribution [here](https://www.lfd.uci.edu/~gohlke/pythonlibs/#sima). -2. `pip install ` -3. `pip install roiextractors` +## Documentation +See our [ReadTheDocs page](https://roiextractors.readthedocs.io/en/latest/) for full documentation, including a gallery of all supported formats. -### Funded by +## Funding +ROIExtractors is funded by * Stanford University as part of the Ripple U19 project (U19NS104590). * LBNL as part of the NWB U24 (U24NS120057). + +## License +ROIExtractors is distributed under the BSD3 License. See [LICENSE](https://github.com/catalystneuro/roiextractors/blob/main/LICENSE.txt) for more information. From 6f1b504f3be8f3d9160a6d2a58693afd5007108c Mon Sep 17 00:00:00 2001 From: Paul Adkisson Date: Thu, 8 Feb 2024 18:20:36 -0500 Subject: [PATCH 18/21] Update Docs (#282) * Update README.md * Update support list * Update README.md to mirror NeuroConv's format * add license to toc * removed developer guide * Update contribute.rst with developer guide info from the readme * Update supported formats to live table * specify ophys tab in support table link * rollback README.md * updated conf to mirror neuroconvs * updated conf to mirror neuroconvs * removed old doc requirements * updated readthedocs yaml to match modern example file * added API docs to toc * rollback API docs * updated definition of roi * removed unneccessary indices and tables from home page --------- Co-authored-by: Cody Baker <51133164+CodyCBakerPhD@users.noreply.github.com> --- .readthedocs.yml | 15 ++--- docs/requirements_doc.txt | 16 ----- docs/source/compatible.rst | 23 +------- docs/source/conf.py | 117 ++++++++++++++++++++----------------- docs/source/contribute.rst | 33 ++++++++++- docs/source/index.rst | 13 +---- requirements-rtd.txt | 8 +++ 7 files changed, 115 insertions(+), 110 deletions(-) delete mode 100644 docs/requirements_doc.txt create mode 100644 requirements-rtd.txt diff --git a/.readthedocs.yml b/.readthedocs.yml index 619e29d1..50688d3a 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,12 +1,13 @@ +version: "2" + build: - image: latest + os: "ubuntu-22.04" + tools: + python: "3.10" -version: 2 +python: + install: + - requirements: requirements-rtd.txt sphinx: configuration: docs/source/conf.py - -python: - version: 3.8 - install: - - requirements: docs/requirements_doc.txt diff --git a/docs/requirements_doc.txt b/docs/requirements_doc.txt deleted file mode 100644 index 135cd2c2..00000000 --- a/docs/requirements_doc.txt +++ /dev/null @@ -1,16 +0,0 @@ -spikeextractors==0.9.0 -tqdm==4.48.2 -lazy_ops==0.2.0 -dill==0.3.2 -scipy==1.10.0 -PyYAML -h5py==2.9.0 -pynwb -nbsphinx -jupyter-sphinx -numpydoc -matplotlib -numpy -notebook -tifffile -git+https://github.com/catalystneuro/roiextractors diff --git a/docs/source/compatible.rst b/docs/source/compatible.rst index 80663ea3..225664fd 100644 --- a/docs/source/compatible.rst +++ b/docs/source/compatible.rst @@ -1,25 +1,8 @@ Supported formats ================= -Roiextractors supports various image formats obtained from different 2photon acquisition systems. -It also supports well known post processing cell extraction/segmentation pipelines. If you use any other format and would like to see it being supported we would love to know! (:doc:`Contact `) +The following is a live record of all the formats supported by ROIExtractors as well as other relevant ecosystem support. -Imaging -------- -1. HDF5 -2. TIFF -3. STK -4. FLI +.. raw:: html -Segmentation ------------- -#. `calciumImagingAnalysis `_ (CNMF-E, EXTRACT) -#. `Caiman `_ -#. `SIMA `_ -#. `NWB `_ -#. `suite2p `_ -#. Numpy (for any currently un-supported format) - -Example Datasets ----------------- -Example datasets for each fo the file formats can be downloaded `here `_ + diff --git a/docs/source/conf.py b/docs/source/conf.py index 36119d95..a26ddd1e 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,65 +1,72 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -import os import sys +from pathlib import Path -sys.path.insert(0, os.path.abspath(".")) - - -# -- Project information ----------------------------------------------------- +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) project = "RoiExtractors" copyright = "2021, Saksham Sharda" author = "Saksham Sharda" -# The full version, including alpha/beta/rc tags -release = "0.2.1" - - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = [] - -nbsphinx_execute_arguments = [ - "--InlineBackend.figure_formats={'svg', 'pdf'}", - "--InlineBackend.rc={'figure.dpi': 96}", +extensions = [ + "sphinx.ext.napoleon", # Support for NumPy and Google style docstrings + "sphinx.ext.autodoc", # Includes documentation from docstrings in docs/api + "sphinx.ext.autosummary", # Not clear. Please add if you know + "sphinx.ext.intersphinx", # Allows links to other sphinx project documentation sites + "sphinx_search.extension", # Allows for auto search function the documentation + "sphinx.ext.viewcode", # Shows source code in the documentation + "sphinx.ext.extlinks", # Allows to use shorter external links defined in the extlinks variable. ] -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -try: - import sphinx_rtd_theme - html_theme = "sphinx_rtd_theme" - html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] -except ImportError: - print("RTD theme not installed, using default") - html_theme = "alabaster" - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". +templates_path = ["_templates"] +master_doc = "index" +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] +html_theme = "pydata_sphinx_theme" html_static_path = ["_static"] + +html_context = { + # "github_url": "https://github.com", # or your GitHub Enterprise site + "github_user": "catalystneuro", + "github_repo": "roiextractors", + "github_version": "main", + "doc_path": "docs", +} + +linkcheck_anchors = False + +# -------------------------------------------------- +# Extension configuration +# -------------------------------------------------- + +# Napoleon +napoleon_google_docstring = False +napoleon_numpy_docstring = True +napoleon_use_param = False +napoleon_use_ivar = True +napoleon_include_init_with_doc = False +napoleon_include_private_with_doc = True +napoleon_include_special_with_doc = True + +# Autodoc +autoclass_content = "both" # Concatenates docstring of the class with that of its __init__ +autodoc_member_order = "bysource" # Displays classes and methods by their order in source code +autodata_content = "both" +autodoc_default_options = { + "members": True, + "member-order": "bysource", + "private-members": True, + "show-inheritance": False, + "toctree": True, +} +add_module_names = False + +# Intersphinx +intersphinx_mapping = { + "hdmf": ("https://hdmf.readthedocs.io/en/stable/", None), + "pynwb": ("https://pynwb.readthedocs.io/en/stable/", None), + "spikeinterface": ("https://spikeinterface.readthedocs.io/en/latest/", None), +} + +# To shorten external links +extlinks = { + "nwbinspector": ("https://nwbinspector.readthedocs.io/en/dev/%s", ""), +} diff --git a/docs/source/contribute.rst b/docs/source/contribute.rst index edcd1122..22adaa6d 100644 --- a/docs/source/contribute.rst +++ b/docs/source/contribute.rst @@ -1,7 +1,38 @@ Contribute: =========== -To contribute to Roiextractors to help us develop an api to handle a new data format for optophysiology: +Example Datasets +---------------- + +Example datasets are maintained at https://gin.g-node.org/CatalystNeuro/ophys_testing_data. + +To download test data on your machine, + +1. Install the gin client (instructions `here `_) +2. Use gin to download data: + + .. code-block:: bash + + gin get CatalystNeuro/ophys_testing_data + cd ophys_testing_data + gin get-content + +3. Change the file at ``roiextractors/tests/gin_test_config.json`` to point to the path of this test data + +To update data later, ``cd`` into the test directory and run ``gin get-content`` + +Troubleshooting +--------------- + +Installing SIMA with python>=3.7: +________________________________ +Will need a manual installation for package dependency **SIMA** since it does not currently support python 3.7: + +1. Download SIMA wheels distribution `here `_. +2. `pip install ` +3. `pip install roiextractors` + +More details on how to construct individual extractors can be found here: .. toctree:: :maxdepth: 1 diff --git a/docs/source/index.rst b/docs/source/index.rst index dc4bd2e0..82f72a0b 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -10,7 +10,7 @@ Welcome to RoiExtractors's documentation! Roiextractors is a library that helps in analyzing, visualizing and interacting with optical physiology data acquired from various acquisition systems. **ROI** - Stands for Region Of Interest, which is the region in a set of acquired fluorescence images which the segmentation software has determined as a neuron. + Stands for Region Of Interest, which is the set of pixels from acquired fluorescence images which the segmentation software has determined to follow a particular cellular structure. With this package, a user can: @@ -20,9 +20,7 @@ With this package, a user can: .. toctree:: :maxdepth: 2 - :caption: Contents: - :glob: - :numbered: + :caption: Contents gettingstarted compatible @@ -31,10 +29,3 @@ With this package, a user can: contribute licence contact - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/requirements-rtd.txt b/requirements-rtd.txt new file mode 100644 index 00000000..9fdd2959 --- /dev/null +++ b/requirements-rtd.txt @@ -0,0 +1,8 @@ +Jinja2 +Sphinx +sphinx_rtd_theme +readthedocs-sphinx-search +sphinx-toggleprompt +sphinx-copybutton +roiextractors +pydata_sphinx_theme From 87571d537870ca8b4f5305c1cbbc6427869de407 Mon Sep 17 00:00:00 2001 From: Paul Adkisson Date: Fri, 9 Feb 2024 11:49:30 -0500 Subject: [PATCH 19/21] removed unknown references (SBK and FLI) and added link to neuroconv (#283) --- docs/source/contribute.rst | 2 +- docs/source/index.rst | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/source/contribute.rst b/docs/source/contribute.rst index 22adaa6d..c29af60a 100644 --- a/docs/source/contribute.rst +++ b/docs/source/contribute.rst @@ -1,4 +1,4 @@ -Contribute: +Contribute =========== Example Datasets diff --git a/docs/source/index.rst b/docs/source/index.rst index 82f72a0b..50e9b7eb 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -14,9 +14,13 @@ Roiextractors is a library that helps in analyzing, visualizing and interacting With this package, a user can: -- Work with imaging data in formats like: TIFF, HDF5, STK, FLI. +- Work with imaging data in formats like: ScanImage TIFF, HDF5, Miniscope, Scanbox and more. - Work with post-processed data (after application of cell extraction/segmentation) output from various commonly used cell extraction/segmentation packages like Suite2p, CNMF-E, Caiman, SIMA. -- Save all this data into NWB format and share it with the community! +- Leverage a common API to streamline analysis and visualization of data from different acquisition systems and cell extraction/segmentation pipelines. + +.. seealso:: + + If you want to write data to NWB, you can check out our primary dependent: `NeuroConv `_. .. toctree:: :maxdepth: 2 From 8d7930446958e14fac56a67955c8fa9ffad9cdc7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 10:53:37 -0500 Subject: [PATCH 20/21] [pre-commit.ci] pre-commit autoupdate (#284) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 24.1.1 → 24.2.0](https://github.com/psf/black/compare/24.1.1...24.2.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4818cc7e..1a0c8fb1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/psf/black - rev: 24.1.1 + rev: 24.2.0 hooks: - id: black exclude: ^docs/ From 87231491552187c63a6a5938a7c3704fce1084d6 Mon Sep 17 00:00:00 2001 From: Paul Adkisson Date: Wed, 14 Feb 2024 22:59:45 -0500 Subject: [PATCH 21/21] Fix bug report versions (#278) * version as string to preserve trailing zeros. * changed code of conduct and bug report check to dropdown style instead of checkboxes * commit suggestion Co-authored-by: Cody Baker <51133164+CodyCBakerPhD@users.noreply.github.com> --------- Co-authored-by: Cody Baker <51133164+CodyCBakerPhD@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/bug_report.yml | 33 +++++++++++++++++---------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index e402ce61..c93809f6 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -60,11 +60,11 @@ body: attributes: label: Python Version options: - - 3.8 - - 3.9 - - 3.10 - - 3.11 - - 3.12 + - "3.8" + - "3.9" + - "3.10" + - "3.11" + - "3.12" validations: required: true - type: textarea @@ -78,13 +78,22 @@ body: You can attach images or log files by clicking this area to highlight it and then dragging files in. If GitHub upload is not working, you can also copy and paste the output into this section. - - type: checkboxes - id: terms + - type: dropdown + id: code_of_conduct attributes: label: Code of Conduct - description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/catalystneuro/roiextractors/blob/master/.github/CODE_OF_CONDUCT.rst) + description: Do you agree to follow our [Code of Conduct](https://github.com/catalystneuro/roiextractors/blob/master/.github/CODE_OF_CONDUCT.rst)? + options: + - "Yes" + validations: + required: true + - type: dropdown + id: duplicated_issue_check + attributes: + label: Duplicated Issue Check + description: Have you ensured this bug was not already [reported](https://github.com/catalystneuro/roiextractors/issues)? options: - - label: I agree to follow this project's [Code of Conduct](https://github.com/catalystneuro/roiextractors/blob/master/.github/CODE_OF_CONDUCT.rst) - required: true - - label: Have you ensured this bug was not already [reported](https://github.com/catalystneuro/roiextractors/issues)? - required: true + - "No" + - "Yes" + validations: + required: true