internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: Project-MONAI/MONAI

Issue:
moving docker min test to self-hosted runner
**Is your feature request related to a problem? Please describe.**
the free github runner has insufficient disk space 
for example https://github.com/Project-MONAI/MONAI/actions/runs/5639252329


Discussion:

Resolving patch:
diff --git a/monai/apps/deepgrow/transforms.py b/monai/apps/deepgrow/transforms.py
--- a/monai/apps/deepgrow/transforms.py
+++ b/monai/apps/deepgrow/transforms.py
@@ -441,8 +441,8 @@ def __call__(self, data):
 
         if np.all(np.less(current_size, self.spatial_size)):
             cropper = SpatialCrop(roi_center=center, roi_size=self.spatial_size)
-            box_start = np.array([s.start for s in cropper.slices])  # type: ignore
-            box_end = np.array([s.stop for s in cropper.slices])  # type: ignore
+            box_start = np.array([s.start for s in cropper.slices])
+            box_end = np.array([s.stop for s in cropper.slices])
         else:
             cropper = SpatialCrop(roi_start=box_start, roi_end=box_end)
 
diff --git a/monai/data/ultrasound_confidence_map.py b/monai/data/ultrasound_confidence_map.py
--- a/monai/data/ultrasound_confidence_map.py
+++ b/monai/data/ultrasound_confidence_map.py
@@ -301,7 +301,7 @@ def confidence_estimation(self, img, seeds, labels, beta, gamma):
         m[:, 0] = labels == 1
 
         # Right-handside (-B^T*M)
-        rhs = -b @ m  # type: ignore
+        rhs = -b @ m
 
         # Solve linear system
         x = self._solve_linear_system(lap, rhs)
@@ -334,7 +334,7 @@ def __call__(self, data: NDArray, sink_mask: NDArray | None = None) -> NDArray:
 
         if self.mode == "RF":
             # MATLAB hilbert applies the Hilbert transform to columns
-            data = np.abs(hilbert(data, axis=0)).astype("float64")  # type: ignore
+            data = np.abs(hilbert(data, axis=0)).astype("float64")
 
         seeds, labels = self.get_seed_and_labels(data, self.sink_mode, sink_mask)
 
diff --git a/monai/transforms/intensity/array.py b/monai/transforms/intensity/array.py
--- a/monai/transforms/intensity/array.py
+++ b/monai/transforms/intensity/array.py
@@ -39,7 +39,6 @@
 
 skimage, _ = optional_import("skimage", "0.19.0", min_version)
 
-
 __all__ = [
     "RandGaussianNoise",
     "RandRicianNoise",


Test patch:
diff --git a/tests/test_ultrasound_confidence_map_transform.py b/tests/test_ultrasound_confidence_map_transform.py
--- a/tests/test_ultrasound_confidence_map_transform.py
+++ b/tests/test_ultrasound_confidence_map_transform.py
@@ -49,7 +49,6 @@
     ]
 )
 
-
 SINK_ALL_OUTPUT = np.array(
     [
         [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
Repository: Project-MONAI/MONAI

Issue:
lazy `RandAffine` has no effect
**Describe the bug**
When using `RandAffine` with `lazy=True`, it does not perform any transform at all.

**To Reproduce**
```python
import torch

from monai import transforms as mt

def main():
    x = torch.randn(1, 32, 32, 32)
    trans = mt.Compose(
        [mt.RandAffine(1., translate_range=[(0, 0), (1, 1), (2, 2)])],
        lazy=False
    )
    print(trans(x).affine)
    lazy_trans = mt.Compose(
        [mt.RandAffine(1., translate_range=[(0, 0), (1, 1), (2, 2)])],
        lazy=True,
    )
    print(lazy_trans(x).affine)

if __name__ == '__main__':
    main()
```

**Actual Result**
```plain
tensor([[1., 0., 0., 0.],
        [0., 1., 0., 1.],
        [0., 0., 1., 2.],
        [0., 0., 0., 1.]], dtype=torch.float64)
tensor([[1., 0., 0., 0.],
        [0., 1., 0., 0.],
        [0., 0., 1., 0.],
        [0., 0., 0., 1.]], dtype=torch.float64)
```


Discussion:

Resolving patch:
diff --git a/monai/transforms/spatial/array.py b/monai/transforms/spatial/array.py
--- a/monai/transforms/spatial/array.py
+++ b/monai/transforms/spatial/array.py
@@ -2523,6 +2523,8 @@ def __call__(
         img = convert_to_tensor(img, track_meta=get_track_meta())
         if lazy_:
             if self._do_transform:
+                if grid is None:
+                    self.rand_affine_grid(sp_size, randomize=randomize, lazy=True)
                 affine = self.rand_affine_grid.get_transformation_matrix()
             else:
                 affine = convert_to_dst_type(torch.eye(len(sp_size) + 1), img, dtype=self.rand_affine_grid.dtype)[0]
diff --git a/monai/transforms/spatial/dictionary.py b/monai/transforms/spatial/dictionary.py
--- a/monai/transforms/spatial/dictionary.py
+++ b/monai/transforms/spatial/dictionary.py
@@ -1141,6 +1141,7 @@ def __call__(
             grid = self.rand_affine.get_identity_grid(sp_size, lazy=lazy_)
             if self._do_transform:  # add some random factors
                 grid = self.rand_affine.rand_affine_grid(sp_size, grid=grid, lazy=lazy_)
+        grid = 0 if grid is None else grid  # always provide a grid to self.rand_affine
 
         for key, mode, padding_mode in self.key_iterator(d, self.mode, self.padding_mode):
             # do the transform


Test patch:
diff --git a/tests/test_rand_affine.py b/tests/test_rand_affine.py
--- a/tests/test_rand_affine.py
+++ b/tests/test_rand_affine.py
@@ -145,6 +145,7 @@ def test_rand_affine(self, input_param, input_data, expected_val):
         g = RandAffine(**input_param)
         g.set_random_state(123)
         result = g(**input_data)
+        g.rand_affine_grid.affine = torch.eye(4, dtype=torch.float64)  # reset affine
         test_resampler_lazy(g, result, input_param, input_data, seed=123)
         if input_param.get("cache_grid", False):
             self.assertTrue(g._cached_grid is not None)
Repository: Project-MONAI/MONAI

Issue:
SSIMLoss supports set_data_range
follow-up of https://github.com/Project-MONAI/tutorials/pull/1351

should we set the `data_range` as a property that could be set and reset anytime, so that we don't need to initialize a new object every time we need to change the `data_range` parameter?

_Originally posted by @binliunls in https://github.com/Project-MONAI/tutorials/pull/1351#discussion_r1178759252_
            


Discussion:

Resolving patch:
diff --git a/monai/losses/ssim_loss.py b/monai/losses/ssim_loss.py
--- a/monai/losses/ssim_loss.py
+++ b/monai/losses/ssim_loss.py
@@ -61,7 +61,7 @@ def __init__(
         """
         super().__init__(reduction=LossReduction(reduction).value)
         self.spatial_dims = spatial_dims
-        self.data_range = data_range
+        self._data_range = data_range
         self.kernel_type = kernel_type
 
         if not isinstance(win_size, Sequence):
@@ -77,7 +77,7 @@ def __init__(
 
         self.ssim_metric = SSIMMetric(
             spatial_dims=self.spatial_dims,
-            data_range=self.data_range,
+            data_range=self._data_range,
             kernel_type=self.kernel_type,
             win_size=self.kernel_size,
             kernel_sigma=self.kernel_sigma,
@@ -85,6 +85,15 @@ def __init__(
             k2=self.k2,
         )
 
+    @property
+    def data_range(self) -> float:
+        return self._data_range
+
+    @data_range.setter
+    def data_range(self, value: float) -> None:
+        self._data_range = value
+        self.ssim_metric.data_range = value
+
     def forward(self, input: torch.Tensor, target: torch.Tensor) -> torch.Tensor:
         """
         Args:


Test patch:
Repository: Project-MONAI/MONAI

Issue:
DistributedWeightedRandomSampler remove `shuffle=False` option
**Describe the bug**
https://github.com/Project-MONAI/MONAI/blob/4cd717ca830ed7cd811144d96675fdbe586633a4/monai/data/samplers.py#L98
the random sampler will always generate 'shuffled' outputs, the `shuffle=False` option is not valid and should be removed


Discussion:
Would like to take this.

Resolving patch:
diff --git a/monai/data/samplers.py b/monai/data/samplers.py
--- a/monai/data/samplers.py
+++ b/monai/data/samplers.py
@@ -81,7 +81,6 @@ class DistributedWeightedRandomSampler(DistributedSampler):
             by default, `world_size` is retrieved from the current distributed group.
         rank: rank of the current process within `num_replicas`. by default,
             `rank` is retrieved from the current distributed group.
-        shuffle: if `True`, sampler will shuffle the indices, default to True.
         kwargs: additional arguments for `DistributedSampler` super class, can be `seed` and `drop_last`.
 
     """
@@ -95,17 +94,10 @@ def __init__(
         even_divisible: bool = True,
         num_replicas: int | None = None,
         rank: int | None = None,
-        shuffle: bool = True,
         **kwargs,
     ):
-        super().__init__(
-            dataset=dataset,
-            even_divisible=even_divisible,
-            num_replicas=num_replicas,
-            rank=rank,
-            shuffle=shuffle,
-            **kwargs,
-        )
+        kwargs.setdefault("shuffle", True)
+        super().__init__(dataset=dataset, even_divisible=even_divisible, num_replicas=num_replicas, rank=rank, **kwargs)
         self.weights = weights
         self.num_samples_per_rank = num_samples_per_rank if num_samples_per_rank is not None else self.num_samples
         self.generator = generator
diff --git a/monai/losses/adversarial_loss.py b/monai/losses/adversarial_loss.py
--- a/monai/losses/adversarial_loss.py
+++ b/monai/losses/adversarial_loss.py
@@ -133,7 +133,7 @@ def forward(
                 "to False. To optimise a generator, target_is_real must be set to True."
             )
 
-        if type(input) is not list:
+        if not isinstance(input, list):
             input = [input]
         target_ = []
         for _, disc_out in enumerate(input):


Test patch:
Repository: Project-MONAI/MONAI

Issue:
Better autodoc generation -- bundle properties
detailed documentation about bundle.properties and usage on docs.monai.io

https://github.com/Project-MONAI/MONAI/blob/dev/monai/bundle/properties.py#L78


Discussion:

Resolving patch:
diff --git a/docs/source/conf.py b/docs/source/conf.py
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -55,7 +55,18 @@
 
 def generate_apidocs(*args):
     """Generate API docs automatically by trawling the available modules"""
-    module_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "monai"))
+
+    import pandas as pd
+    from monai.bundle.properties import TrainProperties, InferProperties, MetaProperties
+
+    csv_file = os.path.join(os.path.dirname(__file__), "train_properties.csv")  # used in mb_properties.rst
+    pd.DataFrame.from_dict(TrainProperties, orient="index").iloc[:, :3].to_csv(csv_file)
+    csv_file = os.path.join(os.path.dirname(__file__), "infer_properties.csv")
+    pd.DataFrame.from_dict(InferProperties, orient="index").iloc[:, :3].to_csv(csv_file)
+    csv_file = os.path.join(os.path.dirname(__file__), "meta_properties.csv")
+    pd.DataFrame.from_dict(MetaProperties, orient="index").iloc[:, :3].to_csv(csv_file)
+
+    module_path = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, "monai"))
     output_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "apidocs"))
     apidoc_command_path = "sphinx-apidoc"
     if hasattr(sys, "real_prefix"):  # called from a virtualenv


Test patch:
Repository: Project-MONAI/MONAI

Issue:
update base image to 23.08
**Is your feature request related to a problem? Please describe.**
would be great to use the latest base image
https://catalog.ngc.nvidia.com/orgs/nvidia/containers/pytorch/tags

cc @Nic-Ma 


Discussion:

Resolving patch:
diff --git a/monai/transforms/spatial/array.py b/monai/transforms/spatial/array.py
--- a/monai/transforms/spatial/array.py
+++ b/monai/transforms/spatial/array.py
@@ -837,7 +837,7 @@ def __call__(
         lazy_ = self.lazy if lazy is None else lazy
         return resize(  # type: ignore
             img,
-            sp_size,
+            tuple(int(_s) for _s in sp_size),
             _mode,
             _align_corners,
             _dtype,


Test patch:
Repository: Project-MONAI/MONAI

Issue:
robust username masking in print_config
https://github.com/Project-MONAI/MONAI/blob/6f5005fddfaf935cc9b723be823f446a09136d11/monai/config/deviceconfig.py#L103-L110
if home directories are in other locations, eg. networked directories, the regex patterns won't match. I'd suggest a more thorough approach is to get the username with `getpass.getuser()` or `os.path.basename(os.path.expanduser("~"))` then replace all instances of that string in the output with "<username>". This will catch more places but will miss paths that might contain other identifying names, but these should be very rare.

_Originally posted by @ericspod in https://github.com/Project-MONAI/MONAI/issues/6913#issuecomment-1699093111_
            


Discussion:
@wyli I would like to pick this up.

Resolving patch:
diff --git a/monai/config/deviceconfig.py b/monai/config/deviceconfig.py
--- a/monai/config/deviceconfig.py
+++ b/monai/config/deviceconfig.py
@@ -11,6 +11,7 @@
 
 from __future__ import annotations
 
+import getpass
 import os
 import platform
 import re
@@ -100,15 +101,8 @@ def print_config(file=sys.stdout):
         print(f"{k} version: {v}", file=file, flush=True)
     print(f"MONAI flags: HAS_EXT = {HAS_EXT}, USE_COMPILED = {USE_COMPILED}, USE_META_DICT = {USE_META_DICT}")
     print(f"MONAI rev id: {monai.__revision_id__}")
-    masked_file_path = re.sub(
-        r"/home/\w+/",
-        "/home/<username>/",
-        re.sub(
-            r"/Users/\w+/",
-            "/Users/<username>/",
-            re.sub(r"C:\\Users\\\w+\\", r"C:\\Users\\<username>\\", monai.__file__),
-        ),
-    )
+    username = getpass.getuser()
+    masked_file_path = re.sub(username, "<username>", monai.__file__)
     print(f"MONAI __file__: {masked_file_path}", file=file, flush=True)
     print("\nOptional dependencies:", file=file, flush=True)
     for k, v in get_optional_config_values().items():


Test patch:
Repository: Project-MONAI/MONAI

Issue:
Enhance the docstring of `EarlyStopHandler` on distributed training
Related code:

https://github.com/Project-MONAI/MONAI/blob/6dfe17a7bfda9b4ddfa19b60886b7fa14e816afd/monai/handlers/earlystop_handler.py#L50-L51

In order to enable this handler on distributed training, the score function should call `dist.all_reduce`. We can enhance the docstring to include this experience.
Related reference:
https://github.com/Project-MONAI/model-zoo/pull/504#discussion_r1325648513


Discussion:

Resolving patch:
diff --git a/monai/handlers/earlystop_handler.py b/monai/handlers/earlystop_handler.py
--- a/monai/handlers/earlystop_handler.py
+++ b/monai/handlers/earlystop_handler.py
@@ -48,7 +48,30 @@ class EarlyStopHandler:
 
     Note:
         If in distributed training and uses loss value of every iteration to detect early stopping,
-        the values may be different in different ranks.
+        the values may be different in different ranks. When using this handler with distributed training,
+        please also note that to prevent "dist.destroy_process_group()" hangs, you can use an "all_reduce" operation
+        to synchronize the stop signal across all ranks. The mechanism can be implemented in the `score_function`. The following
+        is an example:
+
+        .. code-block:: python
+
+            import os
+
+            import torch
+            import torch.distributed as dist
+
+
+            def score_function(engine):
+                val_metric = engine.state.metrics["val_mean_dice"]
+                if dist.is_initialized():
+                    device = torch.device("cuda:" + os.environ["LOCAL_RANK"])
+                    val_metric = torch.tensor([val_metric]).to(device)
+                    dist.all_reduce(val_metric, op=dist.ReduceOp.SUM)
+                    val_metric /= dist.get_world_size()
+                    return val_metric.item()
+                return val_metric
+
+
         User may attach this handler to validator engine to detect validation metrics and stop the training,
         in this case, the `score_function` is executed on validator engine and `trainer` is the trainer engine.
 


Test patch:
Repository: Project-MONAI/MONAI

Issue:
Unclear statement of `epoch_log` and `iteration_log ` in `TensorBoardStatsHandler`
After removing `epoch_interval` and `iteration_interval` in https://github.com/Project-MONAI/MONAI/pull/7019, the statements of `epoch_log` and `iteration_log` are unclear. They could be boolean/int/callable.
Unclear statement of `epoch_log` and `iteration_log ` in `TensorBoardStatsHandler`
After removing `epoch_interval` and `iteration_interval` in https://github.com/Project-MONAI/MONAI/pull/7019, the statements of `epoch_log` and `iteration_log` are unclear. They could be boolean/int/callable.


Discussion:

Resolving patch:
diff --git a/monai/handlers/tensorboard_handlers.py b/monai/handlers/tensorboard_handlers.py
--- a/monai/handlers/tensorboard_handlers.py
+++ b/monai/handlers/tensorboard_handlers.py
@@ -93,8 +93,8 @@ def __init__(
         self,
         summary_writer: SummaryWriter | SummaryWriterX | None = None,
         log_dir: str = "./runs",
-        iteration_log: bool | Callable[[Engine, int], bool] = True,
-        epoch_log: bool | Callable[[Engine, int], bool] = True,
+        iteration_log: bool | Callable[[Engine, int], bool] | int = True,
+        epoch_log: bool | Callable[[Engine, int], bool] | int = True,
         epoch_event_writer: Callable[[Engine, Any], Any] | None = None,
         epoch_interval: int = 1,
         iteration_event_writer: Callable[[Engine, Any], Any] | None = None,
@@ -110,11 +110,13 @@ def __init__(
                 default to create a new TensorBoard writer.
             log_dir: if using default SummaryWriter, write logs to this directory, default is `./runs`.
             iteration_log: whether to write data to TensorBoard when iteration completed, default to `True`.
-                ``iteration_log`` can be also a function and it will be interpreted as an event filter
+                ``iteration_log`` can be also a function or int. If it is an int, it will be interpreted as the iteration interval
+                at which the iteration_event_writer is called. If it is a function, it will be interpreted as an event filter
                 (see https://pytorch.org/ignite/generated/ignite.engine.events.Events.html for details).
                 Event filter function accepts as input engine and event value (iteration) and should return True/False.
             epoch_log: whether to write data to TensorBoard when epoch completed, default to `True`.
-                ``epoch_log`` can be also a function and it will be interpreted as an event filter.
+                ``epoch_log`` can be also a function or int. If it is an int, it will be interpreted as the epoch interval
+                at which the epoch_event_writer is called. If it is a function, it will be interpreted as an event filter.
                 See ``iteration_log`` argument for more details.
             epoch_event_writer: customized callable TensorBoard writer for epoch level.
                 Must accept parameter "engine" and "summary_writer", use default event writer if None.


Test patch:
Repository: Project-MONAI/MONAI

Issue:
docker tagging no space
https://github.com/Project-MONAI/MONAI/actions/runs/6274006320/job/17039074690
```
--------------------
ERROR: failed to solve: failed to register layer: write /usr/local/nvm/.cache/bin/node-v16.20.0-linux-x64/node-v16.20.0-linux-x64.tar.xz: no space left on device
Error: Process completed with exit code 1.
```


Discussion:

Resolving patch:
diff --git a/monai/networks/nets/segresnet_ds.py b/monai/networks/nets/segresnet_ds.py
--- a/monai/networks/nets/segresnet_ds.py
+++ b/monai/networks/nets/segresnet_ds.py
@@ -127,7 +127,7 @@ def forward(self, x):
 
 class SegResEncoder(nn.Module):
     """
-    SegResEncoder based on the econder structure in `3D MRI brain tumor segmentation using autoencoder regularization
+    SegResEncoder based on the encoder structure in `3D MRI brain tumor segmentation using autoencoder regularization
     <https://arxiv.org/pdf/1810.11654.pdf>`_.
 
     Args:
diff --git a/monai/transforms/utils.py b/monai/transforms/utils.py
--- a/monai/transforms/utils.py
+++ b/monai/transforms/utils.py
@@ -187,7 +187,7 @@ def rescale_array(
     Args:
         arr: input array to rescale.
         minv: minimum value of target rescaled array.
-        maxv: maxmum value of target rescaled array.
+        maxv: maximum value of target rescaled array.
         dtype: if not None, convert input array to dtype before computation.
 
     """


Test patch:
Repository: Project-MONAI/MONAI

Issue:
`SaveImaged` docstrings missing `.dcm` for `output_ext`
`output_ext` actually supports to set `.dcm`


Discussion:
May also missing other supported extension names, would be nice if anyone can help to double check it.

Resolving patch:
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
@@ -198,7 +198,7 @@ class SaveImaged(MapTransform):
                     Handled by ``folder_layout`` instead, if ``folder_layout`` is not ``None``.
         output_postfix: a string appended to all output file names, default to ``trans``.
                         Handled by ``folder_layout`` instead, if ``folder_layout`` is not ``None``.
-        output_ext: output file extension name, available extensions: ``.nii.gz``, ``.nii``, ``.png``.
+        output_ext: output file extension name, available extensions: ``.nii.gz``, ``.nii``, ``.png``, ``.dcm``.
                     Handled by ``folder_layout`` instead, if ``folder_layout`` not ``None``.
         resample: whether to resample image (if needed) before saving the data array,
             based on the ``spatial_shape`` (and ``original_affine``) from metadata.


Test patch:
Repository: Project-MONAI/MONAI

Issue:
Allow different input types for `DataStats` transform by default
**Is your feature request related to a problem? Please describe.**
Currently `DataStats` supports Ndarray or Tensor and breaks by default for any other data type if the `shape` attribute is not available. 

There are four items for DataStats and in the default behavior,
1. data_type: Works irrespective of the provided type.
2. data_shape: Breaks when `shape` attribute is missing
3. value_range: Works irrespective of provided type as there is a conditional check for type
4. data_value: Off by default

**Describe the solution you'd like**
Could we streamline 2 and 3 so that there is a conditional check for the `data_shape` similar to type checks for `value_range`?
https://github.com/Project-MONAI/MONAI/blob/8e99af5f96df0746d6cbcaed88feaea0e51abd56/monai/transforms/utility/array.py#L754

It makes sense that they would work the same and either both break by default or handle arbitrary types by default. 

**Describe alternatives you've considered**
Setting `data_shape` to `False` explicitly works for arbitrary types.




Discussion:

Resolving patch:
diff --git a/monai/transforms/utility/array.py b/monai/transforms/utility/array.py
--- a/monai/transforms/utility/array.py
+++ b/monai/transforms/utility/array.py
@@ -681,7 +681,7 @@ def __call__(
         if self.data_type if data_type is None else data_type:
             lines.append(f"Type: {type(img)} {img.dtype if hasattr(img, 'dtype') else None}")
         if self.data_shape if data_shape is None else data_shape:
-            lines.append(f"Shape: {img.shape}")
+            lines.append(f"Shape: {img.shape if hasattr(img, 'shape') else None}")
         if self.value_range if value_range is None else value_range:
             if isinstance(img, np.ndarray):
                 lines.append(f"Value range: ({np.min(img)}, {np.max(img)})")


Test patch: