Repository: Project-MONAI/MONAI

Issue:
nifti saver squeeze dims
Fixes https://github.com/Project-MONAI/MONAI/discussions/1678.

### Description
Currently `NiftiSaver` (therefore default `SaveImage` and `SaveImaged`) saves images as `(H,W,D,C)`, even if input image had no channel dimension, or was only a 2D image.

This PR allows users to squeeze trailing singleton dimensions. If C==1, image will be saved as `(H,W,D)`. If D is also == 1, image will be saved as `(H,W)`. If D==1, but C>1, image will still be saved as `(H,W,D,C)` (to avoid channel dimension being interpreted as depth).

~~I also changed the saved path from `/some/path/filename/filename.nii.gz` to `/some/path/filename.nii.gz`, as I assumed the former was a mistake. I can undo this if it was intentional.~~ EDIT: I reverted this for backwards compatibility, but I still find it ugly.

### Status
**Ready**

### 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).
- [x] New tests added to cover the changes.
- [x] Integration tests passed locally by running `./runtests.sh --codeformat --coverage`.
- [x] Quick tests passed locally by running `./runtests.sh --quick`.
- [x] In-line docstrings updated.
- [x] Documentation updated, tested `make html` command in the `docs/` folder.



Discussion:

Resolving patch:
diff --git a/monai/handlers/segmentation_saver.py b/monai/handlers/segmentation_saver.py
--- a/monai/handlers/segmentation_saver.py
+++ b/monai/handlers/segmentation_saver.py
@@ -41,6 +41,7 @@ def __init__(
         scale: Optional[int] = None,
         dtype: DtypeLike = np.float64,
         output_dtype: DtypeLike = np.float32,
+        squeeze_end_dims: bool = True,
         batch_transform: Callable = lambda x: x,
         output_transform: Callable = lambda x: x,
         name: Optional[str] = None,
@@ -77,6 +78,11 @@ def __init__(
                 If None, use the data type of input data.
                 It's used for Nifti format only.
             output_dtype: data type for saving data. Defaults to ``np.float32``, it's used for Nifti format only.
+            squeeze_end_dims: if True, any trailing singleton dimensions will be removed (after the channel
+                has been moved to the end). So if input is (C,H,W,D), this will be altered to (H,W,D,C), and
+                then if C==1, it will be saved as (H,W,D). If D also ==1, it will be saved as (H,W). If false,
+                image will always be saved as (H,W,D,C).
+                it's used for NIfTI format only.
             batch_transform: a callable that is used to transform the
                 ignite.engine.batch into expected format to extract the meta_data dictionary.
             output_transform: a callable that is used to transform the
@@ -96,6 +102,7 @@ def __init__(
             scale=scale,
             dtype=dtype,
             output_dtype=output_dtype,
+            squeeze_end_dims=squeeze_end_dims,
             save_batch=True,
         )
         self.batch_transform = batch_transform
diff --git a/monai/transforms/io/array.py b/monai/transforms/io/array.py
--- a/monai/transforms/io/array.py
+++ b/monai/transforms/io/array.py
@@ -206,6 +206,7 @@ class SaveImage(Transform):
             has been moved to the end). So if input is (C,H,W,D), this will be altered to (H,W,D,C), and
             then if C==1, it will be saved as (H,W,D). If D also ==1, it will be saved as (H,W). If false,
             image will always be saved as (H,W,D,C).
+            it's used for NIfTI format only.
 
     """
 
diff --git a/monai/transforms/io/dictionary.py b/monai/transforms/io/dictionary.py
--- a/monai/transforms/io/dictionary.py
+++ b/monai/transforms/io/dictionary.py
@@ -172,6 +172,7 @@ class SaveImaged(MapTransform):
             has been moved to the end). So if input is (C,H,W,D), this will be altered to (H,W,D,C), and
             then if C==1, it will be saved as (H,W,D). If D also ==1, it will be saved as (H,W). If false,
             image will always be saved as (H,W,D,C).
+            it's used for NIfTI format only.
 
     """
 


Test patch: