Repository: nilearn/nilearn

Issue:
Add globbing to nilearn._utils.niimg_conversions._iter_check_niimg
We should add globbing to nilearn._utils.niimg_conversions._iter_check_niimg

We should also add a specific error message to this function when the list is empty raising a valueerror saying explicitly that an empty list was given.



Discussion:
Cc @aabadie 

I'll have a look (sorry I missed it)

Looking at the code  `_iter_check_niimg` internally calls `check_niimg`. If no file is found when consuming the generator, a ValueError is raised by `check_niimg`.


Resolving patch:
diff --git a/nilearn/_utils/niimg_conversions.py b/nilearn/_utils/niimg_conversions.py
--- a/nilearn/_utils/niimg_conversions.py
+++ b/nilearn/_utils/niimg_conversions.py
@@ -102,12 +102,25 @@ def _iter_check_niimg(niimgs, ensure_ndim=None, atleast_4d=False,
         Data type toward which the data should be converted. If "auto", the
         data will be converted to int32 if dtype is discrete and float32 if it
         is continuous.
+
+    See also
+    --------
+        check_niimg, check_niimg_3d, check_niimg_4d
     """
+    # If niimgs is a string, use glob to expand it to the matching filenames.
+    if isinstance(niimgs, _basestring):
+        niimgs_list = glob.glob(os.path.expanduser(niimgs))
+        # Raise an error in case the niimgs list is empty.
+        if len(niimgs_list) == 0:
+            raise ValueError("No files matching path: %s" % niimgs)
+        niimgs = niimgs_list
+
     ref_fov = None
     resample_to_first_img = False
     ndim_minus_one = ensure_ndim - 1 if ensure_ndim is not None else None
     if target_fov is not None and target_fov != "first":
         ref_fov = target_fov
+    i = -1
     for i, niimg in enumerate(niimgs):
         try:
             niimg = check_niimg(
@@ -153,6 +166,10 @@ def _iter_check_niimg(niimgs, ensure_ndim=None, atleast_4d=False,
                          % (i, img_name),) + exc.args)
             raise
 
+    # Raising an error if input generator is empty.
+    if i == -1:
+        raise ValueError("Input niimgs list is empty.")
+
 
 def check_niimg(niimg, ensure_ndim=None, atleast_4d=False, dtype=None,
                 return_iterator=False,
@@ -206,6 +223,10 @@ def check_niimg(niimg, ensure_ndim=None, atleast_4d=False, dtype=None,
     necessary.
 
     Its application is idempotent.
+
+    See also
+    --------
+        _iter_check_niimg, check_niimg_3d, check_niimg_4d
     """
     from ..image import new_img_like  # avoid circular imports
 


Test patch:
diff --git a/nilearn/tests/test_niimg_conversions.py b/nilearn/tests/test_niimg_conversions.py
--- a/nilearn/tests/test_niimg_conversions.py
+++ b/nilearn/tests/test_niimg_conversions.py
@@ -24,6 +24,7 @@
 from nilearn._utils.exceptions import DimensionError
 from nilearn._utils import testing, niimg_conversions
 from nilearn._utils.testing import assert_raises_regex
+from nilearn._utils.niimg_conversions import _iter_check_niimg
 
 
 class PhonyNiimage(nibabel.spatialimages.SpatialImage):
@@ -306,6 +307,40 @@ def test_check_niimg_wildcards():
     ni.EXPAND_PATH_WILDCARDS = True
 
 
+def test_iter_check_niimgs():
+    no_file_matching = "No files matching path: %s"
+    affine = np.eye(4)
+    img_4d = Nifti1Image(np.ones((10, 10, 10, 4)), affine)
+    img_2_4d = [[img_4d, img_4d]]
+
+    for empty in ((), [], (i for i in ()), [i for i in ()]):
+        assert_raises_regex(ValueError,
+                            "Input niimgs list is empty.",
+                            list, _iter_check_niimg(empty))
+
+    nofile_path = "/tmp/nofile"
+    assert_raises_regex(ValueError,
+                        no_file_matching % nofile_path,
+                        list, _iter_check_niimg(nofile_path))
+
+    # Create a test file
+    filename = tempfile.mktemp(prefix="nilearn_test",
+                               suffix=".nii",
+                               dir=None)
+    img_4d.to_filename(filename)
+    niimgs = list(_iter_check_niimg([filename]))
+    assert_array_equal(niimgs[0].get_data(),
+                       _utils.check_niimg(img_4d).get_data())
+    del img_4d
+    del niimgs
+    os.remove(filename)
+
+    # Regular case
+    niimgs = list(_iter_check_niimg(img_2_4d))
+    assert_array_equal(niimgs[0].get_data(),
+                       _utils.check_niimg(img_2_4d).get_data())
+
+
 def test_repr_niimgs():
     # Test with file path
     assert_equal(_utils._repr_niimgs("test"), "test")