Convert MRI sourcedata to BIDS

In this tutorial, you will learn how to use Nipoppy and the BIDS converter dcm2bids to convert your imaging sourcedata to BIDS.

Concretely, we will:

  1. Initialize a Nipoppy dataset

  2. Reorganize DICOM sourcedata

  3. Install and set up the dcm2bids pipeline

  4. Extract DICOM header information to create the dcm2bids_config.json file

  5. Convert the DICOM sourcedata to NIfTI BIDS raw data

Note

If you have not installed Nipoppy yet, instructions are available here.

Step 0: Download the tutorial dataset

We will use the tutorial dataset provided on the Nipoppy GitHub, which includes DICOM data of different modalities for 4 subjects (Note: Data of one subject was copied in order to create multiple subjects with different modalities for training purposes. Hence, all data stems from one subject).

There are multiple ways of downloading the dataset:

1. via git clone

SSH: git clone git@github.com:nipoppy/tutorial-dataset.git

HTTPS: git clone https://github.com/nipoppy/tutorial-dataset.git

2. via the browser:

3. via the command line:

wget -O tutorial-dataset.zip https://github.com/nipoppy/tutorial-dataset/archive/refs/heads/main.zip

Unzip once downloaded.

Step 1: Initialize the Nipoppy dataset

1.1. Run the following command to create a Nipoppy dataset:

$ nipoppy init --dataset nipoppy_study

This command creates a folder named nipoppy_study with subdirectories for raw data, processed (derivatives) data, pipeline configuration files, logs, etc. The tree command can be used to show the directory structure.

$ tree -L 1 nipoppy_study
Output
nipoppy_study/
├── bids
├── code
├── containers
├── derivatives
├── global_config.json
├── logs
├── manifest.tsv
├── pipelines
├── scratch
├── sourcedata
└── tabular

1.2. Please replace the manifest.tsv in nipoppy_study with the manifest.tsv provided in the tutorial dataset. This file is considered the ground truth for which participants and sessions are available for processing.

Step 2: Reorganize the DICOM sourcedata

Good to know: why reorganization?

Usually, there is a gap between data state out of scanner vs. ready for bidsification. Source data is often messy in different ways, making it hard to use BIDSification tools directly. Nipoppy provides a unified way to deal with DICOM vs. Nifti sourcedata which simplifies BIDSification. It also helps fixing issues related to file naming which often appear in chaotic data dumps or due to typos. Additionally, the organization simplifies taring the DICOMs after bidsification. All this is implemented in one simple command, namely nipoppy reorg.

2.1. We need to move the content of the tutorial-dataset/reorg directory to the sourcedata/imaging/pre_reorg directory of our nipoppy_study dataset, i.e.:

mv tutorial-dataset/reorg/* nipoppy_study/sourcedata/imaging/pre_reorg

Running tree nipoppy_study/sourcedata/imaging/pre_reorg/ | head we can see come of the content of the pre_reorg folder:

├── ED01
│   └── BL
│       ├── DTI_30_DIRs_AP_15
│       │   ├── IM-0003-0001.dcm
│       │   ├── IM-0003-0002.dcm
│       │   ├── IM-0003-0003.dcm
│       │   ├── IM-0003-0004.dcm
│       │   ├── IM-0003-0005.dcm
│       │   ├── IM-0003-0006.dcm
...

We need to track this modification in our dataset by running

nipoppy track-curation --dataset nipoppy_study

before we can have an overview of the dataset status with

nipoppy status --dataset nipoppy_study
Partial output
     Participant counts by session at each Nipoppy checkpoint
            ╷             ╷
 session_id │ in_manifest │ in_pre_reorg
════════════╪═════════════╪════════════════
    01      │      4      │      4
            ╵             ╵

2.2. We run

nipoppy reorg --dataset nipoppy_study

Our data was symlinked and reorganized into the post_reorg directory. We can see so by running

tree nipoppy_study/sourcedata/imaging/post_reorg/ | head
Output
├── README.md
├── sub-ED01
│   └── ses-BL
│       ├── 82519e8_IM-0003-0001.dcm -> ../../../pre_reorg/ED01/BL/DTI_30_DIRs_AP_15/IM-0003-0001.dcm
│       ├── 82519e8_IM-0003-0002.dcm -> ../../../pre_reorg/ED01/BL/DTI_30_DIRs_AP_15/IM-0003-0002.dcm
│       ├── 82519e8_IM-0003-0003.dcm -> ../../../pre_reorg/ED01/BL/DTI_30_DIRs_AP_15/IM-0003-0003.dcm
│       ├── 82519e8_IM-0003-0004.dcm -> ../../../pre_reorg/ED01/BL/DTI_30_DIRs_AP_15/IM-0003-0004.dcm
│       ├── 82519e8_IM-0003-0005.dcm -> ../../../pre_reorg/ED01/BL/DTI_30_DIRs_AP_15/IM-0003-0005.dcm
│       ├── 82519e8_IM-0003-0006.dcm -> ../../../pre_reorg/ED01/BL/DTI_30_DIRs_AP_15/IM-0003-0006.dcm

and by running nipoppy status:

Partial output
     Participant counts by session at each Nipoppy checkpoint
            ╷             ╷
 session_id │ in_manifest │ in_post_reorg
════════════╪═════════════╪════════════════
    01      │      4      │      4
            ╵             ╵

Step 3: Install and set up the dcm2bids pipeline

3.1. The nipoppy init command created the configuration file at nipoppy_study/global_config.json. This file may need to be updated with information specific to your computing environment. Initially, it will look like this:

 1{
 2    "SUBSTITUTIONS": {
 3        "_comment": "Self-references like NIPOPPY_DPATH_CONTAINERS are resolved from the layout at runtime, making them layout-aware",
 4        "[[NIPOPPY_DPATH_CONTAINERS]]": "[[NIPOPPY_DPATH_CONTAINERS]]",
 5        "[[HPC_ACCOUNT_NAME]]": ""
 6    },
 7    "DICOM_DIR_PARTICIPANT_FIRST": true,
 8    "CONTAINER_CONFIG": {
 9        "COMMAND": "apptainer",
10        "ARGS": [
11            "--cleanenv"
12        ],
13        "BIND_PATHS": [],
14        "ENV_VARS": {
15            "PYTHONUNBUFFERED": "1"
16        }
17    },
18    "HPC_PREAMBLE": [
19        "# (These lines can all be removed if not using HPC functionality.)",
20        "# ========== Activate Python environment ==========",
21        "# Here we need the command to activate your Python environment in an ",
22        "# HPC job, for example:",
23        "# - venv:  source <PATH_TO_VENV>/bin/activate",
24        "# - conda: source ~/.bashrc; conda activate <ENV_NAME>",
25        "# ========== Set environment variables ==========",
26        "export PYTHONUNBUFFERED=1"
27    ],
28    "PIPELINE_VARIABLES": {
29        "BIDSIFICATION": {},
30        "PROCESSING": {},
31        "EXTRACTION": {}
32    },
33    "CUSTOM": {}
34}

By default, this file does not contain any pipeline-specific information, since the dataset does not have any pipelines installed yet. Still, there are fields that may need to be modified depending on your setup:

  • If Apptainer is not available on your system, you will need to change CONTAINER_CONFIG -> COMMAND to

    • "singularity" if you have Singularity installed

    • "docker" if you have Docker installed

    • "null" if you have dcm2bids installed locally (“baremetal” install)

  • If your group uses a shared directory for storing container image files, you can replace the value of "[[NIPOPPY_DPATH_CONTAINERS]]" by the full path to that shared directory. For example:

    "SUBSTITUTIONS": {
        "_comment": "Self-references like NIPOPPY_DPATH_CONTAINERS are resolved from the layout at runtime, making them layout-aware",
        "[[NIPOPPY_DPATH_CONTAINERS]]": "<PATH_TO_SHARED_DIRECTORY>",
        "[[HPC_ACCOUNT_NAME]]": ""
    },
    
    • Alternatively, you can create a symlink from <NIPOPPY_PROJECT_ROOT>/containers to that directory (then this line in the configuration can be deleted) (recommended).

3.2. We can use following command to check which pipelines can be run with the dataset:

$ nipoppy pipeline list --dataset nipoppy_study

The output says that there are no available pipelines to be run:

INFO     No available bidsification pipelines
INFO     No available processing pipelines
INFO     No available extraction pipelines

That is because a newly initialized Nipoppy dataset does not contain any pipelines. Pipeline configuration files are available on the Zenodo data repository and can be searched for directly from your terminal using the command nipoppy pipeline search. The configuration files for dcm2bids can be downloaded by running the following:

$ nipoppy pipeline install --dataset nipoppy_study 16876754

When running nipoppy pipeline install, if using a container engine, you will be asked if you would like to download the dcm2bids container. If you do not already have a download of the container, type y and press Enter to do so. The download/building process may take ~10 minutes. Apptainer or Singularity container images will be downloaded as dcm2bids_3.2.0.sif inside the container store directory (i.e., nipoppy_study/containers or the custom path you set in the global_config.json file). Docker images are managed centrally and so will not be downloaded to the dataset.

3.3. When we open the nipoppy_study/global_config.json, we can see that the pipeline expects some more configuration (indicated by the null placeholder):

    "PIPELINE_VARIABLES": {
        "BIDSIFICATION": {
            "dcm2bids": {
                "3.2.0": {
                    "DCM2BIDS_CONFIG_FILE": null
                }
            }
        },
        "PROCESSING": {},
        "EXTRACTION": {}
    },

We need to replace the null next to the DCM2BIDS_CONFIG_FILE field with file path to the dcm2bids_config.json file that we will create in the next step. We recommend to keep this file in the code directory in your nipoppy dataset, like so:

    "PIPELINE_VARIABLES": {
        "BIDSIFICATION": {
            "dcm2bids": {
                "3.2.0": {
                    "DCM2BIDS_CONFIG_FILE": "[[NIPOPPY_DPATH_CODE]]/dcm2bids_config.json"
                }
            }
        },
        "PROCESSING": {},
        "EXTRACTION": {}
    },

Note

Without setting this path now, the next nipoppy bidsify prepare step will crash.

Step 4: Extract DICOM header information to create the dcm2bids_config.json

dcm2bids is a multi-step pipeline in Nipoppy. The steps are detailed in <NIPOPPY_PROJECT_ROOT>/pipelines/bidsification/dcm2bids-3.2.0/config.json:

4.1. We run

nipoppy bidsify --dataset nipoppy_study --pipeline dcm2bids --pipeline-version 3.2.0 --pipeline-step prepare

In our scratch directory we should see something like this now:

scratch/
├── dcm2bids_helper
│   ├── 013_post_reorg_T1_mprage_1mm_20180706110327.json
│   ├── 013_post_reorg_T1_mprage_1mm_20180706110327.nii.gz
│   ├── 015_post_reorg_DTI_30_DIRs_A-P_20180706110327.bval
│   ├── 015_post_reorg_DTI_30_DIRs_A-P_20180706110327.bvec
│   ├── 015_post_reorg_DTI_30_DIRs_A-P_20180706110327.json
│   ├── 015_post_reorg_DTI_30_DIRs_A-P_20180706110327.nii.gz
│   ├── 018_post_reorg_restingstate_20180706110327.json
│   └── 018_post_reorg_restingstate_20180706110327.nii.gz

The “prepare” step uses the dcm2bids_helper command to turn one participant’s DICOMs into NIfTI files with their accompanying JSON metadata files. Our task is now to find unique metadata or descriptions in each modality’s JSON file, so that dcm2bids knows how to group a set of acquisitions and how to label them according to BIDS. In other words, we need to link the metadata to BIDS-specific vocabulary.

Unique entries in the JSON files can be SeriesDescription, EchoTime, ProtocolName, ImageType etc. Whatever makes the files acquired under one condition different from other files acquired under different conditions. Also, we need to tell dcm2bids to which BIDS datatype this acquisition refers to and which BIDS suffix this file is going to have, so you need some knowledge of the BIDS specification for this task.

In our case, the dcm2bids_config.json can look like this:

{
    "descriptions": [
      {
        "datatype": "anat",
        "suffix": "T1w",
        "criteria": {
          "SeriesDescription": "T1_mprage_1mm"
        }
      },
      {
        "datatype": "func",
        "suffix": "bold",
        "custom_entities": "task-rest",
        "criteria": {
          "SeriesDescription": "restingstate",
        "sidecar_changes": {
          "TaskName": "rest"
          }
        }
      },
      {
      "datatype": "dwi",
      "suffix": "dwi",
      "criteria": {
        "SeriesDescription": "DTI_30_DIRs_A-P"
        }
      }
    ]
  }

4.2. We create a dcm2bids_config.json with the above content and place it in the code directory in our nipoppy_studydataset.

Step 5: Convert the DICOM sourcedata to NIfTI BIDS raw data

5.1. We are now ready to run the “convert” step

nipoppy bidsify --dataset nipoppy_study --pipeline dcm2bids --pipeline-version 3.2.0 --pipeline-step convert

After successful conversion, the output of nipoppy status should tell us that we have all our participants in_bids:

Partial output
     Participant counts by session at each Nipoppy checkpoint
            ╷             ╷
 session_id │ in_manifest │ in_bids
════════════╪═════════════╪═════════
    01      │      4      │      4
            ╵             ╵