We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Vips installation is a pain and should be made optional, or use something else entirely
**Is your feature request related to a problem? Please describe.**
VIPS (libvips/pyvips) is a major pain to install and use, since it does not install all dependencies from pypi.

**Describe the solution you'd like**
Currently, we are only using VIPS for a resize operation in the unit tests, and this should be either made optional or changed to use another library.

**Describe alternatives you've considered**
Nothing else, since VIPS is just a pain.

**Additional context**
N.A.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `GANDLF/utils/generic.py`
Content:
```
1 import os, datetime, sys
2 import numpy as np
3 
4 
5 def checkPatchDivisibility(patch_size, number=16):
6     """
7     This function checks the divisibility of a numpy array or integer for architectural integrity
8 
9     Args:
10         patch_size (numpy.array): The patch size for checking.
11         number (int, optional): The number to check divisibility for. Defaults to 16.
12 
13     Returns:
14         bool: If all elements of array are divisible or not, after taking 2D patches into account.
15     """
16     if isinstance(patch_size, int):
17         patch_size_to_check = np.array(patch_size)
18     else:
19         patch_size_to_check = patch_size
20     # for 2D, don't check divisibility of last dimension
21     if patch_size_to_check[-1] == 1:
22         patch_size_to_check = patch_size_to_check[:-1]
23     # for 2D, don't check divisibility of first dimension
24     elif patch_size_to_check[0] == 1:
25         patch_size_to_check = patch_size_to_check[1:]
26     if np.count_nonzero(np.remainder(patch_size_to_check, number)) > 0:
27         return False
28 
29     # adding check to address https://github.com/CBICA/GaNDLF/issues/53
30     # there is quite possibly a better way to do this
31     unique = np.unique(patch_size_to_check)
32     if (unique.shape[0] == 1) and (unique[0] <= number):
33         return False
34     return True
35 
36 
37 def fix_paths(cwd):
38     """
39     This function takes the current working directory of the script (which is required for VIPS) and sets up all the paths correctly
40 
41     Args:
42         cwd (str): The current working directory.
43     """
44     if os.name == "nt":  # proceed for windows
45         vipshome = os.path.join(cwd, "vips/vips-dev-8.10/bin")
46         os.environ["PATH"] = vipshome + ";" + os.environ["PATH"]
47 
48 
49 def get_date_time():
50     """
51     Get a well-parsed date string
52 
53     Returns:
54         str: The date in format YYYY/MM/DD::HH:MM:SS
55     """
56     now = datetime.datetime.now().strftime("%Y/%m/%d::%H:%M:%S")
57     return now
58 
59 
60 def get_unique_timestamp():
61     """
62     Get a well-parsed timestamp string to be used for unique filenames
63 
64     Returns:
65         str: The date in format YYYYMMDD_HHMMSS
66     """
67     now = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
68     return now
69 
70 
71 def get_filename_extension_sanitized(filename):
72     """
73     This function returns the extension of the filename with leading and trailing characters removed.
74     Args:
75         filename (str): The filename to be processed.
76     Returns:
77         str: The filename with extension removed.
78     """
79     _, ext = os.path.splitext(filename)
80     # if .gz or .nii file is detected, always return .nii.gz
81     if (ext == ".gz") or (ext == ".nii"):
82         ext = ".nii.gz"
83     return ext
84 
85 
86 def parse_version(version_string):
87     """
88     Parses version string, discards last identifier (NR/alpha/beta) and returns an integer for comparison.
89 
90     Args:
91         version_string (str): The string to be parsed.
92 
93     Returns:
94         int: The version number.
95     """
96     version_string_split = version_string.split(".")
97     if len(version_string_split) > 3:
98         del version_string_split[-1]
99     return int("".join(version_string_split))
100 
101 
102 def version_check(version_from_config, version_to_check):
103     """
104     This function checks if the version of the config file is compatible with the version of the code.
105 
106     Args:
107         version_from_config (str): The version of the config file.
108         version_to_check (str): The version of the code or model to check.
109 
110     Returns:
111         bool: If the version of the config file is compatible with the version of the code.
112     """
113     version_to_check_int = parse_version(version_to_check)
114     min_ver = parse_version(version_from_config["minimum"])
115     max_ver = parse_version(version_from_config["maximum"])
116     if (min_ver > version_to_check_int) or (max_ver < version_to_check_int):
117         sys.exit(
118             "Incompatible version of GaNDLF detected ("
119             + str(version_to_check_int)
120             + ")"
121         )
122 
123     return True
124 
125 
126 def checkPatchDimensions(patch_size, numlay):
127     """
128     This function checks the divisibility of a numpy array or integer for architectural integrity
129 
130     Args:
131         patch_size (numpy.array): The patch size for checking.
132         number (int, optional): The number to check divisibility for. Defaults to 16.
133 
134     Returns:
135         int: Largest multiple of 2 (less than or equal to numlay) that each element of patch size is divisible by to yield int >= 2
136     """
137     if isinstance(patch_size, int):
138         patch_size_to_check = np.array(patch_size)
139     else:
140         patch_size_to_check = patch_size
141     # for 2D, don't check divisibility of last dimension
142     if patch_size_to_check[-1] == 1:
143         patch_size_to_check = patch_size_to_check[:-1]
144 
145     if all(
146         [x >= 2 ** (numlay + 1) and x % 2**numlay == 0 for x in patch_size_to_check]
147     ):
148         return numlay
149     else:
150         # base2 = np.floor(np.log2(patch_size_to_check))
151         base2 = np.array([getBase2(x) for x in patch_size_to_check])
152         remain = patch_size_to_check / 2**base2  # check that at least 1
153 
154         layers = np.where(remain == 1, base2 - 1, base2)
155         return int(np.min(layers))
156 
157 
158 def getBase2(num):
159     # helper for checkPatchDimensions (returns the largest multiple of 2 that num is evenly divisible by)
160     base = 0
161     while num % 2 == 0:
162         num = num / 2
163         base = base + 1
164     return base
165
```

Path: `setup.py`
Content:
```
1 #!/usr/bin/env python
2 
3 """The setup script."""
4 
5 
6 import os
7 from setuptools import setup, find_packages
8 from setuptools.command.install import install
9 from setuptools.command.develop import develop
10 from setuptools.command.egg_info import egg_info
11 
12 with open("README.md") as readme_file:
13     readme = readme_file.read()
14 
15 
16 def git_submodule_update():
17     ## submodule update
18     os.system("git submodule update --init --recursive")
19 
20 
21 class CustomInstallCommand(install):
22     def run(self):
23         install.run(self)
24         git_submodule_update()
25 
26 
27 class CustomDevelopCommand(develop):
28     def run(self):
29         develop.run(self)
30         git_submodule_update()
31 
32 
33 class CustomEggInfoCommand(egg_info):
34     def run(self):
35         egg_info.run(self)
36         git_submodule_update()
37 
38 
39 # read version.py
40 import sys, re
41 
42 try:
43     filepath = "GANDLF/version.py"
44     version_file = open(filepath)
45     (__version__,) = re.findall('__version__ = "(.*)"', version_file.read())
46 
47 except Exception as error:
48     __version__ = "0.0.1"
49     sys.stderr.write("Warning: Could not open '%s' due %s\n" % (filepath, error))
50 
51 requirements = [
52     "black",
53     "numpy==1.22.0",
54     "scipy",
55     "SimpleITK!=2.0.*",
56     "torchvision",
57     "tqdm",
58     "torchio==0.18.57",
59     "pandas",
60     "pylint",
61     "scikit-learn>=0.23.2",
62     "scikit-image>=0.19.1",
63     'pickle5>=0.0.11; python_version < "3.8.0"',
64     "setuptools",
65     "seaborn",
66     "pyyaml",
67     "tiffslide",
68     "matplotlib",
69     "requests>=2.25.0",
70     "pyvips==2.2.1",
71     "pytest",
72     "coverage",
73     "pytest-cov",
74     "psutil",
75     "medcam",
76     "opencv-python",
77     "torchmetrics==0.5.1",  # newer versions have changed api for f1 invocation
78     "OpenPatchMiner==0.1.8",
79     "zarr==2.10.3",
80     "pydicom",
81     "onnx",
82     "torchinfo==1.7.0",
83 ]
84 
85 # pytorch doesn't have LTS support on OSX - https://github.com/CBICA/GaNDLF/issues/389
86 if sys.platform == "darwin":
87     requirements.append("torch==1.9.0")
88 else:
89     requirements.append("torch==1.8.2")
90 
91 setup(
92     name="GANDLF",
93     version=__version__,
94     author="Jose Agraz, Vinayak Ahluwalia, Bhakti Baheti, Spyridon Bakas, Ujjwal Baid, Megh Bhalerao, Brandon Edwards, Karol Gotkowski, Caleb Grenko, Orhun Güley, Ibrahim Ethem Hamamci, Sarthak Pati, Micah Sheller, Juliia Skobleva, Siddhesh Thakur, Spiros Thermos",  # alphabetical order
95     author_email="software@cbica.upenn.edu",
96     python_requires=">=3.7",
97     packages=find_packages(),
98     cmdclass={  # this ensures git_submodule_update is called during install
99         "install": CustomInstallCommand,
100         "develop": CustomDevelopCommand,
101         "egg_info": CustomEggInfoCommand,
102     },
103     scripts=[
104         "gandlf_run",
105         "gandlf_constructCSV",
106         "gandlf_collectStats",
107         "gandlf_patchMiner",
108         "gandlf_preprocess",
109         "gandlf_anonymizer",
110         "gandlf_verifyInstall",
111     ],
112     classifiers=[
113         "Development Status :: 3 - Alpha",
114         "Intended Audience :: Science/Research",
115         "License :: OSI Approved :: BSD License",
116         "Natural Language :: English",
117         "Operating System :: OS Independent",
118         "Programming Language :: Python :: 3.7",
119         "Programming Language :: Python :: 3.8",
120         "Programming Language :: Python :: 3.9",
121         "Topic :: Scientific/Engineering :: Medical Science Apps",
122     ],
123     description=(
124         "PyTorch-based framework that handles segmentation/regression/classification using various DL architectures for medical imaging."
125     ),
126     install_requires=requirements,
127     license="BSD-3-Clause License",
128     long_description=readme,
129     long_description_content_type="text/markdown",
130     include_package_data=True,
131     keywords="semantic, segmentation, regression, classification, data-augmentation, medical-imaging",
132     zip_safe=False,
133 )
134 
135 ## windows vips installation
136 if os.name == "nt":  # proceed for windows
137     from pathlib import Path
138 
139     # download and extract if main dll is absent
140     if not Path("./vips/vips-dev-8.10/bin/libvips-42.dll").exists():
141         print("Downloading and extracting VIPS for Windows")
142         url = "https://github.com/libvips/libvips/releases/download/v8.10.2/vips-dev-w64-all-8.10.2.zip"
143         zip_to_extract = "./vips.zip"
144         import urllib.request, zipfile
145 
146         urllib.request.urlretrieve(url, zip_to_extract)
147         z = zipfile.ZipFile(zip_to_extract)
148         z.extractall("./vips")
149         z.close()
150         os.remove(zip_to_extract)
151
```

Path: `GANDLF/utils/__init__.py`
Content:
```
1 import os
2 
3 # hides torchio citation request, see https://github.com/fepegar/torchio/issues/235
4 os.environ["TORCHIO_HIDE_CITATION_PROMPT"] = "1"
5 
6 from .imaging import (
7     resize_image,
8     resample_image,
9     perform_sanity_check_on_subject,
10     write_training_patches,
11 )
12 
13 from .tensor import (
14     one_hot,
15     reverse_one_hot,
16     send_model_to_device,
17     get_class_imbalance_weights,
18     get_class_imbalance_weights_segmentation,
19     get_class_imbalance_weights_classification,
20     get_linear_interpolation_mode,
21     print_model_summary,
22 )
23 
24 from .write_parse import (
25     writeTrainingCSV,
26     parseTrainingCSV,
27     get_dataframe,
28 )
29 
30 from .parameter_processing import (
31     populate_header_in_parameters,
32     find_problem_type,
33     populate_channel_keys_in_params,
34 )
35 
36 from .generic import (
37     fix_paths,
38     get_date_time,
39     get_unique_timestamp,
40     get_filename_extension_sanitized,
41     version_check,
42 )
43 
44 from .modelio import (
45     best_model_path_end,
46     load_model,
47     load_ov_model,
48     save_model,
49 )
50
```
--- 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/GANDLF/utils/__init__.py b/GANDLF/utils/__init__.py
--- a/GANDLF/utils/__init__.py
+++ b/GANDLF/utils/__init__.py
@@ -34,7 +34,6 @@
 )
 
 from .generic import (
-    fix_paths,
     get_date_time,
     get_unique_timestamp,
     get_filename_extension_sanitized,
diff --git a/GANDLF/utils/generic.py b/GANDLF/utils/generic.py
--- a/GANDLF/utils/generic.py
+++ b/GANDLF/utils/generic.py
@@ -34,18 +34,6 @@
     return True
 
 
-def fix_paths(cwd):
-    """
-    This function takes the current working directory of the script (which is required for VIPS) and sets up all the paths correctly
-
-    Args:
-        cwd (str): The current working directory.
-    """
-    if os.name == "nt":  # proceed for windows
-        vipshome = os.path.join(cwd, "vips/vips-dev-8.10/bin")
-        os.environ["PATH"] = vipshome + ";" + os.environ["PATH"]
-
-
 def get_date_time():
     """
     Get a well-parsed date string
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -67,7 +67,6 @@
     "tiffslide",
     "matplotlib",
     "requests>=2.25.0",
-    "pyvips==2.2.1",
     "pytest",
     "coverage",
     "pytest-cov",
@@ -131,20 +130,3 @@
     keywords="semantic, segmentation, regression, classification, data-augmentation, medical-imaging",
     zip_safe=False,
 )
-
-## windows vips installation
-if os.name == "nt":  # proceed for windows
-    from pathlib import Path
-
-    # download and extract if main dll is absent
-    if not Path("./vips/vips-dev-8.10/bin/libvips-42.dll").exists():
-        print("Downloading and extracting VIPS for Windows")
-        url = "https://github.com/libvips/libvips/releases/download/v8.10.2/vips-dev-w64-all-8.10.2.zip"
-        zip_to_extract = "./vips.zip"
-        import urllib.request, zipfile
-
-        urllib.request.urlretrieve(url, zip_to_extract)
-        z = zipfile.ZipFile(zip_to_extract)
-        z.extractall("./vips")
-        z.close()
-        os.remove(zip_to_extract)

{"golden_diff": "diff --git a/GANDLF/utils/__init__.py b/GANDLF/utils/__init__.py\n--- a/GANDLF/utils/__init__.py\n+++ b/GANDLF/utils/__init__.py\n@@ -34,7 +34,6 @@\n )\n \n from .generic import (\n-    fix_paths,\n     get_date_time,\n     get_unique_timestamp,\n     get_filename_extension_sanitized,\ndiff --git a/GANDLF/utils/generic.py b/GANDLF/utils/generic.py\n--- a/GANDLF/utils/generic.py\n+++ b/GANDLF/utils/generic.py\n@@ -34,18 +34,6 @@\n     return True\n \n \n-def fix_paths(cwd):\n-    \"\"\"\n-    This function takes the current working directory of the script (which is required for VIPS) and sets up all the paths correctly\n-\n-    Args:\n-        cwd (str): The current working directory.\n-    \"\"\"\n-    if os.name == \"nt\":  # proceed for windows\n-        vipshome = os.path.join(cwd, \"vips/vips-dev-8.10/bin\")\n-        os.environ[\"PATH\"] = vipshome + \";\" + os.environ[\"PATH\"]\n-\n-\n def get_date_time():\n     \"\"\"\n     Get a well-parsed date string\ndiff --git a/setup.py b/setup.py\n--- a/setup.py\n+++ b/setup.py\n@@ -67,7 +67,6 @@\n     \"tiffslide\",\n     \"matplotlib\",\n     \"requests>=2.25.0\",\n-    \"pyvips==2.2.1\",\n     \"pytest\",\n     \"coverage\",\n     \"pytest-cov\",\n@@ -131,20 +130,3 @@\n     keywords=\"semantic, segmentation, regression, classification, data-augmentation, medical-imaging\",\n     zip_safe=False,\n )\n-\n-## windows vips installation\n-if os.name == \"nt\":  # proceed for windows\n-    from pathlib import Path\n-\n-    # download and extract if main dll is absent\n-    if not Path(\"./vips/vips-dev-8.10/bin/libvips-42.dll\").exists():\n-        print(\"Downloading and extracting VIPS for Windows\")\n-        url = \"https://github.com/libvips/libvips/releases/download/v8.10.2/vips-dev-w64-all-8.10.2.zip\"\n-        zip_to_extract = \"./vips.zip\"\n-        import urllib.request, zipfile\n-\n-        urllib.request.urlretrieve(url, zip_to_extract)\n-        z = zipfile.ZipFile(zip_to_extract)\n-        z.extractall(\"./vips\")\n-        z.close()\n-        os.remove(zip_to_extract)\n", "issue": "Vips installation is a pain and should be made optional, or use something else entirely\n**Is your feature request related to a problem? Please describe.**\r\nVIPS (libvips/pyvips) is a major pain to install and use, since it does not install all dependencies from pypi.\r\n\r\n**Describe the solution you'd like**\r\nCurrently, we are only using VIPS for a resize operation in the unit tests, and this should be either made optional or changed to use another library.\r\n\r\n**Describe alternatives you've considered**\r\nNothing else, since VIPS is just a pain.\r\n\r\n**Additional context**\r\nN.A.\r\n\n", "before_files": [{"content": "import os, datetime, sys\nimport numpy as np\n\n\ndef checkPatchDivisibility(patch_size, number=16):\n    \"\"\"\n    This function checks the divisibility of a numpy array or integer for architectural integrity\n\n    Args:\n        patch_size (numpy.array): The patch size for checking.\n        number (int, optional): The number to check divisibility for. Defaults to 16.\n\n    Returns:\n        bool: If all elements of array are divisible or not, after taking 2D patches into account.\n    \"\"\"\n    if isinstance(patch_size, int):\n        patch_size_to_check = np.array(patch_size)\n    else:\n        patch_size_to_check = patch_size\n    # for 2D, don't check divisibility of last dimension\n    if patch_size_to_check[-1] == 1:\n        patch_size_to_check = patch_size_to_check[:-1]\n    # for 2D, don't check divisibility of first dimension\n    elif patch_size_to_check[0] == 1:\n        patch_size_to_check = patch_size_to_check[1:]\n    if np.count_nonzero(np.remainder(patch_size_to_check, number)) > 0:\n        return False\n\n    # adding check to address https://github.com/CBICA/GaNDLF/issues/53\n    # there is quite possibly a better way to do this\n    unique = np.unique(patch_size_to_check)\n    if (unique.shape[0] == 1) and (unique[0] <= number):\n        return False\n    return True\n\n\ndef fix_paths(cwd):\n    \"\"\"\n    This function takes the current working directory of the script (which is required for VIPS) and sets up all the paths correctly\n\n    Args:\n        cwd (str): The current working directory.\n    \"\"\"\n    if os.name == \"nt\":  # proceed for windows\n        vipshome = os.path.join(cwd, \"vips/vips-dev-8.10/bin\")\n        os.environ[\"PATH\"] = vipshome + \";\" + os.environ[\"PATH\"]\n\n\ndef get_date_time():\n    \"\"\"\n    Get a well-parsed date string\n\n    Returns:\n        str: The date in format YYYY/MM/DD::HH:MM:SS\n    \"\"\"\n    now = datetime.datetime.now().strftime(\"%Y/%m/%d::%H:%M:%S\")\n    return now\n\n\ndef get_unique_timestamp():\n    \"\"\"\n    Get a well-parsed timestamp string to be used for unique filenames\n\n    Returns:\n        str: The date in format YYYYMMDD_HHMMSS\n    \"\"\"\n    now = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n    return now\n\n\ndef get_filename_extension_sanitized(filename):\n    \"\"\"\n    This function returns the extension of the filename with leading and trailing characters removed.\n    Args:\n        filename (str): The filename to be processed.\n    Returns:\n        str: The filename with extension removed.\n    \"\"\"\n    _, ext = os.path.splitext(filename)\n    # if .gz or .nii file is detected, always return .nii.gz\n    if (ext == \".gz\") or (ext == \".nii\"):\n        ext = \".nii.gz\"\n    return ext\n\n\ndef parse_version(version_string):\n    \"\"\"\n    Parses version string, discards last identifier (NR/alpha/beta) and returns an integer for comparison.\n\n    Args:\n        version_string (str): The string to be parsed.\n\n    Returns:\n        int: The version number.\n    \"\"\"\n    version_string_split = version_string.split(\".\")\n    if len(version_string_split) > 3:\n        del version_string_split[-1]\n    return int(\"\".join(version_string_split))\n\n\ndef version_check(version_from_config, version_to_check):\n    \"\"\"\n    This function checks if the version of the config file is compatible with the version of the code.\n\n    Args:\n        version_from_config (str): The version of the config file.\n        version_to_check (str): The version of the code or model to check.\n\n    Returns:\n        bool: If the version of the config file is compatible with the version of the code.\n    \"\"\"\n    version_to_check_int = parse_version(version_to_check)\n    min_ver = parse_version(version_from_config[\"minimum\"])\n    max_ver = parse_version(version_from_config[\"maximum\"])\n    if (min_ver > version_to_check_int) or (max_ver < version_to_check_int):\n        sys.exit(\n            \"Incompatible version of GaNDLF detected (\"\n            + str(version_to_check_int)\n            + \")\"\n        )\n\n    return True\n\n\ndef checkPatchDimensions(patch_size, numlay):\n    \"\"\"\n    This function checks the divisibility of a numpy array or integer for architectural integrity\n\n    Args:\n        patch_size (numpy.array): The patch size for checking.\n        number (int, optional): The number to check divisibility for. Defaults to 16.\n\n    Returns:\n        int: Largest multiple of 2 (less than or equal to numlay) that each element of patch size is divisible by to yield int >= 2\n    \"\"\"\n    if isinstance(patch_size, int):\n        patch_size_to_check = np.array(patch_size)\n    else:\n        patch_size_to_check = patch_size\n    # for 2D, don't check divisibility of last dimension\n    if patch_size_to_check[-1] == 1:\n        patch_size_to_check = patch_size_to_check[:-1]\n\n    if all(\n        [x >= 2 ** (numlay + 1) and x % 2**numlay == 0 for x in patch_size_to_check]\n    ):\n        return numlay\n    else:\n        # base2 = np.floor(np.log2(patch_size_to_check))\n        base2 = np.array([getBase2(x) for x in patch_size_to_check])\n        remain = patch_size_to_check / 2**base2  # check that at least 1\n\n        layers = np.where(remain == 1, base2 - 1, base2)\n        return int(np.min(layers))\n\n\ndef getBase2(num):\n    # helper for checkPatchDimensions (returns the largest multiple of 2 that num is evenly divisible by)\n    base = 0\n    while num % 2 == 0:\n        num = num / 2\n        base = base + 1\n    return base\n", "path": "GANDLF/utils/generic.py"}, {"content": "#!/usr/bin/env python\n\n\"\"\"The setup script.\"\"\"\n\n\nimport os\nfrom setuptools import setup, find_packages\nfrom setuptools.command.install import install\nfrom setuptools.command.develop import develop\nfrom setuptools.command.egg_info import egg_info\n\nwith open(\"README.md\") as readme_file:\n    readme = readme_file.read()\n\n\ndef git_submodule_update():\n    ## submodule update\n    os.system(\"git submodule update --init --recursive\")\n\n\nclass CustomInstallCommand(install):\n    def run(self):\n        install.run(self)\n        git_submodule_update()\n\n\nclass CustomDevelopCommand(develop):\n    def run(self):\n        develop.run(self)\n        git_submodule_update()\n\n\nclass CustomEggInfoCommand(egg_info):\n    def run(self):\n        egg_info.run(self)\n        git_submodule_update()\n\n\n# read version.py\nimport sys, re\n\ntry:\n    filepath = \"GANDLF/version.py\"\n    version_file = open(filepath)\n    (__version__,) = re.findall('__version__ = \"(.*)\"', version_file.read())\n\nexcept Exception as error:\n    __version__ = \"0.0.1\"\n    sys.stderr.write(\"Warning: Could not open '%s' due %s\\n\" % (filepath, error))\n\nrequirements = [\n    \"black\",\n    \"numpy==1.22.0\",\n    \"scipy\",\n    \"SimpleITK!=2.0.*\",\n    \"torchvision\",\n    \"tqdm\",\n    \"torchio==0.18.57\",\n    \"pandas\",\n    \"pylint\",\n    \"scikit-learn>=0.23.2\",\n    \"scikit-image>=0.19.1\",\n    'pickle5>=0.0.11; python_version < \"3.8.0\"',\n    \"setuptools\",\n    \"seaborn\",\n    \"pyyaml\",\n    \"tiffslide\",\n    \"matplotlib\",\n    \"requests>=2.25.0\",\n    \"pyvips==2.2.1\",\n    \"pytest\",\n    \"coverage\",\n    \"pytest-cov\",\n    \"psutil\",\n    \"medcam\",\n    \"opencv-python\",\n    \"torchmetrics==0.5.1\",  # newer versions have changed api for f1 invocation\n    \"OpenPatchMiner==0.1.8\",\n    \"zarr==2.10.3\",\n    \"pydicom\",\n    \"onnx\",\n    \"torchinfo==1.7.0\",\n]\n\n# pytorch doesn't have LTS support on OSX - https://github.com/CBICA/GaNDLF/issues/389\nif sys.platform == \"darwin\":\n    requirements.append(\"torch==1.9.0\")\nelse:\n    requirements.append(\"torch==1.8.2\")\n\nsetup(\n    name=\"GANDLF\",\n    version=__version__,\n    author=\"Jose Agraz, Vinayak Ahluwalia, Bhakti Baheti, Spyridon Bakas, Ujjwal Baid, Megh Bhalerao, Brandon Edwards, Karol Gotkowski, Caleb Grenko, Orhun G\u00fcley, Ibrahim Ethem Hamamci, Sarthak Pati, Micah Sheller, Juliia Skobleva, Siddhesh Thakur, Spiros Thermos\",  # alphabetical order\n    author_email=\"software@cbica.upenn.edu\",\n    python_requires=\">=3.7\",\n    packages=find_packages(),\n    cmdclass={  # this ensures git_submodule_update is called during install\n        \"install\": CustomInstallCommand,\n        \"develop\": CustomDevelopCommand,\n        \"egg_info\": CustomEggInfoCommand,\n    },\n    scripts=[\n        \"gandlf_run\",\n        \"gandlf_constructCSV\",\n        \"gandlf_collectStats\",\n        \"gandlf_patchMiner\",\n        \"gandlf_preprocess\",\n        \"gandlf_anonymizer\",\n        \"gandlf_verifyInstall\",\n    ],\n    classifiers=[\n        \"Development Status :: 3 - Alpha\",\n        \"Intended Audience :: Science/Research\",\n        \"License :: OSI Approved :: BSD License\",\n        \"Natural Language :: English\",\n        \"Operating System :: OS Independent\",\n        \"Programming Language :: Python :: 3.7\",\n        \"Programming Language :: Python :: 3.8\",\n        \"Programming Language :: Python :: 3.9\",\n        \"Topic :: Scientific/Engineering :: Medical Science Apps\",\n    ],\n    description=(\n        \"PyTorch-based framework that handles segmentation/regression/classification using various DL architectures for medical imaging.\"\n    ),\n    install_requires=requirements,\n    license=\"BSD-3-Clause License\",\n    long_description=readme,\n    long_description_content_type=\"text/markdown\",\n    include_package_data=True,\n    keywords=\"semantic, segmentation, regression, classification, data-augmentation, medical-imaging\",\n    zip_safe=False,\n)\n\n## windows vips installation\nif os.name == \"nt\":  # proceed for windows\n    from pathlib import Path\n\n    # download and extract if main dll is absent\n    if not Path(\"./vips/vips-dev-8.10/bin/libvips-42.dll\").exists():\n        print(\"Downloading and extracting VIPS for Windows\")\n        url = \"https://github.com/libvips/libvips/releases/download/v8.10.2/vips-dev-w64-all-8.10.2.zip\"\n        zip_to_extract = \"./vips.zip\"\n        import urllib.request, zipfile\n\n        urllib.request.urlretrieve(url, zip_to_extract)\n        z = zipfile.ZipFile(zip_to_extract)\n        z.extractall(\"./vips\")\n        z.close()\n        os.remove(zip_to_extract)\n", "path": "setup.py"}, {"content": "import os\n\n# hides torchio citation request, see https://github.com/fepegar/torchio/issues/235\nos.environ[\"TORCHIO_HIDE_CITATION_PROMPT\"] = \"1\"\n\nfrom .imaging import (\n    resize_image,\n    resample_image,\n    perform_sanity_check_on_subject,\n    write_training_patches,\n)\n\nfrom .tensor import (\n    one_hot,\n    reverse_one_hot,\n    send_model_to_device,\n    get_class_imbalance_weights,\n    get_class_imbalance_weights_segmentation,\n    get_class_imbalance_weights_classification,\n    get_linear_interpolation_mode,\n    print_model_summary,\n)\n\nfrom .write_parse import (\n    writeTrainingCSV,\n    parseTrainingCSV,\n    get_dataframe,\n)\n\nfrom .parameter_processing import (\n    populate_header_in_parameters,\n    find_problem_type,\n    populate_channel_keys_in_params,\n)\n\nfrom .generic import (\n    fix_paths,\n    get_date_time,\n    get_unique_timestamp,\n    get_filename_extension_sanitized,\n    version_check,\n)\n\nfrom .modelio import (\n    best_model_path_end,\n    load_model,\n    load_ov_model,\n    save_model,\n)\n", "path": "GANDLF/utils/__init__.py"}], "after_files": [{"content": "import os, datetime, sys\nimport numpy as np\n\n\ndef checkPatchDivisibility(patch_size, number=16):\n    \"\"\"\n    This function checks the divisibility of a numpy array or integer for architectural integrity\n\n    Args:\n        patch_size (numpy.array): The patch size for checking.\n        number (int, optional): The number to check divisibility for. Defaults to 16.\n\n    Returns:\n        bool: If all elements of array are divisible or not, after taking 2D patches into account.\n    \"\"\"\n    if isinstance(patch_size, int):\n        patch_size_to_check = np.array(patch_size)\n    else:\n        patch_size_to_check = patch_size\n    # for 2D, don't check divisibility of last dimension\n    if patch_size_to_check[-1] == 1:\n        patch_size_to_check = patch_size_to_check[:-1]\n    # for 2D, don't check divisibility of first dimension\n    elif patch_size_to_check[0] == 1:\n        patch_size_to_check = patch_size_to_check[1:]\n    if np.count_nonzero(np.remainder(patch_size_to_check, number)) > 0:\n        return False\n\n    # adding check to address https://github.com/CBICA/GaNDLF/issues/53\n    # there is quite possibly a better way to do this\n    unique = np.unique(patch_size_to_check)\n    if (unique.shape[0] == 1) and (unique[0] <= number):\n        return False\n    return True\n\n\ndef get_date_time():\n    \"\"\"\n    Get a well-parsed date string\n\n    Returns:\n        str: The date in format YYYY/MM/DD::HH:MM:SS\n    \"\"\"\n    now = datetime.datetime.now().strftime(\"%Y/%m/%d::%H:%M:%S\")\n    return now\n\n\ndef get_unique_timestamp():\n    \"\"\"\n    Get a well-parsed timestamp string to be used for unique filenames\n\n    Returns:\n        str: The date in format YYYYMMDD_HHMMSS\n    \"\"\"\n    now = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n    return now\n\n\ndef get_filename_extension_sanitized(filename):\n    \"\"\"\n    This function returns the extension of the filename with leading and trailing characters removed.\n    Args:\n        filename (str): The filename to be processed.\n    Returns:\n        str: The filename with extension removed.\n    \"\"\"\n    _, ext = os.path.splitext(filename)\n    # if .gz or .nii file is detected, always return .nii.gz\n    if (ext == \".gz\") or (ext == \".nii\"):\n        ext = \".nii.gz\"\n    return ext\n\n\ndef parse_version(version_string):\n    \"\"\"\n    Parses version string, discards last identifier (NR/alpha/beta) and returns an integer for comparison.\n\n    Args:\n        version_string (str): The string to be parsed.\n\n    Returns:\n        int: The version number.\n    \"\"\"\n    version_string_split = version_string.split(\".\")\n    if len(version_string_split) > 3:\n        del version_string_split[-1]\n    return int(\"\".join(version_string_split))\n\n\ndef version_check(version_from_config, version_to_check):\n    \"\"\"\n    This function checks if the version of the config file is compatible with the version of the code.\n\n    Args:\n        version_from_config (str): The version of the config file.\n        version_to_check (str): The version of the code or model to check.\n\n    Returns:\n        bool: If the version of the config file is compatible with the version of the code.\n    \"\"\"\n    version_to_check_int = parse_version(version_to_check)\n    min_ver = parse_version(version_from_config[\"minimum\"])\n    max_ver = parse_version(version_from_config[\"maximum\"])\n    if (min_ver > version_to_check_int) or (max_ver < version_to_check_int):\n        sys.exit(\n            \"Incompatible version of GaNDLF detected (\"\n            + str(version_to_check_int)\n            + \")\"\n        )\n\n    return True\n\n\ndef checkPatchDimensions(patch_size, numlay):\n    \"\"\"\n    This function checks the divisibility of a numpy array or integer for architectural integrity\n\n    Args:\n        patch_size (numpy.array): The patch size for checking.\n        number (int, optional): The number to check divisibility for. Defaults to 16.\n\n    Returns:\n        int: Largest multiple of 2 (less than or equal to numlay) that each element of patch size is divisible by to yield int >= 2\n    \"\"\"\n    if isinstance(patch_size, int):\n        patch_size_to_check = np.array(patch_size)\n    else:\n        patch_size_to_check = patch_size\n    # for 2D, don't check divisibility of last dimension\n    if patch_size_to_check[-1] == 1:\n        patch_size_to_check = patch_size_to_check[:-1]\n\n    if all(\n        [x >= 2 ** (numlay + 1) and x % 2**numlay == 0 for x in patch_size_to_check]\n    ):\n        return numlay\n    else:\n        # base2 = np.floor(np.log2(patch_size_to_check))\n        base2 = np.array([getBase2(x) for x in patch_size_to_check])\n        remain = patch_size_to_check / 2**base2  # check that at least 1\n\n        layers = np.where(remain == 1, base2 - 1, base2)\n        return int(np.min(layers))\n\n\ndef getBase2(num):\n    # helper for checkPatchDimensions (returns the largest multiple of 2 that num is evenly divisible by)\n    base = 0\n    while num % 2 == 0:\n        num = num / 2\n        base = base + 1\n    return base\n", "path": "GANDLF/utils/generic.py"}, {"content": "#!/usr/bin/env python\n\n\"\"\"The setup script.\"\"\"\n\n\nimport os\nfrom setuptools import setup, find_packages\nfrom setuptools.command.install import install\nfrom setuptools.command.develop import develop\nfrom setuptools.command.egg_info import egg_info\n\nwith open(\"README.md\") as readme_file:\n    readme = readme_file.read()\n\n\ndef git_submodule_update():\n    ## submodule update\n    os.system(\"git submodule update --init --recursive\")\n\n\nclass CustomInstallCommand(install):\n    def run(self):\n        install.run(self)\n        git_submodule_update()\n\n\nclass CustomDevelopCommand(develop):\n    def run(self):\n        develop.run(self)\n        git_submodule_update()\n\n\nclass CustomEggInfoCommand(egg_info):\n    def run(self):\n        egg_info.run(self)\n        git_submodule_update()\n\n\n# read version.py\nimport sys, re\n\ntry:\n    filepath = \"GANDLF/version.py\"\n    version_file = open(filepath)\n    (__version__,) = re.findall('__version__ = \"(.*)\"', version_file.read())\n\nexcept Exception as error:\n    __version__ = \"0.0.1\"\n    sys.stderr.write(\"Warning: Could not open '%s' due %s\\n\" % (filepath, error))\n\nrequirements = [\n    \"black\",\n    \"numpy==1.22.0\",\n    \"scipy\",\n    \"SimpleITK!=2.0.*\",\n    \"torchvision\",\n    \"tqdm\",\n    \"torchio==0.18.57\",\n    \"pandas\",\n    \"pylint\",\n    \"scikit-learn>=0.23.2\",\n    \"scikit-image>=0.19.1\",\n    'pickle5>=0.0.11; python_version < \"3.8.0\"',\n    \"setuptools\",\n    \"seaborn\",\n    \"pyyaml\",\n    \"tiffslide\",\n    \"matplotlib\",\n    \"requests>=2.25.0\",\n    \"pytest\",\n    \"coverage\",\n    \"pytest-cov\",\n    \"psutil\",\n    \"medcam\",\n    \"opencv-python\",\n    \"torchmetrics==0.5.1\",  # newer versions have changed api for f1 invocation\n    \"OpenPatchMiner==0.1.8\",\n    \"zarr==2.10.3\",\n    \"pydicom\",\n    \"onnx\",\n    \"torchinfo==1.7.0\",\n]\n\n# pytorch doesn't have LTS support on OSX - https://github.com/CBICA/GaNDLF/issues/389\nif sys.platform == \"darwin\":\n    requirements.append(\"torch==1.9.0\")\nelse:\n    requirements.append(\"torch==1.8.2\")\n\nsetup(\n    name=\"GANDLF\",\n    version=__version__,\n    author=\"Jose Agraz, Vinayak Ahluwalia, Bhakti Baheti, Spyridon Bakas, Ujjwal Baid, Megh Bhalerao, Brandon Edwards, Karol Gotkowski, Caleb Grenko, Orhun G\u00fcley, Ibrahim Ethem Hamamci, Sarthak Pati, Micah Sheller, Juliia Skobleva, Siddhesh Thakur, Spiros Thermos\",  # alphabetical order\n    author_email=\"software@cbica.upenn.edu\",\n    python_requires=\">=3.7\",\n    packages=find_packages(),\n    cmdclass={  # this ensures git_submodule_update is called during install\n        \"install\": CustomInstallCommand,\n        \"develop\": CustomDevelopCommand,\n        \"egg_info\": CustomEggInfoCommand,\n    },\n    scripts=[\n        \"gandlf_run\",\n        \"gandlf_constructCSV\",\n        \"gandlf_collectStats\",\n        \"gandlf_patchMiner\",\n        \"gandlf_preprocess\",\n        \"gandlf_anonymizer\",\n        \"gandlf_verifyInstall\",\n    ],\n    classifiers=[\n        \"Development Status :: 3 - Alpha\",\n        \"Intended Audience :: Science/Research\",\n        \"License :: OSI Approved :: BSD License\",\n        \"Natural Language :: English\",\n        \"Operating System :: OS Independent\",\n        \"Programming Language :: Python :: 3.7\",\n        \"Programming Language :: Python :: 3.8\",\n        \"Programming Language :: Python :: 3.9\",\n        \"Topic :: Scientific/Engineering :: Medical Science Apps\",\n    ],\n    description=(\n        \"PyTorch-based framework that handles segmentation/regression/classification using various DL architectures for medical imaging.\"\n    ),\n    install_requires=requirements,\n    license=\"BSD-3-Clause License\",\n    long_description=readme,\n    long_description_content_type=\"text/markdown\",\n    include_package_data=True,\n    keywords=\"semantic, segmentation, regression, classification, data-augmentation, medical-imaging\",\n    zip_safe=False,\n)\n", "path": "setup.py"}, {"content": "import os\n\n# hides torchio citation request, see https://github.com/fepegar/torchio/issues/235\nos.environ[\"TORCHIO_HIDE_CITATION_PROMPT\"] = \"1\"\n\nfrom .imaging import (\n    resize_image,\n    resample_image,\n    perform_sanity_check_on_subject,\n    write_training_patches,\n)\n\nfrom .tensor import (\n    one_hot,\n    reverse_one_hot,\n    send_model_to_device,\n    get_class_imbalance_weights,\n    get_class_imbalance_weights_segmentation,\n    get_class_imbalance_weights_classification,\n    get_linear_interpolation_mode,\n    print_model_summary,\n)\n\nfrom .write_parse import (\n    writeTrainingCSV,\n    parseTrainingCSV,\n    get_dataframe,\n)\n\nfrom .parameter_processing import (\n    populate_header_in_parameters,\n    find_problem_type,\n    populate_channel_keys_in_params,\n)\n\nfrom .generic import (\n    get_date_time,\n    get_unique_timestamp,\n    get_filename_extension_sanitized,\n    version_check,\n)\n\nfrom .modelio import (\n    best_model_path_end,\n    load_model,\n    load_ov_model,\n    save_model,\n)\n", "path": "GANDLF/utils/__init__.py"}]}