Getting study level bids files (e.g., participants.tsv) in the correct place

I’m stuck with something and don’t want to start reinventing the wheel. Could you help?

I am iterating through the scanning sessions in our DICOM store and calling heudiconv for each. I’d like BIDS output.

If I include the subject and session in “outdir” then the func etc directories end up where I want them (e.g., bids/sub-ICN1/sess-2/func). But the study-level bids files then end up in those same session directories (e.g., bids/sub-ICN1/sess-2/dataset_description.json).
But, if I omit the subject and session then the func ends up at the study level.

I’ve tried various ways of implementing - dicom_dir_template and subjs/session below; or using files and infotoids. But I never get right mix. What have I broken?

I’m calling from python, hope that’s allowed.
Thanks for the great tool.
All the best, Rhodri

from heudiconv import bids
from heudiconv.main import workflow
from os import path

import glob

# Path to scan

# Each subject
allsubjdicom = glob.glob(path.join(dcmpth,'*_RC_FOUNDCOG'))
for subjdicom in allsubjdicom:
    # get pithy sub from DICOM participant name
    flds = path.basename(subjdicom).split('_') 
    sub = '_'.join(flds[:2]) 

    # Each session for this subject
    allsessdicom = glob.glob(subjdicom + '/*')
    allsessdicom.sort() # sessions in ascending order by time

    for ses, sessdicom in enumerate(allsessdicom, start = 1):
        print(f'Working on sub-{sub} ses-{ses}')


I think culprit could be in that custom heuristic

1 Like

In here?

import os
from os import path

def create_key(template, outtype=('nii.gz',), annotation_classes=None):
    if template is None or not template:
        raise ValueError('Template must be a valid format string')
    return template, outtype, annotation_classes
def infotodict(seqinfo):
    """Heuristic evaluator for determining which runs belong where
    allowed template fields - follow python string module:
    item: index within category
    subject: participant id
    seqitem: run number during scanning
    subindex: sub index within group
    anat = create_key('anat/sub-{subject}_{session}_run-00{item:01d}_T1w')
    func_video = create_key('func/sub-{subject}_{session}_dir-AP_task-videos_run-00{item:01d}_bold')
    func_pictures = create_key('func/sub-{subject}_{session}_dir-AP_task-pictures_run-00{item:01d}_bold')
    func_rest5 = create_key('func/sub-{subject}_{session}_dir-AP_task-rest5_run-00{item:01d}_bold')
    func_rest10 = create_key('func/sub-{subject}_{session}_dir-AP_task-rest10_run-00{item:01d}_bold')
    dwi = create_key('dwi/sub-{subject}_{session}_dir-{dir}_run-{item}_dwi')
    fmap = create_key('fmap/sub-{subject}_{session}_dir-{dir}_run-{item}_epi')
    info = {anat: [], func_video: [], func_pictures: [], func_rest5: [], func_rest10: [], dwi: [], fmap:[] }
    for idx, s in enumerate(seqinfo):
        if 't2_tse_tra_p3_noisereduction' in s.protocol_name:
        if (s.dim1 == 64) and (s.dim2 == 64) and ('cmrr_mbep2d_bold_videos_AP' in s.protocol_name):
        if (s.dim1 == 64) and (s.dim2 == 64) and ('cmrr_mbep2d_bold_Pictures_AP' in s.protocol_name):
        if (s.dim1 == 64) and (s.dim2 == 64) and ('cmrr_mbep2d_bold_Resting_10' in s.protocol_name):
        if (s.dim1 == 64) and (s.dim2 == 64) and ('cmrr_mbep2d_bold_Resting_5' in s.protocol_name):
        if (s.dim1 == 96) and (s.dim2 == 96) and ('cmrr_mbep2d_diff_AP_mb4_norm_pulse1.5x' in s.protocol_name):
            info[dwi].append({'item': s.series_id, 'dir':'AP'})
        if (s.dim1 == 96) and (s.dim2 == 96) and ('cmrr_mbep2d_diff_PA_mb4_norm_pulse1.5x' in s.protocol_name):
            info[dwi].append({'item': s.series_id, 'dir':'PA'})
        if (s.dim1 == 64) and (s.dim2 == 64) and ('cmrr_mbep2d_se_AP' in s.protocol_name):
            info[fmap].append({'item': s.series_id, 'dir':'AP'})
        if (s.dim1 == 64) and (s.dim2 == 64) and ('cmrr_mbep2d_se_PA' in s.protocol_name):
            info[fmap].append({'item': s.series_id, 'dir':'PA'})

    print('*** infotodict')

    return info

# # Get a numeric subject ID for BIDS format from list of DICOM file names
# def infotoids(seqinfos, outdir):
#     # Use the sub and ses labels as given in the output path
#     fp = outdir.split(path.sep)
#     if fp[-1][:4] == 'ses-':
#         ses=fp[-1][4:]
#     if fp[-2][:4] == 'sub-':
#         sub=fp[-2][4:]
#     return({'subject':sub, 'session':ses, 'locator':outdir})

P.S. heudiconv version 0.10.0

SOLVED: I’m sorry I realise now it was an error in my create_key commands, I needed

1 Like