Loading...
Loading...
DICOM and NIfTI medical image processing pipeline. Triggers on DICOM, NIfTI, dcm2niix, de-identification, pydicom, DICOM header, conversion, anonymization, BIDS, DICOM tags, medical image format conversion, "DICOM to NIfTI", "burned-in PHI", "SeriesInstanceUID", "nibabel", "DICOM anonymization".
npx skill4agent add awslabs/hcls-agent-skills dicom-processingdcm2niixpydicompydicomnibabelSeriesInstanceUID.dcm.nii.nii.gz# Standard conversion: gzip output, BIDS sidecar, pattern-named files
dcm2niix -z y -b y -f %p_%s -o output_dir input_dir| Flag | Meaning |
|---|---|
| gzip output ( |
| emit BIDS JSON sidecar |
| filename pattern: |
| do NOT merge 2D slices across series (prevents cross-series mixing) |
| output directory |
%p%s%t%i%n%dimport pydicom
ds = pydicom.dcmread('file.dcm')
print(ds.PatientName, ds.StudyDate, ds.Modality)
print(ds.pixel_array.shape) # numpy array of pixel dataimport pydicom
from pydicom.uid import generate_uid
ds = pydicom.dcmread('file.dcm')
tags_to_remove = [
'PatientName', 'PatientID', 'PatientBirthDate',
'InstitutionName', 'ReferringPhysicianName', 'StudyDate',
]
for tag in tags_to_remove:
if tag in ds:
del ds[tag]
ds.PatientID = 'ANON_001'
# Remove private (vendor) tags — they frequently contain PHI
ds.remove_private_tags()
# Replace UIDs so the study/series/instance cannot be linked back
ds.StudyInstanceUID = generate_uid()
ds.SeriesInstanceUID = generate_uid()
ds.SOPInstanceUID = generate_uid()
ds.save_as('anon.dcm')# RSNA CTP / DicomBrowser DAP (DICOM Anonymizer Program)
java -jar DAP.jar -p profile.script -i input/ -o output/import nibabel as nib
img = nib.load('file.nii.gz')
data = img.get_fdata() # numpy ndarray
affine = img.affine # 4x4 voxel-to-world transform
header = img.headerfrom pathlib import Path
from collections import defaultdict
import pydicom, subprocess
def group_by_series(input_dir):
series = defaultdict(list)
for p in Path(input_dir).rglob('*.dcm'):
ds = pydicom.dcmread(p, stop_before_pixels=True)
series[ds.SeriesInstanceUID].append(p)
return series
def convert_all(input_dir, output_dir):
Path(output_dir).mkdir(parents=True, exist_ok=True)
# dcm2niix handles series grouping internally when given a directory
subprocess.run(
['dcm2niix', '-z', 'y', '-b', 'y', '-f', '%p_%s',
'-o', output_dir, input_dir],
check=True,
)dataset/
├── dataset_description.json
├── participants.tsv
└── sub-01/
└── ses-01/
├── anat/ sub-01_ses-01_T1w.nii.gz
├── func/ sub-01_ses-01_task-rest_bold.nii.gz
└── dwi/ sub-01_ses-01_dwi.nii.gzsub-<label>/ses-<label>/<modality>/<sub>_<ses>_<suffix>.nii.gz.jsonWhat is the target format?
├─ NIfTI (analysis) → dcm2niix -z y -b y
│ ├─ Need BIDS layout? → add -f sub-%i_ses-%t_%p, reorganize post-hoc
│ └─ Single series only? → point dcm2niix at series directory directly
└─ DICOM (archive/PACS) → pydicom read/write
De-identification method:
├─ Small cohort (< 100 studies) → pydicom script (remove tags + private + replace UIDs)
├─ Large cohort or regulatory → CTP DicomAnonymizer with Supplement 142 profile
└─ Burned-in pixel PHI risk?
├─ US / Secondary Capture / Screenshots → YES: add OCR + pixel masking step
└─ CT / MR / PT → Usually NO: tag-level de-ID sufficientPatient → Study → Series → InstanceSeriesInstanceUIDStudyInstanceUIDgenerate_uid()ds.remove_private_tags()| Tag | Name | Purpose |
|---|---|---|
| Modality | CT / MR / CR / US / PT ... |
| SliceThickness | mm |
| PixelSpacing | in-plane spacing |
| ImagePositionPatient | origin of slice in patient coords |
| ImageOrientationPatient | row/col direction cosines |
affinedcm2niix# Convert
dcm2niix -z y -b y -f %p_%s -o out/ in/
# Skip merging across series (safer)
dcm2niix -z y -b y -m n -f %p_%s -o out/ in/
# Batch anonymization (CTP)
java -jar DAP.jar -p profile.script -i input/ -o output/# Read DICOM
ds = pydicom.dcmread('file.dcm')
ds.PatientName, ds.Modality, ds.pixel_array.shape
# Header-only (fast, no pixels)
ds = pydicom.dcmread('file.dcm', stop_before_pixels=True)
# Anonymize core fields
for t in ['PatientName','PatientID','PatientBirthDate',
'InstitutionName','ReferringPhysicianName','StudyDate']:
if t in ds: del ds[t]
ds.remove_private_tags()
ds.StudyInstanceUID = generate_uid()
ds.SeriesInstanceUID = generate_uid()
ds.SOPInstanceUID = generate_uid()
# Load NIfTI
img = nib.load('file.nii.gz'); data = img.get_fdata(); aff = img.affineds.remove_private_tags()StudyInstanceUIDSeriesInstanceUIDSOPInstanceUIDgenerate_uid()-m n.nii-z y.nii.gzpydicom.dcmread(path, stop_before_pixels=True).dcmPath(input_dir).rglob('*.dcm')