Skip to content

Commit

Permalink
Support specified filenames in Saveimage (Project-MONAI#7318)
Browse files Browse the repository at this point in the history
Fixes Project-MONAI#7317

### Description

Add support specified filename for users to save like nibabel.save.

### Types of changes
<!--- Put an `x` in all the boxes that apply, and remove the not
applicable items -->
- [x] Non-breaking change (fix or new feature that would not break
existing functionality).
- [ ] Breaking change (fix or new feature that would cause existing
functionality to change).
- [ ] New tests added to cover the changes.
- [ ] Integration tests passed locally by running `./runtests.sh -f -u
--net --coverage`.
- [ ] Quick tests passed locally by running `./runtests.sh --quick
--unittests --disttests`.
- [ ] In-line docstrings updated.
- [ ] Documentation updated, tested `make html` command in the `docs/`
folder.

---------

Signed-off-by: YunLiu <[email protected]>
Signed-off-by: Yu0610 <[email protected]>
  • Loading branch information
KumoLiu authored and Yu0610 committed Apr 11, 2024
1 parent c99f3ca commit 5707e8d
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 3 deletions.
17 changes: 14 additions & 3 deletions monai/transforms/io/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,9 @@ def __init__(
self.fname_formatter = output_name_formatter

self.output_ext = output_ext.lower() or output_format.lower()
self.output_ext = (
f".{self.output_ext}" if self.output_ext and not self.output_ext.startswith(".") else self.output_ext
)
if isinstance(writer, str):
writer_, has_built_in = optional_import("monai.data", name=f"{writer}") # search built-in
if not has_built_in:
Expand Down Expand Up @@ -458,15 +461,23 @@ def set_options(self, init_kwargs=None, data_kwargs=None, meta_kwargs=None, writ
self.write_kwargs.update(write_kwargs)
return self

def __call__(self, img: torch.Tensor | np.ndarray, meta_data: dict | None = None):
def __call__(
self, img: torch.Tensor | np.ndarray, meta_data: dict | None = None, filename: str | PathLike | None = None
):
"""
Args:
img: target data content that save into file. The image should be channel-first, shape: `[C,H,W,[D]]`.
meta_data: key-value pairs of metadata corresponding to the data.
filename: str or file-like object which to save img.
If specified, will ignore `self.output_name_formatter` and `self.folder_layout`.
"""
meta_data = img.meta if isinstance(img, MetaTensor) else meta_data
kw = self.fname_formatter(meta_data, self)
filename = self.folder_layout.filename(**kw)
if filename is not None:
filename = f"{filename}{self.output_ext}"
else:
kw = self.fname_formatter(meta_data, self)
filename = self.folder_layout.filename(**kw)

if meta_data:
meta_spatial_shape = ensure_tuple(meta_data.get("spatial_shape", ()))
if len(meta_spatial_shape) >= len(img.shape):
Expand Down
16 changes: 16 additions & 0 deletions tests/test_save_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
False,
]

TEST_CASE_5 = [torch.randint(0, 255, (3, 2, 4, 5), dtype=torch.uint8), ".dcm", False]


@unittest.skipUnless(has_itk, "itk not installed")
class TestSaveImage(unittest.TestCase):
Expand All @@ -58,6 +60,20 @@ def test_saved_content(self, test_data, meta_data, output_ext, resample):
filepath = "testfile0" if meta_data is not None else "0"
self.assertTrue(os.path.exists(os.path.join(tempdir, filepath + "_trans" + output_ext)))

@parameterized.expand([TEST_CASE_5])
def test_saved_content_with_filename(self, test_data, output_ext, resample):
with tempfile.TemporaryDirectory() as tempdir:
trans = SaveImage(
output_dir=tempdir,
output_ext=output_ext,
resample=resample,
separate_folder=False, # test saving into the same folder
)
filename = str(os.path.join(tempdir, "test"))
trans(test_data, filename=filename)

self.assertTrue(os.path.exists(filename + output_ext))


if __name__ == "__main__":
unittest.main()

0 comments on commit 5707e8d

Please sign in to comment.