diff --git a/qim3d/io/convert.py b/qim3d/io/convert.py index f2af9e6b4f201621bf55190247bc8ac6d90a1038..a1cfd9aed8d36fd4b679940449fcba5845c881ba 100644 --- a/qim3d/io/convert.py +++ b/qim3d/io/convert.py @@ -10,6 +10,7 @@ from tqdm import tqdm from qim3d.utils.internal_tools import stringify_path from qim3d.io.saving import save +from qim3d.io.loading import load class Convert: @@ -24,10 +25,11 @@ class Convert: def convert(self, input_path, output_path): def get_file_extension(file_path): root, ext = os.path.splitext(file_path) - if ext in ['.gz', '.bz2', '.xz']: # handle common compressed extensions + if ext in [".gz", ".bz2", ".xz"]: # handle common compressed extensions root, ext2 = os.path.splitext(root) ext = ext2 + ext return ext + # Stringify path in case it is not already a string input_path = stringify_path(input_path) input_ext = get_file_extension(input_path) @@ -67,20 +69,13 @@ class Convert: else: raise ValueError("Invalid path") - def convert_tif_to_zarr(self, tif_path, zarr_path): - """Convert a tiff file to a zarr file - - Args: - tif_path (str): path to the tiff file - zarr_path (str): path to the zarr file - chunks (tuple, optional): chunk size for the zarr file. Defaults to (64, 64, 64). - - Returns: - zarr.core.Array: zarr array containing the data from the tiff file - """ - vol = tiff.memmap(tif_path) + def _save_zarr(self, zarr_path, vol): z = zarr.open( - zarr_path, mode="w", shape=vol.shape, chunks=self.chunk_shape, dtype=vol.dtype + 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 @@ -97,6 +92,20 @@ class Convert: return z + def convert_tif_to_zarr(self, tif_path, zarr_path): + """Convert a tiff file to a zarr file + + Args: + tif_path (str): path to the tiff file + zarr_path (str): path to the zarr file + chunks (tuple, optional): chunk size for the zarr file. Defaults to (64, 64, 64). + + Returns: + zarr.core.Array: zarr array containing the data from the tiff file + """ + vol = tiff.memmap(tif_path) + return self._save_zarr(zarr_path, vol) + def convert_zarr_to_tif(self, zarr_path, tif_path): """Convert a zarr file to a tiff file @@ -110,6 +119,33 @@ class Convert: z = zarr.open(zarr_path) save(tif_path, z) + def convert_tiff_stack_to_zarr(self, tiff_stack_path, zarr_path): + """Convert a tiff stack to a zarr file + + Args: + tiff_stack_path (str): path to the tiff stack + zarr_path (str): path to the zarr file + + Returns: + zarr.core.Array: zarr array containing the data from the tiff stack + """ + # ! 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) + return self._save_zarr(zarr_path, vol) + + def convert_zarr_to_tiff_stack(self, zarr_path, tiff_stack_path): + """Convert a zarr file to a tiff stack + + Args: + zarr_path (str): path to the zarr file + tiff_stack_path (str): path to the tiff stack + + Returns: + None + """ + z = zarr.open(zarr_path) + save(tiff_stack_path, z) + def convert_nifti_to_zarr(self, nifti_path, zarr_path): """Convert a nifti file to a zarr file @@ -121,23 +157,7 @@ class Convert: zarr.core.Array: zarr array containing the data from the nifti file """ vol = nib.load(nifti_path).dataobj - 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 + return self._save_zarr(zarr_path, vol) def convert_zarr_to_nifti(self, zarr_path, nifti_path, compression=False): """Convert a zarr file to a nifti file @@ -151,7 +171,7 @@ class Convert: """ z = zarr.open(zarr_path) save(nifti_path, z, compression=compression) - + def convert(input_path: str, output_path: str, chunk_shape: tuple = (64, 64, 64)): """Convert a file to another format without loading the entire file into memory