internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: pytorch/ignite

Issue:
Fix a few bugs in engine interrupt/resume feature
## 🐛 Bug description

- [ ] A typo in [docstrings](https://github.com/pytorch/ignite/blob/c12ad57e26aa8ec2b191ff4bc0e01e97ef24f8f7/ignite/engine/engine.py#L34). 0.4.10 or 0.5.0?
- [ ] ~~`_run_once_on_dataset_as_gen` is restarted (because it is called) whenever we get into `_internal_run_as_gen`~~
- [ ] ~~Some statements before `_run_once_on_dataset_as_gen` should be skipped on resume and some other after that should be skipped on interrupt~~
- [ ] ~~Once running after a terminated state, `_run_once_on_dataset_as_gen` should be set to None before entering `_internal_run`.~~
- [ ] ~~If engine was interrupted in the middle of the last epoch, `is_done` incorrectly returns True on resume thus preventing it.~~
- [ ] ~~`_run_once_on_dataset_as_gen` yields the state on interrupt, not the time, so [this](https://github.com/pytorch/ignite/blob/c12ad57e26aa8ec2b191ff4bc0e01e97ef24f8f7/ignite/engine/engine.py#L965) shoud be changed.~~
- [ ] Since `_run_once_on_dataset_as_gen` has both return value and yield value with different types, its annotation could be updated to reflect this e.g. become `Generator[State, None, float]`


Discussion:
> A typo in [docstrings](https://github.com/pytorch/ignite/blob/c12ad57e26aa8ec2b191ff4bc0e01e97ef24f8f7/ignite/engine/engine.py#L34). 0.4.10 or 0.5.0?

v0.5.0 is correct.

@sadra-barikbin for other points can you provide a repro for each statement to see exactly how it is failing ? Thanks!

Resolving patch:
diff --git a/ignite/engine/engine.py b/ignite/engine/engine.py
--- a/ignite/engine/engine.py
+++ b/ignite/engine/engine.py
@@ -31,7 +31,7 @@ class Engine(Serializable):
         last_event_name: last event name triggered by the engine.
 
     Note:
-        :class:`~ignite.engine.engine.Engine` implementation has changed in v0.4.10 with "interrupt/resume" feature.
+        :class:`~ignite.engine.engine.Engine` implementation has changed in v0.5.0 with "interrupt/resume" feature.
         Engine may behave differently on certain corner cases compared to the one from v0.4.9 and before.
         In such case, you can set ``Engine.interrupt_resume_enabled = False`` to restore previous behaviour.
 
@@ -1013,7 +1013,7 @@ def _maybe_terminate_or_interrupt(self) -> Generator:
             self.should_interrupt = False
             yield self.state
 
-    def _run_once_on_dataset_as_gen(self) -> Generator:
+    def _run_once_on_dataset_as_gen(self) -> Generator[State, None, float]:
         start_time = time.time()
 
         # We need to setup iter_counter > 0 if we resume from an iteration


Test patch:
Repository: pytorch/ignite

Issue:
mypy issue on master
```bash
Run bash ./tests/run_code_style.sh mypy
+ '[' mypy = lint ']'
+ '[' mypy = fmt ']'
+ '[' mypy = mypy ']'
+ mypy --config-file mypy.ini
ignite/distributed/comp_models/native.py:125: error: Argument 3 to
"init_process_group" has incompatible type "**Dict[str, int]"; expected
"timedelta"  [arg-type]
    ...init_process_group(backend, init_method=init_method, **init_pg_kwargs)
                                                              ^
ignite/distributed/comp_models/native.py:125: error: Argument 3 to
"init_process_group" has incompatible type "**Dict[str, int]"; expected
"Optional[Store]"  [arg-type]
    ...init_process_group(backend, init_method=init_method, **init_pg_kwargs)
                                                              ^
ignite/distributed/comp_models/native.py:125: error: Argument 3 to
"init_process_group" has incompatible type "**Dict[str, int]"; expected "str" 
[arg-type]
    ...init_process_group(backend, init_method=init_method, **init_pg_kwargs)
                                                              ^
Found 3 errors in 1 file (checked 103 source files)
```


Discussion:

Resolving patch:
diff --git a/ignite/distributed/comp_models/native.py b/ignite/distributed/comp_models/native.py
--- a/ignite/distributed/comp_models/native.py
+++ b/ignite/distributed/comp_models/native.py
@@ -110,7 +110,7 @@ def _create_from_backend(
             self._backend = backend
             self.setup_env_vars(rank, world_size)
 
-            init_pg_kwargs = {}
+            init_pg_kwargs: Dict[str, Any] = {}
             if timeout is not None:
                 init_pg_kwargs["timeout"] = timeout
 


Test patch:
Repository: pytorch/ignite

Issue:
Update Polyaxon_logger example for v1.X
## 📚 Documentation

- https://pytorch.org/ignite/generated/ignite.contrib.handlers.polyaxon_logger.html#ignite.contrib.handlers.polyaxon_logger.PolyaxonLogger

```python
# Log experiment parameters with <1.0
plx_logger.log_params(**{
    "seed": seed,
    "batch_size": batch_size,
    "model": model.__class__.__name__,
    "pytorch version": torch.__version__,
    "ignite version": ignite.__version__,
    "cuda version": torch.version.cuda,
    "device name": torch.cuda.get_device_name(0)
})
```
and for >=1.X one should do
```python
plx_logger.log_inputs(**{
    "seed": seed,
    "batch_size": batch_size,
    "model": model.__class__.__name__,
    "pytorch version": torch.__version__,
    "ignite version": ignite.__version__,
    "cuda version": torch.version.cuda,
    "device name": torch.cuda.get_device_name(0)
})
```
- https://polyaxon.com/integrations/tracking-ignite/


Let's add newer option instead of the old one



Discussion:

Resolving patch:
diff --git a/examples/references/classification/imagenet/code/utils/exp_tracking.py b/examples/references/classification/imagenet/code/utils/exp_tracking.py
--- a/examples/references/classification/imagenet/code/utils/exp_tracking.py
+++ b/examples/references/classification/imagenet/code/utils/exp_tracking.py
@@ -69,8 +69,8 @@ def _plx_log_params(params_dict):
     from polyaxon_client.tracking import Experiment
 
     plx_exp = Experiment()
-    plx_exp.log_params(**{"pytorch version": torch.__version__, "ignite version": ignite.__version__})
-    plx_exp.log_params(**params_dict)
+    plx_exp.log_inputs(**{"pytorch version": torch.__version__, "ignite version": ignite.__version__})
+    plx_exp.log_inputs(**params_dict)
 
 
 def _mlflow_get_output_path():
diff --git a/ignite/contrib/handlers/polyaxon_logger.py b/ignite/contrib/handlers/polyaxon_logger.py
--- a/ignite/contrib/handlers/polyaxon_logger.py
+++ b/ignite/contrib/handlers/polyaxon_logger.py
@@ -40,7 +40,7 @@ class PolyaxonLogger(BaseLogger):
             plx_logger = PolyaxonLogger()
 
             # Log experiment parameters:
-            plx_logger.log_params(**{
+            plx_logger.log_inputs(**{
                 "seed": seed,
                 "batch_size": batch_size,
                 "model": model.__class__.__name__,


Test patch:
Repository: pytorch/ignite

Issue:
Scheduled workflow failed
Oh no, something went wrong in the scheduled workflow **Nightly Releases with commit 743ff31dbb8f9750ef403c0a022ad2339819c5a8**.
Please look into it:

https://github.com/pytorch/ignite/actions/runs/3878889619

Feel free to close this if this was just a one-off error.



Discussion:

Resolving patch:
diff --git a/ignite/distributed/comp_models/native.py b/ignite/distributed/comp_models/native.py
--- a/ignite/distributed/comp_models/native.py
+++ b/ignite/distributed/comp_models/native.py
@@ -154,6 +154,7 @@ def _compute_nproc_per_node(self) -> int:
             gloo_group = dist.new_group(backend="gloo")
             tensor = torch.tensor([local_rank + 1]).to("cpu")
             dist.all_reduce(tensor, op=dist.ReduceOp.MAX, group=gloo_group)
+            dist.destroy_process_group(gloo_group)
             return int(tensor.item())
 
         def _get_all_hostnames(self) -> List[Tuple[str, ...]]:
@@ -379,7 +380,7 @@ def spawn(
                     default_start_method = "spawn"
                 spawn_kwargs["start_method"] = kwargs.get("start_method", default_start_method)
                 start_processes = mp.start_processes
-
+            # TODO: `spawn` wrongfully does not adopt address and port from environment if `init_method` is "env://"
             if init_method in [None, "env://"]:
                 init_method = "env://"
                 if master_port is None:


Test patch:
Repository: pytorch/ignite

Issue:
Issue with Enum on Python3.11
## 🐛 Bug description

Importing `ignite.distributed` fails on Python3.11. 

To reproduce: 
```bash
python3.11 -m pip install pytorch-ignite
python3.11 -c 'import ignite.distributed'
```

I get the following `AttributeError`: 
```python
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/opt/homebrew/lib/python3.11/site-packages/ignite/__init__.py", line 3, in <module>
    import ignite.engine
  File "/opt/homebrew/lib/python3.11/site-packages/ignite/engine/__init__.py", line 7, in <module>
    from ignite.engine.deterministic import DeterministicEngine
  File "/opt/homebrew/lib/python3.11/site-packages/ignite/engine/deterministic.py", line 11, in <module>
    from ignite.engine.engine import Engine
  File "/opt/homebrew/lib/python3.11/site-packages/ignite/engine/engine.py", line 13, in <module>
    from ignite.engine.events import CallableEventWithFilter, EventEnum, Events, EventsList, RemovableEventHandle, State
  File "/opt/homebrew/lib/python3.11/site-packages/ignite/engine/events.py", line 254, in <module>
    class Events(EventEnum):
  File "/opt/homebrew/Cellar/python@3.11/3.11.2_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/enum.py", line 560, in __new__
    raise exc
  File "/opt/homebrew/Cellar/python@3.11/3.11.2_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/enum.py", line 280, in __set_name__
    enum_member = enum_class._value2member_map_[value]
                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/ignite/engine/events.py", line 200, in __hash__
    return hash(self._name_)
                ^^^^^^^^^^^
AttributeError: 'CallableEventWithFilter' object has no attribute '_name_'. Did you mean: 'name'?
```
<!-- A clear and concise description of what the bug is. -->
<!-- Please, add steps on how to reproduce it. -->
<!-- If you have a code sample, error messages, stack traces, please provide it here as well -->
<!-- A clear and concise description of what you expected to happen. -->

## Environment

- PyTorch Version: 2.0.0
- Ignite Version: 0.4.11
- OS (e.g., Linux): macOS Ventura 13.2.1
- How you installed Ignite: `pip`
- Python version: 3.11



Discussion:
@kalkun thanks a lot for reporting this issue! Definitely, we have to fix this.

Resolving patch:
diff --git a/ignite/engine/events.py b/ignite/engine/events.py
--- a/ignite/engine/events.py
+++ b/ignite/engine/events.py
@@ -237,7 +237,10 @@ def function_before_backprop(engine):
                 # ...
     """
 
-    pass
+    def __new__(cls, value: str) -> "EventEnum":
+        obj = CallableEventWithFilter.__new__(cls)
+        obj._value_ = value
+        return obj
 
 
 class Events(EventEnum):


Test patch:
Repository: pytorch/ignite

Issue:
Minor Bug | metrics.ssim, produces empty tensors in update function
## 🐛 Bug description

In line 165
```
output_list = [outputs[x * y_pred.size(0) : (x + 1) * y_pred.size(0)] for x in range(len(outputs))]
```
the list comprehension produces a list with `len  = (Batch_size * 5)`, where only the first 5 elements are valid and correspond to stacked `[y_pred, y, y_pred * y_pred, y * y, y_pred * y]` of all the batches, in cases where the batch size is greater than one the elements with index>4 are empty `torch.Tensors` with shape `(0, C, H, W)` .

### Solution
This bug neither affects the output, nor consumes a lot of RAM, but I thought I should point it out.
The fix for this is pretty simple and you only need to divide the len of outputs by the batch size.
```
output_list = [outputs[x * y_pred.size(0) : (x + 1) * y_pred.size(0)] for x in range(int(len(outputs)/y_pred.size(0)))] # len(outputs) is B*5 so we need to divide it by B so it's only 5 -> [y_pred, y, y_pred * y_pred, y * y, y_pred * y]
```



Discussion:
@moienr thanks for reporting! Can you please provide a code snippet to reproduce the issue and also get it right?

Resolving patch:
diff --git a/ignite/metrics/ssim.py b/ignite/metrics/ssim.py
--- a/ignite/metrics/ssim.py
+++ b/ignite/metrics/ssim.py
@@ -159,10 +159,10 @@ def update(self, output: Sequence[torch.Tensor]) -> None:
         y_pred = F.pad(y_pred, [self.pad_w, self.pad_w, self.pad_h, self.pad_h], mode="reflect")
         y = F.pad(y, [self.pad_w, self.pad_w, self.pad_h, self.pad_h], mode="reflect")
 
-        input_list = torch.cat([y_pred, y, y_pred * y_pred, y * y, y_pred * y])
-        outputs = F.conv2d(input_list, self._kernel, groups=channel)
-
-        output_list = [outputs[x * y_pred.size(0) : (x + 1) * y_pred.size(0)] for x in range(len(outputs))]
+        input_list = [y_pred, y, y_pred * y_pred, y * y, y_pred * y]
+        outputs = F.conv2d(torch.cat(input_list), self._kernel, groups=channel)
+        batch_size = y_pred.size(0)
+        output_list = [outputs[x * batch_size : (x + 1) * batch_size] for x in range(len(input_list))]
 
         mu_pred_sq = output_list[0].pow(2)
         mu_target_sq = output_list[1].pow(2)


Test patch:
Repository: pytorch/ignite

Issue:
Scheduled workflow failed
Oh no, something went wrong in the scheduled workflow **PyTorch version tests with commit e9e5b45d08b8c5008a30a7d79b5ab08e313d2c8b**.
Please look into it:

https://github.com/pytorch/ignite/actions/runs/5074580573

Feel free to close this if this was just a one-off error.



Discussion:

Resolving patch:
diff --git a/ignite/handlers/param_scheduler.py b/ignite/handlers/param_scheduler.py
--- a/ignite/handlers/param_scheduler.py
+++ b/ignite/handlers/param_scheduler.py
@@ -809,12 +809,8 @@ def optimizer(self) -> torch.optim.Optimizer:
         return self._lr_scheduler.optimizer
 
     def get_lr(self, epoch: Optional[int] = None) -> List[float]:
-        # TODO: Remove this workaround when pytorch has fixed wrong type hints:
-        # https://github.com/pytorch/pytorch/pull/102067
-        # Replace below T_mult -> self._lr_scheduler.T_mult
-        # Replace below eta_min -> self._lr_scheduler.eta_min
-        T_mult = cast(int, self._lr_scheduler.T_mult)
-        eta_min = cast(float, self._lr_scheduler.eta_min)
+        T_mult = self._lr_scheduler.T_mult
+        eta_min = self._lr_scheduler.eta_min
 
         if epoch is None and self.last_epoch < 0:
             epoch = 0


Test patch:
diff --git a/tests/ignite/handlers/test_param_scheduler.py b/tests/ignite/handlers/test_param_scheduler.py
--- a/tests/ignite/handlers/test_param_scheduler.py
+++ b/tests/ignite/handlers/test_param_scheduler.py
@@ -1378,7 +1378,7 @@ def get_optim():
         return torch.optim.SGD([t1], lr=lr)
 
     def get_cos_shed():
-        return CosineAnnealingWarmRestarts(optimizer, T_0=T_0, T_mult=T_mult, verbose=False)
+        return CosineAnnealingWarmRestarts(optimizer, T_0=T_0, T_mult=T_mult)
 
     optimizer = get_optim()
     scheduler = get_cos_shed()
Repository: pytorch/ignite

Issue:
Fix warning in fast_neural_style example
Here is another good first issue to improve the ignite project. Currently, we have a warning on this line: https://github.com/pytorch/ignite/blob/master/examples/fast_neural_style/vgg.py#L10 (fast neural style example)
 /opt/hostedtoolcache/Python/3.9.17/x64/lib/python3.9/site-packages/torchvision/models/_utils.py:208: UserWarning: The parameter 'pretrained' is deprecated since 0.13 and may be removed in the future, please use 'weights' instead.
  warnings.warn(
/opt/hostedtoolcache/Python/3.9.17/x64/lib/python3.9/site-packages/torchvision/models/_utils.py:223: UserWarning: Arguments other than a weight enum or `None` for 'weights' are deprecated since 0.13 and may be removed in the future. The current behavior is equivalent to passing `weights=VGG16_Weights.IMAGENET1K_V1`. You can also use `weights=VGG16_Weights.DEFAULT` to get the most up-to-date weights.


Discussion:

Resolving patch:
diff --git a/examples/fast_neural_style/vgg.py b/examples/fast_neural_style/vgg.py
--- a/examples/fast_neural_style/vgg.py
+++ b/examples/fast_neural_style/vgg.py
@@ -2,12 +2,13 @@
 
 import torch
 from torchvision import models
+from torchvision.models.vgg import VGG16_Weights
 
 
 class Vgg16(torch.nn.Module):
     def __init__(self, requires_grad=False):
         super(Vgg16, self).__init__()
-        vgg_pretrained_features = models.vgg16(pretrained=True).features
+        vgg_pretrained_features = models.vgg16(weights=VGG16_Weights.IMAGENET1K_V1).features
         self.slice1 = torch.nn.Sequential()
         self.slice2 = torch.nn.Sequential()
         self.slice3 = torch.nn.Sequential()


Test patch:
Repository: pytorch/ignite

Issue:
Mean Absolute Percentage Error (MAPE)
## 🚀 Feature

I'd like to implement the mean absolute percentage error [(MAPE)](https://en.wikipedia.org/wiki/Mean_absolute_percentage_error) in `ignite/metrics`.

It is a commonly used metric for regression problems and it would be really convenient to be able to use it directly with ignite evaluators.

For that, I would write a custom Metric class in a new file `mean_absolute_percentage_error.py` inheriting from the base `Metric` class in `ignite/metrics/metric.py`.



Discussion:
@aalbayrak394 thanks for asking, ~we have this metric in ignite contrib metrics: https://pytorch.org/ignite/v0.4.13/generated/ignite.contrib.metrics.regression.MedianAbsolutePercentageError.html~

EDIT: sorry, misread mean vs median.

~yes, let's add it into contrib/regression metrics~

OK, MAPE is also MARE: https://pytorch.org/ignite/v0.4.13/generated/ignite.contrib.metrics.regression.MeanAbsoluteRelativeError.html#ignite.contrib.metrics.regression.MeanAbsoluteRelativeError

Let's make a shortcut and improve docs for better discovery.
What do you think ?
Sure, that would make more sense. Maybe adding ", also known as Mean Absolute Percentage Error" to the first line of the doc would do it?
Yeah, and also add "(MAPE)" and "(MARE)" like that:
```
Calculate Mean Absolute Relative Error (MARE), also known as Mean Absolute Percentage Error (MAPE).
```


Resolving patch:
diff --git a/ignite/contrib/metrics/regression/mean_absolute_relative_error.py b/ignite/contrib/metrics/regression/mean_absolute_relative_error.py
--- a/ignite/contrib/metrics/regression/mean_absolute_relative_error.py
+++ b/ignite/contrib/metrics/regression/mean_absolute_relative_error.py
@@ -8,7 +8,7 @@
 
 
 class MeanAbsoluteRelativeError(_BaseRegression):
-    r"""Calculate Mean Absolute Relative Error.
+    r"""Calculate Mean Absolute Relative Error (MARE), also known as Mean Absolute Percentage Error (MAPE).
 
     .. math::
         \text{MARE} = \frac{1}{n}\sum_{j=1}^n\frac{\left|A_j-P_j\right|}{\left|A_j\right|}


Test patch:
Repository: pytorch/ignite

Issue:
Add python 3.12 to CI
## 🚀 Feature

Add python 3.12 to CI: https://github.com/pytorch/ignite/blob/master/.github/workflows/unit-tests.yml



Discussion:

Resolving patch:
diff --git a/examples/mnist/mnist.py b/examples/mnist/mnist.py
--- a/examples/mnist/mnist.py
+++ b/examples/mnist/mnist.py
@@ -96,7 +96,7 @@ def log_validation_results(engine):
 
     @trainer.on(Events.EPOCH_COMPLETED | Events.COMPLETED)
     def log_time(engine):
-        tqdm.write(f"{trainer.last_event_name.name} took { trainer.state.times[trainer.last_event_name.name]} seconds")
+        tqdm.write(f"{trainer.last_event_name.name} took {trainer.state.times[trainer.last_event_name.name]} seconds")
 
     trainer.run(train_loader, max_epochs=epochs)
     pbar.close()


Test patch:
Repository: pymeasure/pymeasure

Issue:
Rename pyvisa imports
In the upcoming pyvisa version, using `import visa` is being [deprecated](https://github.com/pyvisa/pyvisa/pull/448) to avoid a name clash with another package. We need to fix that in our codebase, too. This could also be behind the version comparison issues like #130


Discussion:

Resolving patch:
diff --git a/pymeasure/adapters/visa.py b/pymeasure/adapters/visa.py
--- a/pymeasure/adapters/visa.py
+++ b/pymeasure/adapters/visa.py
@@ -25,7 +25,7 @@
 import logging
 
 import copy
-import visa
+import pyvisa
 import numpy as np
 from pkg_resources import parse_version
 
@@ -54,7 +54,7 @@ def __init__(self, resourceName, visa_library='', **kwargs):
             resourceName = "GPIB0::%d::INSTR" % resourceName
         super(VISAAdapter, self).__init__()
         self.resource_name = resourceName
-        self.manager = visa.ResourceManager(visa_library)
+        self.manager = pyvisa.ResourceManager(visa_library)
         safeKeywords = ['resource_name', 'timeout',
                         'chunk_size', 'lock', 'query_delay', 'send_end',
                         'values_format', 'read_termination', 'write_termination']
@@ -70,8 +70,8 @@ def __init__(self, resourceName, visa_library='', **kwargs):
     @staticmethod
     def has_supported_version():
         """ Returns True if the PyVISA version is greater than 1.8 """
-        if hasattr(visa, '__version__'):
-            return parse_version(visa.__version__) >= parse_version('1.8')
+        if hasattr(pyvisa, '__version__'):
+            return parse_version(pyvisa.__version__) >= parse_version('1.8')
         else:
             return False
 
diff --git a/pymeasure/instruments/resources.py b/pymeasure/instruments/resources.py
--- a/pymeasure/instruments/resources.py
+++ b/pymeasure/instruments/resources.py
@@ -22,7 +22,7 @@
 # THE SOFTWARE.
 #
 
-import visa
+import pyvisa
 
 
 def list_resources():
@@ -38,7 +38,7 @@ def list_resources():
         dmm = Agilent34410(resources[0])
     
     """
-    rm = visa.ResourceManager()
+    rm = pyvisa.ResourceManager()
     instrs = rm.list_resources()
     for n, instr in enumerate(instrs):
         # trying to catch errors in comunication
@@ -48,12 +48,12 @@ def list_resources():
             try:
                 # noinspection PyUnresolvedReferences
                 idn = res.ask('*idn?')[:-1]
-            except visa.Error:
+            except pyvisa.Error:
                 idn = "Not known"
             finally:
                 res.close()
                 print(n, ":", instr, ":", idn)
-        except visa.VisaIOError as e:
+        except pyvisa.VisaIOError as e:
             print(n, ":", instr, ":", "Visa IO Error: check connections")
             print(e)
     rm.close()


Test patch:
Repository: pymeasure/pymeasure

Issue:
Small deprecation warning
The Travis pytest run [warns](https://travis-ci.org/github/ralph-group/pymeasure/jobs/700083662):
```
pymeasure/display/widgets.py:318

  /home/travis/build/ralph-group/pymeasure/pymeasure/display/widgets.py:318: DeprecationWarning: invalid escape sequence \(

    units_pattern = "\((?P<units>\w+)\)"
```
That should be diagnosed and fixed at some point.


Discussion:

Resolving patch:
diff --git a/pymeasure/display/widgets.py b/pymeasure/display/widgets.py
--- a/pymeasure/display/widgets.py
+++ b/pymeasure/display/widgets.py
@@ -315,7 +315,7 @@ def update_curves(self):
     def parse_axis(self, axis):
         """ Returns the units of an axis by searching the string
         """
-        units_pattern = "\((?P<units>\w+)\)"
+        units_pattern = r"\((?P<units>\w+)\)"
         try:
             match = re.search(units_pattern, axis)
         except TypeError:


Test patch: