Repository: nilearn/nilearn

Issue:
regions from RegionExtractor with a given mask_img lie outside mask
Hi all,

I am trying to extract regions that lie within a mask image from dict learning components image but I got regions outside my mask. The following code
```Python
from nilearn.regions import RegionExtractor
extractor = RegionExtractor(components_img, mask_img=mask_img)
extractor.fit()

mask_data = mask_img.get_data()
data = extractor.regions_img_.get_data()
print(data[mask_data == 0, 0].max())
```
outputs 0.0064742849 instead of 0. My nilearn version is 0.5.0.

I can do a PR to fix it




Discussion:
Thanks @salma1601 PR welcome.

You want to fix it by passing mask_img to connected_regions ?
Meanwhile, could you please provide a full script for reproducibility ?
> You want to fix it by passing mask_img to connected_regions ?

yes. Here is the full script
```Python
import glob
mask_img = '/tmp/mask.nii.gz'
func_files = glob.glob('/tmp/func/*.nii.gz')

from nilearn.decomposition import DictLearning
dict_learning = DictLearning(n_components=40,
                             memory="nilearn_cache", memory_level=2,
                             verbose=1,
                             random_state=0,
                             n_epochs=1,
                             n_jobs=3,
                             mask=mask_img, t_r=2.382)
dict_learning.fit(func_files)
components_img = dict_learning.components_img_

from nilearn.regions import RegionExtractor
extractor = RegionExtractor(components_img, mask_img=mask_img)
extractor.fit()

mask_data = mask_img.get_data()
data = extractor.regions_img_.get_data()
print(data[mask_data == 0, 0].max())
```


Resolving patch:
diff --git a/nilearn/regions/region_extractor.py b/nilearn/regions/region_extractor.py
--- a/nilearn/regions/region_extractor.py
+++ b/nilearn/regions/region_extractor.py
@@ -199,9 +199,9 @@ def connected_regions(maps_img, min_region_size=1350,
                                     target_affine=maps_img.affine,
                                     target_shape=maps_img.shape[:3],
                                     interpolation="nearest")
-            mask_data, _ = masking._load_mask_img(mask_img)
-            # Set as 0 to the values which are outside of the mask
-            maps[mask_data == 0.] = 0.
+        mask_data, _ = masking._load_mask_img(mask_img)
+        # Set as 0 to the values which are outside of the mask
+        maps[mask_data == 0.] = 0.
 
     for index in range(maps.shape[-1]):
         regions = []
@@ -410,7 +410,8 @@ def fit(self, X=None, y=None):
         self.regions_img_, self.index_ = connected_regions(threshold_maps,
                                                            self.min_region_size,
                                                            self.extractor,
-                                                           self.smoothing_fwhm)
+                                                           self.smoothing_fwhm,
+                                                           mask_img=self.mask_img)
 
         self.maps_img = self.regions_img_
         super(RegionExtractor, self).fit()


Test patch:
diff --git a/nilearn/regions/tests/test_region_extractor.py b/nilearn/regions/tests/test_region_extractor.py
--- a/nilearn/regions/tests/test_region_extractor.py
+++ b/nilearn/regions/tests/test_region_extractor.py
@@ -4,7 +4,8 @@
 import nibabel
 from scipy import ndimage
 
-from nose.tools import assert_equal, assert_true, assert_not_equal
+from nose.tools import (assert_equal, assert_true, assert_not_equal,
+                        assert_greater, assert_false)
 
 from nilearn.regions import (connected_regions, RegionExtractor,
                              connected_label_regions)
@@ -101,10 +102,16 @@ def test_connected_regions():
         assert_true(connected_extraction_3d_img.shape[-1] >= 1)
 
     # Test input mask_img
+    mask = mask_img.get_data()
+    mask[1, 1, 1] = 0
     extraction_with_mask_img, index = connected_regions(maps,
                                                         mask_img=mask_img)
     assert_true(extraction_with_mask_img.shape[-1] >= 1)
 
+    extraction_without_mask_img, index = connected_regions(maps)
+    assert_true(np.all(extraction_with_mask_img.get_data()[mask == 0] == 0.))
+    assert_false(np.all(extraction_without_mask_img.get_data()[mask == 0] == 0.))
+
     # mask_img with different shape
     mask = np.zeros(shape=(10, 11, 12), dtype=np.int)
     mask[1:-1, 1:-1, 1:-1] = 1
@@ -118,6 +125,10 @@ def test_connected_regions():
     assert_equal(maps.shape[:3], extraction_not_same_fov_mask.shape[:3])
     assert_not_equal(mask_img.shape, extraction_not_same_fov_mask.shape[:3])
 
+    extraction_not_same_fov, _ = connected_regions(maps)
+    assert_greater(np.sum(extraction_not_same_fov.get_data() == 0),
+                   np.sum(extraction_not_same_fov_mask.get_data() == 0))
+
 
 def test_invalid_threshold_strategies():
     maps, _ = generate_maps((6, 8, 10), n_regions=1)
@@ -148,6 +159,18 @@ def test_region_extractor_fit_and_transform():
     n_subjects = 5
     maps, mask_img = generate_maps((40, 40, 40), n_regions=n_regions)
 
+    # Test maps are zero in the mask
+    mask_data = mask_img.get_data()
+    mask_data[1, 1, 1] = 0
+    extractor_without_mask = RegionExtractor(maps)
+    extractor_without_mask.fit()
+    extractor_with_mask = RegionExtractor(maps, mask_img=mask_img)
+    extractor_with_mask.fit()
+    assert_false(np.all(
+        extractor_without_mask.regions_img_.get_data()[mask_data == 0] == 0.))
+    assert_true(np.all(
+        extractor_with_mask.regions_img_.get_data()[mask_data == 0] == 0.))
+
     # smoke test to RegionExtractor with thresholding_strategy='ratio_n_voxels'
     extract_ratio = RegionExtractor(maps, threshold=0.2,
                                     thresholding_strategy='ratio_n_voxels')