Repository: nilearn/nilearn

Issue:
Refactor nifti masker code
Since we are at it, how about refactoring all the nifti masker classes into a single python file?

More concretely, how about unifying the code of...

``` python
- base_masker.py
- nifti_masker.py
- nifti_region.py
- multi_nifti_masker.py
```



Discussion:
I tend to like the organization where there is one major class per file,
and the file name is the snake_case version of the CamelCase class name.

> I tend to like the organization where there is one major class per file, and the file name is the snake_case version of the CamelCase class name.

So should we split nifti_region into nifti_labels_masker and nifti_maps_masker?

> split nifti_region into nifti_labels_masker and nifti_maps_masker

This seems to make sense for the sake of consistency.

> So should we split nifti_region into nifti_labels_masker and
> nifti_maps_masker?

IMHO Yes. I find that such organization of the codebase makes it very
easy to find where a class is defined.

@banilo, do you volunteer? ;)

If not, I'll find 10 minutes to do that during the week end. Given that we have released, I think that this kind of change should be done ASAP.

I volunteer - will do it this afternoon.


Resolving patch:
diff --git a/nilearn/input_data/__init__.py b/nilearn/input_data/__init__.py
--- a/nilearn/input_data/__init__.py
+++ b/nilearn/input_data/__init__.py
@@ -4,4 +4,5 @@
 """
 from .nifti_masker import NiftiMasker
 from .multi_nifti_masker import MultiNiftiMasker
-from .nifti_region import NiftiLabelsMasker, NiftiMapsMasker
+from .nifti_labels_masker import NiftiLabelsMasker
+from .nifti_maps_masker import NiftiMapsMasker
diff --git a/nilearn/input_data/nifti_labels_masker.py b/nilearn/input_data/nifti_labels_masker.py
new file mode 100644
--- /dev/null
+++ b/nilearn/input_data/nifti_labels_masker.py
@@ -0,0 +1,303 @@
+"""
+Transformer for computing ROI signals.
+"""
+
+import numpy as np
+
+from sklearn.base import BaseEstimator, TransformerMixin
+from sklearn.externals.joblib import Memory
+
+import nibabel
+
+from .. import _utils
+from .._utils import logger
+from .._utils import CacheMixin
+from .._utils.niimg_conversions import _check_same_fov
+from .. import signal
+from .. import region
+from .. import masking
+from .. import image
+
+
+def _compose_err_msg(msg, **kwargs):
+    """Append key-value pairs to msg, for display.
+
+    Parameters
+    ==========
+    msg: string
+        arbitrary message
+    kwargs: dict
+        arbitrary dictionary
+
+    Returns
+    =======
+    updated_msg: string
+        msg, with "key: value" appended. Only string values are appended.
+    """
+    updated_msg = msg
+    for k, v in kwargs.iteritems():
+        if isinstance(v, basestring):
+            updated_msg += "\n" + k + ": " + v
+
+    return updated_msg
+
+
+class NiftiLabelsMasker(BaseEstimator, TransformerMixin, CacheMixin):
+    """Class for masking of Niimg-like objects.
+
+    NiftiLabelsMasker is useful when data from non-overlapping volumes should
+    be extracted (contrarily to NiftiMapsMasker). Use case: Summarize brain
+    signals from clusters that were obtained by prior K-means or Ward
+    clustering.
+
+    Parameters
+    ==========
+    labels_img: Niimg-like object
+        See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg.
+        Region definitions, as one image of labels.
+
+    background_label: number, optional
+        Label used in labels_img to represent background.
+
+    mask_img: Niimg-like object, optional
+        See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg.
+        Mask to apply to regions before extracting signals.
+
+    smoothing_fwhm: float, optional
+        If smoothing_fwhm is not None, it gives the full-width half maximum in
+        millimeters of the spatial smoothing to apply to the signal.
+
+    standardize: boolean, optional
+        If standardize is True, the time-series are centered and normed:
+        their mean is put to 0 and their variance to 1 in the time dimension.
+
+    detrend: boolean, optional
+        This parameter is passed to signal.clean. Please see the related
+        documentation for details
+
+    low_pass: False or float, optional
+        This parameter is passed to signal.clean. Please see the related
+        documentation for details
+
+    high_pass: False or float, optional
+        This parameter is passed to signal.clean. Please see the related
+        documentation for details
+
+    t_r: float, optional
+        This parameter is passed to signal.clean. Please see the related
+        documentation for details
+
+    resampling_target: {"data", "labels", None}, optional.
+        Gives which image gives the final shape/size. For example, if
+        `resampling_target` is "data", the atlas is resampled to the
+        shape of the data if needed. If it is "labels" then mask_img
+        and images provided to fit() are resampled to the shape and
+        affine of maps_img. "None" means no resampling: if shapes and
+        affines do not match, a ValueError is raised. Defaults to "data".
+
+    memory: joblib.Memory or str, optional
+        Used to cache the region extraction process.
+        By default, no caching is done. If a string is given, it is the
+        path to the caching directory.
+
+    memory_level: int, optional
+        Aggressiveness of memory caching. The higher the number, the higher
+        the number of functions that will be cached. Zero means no caching.
+
+    verbose: integer, optional
+        Indicate the level of verbosity. By default, nothing is printed
+
+    See also
+    ========
+    nilearn.input_data.NiftiMasker
+    """
+    # memory and memory_level are used by CacheMixin.
+
+    def __init__(self, labels_img, background_label=0, mask_img=None,
+                 smoothing_fwhm=None, standardize=False, detrend=False,
+                 low_pass=None, high_pass=None, t_r=None,
+                 resampling_target="data",
+                 memory=Memory(cachedir=None, verbose=0), memory_level=1,
+                 verbose=0):
+        self.labels_img = labels_img
+        self.background_label = background_label
+        self.mask_img = mask_img
+
+        # Parameters for _smooth_array
+        self.smoothing_fwhm = smoothing_fwhm
+
+        # Parameters for clean()
+        self.standardize = standardize
+        self.detrend = detrend
+        self.low_pass = low_pass
+        self.high_pass = high_pass
+        self.t_r = t_r
+
+        # Parameters for resampling
+        self.resampling_target = resampling_target
+
+        # Parameters for joblib
+        self.memory = memory
+        self.memory_level = memory_level
+        self.verbose = verbose
+
+        if resampling_target not in ("labels", "data", None):
+            raise ValueError("invalid value for 'resampling_target' "
+                             "parameter: " + str(resampling_target))
+
+    def fit(self, X=None, y=None):
+        """Prepare signal extraction from regions.
+
+        All parameters are unused, they are for scikit-learn compatibility.
+        """
+        logger.log("loading data from %s" %
+                   _utils._repr_niimgs(self.labels_img)[:200],
+                   verbose=self.verbose)
+        self.labels_img_ = _utils.check_niimg(self.labels_img)
+        if self.mask_img is not None:
+            logger.log("loading data from %s" %
+                       _utils._repr_niimgs(self.mask_img)[:200],
+                       verbose=self.verbose)
+            self.mask_img_ = _utils.check_niimg(self.mask_img, ensure_3d=True)
+        else:
+            self.mask_img_ = None
+
+        # Check shapes and affines or resample.
+        if self.mask_img_ is not None:
+            if self.resampling_target == "data":
+                # resampling will be done at transform time
+                pass
+            elif self.resampling_target is None:
+                if _utils._get_shape(self.mask_img_) \
+                        != _utils._get_shape(self.labels_img_)[:3]:
+                    raise ValueError(
+                        _compose_err_msg(
+                            "Regions and mask do not have the same shape",
+                            mask_img=self.mask_img,
+                            labels_img=self.labels_img))
+                if not np.allclose(self.mask_img_.get_affine(),
+                                   self.labels_img_.get_affine()):
+                    raise ValueError(_compose_err_msg(
+                        "Regions and mask do not have the same affine.",
+                        mask_img=self.mask_img, labels_img=self.labels_img))
+
+            elif self.resampling_target == "labels":
+                logger.log("resampling the mask", verbose=self.verbose)
+                self.mask_img_ = image.resample_img(
+                    self.mask_img_,
+                    target_affine=self.labels_img_.get_affine(),
+                    target_shape=_utils._get_shape(
+                                                self.labels_img_)[:3],
+                    interpolation="nearest",
+                    copy=True)
+            else:
+                raise ValueError("Invalid value for resampling_target: "
+                                 + str(self.resampling_target))
+
+            mask_data, mask_affine = masking._load_mask_img(self.mask_img_)
+
+        return self
+
+    def fit_transform(self, imgs, confounds=None):
+        return self.fit().transform(imgs, confounds=confounds)
+
+    def _check_fitted(self):
+        if not hasattr(self, "labels_img_"):
+            raise ValueError('It seems that %s has not been fitted. '
+                             'You must call fit() before calling transform().'
+                             % self.__class__.__name__)
+
+    def transform(self, imgs, confounds=None):
+        """Extract signals from images.
+
+        Parameters
+        ==========
+        imgs: Niimg-like object
+            See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg.
+            Images to process. It must boil down to a 4D image with scans
+            number as last dimension.
+
+        confounds: array-like, optional
+            This parameter is passed to signal.clean. Please see the related
+            documentation for details.
+            shape: (number of scans, number of confounds)
+
+        Returns
+        =======
+        signals: 2D numpy.ndarray
+            Signal for each region.
+            shape: (number of scans, number of regions)
+
+        """
+        self._check_fitted()
+
+        logger.log("loading images: %s" %
+                   _utils._repr_niimgs(imgs)[:200], verbose=self.verbose)
+        imgs = _utils.check_niimgs(imgs)
+
+        if self.resampling_target == "data":
+            if not hasattr(self, '_resampled_labels_img_'):
+                self._resampled_labels_img_ = self.labels_img_
+            if not _check_same_fov(imgs, self._resampled_labels_img_):
+                logger.log("resampling labels", verbose=self.verbose)
+                self._resampled_labels_img_ = self._cache(image.resample_img,
+                    func_memory_level=1)(
+                        self.labels_img_, interpolation="nearest",
+                        target_shape=_utils._get_shape(imgs)[:3],
+                        target_affine=imgs.get_affine(),
+                    )
+        elif self.resampling_target == "labels":
+            self._resampled_labels_img_ = self.labels_img_
+            logger.log("resampling images", verbose=self.verbose)
+            imgs = self._cache(image.resample_img, func_memory_level=1)(
+                imgs, interpolation="continuous",
+                target_shape=_utils._get_shape(self.labels_img_),
+                target_affine=self.labels_img_.get_affine())
+        else:
+            self._resampled_labels_img_ = self.labels_img_
+
+        if self.smoothing_fwhm is not None:
+            logger.log("smoothing images", verbose=self.verbose)
+            imgs = self._cache(image.smooth_img, func_memory_level=1)(
+                imgs, fwhm=self.smoothing_fwhm)
+
+        logger.log("extracting region signals", verbose=self.verbose)
+        region_signals, self.labels_ = self._cache(
+            region.img_to_signals_labels, func_memory_level=1)(
+                imgs, self._resampled_labels_img_,
+                background_label=self.background_label)
+
+        logger.log("cleaning extracted signals", verbose=self.verbose)
+        region_signals = self._cache(signal.clean, func_memory_level=1
+                                     )(region_signals,
+                                       detrend=self.detrend,
+                                       standardize=self.standardize,
+                                       t_r=self.t_r,
+                                       low_pass=self.low_pass,
+                                       high_pass=self.high_pass,
+                                       confounds=confounds)
+        return region_signals
+
+    def inverse_transform(self, signals):
+        """Compute voxel signals from region signals
+
+        Any mask given at initialization is taken into account.
+
+        Parameters
+        ==========
+        signals (2D numpy.ndarray)
+            Signal for each region.
+            shape: (number of scans, number of regions)
+
+        Returns
+        =======
+        voxel_signals (Nifti1Image)
+            Signal for each voxel
+            shape: (number of scans, number of voxels)
+        """
+        self._check_fitted()
+
+        logger.log("computing image from signals", verbose=self.verbose)
+        return region.signals_to_img_labels(
+            signals, self.labels_img_, self.mask_img_,
+            background_label=self.background_label)
diff --git a/nilearn/input_data/nifti_region.py b/nilearn/input_data/nifti_maps_masker.py
similarity index 55%
rename from nilearn/input_data/nifti_region.py
rename to nilearn/input_data/nifti_maps_masker.py
--- a/nilearn/input_data/nifti_region.py
+++ b/nilearn/input_data/nifti_maps_masker.py
@@ -15,7 +15,6 @@
 from .._utils.niimg_conversions import _check_same_fov
 from .. import signal
 from .. import region
-from .. import masking
 from .. import image
 
 
@@ -42,270 +41,9 @@ def _compose_err_msg(msg, **kwargs):
     return updated_msg
 
 
-class NiftiLabelsMasker(BaseEstimator, TransformerMixin, CacheMixin):
-    """Class for masking of Niimg-like objects.
-    
-    NiftiLabelsMasker is useful when data from non-overlapping volumes should
-    be extracted (contrarily to NiftiMapsMasker). Use case: Summarize brain
-    signals from clusters that were obtained by prior K-means or Ward
-    clustering.
-
-    Parameters
-    ==========
-    labels_img: Niimg-like object
-        See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg.
-        Region definitions, as one image of labels.
-
-    background_label: number, optional
-        Label used in labels_img to represent background.
-
-    mask_img: Niimg-like object, optional
-        See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg.
-        Mask to apply to regions before extracting signals.
-
-    smoothing_fwhm: float, optional
-        If smoothing_fwhm is not None, it gives the full-width half maximum in
-        millimeters of the spatial smoothing to apply to the signal.
-
-    standardize: boolean, optional
-        If standardize is True, the time-series are centered and normed:
-        their mean is put to 0 and their variance to 1 in the time dimension.
-
-    detrend: boolean, optional
-        This parameter is passed to signal.clean. Please see the related
-        documentation for details
-
-    low_pass: False or float, optional
-        This parameter is passed to signal.clean. Please see the related
-        documentation for details
-
-    high_pass: False or float, optional
-        This parameter is passed to signal.clean. Please see the related
-        documentation for details
-
-    t_r: float, optional
-        This parameter is passed to signal.clean. Please see the related
-        documentation for details
-
-    resampling_target: {"data", "labels", None}, optional.
-        Gives which image gives the final shape/size. For example, if
-        `resampling_target` is "data", the atlas is resampled to the
-        shape of the data if needed. If it is "labels" then mask_img
-        and images provided to fit() are resampled to the shape and
-        affine of maps_img. "None" means no resampling: if shapes and
-        affines do not match, a ValueError is raised. Defaults to "data".
-
-    memory: joblib.Memory or str, optional
-        Used to cache the region extraction process.
-        By default, no caching is done. If a string is given, it is the
-        path to the caching directory.
-
-    memory_level: int, optional
-        Aggressiveness of memory caching. The higher the number, the higher
-        the number of functions that will be cached. Zero means no caching.
-
-    verbose: integer, optional
-        Indicate the level of verbosity. By default, nothing is printed
-
-    See also
-    ========
-    nilearn.input_data.NiftiMasker
-    """
-    # memory and memory_level are used by CacheMixin.
-
-    def __init__(self, labels_img, background_label=0, mask_img=None,
-                 smoothing_fwhm=None, standardize=False, detrend=False,
-                 low_pass=None, high_pass=None, t_r=None,
-                 resampling_target="data",
-                 memory=Memory(cachedir=None, verbose=0), memory_level=1,
-                 verbose=0):
-        self.labels_img = labels_img
-        self.background_label = background_label
-        self.mask_img = mask_img
-
-        # Parameters for _smooth_array
-        self.smoothing_fwhm = smoothing_fwhm
-
-        # Parameters for clean()
-        self.standardize = standardize
-        self.detrend = detrend
-        self.low_pass = low_pass
-        self.high_pass = high_pass
-        self.t_r = t_r
-
-        # Parameters for resampling
-        self.resampling_target = resampling_target
-
-        # Parameters for joblib
-        self.memory = memory
-        self.memory_level = memory_level
-        self.verbose = verbose
-
-        if resampling_target not in ("labels", "data", None):
-            raise ValueError("invalid value for 'resampling_target' "
-                             "parameter: " + str(resampling_target))
-
-    def fit(self, X=None, y=None):
-        """Prepare signal extraction from regions.
-
-        All parameters are unused, they are for scikit-learn compatibility.
-        """
-        logger.log("loading data from %s" %
-                   _utils._repr_niimgs(self.labels_img)[:200],
-                   verbose=self.verbose)
-        self.labels_img_ = _utils.check_niimg(self.labels_img)
-        if self.mask_img is not None:
-            logger.log("loading data from %s" %
-                       _utils._repr_niimgs(self.mask_img)[:200],
-                       verbose=self.verbose)
-            self.mask_img_ = _utils.check_niimg(self.mask_img, ensure_3d=True)
-        else:
-            self.mask_img_ = None
-
-        # Check shapes and affines or resample.
-        if self.mask_img_ is not None:
-            if self.resampling_target == "data":
-                # resampling will be done at transform time
-                pass
-            elif self.resampling_target is None:
-                if _utils._get_shape(self.mask_img_) \
-                        != _utils._get_shape(self.labels_img_)[:3]:
-                    raise ValueError(
-                        _compose_err_msg(
-                            "Regions and mask do not have the same shape",
-                            mask_img=self.mask_img,
-                            labels_img=self.labels_img))
-                if not np.allclose(self.mask_img_.get_affine(),
-                                   self.labels_img_.get_affine()):
-                    raise ValueError(_compose_err_msg(
-                        "Regions and mask do not have the same affine.",
-                        mask_img=self.mask_img, labels_img=self.labels_img))
-
-            elif self.resampling_target == "labels":
-                logger.log("resampling the mask", verbose=self.verbose)
-                self.mask_img_ = image.resample_img(
-                    self.mask_img_,
-                    target_affine=self.labels_img_.get_affine(),
-                    target_shape=_utils._get_shape(
-                                                self.labels_img_)[:3],
-                    interpolation="nearest",
-                    copy=True)
-            else:
-                raise ValueError("Invalid value for resampling_target: "
-                                 + str(self.resampling_target))
-
-            mask_data, mask_affine = masking._load_mask_img(self.mask_img_)
-
-        return self
-
-    def fit_transform(self, imgs, confounds=None):
-        return self.fit().transform(imgs, confounds=confounds)
-
-    def _check_fitted(self):
-        if not hasattr(self, "labels_img_"):
-            raise ValueError('It seems that %s has not been fitted. '
-                             'You must call fit() before calling transform().'
-                             % self.__class__.__name__)
-
-    def transform(self, imgs, confounds=None):
-        """Extract signals from images.
-
-        Parameters
-        ==========
-        imgs: Niimg-like object
-            See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg.
-            Images to process. It must boil down to a 4D image with scans
-            number as last dimension.
-
-        confounds: array-like, optional
-            This parameter is passed to signal.clean. Please see the related
-            documentation for details.
-            shape: (number of scans, number of confounds)
-
-        Returns
-        =======
-        signals: 2D numpy.ndarray
-            Signal for each region.
-            shape: (number of scans, number of regions)
-
-        """
-        self._check_fitted()
-
-        logger.log("loading images: %s" %
-                   _utils._repr_niimgs(imgs)[:200], verbose=self.verbose)
-        imgs = _utils.check_niimgs(imgs)
-
-        if self.resampling_target == "data":
-            if not hasattr(self, '_resampled_labels_img_'):
-                self._resampled_labels_img_ = self.labels_img_
-            if not _check_same_fov(imgs, self._resampled_labels_img_):
-                logger.log("resampling labels", verbose=self.verbose)
-                self._resampled_labels_img_ = self._cache(image.resample_img,
-                    func_memory_level=1)(
-                        self.labels_img_, interpolation="nearest",
-                        target_shape=_utils._get_shape(imgs)[:3],
-                        target_affine=imgs.get_affine(),
-                    )
-        elif self.resampling_target == "labels":
-            self._resampled_labels_img_ = self.labels_img_
-            logger.log("resampling images", verbose=self.verbose)
-            imgs = self._cache(image.resample_img, func_memory_level=1)(
-                imgs, interpolation="continuous",
-                target_shape=_utils._get_shape(self.labels_img_),
-                target_affine=self.labels_img_.get_affine())
-        else:
-            self._resampled_labels_img_ = self.labels_img_
-
-        if self.smoothing_fwhm is not None:
-            logger.log("smoothing images", verbose=self.verbose)
-            imgs = self._cache(image.smooth_img, func_memory_level=1)(
-                imgs, fwhm=self.smoothing_fwhm)
-
-        logger.log("extracting region signals", verbose=self.verbose)
-        region_signals, self.labels_ = self._cache(
-            region.img_to_signals_labels, func_memory_level=1)(
-                imgs, self._resampled_labels_img_,
-                background_label=self.background_label)
-
-        logger.log("cleaning extracted signals", verbose=self.verbose)
-        region_signals = self._cache(signal.clean, func_memory_level=1
-                                     )(region_signals,
-                                       detrend=self.detrend,
-                                       standardize=self.standardize,
-                                       t_r=self.t_r,
-                                       low_pass=self.low_pass,
-                                       high_pass=self.high_pass,
-                                       confounds=confounds)
-        return region_signals
-
-    def inverse_transform(self, signals):
-        """Compute voxel signals from region signals
-
-        Any mask given at initialization is taken into account.
-
-        Parameters
-        ==========
-        signals (2D numpy.ndarray)
-            Signal for each region.
-            shape: (number of scans, number of regions)
-
-        Returns
-        =======
-        voxel_signals (Nifti1Image)
-            Signal for each voxel
-            shape: (number of scans, number of voxels)
-        """
-        self._check_fitted()
-        
-        logger.log("computing image from signals", verbose=self.verbose)
-        return region.signals_to_img_labels(
-            signals, self.labels_img_, self.mask_img_,
-            background_label=self.background_label)
-
-
 class NiftiMapsMasker(BaseEstimator, TransformerMixin, CacheMixin):
     """Class for masking of Niimg-like objects.
-    
+
     NiftiMapsMasker is useful when data from overlapping volumes should be
     extracted (contrarily to NiftiLabelsMasker). Use case: Summarize brain
     signals from large-scale networks obtained by prior PCA or ICA.
@@ -594,7 +332,7 @@ def inverse_transform(self, region_signals):
             Signal for each voxel. shape: that of maps.
         """
         self._check_fitted()
-        
+
         logger.log("computing image from signals", verbose=self.verbose)
         return region.signals_to_img_maps(region_signals, self.maps_img_,
                                           mask_img=self.mask_img_)


Test patch:
diff --git a/nilearn/input_data/tests/test_nifti_labels_masker.py b/nilearn/input_data/tests/test_nifti_labels_masker.py
new file mode 100644
--- /dev/null
+++ b/nilearn/input_data/tests/test_nifti_labels_masker.py
@@ -0,0 +1,216 @@
+"""Test the nifti_region module
+
+Functions in this file only test features added by the NiftiLabelsMasker class,
+not the underlying functions (clean(), img_to_signals_labels(), etc.). See
+test_masking.py and test_signal.py for details.
+"""
+
+from nose.tools import assert_raises, assert_equal, assert_true
+import numpy as np
+
+import nibabel
+
+from nilearn.input_data.nifti_labels_masker import NiftiLabelsMasker
+from nilearn._utils import testing
+from nilearn._utils import as_ndarray
+
+
+def generate_random_img(shape, length=1, affine=np.eye(4),
+                        rand_gen=np.random.RandomState(0)):
+    data = rand_gen.randn(*(shape + (length,)))
+    return nibabel.Nifti1Image(data, affine), nibabel.Nifti1Image(
+                    as_ndarray(data[..., 0] > 0.2, dtype=np.int8), affine)
+
+
+def test_nifti_labels_masker():
+    # Check working of shape/affine checks
+    shape1 = (13, 11, 12)
+    affine1 = np.eye(4)
+
+    shape2 = (12, 10, 14)
+    affine2 = np.diag((1, 2, 3, 1))
+
+    n_regions = 9
+    length = 3
+
+    fmri11_img, mask11_img = generate_random_img(shape1, affine=affine1,
+                                                 length=length)
+    fmri12_img, mask12_img = generate_random_img(shape1, affine=affine2,
+                                                 length=length)
+    fmri21_img, mask21_img = generate_random_img(shape2, affine=affine1,
+                                                 length=length)
+
+    labels11_img = testing.generate_labeled_regions(shape1, affine=affine1,
+                                                    n_regions=n_regions)
+
+    mask_img_4d = nibabel.Nifti1Image(np.ones((2, 2, 2, 2), dtype=np.int8),
+                                      affine=np.diag((4, 4, 4, 1)))
+
+    # verify that 4D mask arguments are refused
+    masker = NiftiLabelsMasker(labels11_img, mask_img=mask_img_4d)
+    testing.assert_raises_regexp(TypeError, "A 3D image is expected",
+                                 masker.fit)
+
+    # check exception when transform() called without prior fit()
+    masker11 = NiftiLabelsMasker(labels11_img, resampling_target=None)
+    testing.assert_raises_regexp(
+        ValueError,
+        'has not been fitted. ', masker11.transform, fmri11_img)
+
+    # No exception raised here
+    signals11 = masker11.fit().transform(fmri11_img)
+    assert_equal(signals11.shape, (length, n_regions))
+
+    masker11 = NiftiLabelsMasker(labels11_img, mask_img=mask11_img,
+                                 resampling_target=None)
+    signals11 = masker11.fit().transform(fmri11_img)
+    assert_equal(signals11.shape, (length, n_regions))
+
+    # Test all kinds of mismatch between shapes and between affines
+    masker11 = NiftiLabelsMasker(labels11_img, resampling_target=None)
+    masker11.fit()
+    assert_raises(ValueError, masker11.transform, fmri12_img)
+    assert_raises(ValueError, masker11.transform, fmri21_img)
+
+    masker11 = NiftiLabelsMasker(labels11_img, mask_img=mask12_img,
+                                 resampling_target=None)
+    assert_raises(ValueError, masker11.fit)
+
+    masker11 = NiftiLabelsMasker(labels11_img, mask_img=mask21_img,
+                                 resampling_target=None)
+    assert_raises(ValueError, masker11.fit)
+
+    # Transform, with smoothing (smoke test)
+    masker11 = NiftiLabelsMasker(labels11_img, smoothing_fwhm=3,
+                                 resampling_target=None)
+    signals11 = masker11.fit().transform(fmri11_img)
+    assert_equal(signals11.shape, (length, n_regions))
+
+    masker11 = NiftiLabelsMasker(labels11_img, smoothing_fwhm=3,
+                                 resampling_target=None)
+    signals11 = masker11.fit_transform(fmri11_img)
+    assert_equal(signals11.shape, (length, n_regions))
+
+    testing.assert_raises_regexp(
+        ValueError, 'has not been fitted. ',
+        NiftiLabelsMasker(labels11_img).inverse_transform, signals11)
+
+    # Call inverse transform (smoke test)
+    fmri11_img_r = masker11.inverse_transform(signals11)
+    assert_equal(fmri11_img_r.shape, fmri11_img.shape)
+    np.testing.assert_almost_equal(fmri11_img_r.get_affine(),
+                                   fmri11_img.get_affine())
+
+
+def test_nifti_labels_masker_resampling():
+    # Test resampling in NiftiLabelsMasker
+    shape1 = (10, 11, 12)
+    affine = np.eye(4)
+
+    # mask
+    shape2 = (16, 17, 18)
+
+    # labels
+    shape3 = (13, 14, 15)
+
+    n_regions = 9
+    length = 3
+
+    # With data of the same affine
+    fmri11_img, _ = generate_random_img(shape1, affine=affine,
+                                                 length=length)
+    _, mask22_img = generate_random_img(shape2, affine=affine,
+                                                 length=length)
+
+    labels33_img = testing.generate_labeled_regions(shape3, n_regions,
+                                                    affine=affine)
+
+    # Test error checking
+    assert_raises(ValueError, NiftiLabelsMasker, labels33_img,
+                  resampling_target="mask")
+    assert_raises(ValueError, NiftiLabelsMasker, labels33_img,
+                  resampling_target="invalid")
+
+    # Target: labels
+    masker = NiftiLabelsMasker(labels33_img, mask_img=mask22_img,
+                               resampling_target="labels")
+
+    masker.fit()
+    np.testing.assert_almost_equal(masker.labels_img_.get_affine(),
+                                   labels33_img.get_affine())
+    assert_equal(masker.labels_img_.shape, labels33_img.shape)
+
+    np.testing.assert_almost_equal(masker.mask_img_.get_affine(),
+                                   masker.labels_img_.get_affine())
+    assert_equal(masker.mask_img_.shape, masker.labels_img_.shape[:3])
+
+    transformed = masker.transform(fmri11_img)
+    assert_equal(transformed.shape, (length, n_regions))
+
+    fmri11_img_r = masker.inverse_transform(transformed)
+    np.testing.assert_almost_equal(fmri11_img_r.get_affine(),
+                                   masker.labels_img_.get_affine())
+    assert_equal(fmri11_img_r.shape,
+                 (masker.labels_img_.shape[:3] + (length,)))
+
+    # Test with clipped labels: mask does not contain all labels.
+    # Shapes do matter in that case, because there is some resampling
+    # taking place.
+    shape1 = (10, 11, 12)  # fmri
+    shape2 = (8, 9, 10)  # mask
+    shape3 = (16, 18, 20)  # maps
+
+    n_regions = 9
+    length = 21
+
+    fmri11_img, _ = generate_random_img(shape1, affine=affine,
+                                        length=length)
+    _, mask22_img = generate_random_img(shape2, affine=affine,
+                                        length=length)
+
+    # Target: labels
+    labels33_img = testing.generate_labeled_regions(shape3, n_regions,
+                                                    affine=affine)
+
+    masker = NiftiLabelsMasker(labels33_img, mask_img=mask22_img,
+                               resampling_target="labels")
+
+    masker.fit()
+    np.testing.assert_almost_equal(masker.labels_img_.get_affine(),
+                                   labels33_img.get_affine())
+    assert_equal(masker.labels_img_.shape, labels33_img.shape)
+
+    np.testing.assert_almost_equal(masker.mask_img_.get_affine(),
+                                   masker.labels_img_.get_affine())
+    assert_equal(masker.mask_img_.shape, masker.labels_img_.shape[:3])
+
+    uniq_labels = np.unique(masker.labels_img_.get_data())
+    assert_equal(uniq_labels[0], 0)
+    assert_true(len(uniq_labels) - 1 == n_regions)
+
+    transformed = masker.transform(fmri11_img)
+    assert_equal(transformed.shape, (length, n_regions))
+    # Some regions have been clipped. Resulting signal must be zero
+    assert_true((transformed.var(axis=0) == 0).sum() < n_regions)
+
+    fmri11_img_r = masker.inverse_transform(transformed)
+    np.testing.assert_almost_equal(fmri11_img_r.get_affine(),
+                                   masker.labels_img_.get_affine())
+    assert_equal(fmri11_img_r.shape,
+                 (masker.labels_img_.shape[:3] + (length,)))
+
+
+    # Test with data and atlas of different shape: the atlas should be
+    # resampled to the data
+    shape22 = (5, 5, 6)
+    affine2 = 2 * np.eye(4)
+    affine2[-1, -1] = 1
+
+    fmri22_img, _ = generate_random_img(shape22, affine=affine2,
+                                                 length=length)
+    masker = NiftiLabelsMasker(labels33_img, mask_img=mask22_img)
+
+    masker.fit_transform(fmri22_img)
+    np.testing.assert_array_equal(
+        masker._resampled_labels_img_.get_affine(),
+        affine2)
diff --git a/nilearn/input_data/tests/test_nifti_region.py b/nilearn/input_data/tests/test_nifti_maps_masker.py
similarity index 54%
rename from nilearn/input_data/tests/test_nifti_region.py
rename to nilearn/input_data/tests/test_nifti_maps_masker.py
--- a/nilearn/input_data/tests/test_nifti_region.py
+++ b/nilearn/input_data/tests/test_nifti_maps_masker.py
@@ -10,7 +10,8 @@
 
 import nibabel
 
-from nilearn.input_data.nifti_region import NiftiLabelsMasker, NiftiMapsMasker
+from nilearn.input_data.nifti_labels_masker import NiftiLabelsMasker
+from nilearn.input_data.nifti_maps_masker import NiftiMapsMasker
 from nilearn._utils import testing, as_ndarray
 
 
@@ -21,199 +22,6 @@ def generate_random_img(shape, length=1, affine=np.eye(4),
                     as_ndarray(data[..., 0] > 0.2, dtype=np.int8), affine)
 
 
-def test_nifti_labels_masker():
-    # Check working of shape/affine checks
-    shape1 = (13, 11, 12)
-    affine1 = np.eye(4)
-
-    shape2 = (12, 10, 14)
-    affine2 = np.diag((1, 2, 3, 1))
-
-    n_regions = 9
-    length = 3
-
-    fmri11_img, mask11_img = generate_random_img(shape1, affine=affine1,
-                                                 length=length)
-    fmri12_img, mask12_img = generate_random_img(shape1, affine=affine2,
-                                                 length=length)
-    fmri21_img, mask21_img = generate_random_img(shape2, affine=affine1,
-                                                 length=length)
-
-    labels11_img = testing.generate_labeled_regions(shape1, affine=affine1,
-                                                    n_regions=n_regions)
-
-    mask_img_4d = nibabel.Nifti1Image(np.ones((2, 2, 2, 2), dtype=np.int8),
-                                      affine=np.diag((4, 4, 4, 1)))
-
-    # verify that 4D mask arguments are refused
-    masker = NiftiLabelsMasker(labels11_img, mask_img=mask_img_4d)
-    testing.assert_raises_regexp(TypeError, "A 3D image is expected",
-                                 masker.fit)
-
-    # check exception when transform() called without prior fit()
-    masker11 = NiftiLabelsMasker(labels11_img, resampling_target=None)
-    testing.assert_raises_regexp(
-        ValueError,
-        'has not been fitted. ', masker11.transform, fmri11_img)
-
-    # No exception raised here
-    signals11 = masker11.fit().transform(fmri11_img)
-    assert_equal(signals11.shape, (length, n_regions))
-
-    masker11 = NiftiLabelsMasker(labels11_img, mask_img=mask11_img,
-                                 resampling_target=None)
-    signals11 = masker11.fit().transform(fmri11_img)
-    assert_equal(signals11.shape, (length, n_regions))
-
-    # Test all kinds of mismatch between shapes and between affines
-    masker11 = NiftiLabelsMasker(labels11_img, resampling_target=None)
-    masker11.fit()
-    assert_raises(ValueError, masker11.transform, fmri12_img)
-    assert_raises(ValueError, masker11.transform, fmri21_img)
-
-    masker11 = NiftiLabelsMasker(labels11_img, mask_img=mask12_img,
-                                 resampling_target=None)
-    assert_raises(ValueError, masker11.fit)
-
-    masker11 = NiftiLabelsMasker(labels11_img, mask_img=mask21_img,
-                                 resampling_target=None)
-    assert_raises(ValueError, masker11.fit)
-
-    # Transform, with smoothing (smoke test)
-    masker11 = NiftiLabelsMasker(labels11_img, smoothing_fwhm=3,
-                                 resampling_target=None)
-    signals11 = masker11.fit().transform(fmri11_img)
-    assert_equal(signals11.shape, (length, n_regions))
-
-    masker11 = NiftiLabelsMasker(labels11_img, smoothing_fwhm=3,
-                                 resampling_target=None)
-    signals11 = masker11.fit_transform(fmri11_img)
-    assert_equal(signals11.shape, (length, n_regions))
-
-    testing.assert_raises_regexp(
-        ValueError, 'has not been fitted. ',
-        NiftiLabelsMasker(labels11_img).inverse_transform, signals11)
-
-    # Call inverse transform (smoke test)
-    fmri11_img_r = masker11.inverse_transform(signals11)
-    assert_equal(fmri11_img_r.shape, fmri11_img.shape)
-    np.testing.assert_almost_equal(fmri11_img_r.get_affine(),
-                                   fmri11_img.get_affine())
-
-
-def test_nifti_labels_masker_resampling():
-    # Test resampling in NiftiLabelsMasker
-    shape1 = (10, 11, 12)
-    affine = np.eye(4)
-
-    # mask
-    shape2 = (16, 17, 18)
-
-    # labels
-    shape3 = (13, 14, 15)
-
-    n_regions = 9
-    length = 3
-
-    # With data of the same affine
-    fmri11_img, _ = generate_random_img(shape1, affine=affine,
-                                                 length=length)
-    _, mask22_img = generate_random_img(shape2, affine=affine,
-                                                 length=length)
-
-    labels33_img = testing.generate_labeled_regions(shape3, n_regions,
-                                                    affine=affine)
-
-    # Test error checking
-    assert_raises(ValueError, NiftiLabelsMasker, labels33_img,
-                  resampling_target="mask")
-    assert_raises(ValueError, NiftiLabelsMasker, labels33_img,
-                  resampling_target="invalid")
-
-    # Target: labels
-    masker = NiftiLabelsMasker(labels33_img, mask_img=mask22_img,
-                               resampling_target="labels")
-
-    masker.fit()
-    np.testing.assert_almost_equal(masker.labels_img_.get_affine(),
-                                   labels33_img.get_affine())
-    assert_equal(masker.labels_img_.shape, labels33_img.shape)
-
-    np.testing.assert_almost_equal(masker.mask_img_.get_affine(),
-                                   masker.labels_img_.get_affine())
-    assert_equal(masker.mask_img_.shape, masker.labels_img_.shape[:3])
-
-    transformed = masker.transform(fmri11_img)
-    assert_equal(transformed.shape, (length, n_regions))
-
-    fmri11_img_r = masker.inverse_transform(transformed)
-    np.testing.assert_almost_equal(fmri11_img_r.get_affine(),
-                                   masker.labels_img_.get_affine())
-    assert_equal(fmri11_img_r.shape,
-                 (masker.labels_img_.shape[:3] + (length,)))
-
-    # Test with clipped labels: mask does not contain all labels.
-    # Shapes do matter in that case, because there is some resampling
-    # taking place.
-    shape1 = (10, 11, 12)  # fmri
-    shape2 = (8, 9, 10)  # mask
-    shape3 = (16, 18, 20)  # maps
-
-    n_regions = 9
-    length = 21
-
-    fmri11_img, _ = generate_random_img(shape1, affine=affine,
-                                        length=length)
-    _, mask22_img = generate_random_img(shape2, affine=affine,
-                                        length=length)
-
-    # Target: labels
-    labels33_img = testing.generate_labeled_regions(shape3, n_regions,
-                                                    affine=affine)
-
-    masker = NiftiLabelsMasker(labels33_img, mask_img=mask22_img,
-                               resampling_target="labels")
-
-    masker.fit()
-    np.testing.assert_almost_equal(masker.labels_img_.get_affine(),
-                                   labels33_img.get_affine())
-    assert_equal(masker.labels_img_.shape, labels33_img.shape)
-
-    np.testing.assert_almost_equal(masker.mask_img_.get_affine(),
-                                   masker.labels_img_.get_affine())
-    assert_equal(masker.mask_img_.shape, masker.labels_img_.shape[:3])
-
-    uniq_labels = np.unique(masker.labels_img_.get_data())
-    assert_equal(uniq_labels[0], 0)
-    assert_true(len(uniq_labels) - 1 == n_regions)
-
-    transformed = masker.transform(fmri11_img)
-    assert_equal(transformed.shape, (length, n_regions))
-    # Some regions have been clipped. Resulting signal must be zero
-    assert_true((transformed.var(axis=0) == 0).sum() < n_regions)
-
-    fmri11_img_r = masker.inverse_transform(transformed)
-    np.testing.assert_almost_equal(fmri11_img_r.get_affine(),
-                                   masker.labels_img_.get_affine())
-    assert_equal(fmri11_img_r.shape,
-                 (masker.labels_img_.shape[:3] + (length,)))
-
-    # Test with data and atlas of different shape: the atlas should be
-    # resampled to the data
-    shape22 = (5, 5, 6)
-    affine2 = 2 * np.eye(4)
-    affine2[-1, -1] = 1
-
-    fmri22_img, _ = generate_random_img(shape22, affine=affine2,
-                                                 length=length)
-    masker = NiftiLabelsMasker(labels33_img, mask_img=mask22_img)
-
-    masker.fit_transform(fmri22_img)
-    np.testing.assert_array_equal(
-        masker._resampled_labels_img_.get_affine(),
-        affine2)
-
-
 def test_nifti_maps_masker():
     # Check working of shape/affine checks
     shape1 = (13, 11, 12)