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

Issue:
Setting arbitrary num_fold in AutoRunner is permitted regardless the Auto3DSeg datalist doesn't support
**Describe the bug**

The `num_fold` in `AutoRunner` is not checked in the Auto3DSeg pipeline. As a result, the `BundleGen` would create templated algorithms (dints_0, dints_1, dints_<num_fold>) even if there aren't num folds in the datalist.

**To Reproduce**
```
work_dir = "./work_dir"
input = "path/to/input_yaml"
runner = AutoRunner(work_dir=work_dir, input=input)
runner.set_num_fold(n_fold=10000)
```

**Expected behavior**
Should raise an error if the num fold exceeds the max




Discussion:

Resolving patch:
diff --git a/monai/apps/auto3dseg/auto_runner.py b/monai/apps/auto3dseg/auto_runner.py
--- a/monai/apps/auto3dseg/auto_runner.py
+++ b/monai/apps/auto3dseg/auto_runner.py
@@ -298,9 +298,13 @@ def __init__(
                 pass
 
         # inspect and update folds
-        num_fold = self.inspect_datalist_folds(datalist_filename=datalist_filename)
+        self.max_fold = self.inspect_datalist_folds(datalist_filename=datalist_filename)
         if "num_fold" in self.data_src_cfg:
             num_fold = int(self.data_src_cfg["num_fold"])  # override from config
+            logger.info(f"Setting num_fold {num_fold} based on the input config.")
+        else:
+            num_fold = self.max_fold
+            logger.info(f"Setting num_fold {num_fold} based on the input datalist {datalist_filename}.")
 
         self.data_src_cfg["datalist"] = datalist_filename  # update path to a version in work_dir and save user input
         ConfigParser.export_config_file(
@@ -398,7 +402,10 @@ def inspect_datalist_folds(self, datalist_filename: str) -> int:
 
         if len(fold_list) > 0:
             num_fold = max(fold_list) + 1
-            logger.info(f"Setting num_fold {num_fold} based on the input datalist {datalist_filename}.")
+            logger.info(f"Found num_fold {num_fold} based on the input datalist {datalist_filename}.")
+            # check if every fold is present
+            if len(set(fold_list)) != num_fold:
+                raise ValueError(f"Fold numbers are not continuous from 0 to {num_fold - 1}")
         elif "validation" in datalist and len(datalist["validation"]) > 0:
             logger.info("No fold numbers provided, attempting to use a single fold based on the validation key")
             # update the datalist file
@@ -492,6 +499,11 @@ def set_num_fold(self, num_fold: int = 5) -> AutoRunner:
 
         if num_fold <= 0:
             raise ValueError(f"num_fold is expected to be an integer greater than zero. Now it gets {num_fold}")
+        if num_fold > self.max_fold + 1:
+            # Auto3DSeg allows no validation set, so the maximum fold number is max_fold + 1
+            raise ValueError(
+                f"num_fold is greater than the maximum fold number {self.max_fold} in {self.datalist_filename}."
+            )
         self.num_fold = num_fold
 
         return self


Test patch:
Repository: Project-MONAI/MONAI

Issue:
TensorRT throws warning during conversion
**Describe the bug**
TensorRT conversion throws warning:
```
WARNING:torch_tensorrt._compile:Input graph is a Torchscript module but the ir provided is default (dynamo). Please set ir=torchscript to suppress the warning. Compiling the module with ir=torchscript
```

**To Reproduce**
Run the command shown below with the spleen_ct_segmentation bundle in model zoo:
```
python -m monai.bundle trt_export --net_id network_def --filepath models/model_trt.ts --ckpt_file models/model.pt --meta_file configs/metadata.json --config_file configs/inference.json --precision fp32 --dynamic_batchsize "[1, 4, 8]" --use_onnx "False" --use_trace "False"
```

**Expected behavior**
Update the code as the warning suggested.



Discussion:

Resolving patch:
diff --git a/monai/networks/utils.py b/monai/networks/utils.py
--- a/monai/networks/utils.py
+++ b/monai/networks/utils.py
@@ -986,6 +986,7 @@ def scale_batch_size(input_shape: Sequence[int], scale_num: int):
                     inputs=input_placeholder,
                     enabled_precisions=convert_precision,
                     device=target_device,
+                    ir="torchscript",
                     **kwargs,
                 )
 


Test patch:
Repository: Project-MONAI/MONAI

Issue:
Negative strides issue in monai.transforms.LoadImage causes error during collate
**Describe the bug**
When using `monai.transforms.LoadImage` with the nrrdreader to load an NRRD file, the resulting image metadata contains negative strides. This negative strides issue leads to an error when the tensor is collated.

**To Reproduce**
```
import monai

# Load an NRRD file
img = monai.transforms.LoadImage(reader="nrrdreader", index_order="C")("wrong_something.nrrd")

print(img.meta['spatial_shape'].strides)  # Output: (-8,)
```
Error log:
```
torch/utils/data/_utils/collate.py", line 222, in <listcomp>
    return collate([torch.as_tensor(b) for b in batch], collate_fn_map=collate_fn_map)
ValueError: At least one stride in the given numpy array is negative, and tensors with negative strides are not currently supported. (You can probably work around this by making a copy of your array  with array.copy().)
```
Test data:
https://drive.google.com/file/d/1Et-khdsou7E2T_aoX0zLvnld49Xh8YDn/view?usp=drive_link
Negative strides issue in monai.transforms.LoadImage causes error during collate
**Describe the bug**
When using `monai.transforms.LoadImage` with the nrrdreader to load an NRRD file, the resulting image metadata contains negative strides. This negative strides issue leads to an error when the tensor is collated.

**To Reproduce**
```
import monai

# Load an NRRD file
img = monai.transforms.LoadImage(reader="nrrdreader", index_order="C")("wrong_something.nrrd")

print(img.meta['spatial_shape'].strides)  # Output: (-8,)
```
Error log:
```
torch/utils/data/_utils/collate.py", line 222, in <listcomp>
    return collate([torch.as_tensor(b) for b in batch], collate_fn_map=collate_fn_map)
ValueError: At least one stride in the given numpy array is negative, and tensors with negative strides are not currently supported. (You can probably work around this by making a copy of your array  with array.copy().)
```
Test data:
https://drive.google.com/file/d/1Et-khdsou7E2T_aoX0zLvnld49Xh8YDn/view?usp=drive_link


Discussion:

Resolving patch:
diff --git a/monai/data/image_reader.py b/monai/data/image_reader.py
--- a/monai/data/image_reader.py
+++ b/monai/data/image_reader.py
@@ -1331,7 +1331,7 @@ def get_data(self, img: NrrdImage | list[NrrdImage]) -> tuple[np.ndarray, dict]:
                 header[MetaKeys.SPACE] = SpaceKeys.LPS  # assuming LPS if not specified
 
             header[MetaKeys.AFFINE] = header[MetaKeys.ORIGINAL_AFFINE].copy()
-            header[MetaKeys.SPATIAL_SHAPE] = header["sizes"]
+            header[MetaKeys.SPATIAL_SHAPE] = header["sizes"].copy()
             [header.pop(k) for k in ("sizes", "space origin", "space directions")]  # rm duplicated data in header
 
             if self.channel_dim is None:  # default to "no_channel" or -1


Test patch:
Repository: Project-MONAI/MONAI

Issue:
'load_module()' deprecated in Python 3.12
```
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/yunliu/Workspace/Code/MONAI/monai/__init__.py", line 58, in <module>
    load_submodules(sys.modules[__name__], False, exclude_pattern=excludes)
  File "/home/yunliu/Workspace/Code/MONAI/monai/utils/module.py", line 212, in load_submodules
    importer.find_spec(name).loader.load_module(name)  # type: ignore
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap_external>", line 605, in _check_name_wrapper
  File "<frozen importlib._bootstrap_external>", line 1120, in load_module
  File "<frozen importlib._bootstrap_external>", line 945, in load_module
  File "<frozen importlib._bootstrap>", line 283, in _load_module_shim
DeprecationWarning: the load_module() method is deprecated and slated for removal in Python 3.12; use exec_module() instead
```
'load_module()' deprecated in Python 3.12
```
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/yunliu/Workspace/Code/MONAI/monai/__init__.py", line 58, in <module>
    load_submodules(sys.modules[__name__], False, exclude_pattern=excludes)
  File "/home/yunliu/Workspace/Code/MONAI/monai/utils/module.py", line 212, in load_submodules
    importer.find_spec(name).loader.load_module(name)  # type: ignore
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap_external>", line 605, in _check_name_wrapper
  File "<frozen importlib._bootstrap_external>", line 1120, in load_module
  File "<frozen importlib._bootstrap_external>", line 945, in load_module
  File "<frozen importlib._bootstrap>", line 283, in _load_module_shim
DeprecationWarning: the load_module() method is deprecated and slated for removal in Python 3.12; use exec_module() instead
```


Discussion:

Resolving patch:
diff --git a/monai/utils/module.py b/monai/utils/module.py
--- a/monai/utils/module.py
+++ b/monai/utils/module.py
@@ -13,6 +13,7 @@
 
 import enum
 import functools
+import importlib.util
 import os
 import pdb
 import re
@@ -208,9 +209,11 @@ def load_submodules(
     ):
         if (is_pkg or load_all) and name not in sys.modules and match(exclude_pattern, name) is None:
             try:
-                mod = import_module(name)
-                importer.find_spec(name).loader.load_module(name)  # type: ignore
-                submodules.append(mod)
+                mod_spec = importer.find_spec(name)  # type: ignore
+                if mod_spec and mod_spec.loader:
+                    mod = importlib.util.module_from_spec(mod_spec)
+                    mod_spec.loader.exec_module(mod)
+                    submodules.append(mod)
             except OptionalImportError:
                 pass  # could not import the optional deps., they are ignored
             except ImportError as e:


Test patch:
Repository: Project-MONAI/MONAI

Issue:
distutils is removed in python 3.12+
**Describe the bug**
distutils (and by extension strtobool) is deprecated in python3.12

**To Reproduce**
Try to run in python 3.12

**Expected behavior**
MONAI should work in python 3.12

**Environment**

Both Mac and Linux.




Discussion:

Resolving patch:
diff --git a/monai/utils/misc.py b/monai/utils/misc.py
--- a/monai/utils/misc.py
+++ b/monai/utils/misc.py
@@ -24,7 +24,6 @@
 import warnings
 from ast import literal_eval
 from collections.abc import Callable, Iterable, Sequence
-from distutils.util import strtobool
 from math import log10
 from pathlib import Path
 from typing import TYPE_CHECKING, Any, TypeVar, cast, overload
@@ -78,6 +77,25 @@
     "run_cmd",
 ]
 
+
+def _strtobool(val: str) -> bool:
+    """
+    Replaces deprecated (pre python 3.12)
+    distutils strtobool function.
+
+    True values are y, yes, t, true, on and 1;
+    False values are n, no, f, false, off and 0.
+    Raises ValueError if val is anything else.
+    """
+    val = val.lower()
+    if val in ("y", "yes", "t", "true", "on", "1"):
+        return True
+    elif val in ("n", "no", "f", "false", "off", "0"):
+        return False
+    else:
+        raise ValueError(f"invalid truth value {val}")
+
+
 _seed = None
 _flag_deterministic = torch.backends.cudnn.deterministic
 _flag_cudnn_benchmark = torch.backends.cudnn.benchmark
@@ -400,7 +418,7 @@ def _parse_var(s):
                 d[key] = literal_eval(value)
             except ValueError:
                 try:
-                    d[key] = bool(strtobool(str(value)))
+                    d[key] = bool(_strtobool(str(value)))
                 except ValueError:
                     d[key] = value
     return d


Test patch:
Repository: wright-group/WrightTools

Issue:
link to github on sphinx docs



Discussion:

Resolving patch:
diff --git a/docs/conf.py b/docs/conf.py
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -100,6 +100,15 @@
 #
 # html_theme_options = {}
 
+# HTML context adapted from http://docs.readthedocs.io/en/latest/vcs.html
+html_context = {
+    "display_github": True, # Integrate GitHub
+    "github_user": "wright-group", # Username
+    "github_repo": "WrightTools", # Repo name
+    "github_version": "documentation", # Version
+    "conf_py_path": "/docs/", # Path in the checkout to the docs root
+}
+
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".


Test patch:
Repository: wright-group/WrightTools

Issue:
Behavior of wt.artists.set_fig_labels() does not conform to documented or expected behavior
`set_fig_labels` has the kwarg `label_fontsize`, but it doesn't pass this kwarg to the `set_ac_labels` method it calls. This is an easy fix.



Discussion:
@darienmorrow thanks for rooting that out :heart:

Resolving patch:
diff --git a/WrightTools/artists.py b/WrightTools/artists.py
--- a/WrightTools/artists.py
+++ b/WrightTools/artists.py
@@ -1101,13 +1101,13 @@ def set_fig_labels(fig=None, xlabel=None, ylabel=None, xticks=None, yticks=None,
     for ax in fig.axes:
         if ax.is_first_col() and ax.is_last_row():
             # lower left corner
-            set_ax_labels(ax=ax, xlabel=xlabel, ylabel=ylabel, xticks=xticks, yticks=yticks)
+            set_ax_labels(ax=ax, xlabel=xlabel, ylabel=ylabel, xticks=xticks, yticks=yticks, label_fontsize=label_fontsize)
         elif ax.is_first_col():
             # lefthand column
-            set_ax_labels(ax=ax, ylabel=ylabel, xticks=False, yticks=yticks)
+            set_ax_labels(ax=ax, ylabel=ylabel, xticks=False, yticks=yticks, label_fontsize=label_fontsize)
         elif ax.is_last_row():
             # bottom row
-            set_ax_labels(ax=ax, xlabel=xlabel, xticks=xticks, yticks=False)
+            set_ax_labels(ax=ax, xlabel=xlabel, xticks=xticks, yticks=False, label_fontsize=label_fontsize)
         else:
             set_ax_labels(ax=ax, xticks=False, yticks=False)
     # title


Test patch:
Repository: wright-group/WrightTools

Issue:
workup.panda docstring description



Discussion:
Can we delete workup.panda instead? I don't know who put it in, I suspect @neffmallon.

Resolving patch:
diff --git a/WrightTools/tuning/workup.py b/WrightTools/tuning/workup.py
--- a/WrightTools/tuning/workup.py
+++ b/WrightTools/tuning/workup.py
@@ -36,8 +36,6 @@
 import scipy.integrate as integrate
 from scipy.optimize import leastsq
 
-from pylab import *
-
 from . import curve as wt_curve
 from .. import artists as wt_artists
 from .. import data as wt_data
@@ -248,51 +246,3 @@ def tune_test(data, curve, channel_name, level=False, cutoff_factor=0.01,
         p = os.path.join(save_directory, 'tune test.png')
         wt_artists.savefig(p, fig=fig)
     return curve
-
-
-def panda(data, curve, channel_name, level=False, cutoff_factor=0.01,
-          autosave=True, save_directory=None):
-    """
-
-    Parameters
-    ----------
-    data : wt.data.Data object
-        should be in (setpoint, detuning)
-    curve : wt.curve object
-        tuning curve used to do tune_test
-    channel_nam : str
-        name of the signal chanel to evalute
-    level : bool (optional)
-        does nothing, default is False
-    cutoff_factor : float (optoinal)
-        minimum value for datapoint/max(datapoints) for point to be included
-        in the fitting procedure, default is 0.01
-    autosave : bool (optional)
-        saves output curve if True, default is True
-    save_directory : str
-        directory to save new curve, default is None which uses the data source
-        directory
-
-    Returns
-    -------
-    curve
-        New curve object.
-    """
-    # make data object
-    data.bring_to_front(channel_name)
-    data.transpose()
-    # process data ------------------------------------------------------------
-    # cutoff
-    channel_index = data.channel_names.index(channel_name)
-    channel = data.channels[channel_index]
-    cutoff = np.nanmax(channel.values) * cutoff_factor
-    channel.values[channel.values < cutoff] = np.nan
-    # fit
-    # TODO: evaluate suggested edits to fit section
-    function = wt_fit.Moments()
-    fitter = wt_fit.Fitter(function, data, data.axes[0].name)
-    outs = fitter.run()
-    gauss_function = wt_fit.Gaussian()
-    g_fitter = wt_fit.Fitter(gauss_function, data, data.axes[0].name)
-    gauss_outs = g_fitter.run()
-    return gauss_outs


Test patch:
Repository: wright-group/WrightTools

Issue:
wt.artists.Axes.contourf fails to plot entire dynamic range of data



Discussion:

Resolving patch:
diff --git a/WrightTools/artists.py b/WrightTools/artists.py
--- a/WrightTools/artists.py
+++ b/WrightTools/artists.py
@@ -85,10 +85,30 @@ def add_sideplot(self, along, pad=0, height=0.75, ymin=0, ymax=1.1):
         return ax
 
     def contourf(self, *args, **kwargs):
+        # I'm overloading contourf in an attempt to fix aliasing problems when saving vector graphics
+        # see https://stackoverflow.com/questions/15822159
+        # also see https://stackoverflow.com/a/32911283
+        # set_edgecolor('face') does indeed remove all of the aliasing problems
+        # unfortunately, it also seems to distort the plot in a subtle but important way
+        # it shifts the entire colorbar down w.r.t. the data (by one contour? not clear)
+        # so for now, I am trying to fix the problem by adding contour just below contourf
+        # this does not perfectly get rid of the aliasing, but it doesn't distort the data
+        # which is more important
+        # I anticipate that this method will be tinkered with in the future
+        # so I've left the things I have tried and abandoned as comments---good luck!
+        # ---Blaise 2017-07-30
+        kwargs['antialiased'] = False
+        kwargs['extend'] = 'both'
         contours = matplotlib.axes.Axes.contourf(self, *args, **kwargs)  # why can't I use super?
-        # from http://stackoverflow.com/a/32911283/2860501
+        # fill lines
+        zorder = contours.collections[0].zorder - 0.1
+        matplotlib.axes.Axes.contour(self, *args[:3], len(contours.levels), cmap=contours.cmap,
+                                     zorder=zorder)
+        # PathCollection modifications
         for c in contours.collections:
-            c.set_edgecolor('face')
+            pass
+            #c.set_rasterized(True)
+            #c.set_edgecolor('face')
         return contours
 
     def legend(self, *args, **kwargs):


Test patch:
Repository: wright-group/WrightTools

Issue:
znull should never be outside of [zmin, zmax]
I think that it never makes sense for a channel's znull to be outside of [zmin, zmax].

I plan to enforce this by changing Channel._update:

``` python
def _update(self):
    self.zmin = np.nanmin(self.values)
    self.zmax = np.nanmax(self.values)
    self.znull = max(self.zmin, min(self.znull, self.zmax))
```
(the assignment to znull is new)

This will fix the annoying problem that @ksunden experienced today with `Data.clip`.


Discussion:

Resolving patch:
diff --git a/WrightTools/data.py b/WrightTools/data.py
--- a/WrightTools/data.py
+++ b/WrightTools/data.py
@@ -172,6 +172,7 @@ def __repr__(self):
     def _update(self):
         self.zmin = np.nanmin(self.values)
         self.zmax = np.nanmax(self.values)
+        self.znull = self.znull = max(self.zmin, min(self.znull, self.zmax))
 
     def _pupdate(self, *args, **kwargs):
         return self._update(*args, **kwargs)


Test patch:
Repository: wright-group/WrightTools

Issue:
illegal characters in axis names
WrightTools allows me to create an axis with name `'w2=w1'` but this is not a python recognizable object attribute due to the character `=`. 

This is annoying because the way one generally gets the points of an axis is to write `d.w2.points` but in this case, `d.w2=w1.points` is not allowed by python. So one must resort to `d.axes[0].points`.


Discussion:

[000.zip](https://github.com/wright-group/WrightTools/files/1212410/000.zip)
Here is a .zip file that contains a .data file which has an example of an illegal axis name.

Resolving patch:
diff --git a/WrightTools/data.py b/WrightTools/data.py
--- a/WrightTools/data.py
+++ b/WrightTools/data.py
@@ -54,7 +54,7 @@ class Axis:
     def __init__(self, points, units, symbol_type=None,
                  tolerance=None, file_idx=None,
                  name='', label_seed=[''], **kwargs):
-        self.name = name
+        self.name = wt_kit.string2identifier(name)
         self.tolerance = tolerance
         self.points = np.asarray(points)
         self.units = units
@@ -157,7 +157,7 @@ class Channel:
     def __init__(self, values, units=None, file_idx=None, null=None, signed=None, name='channel',
                  label=None, label_seed=None):
         # import
-        self.name = name
+        self.name = wt_kit.string2identifier(name)
         self.label = label
         self.label_seed = label_seed
         self.units = units
diff --git a/WrightTools/kit.py b/WrightTools/kit.py
--- a/WrightTools/kit.py
+++ b/WrightTools/kit.py
@@ -16,6 +16,7 @@
 import time
 import pytz
 import h5py
+import string
 import warnings
 import dateutil
 import datetime
@@ -1239,6 +1240,32 @@ def string2array(string, sep='\t'):
     return arr
 
 
+def string2identifier(s):
+    """Turns a string into a valid python identifier.
+
+    Parameters
+    ----------
+    s : string
+        string to convert
+
+    Returns
+    -------
+    str
+        valid python identifier.
+    """
+    # https://docs.python.org/3/reference/lexical_analysis.html#identifiers
+    if s[0] not in string.ascii_letters:
+        s = '_' + s
+    valids = string.ascii_letters + string.digits + '_'
+    out = ''
+    for i, char in enumerate(s):
+        if char in valids:
+            out += char
+        else:
+            out += '_'
+    return out
+
+
 def string2item(string, sep='\t'):
     # TODO: document
     if string[0] == '\'' and string[-1] == '\'':


Test patch: