Hi @mgxd,
Please find below the command I use:
docker run --rm -it -v /mnt/HDD_2To/COMAJ/BIDS/DICOM:/data:ro \
-v /mnt/HDD_2To/COMAJ/BIDS/Nifti:/output nipy/heudiconv:latest \
-d /data/{subject}/*/*.dcm -s 207187_M0_2016-10-11 \
-f /data/BIDS_heuristic_COMAJ.py -b -o /output
Below my dicominfo.tsv:
total_files_till_now | example_dcm_file | series_id | dcm_dir_name | unspecified2 | unspecified3 | dim1 | dim2 | dim3 | dim4 | TR | TE | protocol_name | is_motion_corrected | is_derived | patient_id | study_description | referring_physician_name | series_description | sequence_name | image_type | accession_number | patient_age | patient_sex | date | series_uid |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
11 | MR_1.3.46.670589.11.34037.5.0.4548.2016101113143433305.dcm | 101-WIP SURVEY CLEAR | 101_SURVEY | - | - | 256 | 256 | 11 | 1 | 0.0044959002 | 2.303 | WIP SURVEY CLEAR | False | False | 3T11101613H15 | COMAJ | SURVEY | Not found | (‘ORIGINAL’, ‘PRIMARY’, ‘M_FFE’, ‘M’, ‘FFE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.4548.2016101113141954303 | |
3851 | MR_1.3.46.670589.11.34037.5.0.4548.2016101113252254320.dcm | 201-WIP 3DMULTIGRE SAG STRICT SENSE | 201_3DMULTIGRE_SAG_STRICT | - | - | 256 | 256 | 3840 | 1 | 0.054 | 30.521 | WIP 3DMULTIGRE SAG STRICT SENSE | False | False | 3T11101613H15 | COMAJ | 3DMULTIGRE SAG STRICT | Not found | (‘ORIGINAL’, ‘PRIMARY’, ‘PHASE MAP’, ‘P’, ‘FFE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.4548.2016101113151209318 | |
4011 | MR_1.3.46.670589.11.34037.5.0.4548.2016101113370035006.dcm | 301-WIP s3DT1 ISO 1mm HR SENSE | 301_s3DT1_ISO_1mm_HR | - | - | 256 | 256 | 160 | 1 | 0.0098773003 | 4.595 | WIP s3DT1 ISO 1mm HR SENSE | False | False | 3T11101613H15 | COMAJ | s3DT1 ISO 1mm HR | Not found | (‘ORIGINAL’, ‘PRIMARY’, ‘M_FFE’, ‘M’, ‘FFE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.4548.2016101113252474529 | |
4034 | MR_1.3.46.670589.11.34037.5.0.5740.2016101113370804000.dcm | 302-ax | 302_ax | - | - | 256 | 256 | 23 | 1 | 0.0098773003 | 4.595 | ax | False | False | 3T11101613H15 | COMAJ | ax | (‘ORIGINAL’, ‘PRIMARY’, ‘PROJECTION IMAGE’, ‘M’, ‘FFE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.2580.2016101113370746000 | ||
4057 | MR_1.3.46.670589.11.34037.5.0.7788.2016101113371042000.dcm | 303-coro | 303_coro | - | - | 256 | 256 | 23 | 1 | 0.0098773003 | 4.595 | coro | False | False | 3T11101613H15 | COMAJ | coro | (‘ORIGINAL’, ‘PRIMARY’, ‘PROJECTION IMAGE’, ‘M’, ‘FFE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.9836.2016101113370988000 | ||
4080 | MR_1.3.46.670589.11.34037.5.0.9376.2016101113371261000.dcm | 304-sag | 304_sag | - | - | 256 | 256 | 23 | 1 | 0.0098773003 | 4.595 | sag | False | False | 3T11101613H15 | COMAJ | sag | (‘ORIGINAL’, ‘PRIMARY’, ‘PROJECTION IMAGE’, ‘M’, ‘FFE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.8664.2016101113371205000 | ||
4111 | MR_1.3.46.670589.11.34037.5.0.4548.2016101113402658168.dcm | 401-WIP T2 * CLEAR | 401_T2_ETOILE | - | - | 256 | 256 | 31 | 1 | 0.9140009155 | 16.12 | WIP T2 * CLEAR | False | False | 3T11101613H15 | COMAJ | T2 * | Not found | (‘ORIGINAL’, ‘PRIMARY’, ‘M_FFE’, ‘M’, ‘FFE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.4548.2016101113370239049 | |
4141 | MR_1.3.46.670589.11.34037.5.0.4548.2016101113412429201.dcm | 501-WIP TSE T2 5mm CLEAR | 501_TSE_T2_5mm | - | - | 560 | 560 | 30 | 1 | 2.8172145996 | 80 | WIP TSE T2 5mm CLEAR | False | False | 3T11101613H15 | COMAJ | TSE T2 5mm | Not found | (‘ORIGINAL’, ‘PRIMARY’, ‘M_SE’, ‘M’, ‘SE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.4548.2016101113402920199 | |
4185 | MR_1.3.46.670589.11.34037.5.0.4548.2016101113441543233.dcm | 601-WIP FLAIR_3 mm SENSE | 601_FLAIR_3_mm | - | - | 560 | 560 | 44 | 1 | 11 | 125 | WIP FLAIR_3 mm SENSE | False | False | 3T11101613H15 | COMAJ | FLAIR_3 mm | Not found | (‘ORIGINAL’, ‘PRIMARY’, ‘M_IR’, ‘M’, ‘IR’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.4548.2016101113421765231 | |
5145 | MR_1.3.46.670589.11.34037.5.0.4548.2016101113543018279.dcm | 701-WIP DTI_15dir serie 1 SENSE | 701_DTI_15dir_serie_1 | - | - | 128 | 128 | 960 | 1 | 12 | 56 | WIP DTI_15dir serie 1 SENSE | False | False | 3T11101613H15 | COMAJ | DTI_15dir serie 1 | Not found | (‘ORIGINAL’, ‘PRIMARY’, ‘M_SE’, ‘M’, ‘SE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.4548.2016101113492972277 | |
5205 | MR_1.3.46.670589.11.34037.5.0.6520.2016101115153538035.dcm | 702-isoTRACE | 702_isoTRACE | - | - | 128 | 128 | 60 | 1 | 12 | 56 | isoTRACE | False | False | 3T11101613H15 | COMAJ | isoTRACE | (‘ORIGINAL’, ‘PRIMARY’, ‘M_SE’, ‘M’, ‘SE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.6520.2016101115153521000 | ||
5685 | MR_1.3.46.670589.11.34037.5.0.4548.2016101113570730241.dcm | 801-WIP DTI CORRECTION SENSE | 801_DTI_CORRECTION | - | - | 128 | 128 | 480 | 1 | 12 | 56 | WIP DTI CORRECTION SENSE | False | False | 3T11101613H15 | COMAJ | DTI CORRECTION | Not found | (‘ORIGINAL’, ‘PRIMARY’, ‘M_SE’, ‘M’, ‘SE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.4548.2016101113543280731 | |
6645 | MR_1.3.46.670589.11.34037.5.0.4548.2016101114013884723.dcm | 901-WIP DTI_15dir serie 2 SENSE | 901_DTI_15dir_serie_2 | - | - | 128 | 128 | 960 | 1 | 12 | 56 | WIP DTI_15dir serie 2 SENSE | False | False | 3T11101613H15 | COMAJ | DTI_15dir serie 2 | Not found | (‘ORIGINAL’, ‘PRIMARY’, ‘M_SE’, ‘M’, ‘SE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.4548.2016101113570999626 | |
6705 | MR_1.3.46.670589.11.34037.5.0.4548.2016101114070249687.dcm | 1001-WIP B0 map CLEAR | 1001_B0_map | - | - | 128 | 128 | 60 | 1 | 0.5899979858 | 3.947 | WIP B0 map CLEAR | False | False | 3T11101613H15 | COMAJ | B0 map | Not found | (‘ORIGINAL’, ‘PRIMARY’, ‘M_FFE’, ‘M’, ‘FFE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.4548.2016101114014381683 | |
16705 | MR_1.3.46.670589.11.34037.5.0.4548.2016101114075631749.dcm | 1101-WIP FE_EPI 64x64 resting state SENSE | 1101_FE_EPI_64x64_resting_state | - | - | 64 | 64 | 10000 | 1 | 2.4 | 30 | WIP FE_EPI 64x64 resting state SENSE | False | False | 3T11101613H15 | COMAJ | FE_EPI 64x64 resting state | Not found | (‘ORIGINAL’, ‘PRIMARY’, ‘M_FFE’, ‘M’, ‘FFE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.4548.2016101114071031747 | |
16745 | MR_1.3.46.670589.11.34037.5.0.4548.2016101114190599751.dcm | 1201-WIP SE_FMRI_CORR_PA SENSE | 1201_SE_FMRI_CORR_PA | - | - | 64 | 64 | 40 | 1 | 7.06 | 58 | WIP SE_FMRI_CORR_PA SENSE | False | False | 3T11101613H15 | COMAJ | SE_FMRI_CORR_PA | Not found | (‘ORIGINAL’, ‘PRIMARY’, ‘M_SE’, ‘M’, ‘SE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.4548.2016101114175419749 | |
16785 | MR_1.3.46.670589.11.34037.5.0.4548.2016101114201142793.dcm | 1301-WIP SE_FMRI_CORR_AP SENSE | 1301_SE_FMRI_CORR_AP | - | - | 64 | 64 | 40 | 1 | 7.06 | 58 | WIP SE_FMRI_CORR_AP SENSE | False | False | 3T11101613H15 | COMAJ | SE_FMRI_CORR_AP | Not found | (‘ORIGINAL’, ‘PRIMARY’, ‘M_SE’, ‘M’, ‘SE’) | 3T11101613H15 | 066Y | F | 20161011 | 1.3.46.670589.11.34037.5.0.4548.2016101114190634791 |
And finally the heuristic:
import os
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
"""
t1 = create_key('sub-{subject}/anat/sub-{subject}_T1w')
t2 = create_key('sub-{subject}/anat/sub-{subject}_T2w')
rest = create_key('sub-{subject}/func/sub-{subject}_task-rest_run-{item:02d}_bold')
rest_corrpa = create_key('sub-{subject}/func/sub-{subject}_task-rest_run-{item:02d}_corrpa')
rest_corrap = create_key('sub-{subject}/func/sub-{subject}_task-rest_run-{item:02d}_corrap')
dwi = create_key('sub-{subject}/dwi/sub-{subject}_run-{item:02d}_dwi')
dwi_corr = create_key('sub-{subject}/dwi/sub-{subject}_run-{item:02d}_corr')
fmap = create_key('sub-{subject}/fmap/sub-{subject}_dir-{dir}_run-{item:02d}_epi')
info = {t1:[], t2:[],
rest:[], dwi:[],
rest_corrpa:[], rest_corrap:[], dwi_corr:[],
fmap:[]}
for idx, s in enumerate(seqinfo):
# T1 and T2 scans
if (s.dim3 == 160) and (s.dim4 == 1) and ('s3DT1 ISO 1mm' in s.protocol_name):
info[t1] = [s.series_id]
if (s.dim3 == 44) and (s.dim4 == 1) and ('FLAIR_3 mm SENSE' in s.protocol_name):
info[t2] = [s.series_id]
# diffusion scans
if ('DTI' in s.protocol_name):
key = None
if (s.dim3 == 960):
key = dwi
elif (s.dim3 == 480) and ('DTI CORRECTION' in s.series_description):
key = dwi_corr
if key:
info[key].append({'item': s.series_id})
# functional scans
if (s.dim3 == 10000) and ('EPI 64x64 resting state' in s.protocol_name):
info[rest].append({'item': s.series_id})
if (s.dim3 == 40) and ('FMRI_CORR_PA' in s.protocol_name):
info[rest_corrpa].append({'item': s.series_id})
if (s.dim3 == 40) and ('FMRI_CORR_AP' in s.protocol_name):
info[rest_corrap].append({'item': s.series_id})
if (s.dim3 == 60) and ('B0 map' in s.protocol_name):
dirtype = s.protocol_name.split('_')[-1]
info[fmap].append({'item': s.series_id, 'dir': dirtype})
# You can even put checks in place for your protocol
msg = []
if len(info[t1]) != 1: msg.append('Missing correct number of t1 runs')
if len(info[t2]) != 1: msg.append('Missing correct number of t2 runs')
if len(info[dwi]) != 2: msg.append('Missing correct number of dwi runs')
if len(info[dwi_corr]) != 1: msg.append('Missing correct number of dwi_corr runs')
if len(info[rest]) != 1: msg.append('Missing correct number of resting runs')
if len(info[rest_corrpa]) != 1: msg.append('Missing correct number of rest_corrpa runs')
if len(info[rest_corrap]) != 1: msg.append('Missing correct number of rest_corrap runs')
if msg:
raise ValueError('\n'.join(msg))
return info
Thanks !