We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Default mapping to GPU device during inference
**Describe the bug**
When running on CPU, this issue occurs: RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False. If you are running on a CPU-only machine, please use torch.load with map_location=torch.device('cpu') to map your storages to the CPU. Hence adding `map_location` to torch.load (Ref: https://pytorch.org/docs/stable/generated/torch.load.html).
Please review.

**To Reproduce**
Steps to reproduce the behavior:
After data preprocess, run:
python gandlf_run -c <config> -i <val_dataset> -m <model_dir> -t False -d cpu

**Expected behavior**
Model should be mapped to the CPU device. Although there is a `send_model_to_device` method implemented, this error occurs before that, during `torch.load`

**Screenshots**
If applicable, add screenshots to help explain your problem.

**GaNDLF Version**
Version: 0.0.13

**Desktop (please complete the following information):**
 - OS: Linux CentOS 7.6

**Additional context**
Can provided if needed


--- 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/compute/inference_loop.py`
Content:
```
1 from .forward_pass import validate_network
2 import os
3 
4 # hides torchio citation request, see https://github.com/fepegar/torchio/issues/235
5 os.environ["TORCHIO_HIDE_CITATION_PROMPT"] = "1"
6 
7 import pickle, argparse, torch
8 import numpy as np
9 import pandas as pd
10 from torch.utils.data import DataLoader
11 from skimage.io import imsave
12 from tqdm import tqdm
13 from torch.cuda.amp import autocast
14 from GANDLF.data.ImagesFromDataFrame import ImagesFromDataFrame
15 from GANDLF.utils import populate_channel_keys_in_params, send_model_to_device
16 from GANDLF.models import global_models_dict
17 
18 
19 def inference_loop(inferenceDataFromPickle, device, parameters, outputDir):
20     """
21     The main training loop.
22 
23     Args:
24         inferenceDataFromPickle (pandas.DataFrame): The data to use for inference.
25         device (str): The device to perform computations on.
26         parameters (dict): The parameters dictionary.
27         outputDir (str): The output directory.
28     """
29     # Defining our model here according to parameters mentioned in the configuration file
30     print("Number of dims     : ", parameters["model"]["dimension"])
31     if "num_channels" in parameters["model"]:
32         print("Number of channels : ", parameters["model"]["num_channels"])
33     print("Number of classes  : ", len(parameters["model"]["class_list"]))
34 
35     # Fetch the model according to params mentioned in the configuration file
36     model = global_models_dict[parameters["model"]["architecture"]](
37         parameters=parameters
38     )
39 
40     # Setting up the inference loader
41     inferenceDataForTorch = ImagesFromDataFrame(
42         inferenceDataFromPickle, parameters, train=False
43     )
44     inference_loader = DataLoader(inferenceDataForTorch, batch_size=1)
45 
46     # Loading the weights into the model
47     main_dict = outputDir
48     if os.path.isdir(outputDir):
49         file_to_check = os.path.join(
50             outputDir, str(parameters["model"]["architecture"]) + "_best.pth.tar"
51         )
52         if not os.path.isfile(file_to_check):
53             raise ValueError("The model specified model was not found:", file_to_check)
54     main_dict = torch.load(file_to_check)
55     model.load_state_dict(main_dict["model_state_dict"])
56 
57     if not (os.environ.get("HOSTNAME") is None):
58         print("\nHostname     :" + str(os.environ.get("HOSTNAME")), flush=True)
59 
60     # get the channel keys for concatenation later (exclude non numeric channel keys)
61     parameters = populate_channel_keys_in_params(inference_loader, parameters)
62     parameters["save_output"] = True
63 
64     print("Data Samples: ", len(inference_loader.dataset), flush=True)
65     model, parameters["model"]["amp"], parameters["device"] = send_model_to_device(
66         model, parameters["model"]["amp"], device, optimizer=None
67     )
68 
69     print("Using device:", parameters["device"], flush=True)
70 
71     # radiology inference
72     if parameters["modality"] == "rad":
73         average_epoch_valid_loss, average_epoch_valid_metric = validate_network(
74             model, inference_loader, None, parameters, mode="inference"
75         )
76         print(average_epoch_valid_loss, average_epoch_valid_metric)
77     elif (parameters["modality"] == "path") or (parameters["modality"] == "histo"):
78         # histology inference
79         if os.name != "nt":
80             """
81             path inference is Linux-only because openslide for Windows works only for Python-3.8  whereas pickle5 works only for 3.6 and 3.7
82             """
83             from GANDLF.data.inference_dataloader_histopath import InferTumorSegDataset
84             from openslide import OpenSlide
85 
86             # actual computation
87             for _, row in inferenceDataForTorch.iterrows():
88                 subject_name = row[parameters["headers"]["subjectIDHeader"]]
89                 print(
90                     "Patient Slide       : ",
91                     row[parameters["headers"]["subjectIDHeader"]],
92                 )
93                 print(
94                     "Patient Location    : ",
95                     row[parameters["headers"]["channelHeaders"]],
96                 )
97                 print(row[parameters["headers"]["channelHeaders"]].values[0])
98                 os_image = OpenSlide(
99                     row[parameters["headers"]["channelHeaders"]].values[0]
100                 )
101                 level_width, level_height = os_image.level_dimensions[
102                     int(parameters["slide_level"])
103                 ]
104                 subject_dest_dir = os.path.join(outputDir, subject_name)
105                 os.makedirs(subject_dest_dir, exist_ok=True)
106 
107                 probs_map = np.zeros((level_height, level_width), dtype=np.float16)
108                 count_map = np.zeros((level_height, level_width), dtype=np.uint8)
109 
110                 patient_dataset_obj = InferTumorSegDataset(
111                     row[parameters["headers"]["channelHeaders"]].values[0],
112                     patch_size=patch_size,
113                     stride_size=parameters["stride_size"],
114                     selected_level=parameters["slide_level"],
115                     mask_level=4,
116                 )
117 
118                 dataloader = DataLoader(
119                     patient_dataset_obj,
120                     batch_size=int(parameters["batch_size"]),
121                     shuffle=False,
122                     num_workers=parameters["q_num_workers"],
123                 )
124                 for image_patches, (x_coords, y_coords) in tqdm(dataloader):
125                     x_coords, y_coords = y_coords.numpy(), x_coords.numpy()
126                     if parameters["model"]["amp"]:
127                         with autocast():
128                             output = model(
129                                 image_patches.float().to(parameters["device"])
130                             )
131                     else:
132                         output = model(image_patches.float().to(parameters["device"]))
133                     output = output.detach().cpu().numpy()
134                     for i in range(int(output.shape[0])):
135                         count_map[
136                             x_coords[i] : x_coords[i] + patch_size[0],
137                             y_coords[i] : y_coords[i] + patch_size[1],
138                         ] += 1
139                         probs_map[
140                             x_coords[i] : x_coords[i] + patch_size[0],
141                             y_coords[i] : y_coords[i] + patch_size[1],
142                         ] += output[i][0]
143                 probs_map = probs_map / count_map
144                 count_map = count_map / count_map.max()
145                 out = count_map * probs_map
146                 count_map = np.array(count_map * 255, dtype=np.uint16)
147                 out_thresh = np.array((out > 0.5) * 255, dtype=np.uint16)
148                 imsave(
149                     os.path.join(
150                         subject_dest_dir,
151                         row[parameters["headers"]["subjectIDHeader"]] + "_prob.png",
152                     ),
153                     out,
154                 )
155                 imsave(
156                     os.path.join(
157                         subject_dest_dir,
158                         row[parameters["headers"]["subjectIDHeader"]] + "_seg.png",
159                     ),
160                     out_thresh,
161                 )
162                 imsave(
163                     os.path.join(
164                         subject_dest_dir,
165                         row[parameters["headers"]["subjectIDHeader"]] + "_count.png",
166                     ),
167                     count_map,
168                 )
169         else:
170             print(
171                 "ERROR: histo/path inference is Linux-only because openslide for Windows works only for Python-3.8, whereas pickle5 works only for 3.6 and 3.7"
172             )
173 
174 
175 if __name__ == "__main__":
176 
177     # parse the cli arguments here
178     parser = argparse.ArgumentParser(description="Inference Loop of GANDLF")
179     parser.add_argument(
180         "-inference_loader_pickle",
181         type=str,
182         help="Inference loader pickle",
183         required=True,
184     )
185     parser.add_argument(
186         "-parameter_pickle", type=str, help="Parameters pickle", required=True
187     )
188     parser.add_argument(
189         "-headers_pickle", type=str, help="Header pickle", required=True
190     )
191     parser.add_argument("-outputDir", type=str, help="Output directory", required=True)
192     parser.add_argument("-device", type=str, help="Device to train on", required=True)
193 
194     args = parser.parse_args()
195 
196     # # write parameters to pickle - this should not change for the different folds, so keeping is independent
197     patch_size = pickle.load(open(args.patch_size_pickle, "rb"))
198     headers = pickle.load(open(args.headers_pickle, "rb"))
199     label_header = pickle.load(open(args.label_header_pickle, "rb"))
200     parameters = pickle.load(open(args.parameter_pickle, "rb"))
201     inferenceDataFromPickle = pd.read_pickle(args.inference_loader_pickle)
202 
203     inference_loop(
204         inferenceDataFromPickle=inferenceDataFromPickle,
205         parameters=parameters,
206         outputDir=args.outputDir,
207         device=args.device,
208     )
209
```
--- 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/compute/inference_loop.py b/GANDLF/compute/inference_loop.py
--- a/GANDLF/compute/inference_loop.py
+++ b/GANDLF/compute/inference_loop.py
@@ -51,7 +51,8 @@
         )
         if not os.path.isfile(file_to_check):
             raise ValueError("The model specified model was not found:", file_to_check)
-    main_dict = torch.load(file_to_check)
+
+    main_dict = torch.load(file_to_check, map_location=torch.device(device))
     model.load_state_dict(main_dict["model_state_dict"])
 
     if not (os.environ.get("HOSTNAME") is None):

{"golden_diff": "diff --git a/GANDLF/compute/inference_loop.py b/GANDLF/compute/inference_loop.py\n--- a/GANDLF/compute/inference_loop.py\n+++ b/GANDLF/compute/inference_loop.py\n@@ -51,7 +51,8 @@\n         )\n         if not os.path.isfile(file_to_check):\n             raise ValueError(\"The model specified model was not found:\", file_to_check)\n-    main_dict = torch.load(file_to_check)\n+\n+    main_dict = torch.load(file_to_check, map_location=torch.device(device))\n     model.load_state_dict(main_dict[\"model_state_dict\"])\n \n     if not (os.environ.get(\"HOSTNAME\") is None):\n", "issue": "Default mapping to GPU device during inference\n**Describe the bug**\r\nWhen running on CPU, this issue occurs: RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False. If you are running on a CPU-only machine, please use torch.load with map_location=torch.device('cpu') to map your storages to the CPU. Hence adding `map_location` to torch.load (Ref: https://pytorch.org/docs/stable/generated/torch.load.html).\r\nPlease review.\r\n\r\n**To Reproduce**\r\nSteps to reproduce the behavior:\r\nAfter data preprocess, run:\r\npython gandlf_run -c <config> -i <val_dataset> -m <model_dir> -t False -d cpu\r\n\r\n**Expected behavior**\r\nModel should be mapped to the CPU device. Although there is a `send_model_to_device` method implemented, this error occurs before that, during `torch.load`\r\n\r\n**Screenshots**\r\nIf applicable, add screenshots to help explain your problem.\r\n\r\n**GaNDLF Version**\r\nVersion: 0.0.13\r\n\r\n**Desktop (please complete the following information):**\r\n - OS: Linux CentOS 7.6\r\n\r\n**Additional context**\r\nCan provided if needed\r\n\n", "before_files": [{"content": "from .forward_pass import validate_network\nimport os\n\n# hides torchio citation request, see https://github.com/fepegar/torchio/issues/235\nos.environ[\"TORCHIO_HIDE_CITATION_PROMPT\"] = \"1\"\n\nimport pickle, argparse, torch\nimport numpy as np\nimport pandas as pd\nfrom torch.utils.data import DataLoader\nfrom skimage.io import imsave\nfrom tqdm import tqdm\nfrom torch.cuda.amp import autocast\nfrom GANDLF.data.ImagesFromDataFrame import ImagesFromDataFrame\nfrom GANDLF.utils import populate_channel_keys_in_params, send_model_to_device\nfrom GANDLF.models import global_models_dict\n\n\ndef inference_loop(inferenceDataFromPickle, device, parameters, outputDir):\n    \"\"\"\n    The main training loop.\n\n    Args:\n        inferenceDataFromPickle (pandas.DataFrame): The data to use for inference.\n        device (str): The device to perform computations on.\n        parameters (dict): The parameters dictionary.\n        outputDir (str): The output directory.\n    \"\"\"\n    # Defining our model here according to parameters mentioned in the configuration file\n    print(\"Number of dims     : \", parameters[\"model\"][\"dimension\"])\n    if \"num_channels\" in parameters[\"model\"]:\n        print(\"Number of channels : \", parameters[\"model\"][\"num_channels\"])\n    print(\"Number of classes  : \", len(parameters[\"model\"][\"class_list\"]))\n\n    # Fetch the model according to params mentioned in the configuration file\n    model = global_models_dict[parameters[\"model\"][\"architecture\"]](\n        parameters=parameters\n    )\n\n    # Setting up the inference loader\n    inferenceDataForTorch = ImagesFromDataFrame(\n        inferenceDataFromPickle, parameters, train=False\n    )\n    inference_loader = DataLoader(inferenceDataForTorch, batch_size=1)\n\n    # Loading the weights into the model\n    main_dict = outputDir\n    if os.path.isdir(outputDir):\n        file_to_check = os.path.join(\n            outputDir, str(parameters[\"model\"][\"architecture\"]) + \"_best.pth.tar\"\n        )\n        if not os.path.isfile(file_to_check):\n            raise ValueError(\"The model specified model was not found:\", file_to_check)\n    main_dict = torch.load(file_to_check)\n    model.load_state_dict(main_dict[\"model_state_dict\"])\n\n    if not (os.environ.get(\"HOSTNAME\") is None):\n        print(\"\\nHostname     :\" + str(os.environ.get(\"HOSTNAME\")), flush=True)\n\n    # get the channel keys for concatenation later (exclude non numeric channel keys)\n    parameters = populate_channel_keys_in_params(inference_loader, parameters)\n    parameters[\"save_output\"] = True\n\n    print(\"Data Samples: \", len(inference_loader.dataset), flush=True)\n    model, parameters[\"model\"][\"amp\"], parameters[\"device\"] = send_model_to_device(\n        model, parameters[\"model\"][\"amp\"], device, optimizer=None\n    )\n\n    print(\"Using device:\", parameters[\"device\"], flush=True)\n\n    # radiology inference\n    if parameters[\"modality\"] == \"rad\":\n        average_epoch_valid_loss, average_epoch_valid_metric = validate_network(\n            model, inference_loader, None, parameters, mode=\"inference\"\n        )\n        print(average_epoch_valid_loss, average_epoch_valid_metric)\n    elif (parameters[\"modality\"] == \"path\") or (parameters[\"modality\"] == \"histo\"):\n        # histology inference\n        if os.name != \"nt\":\n            \"\"\"\n            path inference is Linux-only because openslide for Windows works only for Python-3.8  whereas pickle5 works only for 3.6 and 3.7\n            \"\"\"\n            from GANDLF.data.inference_dataloader_histopath import InferTumorSegDataset\n            from openslide import OpenSlide\n\n            # actual computation\n            for _, row in inferenceDataForTorch.iterrows():\n                subject_name = row[parameters[\"headers\"][\"subjectIDHeader\"]]\n                print(\n                    \"Patient Slide       : \",\n                    row[parameters[\"headers\"][\"subjectIDHeader\"]],\n                )\n                print(\n                    \"Patient Location    : \",\n                    row[parameters[\"headers\"][\"channelHeaders\"]],\n                )\n                print(row[parameters[\"headers\"][\"channelHeaders\"]].values[0])\n                os_image = OpenSlide(\n                    row[parameters[\"headers\"][\"channelHeaders\"]].values[0]\n                )\n                level_width, level_height = os_image.level_dimensions[\n                    int(parameters[\"slide_level\"])\n                ]\n                subject_dest_dir = os.path.join(outputDir, subject_name)\n                os.makedirs(subject_dest_dir, exist_ok=True)\n\n                probs_map = np.zeros((level_height, level_width), dtype=np.float16)\n                count_map = np.zeros((level_height, level_width), dtype=np.uint8)\n\n                patient_dataset_obj = InferTumorSegDataset(\n                    row[parameters[\"headers\"][\"channelHeaders\"]].values[0],\n                    patch_size=patch_size,\n                    stride_size=parameters[\"stride_size\"],\n                    selected_level=parameters[\"slide_level\"],\n                    mask_level=4,\n                )\n\n                dataloader = DataLoader(\n                    patient_dataset_obj,\n                    batch_size=int(parameters[\"batch_size\"]),\n                    shuffle=False,\n                    num_workers=parameters[\"q_num_workers\"],\n                )\n                for image_patches, (x_coords, y_coords) in tqdm(dataloader):\n                    x_coords, y_coords = y_coords.numpy(), x_coords.numpy()\n                    if parameters[\"model\"][\"amp\"]:\n                        with autocast():\n                            output = model(\n                                image_patches.float().to(parameters[\"device\"])\n                            )\n                    else:\n                        output = model(image_patches.float().to(parameters[\"device\"]))\n                    output = output.detach().cpu().numpy()\n                    for i in range(int(output.shape[0])):\n                        count_map[\n                            x_coords[i] : x_coords[i] + patch_size[0],\n                            y_coords[i] : y_coords[i] + patch_size[1],\n                        ] += 1\n                        probs_map[\n                            x_coords[i] : x_coords[i] + patch_size[0],\n                            y_coords[i] : y_coords[i] + patch_size[1],\n                        ] += output[i][0]\n                probs_map = probs_map / count_map\n                count_map = count_map / count_map.max()\n                out = count_map * probs_map\n                count_map = np.array(count_map * 255, dtype=np.uint16)\n                out_thresh = np.array((out > 0.5) * 255, dtype=np.uint16)\n                imsave(\n                    os.path.join(\n                        subject_dest_dir,\n                        row[parameters[\"headers\"][\"subjectIDHeader\"]] + \"_prob.png\",\n                    ),\n                    out,\n                )\n                imsave(\n                    os.path.join(\n                        subject_dest_dir,\n                        row[parameters[\"headers\"][\"subjectIDHeader\"]] + \"_seg.png\",\n                    ),\n                    out_thresh,\n                )\n                imsave(\n                    os.path.join(\n                        subject_dest_dir,\n                        row[parameters[\"headers\"][\"subjectIDHeader\"]] + \"_count.png\",\n                    ),\n                    count_map,\n                )\n        else:\n            print(\n                \"ERROR: histo/path inference is Linux-only because openslide for Windows works only for Python-3.8, whereas pickle5 works only for 3.6 and 3.7\"\n            )\n\n\nif __name__ == \"__main__\":\n\n    # parse the cli arguments here\n    parser = argparse.ArgumentParser(description=\"Inference Loop of GANDLF\")\n    parser.add_argument(\n        \"-inference_loader_pickle\",\n        type=str,\n        help=\"Inference loader pickle\",\n        required=True,\n    )\n    parser.add_argument(\n        \"-parameter_pickle\", type=str, help=\"Parameters pickle\", required=True\n    )\n    parser.add_argument(\n        \"-headers_pickle\", type=str, help=\"Header pickle\", required=True\n    )\n    parser.add_argument(\"-outputDir\", type=str, help=\"Output directory\", required=True)\n    parser.add_argument(\"-device\", type=str, help=\"Device to train on\", required=True)\n\n    args = parser.parse_args()\n\n    # # write parameters to pickle - this should not change for the different folds, so keeping is independent\n    patch_size = pickle.load(open(args.patch_size_pickle, \"rb\"))\n    headers = pickle.load(open(args.headers_pickle, \"rb\"))\n    label_header = pickle.load(open(args.label_header_pickle, \"rb\"))\n    parameters = pickle.load(open(args.parameter_pickle, \"rb\"))\n    inferenceDataFromPickle = pd.read_pickle(args.inference_loader_pickle)\n\n    inference_loop(\n        inferenceDataFromPickle=inferenceDataFromPickle,\n        parameters=parameters,\n        outputDir=args.outputDir,\n        device=args.device,\n    )\n", "path": "GANDLF/compute/inference_loop.py"}], "after_files": [{"content": "from .forward_pass import validate_network\nimport os\n\n# hides torchio citation request, see https://github.com/fepegar/torchio/issues/235\nos.environ[\"TORCHIO_HIDE_CITATION_PROMPT\"] = \"1\"\n\nimport pickle, argparse, torch\nimport numpy as np\nimport pandas as pd\nfrom torch.utils.data import DataLoader\nfrom skimage.io import imsave\nfrom tqdm import tqdm\nfrom torch.cuda.amp import autocast\nfrom GANDLF.data.ImagesFromDataFrame import ImagesFromDataFrame\nfrom GANDLF.utils import populate_channel_keys_in_params, send_model_to_device\nfrom GANDLF.models import global_models_dict\n\n\ndef inference_loop(inferenceDataFromPickle, device, parameters, outputDir):\n    \"\"\"\n    The main training loop.\n\n    Args:\n        inferenceDataFromPickle (pandas.DataFrame): The data to use for inference.\n        device (str): The device to perform computations on.\n        parameters (dict): The parameters dictionary.\n        outputDir (str): The output directory.\n    \"\"\"\n    # Defining our model here according to parameters mentioned in the configuration file\n    print(\"Number of dims     : \", parameters[\"model\"][\"dimension\"])\n    if \"num_channels\" in parameters[\"model\"]:\n        print(\"Number of channels : \", parameters[\"model\"][\"num_channels\"])\n    print(\"Number of classes  : \", len(parameters[\"model\"][\"class_list\"]))\n\n    # Fetch the model according to params mentioned in the configuration file\n    model = global_models_dict[parameters[\"model\"][\"architecture\"]](\n        parameters=parameters\n    )\n\n    # Setting up the inference loader\n    inferenceDataForTorch = ImagesFromDataFrame(\n        inferenceDataFromPickle, parameters, train=False\n    )\n    inference_loader = DataLoader(inferenceDataForTorch, batch_size=1)\n\n    # Loading the weights into the model\n    main_dict = outputDir\n    if os.path.isdir(outputDir):\n        file_to_check = os.path.join(\n            outputDir, str(parameters[\"model\"][\"architecture\"]) + \"_best.pth.tar\"\n        )\n        if not os.path.isfile(file_to_check):\n            raise ValueError(\"The model specified model was not found:\", file_to_check)\n\n    main_dict = torch.load(file_to_check, map_location=torch.device(device))\n    model.load_state_dict(main_dict[\"model_state_dict\"])\n\n    if not (os.environ.get(\"HOSTNAME\") is None):\n        print(\"\\nHostname     :\" + str(os.environ.get(\"HOSTNAME\")), flush=True)\n\n    # get the channel keys for concatenation later (exclude non numeric channel keys)\n    parameters = populate_channel_keys_in_params(inference_loader, parameters)\n    parameters[\"save_output\"] = True\n\n    print(\"Data Samples: \", len(inference_loader.dataset), flush=True)\n    model, parameters[\"model\"][\"amp\"], parameters[\"device\"] = send_model_to_device(\n        model, parameters[\"model\"][\"amp\"], device, optimizer=None\n    )\n\n    print(\"Using device:\", parameters[\"device\"], flush=True)\n\n    # radiology inference\n    if parameters[\"modality\"] == \"rad\":\n        average_epoch_valid_loss, average_epoch_valid_metric = validate_network(\n            model, inference_loader, None, parameters, mode=\"inference\"\n        )\n        print(average_epoch_valid_loss, average_epoch_valid_metric)\n    elif (parameters[\"modality\"] == \"path\") or (parameters[\"modality\"] == \"histo\"):\n        # histology inference\n        if os.name != \"nt\":\n            \"\"\"\n            path inference is Linux-only because openslide for Windows works only for Python-3.8  whereas pickle5 works only for 3.6 and 3.7\n            \"\"\"\n            from GANDLF.data.inference_dataloader_histopath import InferTumorSegDataset\n            from openslide import OpenSlide\n\n            # actual computation\n            for _, row in inferenceDataForTorch.iterrows():\n                subject_name = row[parameters[\"headers\"][\"subjectIDHeader\"]]\n                print(\n                    \"Patient Slide       : \",\n                    row[parameters[\"headers\"][\"subjectIDHeader\"]],\n                )\n                print(\n                    \"Patient Location    : \",\n                    row[parameters[\"headers\"][\"channelHeaders\"]],\n                )\n                print(row[parameters[\"headers\"][\"channelHeaders\"]].values[0])\n                os_image = OpenSlide(\n                    row[parameters[\"headers\"][\"channelHeaders\"]].values[0]\n                )\n                level_width, level_height = os_image.level_dimensions[\n                    int(parameters[\"slide_level\"])\n                ]\n                subject_dest_dir = os.path.join(outputDir, subject_name)\n                os.makedirs(subject_dest_dir, exist_ok=True)\n\n                probs_map = np.zeros((level_height, level_width), dtype=np.float16)\n                count_map = np.zeros((level_height, level_width), dtype=np.uint8)\n\n                patient_dataset_obj = InferTumorSegDataset(\n                    row[parameters[\"headers\"][\"channelHeaders\"]].values[0],\n                    patch_size=patch_size,\n                    stride_size=parameters[\"stride_size\"],\n                    selected_level=parameters[\"slide_level\"],\n                    mask_level=4,\n                )\n\n                dataloader = DataLoader(\n                    patient_dataset_obj,\n                    batch_size=int(parameters[\"batch_size\"]),\n                    shuffle=False,\n                    num_workers=parameters[\"q_num_workers\"],\n                )\n                for image_patches, (x_coords, y_coords) in tqdm(dataloader):\n                    x_coords, y_coords = y_coords.numpy(), x_coords.numpy()\n                    if parameters[\"model\"][\"amp\"]:\n                        with autocast():\n                            output = model(\n                                image_patches.float().to(parameters[\"device\"])\n                            )\n                    else:\n                        output = model(image_patches.float().to(parameters[\"device\"]))\n                    output = output.detach().cpu().numpy()\n                    for i in range(int(output.shape[0])):\n                        count_map[\n                            x_coords[i] : x_coords[i] + patch_size[0],\n                            y_coords[i] : y_coords[i] + patch_size[1],\n                        ] += 1\n                        probs_map[\n                            x_coords[i] : x_coords[i] + patch_size[0],\n                            y_coords[i] : y_coords[i] + patch_size[1],\n                        ] += output[i][0]\n                probs_map = probs_map / count_map\n                count_map = count_map / count_map.max()\n                out = count_map * probs_map\n                count_map = np.array(count_map * 255, dtype=np.uint16)\n                out_thresh = np.array((out > 0.5) * 255, dtype=np.uint16)\n                imsave(\n                    os.path.join(\n                        subject_dest_dir,\n                        row[parameters[\"headers\"][\"subjectIDHeader\"]] + \"_prob.png\",\n                    ),\n                    out,\n                )\n                imsave(\n                    os.path.join(\n                        subject_dest_dir,\n                        row[parameters[\"headers\"][\"subjectIDHeader\"]] + \"_seg.png\",\n                    ),\n                    out_thresh,\n                )\n                imsave(\n                    os.path.join(\n                        subject_dest_dir,\n                        row[parameters[\"headers\"][\"subjectIDHeader\"]] + \"_count.png\",\n                    ),\n                    count_map,\n                )\n        else:\n            print(\n                \"ERROR: histo/path inference is Linux-only because openslide for Windows works only for Python-3.8, whereas pickle5 works only for 3.6 and 3.7\"\n            )\n\n\nif __name__ == \"__main__\":\n\n    # parse the cli arguments here\n    parser = argparse.ArgumentParser(description=\"Inference Loop of GANDLF\")\n    parser.add_argument(\n        \"-inference_loader_pickle\",\n        type=str,\n        help=\"Inference loader pickle\",\n        required=True,\n    )\n    parser.add_argument(\n        \"-parameter_pickle\", type=str, help=\"Parameters pickle\", required=True\n    )\n    parser.add_argument(\n        \"-headers_pickle\", type=str, help=\"Header pickle\", required=True\n    )\n    parser.add_argument(\"-outputDir\", type=str, help=\"Output directory\", required=True)\n    parser.add_argument(\"-device\", type=str, help=\"Device to train on\", required=True)\n\n    args = parser.parse_args()\n\n    # # write parameters to pickle - this should not change for the different folds, so keeping is independent\n    patch_size = pickle.load(open(args.patch_size_pickle, \"rb\"))\n    headers = pickle.load(open(args.headers_pickle, \"rb\"))\n    label_header = pickle.load(open(args.label_header_pickle, \"rb\"))\n    parameters = pickle.load(open(args.parameter_pickle, \"rb\"))\n    inferenceDataFromPickle = pd.read_pickle(args.inference_loader_pickle)\n\n    inference_loop(\n        inferenceDataFromPickle=inferenceDataFromPickle,\n        parameters=parameters,\n        outputDir=args.outputDir,\n        device=args.device,\n    )\n", "path": "GANDLF/compute/inference_loop.py"}]}