Xcp_d process HCP minimal preprocessed fMRI data to obtain nifti data

Summary of what happened:

I have used the xcpd to perform denoise for hcp minimal preprocessed fMRI data to obtain the nifti data. I used the xcpd 0.6.1rc1 to convert the hcp data to bids-style. And then, I used the xcpd to perform denoise using the bids-style data (–input-tyle fmriprep). The xcpd can running this process with no error, but it stuck in “denoise_bold_wf.regress_and_filter_bold” more than 12 hours. Is there anything wrong? Thank you very much for your help!

Command used (and if a helper script was used, a link to the helper script or the command generated):

step 1st: using xcpd 0.6.1rc1 to convert hcp data to bids style

#!/bin/bash
#SBATCH --job-name=xcpd
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=4
#SBATCH --mem-per-cpu 20G
#SBATCH -p q_fat_c
#SBATCH --qos=high_c
#SBATCH -o ./job.%j.out
#SBATCH -e ./job.%j.error.txt
module load singularity
subj=100610
Path=/ibmgpfs/cuizaixu_lab/xulongzhou/HCP_WMfMRI/xcpd0.3.2
hcpminiprep=/ibmgpfs/cuizaixu_lab/xulongzhou/HCP_WMfMRI/hcp_rest_1_miniprep
# Unzip rest-fMRI-1 data
for zipfile in /GPFS/PUB/ALL_Family_Subjects/Resting_State_fMRI_1_Preprocessed/${subj}*.zip
do
    # Create a directory with the same name as the zip file (excluding the .zip extension)
    # dirname=$(basename "$zipfile" .zip)
    # mkdir -p "/ibmgpfs/cuizaixu_lab/xulongzhou/HCP_WMfMRI/hcp_unzip/$dirname"

    # Create a common directory for all unzipped files (if it doesn't already exist)
    mkdir -p $hcpminiprep

    # Unzip the zip file to the corresponding directory without overwriting existing files
    unzip -n "$zipfile" -d $hcpminiprep
done

# Unzip T1w data
for zipfile in /GPFS/PUB/ALL_Family_Subjects/Structural_Preprocessed/${subj}*.zip
do
    # Unzip the zip file to the specified directory without overwriting existing files
    unzip -n "$zipfile" -d $hcpminiprep
done

xcpd_op=${Path}/step_1st_hcp2bids
mkdir -p $xcpd_op
xcpd_wp=${Path}/step_1st_wd/wd_$subj
mkdir -p $xcpd_wp
fslic=/ibmgpfs/cuizaixu_lab/xulongzhou/tool/freesurfer
templateflow=/ibmgpfs/cuizaixu_lab/xulongzhou/tool/templateflow
#Run xcpd
echo ""
echo "Running xcpd on participant: sub-$subj"
echo ""

# convert hcp to bids
unset PYTHONPATH
export SINGULARITYENV_TEMPLATEFLOW_HOME=$templateflow
singularity run --cleanenv \
        -B $hcpminiprep:/hcpminiprep \
        -B $xcpd_op:/output \
        -B $xcpd_wp:/work \
        -B $fslic:/fslic \
        -B $templateflow:$templateflow \
        /ibmgpfs/cuizaixu_lab/xulongzhou/apps/singularity_update/xcpd-0.6.1rc1.simg \
        /hcpminiprep /output participant --participant_label ${subj} \
        -w /work --nthreads 4 --omp-nthreads 4 --mem_gb 80 \
        --fs-license-file /fslic/license.txt \
        --input-type hcp \
        --nuisance-regressors none \
        --disable-bandpass-filter \
        --fd-thresh -1 \
        --resource-monitor

step 2nd: constuct the fMRIprep data to complete xcpd needed

module load singularity
subj=$1
Path=/ibmgpfs/cuizaixu_lab/xulongzhou/HCP_WMfMRI/xcpd0.3.2
customCP=/ibmgpfs/cuizaixu_lab/xulongzhou/HCP_WMfMRI/custom_confounds_csf_global_2p
fslic=/ibmgpfs/cuizaixu_lab/xulongzhou/tool/freesurfer
templateflow=/ibmgpfs/cuizaixu_lab/xulongzhou/tool/templateflow

# construct bids-style file
bids=${Path}/bids
mkdir -p ${bids}/sub-${subj}
cp -r ${Path}/step_1st_wd/wd_$subj/dset_bids/derivatives/hcp/sub-${subj}/func ${Path}/bids/sub-${subj}/
cp -r ${Path}/step_1st_wd/wd_$subj/dset_bids/derivatives/hcp/sub-${subj}/anat ${Path}/bids/sub-${subj}/

# construct custom confounds file
module load MATLAB
filePath=${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-LR_run-1_desc-confounds_timeseries.tsv
savePath=${customCP}/sub-${subj}_task-rest_dir-LR_run-1_desc-confounds_timeseries.tsv
rm -rf ${savePath}
matlab -nodisplay -nosplash -nodesktop -r \
    "extract_columns_by_title('${filePath}', '${savePath}', {'global_signal', 'csf'}); exit;"

filePath=${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-RL_run-1_desc-confounds_timeseries.tsv
savePath=${customCP}/sub-${subj}_task-rest_dir-RL_run-1_desc-confounds_timeseries.tsv
rm -rf ${savePath}
matlab -nodisplay -nosplash -nodesktop -r \
    "extract_columns_by_title('${filePath}', '${savePath}', {'global_signal', 'csf'}); exit;"

# add the BIDS version in the json file
cp ${Path}/dataset_description.json ${bids}/dataset_description.json

# construct fmriprep-style file structure
cp ${bids}/sub-${subj}/anat/sub-${subj}_space-MNI152NLin6Asym_res-2_desc-preproc_T1w.nii.gz ${bids}/sub-${subj}/anat/sub-${subj}_desc-preproc_T1w.nii.gz
cp ${bids}/sub-${subj}/anat/sub-${subj}_space-MNI152NLin6Asym_res-2_desc-brain_mask.nii.gz ${bids}/sub-${subj}/anat/sub-${subj}_desc-brain_mask.nii.gz
cp ${bids}/sub-${subj}/anat/sub-${subj}_space-MNI152NLin6Asym_res-2_desc-aparcaseg_dseg.nii.gz ${bids}/sub-${subj}/anat/sub-${subj}_desc-aparcaseg_dseg.nii.gz

cp ${bids}/sub-${subj}/anat/sub-${subj}_space-MNI152NLin6Asym_res-2_desc-brain_mask.nii.gz ${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-RL_run-1_space-MNI152NLin6Asym_res-2_desc-brain_mask.nii.gz
cp ${bids}/sub-${subj}/anat/sub-${subj}_space-MNI152NLin6Asym_res-2_desc-brain_mask.nii.gz ${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-LR_run-1_space-MNI152NLin6Asym_res-2_desc-brain_mask.nii.gz

cp ${bids}/sub-${subj}/anat/sub-${subj}_from-MNI152NLin6Asym_to-T1w_mode-image_xfm.txt ${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-LR_run-1_from-MNI152NLin6Asym_to-T1w_mode-image_xfm.txt
cp ${bids}/sub-${subj}/anat/sub-${subj}_from-MNI152NLin6Asym_to-T1w_mode-image_xfm.txt ${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-RL_run-1_from-MNI152NLin6Asym_to-T1w_mode-image_xfm.txt
cp ${bids}/sub-${subj}/anat/sub-${subj}_from-T1w_to-MNI152NLin6Asym_mode-image_xfm.txt ${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-LR_run-1_from-T1w_to-MNI152NLin6Asym_mode-image_xfm.txt
cp ${bids}/sub-${subj}/anat/sub-${subj}_from-T1w_to-MNI152NLin6Asym_mode-image_xfm.txt ${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-RL_run-1_from-T1w_to-MNI152NLin6Asym_mode-image_xfm.txt

step 3rd: running xcpd using fmriprep style to obtain denoised nifti data

module load singularity
subj=100610
Path=/ibmgpfs/cuizaixu_lab/xulongzhou/HCP_WMfMRI/xcpd0.3.2
fslic=/ibmgpfs/cuizaixu_lab/xulongzhou/tool/freesurfer
templateflow=/ibmgpfs/cuizaixu_lab/xulongzhou/tool/templateflow
custom_confound=/ibmgpfs/cuizaixu_lab/xulongzhou/HCP_WMfMRI/custom_confounds_csf_global_2p
output=${Path}/step_2nd_24PcsfGlobal
mkdir -p ${output}
wd=${Path}/step_2nd_wd/sub-${subj}
mkdir -p ${wd}
# running xcpd
unset PYTHONPATH
export SINGULARITYENV_TEMPLATEFLOW_HOME=$templateflow
singularity run --cleanenv \
        -B $Path/bids:/bids \
        -B $output:/output \
        -B $wd:/wd \
        -B $custom_confound:/custom_confounds \
        -B $fslic:/fslic \
        -B $templateflow:$templateflow \
        /ibmgpfs/cuizaixu_lab/xulongzhou/apps/singularity_update/xcpd-0.6.1rc1.simg \
        /bids /output participant \
        --participant_label ${subj} --task-id rest \
        --input-type fmriprep \
        --fs-license-file /fslic/license.txt \
        -w /wd --nthreads 16 --omp-nthreads 8 --mem-gb 320 \
        --nuisance-regressors 24P --despike -c /custom_confounds \
        --lower-bpf=0.01 --upper-bpf=0.1 \
        --dummy-scans auto \
        --fd-thresh -1

Version:

singularity version 3.7.0+61-g920a6a4-dirty
xcp_d 0.6.1rc1

bids-style file

bids
├── dataset_description.json
└── sub-100610
    ├── anat
    │   ├── sub-100610_desc-aparcaseg_dseg.nii.gz
    │   ├── sub-100610_desc-brain_mask.nii.gz
    │   ├── sub-100610_desc-preproc_T1w.nii.gz
    │   ├── sub-100610_dseg.nii.gz
    │   ├── sub-100610_from-MNI152NLin6Asym_to-T1w_mode-image_xfm.txt
    │   ├── sub-100610_from-T1w_to-MNI152NLin6Asym_mode-image_xfm.txt
    │   ├── sub-100610_space-fsLR_den-32k_hemi-L_pial.surf.gii
    │   ├── sub-100610_space-fsLR_den-32k_hemi-L_smoothwm.surf.gii
    │   ├── sub-100610_space-fsLR_den-32k_hemi-R_pial.surf.gii
    │   ├── sub-100610_space-fsLR_den-32k_hemi-R_smoothwm.surf.gii
    │   ├── sub-100610_space-fsLR_den-91k_curv.dscalar.nii
    │   ├── sub-100610_space-fsLR_den-91k_desc-corrected_thickness.dscalar.nii
    │   ├── sub-100610_space-fsLR_den-91k_desc-smoothed_myelinw.dscalar.nii
    │   ├── sub-100610_space-fsLR_den-91k_myelinw.dscalar.nii
    │   ├── sub-100610_space-fsLR_den-91k_sulc.dscalar.nii
    │   ├── sub-100610_space-fsLR_den-91k_thickness.dscalar.nii
    │   ├── sub-100610_space-MNI152NLin6Asym_res-2_desc-aparcaseg_dseg.nii.gz
    │   ├── sub-100610_space-MNI152NLin6Asym_res-2_desc-brain_mask.nii.gz
    │   ├── sub-100610_space-MNI152NLin6Asym_res-2_desc-preproc_T1w.nii.gz
    │   ├── sub-100610_space-MNI152NLin6Asym_res-2_desc-ribbon_T1w.nii.gz
    │   └── sub-100610_space-MNI152NLin6Asym_res-2_dseg.nii.gz
    └── func
        ├── sub-100610_task-rest_dir-LR_run-1_desc-confounds_timeseries.json
        ├── sub-100610_task-rest_dir-LR_run-1_desc-confounds_timeseries.tsv
        ├── sub-100610_task-rest_dir-LR_run-1_from-MNI152NLin6Asym_to-T1w_mode-image_xfm.txt
        ├── sub-100610_task-rest_dir-LR_run-1_from-T1w_to-MNI152NLin6Asym_mode-image_xfm.txt
        ├── sub-100610_task-rest_dir-LR_run-1_space-fsLR_den-91k_bold.dtseries.json
        ├── sub-100610_task-rest_dir-LR_run-1_space-fsLR_den-91k_bold.dtseries.nii
        ├── sub-100610_task-rest_dir-LR_run-1_space-MNI152NLin6Asym_res-2_boldref.nii.gz
        ├── sub-100610_task-rest_dir-LR_run-1_space-MNI152NLin6Asym_res-2_desc-brain_mask.nii.gz
        ├── sub-100610_task-rest_dir-LR_run-1_space-MNI152NLin6Asym_res-2_desc-preproc_bold.json
        ├── sub-100610_task-rest_dir-LR_run-1_space-MNI152NLin6Asym_res-2_desc-preproc_bold.nii.gz
        ├── sub-100610_task-rest_dir-RL_run-1_desc-confounds_timeseries.json
        ├── sub-100610_task-rest_dir-RL_run-1_desc-confounds_timeseries.tsv
        ├── sub-100610_task-rest_dir-RL_run-1_from-MNI152NLin6Asym_to-T1w_mode-image_xfm.txt
        ├── sub-100610_task-rest_dir-RL_run-1_from-T1w_to-MNI152NLin6Asym_mode-image_xfm.txt
        ├── sub-100610_task-rest_dir-RL_run-1_space-fsLR_den-91k_bold.dtseries.json
        ├── sub-100610_task-rest_dir-RL_run-1_space-fsLR_den-91k_bold.dtseries.nii
        ├── sub-100610_task-rest_dir-RL_run-1_space-MNI152NLin6Asym_res-2_boldref.nii.gz
        ├── sub-100610_task-rest_dir-RL_run-1_space-MNI152NLin6Asym_res-2_desc-brain_mask.nii.gz
        ├── sub-100610_task-rest_dir-RL_run-1_space-MNI152NLin6Asym_res-2_desc-preproc_bold.json
        └── sub-100610_task-rest_dir-RL_run-1_space-MNI152NLin6Asym_res-2_desc-preproc_bold.nii.gz

Relevant log outputs (up to 20 lines):

240408-19:59:51,377 nipype.workflow INFO:
         [Node] Finished "despike3d", elapsed time 112.259767s.
240408-19:59:53,167 nipype.workflow INFO:
         [Job 51] Completed (xcpd_wf.single_subject_100610_wf.nifti_postprocess_1_wf.despike_wf.despike3d).
240408-19:59:53,168 nipype.workflow INFO:
         [MultiProc] Running 1 tasks, and 21 jobs ready. Free memory (GB): 304.00/320.00, Free processors: 8/16.
                     Currently running:
                       * xcpd_wf.single_subject_100610_wf.nifti_postprocess_0_wf.denoise_bold_wf.regress_and_filter_bold
240408-19:59:53,260 nipype.workflow INFO:
         [Node] Setting-up "xcpd_wf.single_subject_100610_wf.nifti_postprocess_1_wf.prepare_confounds_wf.censor_report" in "/wd/xcpd_wf/single_subject_100610_wf/nifti_postprocess_1_wf/prepare_confounds_wf/censor_report".
240408-19:59:53,266 nipype.workflow INFO:
         [Node] Executing "censor_report" <xcp_d.interfaces.plotting.CensoringPlot>
240408-19:59:53,378 nipype.workflow INFO:
         [Node] Finished "censor_report", elapsed time 0.111797s.
240408-19:59:55,171 nipype.workflow INFO:
         [Job 68] Completed (xcpd_wf.single_subject_100610_wf.nifti_postprocess_1_wf.prepare_confounds_wf.censor_report).
240408-19:59:55,172 nipype.workflow INFO:
         [MultiProc] Running 1 tasks, and 21 jobs ready. Free memory (GB): 304.00/320.00, Free processors: 8/16.
                     Currently running:
                       * xcpd_wf.single_subject_100610_wf.nifti_postprocess_0_wf.denoise_bold_wf.regress_and_filter_bold
240408-19:59:55,263 nipype.workflow INFO:
         [Node] Setting-up "xcpd_wf.single_subject_100610_wf.nifti_postprocess_1_wf.denoise_bold_wf.regress_and_filter_bold" in "/wd/xcpd_wf/single_subject_100610_wf/nifti_postprocess_1_wf/denoise_bold_wf/regress_and_filter_bold".
240408-19:59:55,268 nipype.workflow INFO:
         [Node] Executing "regress_and_filter_bold" <xcp_d.interfaces.nilearn.DenoiseNifti>
240408-19:59:57,178 nipype.workflow INFO:
         [MultiProc] Running 2 tasks, and 20 jobs ready. Free memory (GB): 288.00/320.00, Free processors: 0/16.
                     Currently running:
                       * xcpd_wf.single_subject_100610_wf.nifti_postprocess_1_wf.denoise_bold_wf.regress_and_filter_bold
                       * xcpd_wf.single_subject_100610_wf.nifti_postprocess_0_wf.denoise_bold_wf.regress_and_filter_bold
_____

I have tested xcpd verison: 0.3.2, 0.4.1rc2, 0.6.1rc1, same problem. And the 0.0.9 and 0.1.0 can not running step 3rd.

If I using the xcpd 0.7.1rc5, I got this error:

240409-09:28:14,223 nipype.workflow ERROR:
         Node regress_and_filter_bold failed to run on host fat14.
240409-09:28:14,226 nipype.workflow ERROR:
         Saving crash info to /output/sub-100610/log/20240409-092156_bf364ada-05a8-420a-a8b7-01b3b17f5cb4/crash-20240409-092814-xulongzhou-regress_and_filter_bold-c2e85bfc-cef6-46a6-bf7b-897c448753a4.txt
Traceback (most recent call last):
  File "/usr/local/miniconda/lib/python3.10/site-packages/nipype/pipeline/plugins/multiproc.py", line 67, in run_node
    result["result"] = node.run(updatehash=updatehash)
  File "/usr/local/miniconda/lib/python3.10/site-packages/nipype/pipeline/engine/nodes.py", line 527, in run
    result = self._run_interface(execute=True)
  File "/usr/local/miniconda/lib/python3.10/site-packages/nipype/pipeline/engine/nodes.py", line 645, in _run_interface
    return self._run_command(execute)
  File "/usr/local/miniconda/lib/python3.10/site-packages/nipype/pipeline/engine/nodes.py", line 771, in _run_command
    raise NodeExecutionError(msg)
nipype.pipeline.engine.nodes.NodeExecutionError: Exception raised while executing Node regress_and_filter_bold.

Traceback:
        Traceback (most recent call last):
          File "/usr/local/miniconda/lib/python3.10/site-packages/nipype/interfaces/base/core.py", line 397, in run
            runtime = self._run_interface(runtime)
          File "/usr/local/miniconda/lib/python3.10/site-packages/xcp_d/interfaces/nilearn.py", line 349, in _run_interface
            preprocessed_bold_arr = masking.apply_mask(
          File "/usr/local/miniconda/lib/python3.10/site-packages/nilearn/masking.py", line 809, in apply_mask
            return apply_mask_fmri(
          File "/usr/local/miniconda/lib/python3.10/site-packages/nilearn/masking.py", line 839, in apply_mask_fmri
            raise ValueError(
        ValueError: Mask affine:
        [[  -0.69999999    0.            0.           90.        ]
         [   0.            0.69999999    0.         -126.        ]
         [   0.            0.            0.69999999  -72.        ]
         [   0.            0.            0.            1.        ]]
         is different from img affine:
        {imgs_img.affine}


240409-09:28:16,199 nipype.workflow ERROR:
         could not run node: xcp_d_0_7_wf.sub_100610_wf.nifti_postprocess_0_wf.denoise_bold_wf.regress_and_filter_bold
240409-09:28:16,202 nipype.workflow ERROR:
         could not run node: xcp_d_0_7_wf.sub_100610_wf.nifti_postprocess_1_wf.denoise_bold_wf.regress_and_filter_bold
240409-09:28:16,324 nipype.workflow CRITICAL:
         XCP-D failed: 2 raised. Re-raising first.
240409-09:28:17,25 cli ERROR:
         Processing did not finish successfully. Errors occurred while processing data from participants: 100610 (2). Check the HTML reports for details.

I think maybe becaues the brainmask’s resolution 0.7mm, and MNI-fmri data’s resolution is 2mm.

I believe I have identified the issue. The problem lies with the hcp2bids function in xcpd, which generates a misleading file name: “/step_1st_wd/wd_100610/dset_bids/derivatives/hcp/sub-100610/anat/sub-100610_space-MNI152NLin6Asym_res-2_desc-brain_mask.nii.gz”. Despite the file name suggesting a resolution of “res-2”, the actual resolution is 0.7. After replacing it with the correct file to build an fmriprep-style file structure and running xcpd version 0.7.1rc5, the process executed without any errors.

Here is the pipeline using xcpd 0.7.1rc5 to perform postprocessing for HCP minimal preprocessed Data to obtain nifti data for white matter fMRI analysis.

#!/bin/bash
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=2
#SBATCH --mem-per-cpu 20G
#SBATCH -p q_fat_c
#SBATCH --qos=high_c

module load singularity

subj=$1
Path=/ibmgpfs/cuizaixu_lab/xulongzhou/HCP_WMfMRI/xcpd0.7.1rc5
hcpminiprep=/ibmgpfs/cuizaixu_lab/xulongzhou/HCP_WMfMRI/hcp_rest_1_miniprep
# Unzip rest-fMRI-1 data  
for zipfile in /GPFS/PUB/ALL_Family_Subjects/Resting_State_fMRI_1_Preprocessed/${subj}*.zip  
do    
    # Create a directory with the same name as the zip file (excluding the .zip extension)  
    # dirname=$(basename "$zipfile" .zip)  
    # mkdir -p "/ibmgpfs/cuizaixu_lab/xulongzhou/HCP_WMfMRI/hcp_unzip/$dirname"  
      
    # Create a common directory for all unzipped files (if it doesn't already exist)  
    mkdir -p $hcpminiprep
      
    # Unzip the zip file to the corresponding directory without overwriting existing files  
    unzip -n "$zipfile" -d $hcpminiprep
done  
  
# Unzip T1w data  
for zipfile in /GPFS/PUB/ALL_Family_Subjects/Structural_Preprocessed/${subj}*.zip  
do  
    # Unzip the zip file to the specified directory without overwriting existing files  
    unzip -n "$zipfile" -d $hcpminiprep
done

xcpd_op=${Path}/step_1st_hcp2bids
mkdir -p $xcpd_op
xcpd_wp=${Path}/step_1st_wd/wd_$subj
mkdir -p $xcpd_wp
fslic=/ibmgpfs/cuizaixu_lab/xulongzhou/tool/freesurfer
templateflow=/ibmgpfs/cuizaixu_lab/xulongzhou/tool/templateflow

# convert hcp to bids
unset PYTHONPATH
export SINGULARITYENV_TEMPLATEFLOW_HOME=$templateflow
singularity run --cleanenv \
        -B $hcpminiprep:/hcpminiprep \
        -B $xcpd_op:/output \
        -B $xcpd_wp:/work \
        -B $fslic:/fslic \
        -B $templateflow:$templateflow \
        /ibmgpfs/cuizaixu_lab/xulongzhou/apps/singularity_update/xcpd-0.7.1rc5.simg \
        /hcpminiprep /output participant --participant_label ${subj} \
        -w /work --nthreads 2 --mem_gb 40 \
        --fs-license-file /fslic/license.txt \
        --input-type hcp \
        --nuisance-regressors none \
        --disable-bandpass-filter \
        --skip-parcellation \
        --fd-thresh -1 \
        --resource-monitor

# construct bids-style file
bids=${Path}/bids
mkdir -p ${bids}/sub-${subj}
cp -r ${Path}/step_1st_wd/wd_$subj/dset_bids/derivatives/hcp/sub-${subj}/func ${Path}/bids/sub-${subj}/
cp -r ${Path}/step_1st_wd/wd_$subj/dset_bids/derivatives/hcp/sub-${subj}/anat ${Path}/bids/sub-${subj}/

# construct custom confounds file
customCP=/ibmgpfs/cuizaixu_lab/xulongzhou/HCP_WMfMRI/custom_confounds_csf_global_2p
module load MATLAB
filePath=${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-LR_run-1_desc-confounds_timeseries.tsv
savePath=${customCP}/sub-${subj}_task-rest_dir-LR_run-1_desc-confounds_timeseries.tsv
rm -rf ${savePath}
matlab -nodisplay -nosplash -nodesktop -r \
    "extract_columns_by_title('${filePath}', '${savePath}', {'csf'}); exit;"

filePath=${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-RL_run-1_desc-confounds_timeseries.tsv
savePath=${customCP}/sub-${subj}_task-rest_dir-RL_run-1_desc-confounds_timeseries.tsv
rm -rf ${savePath}
matlab -nodisplay -nosplash -nodesktop -r \
    "extract_columns_by_title('${filePath}', '${savePath}', {'csf'}); exit;"

# add the BIDS version in the json file
cp ${Path}/dataset_description.json ${bids}/dataset_description.json

# construct fmriprep-style file structure
cp ${hcpminiprep}/${subj}/MNINonLinear/T1w.nii.gz               ${bids}/sub-${subj}/anat/sub-${subj}_desc-preproc_T1w.nii.gz
cp ${hcpminiprep}/${subj}/MNINonLinear/brainmask_fs.nii.gz      ${bids}/sub-${subj}/anat/sub-${subj}_desc-brain_mask.nii.gz
cp ${hcpminiprep}/${subj}/MNINonLinear/ribbon.nii.gz            ${bids}/sub-${subj}/anat/sub-${subj}_desc-ribbon_T1w.nii.gz
cp ${hcpminiprep}/${subj}/MNINonLinear/wmparc.nii.gz            ${bids}/sub-${subj}/anat/sub-${subj}_desc-wmparc_T1w.nii.gz
cp ${hcpminiprep}/${subj}/MNINonLinear/aparc+aseg.nii.gz        ${bids}/sub-${subj}/anat/sub-${subj}_desc-aparcaseg_dseg.nii.gz

wmparc=${bids}/sub-${subj}/anat/sub-${subj}_desc-wmparc_T1w.nii.gz
brainmask=${bids}/sub-${subj}/anat/sub-${subj}_desc-brain_mask.nii.gz
dseg=${bids}/sub-${subj}/anat/sub-${subj}_dseg.nii
matlab -nodisplay -nosplash -nodesktop -r "convert_wmparc2dseg('$wmparc', '$dseg', '$brainmask'); exit;"
gzip ${dseg}

cp ${hcpminiprep}/${subj}/MNINonLinear/Results/rfMRI_REST1_LR/brainmask_fs.2.nii.gz             ${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-LR_run-1_space-MNI152NLin6Asym_res-2_desc-brain_mask.nii.gz
cp ${hcpminiprep}/${subj}/MNINonLinear/Results/rfMRI_REST1_RL/brainmask_fs.2.nii.gz             ${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-RL_run-1_space-MNI152NLin6Asym_res-2_desc-brain_mask.nii.gz

#cp ${bids}/sub-${subj}/anat/sub-${subj}_from-MNI152NLin6Asym_to-T1w_mode-image_xfm.txt ${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-LR_run-1_from-MNI152NLin6Asym_to-T1w_mode-image_xfm.txt
#cp ${bids}/sub-${subj}/anat/sub-${subj}_from-MNI152NLin6Asym_to-T1w_mode-image_xfm.txt ${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-RL_run-1_from-MNI152NLin6Asym_to-T1w_mode-image_xfm.txt
#cp ${bids}/sub-${subj}/anat/sub-${subj}_from-T1w_to-MNI152NLin6Asym_mode-image_xfm.txt ${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-LR_run-1_from-T1w_to-MNI152NLin6Asym_mode-image_xfm.txt
#cp ${bids}/sub-${subj}/anat/sub-${subj}_from-T1w_to-MNI152NLin6Asym_mode-image_xfm.txt ${bids}/sub-${subj}/func/sub-${subj}_task-rest_dir-RL_run-1_from-T1w_to-MNI152NLin6Asym_mode-image_xfm.txt

#cp ${hcpminiprep}/${subj}/MNINonLinear/T1w_restore.2.nii.gz                             ${bids}/sub-${subj}/anat/sub-${subj}_space-MNI152NLin6Asym_res-2_desc-preproc_T1w.nii.gz
#cp ${hcpminiprep}/${subj}/MNINonLinear/ROIs/wmparc.2.nii.gz                             ${bids}/sub-${subj}/anat/sub-${subj}_space-MNI152NLin6Asym_res-2_desc-brain_mask.nii.gz
#cp ${hcpminiprep}/${subj}/MNINonLinear/Results/rfMRI_REST1_LR/brainmask_fs.2.nii.gz     ${bids}/sub-${subj}/anat/sub-${subj}_space-MNI152NLin6Asym_res-2_desc-wmparc_T1w.nii.gz
#MNIwmparc=${bids}/sub-${subj}/anat/sub-${subj}_space-MNI152NLin6Asym_res-2_desc-wmparc_T1w.nii.gz
#MNIbrainmask=${bids}/sub-${subj}/anat/sub-${subj}_space-MNI152NLin6Asym_res-2_desc-brain_mask.nii.gz
#MNIdseg=${bids}/sub-${subj}/anat/sub-${subj}_space-MNI152NLin6Asym_res-2_dseg.nii
#matlab -nodisplay -nosplash -nodesktop -r "convert_wmparc2dseg('$wmparc', '$dseg', '$brainmask'); exit;"
#gzip ${dseg}

# running xcpd
output=${Path}/step_2nd_24PcsfGlobal
mkdir -p ${output}
wd=${Path}/step_2nd_wd/sub-${subj}
mkdir -p ${wd}
unset PYTHONPATH
export SINGULARITYENV_TEMPLATEFLOW_HOME=$templateflow
singularity run --cleanenv \
        -B $Path/bids:/bids \
        -B $output:/output \
        -B $wd:/wd \
        -B $customCP:/custom_confounds \
        -B $fslic:/fslic \
        -B $templateflow:$templateflow \
        /ibmgpfs/cuizaixu_lab/xulongzhou/apps/singularity_update/xcpd-0.7.1rc5.simg \
        /bids /output participant \
        --participant_label ${subj} --task-id rest \
        --input-type fmriprep \
        --fs-license-file /fslic/license.txt \
        -w /wd --nthreads 2 --mem-gb 40 \
        --nuisance-regressors 24P --despike -c /custom_confounds \
        --lower-bpf=0.01 --upper-bpf=0.1 \
        --smoothing 6 \
        --motion-filter-type lp --band-stop-min 6 \
        --skip-parcellation \
        --fd-thresh -1

construct custom confounds file

function extract_columns_by_title(filePath, savePath, titles)  
    % Read the TSV file  
    tbl = readtable(filePath, 'FileType', 'text', 'Delimiter', '\t');  
      
    % Initialize an empty table to store the extracted columns  
    extractedTbl = table;  
      
    % Iterate through all titles to extract the corresponding columns  
    for i = 1:length(titles)  
        % Find the column with a matching title  
        colIndex = find(strcmp(tbl.Properties.VariableNames, titles{i}));  
          
        % If a matching column is found, add it to the extracted table  
        if ~isempty(colIndex)  
            extractedTbl.(titles{i}) = tbl{:, colIndex};  
        else  
            warning('Column "%s" not found in the TSV file.', titles{i});  
        end  
    end  
      
    % Write the extracted table to a new TSV file  
    writetable(extractedTbl, savePath, 'FileType', 'text', 'Delimiter', '\t');  
      
    % Display the path of the output file  
    fprintf('Extracted columns have been saved to: %s\n', savePath);  
end

convert wmparc dseg data in hcp data to fMRIprep dseg data

function convert_wmparc2dseg(wmparc, dseg, brainmask)

    wmparc_nii = niftiread(wmparc);
    GM1 = wmparc_nii <= 2999 & wmparc_nii >= 1000;%Cerebral-Cortex  
    GM2 = wmparc_nii == 8 | wmparc_nii == 47; %Cerebellum-Cortex
    GM3 = wmparc_nii>=10 & wmparc_nii <= 13; % subcortex
    GM4 = wmparc_nii>=16 & wmparc_nii <= 18; % subcortex
    GM5 = wmparc_nii>=49 & wmparc_nii <=54;  % subcortex
    GM6 = wmparc_nii == 58 | wmparc_nii == 60 | wmparc_nii == 26 | wmparc_nii == 28;% Accumbens-area and VentralDC
    WM1 = wmparc_nii >=3000; % Cerebral-White-Matter 
    WM2 = wmparc_nii == 7 | wmparc_nii == 46; %Cerebellum-White-Matter
    WM3 = wmparc_nii<=255 & wmparc_nii >=251; %CC
    WM4 = wmparc_nii >=77 & wmparc_nii <= 79; %WM
    WM5 = wmparc_nii == 85; % optic chiasm
    WM6 = wmparc_nii == 2 | wmparc_nii == 41; %cerebral white matter
    CSF1 = wmparc_nii == 24; % CSF
    CSF2 = wmparc_nii == 4 | wmparc_nii == 5 |wmparc_nii == 14 | wmparc_nii == 15 | wmparc_nii == 43 | wmparc_nii == 44 | wmparc_nii == 72;% ventricle
    CSF3 = wmparc_nii == 30 | wmparc_nii == 31 | wmparc_nii == 62 | wmparc_nii == 63; 

    dseg_nii = wmparc_nii;
    dseg_nii(GM1 == 1) = 1;
    dseg_nii(GM2 == 1) = 1;
    dseg_nii(GM3 == 1) = 1;
    dseg_nii(GM4 == 1) = 1;
    dseg_nii(GM5 == 1) = 1;
    dseg_nii(GM6 == 1) = 1;
    dseg_nii(WM1 == 1) = 2;
    dseg_nii(WM2 == 1) = 2;
    dseg_nii(WM3 == 1) = 2;
    dseg_nii(WM4 == 1) = 2;
    dseg_nii(WM5 == 1) = 2;
    dseg_nii(WM6 == 1) = 2;
    dseg_nii(CSF1 == 1) = 3;
    dseg_nii(CSF2 == 1) = 3;
    dseg_nii(CSF3 == 1) = 3;
    dseg_nii(dseg_nii >3) = 3;

    brainmask_nii = niftiread(brainmask);
    if size(brainmask_nii, 1) ~= size(dseg_nii, 1)
        error('The affine of brain mask is different form image');
    end
    if size(brainmask_nii, 2) ~= size(dseg_nii, 2)
        error('The affine of brain mask is different form image');
    end
    if size(brainmask_nii, 3) ~= size(dseg_nii, 3)
        error('The affine of brain mask is different form image');
    end
    dseg_nii = dseg_nii + brainmask_nii;
    dseg_nii(dseg_nii == 1) = 4;
    dseg_nii = dseg_nii - brainmask_nii;
    
    % save
    info = niftiinfo(wmparc);
    niftiwrite(dseg_nii, dseg, info);
end