def create_dicom_base(self): if _dicom_loaded is False: raise ModuleNotLoadedError("Dicom") if self.header_set is False: raise InputError("Header not loaded") meta = Dataset() meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' # CT Image Storage meta.MediaStorageSOPInstanceUID = "1.2.3" meta.ImplementationClassUID = "1.2.3.4" meta.TransferSyntaxUID = UID.ImplicitVRLittleEndian # Implicit VR Little Endian - Default Transfer Syntax ds = FileDataset("file", {}, file_meta=meta, preamble=b"\0" * 128) ds.PatientsName = self.patient_name ds.PatientID = "123456" ds.PatientsSex = '0' ds.PatientsBirthDate = '19010101' ds.SpecificCharacterSet = 'ISO_IR 100' ds.AccessionNumber = '' ds.is_little_endian = True ds.is_implicit_VR = True ds.SOPClassUID = '1.2.3' # !!!!!!!! ds.SOPInstanceUID = '1.2.3' # !!!!!!!!!! ds.StudyInstanceUID = '1.2.3' # !!!!!!!!!! ds.FrameofReferenceUID = '1.2.3' # !!!!!!!!! ds.StudyDate = '19010101' # !!!!!!! ds.StudyTime = '000000' # !!!!!!!!!! ds.PhotometricInterpretation = 'MONOCHROME2' ds.SamplesPerPixel = 1 ds.ImageOrientationPatient = ['1', '0', '0', '0', '1', '0'] ds.Rows = self.dimx ds.Columns = self.dimy ds.SliceThickness = str(self.slice_distance) ds.PixelSpacing = [self.pixel_size, self.pixel_size] return ds
def writeDicom(ods, mrn, studyID, outdir): file_meta = Dataset() file_meta.MediaStorageSOPClassUID = 'Secondary Capture Image Storage' file_meta.MediaStorageSOPInstanceUID = '0.0' file_meta.ImplementationClassUID = '0.0' ds = FileDataset(studyID, {}, file_meta=file_meta, preamble="\0" * 128) ds.Modality = ods.Modality if "Modality" in ods else "" ds.StudyDate = ods.StudyDate if "StudyDate" in ods else "" ds.StudyTime = ods.StudyTime if "StudyTime" in ods else "" ds.StudyInstanceUID = '0.0' ds.SeriesInstanceUID = '0.0' ds.SOPInstanceUID = '0.0' ds.SOPClassUID = 'Secondary Capture Image Storage' ds.SecondaryCaptureDeviceManufctur = 'Python 2.7.3' ## These are the necessary imaging components of the FileDataset object. ds.AccessionNumber = str(studyID) ds.PatientID = str(mrn) ds.StudyID = str(studyID) ds.PatientName = str(studyID) ds.PatientBirthDate = "00000000" ds.PatientAge = calculateAge( ods.StudyDate, ods.PatientBirthDate ) if "StudyDate" in ods and "PatientBirthDate" in ods else "" ds.PatientSex = ods.PatientSex if "PatientSex" in ods else "" ds.StudyDescription = ods.StudyDescription if "StudyDescription" in ods else "" ds.SeriesDescription = ods.SeriesDescription if "SeriesDescription" in ods else "" ds.ViewPosition = ods.ViewPosition if "ViewPosition" in ods else "" ds.InstanceNumber = ods.InstanceNumber if "InstanceNumber" in ods else "" ds.SeriesNumber = ods.SeriesNumber if "SeriesNumber" in ods else "" ds.SamplesPerPixel = ods.SamplesPerPixel if "SamplesPerPixel" in ods else "" ds.PhotometricInterpretation = ods.PhotometricInterpretation if "PhotometricInterpretation" in ods else "" ds.PixelRepresentation = ods.PixelRepresentation if "PixelRepresentation" in ods else "" ds.HighBit = ods.HighBit if "HighBit" in ods else "" ds.BitsStored = ods.BitsStored if "BitsStored" in ods else "" ds.BitsAllocated = ods.BitsAllocated if "BitsAllocated" in ods else "" ds.Columns = ods.Columns if "Columns" in ods else "" ds.Rows = ods.Rows if "Rows" in ods else "" ds.PixelData = ods.PixelData if "PixelData" in ods else "" filename = cleanString( str(studyID) + "_" + str(ds.SeriesNumber) + "_" + str(ds.InstanceNumber) + "_" + str(ds.Modality) + "_" + str(ds.StudyDescription) + "_" + str(ds.SeriesDescription) + "_" + str(ds.ViewPosition) + ".dcm") outpath = os.path.join(outdir, filename) ds.save_as(outpath) return
def create_dicom(self): """ Generates and returns Dicom RTSTRUCT object, which holds all VOIs. :returns: a Dicom RTSTRUCT object holding any VOIs. """ if _dicom_loaded is False: raise ModuleNotLoadedError("Dicom") meta = Dataset() meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.481.3' # RT Structure Set Storage SOP Class # see https://github.com/darcymason/pydicom/blob/master/pydicom/_uid_dict.py meta.MediaStorageSOPInstanceUID = "1.2.3" meta.ImplementationClassUID = "1.2.3.4" meta.TransferSyntaxUID = UID.ImplicitVRLittleEndian # Implicit VR Little Endian - Default Transfer Syntax ds = FileDataset("file", {}, file_meta=meta, preamble=b"\0" * 128) if self.cube is not None: ds.PatientsName = self.cube.patient_name else: ds.PatientsName = "" ds.PatientID = "123456" ds.PatientsSex = '0' ds.PatientsBirthDate = '19010101' ds.SpecificCharacterSet = 'ISO_IR 100' ds.AccessionNumber = '' ds.is_little_endian = True ds.is_implicit_VR = True ds.SOPClassUID = '1.2.840.10008.5.1.4.1.1.481.3' # RT Structure Set Storage SOP Class ds.SOPInstanceUID = '1.2.3' # !!!!!!!!!! ds.StudyInstanceUID = '1.2.3' # !!!!!!!!!! ds.SeriesInstanceUID = '1.2.3' # !!!!!!!!!! ds.FrameofReferenceUID = '1.2.3' # !!!!!!!!! ds.SeriesDate = '19010101' # !!!!!!!! ds.ContentDate = '19010101' # !!!!!! ds.StudyDate = '19010101' # !!!!!!! ds.SeriesTime = '000000' # !!!!!!!!! ds.StudyTime = '000000' # !!!!!!!!!! ds.ContentTime = '000000' # !!!!!!!!! ds.StructureSetLabel = 'pyTRiP plan' ds.StructureSetDate = '19010101' ds.StructureSetTime = '000000' ds.StructureSetName = 'ROI' ds.Modality = 'RTSTRUCT' roi_label_list = [] roi_data_list = [] roi_structure_roi_list = [] # to get DICOM which can be loaded in Eclipse we need to store information about UIDs of all slices in CT # first we check if DICOM cube is loaded if self.cube is not None: rt_ref_series_data = Dataset() rt_ref_series_data.SeriesInstanceUID = '1.2.3.4.5' rt_ref_series_data.ContourImageSequence = Sequence([]) # each CT slice corresponds to one DICOM file for slice_dicom in self.cube.create_dicom(): slice_dataset = Dataset() slice_dataset.ReferencedSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' # CT Image Storage SOP Class slice_dataset.ReferencedSOPInstanceUID = slice_dicom.SOPInstanceUID # most important - slice UID rt_ref_series_data.ContourImageSequence.append(slice_dataset) rt_ref_study_seq_data = Dataset() rt_ref_study_seq_data.ReferencedSOPClassUID = '1.2.840.10008.3.1.2.3.2' # Study Component Management Class rt_ref_study_seq_data.ReferencedSOPInstanceUID = '1.2.3.4.5' rt_ref_study_seq_data.RTReferencedSeriesSequence = Sequence([rt_ref_series_data]) rt_ref_frame_study_data = Dataset() rt_ref_frame_study_data.RTReferencedStudySequence = Sequence([rt_ref_study_seq_data]) rt_ref_frame_study_data.FrameOfReferenceUID = '1.2.3.4.5' ds.ReferencedFrameOfReferenceSequence = Sequence([rt_ref_frame_study_data]) for i in range(self.number_of_vois()): roi_label = self.vois[i].create_dicom_label() roi_label.ObservationNumber = str(i + 1) roi_label.ReferencedROINumber = str(i + 1) roi_label.RefdROINumber = str(i + 1) roi_contours = self.vois[i].create_dicom_contour_data(i) roi_contours.RefdROINumber = str(i + 1) roi_contours.ReferencedROINumber = str(i + 1) roi_structure_roi = self.vois[i].create_dicom_structure_roi() roi_structure_roi.ROINumber = str(i + 1) roi_structure_roi_list.append(roi_structure_roi) roi_label_list.append(roi_label) roi_data_list.append(roi_contours) ds.RTROIObservations = Sequence(roi_label_list) ds.ROIContours = Sequence(roi_data_list) ds.StructureSetROIs = Sequence(roi_structure_roi_list) return ds
def create_dicom_base(self): if _dicom_loaded is False: raise ModuleNotLoadedError("Dicom") if self.header_set is False: raise InputError("Header not loaded") # TODO tags + code datatypes are described here: # https://www.dabsoft.ch/dicom/6/6/#(0020,0012) # datatype codes are described here: # ftp://dicom.nema.org/medical/DICOM/2013/output/chtml/part05/sect_6.2.html meta = Dataset() meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' # CT Image Storage # Media Storage SOP Instance UID tag 0x0002,0x0003 (type UI - Unique Identifier) meta.MediaStorageSOPInstanceUID = self._ct_sop_instance_uid meta.ImplementationClassUID = "1.2.3.4" meta.TransferSyntaxUID = UID.ImplicitVRLittleEndian # Implicit VR Little Endian - Default Transfer Syntax ds = FileDataset("file", {}, file_meta=meta, preamble=b"\0" * 128) ds.PatientsName = self.patient_name if self.patient_id in (None, ''): ds.PatientID = datetime.datetime.today().strftime('%Y%m%d-%H%M%S') else: ds.PatientID = self.patient_id # Patient ID tag 0x0010,0x0020 (type LO - Long String) ds.PatientsSex = '' # Patient's Sex tag 0x0010,0x0040 (type CS - Code String) # Enumerated Values: M = male F = female O = other. ds.PatientsBirthDate = '19010101' ds.SpecificCharacterSet = 'ISO_IR 100' ds.AccessionNumber = '' ds.is_little_endian = True ds.is_implicit_VR = True ds.SOPClassUID = '1.2.3' # !!!!!!!! # SOP Instance UID tag 0x0008,0x0018 (type UI - Unique Identifier) ds.SOPInstanceUID = self._ct_sop_instance_uid # Study Instance UID tag 0x0020,0x000D (type UI - Unique Identifier) # self._dicom_study_instance_uid may be either set in __init__ when creating new object # or set when import a DICOM file # Study Instance UID for structures is the same as Study Instance UID for CTs ds.StudyInstanceUID = self._dicom_study_instance_uid # Series Instance UID tag 0x0020,0x000E (type UI - Unique Identifier) # self._ct_dicom_series_instance_uid may be either set in __init__ when creating new object # or set when import a DICOM file # Series Instance UID for structures might be different than Series Instance UID for CTs ds.SeriesInstanceUID = self._ct_dicom_series_instance_uid # Study Instance UID tag 0x0020,0x000D (type UI - Unique Identifier) ds.FrameofReferenceUID = '1.2.3' # !!!!!!!!! ds.StudyDate = datetime.datetime.today().strftime('%Y%m%d') ds.StudyTime = datetime.datetime.today().strftime('%H%M%S') ds.PhotometricInterpretation = 'MONOCHROME2' ds.SamplesPerPixel = 1 ds.ImageOrientationPatient = ['1', '0', '0', '0', '1', '0'] ds.Rows = self.dimx ds.Columns = self.dimy ds.SliceThickness = str(self.slice_distance) ds.PixelSpacing = [self.pixel_size, self.pixel_size] # Add eclipse friendly IDs ds.StudyID = '1' # Study ID tag 0x0020,0x0010 (type SH - Short String) ds.ReferringPhysiciansName = 'py^trip' # Referring Physician's Name tag 0x0008,0x0090 (type PN - Person Name) ds.PositionReferenceIndicator = '' # Position Reference Indicator tag 0x0020,0x1040 ds.SeriesNumber = '1' # SeriesNumber tag 0x0020,0x0011 (type IS - Integer String) return ds
def write_dicom(pixel_array, filename, origin, origins, orientation): file_meta = Dataset() file_meta.MediaStorageSOPClassUID = 'Secondary Capture Image Storage' file_meta.MediaStorageSOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780' file_meta.ImplementationClassUID = '1.3.6.1.4.1.9590.100.1.0.100.4.0' ds = FileDataset(filename, {},file_meta = file_meta,preamble="\0"*128) ds.ImageType= 'ORIGINAL\PRIMARY\AXIAL\CT' ds.SOPClassUID = 'Secondary Capture Image Storage' ds.SOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780' ds.StudyDate = str(datetime.date.today()).replace('-','') #ds.ImageDate = str(datetime.date.today()).replace('-','') ds.StudyTime = str(time.time()) #ds.ImageTime = str(time.time()) ds.AccessionNumber = '153745645' ds.Modality = 'CT' ds.Manufacturer = 'PY_BONEMAT_ABAQUS' ds.InstitutionName = 'UNIVERISTY_OF_BATH' ds.ReferringPhysiciansName = 'NOTAPPLICABLE' ds.ManufacturersModelName = 'VERSION1-0-9' ds.ReferencedImageSequence = '' ds.PatientsName = 'SUBJECT001' ds.PatientID = '' ds.PatientsBirthDate = '' ds.PatientsSex = 'F' ds.SliceThickness = 2.7 ds.KVP = 120 ds.SpacingBetweenSlices = 1 ds.DataCollectionDiameter = 430 ds.ReconstructionDiameter = 430.00 ds.DistanceSourceToDetector = 1093 ds.DistanceSourceToPatient = 630. ds.GantryDetectorTilt = 0.0 ds.ScanArc = 403 ds.XRayTubeCurrent = 200 ds.Exposure = 135 ds.FilterType = 'F' ds.PatientPosition = 'HFS' ds.StudyInstanceUID = '1.3.6.1.4.1.9590.100.1.1.124313977412360175234271287472804872093' ds.SeriesInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780.1' #ds.ReferenceSOPClassUID = 'Secondary Capture Image Storage' #ds.ReferencedSOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780' #ds.ContentDate = str(datetime.date.today()).replace('-','') #ds.ContentTime = str(time.time()) ds.StudyID = '15346254' ds.SeriesNumber = '8733' ds.AcquisitionNumber = 1 ds.ImageNumber = origins.index(origin) + 1 ds.SliceLocation = origin[2] ds.SecondaryCaptureDeviceManufctur = 'Python 2.7.3' ds.SamplesPerPixel = 1 ds.PhotometricInterpretation = "MONOCHROME2" ds.PixelRepresentation = 0 ds.HighBit = 15 ds.BitsStored = 16 ds.BitsAllocated = 16 ds.SmallestImagePixelValue = '\\x00\\x00' ds.LargestImagePixelValue = '\\xff\\xff' ds.Columns = pixel_array.shape[0] ds.Rows = pixel_array.shape[1] ds.PatientOrientation = ['L','P'] ds.ImagePositionPatient = origin ds.ImageOrientationPatient = orientation ds.PixelSpacing = [1.0, 1.0] ds.RescaleSlope = 1.0 ds.RescaleIntercept = 0.0 if pixel_array.dtype != np.uint16: pixel_array = pixel_array.astype(np.uint16) ds.PixelData = pixel_array.tostring() ds.save_as(filename) return