Repository: nilearn/nilearn

Issue:
[BUG] load_confounds on 0.10.1 does not detect the corresponding confound file
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Operating system

- [ ] Linux
- [ ] Mac
- [ ] Windows

### Operating system version

_No response_

### Python version

- [ ] 3.11
- [ ] 3.10
- [ ] 3.9
- [X] 3.8
- [ ] 3.7

### nilearn version

0.10.1.dev

### Expected behavior

load_confounds.py on 0.10.0 works as intended (just request to scrub the BOLD runs (3 in total). However, I had to switch to 0.10.1 to perform second level permutation testing (as 0.10.0 was not performing well, providing completely different results compared to FSL). But now load_confounds cannot locate the corresponding confound file, despite running the same script. 

### Current behavior & error messages

0.10.1 load_confounds.py gives me an error that corresponding confound file does not exist, despite it all working well in 0.10.0

### Steps and code to reproduce bug

```python
confounds_scrub, sample_mask = load_confounds(task_nii,strategy=["scrub"],
                                scrub=5,
                                fd_threshold=.9,
                                std_dvars_threshold=50,
                            )
```

task_nii is my path to my single functional file i analyze (filename including)


Discussion:
Can you share the fMRIPrep version you used, as well as a filetree of your fMRIPrep derivatives?
I use fmriprep 22.0.2

Here are the subdirectories of one participant

```
log/
    20230601-095801_4fc3a418-9574-455c-9017-4d738146ac2f/
        fmriprep.toml
figures/
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_desc-validation_bold.html
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_desc-validation_bold.html
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_desc-validation_bold.html
    sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_desc-validation_bold.html
    sub-01_ses-PRISMA_desc-about_T1w.html
    sub-01_ses-PRISMA_desc-summary_T1w.html
    sub-01_ses-PRISMA_desc-conform_T1w.html
    sub-01_ses-PRISMA_dseg.svg
    sub-01_ses-PRISMA_run-2_fmapid-auto00002_desc-pepolar_fieldmap.svg
    sub-01_ses-PRISMA_run-1_fmapid-auto00001_desc-pepolar_fieldmap.svg
    sub-01_ses-PRISMA_run-1_fmapid-auto00000_desc-pepolar_fieldmap.svg
    sub-01_ses-PRISMA_space-MNI152NLin6Asym_T1w.svg
    sub-01_ses-PRISMA_space-MNI152NLin2009cAsym_T1w.svg
    sub-01_ses-PRISMA_run-3_fmapid-auto00003_desc-pepolar_fieldmap.svg
    sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_desc-sdc_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_desc-sdc_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_desc-sdc_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_desc-sdc_bold.svg
    sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_desc-flirtbbr_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_desc-flirtbbr_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_desc-flirtbbr_bold.svg
    sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_desc-compcorvar_bold.svg
    sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_desc-confoundcorr_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_desc-flirtbbr_bold.svg
    sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_desc-rois_bold.svg
    sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_desc-carpetplot_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_desc-compcorvar_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_desc-confoundcorr_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_desc-compcorvar_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_desc-carpetplot_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_desc-confoundcorr_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_desc-compcorvar_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_desc-confoundcorr_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_desc-rois_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_desc-carpetplot_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_desc-carpetplot_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_desc-rois_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_desc-rois_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_desc-aroma_bold.svg
    sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_desc-aroma_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_desc-summary_bold.html
    sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_desc-summary_bold.html
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_desc-aroma_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_desc-summary_bold.html
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_desc-aroma_bold.svg
    sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_desc-summary_bold.html
ses-PRISMA/
    anat/
        sub-01_ses-PRISMA_desc-preproc_T1w.nii.gz
        sub-01_ses-PRISMA_desc-preproc_T1w.json
        sub-01_ses-PRISMA_desc-brain_mask.nii.gz
        sub-01_ses-PRISMA_desc-brain_mask.json
        sub-01_ses-PRISMA_label-GM_probseg.nii.gz
        sub-01_ses-PRISMA_label-WM_probseg.nii.gz
        sub-01_ses-PRISMA_label-CSF_probseg.nii.gz
        sub-01_ses-PRISMA_dseg.nii.gz
        sub-01_ses-PRISMA_from-T1w_to-MNI152NLin2009cAsym_mode-image_xfm.h5
        sub-01_ses-PRISMA_from-T1w_to-MNI152NLin6Asym_mode-image_xfm.h5
        sub-01_ses-PRISMA_from-MNI152NLin2009cAsym_to-T1w_mode-image_xfm.h5
        sub-01_ses-PRISMA_from-MNI152NLin6Asym_to-T1w_mode-image_xfm.h5
        sub-01_ses-PRISMA_space-MNI152NLin2009cAsym_res-2_desc-preproc_T1w.nii.gz
        sub-01_ses-PRISMA_space-MNI152NLin2009cAsym_res-2_desc-preproc_T1w.json
        sub-01_ses-PRISMA_space-MNI152NLin2009cAsym_res-2_label-GM_probseg.nii.gz
        sub-01_ses-PRISMA_space-MNI152NLin2009cAsym_res-2_label-WM_probseg.nii.gz
        sub-01_ses-PRISMA_space-MNI152NLin2009cAsym_res-2_label-CSF_probseg.nii.gz
        sub-01_ses-PRISMA_space-MNI152NLin2009cAsym_res-2_desc-brain_mask.nii.gz
        sub-01_ses-PRISMA_space-MNI152NLin2009cAsym_res-2_desc-brain_mask.json
        sub-01_ses-PRISMA_space-MNI152NLin2009cAsym_res-2_dseg.nii.gz
    fmap/
        sub-01_ses-PRISMA_run-2_fmapid-auto00002_desc-coeff_fieldmap.nii.gz
        sub-01_ses-PRISMA_run-1_fmapid-auto00000_desc-coeff_fieldmap.nii.gz
        sub-01_ses-PRISMA_run-2_fmapid-auto00002_desc-epi_fieldmap.nii.gz
        sub-01_ses-PRISMA_run-1_fmapid-auto00001_desc-coeff_fieldmap.nii.gz
        sub-01_ses-PRISMA_run-2_fmapid-auto00002_desc-preproc_fieldmap.nii.gz
        sub-01_ses-PRISMA_run-2_fmapid-auto00002_desc-preproc_fieldmap.json
        sub-01_ses-PRISMA_run-1_fmapid-auto00000_desc-epi_fieldmap.nii.gz
        sub-01_ses-PRISMA_run-1_fmapid-auto00001_desc-epi_fieldmap.nii.gz
        sub-01_ses-PRISMA_run-1_fmapid-auto00000_desc-preproc_fieldmap.nii.gz
        sub-01_ses-PRISMA_run-1_fmapid-auto00000_desc-preproc_fieldmap.json
        sub-01_ses-PRISMA_run-1_fmapid-auto00001_desc-preproc_fieldmap.nii.gz
        sub-01_ses-PRISMA_run-1_fmapid-auto00001_desc-preproc_fieldmap.json
        sub-01_ses-PRISMA_run-3_fmapid-auto00003_desc-coeff_fieldmap.nii.gz
        sub-01_ses-PRISMA_run-3_fmapid-auto00003_desc-epi_fieldmap.nii.gz
        sub-01_ses-PRISMA_run-3_fmapid-auto00003_desc-preproc_fieldmap.nii.gz
        sub-01_ses-PRISMA_run-3_fmapid-auto00003_desc-preproc_fieldmap.json
    func/
        sub-01_ses-PRISMA_task-rest_dir-ap_run-1_from-scanner_to-T1w_mode-image_xfm.txt
        sub-01_ses-PRISMA_task-rest_dir-ap_run-1_from-T1w_to-scanner_mode-image_xfm.txt
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_from-scanner_to-T1w_mode-image_xfm.txt
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_from-T1w_to-scanner_mode-image_xfm.txt
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_from-scanner_to-T1w_mode-image_xfm.txt
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_from-T1w_to-scanner_mode-image_xfm.txt
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_from-scanner_to-T1w_mode-image_xfm.txt
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_from-T1w_to-scanner_mode-image_xfm.txt
        sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_space-MNI152NLin2009cAsym_res-2_desc-preproc_bold.nii.gz
        sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_space-MNI152NLin2009cAsym_res-2_desc-preproc_bold.json
        sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_space-MNI152NLin2009cAsym_res-2_boldref.nii.gz
        sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_space-MNI152NLin2009cAsym_res-2_desc-brain_mask.nii.gz
        sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_space-MNI152NLin2009cAsym_res-2_desc-brain_mask.json
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_space-MNI152NLin2009cAsym_res-2_desc-preproc_bold.nii.gz
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_space-MNI152NLin2009cAsym_res-2_desc-preproc_bold.json
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_space-MNI152NLin2009cAsym_res-2_boldref.nii.gz
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_space-MNI152NLin2009cAsym_res-2_desc-brain_mask.nii.gz
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_space-MNI152NLin2009cAsym_res-2_desc-brain_mask.json
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_space-MNI152NLin2009cAsym_res-2_desc-preproc_bold.nii.gz
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_space-MNI152NLin2009cAsym_res-2_desc-preproc_bold.json
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_space-MNI152NLin2009cAsym_res-2_boldref.nii.gz
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_space-MNI152NLin2009cAsym_res-2_desc-brain_mask.nii.gz
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_space-MNI152NLin2009cAsym_res-2_desc-brain_mask.json
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_space-MNI152NLin2009cAsym_res-2_desc-preproc_bold.nii.gz
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_space-MNI152NLin2009cAsym_res-2_desc-preproc_bold.json
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_space-MNI152NLin2009cAsym_res-2_boldref.nii.gz
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_space-MNI152NLin2009cAsym_res-2_desc-brain_mask.nii.gz
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_space-MNI152NLin2009cAsym_res-2_desc-brain_mask.json
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_space-MNI152NLin6Asym_desc-smoothAROMAnonaggr_bold.nii.gz
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_space-MNI152NLin6Asym_desc-smoothAROMAnonaggr_bold.json
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_AROMAnoiseICs.csv
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_desc-MELODIC_mixing.tsv
        sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_AROMAnoiseICs.csv
        sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_desc-MELODIC_mixing.tsv
        sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_space-MNI152NLin6Asym_desc-smoothAROMAnonaggr_bold.nii.gz
        sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_space-MNI152NLin6Asym_desc-smoothAROMAnonaggr_bold.json
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_desc-confounds_timeseries.tsv
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-2_part-mag_desc-confounds_timeseries.json
        sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_desc-confounds_timeseries.tsv
        sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_desc-confounds_timeseries.json
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_AROMAnoiseICs.csv
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_desc-MELODIC_mixing.tsv
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_space-MNI152NLin6Asym_desc-smoothAROMAnonaggr_bold.nii.gz
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_space-MNI152NLin6Asym_desc-smoothAROMAnonaggr_bold.json
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_desc-confounds_timeseries.tsv
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-3_part-mag_desc-confounds_timeseries.json
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_AROMAnoiseICs.csv
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_desc-MELODIC_mixing.tsv
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_desc-confounds_timeseries.tsv
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_desc-confounds_timeseries.json
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_space-MNI152NLin6Asym_desc-smoothAROMAnonaggr_bold.nii.gz
        sub-01_ses-PRISMA_task-ROSETTA_dir-ap_run-1_part-mag_space-MNI152NLin6Asym_desc-smoothAROMAnonaggr_bold.json
```
fullpath I give to the script is '/mnt/scratch/PBCTI/BIDS/BIDS_dataset_20230531-1633/derivatives/fmriprep-22.0.2/sub-01/ses-PRISMA/func/sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_space-MNI152NLin2009cAsym_res-2_desc-preproc_bold.nii.gz'
Only the run number is changing
Thanks @vytautasl1337! It seems possible that `load_confounds` is having trouble with the `dir` or `part` entities specifically. I'll take a look at the code.
It looks like the entities `sub`, `ses`, `task`, and `run` are hardcoded into the confounds file collection function, so other entities (`dir` and `part`, in this case) are not considered. We will need to make the file matching step more generic for it to work with your file.

In the meantime, since your requested strategy doesn't include AROMA confounds, the following should work for you:

```python
from nilearn.interfaces.fmriprep import load_confounds

confounds_file = "/mnt/scratch/PBCTI/BIDS/BIDS_dataset_20230531-1633/derivatives/fmriprep-22.0.2/sub-01/ses-PRISMA/func/sub-01_ses-PRISMA_task-rest_dir-ap_run-1_part-mag_desc-confounds_timeseries.tsv"
strategy = "scrub"

confounds_json_file = load_confounds._get_json(confounds_file)
sample_mask, confounds = load_confounds._load_single_confounds_file(
    confounds_file=confounds_file,
    strategy=strategy,
    demean=True,
    confounds_json_file=confounds_json_file,
    scrub=5,
    fd_threshold=.9,
    std_dvars_threshold=50,
)
```
I think @htwangtw has a similar issue on this, no? 
See #3020 

Resolving patch:
diff --git a/nilearn/interfaces/fmriprep/load_confounds_utils.py b/nilearn/interfaces/fmriprep/load_confounds_utils.py
--- a/nilearn/interfaces/fmriprep/load_confounds_utils.py
+++ b/nilearn/interfaces/fmriprep/load_confounds_utils.py
@@ -1,4 +1,5 @@
 """Helper functions for the manipulation of fmriprep output confounds."""
+import itertools
 import json
 import os
 import re
@@ -88,48 +89,80 @@ def _add_suffix(params, model):
     return params_full
 
 
+def _generate_confounds_file_candidates(nii_file):
+    """Generate confounds file candidates.
+
+    Build a list of potential confounds filenames using all combinations of
+    the entities in the image file.
+    """
+    entities = parse_bids_filename(nii_file)
+    file_fields = entities["file_fields"]
+    entities = {k: v for k, v in entities.items() if k in file_fields}
+    entities["desc"] = "confounds"
+    if "desc" not in file_fields:
+        file_fields.append("desc")
+
+    all_subsets = []
+    for n_entities in range(1, len(file_fields) + 1):
+        all_subsets.append(
+            list(itertools.combinations(file_fields, n_entities))
+        )
+
+    # Flatten the list of lists
+    all_subsets = [list(item) for sublist in all_subsets for item in sublist]
+    # https://stackoverflow.com/a/3724558/2589328
+    unique_subsets = [list(x) for x in set(tuple(x) for x in all_subsets)]
+
+    # Require "desc"
+    unique_subsets = [subset for subset in unique_subsets if "desc" in subset]
+
+    filenames = [
+        "_".join(["-".join([k, entities[k]]) for k in lst])
+        for lst in unique_subsets
+    ]
+    return filenames
+
+
 def _get_file_name(nii_file):
-    """Construct the raw confound file name from processed functional data."""
+    """Identify the confounds file associated with a functional image."""
     if isinstance(nii_file, list):  # catch gifti
         nii_file = nii_file[0]
-    entities = parse_bids_filename(nii_file)
-    subject_label = f"sub-{entities['sub']}"
-    if "ses" in entities:
-        subject_label = f"{subject_label}_ses-{entities['ses']}"
-    specifiers = f"task-{entities['task']}"
-    if "run" in entities:
-        specifiers = f"{specifiers}_run-{entities['run']}"
-    img_filename = nii_file.split(os.sep)[-1]
+
+    base_dir = os.path.dirname(nii_file)
+
+    filenames = _generate_confounds_file_candidates(nii_file)
+
     # fmriprep has changed the file suffix between v20.1.1 and v20.2.0 with
     # respect to BEP 012.
     # cf. https://neurostars.org/t/naming-change-confounds-regressors-to-confounds-timeseries/17637 # noqa
     # Check file with new naming scheme exists or replace,
     # for backward compatibility.
-    confounds_raw_candidates = [
-        nii_file.replace(
-            img_filename,
-            f"{subject_label}_{specifiers}_desc-confounds_timeseries.tsv",
-        ),
-        nii_file.replace(
-            img_filename,
-            f"{subject_label}_{specifiers}_desc-confounds_regressors.tsv",
-        ),
-    ]
-
-    confounds_raw = [
-        cr for cr in confounds_raw_candidates if os.path.exists(cr)
+    suffixes = ["_timeseries.tsv", "_regressors.tsv"]
+
+    confound_file_candidates = []
+    for suffix in suffixes:
+        confound_file_candidates += [f + suffix for f in filenames]
+
+    # Sort the potential filenames by decreasing length,
+    # so earlier entries reflect more retained entities.
+    # https://www.geeksforgeeks.org/python-sort-list-of-lists-by-the-size-of-sublists/
+    confound_file_candidates = sorted(confound_file_candidates, key=len)[::-1]
+    confound_file_candidates = [
+        os.path.join(base_dir, crc) for crc in confound_file_candidates
     ]
+    found_files = [cr for cr in confound_file_candidates if os.path.isfile(cr)]
 
-    if not confounds_raw:
+    if not found_files:
         raise ValueError(
             "Could not find associated confound file. "
             "The functional derivatives should exist under the same parent "
             "directory."
         )
-    elif len(confounds_raw) != 1:
-        raise ValueError("Found more than one confound file.")
+    elif len(found_files) != 1:
+        found_str = "\n\t".join(found_files)
+        raise ValueError(f"Found more than one confound file:\n\t{found_str}")
     else:
-        return confounds_raw[0]
+        return found_files[0]
 
 
 def _get_confounds_file(image_file, flag_full_aroma):


Test patch:
diff --git a/nilearn/interfaces/fmriprep/tests/test_load_confounds.py b/nilearn/interfaces/fmriprep/tests/test_load_confounds.py
--- a/nilearn/interfaces/fmriprep/tests/test_load_confounds.py
+++ b/nilearn/interfaces/fmriprep/tests/test_load_confounds.py
@@ -556,7 +556,16 @@ def test_sample_mask(tmp_path):
 
 
 @pytest.mark.parametrize(
-    "image_type", ["regular", "native", "ica_aroma", "gifti", "cifti"]
+    "image_type", [
+        "regular",
+        "native",
+        "ica_aroma",
+        "gifti",
+        "cifti",
+        "res",
+        "den",
+        "part",
+    ],
 )
 def test_inputs(tmp_path, image_type):
     """Test multiple images as input."""
diff --git a/nilearn/interfaces/fmriprep/tests/test_load_confounds_utils.py b/nilearn/interfaces/fmriprep/tests/test_load_confounds_utils.py
--- a/nilearn/interfaces/fmriprep/tests/test_load_confounds_utils.py
+++ b/nilearn/interfaces/fmriprep/tests/test_load_confounds_utils.py
@@ -15,8 +15,13 @@
         (["image1.nii.gz", "image2.nii.gz"], False),
         (["image_L.func.gii", "image_R.func.gii"], True),
         ([["image_L.func.gii", "image_R.func.gii"]], True),
-        ([["image1_L.func.gii", "image1_R.func.gii"],
-          ["image2_L.func.gii", "image2_R.func.gii"]], False),
+        (
+            [
+                ["image1_L.func.gii", "image1_R.func.gii"],
+                ["image2_L.func.gii", "image2_R.func.gii"],
+            ],
+            False,
+        ),
     ],
 )
 def test_sanitize_confounds(inputs, flag):
@@ -25,10 +30,28 @@ def test_sanitize_confounds(inputs, flag):
     assert singleflag is flag
 
 
-@pytest.mark.parametrize("flag,suffix",
-                         [(True, "_desc-confounds_regressors"),
-                          (False, "_desc-confounds_timeseries")])
-def test_get_file_name(tmp_path, flag, suffix):
-    img, _ = create_tmp_filepath(tmp_path, old_derivative_suffix=flag)
+@pytest.mark.parametrize("flag", [True, False])
+@pytest.mark.parametrize(
+    "image_type", ["regular", "native", "res", "cifti", "den", "part", "gifti"]
+)
+def test_get_file_name(tmp_path, flag, image_type):
+    """Test _get_file_name."""
+    if flag:
+        suffix = "_desc-confounds_regressors"
+    else:
+        suffix = "_desc-confounds_timeseries"
+
+    if image_type == "part":
+        kwargs = {"suffix": "sub-test01_task-test_part-mag_run-01"}
+    else:
+        kwargs = {}
+
+    img, _ = create_tmp_filepath(
+        tmp_path,
+        image_type=image_type,
+        old_derivative_suffix=flag,
+        **kwargs,
+    )
+
     conf = _get_file_name(img)
     assert suffix in conf
diff --git a/nilearn/interfaces/fmriprep/tests/utils.py b/nilearn/interfaces/fmriprep/tests/utils.py
--- a/nilearn/interfaces/fmriprep/tests/utils.py
+++ b/nilearn/interfaces/fmriprep/tests/utils.py
@@ -9,12 +9,15 @@
 img_file_patterns = {
     "ica_aroma":
         "_space-MNI152NLin2009cAsym_desc-smoothAROMAnonaggr_bold.nii.gz",
-    "regular":
-        "_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz",
-    "native":
-        "_desc-preproc_bold.nii.gz",
-    "cifti":
-        "_space-fsLR_den-91k_bold.dtseries.nii",
+    "regular": "_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz",
+    "res": "_space-MNI152NLin2009cAsym_res-2_desc-preproc_bold.nii.gz",
+    "native": "_desc-preproc_bold.nii.gz",
+    "cifti": "_space-fsLR_den-91k_bold.dtseries.nii",
+    "den": "_space-fsLR_den-32k_desc-preproc_bold.nii.gz",
+    "part": (
+        "_part-mag_space-MNI152NLin2009cAsym_"
+        "desc-preproc_bold.nii.gz"
+    ),
     "gifti": (
         "_space-fsaverage5_hemi-L_bold.func.gii",
         "_space-fsaverage5_hemi-R_bold.func.gii",