From b07f0ade4ab35a6bbcbbd95e096f6197406849dd Mon Sep 17 00:00:00 2001 From: Eduardo Hirata-Miyasaki Date: Wed, 7 Aug 2024 22:23:30 -0700 Subject: [PATCH 1/6] initial commit adding resolution --- examples/configs/fit_example.yml | 3 ++- examples/configs/predict_example.yml | 1 + examples/configs/test_example.yml | 1 + viscy/data/hcs.py | 14 ++++++++++++-- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/examples/configs/fit_example.yml b/examples/configs/fit_example.yml index 85ff4c67c..7e8e0e7f0 100644 --- a/examples/configs/fit_example.yml +++ b/examples/configs/fit_example.yml @@ -37,6 +37,7 @@ data: batch_size: 32 num_workers: 16 yx_patch_size: [256, 256] + pyramid_resolution: 0 normalizations: - class_path: viscy.transforms.NormalizeSampled init_args: @@ -87,4 +88,4 @@ data: sigma_z: [0.25, 1.5] sigma_y: [0.25, 1.5] sigma_x: [0.25, 1.5] - caching: false \ No newline at end of file + caching: false diff --git a/examples/configs/predict_example.yml b/examples/configs/predict_example.yml index b25561396..64bf8c017 100644 --- a/examples/configs/predict_example.yml +++ b/examples/configs/predict_example.yml @@ -63,5 +63,6 @@ predict: - 256 caching: false predict_scale_source: null + pyramid_resolution: 0 return_predictions: false ckpt_path: null diff --git a/examples/configs/test_example.yml b/examples/configs/test_example.yml index 6c7130a27..6fd4a4a38 100644 --- a/examples/configs/test_example.yml +++ b/examples/configs/test_example.yml @@ -62,5 +62,6 @@ data: - 256 caching: false ground_truth_masks: null + pyramid_resolution: 0 ckpt_path: null verbose: true diff --git a/viscy/data/hcs.py b/viscy/data/hcs.py index e8ba12fa0..2b1634337 100644 --- a/viscy/data/hcs.py +++ b/viscy/data/hcs.py @@ -104,6 +104,8 @@ class SlidingWindowDataset(Dataset): :param ChannelMap channels: source and target channel names, e.g. ``{'source': 'Phase', 'target': ['Nuclei', 'Membrane']}`` :param int z_window_size: Z window size of the 2.5D U-Net, 1 for 2D + :param int pyramid_resolution: pyramid level. + defaults to 0 (full resolution) :param DictTransform | None transform: a callable that transforms data, defaults to None """ @@ -113,16 +115,21 @@ def __init__( positions: list[Position], channels: ChannelMap, z_window_size: int, + pyramid_resolution: int = 0, transform: DictTransform | None = None, ) -> None: super().__init__() self.positions = positions self.channels = {k: _ensure_channel_list(v) for k, v in channels.items()} self.source_ch_idx = [ - positions[0].get_channel_index(c) for c in channels["source"] + positions[pyramid_resolution].get_channel_index(c) + for c in channels["source"] ] self.target_ch_idx = ( - [positions[0].get_channel_index(c) for c in channels["target"]] + [ + positions[pyramid_resolution].get_channel_index(c) + for c in channels["target"] + ] if "target" in channels else None ) @@ -301,6 +308,8 @@ class HCSDataModule(LightningDataModule): :param Path | None ground_truth_masks: path to the ground truth masks, used in the test stage to compute segmentation metrics, defaults to None + :param int pyramid_resolution: pyramid resolution level. + defaults to 0 (full resolution) """ def __init__( @@ -318,6 +327,7 @@ def __init__( augmentations: list[MapTransform] = [], caching: bool = False, ground_truth_masks: Path | None = None, + pyramid_resolution: int = 0, ): super().__init__() self.data_path = Path(data_path) From 8a137d4ca9a90133336079478f0b2f570f4c10c9 Mon Sep 17 00:00:00 2001 From: Eduardo Hirata-Miyasaki Date: Wed, 14 Aug 2024 17:18:40 -0700 Subject: [PATCH 2/6] added the pyramid option to the slidingwindow --- viscy/data/hcs.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/viscy/data/hcs.py b/viscy/data/hcs.py index 2b1634337..262714386 100644 --- a/viscy/data/hcs.py +++ b/viscy/data/hcs.py @@ -115,26 +115,23 @@ def __init__( positions: list[Position], channels: ChannelMap, z_window_size: int, - pyramid_resolution: int = 0, + pyramid_resolution: str = "0", transform: DictTransform | None = None, ) -> None: super().__init__() self.positions = positions self.channels = {k: _ensure_channel_list(v) for k, v in channels.items()} self.source_ch_idx = [ - positions[pyramid_resolution].get_channel_index(c) - for c in channels["source"] + positions[0].get_channel_index(c) for c in channels["source"] ] self.target_ch_idx = ( - [ - positions[pyramid_resolution].get_channel_index(c) - for c in channels["target"] - ] + [positions[0].get_channel_index(c) for c in channels["target"]] if "target" in channels else None ) self.z_window_size = z_window_size self.transform = transform + self.pyramid_resolution = pyramid_resolution self._get_windows() def _get_windows(self) -> None: @@ -145,7 +142,7 @@ def _get_windows(self) -> None: self.window_arrays = [] self.window_norm_meta: list[NormMeta | None] = [] for fov in self.positions: - img_arr: ImageArray = fov["0"] + img_arr: ImageArray = fov[str(self.pyramid_resolution)] ts = img_arr.frames zs = img_arr.slices - self.z_window_size + 1 w += ts * zs @@ -226,7 +223,7 @@ def __getitem__(self, index: int) -> Sample: sample = { "index": sample_index, "source": self._stack_channels(sample_images, "source"), - "norm_meta": norm_meta, + # "norm_meta": norm_meta, } if self.target_ch_idx is not None: sample["target"] = self._stack_channels(sample_images, "target") @@ -327,7 +324,7 @@ def __init__( augmentations: list[MapTransform] = [], caching: bool = False, ground_truth_masks: Path | None = None, - pyramid_resolution: int = 0, + pyramid_resolution: str = "0", ): super().__init__() self.data_path = Path(data_path) @@ -344,6 +341,7 @@ def __init__( self.caching = caching self.ground_truth_masks = ground_truth_masks self.prepare_data_per_node = True + self.pyramid_resolution = pyramid_resolution @property def cache_path(self): @@ -400,6 +398,7 @@ def _base_dataset_settings(self) -> dict[str, dict[str, list[str]] | int]: return { "channels": {"source": self.source_channel}, "z_window_size": self.z_window_size, + "pyramid_resolution": self.pyramid_resolution, } def setup(self, stage: Literal["fit", "validate", "test", "predict"]): From 0ff15abd1d59a12c93bfdd19b57194c623ea64ab Mon Sep 17 00:00:00 2001 From: Eduardo Hirata-Miyasaki Date: Wed, 14 Aug 2024 22:36:32 -0700 Subject: [PATCH 3/6] pyramid as string --- examples/configs/fit_example.yml | 2 +- examples/configs/predict_example.yml | 2 +- examples/configs/test_example.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/configs/fit_example.yml b/examples/configs/fit_example.yml index 7e8e0e7f0..58bf263cb 100644 --- a/examples/configs/fit_example.yml +++ b/examples/configs/fit_example.yml @@ -37,7 +37,7 @@ data: batch_size: 32 num_workers: 16 yx_patch_size: [256, 256] - pyramid_resolution: 0 + pyramid_resolution: "0" normalizations: - class_path: viscy.transforms.NormalizeSampled init_args: diff --git a/examples/configs/predict_example.yml b/examples/configs/predict_example.yml index 64bf8c017..aaa69628f 100644 --- a/examples/configs/predict_example.yml +++ b/examples/configs/predict_example.yml @@ -63,6 +63,6 @@ predict: - 256 caching: false predict_scale_source: null - pyramid_resolution: 0 + pyramid_resolution: "0" return_predictions: false ckpt_path: null diff --git a/examples/configs/test_example.yml b/examples/configs/test_example.yml index 6fd4a4a38..9dd0b8722 100644 --- a/examples/configs/test_example.yml +++ b/examples/configs/test_example.yml @@ -62,6 +62,6 @@ data: - 256 caching: false ground_truth_masks: null - pyramid_resolution: 0 + pyramid_resolution: "0" ckpt_path: null verbose: true From dd78377ed6c4aaf95d47ff37c106e10311703376 Mon Sep 17 00:00:00 2001 From: Eduardo Hirata-Miyasaki Date: Thu, 15 Aug 2024 15:22:09 -0700 Subject: [PATCH 4/6] updated type hint --- viscy/data/hcs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/viscy/data/hcs.py b/viscy/data/hcs.py index 262714386..170814087 100644 --- a/viscy/data/hcs.py +++ b/viscy/data/hcs.py @@ -104,7 +104,7 @@ class SlidingWindowDataset(Dataset): :param ChannelMap channels: source and target channel names, e.g. ``{'source': 'Phase', 'target': ['Nuclei', 'Membrane']}`` :param int z_window_size: Z window size of the 2.5D U-Net, 1 for 2D - :param int pyramid_resolution: pyramid level. + :param str pyramid_resolution: pyramid level. defaults to 0 (full resolution) :param DictTransform | None transform: a callable that transforms data, defaults to None @@ -305,7 +305,7 @@ class HCSDataModule(LightningDataModule): :param Path | None ground_truth_masks: path to the ground truth masks, used in the test stage to compute segmentation metrics, defaults to None - :param int pyramid_resolution: pyramid resolution level. + :param str pyramid_resolution: pyramid resolution level. defaults to 0 (full resolution) """ From e12068010664208d2d7b7abbcefbeb488fbfe148 Mon Sep 17 00:00:00 2001 From: Ziwen Liu <67518483+ziw-liu@users.noreply.github.com> Date: Fri, 28 Mar 2025 09:55:00 -0700 Subject: [PATCH 5/6] fix example type in docstring --- viscy/data/hcs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/viscy/data/hcs.py b/viscy/data/hcs.py index 170814087..86a457c9e 100644 --- a/viscy/data/hcs.py +++ b/viscy/data/hcs.py @@ -105,7 +105,7 @@ class SlidingWindowDataset(Dataset): e.g. ``{'source': 'Phase', 'target': ['Nuclei', 'Membrane']}`` :param int z_window_size: Z window size of the 2.5D U-Net, 1 for 2D :param str pyramid_resolution: pyramid level. - defaults to 0 (full resolution) + defaults to "0" (full resolution) :param DictTransform | None transform: a callable that transforms data, defaults to None """ From 68e9ccdfb209d7c29e4ae5dbbdd3f18eeb10506f Mon Sep 17 00:00:00 2001 From: Eduardo Hirata-Miyasaki Date: Tue, 3 Jun 2025 10:57:55 -0700 Subject: [PATCH 6/6] matching naming conventions to mmap_cache.py --- viscy/data/hcs.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/viscy/data/hcs.py b/viscy/data/hcs.py index add08f362..2df62a228 100644 --- a/viscy/data/hcs.py +++ b/viscy/data/hcs.py @@ -104,10 +104,12 @@ class SlidingWindowDataset(Dataset): :param ChannelMap channels: source and target channel names, e.g. ``{'source': 'Phase', 'target': ['Nuclei', 'Membrane']}`` :param int z_window_size: Z window size of the 2.5D U-Net, 1 for 2D - :param str pyramid_resolution: pyramid level. - defaults to "0" (full resolution) + :param str array_key: + Name of the image arrays (multiscales level), by default "0" :param DictTransform | None transform: a callable that transforms data, defaults to None + :param bool load_normalization_metadata: + whether to load normalization metadata, defaults to True """ def __init__( @@ -115,8 +117,9 @@ def __init__( positions: list[Position], channels: ChannelMap, z_window_size: int, - pyramid_resolution: str = "0", + array_key: str = "0", transform: DictTransform | None = None, + load_normalization_metadata: bool = True, ) -> None: super().__init__() self.positions = positions @@ -131,8 +134,9 @@ def __init__( ) self.z_window_size = z_window_size self.transform = transform - self.pyramid_resolution = pyramid_resolution + self.array_key = array_key self._get_windows() + self.load_normalization_metadata = load_normalization_metadata def _get_windows(self) -> None: """Count the sliding windows along T and Z, @@ -142,7 +146,7 @@ def _get_windows(self) -> None: self.window_arrays = [] self.window_norm_meta: list[NormMeta | None] = [] for fov in self.positions: - img_arr: ImageArray = fov[str(self.pyramid_resolution)] + img_arr: ImageArray = fov[str(self.array_key)] ts = img_arr.frames zs = img_arr.slices - self.z_window_size + 1 if zs < 1: @@ -229,10 +233,11 @@ def __getitem__(self, index: int) -> Sample: sample = { "index": sample_index, "source": self._stack_channels(sample_images, "source"), - # "norm_meta": norm_meta, } if self.target_ch_idx is not None: sample["target"] = self._stack_channels(sample_images, "target") + if self.load_normalization_metadata: + sample["norm_meta"] = norm_meta return sample @@ -330,8 +335,8 @@ class HCSDataModule(LightningDataModule): prefetch_factor : int or None, optional Number of samples loaded in advance by each worker during fitting, defaults to None (2 per PyTorch default). - :param str pyramid_resolution: pyramid resolution level. - defaults to 0 (full resolution) + array_key : str, optional + Name of the image arrays (multiscales level), by default "0" """ def __init__( @@ -351,7 +356,7 @@ def __init__( ground_truth_masks: Path | None = None, persistent_workers=False, prefetch_factor=None, - pyramid_resolution: str = "0", + array_key: str = "0", ): super().__init__() self.data_path = Path(data_path) @@ -370,7 +375,7 @@ def __init__( self.prepare_data_per_node = True self.persistent_workers = persistent_workers self.prefetch_factor = prefetch_factor - self.pyramid_resolution = pyramid_resolution + self.array_key = array_key @property def cache_path(self): @@ -427,7 +432,7 @@ def _base_dataset_settings(self) -> dict[str, dict[str, list[str]] | int]: return { "channels": {"source": self.source_channel}, "z_window_size": self.z_window_size, - "pyramid_resolution": self.pyramid_resolution, + "array_key": self.array_key, } def setup(self, stage: Literal["fit", "validate", "test", "predict"]):