Skip to content
Snippets Groups Projects
Commit ebc8ab67 authored by Christian Kento Rasmussen's avatar Christian Kento Rasmussen
Browse files

refactored convert class to same format as load and save

parent 85f3dfaa
No related branches found
No related tags found
4 merge requests!102Conv zarr tiff folders,!100Conv zarr nifti,!99Zarr cli,!96Zarr loading and converting
import difflib
import os
from itertools import product from itertools import product
import numpy as np import numpy as np
...@@ -5,8 +7,51 @@ import tifffile as tiff ...@@ -5,8 +7,51 @@ import tifffile as tiff
import zarr import zarr
from tqdm import tqdm from tqdm import tqdm
from qim3d.utils.internal_tools import stringify_path
def convert_tif_to_zarr(tif_path, zarr_path, chunks=(64, 64, 64)):
class Convert:
def __init__(self,**kwargs):
""" Utility class to convert files to other formats without loading the entire file into memory
Args:
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))
def convert(self, input_path, output_path):
# Stringify path in case it is not already a string
input_path = stringify_path(input_path)
if os.path.isfile(input_path) and os.path.isfile(output_path):
match input_path, output_path:
case (".tif", ".zarr"):
return self.convert_tif_to_zarr(input_path, output_path)
case (".npy", ".zarr"):
return self.convert_npy_to_zarr(input_path, output_path, shape=(64, 64, 64))
case (".zarr", ".tif"):
return self.convert_zarr_to_tif(input_path, output_path)
case _:
raise ValueError("Unsupported file format")
# Load a directory
elif os.path.isdir(input_path):
raise ValueError("Unsupported file format")
# Fail
else:
# Find the closest matching path to warn the user
parent_dir = os.path.dirname(input_path) or "."
parent_files = os.listdir(parent_dir) if os.path.isdir(parent_dir) else ""
valid_paths = [os.path.join(parent_dir, file) for file in parent_files]
similar_paths = difflib.get_close_matches(input_path, valid_paths)
if similar_paths:
suggestion = similar_paths[0] # Get the closest match
message = f"Invalid path. Did you mean '{suggestion}'?"
raise ValueError(repr(message))
else:
raise ValueError("Invalid path")
def convert_tif_to_zarr(self, tif_path, zarr_path, chunks=(64, 64, 64)):
""" Convert a tiff file to a zarr file """ Convert a tiff file to a zarr file
Args: Args:
...@@ -20,6 +65,7 @@ def convert_tif_to_zarr(tif_path, zarr_path, chunks=(64, 64, 64)): ...@@ -20,6 +65,7 @@ def convert_tif_to_zarr(tif_path, zarr_path, chunks=(64, 64, 64)):
vol = tiff.memmap(tif_path) vol = tiff.memmap(tif_path)
z = zarr.open(zarr_path, mode='w', shape=vol.shape, chunks=chunks, dtype=vol.dtype) z = zarr.open(zarr_path, mode='w', shape=vol.shape, chunks=chunks, dtype=vol.dtype)
chunk_shape = tuple((s + c - 1) // c for s, c in zip(z.shape, z.chunks)) 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)): 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)) slices = tuple(slice(c * i, min(c * (i + 1), s))
for s, c, i in zip(z.shape, z.chunks, chunk_indices)) for s, c, i in zip(z.shape, z.chunks, chunk_indices))
...@@ -29,7 +75,7 @@ def convert_tif_to_zarr(tif_path, zarr_path, chunks=(64, 64, 64)): ...@@ -29,7 +75,7 @@ def convert_tif_to_zarr(tif_path, zarr_path, chunks=(64, 64, 64)):
return z return z
def convert_npy_to_zarr(npy_path, zarr_path, shape, dtype=np.float32, chunks=(64, 64, 64)): def convert_npy_to_zarr(self, npy_path, zarr_path, shape, dtype=np.float32, chunks=(64, 64, 64)):
""" Convert a numpy file to a zarr file """ Convert a numpy file to a zarr file
Args: Args:
...@@ -46,7 +92,7 @@ def convert_npy_to_zarr(npy_path, zarr_path, shape, dtype=np.float32, chunks=(64 ...@@ -46,7 +92,7 @@ def convert_npy_to_zarr(npy_path, zarr_path, shape, dtype=np.float32, chunks=(64
return z return z
def convert_zarr_to_tif(zarr_path, tif_path): def convert_zarr_to_tif(self, zarr_path, tif_path):
""" Convert a zarr file to a tiff file """ Convert a zarr file to a tiff file
Args: Args:
...@@ -58,3 +104,16 @@ def convert_zarr_to_tif(zarr_path, tif_path): ...@@ -58,3 +104,16 @@ def convert_zarr_to_tif(zarr_path, tif_path):
""" """
z = zarr.open(zarr_path) z = zarr.open(zarr_path)
tiff.imwrite(tif_path, z) tiff.imwrite(tif_path, z)
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
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).
"""
converter = Convert(chunk_shape=chunk_shape)
converter.convert(input_path, output_path)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment