Module qute.transforms.io
Input/output transforms.
Classes
class CellposeLabelReader (to_int32: bool = True)
-
Loads a Cellpose label file and returns it as a NumPy array.
Constructor
Parameters
to_int32
:bool
Set to True to convert to np.int32.
Returns
labels
:np.ndarray
- Labels array.
Expand source code
class CellposeLabelReader(Transform): """Loads a Cellpose label file and returns it as a NumPy array.""" def __init__(self, to_int32: bool = True) -> None: """Constructor Parameters ---------- to_int32: bool Set to True to convert to np.int32. Returns ------- labels: np.ndarray Labels array. """ super().__init__() self.to_int32 = to_int32 def __call__(self, file_name: Union[Path, str]) -> np.ndarray: """ Load the file and return the labels tensor. Parameters ---------- file_name: str File name Returns ------- labels: ndarray The labels array from the CellPose labels file. """ data = np.load(Path(file_name).resolve(), allow_pickle=True) d = data[()] if self.to_int32: return d["masks"].astype(np.int32) else: return d["masks"]
Ancestors
- monai.transforms.transform.Transform
- abc.ABC
class CustomND2Reader (ensure_channel_first: bool = True, dtype: torch.dtype = torch.float32, as_meta_tensor: bool = False, voxel_size: Optional[tuple] = None, voxel_size_from_file: bool = False)
-
Loads a Nikon ND2 file using the nd2reader library.
Constructor
Parameters
ensure_channel_first
:bool
- Ensure that the image is in the channel first format.
dtype
:torch.dtype = torch.float32
- Type of the image.
as_meta_tensor
:bool (default = False)
- Set to True to return a MONAI MetaTensor, set to False for a PyTorch Tensor.
If both
as_meta_tensor
is True andvoxel_size
is specified,ensure_channel_first
must be True. voxel_size
:Optional[tuple]
- Set the voxel size [y, x, z] as metadata to the MetaTensor (only if
as_meta_tensor
is True; otherwise it is ignored). If bothas_meta_tensor
is True andvoxel_size
is specified,ensure_channel_first
must be True. voxel_size_from_file
:Optional[tuple]
- If voxel size is not specified, as_meta_tensor is set to True, and set voxel_size_from_file is True
the voxel size is read from the file and set it [y, x, z] as metadata to the MetaTensor.
If both
as_meta_tensor
is True and eithervoxel_size
is specified or voxel_size_from_file is True, thenensure_channel_first
must also be True.
Expand source code
class CustomND2Reader(Transform): """Loads a Nikon ND2 file using the nd2reader library.""" def __init__( self, ensure_channel_first: bool = True, dtype: torch.dtype = torch.float32, as_meta_tensor: bool = False, voxel_size: Optional[tuple] = None, voxel_size_from_file: bool = False, ) -> None: """Constructor Parameters ---------- ensure_channel_first: bool Ensure that the image is in the channel first format. dtype: torch.dtype = torch.float32 Type of the image. as_meta_tensor: bool (default = False) Set to True to return a MONAI MetaTensor, set to False for a PyTorch Tensor. If both `as_meta_tensor` is True and `voxel_size` is specified, `ensure_channel_first` must be True. voxel_size: Optional[tuple] Set the voxel size [y, x, z] as metadata to the MetaTensor (only if `as_meta_tensor` is True; otherwise it is ignored). If both `as_meta_tensor` is True and `voxel_size` is specified, `ensure_channel_first` must be True. voxel_size_from_file: Optional[tuple] If voxel size is not specified, as_meta_tensor is set to True, and set voxel_size_from_file is True the voxel size is read from the file and set it [y, x, z] as metadata to the MetaTensor. If both `as_meta_tensor` is True and either `voxel_size` is specified or voxel_size_from_file is True, then `ensure_channel_first` must also be True. """ super().__init__() self.ensure_channel_first = ensure_channel_first self.dtype = dtype self.as_meta_tensor = as_meta_tensor self.voxel_size = tuple(voxel_size) if voxel_size is not None else None self.voxel_size_from_file = voxel_size_from_file def _parse_voxel_sizes(self, reader, meta) -> tuple[float, ...]: """ Parse metadata of ND2 file and extracts pixel size and z step. """ # Build the array step by step voxel_sizes = [0.0, 0.0, 0.0] # y, x, z if "pixel_microns" in reader.metadata: p = reader.metadata["pixel_microns"] voxel_sizes[0] = p voxel_sizes[1] = p # If there is only one plane, we leave the z step to 0.0 z_coords = None if meta.num_planes > 1: if ( "z_coordinates" in reader.metadata and reader.metadata["z_coordinates"] is not None ): z_coords = np.array(reader.metadata["z_coordinates"]) elif ( hasattr(reader.parser._raw_metadata, "z_data") and reader.parser._raw_metadata.z_data is not None ): z_coords = np.array(reader.parser._raw_metadata.z_data) else: print("Could not read z coordinates!") if z_coords is not None: z_steps = np.zeros(meta.num_series * meta.num_timepoints) for i, z in enumerate(range(0, len(z_coords), meta.num_planes)): z_range = z_coords[z : z + meta.num_planes] z_steps[i] = np.mean(np.diff(z_range)) voxel_sizes[2] = z_steps.mean() # Return the voxel sizes return tuple(voxel_sizes) def _parse_geometry(self, reader): """ Parse geometry of ND2 file and sets `bundle_axis` and `_iter_axis` properties of ND2Reader. """ # Initialize _geometry num_series: int = 1 num_timepoints: int = 1 num_channels: int = 1 num_planes: int = 1 geometry: str = "xy" iter_axis: str = "" class Meta(NamedTuple): geometry: str num_planes: int num_channels: int num_timepoints: int num_series: int iter_axis: str if "z" in reader.sizes and reader.sizes["z"] > 1: num_planes = reader.sizes["z"] geometry = "z" + geometry if "c" in reader.sizes and reader.sizes["c"] > 1: num_channels = reader.sizes["c"] geometry = "c" + geometry if "t" in reader.sizes and reader.sizes["t"] > 1: num_timepoints = reader.sizes["t"] geometry = "t" + geometry reader.bundle_axes = geometry # Axis to iterate upon if "z" in reader.sizes: reader.iter_axes = ["z"] if "c" in reader.sizes: reader.iter_axes = ["c"] if "t" in reader.sizes: reader.iter_axes = ["t"] if "v" in reader.sizes: self._num_series = reader.sizes["v"] reader.iter_axes = ["v"] # Set the main axis for iteration iter_axis = reader.iter_axes[0] # Fill the metadata tuple meta = Meta( geometry=geometry, num_planes=num_planes, num_channels=num_channels, num_timepoints=num_timepoints, num_series=num_series, iter_axis=iter_axis, ) return meta def __call__( self, file_name: Union[Path, str], series_num: int = 0, timepoint: int = 0, channel: int = 0, plane: Optional[int] = None, ) -> torch.Tensor: """ Load the file and return the image/labels Tensor. Parameters ---------- file_name: str File name series_num: int = 0 Number of series to read. timepoint: int = 0 Timepoint to read. channel: int = 0 Channel to read. plane: Optional[int] = None Plane to read. If not specified, and the dataset is 3D, the whole stack will be returned. Returns ------- tensor: torch.Tensor | monai.MetaTensor Tensor with requested type and shape. """ # Check the consistency of the input arguments if self.as_meta_tensor and self.voxel_size is not None: if not self.ensure_channel_first: raise ValueError( f"If both `as_meta_tensor` is True and `voxel_size` is specified," f"`ensure_channel_first` must be True." ) # File path file_path = str(Path(file_name).resolve()) # Load and process image reader = ND2Reader(file_path) meta = self._parse_geometry(reader) # Check the compatibility of the requested dimensions if series_num + 1 > meta.num_series: raise ValueError("The requested series number does not exist.") if timepoint + 1 > meta.num_timepoints: raise ValueError("The requested time point does not exist.") if channel + 1 > meta.num_channels: raise ValueError("The requested channel does not exist.") if plane is not None and plane + 1 > meta.num_planes: raise ValueError("The requested plane does not exist.") match meta.geometry: case "xy": data = torch.Tensor(reader[0].astype(np.float32)) case _: raise NotImplementedError( "Support for this geometry is not implemented yet." ) if self.as_meta_tensor: if self.voxel_size is None and self.voxel_size_from_file: # Get the voxel size self.voxel_size = self._parse_voxel_sizes(reader, meta) else: self.voxel_size = tuple([1.0, 1.0, 1.0]) # To pass a voxel size to the MetaTensor, we need to define the # corresponding affine transform: affine = torch.tensor( [ [self.voxel_size[0], 0.0, 0.0, 0.0], [0.0, self.voxel_size[1], 0.0, 0.0], [0.0, 0.0, self.voxel_size[2], 0.0], [0.0, 0.0, 0.0, 1.0], ] ) data = MetaTensor(data, affine=affine) if self.ensure_channel_first: data = data.unsqueeze(0) if self.dtype is not None: data = data.to(self.dtype) return data
Ancestors
- monai.transforms.transform.Transform
- abc.ABC
class CustomND2Readerd (keys: tuple[str, ...] = ('image', 'label'), ensure_channel_first: bool = True, dtype: torch.dtype = torch.float32, as_meta_tensor: bool = False, voxel_size: Optional[tuple] = None, voxel_size_from_file: bool = False)
-
Loads TIFF files using the tifffile library.
Constructor
Parameters
keys
:tuple[str]
- Keys for the data dictionary.
ensure_channel_first
:bool
- Ensure that the image is in the channel first format.
dtype
:torch.dtype = torch.float32
- Type of the image.
as_meta_tensor
:bool (default = False)
- Set to True to return a MONAI MetaTensor, set to False for a PyTorch Tensor.
If both
as_meta_tensor
is True andvoxel_size
is specified,ensure_channel_first
must be True. voxel_size
:Optional[tuple]
- Set the voxel size [y, x, z] as metadata to the MetaTensor (only if
as_meta_tensor
is True; otherwise it is ignored). If bothas_meta_tensor
is True andvoxel_size
is specified,ensure_channel_first
must be True. voxel_size_from_file
:Optional[tuple]
- If voxel size is not specified, as_meta_tensor is set to True, and set voxel_size_from_file is True
the voxel size is read from the file and set it [y, x, z] as metadata to the MetaTensor.
If both
as_meta_tensor
is True and eithervoxel_size
is specified or voxel_size_from_file is True, thenensure_channel_first
must also be True.
Expand source code
class CustomND2Readerd(MapTransform): """Loads TIFF files using the tifffile library.""" def __init__( self, keys: tuple[str, ...] = ("image", "label"), ensure_channel_first: bool = True, dtype: torch.dtype = torch.float32, as_meta_tensor: bool = False, voxel_size: Optional[tuple] = None, voxel_size_from_file: bool = False, ) -> None: """Constructor Parameters ---------- keys: tuple[str] Keys for the data dictionary. ensure_channel_first: bool Ensure that the image is in the channel first format. dtype: torch.dtype = torch.float32 Type of the image. as_meta_tensor: bool (default = False) Set to True to return a MONAI MetaTensor, set to False for a PyTorch Tensor. If both `as_meta_tensor` is True and `voxel_size` is specified, `ensure_channel_first` must be True. voxel_size: Optional[tuple] Set the voxel size [y, x, z] as metadata to the MetaTensor (only if `as_meta_tensor` is True; otherwise it is ignored). If both `as_meta_tensor` is True and `voxel_size` is specified, `ensure_channel_first` must be True. voxel_size_from_file: Optional[tuple] If voxel size is not specified, as_meta_tensor is set to True, and set voxel_size_from_file is True the voxel size is read from the file and set it [y, x, z] as metadata to the MetaTensor. If both `as_meta_tensor` is True and either `voxel_size` is specified or voxel_size_from_file is True, then `ensure_channel_first` must also be True. """ super().__init__(keys=keys) self.keys = keys self.tensor_reader = CustomND2Reader( ensure_channel_first=ensure_channel_first, dtype=dtype, as_meta_tensor=as_meta_tensor, voxel_size=voxel_size, voxel_size_from_file=voxel_size_from_file, ) def __call__(self, data: dict) -> dict: """ Load the files and return the image and labels Tensors in the data dictionary. Returns ------- data: dict Updated dictionary with normalized "image" tensor. """ # Work on a copy of the dictionary d = dict(data) for key in self.keys: # Get arguments image_path = str(Path(str(d[key])).resolve()) # Use the single tensor reader out = self.tensor_reader(image_path) # Assign the tensor to the corresponding key d[key] = out # (Meta)Tensor(image) return d
Ancestors
- monai.transforms.transform.MapTransform
- monai.transforms.transform.Transform
- abc.ABC
class CustomTIFFReader (ensure_channel_first: bool = True, dtype: torch.dtype = torch.float32, as_meta_tensor: bool = False, voxel_size: Optional[tuple] = None)
-
Loads a TIFF file using the tifffile library.
Constructor
Parameters
ensure_channel_first
:bool
- Ensure that the image is in the channel first format.
dtype
:torch.dtype = torch.float32
- Type of the image.
as_meta_tensor
:bool (default = False)
- Set to True to return a MONAI MetaTensor, set to False for a PyTorch Tensor.
If both
as_meta_tensor
is True andvoxel_size
is specified,ensure_channel_first
must be True. voxel_size
:Optional[tuple]
- Set the voxel size [y, x, z] as metadata to the MetaTensor (only if
as_meta_tensor
is True; otherwise it is ignored). If bothas_meta_tensor
is True andvoxel_size
is specified,ensure_channel_first
must be True.
Expand source code
class CustomTIFFReader(Transform): """Loads a TIFF file using the tifffile library.""" def __init__( self, ensure_channel_first: bool = True, dtype: torch.dtype = torch.float32, as_meta_tensor: bool = False, voxel_size: Optional[tuple] = None, ) -> None: """Constructor Parameters ---------- ensure_channel_first: bool Ensure that the image is in the channel first format. dtype: torch.dtype = torch.float32 Type of the image. as_meta_tensor: bool (default = False) Set to True to return a MONAI MetaTensor, set to False for a PyTorch Tensor. If both `as_meta_tensor` is True and `voxel_size` is specified, `ensure_channel_first` must be True. voxel_size: Optional[tuple] Set the voxel size [y, x, z] as metadata to the MetaTensor (only if `as_meta_tensor` is True; otherwise it is ignored). If both `as_meta_tensor` is True and `voxel_size` is specified, `ensure_channel_first` must be True. """ super().__init__() self.ensure_channel_first = ensure_channel_first self.dtype = dtype self.as_meta_tensor = as_meta_tensor self.voxel_size = tuple(voxel_size) if voxel_size is not None else None def __call__(self, file_name: Union[Path, str]) -> torch.Tensor: """ Load the file and return the image/labels Tensor. Parameters ---------- file_name: str File name Returns ------- tensor: torch.Tensor | monai.MetaTensor Tensor with requested type and shape. """ # Check the consistency of the input arguments if self.as_meta_tensor and self.voxel_size is not None: if not self.ensure_channel_first: raise ValueError( f"If both `as_meta_tensor` is True and `voxel_size` is specified," f"`ensure_channel_first` must be True." ) # File path image_path = str(Path(file_name).resolve()) # Load and process image data = torch.Tensor(imread(image_path).astype(np.float32)) if self.as_meta_tensor: if self.voxel_size is not None: if data.ndim != len(self.voxel_size): raise ValueError( "The size of `voxel_size` does not natch the dimensionality of the image." ) else: self.voxel_size = tuple([1.0, 1.0, 1.0]) # To pass a voxel size to the MetaTensor, we need to define the # corresponding affine transform: affine = torch.tensor( [ [self.voxel_size[0], 0.0, 0.0, 0.0], [0.0, self.voxel_size[1], 0.0, 0.0], [0.0, 0.0, self.voxel_size[2], 0.0], [0.0, 0.0, 0.0, 1.0], ] ) data = MetaTensor(data, affine=affine) if self.ensure_channel_first: data = data.unsqueeze(0) if self.dtype is not None: data = data.to(self.dtype) return data
Ancestors
- monai.transforms.transform.Transform
- abc.ABC