From 39d362a80b9945a93c969c95db54437fc1d1cfd2 Mon Sep 17 00:00:00 2001 From: Christian Kento Rasmussen <christian.kento@gmail.com> Date: Mon, 13 Jan 2025 13:26:58 +0100 Subject: [PATCH] Add basename and contains arguments to convert function for TIFF stack processing --- qim3d/cli/__init__.py | 20 +++++++++++++++++++- qim3d/io/_convert.py | 29 ++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/qim3d/cli/__init__.py b/qim3d/cli/__init__.py index cec79d57..1bf9a658 100644 --- a/qim3d/cli/__init__.py +++ b/qim3d/cli/__init__.py @@ -124,6 +124,20 @@ def main(): default=(64, 64, 64), help="Chunk size for the zarr file. Defaults to (64, 64, 64).", ) + convert_parser.add_argument( + "--basename", + type=str, + metavar="basename", + default="tiff_stack", + help="The base name for the saving of a tiff stack.", + ) + convert_parser.add_argument( + "--contains", + type=str, + metavar="contains", + default=None, + help="Specify common part of file names for tiff stack.", + ) args = parser.parse_args() if args.subcommand == "gui": @@ -193,7 +207,11 @@ def main(): elif args.subcommand == "convert": - qim3d.io.convert(args.input_path, args.output_path, chunk_shape=args.chunks) + qim3d.io.convert(args.input_path, + args.output_path, + chunk_shape=args.chunks, + basename=args.basename, + contains=args.contains) elif args.subcommand is None: print(QIM_TITLE) diff --git a/qim3d/io/_convert.py b/qim3d/io/_convert.py index b7124a52..c02776bf 100644 --- a/qim3d/io/_convert.py +++ b/qim3d/io/_convert.py @@ -21,6 +21,8 @@ class Convert: chunk_shape (tuple, optional): chunk size for the zarr file. Defaults to (64, 64, 64). """ self.chunk_shape = kwargs.get("chunk_shape", (64, 64, 64)) + self.base_name = kwargs.get("basename", "tiff_stack") + self.contains = kwargs.get("contains", None) def convert(self, input_path: str, output_path: str): def get_file_extension(file_path): @@ -115,7 +117,7 @@ class Convert: z = zarr.open(zarr_path) save(tif_path, z) - def convert_zarr_to_tiff_stack(self, zarr_path, tiff_stack_path): + def convert_zarr_to_tiff_stack(self, zarr_path: str, tiff_stack_path: str): """Convert a zarr file to a tiff stack Args: @@ -128,7 +130,7 @@ class Convert: z = zarr.open(zarr_path) save(tiff_stack_path, z, basename=self.base_name) - def convert_tiff_stack_to_zarr(self, tiff_stack_path, zarr_path): + def convert_tiff_stack_to_zarr(self, tiff_stack_path: str, zarr_path: str): """Convert a tiff stack to a zarr file Args: @@ -140,7 +142,23 @@ class Convert: """ # ! tiff stack memmap is stored as slices on disk and not as a single file, making assignments to blocks slow. vol = load(tiff_stack_path, virtual_stack=True, contains=self.contains) - return self._save_zarr(zarr_path, vol) + z = zarr.open( + zarr_path, mode="w", shape=vol.shape, chunks=self.chunk_shape, dtype=vol.dtype + ) + chunk_shape = tuple((s + c - 1) // c for s, c in zip(z.shape, z.chunks)) + # ! Fastest way is z[:] = vol[:], but does not have a progress bar + for chunk_indices in tqdm( + product(*[range(n) for n in chunk_shape]), total=np.prod(chunk_shape) + ): + slices = tuple( + slice(c * i, min(c * (i + 1), s)) + for s, c, i in zip(z.shape, z.chunks, chunk_indices) + ) + temp_data = vol[slices] + # The assignment takes 99% of the cpu-time + z.blocks[chunk_indices] = temp_data + + return z def convert_nifti_to_zarr(self, nifti_path: str, zarr_path: str) -> zarr.core.Array: """Convert a nifti file to a zarr file @@ -185,13 +203,14 @@ class Convert: save(nifti_path, z, compression=compression) -def convert(input_path: str, output_path: str, chunk_shape: tuple = (64, 64, 64)) -> None: +def convert(input_path: str, output_path: str, chunk_shape: tuple = (64, 64, 64), basename: str = 'tiff_stack', contains: str = None) -> None: """Convert a file to another format without loading the entire file into memory Args: input_path (str): path to the input file output_path (str): path to the output file chunk_shape (tuple, optional): chunk size for the zarr file. Defaults to (64, 64, 64). + basename (str, optional): base name for the saving of a tiff stack. Defaults to 'tiff_stack'. """ - converter = Convert(chunk_shape=chunk_shape) + converter = Convert(chunk_shape=chunk_shape, basename=basename, contains=contains) converter.convert(input_path, output_path) -- GitLab