Heudiconv: How to turn subject IDs into consecutive zero-padded numbers as required by BIDS?

Hello everyone,

I am using heudiconv to turn my MRI data into the BIDS format. Everything’s running smoothly (great tool btw, thanks!) however one small problem remains that I was not able to solve, yet:

If I am not mistaking, the BIDS format requires to have subject IDs in a consecutive numbering scheme, i.e., sub-01, sub-02, sub-03 etc. I was not able to achieve this yet. It only works, when I use the original study IDs, e.g., sub-41003

This is my heudiconv command:

heudiconv -d ${INPUT_PATH} -s ${SUB} -ss ${SES_PAD} -f ${HEURISTIC_PATH} -c dcm2niix -o ${OUTPUT_PATH} -b --overwrite

with

SES=1 # or SES=2, as this is run inside a loop over two sessions
SES_PAD=$(printf "%02d\n" $SES) # get the session number with zero padding
INPUT_PATH=$HOME/projectname/rawdata/mri/projectname_{subject}_projectname_{subject}_${SES}*/*/*/*IMA
HEURISTIC_PATH="$HOME/projectname/code/heudiconv_projectname.py" # path to your heuristic file

The code above is part of bash-script that loops over two sessions of multiple subjects and sends the heudiconv command to a node on our cluster. The {subject} input is a unique subject ID (e.g., 41003).

My heuristic file looks like this:

# paths in BIDS format
anat = create_key('sub-{subject}/{session}/anat/sub-{subject}_{session}_acq-{acq}_T1w')
rest = create_key('sub-{subject}/{session}/func/sub-{subject}_{session}_task-rest_acq-{acq}_run-{run_rest}_bold')
	task_prenorm = create_key('sub-{subject}/{session}/func/sub-{subject}_{session}_task-projectname_acq-prenorm_run-{item:02d}_bold')
task_nonorm = create_key('sub-{subject}/{session}/func/sub-{subject}_{session}_task-projectname_acq-nonorm_run-{item:02d}_bold')
fmap_topup = create_key('sub-{subject}/{session}/fmap/sub-{subject}_{session}_acq-{acq}_dir-{dir}_epi')
fmap_mag = create_key('sub-{subject}/{session}/fmap/sub-{subject}_{session}_acq-{acq}_magnitude')
fmap_phase = create_key('sub-{subject}/{session}/fmap/sub-{subject}_{session}_acq-{acq}_phasediff')

info = {anat: [], rest: [], task_prenorm: [], task_nonorm: [], fmap_topup: [], fmap_mag: [], fmap_phase: []}
last_run = len(seqinfo)

for s in seqinfo:

	if 'NORM' in s.image_type:
		acq = 'prenorm'
	else:	
		acq = 'nonorm'

	if 't1' in s.series_description:
		info[anat].append({'item': s.series_id, 'acq': acq})
	if ('FM_' in s.series_description):
		info[fmap_topup].append({'item': s.series_id, 'acq': acq, 'dir': 'AP'})
	if ('FMInv_' in s.series_description):
		info[fmap_topup].append({'item': s.series_id, 'acq': acq, 'dir': 'PA'})	
	if ('gre' in s.series_description) and ('M' in s.image_type):
		  info[fmap_mag].append({'item': s.series_id, 'acq': acq})
	if ('gre' in s.series_description) and ('P' in s.image_type):
		  info[fmap_phase].append({'item': s.series_id, 'acq': acq})
	if ('Rest_Pre' in s.series_description):
		info[rest].append({'item': s.series_id, 'acq': acq, 'run_rest': 'pre'})	
	if ('Rest_Post' in s.series_description):
		info[rest].append({'item': s.series_id, 'acq': acq, 'run_rest': 'post'})
	if ('Run' in s.series_description) and ('nonorm' in acq):
		info[task_nonorm].append({'item': s.series_id})
	if ('Run' in s.series_description) and ('prenorm' in acq):
		info[task_prenorm].append({'item': s.series_id})

What I have tried so far:

  • Use the subindex handle of the heuristic file. However, this only appears to work when multiple subjects are passed into one call to heudiconv. I need to loop over all subjects outside the call to heudiconv, though.
  • Pass a zero-padded number into the heudiconv command. However, this does not work since the subject ID is the unique identifier for the corresponding dicom files in the input path.

I would really appreciate your help! Please let me know if I forgot to mention any important information. Thanks a lot in advance! Best, Lennart

BIDS does not require this. The subject labels need only be alphanumeric. If they are numeric, it’s recommended to zero-pad to ensure a consistent length and facilitate lexical sorting, but this is not a requirement.

From the spec (Section 5):

Hi Chris, thanks for your quick response! Alright, so I wouldn’t necessarily need to change my subject IDs to make them BIDS-compatible. But given that I would want to rename my subject IDs into consecutive zero-padded numbers, how would I do this? Thanks!

Unfortunately, I don’t know anything about heudiconv. Hopefully someone else can chime in.

Hi @lennart

You should be able to hack this use-case with the --anon-cmd flag and a python script. You could set up a script like so:

#!/usr/bin/env python
import sys

subj_map = {
   '41003': '01',
   '42005': '02':
   ... # etc
}

sid = sys.argv[-1]
if sid in subj_map:
    print(subj_map[sid])

and then use it with --anon-cmd /path/to/python/script. I just commented on this feature in a similar issue on our repo

3 Likes

Hi @mgxd,

great, this seems like a good solution! Thank you very much!
I will try and let you if it works for me.

Just to follow up on this:

I now tried the solution proposed by @mgxd and it worked perfectly!

Thanks again!

1 Like