Qsi reconstruction writes to work dir but not derivatives

Summary of what happened:

My colleague ran qsiprep successfully, but qsirecon is not writing most of its output to derivatives.

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

export SIF=${SIF:-/contrib/singularity/shared/neuroimaging}

# Which container do you want to run
export APP=${SIF}/qsiprep_v0.21.2.sif

# Define variables to point to the directories you want to work in
# bids and derivatives directories are siblings in this scheme under a directory referred to as MRIS
export MRIS=/groups/akielar/analysis3
export DATA=${MRIS}/nifti

# Define the output directories used by this app:
# The qsirecon dir will be created under this dir:
export APP_DERIV_DIR=${MRIS}/derivatives
# This is the location of the qsiprep output
export APP_PREP_DERIV_DIR=${MRIS}/derivatives/qsiprep
# If you've run fmriprep, you may have a freesurfer directory. 
# qsirecon can use that.
export FREESURFER_DIR=${MRIS}/derivatives/fmriprep/sourcedata/freesurfer
# define a unique work dir to separate recon from prep work
export WORK_DIR=${MRIS}/qsirecon_work

export RECON_SPEC=pyafq_tractometry

# Just to be safe, create the derivatives subdirectory if it does not exist.
if [ ! -d ${APP_DERIV_DIR} ]; then 
    mkdir -p ${APP_DERIV_DIR}
fi

# Just to be safe, create the work directory if it does not exist. 
# This should be outside the bids input dir.
if [ ! -d ${WORK_DIR} ]; then 
    mkdir ${WORK_DIR}
fi


##############

apptainer run --cleanenv \
--bind ${DATA}:/data:ro \
--bind ${APP_PREP_DERIV_DIR}:/qsiprep-output:ro \
--bind ${APP_DERIV_DIR}:/out \
--bind ${WORK_DIR}:/work \
${APP} /data /out participant \
--participant_label ${Subject} \
--recon-input /qsiprep-output \
--recon-spec ${RECON_SPEC} \
--stop-on-first-crash \
--output-resolution 1.3 -w /work -v -v  \
--n-cpus 16 --omp-nthreads 15 \
--skip-odf-reports --recon-only \
--fs-license-file ${HOME}/license.txt \
--freesurfer_input ${FREESURFER_DIR}

Version:

qsiprep v0.21.2.dev0+g8fd846e.d20240425

Environment:

HPC SLURM Apptainer

Data formatted according to a validatable standard? Please provide the output of the validator:

Yes, the data validated and successfully ran through qsiprep before trying qsirecon

Relevant SLURM log outputs (up to 20 lines):

         [Node] Finished "run_afq", elapsed time 6011.803694s.

IMPORTANT:cli:QSIrecon finished without errors
/opt/conda/envs/qsiprep/lib/python3.10/site-packages/joblib/externals/loky/backend/resource_tracker.py:314: UserWarning: resource_tracker: There appear to be 22 leaked folder objects to clean up at shutdown
  warnings.warn(
INFO:cli:No additional workflows to run.

Contents of derivatives/qsirecon directory:

|-- dataset_description.json
|-- dwiqc.json
|-- logs
|   |-- CITATION.html
|   |-- CITATION.md
|   `-- CITATION.tex
|-- sub-230
|   `-- figures
`-- sub-230.html

Contents of qsirecon_work/qsirecon_wf/sub-230_pyafq_tractometry/sub_230_dir_AP_space_T1w_desc_preproc_recon_wf/pyafq_tractometry/run_afq appear to have the expected directory structure, tracts, html reports etc.

I’ve run qsirecon myself many times and never had a problem with the outputs ending up in derivatives where they belong. I’m not seeing the problem here. Any insights would be appreciated!

-Dianne


Hi @Dianne_Patterson, are there any other directories at the same level as qsirecon? The outputs starting in 0.21 get a separate directory for each pipeline, so there should be a separate directory for the AFQ results at the same level as qsirecon

Hi Matt,

Thank you for your quick reply. I did not see any other sibling directories under derivatives where the data might have been, but I had a lot of experiments in that folder, so I want to clean up and retry…obviously this is taking many hours ; (

I can indeed confirm and reproduce the behavior I reported earlier:

qsiprep in version 21.2 runs correctly (but takes 6.5 hours instead of the 4.0 hours that version 19 took for the same data).

qsirecon pyafq_tractometry does not create any additional directories under derivatives, though it adds some minimal structure to derivatives/qsirecon:

$ pwd
/groups/dkp/Batch/mri_practice/derivatives/qsirecon
$ tree
.
|-- dataset_description.json
|-- dwiqc.json
|-- logs
|   |-- CITATION.html
|   |-- CITATION.md
|   `-- CITATION.tex
|-- sub-CAM003
|   `-- figures
`-- sub-CAM003.html

3 directories, 6 files

It creates much (all?) of the expected output in the work directory:

/groups/dkp/Batch/mri_practice/qsirecon_work/qsirecon_wf contains 40 directories, 425 files including the expected HTML, tract files dwi output etc in a subdirectory called sub-CAM003_pyafq_tractometry, which also includes a lot of typical work stuff like pickle files and intermediate directories.

The SLURM log looks really promising:

INFO:AFQ:Loading Stateful Tractogram...
INFO:AFQ:Generating colorful lines from tractography...
INFO:AFQ:Loading Stateful Tractogram...
INFO:AFQ:Generating colorful lines from tractography...
INFO:AFQ:Time taken for export all: 7220.03827381134
240430-14:25:49,406 nipype.workflow INFO:
         [Node] Finished "run_afq", elapsed time 7220.141795s.
INFO:nipype.workflow:[Node] Finished "run_afq", elapsed time 7220.141795s.
240430-14:25:50,525 nipype.workflow INFO:
         [Job 11] Completed (qsirecon_wf.sub-CAM003_pyafq_tractometry.sub_CAM003_ses_01brain_dir_AP_space_T1w_desc_preproc_recon_wf.pyafq_tractometry.run_afq).
INFO:nipype.workflow:[Job 11] Completed (qsirecon_wf.sub-CAM003_pyafq_tractometry.sub_CAM003_ses_01brain_dir_AP_space_T1w_desc_preproc_recon_wf.pyafq_tractometry.run_afq).
240430-14:25:50,527 nipype.workflow INFO:
         [MultiProc] Running 0 tasks, and 1 jobs ready. Free memory (GB): 56.60/56.60, Free processors: 16/16.
INFO:nipype.workflow:[MultiProc] Running 0 tasks, and 1 jobs ready. Free memory (GB): 56.60/56.60, Free processors: 16/16.
240430-14:25:50,690 nipype.workflow INFO:
         [Node] Setting-up "qsirecon_wf.sub-CAM003_pyafq_tractometry.sub_CAM003_ses_01brain_dir_AP_space_T1w_desc_preproc_recon_wf.pyafq_tractometry.ds_pyafq_tractometry" in "/work/qsirecon_wf/sub-CAM003_pyafq_tractometry/sub_CAM003_ses_01brain_dir_AP_space_T1w_desc_preproc_recon_wf/pyafq_tractometry/ds_pyafq_tractometry".
INFO:nipype.workflow:[Node] Setting-up "qsirecon_wf.sub-CAM003_pyafq_tractometry.sub_CAM003_ses_01brain_dir_AP_space_T1w_desc_preproc_recon_wf.pyafq_tractometry.ds_pyafq_tractometry" in "/work/qsirecon_wf/sub-CAM003_pyafq_tractometry/sub_CAM003_ses_01brain_dir_AP_space_T1w_desc_preproc_recon_wf/pyafq_tractometry/ds_pyafq_tractometry".
240430-14:25:50,736 nipype.workflow INFO:
         [Node] Executing "ds_pyafq_tractometry" <qsiprep.interfaces.bids.ReconDerivativesDataSink>
INFO:nipype.workflow:[Node] Executing "ds_pyafq_tractometry" <qsiprep.interfaces.bids.ReconDerivativesDataSink>
240430-14:25:50,760 nipype.workflow INFO:
         [Node] Finished "ds_pyafq_tractometry", elapsed time 0.000366s.
INFO:nipype.workflow:[Node] Finished "ds_pyafq_tractometry", elapsed time 0.000366s.
240430-14:25:50,777 nipype.workflow INFO:
         [Job 12] Completed (qsirecon_wf.sub-CAM003_pyafq_tractometry.sub_CAM003_ses_01brain_dir_AP_space_T1w_desc_preproc_recon_wf.pyafq_tractometry.ds_pyafq_tractometry).
INFO:nipype.workflow:[Job 12] Completed (qsirecon_wf.sub-CAM003_pyafq_tractometry.sub_CAM003_ses_01brain_dir_AP_space_T1w_desc_preproc_recon_wf.pyafq_tractometry.ds_pyafq_tractometry).
IMPORTANT:cli:QSIrecon finished without errors

But my colleague pointed out the following complaint:

`UserWarning: resource_tracker: There appear to be 22 leaked folder objects to clean up at shutdown`
/opt/conda/envs/qsiprep/lib/python3.10/site-packages/joblib/externals/loky/backend/resource_tracker.py:314: UserWarning: resource_tracker: There appear to be 22 leaked folder objects to clean up at shutdown
  warnings.warn(
INFO:cli:No additional workflows to run.
Detailed performance metrics for this job will be available at https://metrics.hpc.arizona.edu/#job_viewer?action=show&realm=SUPREMM&resource_id=4&local_job_id=1944281 by 8am on 2024/05/01.

I have everything, if there’s something else you want for troubleshooting, and I’m happy to test an alternate approach. Thanks for all your work on improving qsiprep, I love the idea of adding more directory structure to the recon output, despite the bumps in the road.

Thank you,

Dianne

One more data point:

I tried this (because I know it is fast):

export RECON_SPEC=reorient_fslstd

and it worked as you predicted:

$ tree derivatives/qsirecon-FSL
derivatives/qsirecon-FSL
`-- sub-CAM003
    `-- ses-01brain
        `-- dwi
            |-- sub-CAM003_ses-01brain_dir-AP_space-T1w_desc-preproc_dwi.bval
            |-- sub-CAM003_ses-01brain_dir-AP_space-T1w_desc-preproc_dwi.bvec
            |-- sub-CAM003_ses-01brain_dir-AP_space-T1w_desc-preproc_dwimap.nii.gz
            `-- sub-CAM003_ses-01brain_dir-AP_space-T1w_desc-preproc_dwi.nii.gz

3 directories, 4 files

So, maybe pyAFQ is a special case.

This was indeed a bug ([FIX] PyAFQ was not being written to derivatives by mattcieslak · Pull Request #738 · PennLINC/qsiprep · GitHub) and fixed in the current unstable tag. I’m not sure what’s going on with those leaked folder objects though

The “leaked folder objects” warning is probably harmless and appears because pyAFQ uses joblib with the loky backend to parallelize some operations. I believe that loky uses some temporary folders for serialization of objects and those sometimes don’t get cleaned up immediately for various reasons. But, like I said, harmless and unrelated to the main topic here.

1 Like