Repository: nilearn/nilearn

Issue:
Prevent user passing `standardize_confounds=False` with confound variables to `signal.clean` 
<!--Provide a brief description what you would like changes and why.-->

While working on the test in #2946, I noticed there's no mechanism in place to prevent user from passing some illogical options, such as `standardize_confounds=False, detrend=False, standardize=False` and `standardize_confounds=False, detrend=False` when passing confound variables. When confound variables are present, they should always be demeaned or standardised.

<!--Please fill in the following information, to the best of your ability.-->
### Benefits to the change

Reduce the chance of mistake for users who decided not to use the default parameters. 

### Pseudocode for the new behaviour, if applicable

I have thought of several ways:

1. Raise error when bad parameter combinations are passed to the function
2. Raise warning and fall back to default options
3. Warn the user without changing the provided parameters (proposed by @NicolasGensollen)

Here's a list of option combinations that should not be allowed in `signal.clean`.

|`standardize_confounds`|`detrend`|`standardize`|
|--|--|--|
|False|False|zscore|
|False|False|psc|
|False|False|False|


Discussion:
Thanks for opening this @htwangtw !
I agree that combinations of these parameters that do not make sense should be made clear to the user. 
I would add a third possible solution which is to "just" warn the user without changing the provided parameters. 
I vote for 3.
3 it is.

Resolving patch:
diff --git a/nilearn/signal.py b/nilearn/signal.py
--- a/nilearn/signal.py
+++ b/nilearn/signal.py
@@ -529,6 +529,10 @@ def clean(signals, runs=None, detrend=True, standardize='zscore',
     --------
         nilearn.image.clean_img
     """
+    # Raise warning for some parameter combinations when confounds present
+    if confounds is not None:
+        _check_signal_parameters(detrend, standardize_confounds)
+
     # Read confounds and signals
     signals, runs, confounds = _sanitize_inputs(
         signals, runs, confounds, sample_mask, ensure_finite
@@ -824,3 +828,15 @@ def _sanitize_signals(signals, ensure_finite):
         if mask.any():
             signals[mask] = 0
     return _ensure_float(signals)
+
+
+def _check_signal_parameters(detrend, standardize_confounds):
+    """Raise warning if the combination is illogical"""
+    if not detrend and not standardize_confounds:
+        warnings.warn("When confounds are provided, one must perform detrend "
+                      "and/or standarize confounds. You provided detrend={0}, "
+                      "standardize_confounds={1}. If confounds were not "
+                      "standardized or demeaned before passing to signal.clean"
+                      " signal will not be correctly cleaned. ".format(
+                          detrend, standardize_confounds)
+                      )


Test patch:
diff --git a/nilearn/tests/test_signal.py b/nilearn/tests/test_signal.py
--- a/nilearn/tests/test_signal.py
+++ b/nilearn/tests/test_signal.py
@@ -505,13 +505,17 @@ def test_clean_confounds():
 
     # Test without standardizing that constant parts of confounds are
     # accounted for
-    np.testing.assert_almost_equal(nisignal.clean(np.ones((20, 2)),
-                                                  standardize=False,
-                                                  confounds=np.ones(20),
-                                                  standardize_confounds=False,
-                                                  detrend=False,
-                                                  ).mean(),
-                                   np.zeros((20, 2)))
+    # passing standardize_confounds=False, detrend=False should raise warning
+    warning_message = r"must perform detrend and/or standarize confounds"
+    with pytest.warns(UserWarning, match=warning_message):
+        np.testing.assert_almost_equal(
+            nisignal.clean(np.ones((20, 2)),
+                           standardize=False,
+                           confounds=np.ones(20),
+                           standardize_confounds=False,
+                           detrend=False,
+                           ).mean(),
+            np.zeros((20, 2)))
 
     # Test to check that confounders effects are effectively removed from
     # the signals when having a detrending and filtering operation together.