Repository: nilearn/nilearn

Issue:
Fit method of estimators (decomposers, decoders, etc.) should accept filename wildcards
Since `check_niimg_4d` and co. now do globbing, it should be easy to have estimators accept filename wildcards.

For example, we should allow the following usage:

```
canica.fit("/home/mrbumble/nilearn_data/spm_auditory/sub001/fM00223/fM00223_*.img")
```



Discussion:
> Since check_niimg_4d and co. now do globbing, it should be easy to have
> estimators accept filename wildcards.

Don't they?

Probably not, they différent codepaths for efficiency.

@aabadie, do you want to have a look at that?

Nope.

```
ValueError: [MultiNiftiMasker.fit] For multiple processing, you should provide a list of data (e.g. 

Nifti1Image objects or 
filenames).'/home/elvis/nilearn_data/spm_auditory/sub001/fM00223/fM00223_0*.img' is an invalid 

input
```

Any progress ?

> Any progress ?

Seems like more people are reporting this issue. This item increased by 1 in my todo-list.


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
@@ -75,6 +75,17 @@ def _index_img(img, index):
         copy_header=True)
 
 
+def _resolve_globbing(path):
+    if isinstance(path, _basestring):
+        path_list = sorted(glob.glob(os.path.expanduser(path)))
+        # Raise an error in case the niimgs list is empty.
+        if len(path_list) == 0:
+            raise ValueError("No files matching path: %s" % path)
+        path = path_list
+
+    return path
+
+
 def _iter_check_niimg(niimgs, ensure_ndim=None, atleast_4d=False,
                       target_fov=None, dtype=None,
                       memory=Memory(cachedir=None),
@@ -84,7 +95,7 @@ def _iter_check_niimg(niimgs, ensure_ndim=None, atleast_4d=False,
     Parameters
     ----------
 
-    niimgs: list of niimg
+    niimgs: list of niimg or glob pattern
         Image to iterate over
 
     ensure_ndim: integer, optional
@@ -107,12 +118,7 @@ def _iter_check_niimg(niimgs, ensure_ndim=None, atleast_4d=False,
         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
+    niimgs = _resolve_globbing(niimgs)
 
     ref_fov = None
     resample_to_first_img = False
@@ -366,7 +372,7 @@ def concat_niimgs(niimgs, dtype=np.float32, ensure_ndim=None,
 
     Parameters
     ----------
-    niimgs: iterable of Niimg-like objects
+    niimgs: iterable of Niimg-like objects or glob pattern
         See http://nilearn.github.io/manipulating_images/manipulating_images.html#niimg.
         Niimgs to concatenate.
 
@@ -411,6 +417,9 @@ def concat_niimgs(niimgs, dtype=np.float32, ensure_ndim=None,
     if ensure_ndim is not None:
         ndim = ensure_ndim - 1
 
+    # If niimgs is a string, use glob to expand it to the matching filenames.
+    niimgs = _resolve_globbing(niimgs)
+
     # First niimg is extracted to get information and for new_img_like
     first_niimg = None
 


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
@@ -434,12 +434,13 @@ def test_concat_niimgs():
                         auto_resample=False)
 
     # test list of 4D niimgs as input
-    tmpimg1 = tempfile.mktemp(suffix='.nii')
-    tmpimg2 = tempfile.mktemp(suffix='.nii')
+    tempdir = tempfile.mkdtemp()
+    tmpimg1 = os.path.join(tempdir, '1.nii')
+    tmpimg2 = os.path.join(tempdir, '2.nii')
     try:
         nibabel.save(img1, tmpimg1)
         nibabel.save(img3, tmpimg2)
-        concatenated = _utils.concat_niimgs([tmpimg1, tmpimg2])
+        concatenated = _utils.concat_niimgs(os.path.join(tempdir, '*'))
         assert_array_equal(
             concatenated.get_data()[..., 0], img1.get_data())
         assert_array_equal(
@@ -447,6 +448,8 @@ def test_concat_niimgs():
     finally:
         _remove_if_exists(tmpimg1)
         _remove_if_exists(tmpimg2)
+        if os.path.exists(tempdir):
+            os.removedirs(tempdir)
 
     img5d = Nifti1Image(np.ones((2, 2, 2, 2, 2)), affine)
     assert_raises_regex(TypeError, 'Concatenated images must be 3D or 4D. '