Concatenate DICOMs with different protocol names into a single NIfTI with heudiconv

Hi all,

I’m using heudiconv 0.13.0 to convert dicoms to nifti following the BIDS format. I want to concatenate dicoms with different protocol names into a single nifti file: How can I do it?

To be clearer, I have diffusion data for b=1000 and b=25000, which have different protocol names from each other. The idea is to have them together in a nifti file like *_acq_AP_dwi.nii.gz . I tried running heudiconv providing a heuristic that filters by the common info they share, but I failed. It always converts the last one, missing the first. I also attempted to use the --dcmconfg flag and provided a dcmconfig.json containing: {“merge_imgs”: true} , but it didn’t give me the desired output either.

In the last scenario, I also tried dcm2bids (version: 2.1.7), but instead of producing a unique nifti file, it automatically outputs two runs (e.g. *_acq_AP_run-x_dwi.nii.gz).

Here is the heuristic.py I used for heudiconv (b=1000 and b=2500 have in common “cmrr_mbep2d_diff_mb2” in the protocol name):

import os

# create a function called create_key

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):
    # Section 1: These key definitions should be revised by the user
    ###################################################################
    # For each sequence, define a variable using the create_key function:
    # variable = create_key(output_directory_path_and_name).
    #
    # "data" creates sequential numbers which can be for naming sequences.
    # This is especially valuable if you run the same sequence multiple times at the scanner.
    #data = create_key('run-{item:03d}')
    t1w = create_key('sub-{subject}/{session}/anat/sub-{subject}_{session}_T1w')
    dwirev = create_key('sub-{subject}/{session}/dwi/sub-{subject}_{session}_acq-PA_dwi')
    dwi = create_key('sub-{subject}/{session}/dwi/sub-{subject}_{session}_acq-AP_dwi')

    # Section 1b: This data dictionary (below) should be revised by the user.
    # It uses the variables defines above as keys.
    ##########################################################################
    # Enter a key in the dictionary for each key you created above in section 1.
    info = {t1w: [], dwirev: [], dwi: []}
    #last_run = len(seqinfo)

    # Section 2: These criteria should be revised by user.
    ##########################################################
    # Define test criteria to check that each dicom sequence is correct
    # seqinfo (s) refers to information in dicominfo.tsv. Consult that file for
    # available criteria.
    # Here we use two types of criteria:
    # 1) An equivalent field "==" (e.g., good for checking dimensions)
    # 2) A field that includes a string (e.g., 'mprage' in s.protocol_name)
    for idx, s in enumerate(seqinfo):
        if ('MEMPRAGE' in s.protocol_name) and (s.dim3 == 176 or s.dim3 == 132):
            info[t1w].append(s.series_id)
        if ('PEreverse' in s.protocol_name) and (s.dim4 == 1) and ('SBRef' not in s.protocol_name):
            info[dwirev].append(s.series_id)
        if ('cmrr_mbep2d_diff_mb2' in s.protocol_name) and (s.dim1 == 128) and ('SBref' not in s.protocol_name) and ('PEreverse' not in s.protocol_name):
            info[dwi].append(s.series_id)

    return info

And the dcmconfig.json I used for dcm2bids:

{
  "merge_imgs": true,
  "descriptions": [
    {
      "dataType": "dwi",
      "modalityLabel": "dwi",
      "customLabels": "acq-AP",
      "criteria": {
        "SeriesDescription": "cmrr_mbep2d_diff_mb2_*_1.8iso",
        "ImageType": ["ORIGINAL","PRIMARY","DIFFUSION","NONE","MB","ND","MOSAIC"]
      }
    }
  ]
}

Thank you in advance. I strongly prefer heudiconv, but I’m also open to dcm2bids.

In general, when splitting a diffusion study across multiple series, it is wise to ensure that all series include the same maximum b-value. MRI scanners will often apply an number of automatic optimizations, and fixing the b-value constrains these optimizations. At a minimum, I would check the BIDS JSON files to ensure that the TE and bandwidth are actually consistent across your series.

Concatenating different DICOM series can be problematic for many reasons: image position and angulation, sequence optimizations, different shims, etc. For this reason, this issue is out of scope of dcm2niix and presumably all the wrappers for dcm2niix (dcm2bids, heudiconv, etc).

If you are convinced that sequence parameters are identical across series, you can manually concatenate your data. Use fslmerge for the image files and paste (a bash command) for the bvals/bvecs.

Since you are using cmrr sequences, I assume your data is from a Siemens scanner. For future data acquisition, you may want to incorporate these comments. It is worth emphasizing that the default Siemens gradient directions are all half-sphere to keep spatial distortion consistent across all images. However, offline Eddy processing works better with whole sphere vectors, which allows Eddy to model and remove errors. For this reason, Siemens users should create your own gradient tables which is a perfect opportunity to ensure that all series include at least a few images with the maximum b-value. I encourage you to reach out to the Siemens Research Collaboration Manager affiliated with your center - it is their role to help you optimize sequences, and they know of a lot of undocumented tricks.

Thank you very much for the swift response and all the valuable comments.

I understand the perspective of dcm2niix, although it would be beneficial to include the concatenation ‘hack’ within the wrappers, allowing users to utilize it at their discretion. But this might conflict with the philosophy they want to maintain.

As you mentioned, the sequences originate from a Siemens scanner, and have identical parameters. Therefore, I’ll manually concatenate the nifti files to create the desired output.