Store metadata in NIfTI and NRRD is a header write: put a few keys you choose into a NIfTI Nifti1Extension, or onto an NRRD with SetMetaData. This page is that how-to. It is not “convert DICOM to NIfTI.”
If you meant a plain convert without extra tags → how to convert DICOM to NIfTI. dcm2niix already keeps acquisition context in a BIDS sidecar. This page is the other write: fields you attach yourself.
Why bother
A classic DICOM → NIfTI/NRRD convert keeps the pixels and the affine and drops patient tags. That strip is the right default (it is half of anonymization). Some pipelines still need one or two fields to travel with the volume — a series description, an acquisition date you control — without putting the file back into DICOM.
The keys below are placeholders you fill. They are not a dump of (0010,0010) Patient’s Name. Do not copy identifiers you just stripped.
| Format | Call | What it stores |
|---|---|---|
| NIfTI | Nifti1Extension(40, …) on header.extensions |
A JSON blob (here, base64) inside the NIfTI header |
| NRRD | image.SetMetaData(key, value) |
Plain key/value on the NRRD header |
Environment
python -m venv nifti_nrrd_meta
source nifti_nrrd_meta/bin/activate # Windows: nifti_nrrd_metaScriptsactivate
pip install SimpleITK nibabel numpy
Sanity check: import SimpleITK as sitk, nibabel as nib, numpy as np, json, base64. Tutorial repo: pycadd/YouTube-Tutorials — nifti_nrrd_metadata.
NIfTI: Nifti1Extension
SimpleITK reads the series so we have pixels, spacing, direction, and origin. The job on this page starts after that: build the affine, wrap a Nifti1Image, append an extension, save.
import base64
import json
import SimpleITK as sitk
import nibabel as nib
import numpy as np
class SimpleDicomToNiftiConverter:
def __init__(self, dicom_folder, output_nifti):
self.dicom_folder = dicom_folder
self.output_nifti = output_nifti
def convert(self):
reader = sitk.ImageSeriesReader()
dicom_names = reader.GetGDCMSeriesFileNames(self.dicom_folder)
reader.SetFileNames(dicom_names)
image = reader.Execute()
spacing = image.GetSpacing()
direction = image.GetDirection()
origin = image.GetOrigin()
affine = np.eye(4)
affine[:3, :3] = np.array(direction).reshape(3, 3) * spacing
affine[:3, 3] = origin
image_array = sitk.GetArrayFromImage(image)
nifti_image = nib.Nifti1Image(image_array, affine)
# Keys you choose. Not a copy of the DICOM patient tags.
custom_metadata = {
"SeriesDescription": "T1w research export",
"AcquisitionDate": "20260115",
}
json_str = json.dumps(custom_metadata)
encoded_json = base64.b64encode(json_str.encode("utf-8")).decode("utf-8")
nifti_extension = nib.nifti1.Nifti1Extension(40, encoded_json.encode("utf-8"))
nifti_image.header.extensions.append(nifti_extension)
nib.save(nifti_image, self.output_nifti)
print("wrote", self.output_nifti)
Code 40 is a user-defined NIfTI extension. The payload here is base64(JSON) so the bytes stay printable. A reader that does not know the extension still opens the volume; it just ignores the blob. To read it back: walk nifti_image.header.extensions, decode the base64, json.loads.
SeriesDescription and AcquisitionDate are examples. Replace them with the two fields your pipeline actually needs. Patient name / ID do not belong here.
NRRD: SetMetaData
NRRD stores key/value pairs on the image. Same reader, no nibabel.
import SimpleITK as sitk
class SimpleDicomToNrrdConverter:
def __init__(self, dicom_folder, output_nrrd):
self.dicom_folder = dicom_folder
self.output_nrrd = output_nrrd
def convert(self):
reader = sitk.ImageSeriesReader()
dicom_names = reader.GetGDCMSeriesFileNames(self.dicom_folder)
reader.SetFileNames(dicom_names)
image = reader.Execute()
image.SetMetaData("SeriesDescription", "T1w research export")
image.SetMetaData("AcquisitionDate", "20260115")
sitk.WriteImage(image, self.output_nrrd)
print("wrote", self.output_nrrd)
SetMetaData is a string key and a string value. Same two example fields as the NIfTI path so the pair stays consistent. Read them later with image.GetMetaData("SeriesDescription") after sitk.ReadImage.
The DICOM read is only the vehicle. If you do not need extra keys, stop at DICOM to NIfTI and use the sidecar.
PYCAD builds the imaging side of products that have to keep these fields for real. Case studies.