Repository: DeepRegNet/DeepReg

Issue:
Wrong message when labels and images names do not match
# Issue description

If the names of the images and the labels do not match (e.g., image0001.nii.gz and label0001.nii.gz) the following Tensorflow error is raised:

"WARNING:tensorflow:Your input ran out of data; interrupting training. Make sure that your dataset or generator can generate at least `steps_per_epoch * epochs` batches (in this case, 2 batches)."

This is very confusing as one would think that the problem is with the quantity of images instead of the file names.

Could a better error message be shown to point to the documentation?


## Type of Issue

Please delete options that are not relevant.

- [ ] Bug report
- [X] New feature request
- [ ] Documentation update
- [ ] Test request
- [ ] Linting request

#### For bug report or feature request, steps to reproduce the issue, including (but not limited to):

1. OS
2. Environment to reproduce
3. What commands run / sample script used:

#### What's the expected result?

Could a better error message be shown to point to the documentation?

#### What's the actual result?

"WARNING:tensorflow:Your input ran out of data; interrupting training. Make sure that your dataset or generator can generate at least `steps_per_epoch * epochs` batches (in this case, 2 batches)."

#### Additional details / screenshot

## -


Discussion:

Patch:
diff --git a/deepreg/dataset/loader/grouped_loader.py b/deepreg/dataset/loader/grouped_loader.py
index a8c8eb87..2b08f2c6 100644
--- a/deepreg/dataset/loader/grouped_loader.py
+++ b/deepreg/dataset/loader/grouped_loader.py
@@ -116,7 +116,11 @@ class GroupedDataLoader(AbstractUnpairedDataLoader, GeneratorDataLoader):
         if self.labeled is True:
             image_ids = self.loader_moving_image.get_data_ids()
             label_ids = self.loader_moving_label.get_data_ids()
-            check_difference_between_two_lists(list1=image_ids, list2=label_ids)
+            check_difference_between_two_lists(
+                list1=image_ids,
+                list2=label_ids,
+                name="images and labels in grouped loader",
+            )
 
     def get_intra_sample_indices(self) -> list:
         """
diff --git a/deepreg/dataset/loader/paired_loader.py b/deepreg/dataset/loader/paired_loader.py
index 3346c80a..3c042fa5 100644
--- a/deepreg/dataset/loader/paired_loader.py
+++ b/deepreg/dataset/loader/paired_loader.py
@@ -80,16 +80,22 @@ class PairedDataLoader(AbstractPairedDataLoader, GeneratorDataLoader):
         moving_image_ids = self.loader_moving_image.get_data_ids()
         fixed_image_ids = self.loader_fixed_image.get_data_ids()
         check_difference_between_two_lists(
-            list1=moving_image_ids, list2=fixed_image_ids
+            list1=moving_image_ids,
+            list2=fixed_image_ids,
+            name="moving and fixed images in paired loader",
         )
         if self.labeled:
             moving_label_ids = self.loader_moving_label.get_data_ids()
             fixed_label_ids = self.loader_fixed_label.get_data_ids()
             check_difference_between_two_lists(
-                list1=moving_image_ids, list2=moving_label_ids
+                list1=moving_image_ids,
+                list2=moving_label_ids,
+                name="moving images and labels in paired loader",
             )
             check_difference_between_two_lists(
-                list1=moving_image_ids, list2=fixed_label_ids
+                list1=moving_image_ids,
+                list2=fixed_label_ids,
+                name="fixed images and labels in paired loader",
             )
 
     def sample_index_generator(self):
diff --git a/deepreg/dataset/loader/unpaired_loader.py b/deepreg/dataset/loader/unpaired_loader.py
index bcf8611f..1077193e 100644
--- a/deepreg/dataset/loader/unpaired_loader.py
+++ b/deepreg/dataset/loader/unpaired_loader.py
@@ -73,7 +73,11 @@ class UnpairedDataLoader(AbstractUnpairedDataLoader, GeneratorDataLoader):
         if self.labeled:
             image_ids = self.loader_moving_image.get_data_ids()
             label_ids = self.loader_moving_label.get_data_ids()
-            check_difference_between_two_lists(list1=image_ids, list2=label_ids)
+            check_difference_between_two_lists(
+                list1=image_ids,
+                list2=label_ids,
+                name="images and labels in unpaired loader",
+            )
 
     def sample_index_generator(self):
         """
diff --git a/deepreg/dataset/util.py b/deepreg/dataset/util.py
index c26ed43a..256fff84 100644
--- a/deepreg/dataset/util.py
+++ b/deepreg/dataset/util.py
@@ -3,6 +3,7 @@ Module for IO of files in relation to
 data loading.
 """
 import glob
+import itertools as it
 import os
 import random
 
@@ -44,22 +45,18 @@ def get_sorted_file_paths_in_dir_with_suffix(dir_path: str, suffix: (str, list))
     return sorted(paths)
 
 
-def check_difference_between_two_lists(list1: list, list2: list):
+def check_difference_between_two_lists(list1: list, list2: list, name: str):
     """
     Raise error if two lists are not identical
+
     :param list1: list
     :param list2: list
-    :return: error message if lists are not equal
+    :param name: name to be printed in case of difference
+    :raises ValueError: error showing different pairs of items
     """
-
-    list1_unique = sorted(set(list1) - set(list2))
-    list2_unique = sorted(set(list2) - set(list1))
-    if len(list2_unique) != 0 or len(list1_unique) != 0:
-        raise ValueError(
-            "two lists are not identical\n"
-            "list1 has unique elements {}\n"
-            "list2 has unique elements {}\n".format(list1_unique, list2_unique)
-        )
+    diff = [(x, y) for x, y in it.zip_longest(list1, list2) if x != y]
+    if len(diff) > 0:
+        raise ValueError(f"{name} are not identical\n" f"difference are {diff}\n")
 
 
 def get_label_indices(num_labels: int, sample_label: str) -> list:


Test patch:
diff --git a/test/unit/test_dataset_util.py b/test/unit/test_dataset_util.py
index 58d76885..470c5e7f 100644
--- a/test/unit/test_dataset_util.py
+++ b/test/unit/test_dataset_util.py
@@ -114,29 +114,34 @@ def test_get_sorted_file_paths_in_dir_with_suffix():
         assert expected == actual
 
 
-def test_difference_lists_same():
+def test_check_difference_between_two_lists():
     """
-    Check ValueError not raised if lists same
+    Check check_difference_between_two_lists by verifying ValueError
     """
-    list_1 = list_2 = [0, 1, 2]
-    util.check_difference_between_two_lists(list_1, list_2)
+    # same lists, no error
+    list1 = list2 = [0, 1, 2]
+    util.check_difference_between_two_lists(list1, list2, name="same case")
 
+    # diff lists with same unique numbers
+    list_1 = [0, 1, 2]
+    list_2 = [1, 2, 0]
+    with pytest.raises(ValueError) as err_info:
+        util.check_difference_between_two_lists(list_1, list_2, name="diff case")
+    assert "diff case are not identical" in str(err_info.value)
 
-def test_difference_lists_different():
-    """
-    Assert ValueError raised if two lists not identical
-    """
+    # totally diff lists
     list_1 = [0, 1, 2]
     list_2 = [3, 4, 5]
-    with pytest.raises(ValueError):
-        util.check_difference_between_two_lists(list_1, list_2)
+    with pytest.raises(ValueError) as err_info:
+        util.check_difference_between_two_lists(list_1, list_2, name="diff case")
+    assert "diff case are not identical" in str(err_info.value)
 
 
 def test_label_indices_sample():
     """
     Assert random number for passed arg returned
     """
-    expected = set([0, 1, 2, 3])
+    expected = {0, 1, 2, 3}
     actual = util.get_label_indices(4, "sample")
     assert expected.intersection(set(actual))