We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
TypeError: '<' not supported between instances of 'str' and 'int'
### Summary
Hi,

I have been following the tutorials and official documentation for nipype on registering two t1w MRIs using ANTs. 

1) https://nipype.readthedocs.io/en/latest/users/examples/smri_ants_registration.html
2) https://nipype.readthedocs.io/en/1.0.3/interfaces/generated/interfaces.ants/registration.html

However after following the tutorials and writing the script. When I initialize the registration
 `reg = Registration()` the script exits with error `TypeError: '<' not supported between instances of 'str' and 'int'`. I have not been able to find anything conclusive on this issue. I found a similar issue in this repository but it was not clear how to solve the problem (https://github.com/nipy/nipype/issues/3232).
### Actual behavior
Initialization of  Registration via `reg = Registration()` results in script exiting with error `TypeError: '<' not supported between instances of 'str' and 'int'`
### Expected behavior
Script runs without throwing type error.
### How to replicate the behavior
Initialize registration. The script stops. 
### Script/Workflow details
```
import numpy as np
from nipype.interfaces.ants import Registration
from nipype.interfaces.ants import ANTS

#establish paths
template = '/home/sungurea/faisal-sandbox/students/sungurea/Part2-ScaledMR/MNI305/average305_t1_tal_lin.nii'
subject = '/home/sungurea/faisal-sandbox/students/sungurea/Part1_RawMR/UK_BIOBANK_IMAGES_1000/1000106.mgz'

#Registration
reg = Registration()

reg.inputs.fixed_image = template
reg.inputs.moving_image = subject
reg.inputs.output_transform_prefix = 'thisTransform'
reg.inputs.output_warped_image = 'transformed.nii.gz'
reg.inputs.output_transform_prefix = "output_"
reg.inputs.transforms = ['Translation', 'Rigid', 'Affine', 'SyN']
reg.inputs.transform_parameters = [(0.1,), (0.1,), (0.1,), (0.2, 3.0, 0.0)]
reg.inputs.number_of_iterations = ([[10000, 111110, 11110]] * 3 +
                                   [[100, 50, 30]])
reg.inputs.dimension = 3
reg.inputs.write_composite_transform = True
reg.inputs.collapse_output_transforms = False
reg.inputs.metric = ['Mattes'] * 3 + [['Mattes', 'CC']]
reg.inputs.metric_weight = [1] * 3 + [[0.5, 0.5]]
reg.inputs.radius_or_number_of_bins = [32] * 3 + [[32, 4]]
reg.inputs.sampling_strategy = ['Regular'] * 3 + [[None, None]]
reg.inputs.sampling_percentage = [0.3] * 3 + [[None, None]]
reg.inputs.convergence_threshold = [1.e-8] * 3 + [-0.01]
reg.inputs.convergence_window_size = [20] * 3 + [5]
reg.inputs.smoothing_sigmas = [[4, 2, 1]] * 3 + [[1, 0.5, 0]]
reg.inputs.sigma_units = ['vox'] * 4
reg.inputs.shrink_factors = [[6, 4, 2]] + [[3, 2, 1]] * 2 + [[4, 2, 1]]
reg.inputs.use_estimate_learning_rate_once = [True] * 4
reg.inputs.use_histogram_matching = [False] * 3 + [True]
reg.inputs.initial_moving_transform_com = True
print(reg.cmdline)
reg.run()
```

### Traceback
```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/ants/registration.py", line 1009, in __init__
    super(Registration, self).__init__(**inputs)
  File "/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/ants/base.py", line 73, in __init__
    super(ANTSCommand, self).__init__(**inputs)
  File "/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/base/core.py", line 627, in __init__
    super(CommandLine, self).__init__(**inputs)
  File "/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/base/core.py", line 197, in __init__
    unavailable_traits = self._check_version_requirements(
  File "/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/base/core.py", line 295, in _check_version_requirements
    if names and self.version:
  File "/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/ants/base.py", line 121, in version
    return Info.version()
  File "/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/base/core.py", line 1067, in version
    klass._version = klass.parse_version(raw_info)
  File "/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/ants/base.py", line 47, in parse_version
    if "post" in v_string and LooseVersion(v_string) >= LooseVersion(
  File "/cvmfs/soft.computecanada.ca/easybuild/software/2020/avx2/Core/python/3.9.6/lib/python3.9/distutils/version.py", line 70, in __ge__
    c = self._cmp(other)
  File "/cvmfs/soft.computecanada.ca/easybuild/software/2020/avx2/Core/python/3.9.6/lib/python3.9/distutils/version.py", line 341, in _cmp
    if self.version < other.version:
TypeError: '<' not supported between instances of 'str' and 'int'

```
### Platform details:

<!-- Please run the following code from your shell and place the output between the triple ticks, below.
python -c "import nipype; from pprint import pprint; pprint(nipype.get_info())"
-->

```
{'commit_hash': 'b385720',
 'commit_source': 'installation',
 'networkx_version': '2.6.3',
 'nibabel_version': '3.2.1',
 'nipype_version': '1.7.0',
 'numpy_version': '1.21.0',
 'pkg_path': '/home/sungurea/ENV/lib/python3.9/site-packages/nipype',
 'scipy_version': '1.7.0',
 'sys_executable': '/home/sungurea/ENV/bin/python',
 'sys_platform': 'linux',
 'sys_version': '3.9.6 (default, Jul 12 2021, 18:23:59) \n[GCC 9.3.0]',
 'traits_version': '6.2.0'}
```

### Execution environment
python 3.9
ANTs:
- ANTs Version: v2.3.5.post79-gdb98de3
- Compiled: Jan  2 2022 15:47:47

Choose one
Container [Venv]
My python environment inside container [3.9]
My python environment outside container


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `nipype/interfaces/ants/base.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
3 # vi: set ft=python sts=4 ts=4 sw=4 et:
4 """The ants module provides basic functions for interfacing with ANTS tools."""
5 import os
6 
7 # Local imports
8 from ... import logging, LooseVersion
9 from ..base import CommandLine, CommandLineInputSpec, traits, isdefined, PackageInfo
10 
11 iflogger = logging.getLogger("nipype.interface")
12 
13 # -Using -1 gives primary responsibilty to ITKv4 to do the correct
14 #  thread limitings.
15 # -Using 1 takes a very conservative approach to avoid overloading
16 #  the computer (when running MultiProc) by forcing everything to
17 #  single threaded.  This can be a severe penalty for registration
18 #  performance.
19 LOCAL_DEFAULT_NUMBER_OF_THREADS = 1
20 # -Using NSLOTS has the same behavior as ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS
21 #  as long as ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS is not set.  Otherwise
22 #  ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS takes precidence.
23 #  This behavior states that you the user explicitly specifies
24 #  num_threads, then respect that no matter what SGE tries to limit.
25 PREFERED_ITKv4_THREAD_LIMIT_VARIABLE = "NSLOTS"
26 ALT_ITKv4_THREAD_LIMIT_VARIABLE = "ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS"
27 
28 
29 class Info(PackageInfo):
30     version_cmd = (
31         os.path.join(os.getenv("ANTSPATH", ""), "antsRegistration") + " --version"
32     )
33 
34     @staticmethod
35     def parse_version(raw_info):
36         for line in raw_info.splitlines():
37             if line.startswith("ANTs Version: "):
38                 v_string = line.split()[2]
39                 break
40         else:
41             return None
42 
43         # -githash may or may not be appended
44         v_string = v_string.split("-")[0]
45 
46         # 2.2.0-equivalent version string
47         if "post" in v_string and LooseVersion(v_string) >= LooseVersion(
48             "2.1.0.post789"
49         ):
50             return "2.2.0"
51         else:
52             return ".".join(v_string.split(".")[:3])
53 
54 
55 class ANTSCommandInputSpec(CommandLineInputSpec):
56     """Base Input Specification for all ANTS Commands"""
57 
58     num_threads = traits.Int(
59         LOCAL_DEFAULT_NUMBER_OF_THREADS,
60         usedefault=True,
61         nohash=True,
62         desc="Number of ITK threads to use",
63     )
64 
65 
66 class ANTSCommand(CommandLine):
67     """Base class for ANTS interfaces"""
68 
69     input_spec = ANTSCommandInputSpec
70     _num_threads = LOCAL_DEFAULT_NUMBER_OF_THREADS
71 
72     def __init__(self, **inputs):
73         super(ANTSCommand, self).__init__(**inputs)
74         self.inputs.on_trait_change(self._num_threads_update, "num_threads")
75 
76         if not isdefined(self.inputs.num_threads):
77             self.inputs.num_threads = self._num_threads
78         else:
79             self._num_threads_update()
80 
81     def _num_threads_update(self):
82         self._num_threads = self.inputs.num_threads
83         # ONLY SET THE ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS if requested
84         # by the end user.  The default setting did not allow for
85         # overwriting the default values.
86         # In ITKv4 (the version used for all ANTS programs), ITK respects
87         # the SGE controlled $NSLOTS environmental variable.
88         # If user specifies -1, then that indicates that the system
89         # default behavior should be the one specified by ITKv4 rules
90         # (i.e. respect SGE $NSLOTS or environmental variables of threads, or
91         # user environmental settings)
92         if self.inputs.num_threads == -1:
93             if ALT_ITKv4_THREAD_LIMIT_VARIABLE in self.inputs.environ:
94                 del self.inputs.environ[ALT_ITKv4_THREAD_LIMIT_VARIABLE]
95             if PREFERED_ITKv4_THREAD_LIMIT_VARIABLE in self.inputs.environ:
96                 del self.inputs.environ[PREFERED_ITKv4_THREAD_LIMIT_VARIABLE]
97         else:
98             self.inputs.environ.update(
99                 {PREFERED_ITKv4_THREAD_LIMIT_VARIABLE: "%s" % self.inputs.num_threads}
100             )
101 
102     @staticmethod
103     def _format_xarray(val):
104         """Convenience method for converting input arrays [1,2,3] to
105         commandline format '1x2x3'"""
106         return "x".join([str(x) for x in val])
107 
108     @classmethod
109     def set_default_num_threads(cls, num_threads):
110         """Set the default number of threads for ITK calls
111 
112         This method is used to set the default number of ITK threads for all
113         the ANTS interfaces. However, setting this will not update the output
114         type for any existing instances.  For these, assign the
115         <instance>.inputs.num_threads
116         """
117         cls._num_threads = num_threads
118 
119     @property
120     def version(self):
121         return Info.version()
122
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/nipype/interfaces/ants/base.py b/nipype/interfaces/ants/base.py
--- a/nipype/interfaces/ants/base.py
+++ b/nipype/interfaces/ants/base.py
@@ -3,9 +3,10 @@
 # vi: set ft=python sts=4 ts=4 sw=4 et:
 """The ants module provides basic functions for interfacing with ANTS tools."""
 import os
+from packaging.version import Version, parse
 
 # Local imports
-from ... import logging, LooseVersion
+from ... import logging
 from ..base import CommandLine, CommandLineInputSpec, traits, isdefined, PackageInfo
 
 iflogger = logging.getLogger("nipype.interface")
@@ -43,13 +44,16 @@
         # -githash may or may not be appended
         v_string = v_string.split("-")[0]
 
-        # 2.2.0-equivalent version string
-        if "post" in v_string and LooseVersion(v_string) >= LooseVersion(
-            "2.1.0.post789"
-        ):
-            return "2.2.0"
-        else:
-            return ".".join(v_string.split(".")[:3])
+        version = parse(v_string)
+
+        # Known mislabeled versions
+        if version.is_postrelease:
+            if version.base_version == "2.1.0" and version.post >= 789:
+                return "2.2.0"
+
+        # Unless we know of a specific reason to re-version, we will
+        # treat the base version (before pre/post/dev) as authoritative
+        return version.base_version
 
 
 class ANTSCommandInputSpec(CommandLineInputSpec):

{"golden_diff": "diff --git a/nipype/interfaces/ants/base.py b/nipype/interfaces/ants/base.py\n--- a/nipype/interfaces/ants/base.py\n+++ b/nipype/interfaces/ants/base.py\n@@ -3,9 +3,10 @@\n # vi: set ft=python sts=4 ts=4 sw=4 et:\n \"\"\"The ants module provides basic functions for interfacing with ANTS tools.\"\"\"\n import os\n+from packaging.version import Version, parse\n \n # Local imports\n-from ... import logging, LooseVersion\n+from ... import logging\n from ..base import CommandLine, CommandLineInputSpec, traits, isdefined, PackageInfo\n \n iflogger = logging.getLogger(\"nipype.interface\")\n@@ -43,13 +44,16 @@\n         # -githash may or may not be appended\n         v_string = v_string.split(\"-\")[0]\n \n-        # 2.2.0-equivalent version string\n-        if \"post\" in v_string and LooseVersion(v_string) >= LooseVersion(\n-            \"2.1.0.post789\"\n-        ):\n-            return \"2.2.0\"\n-        else:\n-            return \".\".join(v_string.split(\".\")[:3])\n+        version = parse(v_string)\n+\n+        # Known mislabeled versions\n+        if version.is_postrelease:\n+            if version.base_version == \"2.1.0\" and version.post >= 789:\n+                return \"2.2.0\"\n+\n+        # Unless we know of a specific reason to re-version, we will\n+        # treat the base version (before pre/post/dev) as authoritative\n+        return version.base_version\n \n \n class ANTSCommandInputSpec(CommandLineInputSpec):\n", "issue": "TypeError: '<' not supported between instances of 'str' and 'int'\n### Summary\r\nHi,\r\n\r\nI have been following the tutorials and official documentation for nipype on registering two t1w MRIs using ANTs. \r\n\r\n1) https://nipype.readthedocs.io/en/latest/users/examples/smri_ants_registration.html\r\n2) https://nipype.readthedocs.io/en/1.0.3/interfaces/generated/interfaces.ants/registration.html\r\n\r\nHowever after following the tutorials and writing the script. When I initialize the registration\r\n `reg = Registration()` the script exits with error `TypeError: '<' not supported between instances of 'str' and 'int'`. I have not been able to find anything conclusive on this issue. I found a similar issue in this repository but it was not clear how to solve the problem (https://github.com/nipy/nipype/issues/3232).\r\n### Actual behavior\r\nInitialization of  Registration via `reg = Registration()` results in script exiting with error `TypeError: '<' not supported between instances of 'str' and 'int'`\r\n### Expected behavior\r\nScript runs without throwing type error.\r\n### How to replicate the behavior\r\nInitialize registration. The script stops. \r\n### Script/Workflow details\r\n```\r\nimport numpy as np\r\nfrom nipype.interfaces.ants import Registration\r\nfrom nipype.interfaces.ants import ANTS\r\n\r\n#establish paths\r\ntemplate = '/home/sungurea/faisal-sandbox/students/sungurea/Part2-ScaledMR/MNI305/average305_t1_tal_lin.nii'\r\nsubject = '/home/sungurea/faisal-sandbox/students/sungurea/Part1_RawMR/UK_BIOBANK_IMAGES_1000/1000106.mgz'\r\n\r\n#Registration\r\nreg = Registration()\r\n\r\nreg.inputs.fixed_image = template\r\nreg.inputs.moving_image = subject\r\nreg.inputs.output_transform_prefix = 'thisTransform'\r\nreg.inputs.output_warped_image = 'transformed.nii.gz'\r\nreg.inputs.output_transform_prefix = \"output_\"\r\nreg.inputs.transforms = ['Translation', 'Rigid', 'Affine', 'SyN']\r\nreg.inputs.transform_parameters = [(0.1,), (0.1,), (0.1,), (0.2, 3.0, 0.0)]\r\nreg.inputs.number_of_iterations = ([[10000, 111110, 11110]] * 3 +\r\n                                   [[100, 50, 30]])\r\nreg.inputs.dimension = 3\r\nreg.inputs.write_composite_transform = True\r\nreg.inputs.collapse_output_transforms = False\r\nreg.inputs.metric = ['Mattes'] * 3 + [['Mattes', 'CC']]\r\nreg.inputs.metric_weight = [1] * 3 + [[0.5, 0.5]]\r\nreg.inputs.radius_or_number_of_bins = [32] * 3 + [[32, 4]]\r\nreg.inputs.sampling_strategy = ['Regular'] * 3 + [[None, None]]\r\nreg.inputs.sampling_percentage = [0.3] * 3 + [[None, None]]\r\nreg.inputs.convergence_threshold = [1.e-8] * 3 + [-0.01]\r\nreg.inputs.convergence_window_size = [20] * 3 + [5]\r\nreg.inputs.smoothing_sigmas = [[4, 2, 1]] * 3 + [[1, 0.5, 0]]\r\nreg.inputs.sigma_units = ['vox'] * 4\r\nreg.inputs.shrink_factors = [[6, 4, 2]] + [[3, 2, 1]] * 2 + [[4, 2, 1]]\r\nreg.inputs.use_estimate_learning_rate_once = [True] * 4\r\nreg.inputs.use_histogram_matching = [False] * 3 + [True]\r\nreg.inputs.initial_moving_transform_com = True\r\nprint(reg.cmdline)\r\nreg.run()\r\n```\r\n\r\n### Traceback\r\n```\r\nTraceback (most recent call last):\r\n  File \"<stdin>\", line 1, in <module>\r\n  File \"/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/ants/registration.py\", line 1009, in __init__\r\n    super(Registration, self).__init__(**inputs)\r\n  File \"/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/ants/base.py\", line 73, in __init__\r\n    super(ANTSCommand, self).__init__(**inputs)\r\n  File \"/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/base/core.py\", line 627, in __init__\r\n    super(CommandLine, self).__init__(**inputs)\r\n  File \"/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/base/core.py\", line 197, in __init__\r\n    unavailable_traits = self._check_version_requirements(\r\n  File \"/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/base/core.py\", line 295, in _check_version_requirements\r\n    if names and self.version:\r\n  File \"/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/ants/base.py\", line 121, in version\r\n    return Info.version()\r\n  File \"/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/base/core.py\", line 1067, in version\r\n    klass._version = klass.parse_version(raw_info)\r\n  File \"/home/sungurea/ENV/lib/python3.9/site-packages/nipype/interfaces/ants/base.py\", line 47, in parse_version\r\n    if \"post\" in v_string and LooseVersion(v_string) >= LooseVersion(\r\n  File \"/cvmfs/soft.computecanada.ca/easybuild/software/2020/avx2/Core/python/3.9.6/lib/python3.9/distutils/version.py\", line 70, in __ge__\r\n    c = self._cmp(other)\r\n  File \"/cvmfs/soft.computecanada.ca/easybuild/software/2020/avx2/Core/python/3.9.6/lib/python3.9/distutils/version.py\", line 341, in _cmp\r\n    if self.version < other.version:\r\nTypeError: '<' not supported between instances of 'str' and 'int'\r\n\r\n```\r\n### Platform details:\r\n\r\n<!-- Please run the following code from your shell and place the output between the triple ticks, below.\r\npython -c \"import nipype; from pprint import pprint; pprint(nipype.get_info())\"\r\n-->\r\n\r\n```\r\n{'commit_hash': 'b385720',\r\n 'commit_source': 'installation',\r\n 'networkx_version': '2.6.3',\r\n 'nibabel_version': '3.2.1',\r\n 'nipype_version': '1.7.0',\r\n 'numpy_version': '1.21.0',\r\n 'pkg_path': '/home/sungurea/ENV/lib/python3.9/site-packages/nipype',\r\n 'scipy_version': '1.7.0',\r\n 'sys_executable': '/home/sungurea/ENV/bin/python',\r\n 'sys_platform': 'linux',\r\n 'sys_version': '3.9.6 (default, Jul 12 2021, 18:23:59) \\n[GCC 9.3.0]',\r\n 'traits_version': '6.2.0'}\r\n```\r\n\r\n### Execution environment\r\npython 3.9\r\nANTs:\r\n- ANTs Version: v2.3.5.post79-gdb98de3\r\n- Compiled: Jan  2 2022 15:47:47\r\n\r\nChoose one\r\nContainer [Venv]\r\nMy python environment inside container [3.9]\r\nMy python environment outside container\r\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-\n# vi: set ft=python sts=4 ts=4 sw=4 et:\n\"\"\"The ants module provides basic functions for interfacing with ANTS tools.\"\"\"\nimport os\n\n# Local imports\nfrom ... import logging, LooseVersion\nfrom ..base import CommandLine, CommandLineInputSpec, traits, isdefined, PackageInfo\n\niflogger = logging.getLogger(\"nipype.interface\")\n\n# -Using -1 gives primary responsibilty to ITKv4 to do the correct\n#  thread limitings.\n# -Using 1 takes a very conservative approach to avoid overloading\n#  the computer (when running MultiProc) by forcing everything to\n#  single threaded.  This can be a severe penalty for registration\n#  performance.\nLOCAL_DEFAULT_NUMBER_OF_THREADS = 1\n# -Using NSLOTS has the same behavior as ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS\n#  as long as ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS is not set.  Otherwise\n#  ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS takes precidence.\n#  This behavior states that you the user explicitly specifies\n#  num_threads, then respect that no matter what SGE tries to limit.\nPREFERED_ITKv4_THREAD_LIMIT_VARIABLE = \"NSLOTS\"\nALT_ITKv4_THREAD_LIMIT_VARIABLE = \"ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS\"\n\n\nclass Info(PackageInfo):\n    version_cmd = (\n        os.path.join(os.getenv(\"ANTSPATH\", \"\"), \"antsRegistration\") + \" --version\"\n    )\n\n    @staticmethod\n    def parse_version(raw_info):\n        for line in raw_info.splitlines():\n            if line.startswith(\"ANTs Version: \"):\n                v_string = line.split()[2]\n                break\n        else:\n            return None\n\n        # -githash may or may not be appended\n        v_string = v_string.split(\"-\")[0]\n\n        # 2.2.0-equivalent version string\n        if \"post\" in v_string and LooseVersion(v_string) >= LooseVersion(\n            \"2.1.0.post789\"\n        ):\n            return \"2.2.0\"\n        else:\n            return \".\".join(v_string.split(\".\")[:3])\n\n\nclass ANTSCommandInputSpec(CommandLineInputSpec):\n    \"\"\"Base Input Specification for all ANTS Commands\"\"\"\n\n    num_threads = traits.Int(\n        LOCAL_DEFAULT_NUMBER_OF_THREADS,\n        usedefault=True,\n        nohash=True,\n        desc=\"Number of ITK threads to use\",\n    )\n\n\nclass ANTSCommand(CommandLine):\n    \"\"\"Base class for ANTS interfaces\"\"\"\n\n    input_spec = ANTSCommandInputSpec\n    _num_threads = LOCAL_DEFAULT_NUMBER_OF_THREADS\n\n    def __init__(self, **inputs):\n        super(ANTSCommand, self).__init__(**inputs)\n        self.inputs.on_trait_change(self._num_threads_update, \"num_threads\")\n\n        if not isdefined(self.inputs.num_threads):\n            self.inputs.num_threads = self._num_threads\n        else:\n            self._num_threads_update()\n\n    def _num_threads_update(self):\n        self._num_threads = self.inputs.num_threads\n        # ONLY SET THE ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS if requested\n        # by the end user.  The default setting did not allow for\n        # overwriting the default values.\n        # In ITKv4 (the version used for all ANTS programs), ITK respects\n        # the SGE controlled $NSLOTS environmental variable.\n        # If user specifies -1, then that indicates that the system\n        # default behavior should be the one specified by ITKv4 rules\n        # (i.e. respect SGE $NSLOTS or environmental variables of threads, or\n        # user environmental settings)\n        if self.inputs.num_threads == -1:\n            if ALT_ITKv4_THREAD_LIMIT_VARIABLE in self.inputs.environ:\n                del self.inputs.environ[ALT_ITKv4_THREAD_LIMIT_VARIABLE]\n            if PREFERED_ITKv4_THREAD_LIMIT_VARIABLE in self.inputs.environ:\n                del self.inputs.environ[PREFERED_ITKv4_THREAD_LIMIT_VARIABLE]\n        else:\n            self.inputs.environ.update(\n                {PREFERED_ITKv4_THREAD_LIMIT_VARIABLE: \"%s\" % self.inputs.num_threads}\n            )\n\n    @staticmethod\n    def _format_xarray(val):\n        \"\"\"Convenience method for converting input arrays [1,2,3] to\n        commandline format '1x2x3'\"\"\"\n        return \"x\".join([str(x) for x in val])\n\n    @classmethod\n    def set_default_num_threads(cls, num_threads):\n        \"\"\"Set the default number of threads for ITK calls\n\n        This method is used to set the default number of ITK threads for all\n        the ANTS interfaces. However, setting this will not update the output\n        type for any existing instances.  For these, assign the\n        <instance>.inputs.num_threads\n        \"\"\"\n        cls._num_threads = num_threads\n\n    @property\n    def version(self):\n        return Info.version()\n", "path": "nipype/interfaces/ants/base.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-\n# vi: set ft=python sts=4 ts=4 sw=4 et:\n\"\"\"The ants module provides basic functions for interfacing with ANTS tools.\"\"\"\nimport os\nfrom packaging.version import Version, parse\n\n# Local imports\nfrom ... import logging\nfrom ..base import CommandLine, CommandLineInputSpec, traits, isdefined, PackageInfo\n\niflogger = logging.getLogger(\"nipype.interface\")\n\n# -Using -1 gives primary responsibilty to ITKv4 to do the correct\n#  thread limitings.\n# -Using 1 takes a very conservative approach to avoid overloading\n#  the computer (when running MultiProc) by forcing everything to\n#  single threaded.  This can be a severe penalty for registration\n#  performance.\nLOCAL_DEFAULT_NUMBER_OF_THREADS = 1\n# -Using NSLOTS has the same behavior as ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS\n#  as long as ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS is not set.  Otherwise\n#  ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS takes precidence.\n#  This behavior states that you the user explicitly specifies\n#  num_threads, then respect that no matter what SGE tries to limit.\nPREFERED_ITKv4_THREAD_LIMIT_VARIABLE = \"NSLOTS\"\nALT_ITKv4_THREAD_LIMIT_VARIABLE = \"ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS\"\n\n\nclass Info(PackageInfo):\n    version_cmd = (\n        os.path.join(os.getenv(\"ANTSPATH\", \"\"), \"antsRegistration\") + \" --version\"\n    )\n\n    @staticmethod\n    def parse_version(raw_info):\n        for line in raw_info.splitlines():\n            if line.startswith(\"ANTs Version: \"):\n                v_string = line.split()[2]\n                break\n        else:\n            return None\n\n        # -githash may or may not be appended\n        v_string = v_string.split(\"-\")[0]\n\n        version = parse(v_string)\n\n        # Known mislabeled versions\n        if version.is_postrelease:\n            if version.base_version == \"2.1.0\" and version.post >= 789:\n                return \"2.2.0\"\n\n        # Unless we know of a specific reason to re-version, we will\n        # treat the base version (before pre/post/dev) as authoritative\n        return version.base_version\n\n\nclass ANTSCommandInputSpec(CommandLineInputSpec):\n    \"\"\"Base Input Specification for all ANTS Commands\"\"\"\n\n    num_threads = traits.Int(\n        LOCAL_DEFAULT_NUMBER_OF_THREADS,\n        usedefault=True,\n        nohash=True,\n        desc=\"Number of ITK threads to use\",\n    )\n\n\nclass ANTSCommand(CommandLine):\n    \"\"\"Base class for ANTS interfaces\"\"\"\n\n    input_spec = ANTSCommandInputSpec\n    _num_threads = LOCAL_DEFAULT_NUMBER_OF_THREADS\n\n    def __init__(self, **inputs):\n        super(ANTSCommand, self).__init__(**inputs)\n        self.inputs.on_trait_change(self._num_threads_update, \"num_threads\")\n\n        if not isdefined(self.inputs.num_threads):\n            self.inputs.num_threads = self._num_threads\n        else:\n            self._num_threads_update()\n\n    def _num_threads_update(self):\n        self._num_threads = self.inputs.num_threads\n        # ONLY SET THE ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS if requested\n        # by the end user.  The default setting did not allow for\n        # overwriting the default values.\n        # In ITKv4 (the version used for all ANTS programs), ITK respects\n        # the SGE controlled $NSLOTS environmental variable.\n        # If user specifies -1, then that indicates that the system\n        # default behavior should be the one specified by ITKv4 rules\n        # (i.e. respect SGE $NSLOTS or environmental variables of threads, or\n        # user environmental settings)\n        if self.inputs.num_threads == -1:\n            if ALT_ITKv4_THREAD_LIMIT_VARIABLE in self.inputs.environ:\n                del self.inputs.environ[ALT_ITKv4_THREAD_LIMIT_VARIABLE]\n            if PREFERED_ITKv4_THREAD_LIMIT_VARIABLE in self.inputs.environ:\n                del self.inputs.environ[PREFERED_ITKv4_THREAD_LIMIT_VARIABLE]\n        else:\n            self.inputs.environ.update(\n                {PREFERED_ITKv4_THREAD_LIMIT_VARIABLE: \"%s\" % self.inputs.num_threads}\n            )\n\n    @staticmethod\n    def _format_xarray(val):\n        \"\"\"Convenience method for converting input arrays [1,2,3] to\n        commandline format '1x2x3'\"\"\"\n        return \"x\".join([str(x) for x in val])\n\n    @classmethod\n    def set_default_num_threads(cls, num_threads):\n        \"\"\"Set the default number of threads for ITK calls\n\n        This method is used to set the default number of ITK threads for all\n        the ANTS interfaces. However, setting this will not update the output\n        type for any existing instances.  For these, assign the\n        <instance>.inputs.num_threads\n        \"\"\"\n        cls._num_threads = num_threads\n\n    @property\n    def version(self):\n        return Info.version()\n", "path": "nipype/interfaces/ants/base.py"}]}