Repository: nilearn/nilearn

Issue:
NiftiLabelsMasker.inverse_transform() appears to fail in current nilearn version
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-79-642858f1debf> in <module>
----> 1 masker.inverse_transform(labels_and_my.values)

~/anaconda3/lib/python3.7/site-packages/nilearn/input_data/nifti_labels_masker.py in inverse_transform(self, signals)
    296         logger.log("computing image from signals", verbose=self.verbose)
    297         return signal_extraction.signals_to_img_labels(
--> 298             signals, self._resampled_labels_img_, self.mask_img_,
    299             background_label=self.background_label)

AttributeError: 'NiftiLabelsMasker' object has no attribute '_resampled_labels_img_'


Discussion:
Thanks for reporting ! Just to confirm, by current version do you mean the new alpha release or the last stable release, 0.5.2 ?

It looks as though `NiftiLabelsMasker` is expecting that you first call `.transform()` before calling `.inverse_transform()`. From a quick look, it seems that behavior has been consistent since at least 0.5.0.

Here's a MWE:

```python
from nilearn import datasets
from nilearn.input_data import NiftiLabelsMasker

dataset = datasets.fetch_atlas_harvard_oxford('cort-maxprob-thr25-2mm')
atlas_filename = dataset.maps
labels = dataset.labels

func = datasets.fetch_development_fmri(n_subjects=1).func[0]
masker = NiftiLabelsMasker(labels_img=atlas_filename, standardize=True)
masker.fit(func)
timeseries = masker.transform(func)
masker.inverse_transform(timeseries)
```

Removing the line `timeseries = masker.transform(func)` reproduces your error.

Maybe we could improve the error, here, as we do with `._check_fitted()`.
I cannot reproduce: the following works:
```
from nilearn import datasets, input_data
aal = datasets.fetch_atlas_aal()
masker = input_data.NiftiLabelsMasker(labels_img=aal.maps)
data = datasets.fetch_haxby()
X = masker.fit_transform(data.func[0])
masker.inverse_transform(X)
```
Can you please submit a minimal example to reproduce, as required by the issue template.
@emdupre  is correct: it's because transform is not called.

Actually, I would consider this as a bug. Our requirements are typically that fit must be called, but not transform.
Sounds good: so viable solutions include 1) keeping required fit() only consistent across nilearn functions and 2) explicit error message to user that transform() had nor been called before

Danilo


On Thu 24. Oct 2019 at 9:18 PM, Gael Varoquaux <notifications@github.com<mailto:notifications@github.com>> wrote:

@emdupre<https://github.com/emdupre> is correct: it's because transform is not called.

Actually, I would consider this as a bug. Our requirements are typically that fit must be called, but not transform.

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub<https://github.com/nilearn/nilearn/issues/2192?email_source=notifications&email_token=AA5Z6RCJAQFHVPWUCHQXO73QQJCNZA5CNFSM4JE4QVE2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOECG4FCQ#issuecomment-546161290>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AA5Z6RFZ4WZ76CUPVUY7PKTQQJCNZANCNFSM4JE4QVEQ>.

--
================================================
Danilo Bzdok, MD, PhD

Associate Professor
Department of Biomedical Engineering
Faculty of Medicine
McGill University
[https://docs.google.com/uc?export=download&id=1lznM5J5b7pcslyevQS1Bqf7HOY7u8jDz&revid=0ByoFfbRY-dPXcUtmY2VJbkZZVjM2VWpRNnJROUhETEI3S0xjPQ]

Associate Faculty
Montreal Institute for Learning Algorithms
[https://docs.google.com/uc?export=download&id=1lMKIKJaTSs6TXhoQlBJzTw7l-nSA9EI8&revid=0ByoFfbRY-dPXR0tjY1BMNzhvYjlpWFNOOEZXMW5NMXNxMllrPQ]



Resolving patch:
diff --git a/nilearn/input_data/nifti_labels_masker.py b/nilearn/input_data/nifti_labels_masker.py
--- a/nilearn/input_data/nifti_labels_masker.py
+++ b/nilearn/input_data/nifti_labels_masker.py
@@ -214,6 +214,10 @@ def fit(self, X=None, y=None):
 
             mask_data, mask_affine = masking._load_mask_img(self.mask_img_)
 
+        if not hasattr(self, '_resampled_labels_img_'):
+            # obviates need to run .transform() before .inverse_transform()
+            self._resampled_labels_img_ = self.labels_img_
+
         return self
 
     def fit_transform(self, imgs, confounds=None):


Test patch:
diff --git a/nilearn/input_data/tests/test_nifti_labels_masker.py b/nilearn/input_data/tests/test_nifti_labels_masker.py
--- a/nilearn/input_data/tests/test_nifti_labels_masker.py
+++ b/nilearn/input_data/tests/test_nifti_labels_masker.py
@@ -66,6 +66,11 @@ def test_nifti_labels_masker():
     signals11 = masker11.fit().transform(fmri11_img)
     assert_equal(signals11.shape, (length, n_regions))
 
+    # No exception should be raised either
+    masker11 = NiftiLabelsMasker(labels11_img, resampling_target=None)
+    masker11.fit()
+    masker11.inverse_transform(signals11)
+
     masker11 = NiftiLabelsMasker(labels11_img, mask_img=mask11_img,
                                  resampling_target=None)
     signals11 = masker11.fit().transform(fmri11_img)
diff --git a/nilearn/input_data/tests/test_nifti_maps_masker.py b/nilearn/input_data/tests/test_nifti_maps_masker.py
--- a/nilearn/input_data/tests/test_nifti_maps_masker.py
+++ b/nilearn/input_data/tests/test_nifti_maps_masker.py
@@ -105,6 +105,11 @@ def test_nifti_maps_masker():
     assert_equal(fmri11_img_r.shape, fmri11_img.shape)
     np.testing.assert_almost_equal(fmri11_img_r.affine, fmri11_img.affine)
 
+    # Now try on a masker that has never seen the call to "transform"
+    masker2 = NiftiMapsMasker(labels11_img, resampling_target=None)
+    masker2.fit()
+    masker2.inverse_transform(signals11)
+
     # Test with data and atlas of different shape: the atlas should be
     # resampled to the data
     shape22 = (5, 5, 6)