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.

1 Like

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