I am trying to develop a DICOM file from scratch (using pydicom) that can be imported into slicer 3D. This DICOM from scratch can be read by other programs with no issue. Although the DICOM I can generate has a Patient Name, Patient ID, etc. - slicer doesn’t show in the DICOM database.
To further highlight the issue, in the pydicom code (below) I have “ds” as the dicom data that I’m trying to create and “ds_in” as the read in data of the original dicom. If I set ds=ds_in (committed out currently in code below) and make modifications then the pydicom can be read by slicer (not too surprising). Furthermore, if I delete all unwanted dicom tags (so just the specific dicoms I’m manually writing from ds_in to ds in the code current are present), the dicom file still has no issue as long as I set ds=ds_in after “file_meta = FileMetaDataset()”. It is the minute that I comment out ds=ds_in but try to pass in the ds_in tags directly to the ds tags on a tag by tag bases then that file does not work. In other words, if I manually try to force each and every ds_in file meta dataset from the ds_in to the ds variable, I have an issue.
It seems the “file_meta = FileMetaDataset()” is key here in which manually rewriting it, i.e., setting the ds_in tags to the ds file_meta tag group, is not the same as copying the file meta dataset from the original dicom? I am also making sure I’m being consistent with my image datatype - you can see I set my modified image to a uint16 at the end.
Are there any suggestions or example codes to write a basic dicom from scratch with pydicom that is Slicer 3D compatible?
import pydicom
from pydicom.dataset import FileDataset, FileMetaDataset
ds_in = pydicom.dcmread(ReadPath1)
#
file_meta = FileMetaDataset()
file_meta.FileMetaInformationGroupLength = ds_in.file_meta.FileMetaInformationGroupLength
file_meta.FileMetaInformationVersion = ds_in.file_meta.FileMetaInformationVersion #b'\x01\x00'
file_meta.MediaStorageSOPClassUID = ds_in.file_meta.MediaStorageSOPClassUID
file_meta.MediaStorageSOPInstanceUID = ds_in.file_meta.MediaStorageSOPInstanceUID
file_meta.TransferSyntaxUID = ds_in.file_meta.TransferSyntaxUID
file_meta.ImplementationClassUID = ds_in.file_meta.ImplementationClassUID #pydicom.uid.UID(pydicom.uid.PYDICOM_IMPLEMENTATION_UID) #ds_in.file_meta.ImplementationClassUID
file_meta.ImplementationVersionName = ds_in.file_meta.ImplementationVersionName #pydicom.uid.UID(pydicom.uid.PYDICOM_IMPLEMENTATION_UID).name
FileName_TMP = tempfile.NamedTemporaryFile(suffix='.dcm').name
ds = FileDataset(FileName_TMP, {}, file_meta=file_meta, preamble=b"\0" * 128)
# # Works if I set ds to equal ds_in
# ds_in.remove_private_tags()
# ds = ds_in
ds.StudyInstanceUID = ds_in.StudyInstanceUID
ds.SeriesInstanceUID = ds_in.SeriesInstanceUID
ds.SamplesPerPixel = ds_in.SamplesPerPixel
ds.PhotometricInterpretation = ds_in.PhotometricInterpretation
ds.BitsStored = ds_in.BitsStored
ds.BitsAllocated = ds_in.BitsAllocated
ds.HighBit = ds_in.HighBit
ds.PixelRepresentation = ds_in.PixelRepresentation
ds.Rows = ds_in.Rows
ds.Columns = ds_in.Columns
ds.PixelSpacing = ds_in.PixelSpacing
ds.InstanceNumber = ds_in.InstanceNumber
ds.SliceThickness = 2
ds.SpacingBetweenSlices = 15
# Modify image
A = ds_in.pixel_array
from scipy import ndimage
Aavg = ndimage.gaussian_filter(A, 5)
Aedge = ndimage.filters.laplace(A)
A = Aavg + Aedge
A[A > 1000] = 0
A = numpy.uint16(A)
ds.PixelData = A.tobytes()
ds.Modality = ds_in.Modality
ds.ImagePositionPatient = ds_in.ImagePositionPatient
ds.ImageOrientationPatient = ds_in.ImageOrientationPatient
ds.InstanceCreatorUID = ds_in.InstanceCreatorUID
ds.SpecificCharacterSet = ds_in.SpecificCharacterSet
ds.ContentDate = ds_in.ContentDate
ds.ContentTime = ds_in.ContentTime
ds.PatientName = ds_in.PatientName
ds.PatientID = ds_in.PatientID
pydicom.dataset.validate_file_meta(ds.file_meta, enforce_standard=True)
ds.save_as(WritePath + '/' + WriteFile + '.dcm')