Esempio n. 1
0
    def save(self, data: Union[torch.Tensor, np.ndarray], meta_data: Optional[Dict] = None) -> None:
        """
        Save data into a Nifti file.
        The meta_data could optionally have the following keys:

            - ``'filename_or_obj'`` -- for output file name creation, corresponding to filename or object.
            - ``'original_affine'`` -- for data orientation handling, defaulting to an identity matrix.
            - ``'affine'`` -- for data output affine, defaulting to an identity matrix.
            - ``'spatial_shape'`` -- for data output shape.
            - ``'patch_index'`` -- if the data is a patch of big image, append the patch index to filename.

        When meta_data is specified, the saver will try to resample batch data from the space
        defined by "affine" to the space defined by "original_affine".

        If meta_data is None, use the default index (starting from 0) as the filename.

        Args:
            data: target data content that to be saved as a NIfTI format file.
                Assuming the data shape starts with a channel dimension and followed by spatial dimensions.
            meta_data: the meta data information corresponding to the data.

        See Also
            :py:meth:`monai.data.nifti_writer.write_nifti`
        """
        filename = meta_data[Key.FILENAME_OR_OBJ] if meta_data else str(self._data_index)
        self._data_index += 1
        original_affine = meta_data.get("original_affine", None) if meta_data else None
        affine = meta_data.get("affine", None) if meta_data else None
        spatial_shape = meta_data.get("spatial_shape", None) if meta_data else None
        patch_index = meta_data.get(Key.PATCH_INDEX, None) if meta_data else None

        if isinstance(data, torch.Tensor):
            data = data.detach().cpu().numpy()

        path = create_file_basename(self.output_postfix, filename, self.output_dir, self.data_root_dir, patch_index)
        path = f"{path}{self.output_ext}"
        # change data shape to be (channel, h, w, d)
        while len(data.shape) < 4:
            data = np.expand_dims(data, -1)
        # change data to "channel last" format and write to nifti format file
        data = np.moveaxis(np.asarray(data), 0, -1)

        # if desired, remove trailing singleton dimensions
        if self.squeeze_end_dims:
            while data.shape[-1] == 1:
                data = np.squeeze(data, -1)

        write_nifti(
            data,
            file_name=path,
            affine=affine,
            target_affine=original_affine,
            resample=self.resample,
            output_spatial_shape=spatial_shape,
            mode=self.mode,
            padding_mode=self.padding_mode,
            align_corners=self.align_corners,
            dtype=self.dtype,
            output_dtype=self.output_dtype,
        )
Esempio n. 2
0
    def filename(self, subject: PathLike = "subject", idx=None, **kwargs):
        """
        Create a filename based on the input ``subject`` and ``idx``.

        The output filename is formed as:

            ``output_dir/[subject/]subject[_postfix][_idx][_key-value][ext]``

        Args:
            subject: subject name, used as the primary id of the output filename.
                When a `PathLike` object is provided, the base filename will be used as the subject name,
                the extension name of `subject` will be ignored, in favor of ``extension``
                from this class's constructor.
            idx: additional index name of the image.
            kwargs: additional keyword arguments to be used to form the output filename.
                The key-value pairs will be appended to the output filename as ``f"_{k}-{v}"``.
        """
        full_name = create_file_basename(
            postfix=self.postfix,
            input_file_name=subject,
            folder_path=self.output_dir,
            data_root_dir=self.data_root_dir,
            separate_folder=self.parent,
            patch_index=idx,
            makedirs=self.makedirs,
        )
        for k, v in kwargs.items():
            full_name += f"_{k}-{v}"
        if self.ext is not None:
            ext = f"{self.ext}"
            full_name += f".{ext}" if ext and not ext.startswith(".") else f"{ext}"
        return full_name
Esempio n. 3
0
    def save(self,
             data: Union[torch.Tensor, np.ndarray],
             meta_data: Optional[Dict] = None) -> None:
        """
        Save data into a Nifti file.
        The meta_data could optionally have the following keys:

            - ``'filename_or_obj'`` -- for output file name creation, corresponding to filename or object.
            - ``'original_affine'`` -- for data orientation handling, defaulting to an identity matrix.
            - ``'affine'`` -- for data output affine, defaulting to an identity matrix.
            - ``'spatial_shape'`` -- for data output shape.

        When meta_data is specified, the saver will try to resample batch data from the space
        defined by "affine" to the space defined by "original_affine".

        If meta_data is None, use the default index (starting from 0) as the filename.

        Args:
            data: target data content that to be saved as a NIfTI format file.
                Assuming the data shape starts with a channel dimension and followed by spatial dimensions.
            meta_data: the meta data information corresponding to the data.

        See Also
            :py:meth:`monai.data.nifti_writer.write_nifti`
        """
        filename = meta_data["filename_or_obj"] if meta_data else str(
            self._data_index)
        for _ in range(self.output_name_uplevel):
            filename = os.path.dirname(filename)
        self._data_index += 1
        original_affine = meta_data.get("original_affine",
                                        None) if meta_data else None
        affine = meta_data.get("affine", None) if meta_data else None
        spatial_shape = meta_data.get("spatial_shape",
                                      None) if meta_data else None

        if torch.is_tensor(data):
            data = data.detach().cpu().numpy()

        filename = create_file_basename(self.output_postfix, filename,
                                        self.output_dir)
        filename = f"{filename}{self.output_ext}"
        # change data shape to be (channel, h, w, d)
        while len(data.shape) < 4:
            data = np.expand_dims(data, -1)
        # change data to "channel last" format and write to nifti format file
        data = np.moveaxis(data, 0, -1)
        write_nifti(
            data,
            file_name=filename,
            affine=affine,
            target_affine=original_affine,
            resample=self.resample,
            output_spatial_shape=spatial_shape,
            mode=self.mode,
            padding_mode=self.padding_mode,
            align_corners=self.align_corners,
            dtype=self.dtype,
        )
Esempio n. 4
0
    def save(self,
             data: Union[torch.Tensor, np.ndarray],
             meta_data: Optional[Dict] = None) -> None:
        """
        Save data into a png file.
        The meta_data could optionally have the following keys:

            - ``'filename_or_obj'`` -- for output file name creation, corresponding to filename or object.
            - ``'spatial_shape'`` -- for data output shape.
            - ``'patch_index'`` -- if the data is a patch of big image, append the patch index to filename.

        If meta_data is None, use the default index (starting from 0) as the filename.

        Args:
            data: target data content that to be saved as a png format file.
                Assuming the data shape are spatial dimensions.
                Shape of the spatial dimensions (C,H,W).
                C should be 1, 3 or 4
            meta_data: the meta data information corresponding to the data.

        Raises:
            ValueError: When ``data`` channels is not one of [1, 3, 4].

        See Also
            :py:meth:`monai.data.png_writer.write_png`

        """
        filename = meta_data[Key.FILENAME_OR_OBJ] if meta_data else str(
            self._data_index)
        self._data_index += 1
        spatial_shape = meta_data.get(
            "spatial_shape", None) if meta_data and self.resample else None
        patch_index = meta_data.get(Key.PATCH_INDEX,
                                    None) if meta_data else None

        if isinstance(data, torch.Tensor):
            data = data.detach().cpu().numpy()

        path = create_file_basename(self.output_postfix, filename,
                                    self.output_dir, self.data_root_dir,
                                    patch_index)
        path = f"{path}{self.output_ext}"

        if data.shape[0] == 1:
            data = data.squeeze(0)
        elif 2 < data.shape[0] < 5:
            data = np.moveaxis(np.asarray(data), 0, -1)
        else:
            raise ValueError(
                f"Unsupported number of channels: {data.shape[0]}, available options are [1, 3, 4]"
            )

        write_png(
            np.asarray(data),
            file_name=path,
            output_spatial_shape=spatial_shape,
            mode=self.mode,
            scale=self.scale,
        )
Esempio n. 5
0
    def test_value(self):
        with tempfile.TemporaryDirectory() as tempdir:
            output_tmp = os.path.join(tempdir, "output")
            result = create_file_basename("", "test.txt", output_tmp, "")
            expected = os.path.join(output_tmp, "test", "test")
            self.assertEqual(result, expected)

            result = create_file_basename("", os.path.join("foo", "test.txt"), output_tmp, "")
            expected = os.path.join(output_tmp, "test", "test")
            self.assertEqual(result, expected)

            result = create_file_basename("", os.path.join("foo", "test.txt"), output_tmp, "foo")
            expected = os.path.join(output_tmp, "test", "test")
            self.assertEqual(result, expected)

            result = create_file_basename("", os.path.join("foo", "bar", "test.txt"), output_tmp, "foo")
            expected = os.path.join(output_tmp, "bar", "test", "test")
            self.assertEqual(result, expected)

            result = create_file_basename(
                postfix="",
                input_file_name=os.path.join("foo", "bar", "data", "test.txt"),
                folder_path=output_tmp,
                data_root_dir=os.path.join("foo", "bar"),
            )
            expected = os.path.join(output_tmp, "data", "test", "test")
            self.assertEqual(result, expected)

            result = create_file_basename("", os.path.join("foo", "bar", "test.txt"), output_tmp, "bar")
            expected = os.path.join(tempdir, "foo", "bar", "test", "test")
            self.assertEqual(result, expected)

            result = create_file_basename("", os.path.join("rest", "test.txt"), output_tmp, "rest")
            expected = os.path.join(tempdir, "output", "test", "test")
            self.assertEqual(result, expected)

            result = create_file_basename("", "test.txt", output_tmp, "foo")
            expected = os.path.join(output_tmp, "test", "test")
            self.assertEqual(result, expected)

            result = create_file_basename("post", "test.tar.gz", output_tmp, "foo")
            expected = os.path.join(output_tmp, "test", "test_post")
            self.assertEqual(result, expected)
Esempio n. 6
0
    def save(self, data: Union[torch.Tensor, np.ndarray], meta_data: Optional[dict] = None) -> None:
        """
        Save data into a png file.
        The meta_data could optionally have the following keys:

            - ``'filename_or_obj'`` -- for output file name creation, corresponding to filename or object.
            - ``'spatial_shape'`` -- for data output shape.

        If meta_data is None, use the default index (starting from 0) as the filename.

        Args:
            data: target data content that to be saved as a png format file.
                Assuming the data shape are spatial dimensions.
                Shape of the spatial dimensions (C,H,W).
                C should be 1, 3 or 4
            meta_data: the meta data information corresponding to the data.

        Raises:
            ValueError: PNG image should only have 1, 3 or 4 channels.

        See Also
            :py:meth:`monai.data.png_writer.write_png`
        """
        filename = meta_data["filename_or_obj"] if meta_data else str(self._data_index)
        self._data_index += 1
        spatial_shape = meta_data.get("spatial_shape", None) if meta_data and self.resample else None

        if torch.is_tensor(data):
            data = data.detach().cpu().numpy()

        filename = create_file_basename(self.output_postfix, filename, self.output_dir)
        filename = f"{filename}{self.output_ext}"

        if data.shape[0] == 1:
            data = data.squeeze(0)
        elif 2 < data.shape[0] < 5:
            data = np.moveaxis(data, 0, -1)
        else:
            raise ValueError("PNG image should only have 1, 3 or 4 channels.")

        write_png(
            data, file_name=filename, output_spatial_shape=spatial_shape, mode=self.mode, scale=self.scale,
        )
Esempio n. 7
0
 def test_relative_path(self):
     output = create_file_basename("", "test.txt", "output", "", makedirs=False)
     expected = os.path.join("output", "test", "test")
     self.assertEqual(output, expected)