Repository: nilearn/nilearn

Issue:
plot_carpet handles TR information in an unclear way
<!--Provide a brief description of the bug.-->
Currently, the plot_carpet function gets the reeptition time (tr) information as follows:
```tr = img.header.get_zooms()[-1]```
But  depending on the way the image was created, this may lead to wrong values, e.g. it defaults to 1.
Moreover, this is done silently, and the user cannot supply a TR value.

<!--Please fill in the following information, to the best of your ability.-->
Nilearn version:
0.9

### Expected behavior
We  need 2 things:
* document current behavior
* allow user-supplied tr by adding a `tr` argument

### Actual behavior


### Steps and code to reproduce bug

```
from nilearn.datasets import func
data = func.fetch_localizer_first_level()
fmri_img = data.epi_img
from nilearn.plotting import plot_carpet
display = plot_carpet(fmri_img)
display.show()
```



Discussion:

Resolving patch:
diff --git a/examples/01_plotting/plot_carpet.py b/examples/01_plotting/plot_carpet.py
--- a/examples/01_plotting/plot_carpet.py
+++ b/examples/01_plotting/plot_carpet.py
@@ -16,6 +16,10 @@
 
 adhd_dataset = datasets.fetch_adhd(n_subjects=1)
 
+# plot_carpet can infer TR from the image header, but preprocessing can often
+# overwrite that particular header field, so we will be explicit.
+t_r = 2.
+
 # Print basic information on the dataset
 print('First subject functional nifti image (4D) is at: %s' %
       adhd_dataset.func[0])  # 4D data
@@ -35,7 +39,7 @@
 
 from nilearn.plotting import plot_carpet
 
-display = plot_carpet(adhd_dataset.func[0], mask_img)
+display = plot_carpet(adhd_dataset.func[0], mask_img, t_r=t_r)
 
 display.show()
 
@@ -73,6 +77,7 @@
 display = plot_carpet(
     adhd_dataset.func[0],
     discrete_atlas_img,
+    t_r=t_r,
     mask_labels=map_labels,
     axes=ax,
 )
diff --git a/nilearn/plotting/img_plotting.py b/nilearn/plotting/img_plotting.py
--- a/nilearn/plotting/img_plotting.py
+++ b/nilearn/plotting/img_plotting.py
@@ -1354,7 +1354,7 @@ def plot_markers(node_values, node_coords, node_size='auto',
 
 
 @fill_doc
-def plot_carpet(img, mask_img=None, mask_labels=None,
+def plot_carpet(img, mask_img=None, mask_labels=None, t_r=None,
                 detrend=True, output_file=None,
                 figure=None, axes=None, vmin=None, vmax=None, title=None,
                 cmap=plt.cm.gist_ncar):
@@ -1379,6 +1379,15 @@ def plot_carpet(img, mask_img=None, mask_labels=None,
         If ``mask_img`` corresponds to an atlas, then this dictionary maps
         values from the ``mask_img`` to labels. Dictionary keys are labels
         and values are values within the atlas.
+    %(t_r)s
+
+        .. note::
+            If ``t_r`` is not provided, it will be inferred from ``img``'s
+            header (``img.header.get_zooms()[-1]``).
+
+        .. versionadded:: 0.9.1.dev
+            Prior to this, ``t_r`` would be inferred from ``img`` without
+            user input.
 
     detrend : :obj:`bool`, optional
         Detrend and z-score the data prior to plotting. Default=True.
@@ -1391,7 +1400,7 @@ def plot_carpet(img, mask_img=None, mask_labels=None,
     %(cmap)s
 
         .. note::
-            This argumeent is used only if an atlas is used.
+            This argument is used only if an atlas is used.
 
         Default=`plt.cm.gist_ncar`.
 
@@ -1415,7 +1424,7 @@ def plot_carpet(img, mask_img=None, mask_labels=None,
     img = _utils.check_niimg_4d(img, dtype='auto')
 
     # Define TR and number of frames
-    tr = img.header.get_zooms()[-1]
+    t_r = t_r or img.header.get_zooms()[-1]
     n_tsteps = img.shape[-1]
 
     if mask_img is None:
@@ -1458,7 +1467,7 @@ def plot_carpet(img, mask_img=None, mask_labels=None,
 
     # Detrend and standardize data
     if detrend:
-        data = clean(data, t_r=tr, detrend=True, standardize='zscore')
+        data = clean(data, t_r=t_r, detrend=True, standardize='zscore')
 
     if figure is None:
         if not axes:
@@ -1553,7 +1562,7 @@ def plot_carpet(img, mask_img=None, mask_labels=None,
     if title:
         axes.set_title(title)
 
-    labels = tr * (np.array(xticks))
+    labels = t_r * (np.array(xticks))
     labels *= (2 ** n_decimations)
     axes.set_xticklabels(['%.02f' % t for t in labels.tolist()])
 


Test patch:
diff --git a/nilearn/plotting/tests/test_img_plotting/test_plot_carpet.py b/nilearn/plotting/tests/test_img_plotting/test_plot_carpet.py
--- a/nilearn/plotting/tests/test_img_plotting/test_plot_carpet.py
+++ b/nilearn/plotting/tests/test_img_plotting/test_plot_carpet.py
@@ -28,8 +28,8 @@ def test_plot_carpet(testdata_4d):  # noqa:F811
     plt.close(display)
 
     fig, ax = plt.subplots()
-    display = plot_carpet(img_4d_long, mask_img, detrend=True, title='TEST',
-                          figure=fig, axes=ax)
+    display = plot_carpet(img_4d_long, mask_img, t_r=None, detrend=True,
+                          title='TEST', figure=fig, axes=ax)
     # Next two lines retrieve the numpy array from the plot
     ax = display.axes[0]
     plotted_array = ax.images[0].get_array()
@@ -47,7 +47,8 @@ def test_plot_carpet_with_atlas(testdata_4d):  # noqa:F811
     atlas_labels = testdata_4d['atlas_labels']
 
     # Test atlas - labels
-    display = plot_carpet(img_4d, mask_img, detrend=False, title='TEST')
+    # t_r is set explicitly for this test as well
+    display = plot_carpet(img_4d, mask_img, t_r=2, detrend=False, title='TEST')
 
     # Check the output
     # Two axes: 1 for colorbar and 1 for imshow