Repository: mlcommons/GaNDLF

Issue:
Add histology exception tests
**Is your feature request related to a problem? Please describe.**
Currently, the histology inference pipeline contains a lot of exceptions, but they aren't being tested.

**Describe the solution you'd like**
See title.

**Describe alternatives you've considered**
N.A.

**Additional context**
N.A.



Discussion:

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -67,7 +67,7 @@ def run(self):
     "tiffslide",
     "matplotlib",
     "requests>=2.25.0",
-    "pyvips",
+    "pyvips==2.2.1",
     "pytest",
     "coverage",
     "pytest-cov",


Test patch:
diff --git a/testing/test_full.py b/testing/test_full.py
--- a/testing/test_full.py
+++ b/testing/test_full.py
@@ -5,6 +5,7 @@
 import pandas as pd
 
 from pydicom.data import get_testdata_file
+import pyvips as pv
 
 from GANDLF.data.ImagesFromDataFrame import ImagesFromDataFrame
 from GANDLF.utils import *
@@ -1737,8 +1738,125 @@ def test_train_inference_segmentation_histology_2d(device):
     print("passed")
 
 
+def test_train_inference_classification_histology_large_2d(device):
+    print(
+        "35: Starting histology train/inference classification tests for large images to check exception handling"
+    )
+    # overwrite previous results
+    sanitize_outputDir()
+    output_dir_patches = os.path.join(outputDir, "histo_patches")
+    if os.path.isdir(output_dir_patches):
+        shutil.rmtree(output_dir_patches)
+    Path(output_dir_patches).mkdir(parents=True, exist_ok=True)
+    output_dir_patches_output = os.path.join(output_dir_patches, "histo_patches_output")
+    Path(output_dir_patches_output).mkdir(parents=True, exist_ok=True)
+    file_config_temp = os.path.join(
+        output_dir_patches, "config_patch-extraction_temp.yaml"
+    )
+    # if found in previous run, discard.
+    if os.path.exists(file_config_temp):
+        os.remove(file_config_temp)
+
+    parameters_patch = {}
+    # extracting minimal number of patches to ensure that the test does not take too long
+    parameters_patch["num_patches"] = 3
+    parameters_patch["patch_size"] = [128, 128]
+
+    with open(file_config_temp, "w") as file:
+        yaml.dump(parameters_patch, file)
+
+    # resize the image
+    input_df = pd.read_csv(inputDir + "/train_2d_histo_classification.csv")
+    for _, row in input_df.iterrows():
+        img = pv.Image.new_from_file(row["Channel_0"])
+        img_resize = img.resize(10)
+        new_filename = row["Channel_0"].replace(".tiff", "_resize.tiff")
+        row["Channel_0"] = new_filename
+        img_resize.tiffsave(new_filename)
+
+    input_df.to_csv(inputDir + "/train_2d_histo_classification_resize.csv", index=False)
+
+    patch_extraction(
+        inputDir + "/train_2d_histo_classification_resize.csv",
+        output_dir_patches_output,
+        file_config_temp,
+    )
+
+    file_for_Training = os.path.join(output_dir_patches_output, "opm_train.csv")
+    temp_df = pd.read_csv(file_for_Training)
+    temp_df.drop("Label", axis=1, inplace=True)
+    temp_df["valuetopredict"] = np.random.randint(2, size=6)
+    temp_df.to_csv(file_for_Training, index=False)
+    # read and parse csv
+    parameters = parseConfig(
+        testingDir + "/config_classification.yaml", version_check_flag=False
+    )
+    parameters["modality"] = "histo"
+    parameters["patch_size"] = 128
+    file_config_temp = os.path.join(outputDir, "config_classification_temp.yaml")
+    with open(file_config_temp, "w") as file:
+        yaml.dump(parameters, file)
+    parameters = parseConfig(file_config_temp, version_check_flag=False)
+    parameters["model"]["dimension"] = 2
+    # read and parse csv
+    training_data, parameters["headers"] = parseTrainingCSV(file_for_Training)
+    parameters["model"]["num_channels"] = 3
+    parameters["model"]["architecture"] = "densenet121"
+    parameters["model"]["norm_type"] = "none"
+    parameters["data_preprocessing"]["rgba2rgb"] = ""
+    parameters = populate_header_in_parameters(parameters, parameters["headers"])
+    parameters["nested_training"]["testing"] = 1
+    parameters["nested_training"]["validation"] = -2
+    parameters["model"]["print_summary"] = False
+    modelDir = os.path.join(outputDir, "modelDir")
+    if os.path.isdir(modelDir):
+        shutil.rmtree(modelDir)
+    Path(modelDir).mkdir(parents=True, exist_ok=True)
+    TrainingManager(
+        dataframe=training_data,
+        outputDir=modelDir,
+        parameters=parameters,
+        device=device,
+        resume=False,
+        reset=True,
+    )
+    parameters["output_dir"] = modelDir  # this is in inference mode
+    # drop last subject
+    input_df.drop(index=input_df.index[-1], axis=0, inplace=True)
+    input_df.to_csv(inputDir + "/train_2d_histo_classification_resize.csv", index=False)
+    inference_data, parameters["headers"] = parseTrainingCSV(
+        inputDir + "/train_2d_histo_classification_resize.csv", train=False
+    )
+    with pytest.raises(Exception) as exc_info:
+        for model_type in all_model_type:
+            parameters["nested_training"]["testing"] = 1
+            parameters["nested_training"]["validation"] = -2
+            parameters["output_dir"] = modelDir  # this is in inference mode
+            inference_data, parameters["headers"] = parseTrainingCSV(
+                inputDir + "/train_2d_histo_segmentation.csv", train=False
+            )
+            parameters["model"]["type"] = model_type
+            InferenceManager(
+                dataframe=inference_data,
+                outputDir=modelDir,
+                parameters=parameters,
+                device=device,
+            )
+            assert (
+                os.path.exists(
+                    os.path.join(modelDir, input_df["SubjectID"][0], "predictions.csv")
+                )
+                is True
+            )
+
+    exception_raised = exc_info.value
+    print("Exception raised: ", exception_raised)
+
+    print("passed")
+
+
 def test_train_inference_classification_histology_2d(device):
-    print("35: Starting histology train/inference classification tests")
+    print("36: Starting histology train/inference classification tests")
     # overwrite previous results
     sanitize_outputDir()
     output_dir_patches = os.path.join(outputDir, "histo_patches")
@@ -1830,7 +1948,7 @@ def test_train_inference_classification_histology_2d(device):
 
 def test_train_segmentation_unet_layerchange_rad_2d(device):
     # test case to up code coverage --> test decreasing allowed layers for unet
-    print("36: Starting 2D Rad segmentation tests for normtype")
+    print("37: Starting 2D Rad segmentation tests for normtype")
     # read and parse csv
     # read and initialize parameters for specific data dimension
     parameters = parseConfig(
@@ -1877,7 +1995,7 @@ def test_train_segmentation_unet_layerchange_rad_2d(device):
 
 
 def test_train_segmentation_unetr_rad_3d(device):
-    print("37: Testing UNETR for 3D segmentation")
+    print("38: Testing UNETR for 3D segmentation")
     parameters = parseConfig(
         testingDir + "/config_segmentation.yaml", version_check_flag=False
     )
@@ -1933,7 +2051,7 @@ def test_train_segmentation_unetr_rad_3d(device):
 
 
 def test_train_segmentation_unetr_rad_2d(device):
-    print("38: Testing UNETR for 2D segmentation")
+    print("39: Testing UNETR for 2D segmentation")
     parameters = parseConfig(
         testingDir + "/config_segmentation.yaml", version_check_flag=False
     )
@@ -1971,7 +2089,7 @@ def test_train_segmentation_unetr_rad_2d(device):
 
 
 def test_train_segmentation_transunet_rad_2d(device):
-    print("39: Testing TransUNet for 2D segmentation")
+    print("40: Testing TransUNet for 2D segmentation")
     parameters = parseConfig(
         testingDir + "/config_segmentation.yaml", version_check_flag=False
     )
@@ -2020,7 +2138,7 @@ def test_train_segmentation_transunet_rad_2d(device):
 
 
 def test_train_segmentation_transunet_rad_3d(device):
-    print("40: Testing TransUNet for 3D segmentation")
+    print("41: Testing TransUNet for 3D segmentation")
     parameters = parseConfig(
         testingDir + "/config_segmentation.yaml", version_check_flag=False
     )