def get_file_meta(dcm, root_uid): file_meta = FileMetaDataset() # From pydicom file_meta.MediaStorageSOPClassUID = ( pydicom._storage_sopclass_uids.RTStructureSetStorage) file_meta.MediaStorageSOPInstanceUID = pydicom.uid.generate_uid( root_uid) # TODO Generate this properly file_meta.TransferSyntaxUID = pydicom.uid.ImplicitVRLittleEndian # From dicom imaging file imaging_meta = [ "FileMetaInformationVersion", "ImplementationClassUID", "ImplementationVersionName", ] copy_attrs(dcm.file_meta, file_meta, imaging_meta) # file_meta.FileMetaInformationVersion = dcm.file_meta.FileMetaInformationVersion # file_meta.ImplementationClassUID = ( # dcm.file_meta.ImplementationClassUID # ) # TODO Check this is true on non-anon data # file_meta.ImplementationVersionName = dcm.file_meta.ImplementationVersionName return file_meta
def convert(nome_tiff, nome_dicom): global ds # Nomes do arquivo filename_little_endian = nome_dicom # Criando arquivos com informações minimas print('Criando arquivo Dicom Image') file_meta = FileMetaDataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.481.1' #http://dicom.nema.org/dicom/2013/output/chtml/part04/sect_I.4.html file_meta.MediaStorageSOPInstanceUID = "1.2.246.352.81.3.273720375.51644.19651.179.0" file_meta.ImplementationClassUID = "1.2.246.352.70.2.1.160.3" #Criando um dataset "vazio" ==> https://pydicom.github.io/pydicom/dev/reference/generated/pydicom.dataset.FileDataset.html ds = FileDataset(filename_little_endian, {}, file_meta = file_meta, preamble = b"\0"*128) #Adicionando elementos ds.PatientName = "Teste" ds.PatientID = "123456789" #Transfer Syntax ds.file_meta.TransferSyntaxUID = pydicom.uid.ExplicitVRLittleEndian ds.is_little_endian = True ds.is_implicit_VR = False #Adicionando data e hora de criação dt = datetime.datetime.now() ds.ContentDate = dt.strftime('%Y%m%d') timeStr = dt.strftime('%H%M%S.%f') # formato longo com micro segundos ds.ContentTime = timeStr #Carregando arquivo TIFF tiff_file = Image.open(nome_tiff) tiff_rotacionada90 = tiff_file.rotate(90) tiff_array = np.array(tiff_rotacionada90) #Adicionando array e outras informações da imagem ao dataset ds.PixelData = tiff_array.tobytes() tiff_meta_dict = {TAGS[key] : tiff_file.tag[key] for key in tiff_file.tag.keys()} ds.add_new([0x0008,0x0016], 'UI','1.2.840.10008.5.1.4.1.1.481.1') #SOP Class UID ds.add_new([0x0008,0x0018], 'UI','1.2.246.352.81.3.273720375.51644.19651.179.0') #SOP Instance UID ds.add_new([0x0028,0x0010], 'US',tiff_meta_dict['ImageLength'][0]) #rows ds.add_new([0x0028,0x0011], 'US',tiff_meta_dict['ImageWidth'][0]) #columns ds.add_new([0x0028,0x0100], 'US',tiff_meta_dict['BitsPerSample'][0]) #Bits Alocated ds.add_new([0x0028,0x0103], 'US', 0) # PixelRepresentation ds.add_new([0x0028,0x0002], 'US', tiff_meta_dict['SamplesPerPixel'][0]) # SamplesPerPixel ds.add_new([0x0028,0x0004], 'CS', 'MONOCHROME2') # Photometric Interpretation ==> https://dicom.innolitics.com/ciods/enhanced-mr-image/enhanced-mr-image/00280103 ds.add_new([0x0008,0x0060], 'CS', 'RTIMAGE') #Modality ds.add_new([0x0028,0x0101], 'US',tiff_meta_dict['BitsPerSample'][0]) #Bits Stored ds.add_new([0x3002,0x0022], 'DS', 1000.0) # Radiation Machine SAD ds.add_new([0x3002,0x0026], 'DS', 1600.0) # RT Image SID ds.add_new([0x5000,0x0030], 'SH', ['PIXL', 'PIXL']) #Axis Units x = tiff_meta_dict['XResolution'][0] ### Rever resolução IVIEW x_res = 1/((x[0]/x[1])/40.25) # mm por pixel ds.add_new([0x3002,0x0011], 'DS', [x_res,x_res]) #Image Plane Pixel Spacing print('Pronto!')
def _read_file_meta_info(fp: BinaryIO) -> FileMetaDataset: """Return a Dataset containing any File Meta (0002,eeee) elements in `fp`. File Meta elements are always Explicit VR Little Endian (DICOM Standard, Part 10, :dcm:`Section 7<part10/chapter_7.html>`). Once any File Meta elements are read `fp` will be positioned at the start of the next group of elements. Parameters ---------- fp : file-like The file-like positioned at the start of any File Meta Information group elements. Returns ------- dataset.Dataset The File Meta elements as a Dataset instance. May be empty if no File Meta are present. """ def _not_group_0002(tag: BaseTag, vr: Optional[str], length: int) -> bool: """Return True if the tag is not in group 0x0002, False otherwise.""" return tag.group != 2 start_file_meta = fp.tell() file_meta = FileMetaDataset( read_dataset(fp, is_implicit_VR=False, is_little_endian=True, stop_when=_not_group_0002)) if not file_meta._dict: return file_meta # Test the file meta for correct interpretation by requesting the first # data element: if it fails, retry loading the file meta with an # implicit VR (issue #503) try: file_meta[list(file_meta.elements())[0].tag] except NotImplementedError: fp.seek(start_file_meta) file_meta = FileMetaDataset( read_dataset(fp, is_implicit_VR=True, is_little_endian=True, stop_when=_not_group_0002)) # Log if the Group Length doesn't match actual length if 'FileMetaInformationGroupLength' in file_meta: # FileMetaInformationGroupLength must be 12 bytes long and its value # counts from the beginning of the next element to the end of the # file meta elements actual_len = fp.tell() - (start_file_meta + 12) elem_len = file_meta.FileMetaInformationGroupLength if elem_len != actual_len: logger.info( "_read_file_meta_info: (0002,0000) 'File Meta Information " "Group Length' value doesn't match the actual File Meta " f"Information length ({elem_len} vs {actual_len} bytes)") return file_meta
def dicom_object_3d(dicom_object): series = "1.2.345" study = "2.3.456" dcm = deepcopy(dicom_object) source = Path(pydicom.data.get_testdata_files("*CT*")[0]) # type: ignore dcm.StudyInstanceUID = study dcm.SeriesInstanceUID = series dcm.SOPInstanceUID = series file_meta = FileMetaDataset() file_meta.MediaStorageSOPClassUID = UID("1.2.345") file_meta.MediaStorageSOPInstanceUID = UID("2.3.456") def func(num_frames, syntax=ExplicitVRLittleEndian): file_meta.TransferSyntaxUID = syntax old_data = dcm.PixelData dcm.NumberOfFrames = num_frames if syntax.is_compressed: new_data = encapsulate([old_data for _ in range(num_frames)], has_bot=False) dcm.PixelData = new_data dcm.compress(syntax) else: new_data = b"".join(old_data for _ in range(num_frames)) dcm.PixelData = new_data dcm.file_meta = file_meta return dcm return func
def handle(event): meta = FileMetaDataset() meta.TransferSyntaxUID = event.context.transfer_syntax event.dataset.file_meta = meta event_out.append(event.dataset) return 0x0000
def empty_dicom(): file_meta = FileMetaDataset() file_meta.FileMetaInformationGroupLength = 206 file_meta.FileMetaInformationVersion = b'\x00\x01' file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' file_meta.MediaStorageSOPInstanceUID = '1.2.826.0.1.3680043.8.498.51645380419494159785729751472725175471' file_meta.TransferSyntaxUID = '1.2.840.10008.1.2.1' file_meta.ImplementationClassUID = '1.2.826.0.1.3680043.8.498.1' file_meta.ImplementationVersionName = 'PYDICOM 2.0.0' ds = Dataset() ds.ImageType = ['ORIGINAL', 'PRIMARY', 'AXIAL'] ds.SOPClassUID = '1.2.840.10008.5.1.4.1.1.2' ds.SOPInstanceUID = '1.2.826.0.1.3680043.8.498.51645380419494159785729751472725175471' ds.Modality = 'CT' ds.StudyInstanceUID = '1.2.826.0.1.3680043.8.498.75112040858074996916346159754932379994' ds.SeriesInstanceUID = '1.2.826.0.1.3680043.8.498.64119849432490865623274415908957426618' ds.InstanceNumber = "1" ds.FrameOfReferenceUID = '1.2.826.0.1.3680043.8.498.10194591012322579188814682575529857631' ds.ImagesInAcquisition = "1" ds.SamplesPerPixel = 1 ds.PhotometricInterpretation = 'MONOCHROME2' ds.BitsAllocated = 8 ds.BitsStored = 8 ds.HighBit = 7 ds.PixelRepresentation = 0 return ds, file_meta
def create_ds(): # Populate required values for file meta information file_meta = FileMetaDataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' file_meta.MediaStorageSOPInstanceUID = "1.2.3" file_meta.ImplementationClassUID = "1.2.3.4" # Create the FileDataset instance (initially no data elements, but file_meta # supplied) ds = FileDataset(FILENAME_PATH, {}, file_meta=file_meta, preamble=b"\0" * 128) # Add the data elements -- not trying to set all required here. Check DICOM # standard ds.PatientName = "Test^Firstname" ds.PatientID = "123456" # Set the transfer syntax ds.is_little_endian = True ds.is_implicit_VR = True # Set image position patient and image orientation patient ds.PixelSpacing = ['3.0', '3.0'] slice_data = numpy.zeros((50, 50)).astype(numpy.uint16) ds.ImagePositionPatient = [ '-74.87273061275482', '-147.24999237060547', '-147.1303328871727' ] ds.ImageOrientationPatient = [ '0.9995653468771569', '0.027916281967051135', '-0.00947620828628687', '-0.02835352390030065', '0.9983635539946439', '-0.04966177340388578' ] # set the settings for this slice ds.Rows = slice_data.shape[1] ds.Columns = slice_data.shape[0] ds.SamplesPerPixel = 1 ds.PhotometricInterpretation = 'MONOCHROME2' ds.PlanarConfiguration = 0 ds.BitsAllocated = 16 ds.BitsStored = 16 ds.HighBit = 15 ds.PixelRepresentation = 1 ds.WindowCenter = 0 ds.WindowWidth = 100 # Set creation date/time dt = datetime.datetime.now() ds.ContentDate = dt.strftime('%Y%m%d') timeStr = dt.strftime('%H%M%S.%f') # long format with micro seconds ds.ContentTime = timeStr return ds
def set_file_meta(instance: Dataset): meta = FileMetaDataset() # meta.FileMetaInformationGroupLength = ?? # meta.FileMetaInformationVersion = b'\x00\x01' meta.MediaStorageSOPClassUID = instance.SOPClassUID meta.MediaStorageSOPInstanceUID = instance.SOPInstanceUID meta.TransferSyntaxUID = ImplicitVRLittleEndian instance.is_implicit_VR = instance.is_little_endian = True # meta.ImplementationClassUID = ?? # meta.ImplementationVersionName = ?? instance.file_meta = meta instance.preamble = b'\x00' * 128
def get_file_meta() -> FileMetaDataset: file_meta = FileMetaDataset() file_meta.FileMetaInformationGroupLength = 202 file_meta.FileMetaInformationVersion = b'\x00\x01' file_meta.TransferSyntaxUID = ImplicitVRLittleEndian file_meta.MediaStorageSOPClassUID = SOPClassUID.RTSTRUCT file_meta.MediaStorageSOPInstanceUID = generate_uid() # TODO find out random generation is fine file_meta.ImplementationClassUID = SOPClassUID.RTSTRUCT_IMPLEMENTATION_CLASS return file_meta
def get_file_meta(dcms): dcm = dcms[0] file_meta = FileMetaDataset() file_meta.FileMetaInformationVersion = dcm.file_meta.FileMetaInformationVersion file_meta.MediaStorageSOPClassUID = "RT Structure Set Storage" file_meta.MediaStorageSOPInstanceUID = "Anonymous" # TODO file_meta.TransferSyntaxUID = dcm.file_meta.TransferSyntaxUID file_meta.ImplementationClassUID = dcm.file_meta.ImplementationClassUID file_meta.ImplementationVersionName = dcm.file_meta.ImplementationVersionName return file_meta
def __init__(self, ct_path, mask, structures=None, output=None): if structures is None: structures = [] self.ct_path = ct_path self.mask = mask self.structures = structures self.output = output or "RS.dcm" self.ct_files = natsorted([os.path.join(self.ct_path, ct) for ct in os.listdir(self.ct_path) if ct.endswith("dcm")]) self.ds_cts = [dcmread(ct_file) for ct_file in self.ct_files] self.ds_ct_sop_instance_uid = [ds_ct.SOPInstanceUID for ds_ct in self.ds_cts] self.ds_ct_reference = self.ds_cts[0] self.mask = Mask(self.mask, ds_cts=self.ds_cts, ct_path=self.ct_path) self.ds_rs = Dataset() # RS meta self.ds_rs.file_meta = FileMetaDataset() self.ds_rs.file_meta.MediaStorageSOPClassUID = 'RT Structure Set Storage' self.ds_rs.file_meta.MediaStorageSOPInstanceUID = '1.2.345.678.9.1.11111111111111111.1111.11111' # RS transfer syntax self.ds_rs.is_little_endian = True self.ds_rs.is_implicit_VR = True # RS creation date/time date_time = datetime.datetime.now() self.ds_rs.ContentDate = date_time.strftime('%Y%m%d') time_str = date_time.strftime('%H%M%S') self.ds_rs.ContentTime = time_str # RS common tags for tag in COMMON_TAGS: if tag in self.ds_ct_reference: self.ds_rs[tag] = self.ds_ct_reference[tag] # RS series self.ds_rs.Modality = 'RTSTRUCT' self.ds_rs.SOPClassUID = UID('1.2.840.10008.5.1.4.1.1.481.3') self.ds_rs.SOPInstanceUID = generate_uid() self.ds_rs.ManufacturerModelName = "segmentation_RT" self.ds_rs.StructureSetLabel = 'RS: Unapproved' self.ds_rs.ApprovalStatus = 'UNAPPROVED' # RS empty sequences self.ds_rs.add_new('RTROIObservationsSequence', 'SQ', Sequence()) self.ds_rs.add_new('StructureSetROISequence', 'SQ', Sequence()) self.ds_rs.add_new('ROIContourSequence', 'SQ', Sequence()) self.ds_rs.add_new('ReferencedFrameOfReferenceSequence', 'SQ', Sequence()) # RS referenced frame of reference sequence self.add_referenced_frame_of_reference_sequence()
def DICOM_File_Meta_Information(ds): # File meta info data elements file_meta = FileMetaDataset() # file_meta.FileMetaInformationGroupLength = 210 # file_meta.FileMetaInformationVersion = b'\x00\x01' file_meta.MediaStorageSOPClassUID = ds.SOPClassUID file_meta.MediaStorageSOPInstanceUID = ds.SOPInstanceUID file_meta.TransferSyntaxUID = '1.2.840.10008.1.2.1' file_meta.ImplementationClassUID = '1.2.276.0.20.1.1.33.6.1.0' file_meta.ImplementationVersionName = 'PatientSelect6.1' file_meta.SourceApplicationEntityTitle = 'kESI' return file_meta
def setup(self): """Run prior to each test""" self.ae = None self.ds = Dataset() self.ds.file_meta = FileMetaDataset() self.ds.file_meta.TransferSyntaxUID = ImplicitVRLittleEndian self.ds.SOPClassUID = CTImageStorage self.ds.SOPInstanceUID = '1.1.1' self.ds.PatientName = 'Test'
def setup(self): """Run prior to each test""" self.ae = None self.func = start_getscu_cli self.response = ds = Dataset() ds.file_meta = FileMetaDataset() ds.file_meta.TransferSyntaxUID = ImplicitVRLittleEndian ds.SOPClassUID = CTImageStorage ds.SOPInstanceUID = "1.2.3.4" ds.PatientName = "Citizen^Jan"
def setup(self): """Setup the tests.""" # Create a dataset skeleton for use in the cycle tests ds = Dataset() ds.file_meta = FileMetaDataset() ds.file_meta.TransferSyntaxUID = '1.2.840.10008.1.2' ds.Rows = 2 ds.Columns = 4 ds.SamplesPerPixel = 3 ds.PlanarConfiguration = 1 self.ds = ds
def _build_dummy_pydicom_header(fields=None): """Builds dummy pydicom-based header. Note these headers are not dicom compliant and should not be used to write out DICOM files. Adapted from https://pydicom.github.io/pydicom/dev/auto_examples/input_output/plot_write_dicom.html """ suffix = ".dcm" filename_little_endian = tempfile.NamedTemporaryFile(suffix=suffix).name file_meta = FileMetaDataset() file_meta.MediaStorageSOPClassUID = "1.2.840.10008.5.1.4.1.1.2" file_meta.MediaStorageSOPInstanceUID = "1.2.3" file_meta.ImplementationClassUID = "1.2.3.4" # Create the FileDataset instance (initially no data elements, but file_meta supplied). ds = FileDataset(filename_little_endian, {}, file_meta=file_meta, preamble=b"\0" * 128) # Add the data elements -- not trying to set all required here. Check DICOM standard. ds.PatientName = "Test^Firstname" ds.PatientID = "123456" if fields is not None: for k, v in fields.items(): setattr(ds, k, v) # Set the transfer syntax ds.is_little_endian = True ds.is_implicit_VR = True # Set creation date/time dt = datetime.datetime.now() ds.ContentDate = dt.strftime("%Y%m%d") timeStr = dt.strftime("%H%M%S.%f") # long format with micro seconds ds.ContentTime = timeStr return ds
def _dicom(filename='image.dcm', **values): filename = str(tmpdir.join(filename)) file_meta = FileMetaDataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' file_meta.MediaStorageSOPInstanceUID = '1.2.3' file_meta.ImplementationClassUID = '1.2.3.4' ds = FileDataset(filename, {}, file_meta=file_meta, preamble=b'\0' * 128) ds.is_little_endian = True ds.is_implicit_VR = False ds.PatientName = 'Jonathan^Suever' ds.SeriesDescription = 'Dicom Sort Test Series' ds.SeriesNumber = 1 ds.update(values) ds.save_as(filename) return filename, ds
def _basic_file_meta(class_UID): """Create basic file meta for DICOM dataset.""" # File meta info data elements file_meta = FileMetaDataset() file_meta.FileMetaInformationVersion = b'\x00\x01' file_meta.MediaStorageSOPClassUID = class_UID file_meta.MediaStorageSOPInstanceUID = generate_uid() file_meta.TransferSyntaxUID = '1.2.840.10008.1.2' return file_meta
def dicom_from_image_layer(image_layer): suffix = '.dcm' filename_little_endian = tempfile.NamedTemporaryFile(suffix=suffix).name filename_big_endian = tempfile.NamedTemporaryFile(suffix=suffix).name file_meta = FileMetaDataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' file_meta.MediaStorageSOPInstanceUID = "1.2.3" file_meta.ImplementationClassUID = "1.2.3.4" ds = FileDataset(filename_little_endian, {}, file_meta=file_meta, preamble=b"\0" * 128) ds.PatientName = "Test^Firstname" ds.PatientID = "123456" ds.PixelData = image_layer.data.tostring() ds.is_little_endian = True ds.is_implicit_VR = True dt = datetime.datetime.now() ds.ContentDate = dt.strftime('%Y%m%d') timeStr = dt.strftime('%H%M%S.%f') # long format with micro seconds ds.ContentTime = timeStr return ds
def _create_temporary_dataset(shape=(100, 1024, 1024, 3), bit_depth=16): """Function to create a temporary dataset for use in testing. Parameters ---------- shape : 4-tuple The (frames, rows, columns, channels) of the test dataset. bit_depth : int The BitsAllocated value to use for the dataset, one of 8, 16, 32, 64. Returns ------- tempfile.TemporaryFile A created DICOM File Format conformant dataset. """ ds = Dataset() ds.is_little_endian = True ds.is_implicit_VR = False ds.file_meta = FileMetaDataset() ds.file_meta.TransferSyntaxUID = ExplicitVRLittleEndian ds.SOPClassUID = '1.2.3.4' ds.SOPInstanceUID = generate_uid() ds.BitsAllocated = bit_depth ds.PixelRepresentation = 0 ds.PlanarConfiguration = 0 ds.Rows = shape[1] ds.Columns = shape[2] ds.NumberOfFrames = shape[0] ds.SamplesPerPixel = shape[3] if shape[3] == 1: ds.PhotometricInterpretation = 'MONOCHROME2' elif shape[3] == 3: ds.PhotometricInterpretation = 'RGB' arr = np.zeros(shape, dtype='uint{}'.format(bit_depth)) ds.PixelData = arr.tobytes() if len(ds.PixelData) % 2: ds.PixelData += b'\x00' tfile = TemporaryFile(mode='w+b') ds.save_as(tfile, write_like_original=False) tfile.seek(0) return tfile
def handle_store(event): """Store the pydicom Dataset `ds`. Parameters ---------- event : pydicom.event Returns ------- status : int or pydicom.dataset.Dataset The status returned to the peer AE in the C-STORE response. Must be a valid C-STORE status value for the applicable Service Class as either an ``int`` or a ``Dataset`` object containing (at a minimum) a (0000,0900) *Status* element. """ global scpdir ds = event.dataset context = event.context # logging.debug('on_c_store: info {}'.format(info)) # calling_aet = info['requestor']['ae_title'] # called_aet = info['acceptor']['ae_title'] # logging.debug('on_c_store: calling_aet {}'.format(calling_aet)) # logging.debug('on_c_store: called_aet {}'.format(called_aet)) # Add the DICOM File Meta Information meta = FileMetaDataset() meta.MediaStorageSOPClassUID = ds.SOPClassUID meta.MediaStorageSOPInstanceUID = ds.SOPInstanceUID meta.ImplementationClassUID = PYNETDICOM_IMPLEMENTATION_UID meta.ImplementationVersionName = PYNETDICOM_IMPLEMENTATION_VERSION meta.TransferSyntaxUID = context.transfer_syntax # Add the file meta to the dataset ds.file_meta = meta # Set the transfer syntax attributes of the dataset ds.is_little_endian = context.transfer_syntax.is_little_endian ds.is_implicit_VR = context.transfer_syntax.is_implicit_VR # Save the dataset using the SOP Instance UID as the filename ds.save_as( os.path.join(scpdir.name, ds.SOPInstanceUID), write_like_original=False) # Return a 'Success' status return 0x0000
def DicomRT(path, file_name, region_number): file_path = path + 'Dicom/' + file_name dsorg = pydicom.read_file(file_path, force=True) dcmfiles = os.listdir(path + 'Dicom/') IOP = dsorg.ImageOrientationPatient plane = file_plane(IOP) planVal = dsorg.ImagePositionPatient[plane] planVal = float(planVal) xp_rt = dsorg.ImagePositionPatient[0] yp_rt = dsorg.ImagePositionPatient[1] x_rt = dsorg.Columns y_rt = dsorg.Rows uid1 = generate_uid() uid2 = generate_uid() # File meta info data elements file_meta = FileMetaDataset() file_meta.FileMetaInformationGroupLength = 182 file_meta.FileMetaInformationVersion = b'\x00\x01' file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.481.3' file_meta.MediaStorageSOPInstanceUID = uid1 #'1.2.826.0.1.534147.578.2719282597.2020101685637449' file_meta.TransferSyntaxUID = '1.2.840.10008.1.2.1' file_meta.ImplementationClassUID = '1.2.40.0.13.1.1' file_meta.ImplementationVersionName = 'dcm4che-2.0' ds = Dataset() # Main data elements ds = Dataset() ds.SOPClassUID = '1.2.840.10008.5.1.4.1.1.481.3' ds.SOPInstanceUID = uid1 #'1.2.826.0.1.534147.578.2719282597.2020101685637449' ds.StudyDate = dsorg.StudyDate #'20450916' ds.StudyTime = dsorg.StudyTime # '000000' ds.AccessionNumber = '' ds.Modality = 'RTSTRUCT' ds.Manufacturer = dsorg.Manufacturer # 'SIEMENS' ds.ReferringPhysicianName = '' ds.OperatorsName = '' ds.ManufacturerModelName = dsorg.ManufacturerModelName # SOMATOM Definition Edge' ds.PatientName = dsorg.PatientName # 'Covid7175' ds.PatientID = dsorg.PatientID # 'Covid7175' ds.PatientBirthDate = dsorg.PatientBirthDate # '19300101' ds.PatientSex = dsorg.PatientSex # 'F' ds.SoftwareVersions = dsorg.SoftwareVersions # 'syngo CT VA48A' ds.StudyInstanceUID = dsorg.StudyInstanceUID #'1.2.826.0.1.3680043.9.3218.1.1.302475.1985.1592890895061.53221.0' # dsOrg.StudyInstanceUID ds.SeriesInstanceUID = uid2 #'1.2.826.0.1.534147.578.2719282597.2020101685637450' ds.StudyID = '' ds.SeriesNumber = None ds.FrameOfReferenceUID = dsorg.FrameOfReferenceUID #'1.2.826.0.1.3680043.9.3218.1.1.302475.1985.1592890895061.53224.0' # dsOrg.FrameOfReferenceUID ds.PositionReferenceIndicator = '' ds.StructureSetLabel = 'AIM_Multi3_' + str( dsorg.InstanceNumber) + '_' + str(region_number) #Scaling04 ds.StructureSetDate = '20201116' ds.StructureSetTime = '085637' # Referenced Frame of Reference Sequence refd_frame_of_ref_sequence = Sequence() ds.ReferencedFrameOfReferenceSequence = refd_frame_of_ref_sequence # Referenced Frame of Reference Sequence: Referenced Frame of Reference 1 refd_frame_of_ref1 = Dataset() refd_frame_of_ref1.FrameOfReferenceUID = dsorg.FrameOfReferenceUID # '1.2.826.0.1.3680043.9.3218.1.1.302475.1985.1592890895061.53224.0' # RT Referenced Study Sequence rt_refd_study_sequence = Sequence() refd_frame_of_ref1.RTReferencedStudySequence = rt_refd_study_sequence # RT Referenced Study Sequence: RT Referenced Study 1 rt_refd_study1 = Dataset() rt_refd_study1.ReferencedSOPClassUID = '1.2.840.10008.3.1.2.3.1' rt_refd_study1.ReferencedSOPInstanceUID = dsorg.StudyInstanceUID #'1.2.826.0.1.3680043.9.3218.1.1.302475.1985.1592890895061.53221.0' # # RT Referenced Series Sequence rt_refd_series_sequence = Sequence() rt_refd_study1.RTReferencedSeriesSequence = rt_refd_series_sequence # RT Referenced Series Sequence: RT Referenced Series 1 rt_refd_series1 = Dataset() rt_refd_series1.SeriesInstanceUID = dsorg.SeriesInstanceUID #'1.2.826.0.1.3680043.9.3218.1.1.302475.1985.1592890895061.53222.0' # Contour Image Sequence contour_image_sequence = Sequence() rt_refd_series1.ContourImageSequence = contour_image_sequence # Contour Image Sequence: Contour Image 1 ******************************** i = 0 contour_image = [] for dcmname in dcmfiles: if '.dcm' in dcmname: dsorg = pydicom.read_file(path + 'Dicom/' + dcmname, force=True) contour_image.append(Dataset()) contour_image[i] = Dataset() contour_image[ i].ReferencedSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' contour_image[ i].ReferencedSOPInstanceUID = dsorg.SOPInstanceUID #'1.2.826.0.1.3680043.9.3218.1.1.302475.1985.1592890895061.53223.0' contour_image[i].ReferencedFrameNumber = "1" contour_image_sequence.append(contour_image[i]) i = i + 1 # contour_image1 = Dataset() # contour_image1.ReferencedSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' # contour_image1.ReferencedSOPInstanceUID = dsorg.SOPInstanceUID #'1.2.826.0.1.3680043.9.3218.1.1.302475.1985.1592890895061.53223.0' # contour_image1.ReferencedFrameNumber = "1" # contour_image_sequence.append(contour_image1) rt_refd_series_sequence.append(rt_refd_series1) rt_refd_study_sequence.append(rt_refd_study1) refd_frame_of_ref_sequence.append(refd_frame_of_ref1) # Structure Set ROI Sequence structure_set_roi_sequence = Sequence() ds.StructureSetROISequence = structure_set_roi_sequence # Structure Set ROI Sequence: Structure Set ROI 1 structure_set_roi1 = Dataset() structure_set_roi1.ROINumber = "1" structure_set_roi1.ReferencedFrameOfReferenceUID = dsorg.FrameOfReferenceUID #'1.2.826.0.1.3680043.9.3218.1.1.302475.1985.1592890895061.53224.0' # structure_set_roi1.ROIName = 'TestScale' structure_set_roi1.ROIGenerationAlgorithm = '' structure_set_roi_sequence.append(structure_set_roi1) # ROI Contour Sequence roi_contour_sequence = Sequence() ds.ROIContourSequence = roi_contour_sequence # ROI Contour Sequence: ROI Contour 1 roi_contour1 = Dataset() # Contour Sequence contour_sequence = Sequence() roi_contour1.ContourSequence = contour_sequence # Contour Sequence: Contour 1 contour = [] #dcmfiles = os.listdir(path+'Dicom/') came to beginig of the function i = 0 for dcmname in dcmfiles: #print(dcmname) if '.dcm' in dcmname: pnyfiles = os.listdir(path + 'borders/') for pnyname in pnyfiles: if dcmname in pnyname: #print(pnyname) dsorg = pydicom.read_file(path + 'Dicom/' + dcmname, force=True) IOP = dsorg.ImageOrientationPatient plane = file_plane(IOP) planVal = dsorg.ImagePositionPatient[plane] planVal = float(planVal) xp_rt = dsorg.ImagePositionPatient[0] yp_rt = dsorg.ImagePositionPatient[1] x_rt = dsorg.Columns y_rt = dsorg.Rows # Put Contoure pixel cordination Inside file with open(path + 'Borders/' + pnyname, 'rb') as f: num = np.load(f) print(pnyname) print(planVal) borders = [] for t in range(len(num)): #print(t,num[t]) if plane == 0: #"Sagittal" x = planVal y = newPosition(num[t][1], 0, xp_rt, yp_rt, x_rt, y_rt) z = newPosition(num[t][0], 1, xp_rt, yp_rt, x_rt, y_rt) elif plane == 1: #"Coronal" x = newPosition(num[t][1], 0, xp_rt, yp_rt, x_rt, y_rt) y = planVal z = newPosition(num[t][0], 1, xp_rt, yp_rt, x_rt, y_rt) elif plane == 2: # "Transverse" x = newPosition(num[t][1], 0, xp_rt, yp_rt, x_rt, y_rt) y = newPosition(num[t][0], 1, xp_rt, yp_rt, x_rt, y_rt) z = planVal borders.extend([x, y, z]) print(i) contour.append(Dataset()) contour[i] = Dataset() # Contour Image Sequence contour_image_sequence = Sequence() contour[i].ContourImageSequence = contour_image_sequence # Contour Image Sequence: Contour Image 1 contour_image1 = Dataset() contour_image1.ReferencedSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' contour_image1.ReferencedSOPInstanceUID = dsorg.SOPInstanceUID #'1.2.826.0.1.3680043.9.3218.1.1.302475.1985.1592890895061.53223.0' contour_image1.ReferencedFrameNumber = "1" contour_image_sequence.append(contour_image1) contour[i].ContourGeometricType = 'CLOSED_PLANAR' contour[i].NumberOfContourPoints = len(borders) / 3 #"4" contour[i].ContourNumber = "1" contour[ i].ContourData = borders # [-276.91503267973, -162.50000000000, 516.398692810457, 270.222222222222, -162.50000000000, 514.725490196078, 271.895424836601, -162.50000000000, -177.98039215686, -271.89542483660, -162.50000000000, -176.30718954248] contour_sequence.append(contour[i]) i = i + 1 roi_contour1.ReferencedROINumber = "1" roi_contour_sequence.append(roi_contour1) # RT ROI Observations Sequence rtroi_observations_sequence = Sequence() ds.RTROIObservationsSequence = rtroi_observations_sequence # RT ROI Observations Sequence: RT ROI Observations 1 rtroi_observations1 = Dataset() rtroi_observations1.ObservationNumber = "1" rtroi_observations1.ReferencedROINumber = "1" rtroi_observations1.RTROIInterpretedType = '' rtroi_observations1.ROIInterpreter = '' rtroi_observations_sequence.append(rtroi_observations1) ds.file_meta = file_meta ds.is_implicit_VR = False ds.is_little_endian = True ds.save_as(path + 'RTSTRUCT/rt' + str(region_number) + '-' + file_name, write_like_original=False)
def OnRest(output, uri, **request): config = orthancConfig try: worklistdir = config["Worklists"]["Database"] asnofile = os.sep.join([worklistdir, 'accessionid.conf']) except KeyError: output.AnswerBuffer('internal configuration error\n', 'text/plain') return try: today = datetime.today() try: with open(asnofile, 'r') as f: try: asno = int(f.read()) except ValueError: asno = 1 except OSError: asno = 1 with open(asnofile, 'w') as f: f.write(str(asno + 1)) # File meta info data elements file_meta = FileMetaDataset() file_meta.FileMetaInformationGroupLength = 202 file_meta.FileMetaInformationVersion = b'\x00\x01' file_meta.MediaStorageSOPClassUID = '1.2.276.0.7230010.3.1.0.1' file_meta.MediaStorageSOPInstanceUID = pydicom.uid.generate_uid( prefix=None) file_meta.TransferSyntaxUID = '1.2.840.10008.1.2.1' file_meta.ImplementationClassUID = '1.2.276.0.7230010.3.0.1.0.0' file_meta.ImplementationVersionName = 'ORTHANC_RESTWORKLIST_1' # Main data elements ds = Dataset() ds.SpecificCharacterSet = 'ISO_IR 192' dcm_store_path = os.sep.join([ worklistdir, 'R{:010d}-{}.{}'.format(asno, today.strftime('%Y%m%d%H%M%S'), 'wl') ]) ds.AccessionNumber = 'R{:010d}'.format(asno) try: ds.PatientName = '{}^{}'.format(request["get"]["lastname"], request["get"]["firstname"]) except KeyError: ds.PatientName = '{}^{}'.format( request["get"]["name"], request["get"]["surname"] ) # old, buggy parameter naming -> for backwards compatibility ds.PatientID = request["get"]["id"] bdparts = request["get"]["birthdate"].split('.') ds.PatientBirthDate = '{2}{1}{0}'.format(*bdparts) ds.PatientSex = sexReplacement[request["get"][ "sex"]] # LUT for the sex identifier numbers used by Medical Office (0 = Other / Unknown, 1 = Male, 2 = Female, 3 = Other / Unknown) ds.StudyInstanceUID = pydicom.uid.generate_uid(prefix=None) try: ds.RequestedProcedureDescription = request["get"]["procedure"] except KeyError: pass # optional argument, otherwise this tag remains empty # Scheduled Procedure Step Sequence scheduled_procedure_step_sequence = Sequence() ds.ScheduledProcedureStepSequence = scheduled_procedure_step_sequence # Scheduled Procedure Step Sequence: Scheduled Procedure Step 1 scheduled_procedure_step1 = Dataset() try: scheduled_procedure_step1.Modality = request["get"]["modality"] except KeyError: scheduled_procedure_step1.Modality = 'US' # fallback to default (backwards compatibility) try: scheduled_procedure_step1.ScheduledStationAETitle = request["get"][ "scheduledStation"] except KeyError: scheduled_procedure_step1.ScheduledStationAETitle = 'US01' # fallback to default (backwards compatibility) scheduled_procedure_step1.ScheduledProcedureStepStartDate = today.strftime( '%Y%m%d') scheduled_procedure_step1.ScheduledProcedureStepStartTime = today.strftime( '%H%M%S') try: scheduled_procedure_step1.ScheduledPerformingPhysicianName = request[ "get"]["physician"] except KeyError: pass # optional, leave empty if not specified scheduled_procedure_step_sequence.append(scheduled_procedure_step1) ds.file_meta = file_meta ds.is_implicit_VR = False ds.is_little_endian = True ds.save_as(dcm_store_path, write_like_original=False) output.AnswerBuffer( gdtResponse(request["get"]["id"], today, ds.AccessionNumber, request["get"]["procedure"]), 'text/plain') if "UrlOnWorklistEntryAdded" in config["Worklists"]: with urllib.request.urlopen( config["Worklists"]["UrlOnWorklistEntryAdded"]): orthanc.LogWarning("Called {} as configured.".format( config["Worklists"]["UrlOnWorklistEntryAdded"])) except KeyError as e: output.AnswerBuffer('error: {}\n'.format(e), 'text/plain') raise
import os import tempfile import datetime import pydicom from pydicom.dataset import Dataset, FileDataset, FileMetaDataset # Create some temporary filenames suffix = '.dcm' filename_little_endian = tempfile.NamedTemporaryFile(suffix=suffix).name filename_big_endian = tempfile.NamedTemporaryFile(suffix=suffix).name print("Setting file meta information...") # Populate required values for file meta information file_meta = FileMetaDataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' file_meta.MediaStorageSOPInstanceUID = "1.2.3" file_meta.ImplementationClassUID = "1.2.3.4" print("Setting dataset values...") # Create the FileDataset instance (initially no data elements, but file_meta # supplied) ds = FileDataset(filename_little_endian, {}, file_meta=file_meta, preamble=b"\0" * 128) # Add the data elements -- not trying to set all required here. Check DICOM # standard ds.PatientName = "Test^Firstname" ds.PatientID = "123456"
def generate_dicom_sr(file_path, img_ds, data, series_description): """ Generates DICOM Structured Report files for the given file path. :param file_path: the file name and directory to save the DICOM SR file in. :param img_ds: A CT or MR image from the dataset used to pull general information for the DICOM SR. :param data: Text data to be written to the DICOM SR file. :param series_description: Description of text data written to SR. :return: dicom_sr, a dataset for the new DICOM SR file. """ if img_ds is None: raise ValueError("No CT data to initialize RT SS") # Create file meta file_meta = FileMetaDataset() file_meta.FileMetaInformationGroupLength = 238 file_meta.FileMetaInformationVersion = b'\x00\x01' file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.88.33' file_meta.MediaStorageSOPInstanceUID = pydicom.uid.generate_uid() file_meta.TransferSyntaxUID = ImplicitVRLittleEndian validate_file_meta(file_meta) # Create dataset dicom_sr = pydicom.dataset.FileDataset(file_path, {}, preamble=b"\0" * 128, file_meta=file_meta) dicom_sr.fix_meta_info() # Get current date and time now = datetime.datetime.now() dicom_date = now.strftime("%Y%m%d") dicom_time = now.strftime("%H%M") # List of tags to copy from CT/MR image top_level_tags_to_copy: list = [ Tag("PatientName"), Tag("PatientID"), Tag("PatientBirthDate"), Tag("PatientSex"), Tag("StudyDate"), Tag("StudyTime"), Tag("ReferringPhysicianName"), Tag("StudyDescription"), Tag("StudyInstanceUID"), Tag("StudyID"), Tag("RequestingService"), Tag("PatientAge"), Tag("PatientSize"), Tag("PatientWeight"), Tag("MedicalAlerts"), Tag("Allergies"), Tag("PregnancyStatus"), Tag("InstitutionName"), Tag("InstitutionAddress") ] # Copy tags from CT/MR image for tag in top_level_tags_to_copy: if tag in img_ds: dicom_sr[tag] = deepcopy(img_ds[tag]) dicom_sr.AccessionNumber = "" # == SR Document Series Module dicom_sr.SeriesDate = dicom_date dicom_sr.SeriesTime = dicom_time dicom_sr.Modality = "SR" dicom_sr.SeriesDescription = series_description # Can be empty referenced_performed_procedure_step_sequence = Sequence() dicom_sr.ReferencedPerformedProcedureStepSequence = \ referenced_performed_procedure_step_sequence dicom_sr.SeriesInstanceUID = pydicom.uid.generate_uid() dicom_sr.SeriesNumber = 1 # == General Equipment Module dicom_sr.Manufacturer = "OnkoDICOM" dicom_sr.ManufacturersModelName = "OnkoDICOM" # TODO: Pull this off build information in some way dicom_sr.SoftwareVersions = "2021" # == SR Document General Module dicom_sr.ContentDate = dicom_date dicom_sr.ContentTime = dicom_time dicom_sr.InstanceNumber = 1 # Empty if unknown performed_procedure_code_sequence = Sequence() dicom_sr.PerformedProcedureCodeSequence = performed_procedure_code_sequence # Do not want to mark as complete in case it isn't! dicom_sr.CompletionFlag = "PARTIAL" dicom_sr.VerificationFlag = "UNVERIFIED" # == SR Document Content Module referenced_sop_sequence = Sequence([Dataset()]) referenced_sop_sequence[0].ReferencedSOPClassUID = '' referenced_sop_sequence[0].ReferencedSOPInstanceUID = '' dicom_sr.ReferencedSOPSequence = referenced_sop_sequence dicom_sr.ValueType = "CONTAINER" dicom_sr.ContinuityOfContent = "CONTINUOUS" dicom_sr.TemporalRangeTime = "" dicom_sr.ReferencedTimeOffsets = "" dicom_sr.ReferencedDateTime = "" dicom_sr.MeasuredValueSequence = Sequence() og_frame_of_reference_UID = \ deepcopy(img_ds[Tag("FrameOfReferenceUID")].value) dicom_sr.ReferencedFrameOfReferenceUID = og_frame_of_reference_UID # == Content Sequence content_sequence = Sequence([Dataset()]) content_sequence[0].RelationshipType = 'CONTAINS' content_sequence[0].ValueType = 'TEXT' concept_name_code_sequence = Sequence([Dataset()]) concept_name_code_sequence[0].CodeValue = '' concept_name_code_sequence[0].CodingSchemeDesignator = '' concept_name_code_sequence[0].CodeMeaning = '' content_sequence[0].ConceptNameCodeSequence = concept_name_code_sequence content_sequence[0].TextValue = data dicom_sr.ContentSequence = content_sequence # == SOP Common Module dicom_sr.SOPClassUID = '1.2.840.10008.5.1.4.1.1.88.33' dicom_sr.SOPInstanceUID = file_meta.MediaStorageSOPInstanceUID dicom_sr.is_little_endian = True dicom_sr.is_implicit_VR = True return dicom_sr
def anonymizeDicom(self, dcm, dict_study): ''' Anonymize a dicom by pre-defined rules dcm: loaded dicom file to anonymize dict: additional information obtained outside the dicom, such as exam_id, series_id from directory return an anonymized dicom by creating a new one ''' # suffix = '.dcm' # filename_little_endian = tempfile.NamedTemporaryFile(suffix=suffix).name # print(dcm.file_meta) file_meta = FileMetaDataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' file_meta.MediaStorageSOPInstanceUID = "1.2.3" file_meta.ImplementationClassUID = "1.2.3.4" # anonyDcmObj = pydicom.dataset.Dataset() anonyDcmObj = FileDataset([], {}, file_meta=file_meta, preamble=b"\0" * 128) # print(anonyDcmObj.file_meta) # FileDataset(filename_little_endian, {}, # file_meta=file_meta, preamble=b"\0" * 128) # copy pixel_array arr = dcm.pixel_array anonyDcmObj.PixelData = arr.tobytes() # set the required fields anonyDcmObj.preamble = dcm.preamble anonyDcmObj.file_meta = file_meta #dcm.file_meta anonyDcmObj.is_little_endian = dcm.is_little_endian anonyDcmObj.is_implicit_VR = dcm.is_implicit_VR # Test #anonyDcmObj.file_meta.MediaStorageSOPClassUID = [] for sTag in self.tagsHandler: vr = self.lookupTable["dictionary_vr"][sTag] tag = self.str2tag(sTag) if self.tagsHandler[sTag]["method"] == "keep": if tag in dcm: elem = dcm[tag] anonyDcmObj.add(elem) elif tag in dcm.file_meta: elem = dcm.file_meta[tag] # setattr(anonyDcmObj.file_meta, tag, elem) anonyDcmObj.file_meta.add(elem) # because file_meta has already been copied pass elif self.tagsHandler[sTag]["method"] == "const": if tag in dcm or tag in dcm.file_meta: if tag in dcm: elem = dcm[tag] elem.value = self.tagsHandler[sTag]["value"] anonyDcmObj.add(elem) else: elem = dcm.file_meta[tag] elem.value = self.tagsHandler[sTag]["value"] # setattr(anonyDcmObj.file_meta, tag, elem.value) anonyDcmObj.file_meta.add(elem) # The tag belongs to file_meta # anonyDcmObj.file_meta[tag].value = self.tagsHandler[sTag]["value"] elif self.tagsHandler[sTag]["method"] == "lookup": if tag in dcm: tagName = self.lookupTable["Tag2Name"][str(tag).replace( " ", "")] elem = dcm[tag] if tagName == 'PatientName': tagVal = 'Lrm_' + str( dcm[tag].value).split('_')[1] + '_assess' else: tagVal = str(dcm[tag].value) elem.value = self.lookupTable[tagName][tagVal] anonyDcmObj.add(elem) elif self.tagsHandler[sTag]["method"] == "less_than": if tag in dcm: sVal = dcm[tag].value iVal = int(self.extractDigits(sVal)) maxVal = int(self.tagsHandler[sTag]["value"]) if iVal > maxVal: modifiedVal = maxVal else: modifiedVal = iVal elem = dcm[tag] elem.value = "{:03d}Y".format(modifiedVal) anonyDcmObj.add(elem) elif self.tagsHandler[sTag]["method"] == "random": if tag in dcm or tag in dcm.file_meta: if self.tagsHandler[sTag][ "tagID"] == "0020,000e": #SeriesInstanceUID rand_str = '.'.join([ dict_study['rand_6_SeriesInstanceUID'], dict_study['rand_5_SeriesInstanceUID'], '2.1.1', dict_study['rand_tail_SeriesInstanceUID'] ]) elif self.tagsHandler[sTag][ "tagID"] == "0008,0018": #SOPInstanceUID rand_str = '.'.join([ dict_study['rand_6_SOPInstanceUID'], dict_study['rand_5_SOPInstanceUID'], '2.1.3', dict_study['rand_tail_SOPInstanceUID'] ]) elif self.tagsHandler[sTag][ "tagID"] == "0020,000d": #StudyInstanceUID rand_str = '.'.join([ dict_study['rand_6_StudyInstanceUID'], dict_study['rand_5_StudyInstanceUID'], '2.1.1', dict_study['rand_tail_StudyInstanceUID'] ]) elif self.tagsHandler[sTag][ "tagID"] == "0002,0003": #MediaStorageSOPInstanceUID rand_str = '.'.join([ dict_study['rand_6_MediaStorageSOPInstanceUID'], dict_study['rand_5_MediaStorageSOPInstanceUID'], '2.1.3', dict_study['rand_tail_MediaStorageSOPInstanceUID'] ]) if tag in dcm: elem = dcm[tag] elem.value = rand_str anonyDcmObj.add(elem) elif tag in dcm.file_meta: elem = dcm.file_meta[tag] elem.value = rand_str anonyDcmObj.file_meta.add(elem) else: raise NameError('Unknown Method') return anonyDcmObj
else: endIndex = len(seriesDCM) - z - 1 break smask = np.zeros((seg_mask.shape[0], seg_mask.shape[1], endIndex-startIndex+1)) for z in range(startIndex, endIndex + 1): for r in range(seg_mask.shape[0]): for c in range(seg_mask.shape[1]): smask[r][c][z - startIndex] = seg_mask[r][c][z] print("Seg_mask array created") stop = timeit.default_timer() print("Runtime (mask creation): " + str(stop-start) + "s") file_meta = FileMetaDataset() file_meta.MediaStorageSOPClassUID='1.2.840.10008.5.1.4.1.1.66.4' dicomuid = generate_uid() instanceuid=dicomuid file_meta.MediaStorageSOPInstanceUID=instanceuid file_meta.TransferSyntaxUID=ExplicitVRLittleEndian file_meta.ImplementationClassUID='1.2.840.10008.5.1.4.1.1.66.4' file_meta.ImplementationVersionName='ePAD_matlab_1.0' suffix = '.dcm' info = seriesDCM[0] info_mask = FileDataset('output/' + str(name) + str(suffix), {}, file_meta=file_meta, preamble=b"\0" * 128) info_mask.StudyDescription=info.StudyDescription info_mask.is_little_endian = False
def create_file_meta( *, sop_class_uid: UID, sop_instance_uid: UID, transfer_syntax: UID, implementation_uid: UID = PYNETDICOM_IMPLEMENTATION_UID, implementation_version: str = PYNETDICOM_IMPLEMENTATION_VERSION, ) -> FileMetaDataset: """Return a new file meta dataset .. versionadded:: 2.0 Parameters ---------- sop_class_uid : pydicom.uid.UID The value for the *Media Storage SOP Class UID*. sop_instance_uid : pydicom.uid.UID The value for the *Media Storage SOP Instance UID*. transfer_syntax : pydicom.uid.UID The value for the *Transfer Syntax UID*. implementation_uid : pydicom.uid.UID, optional The value for the *Implementation Class UID*. implementation_version : str, optional The value for the *Implementation Version Name*. Returns ------- pydicom.dataset.FileMetaDataset The File Meta dataset """ file_meta = FileMetaDataset() file_meta.FileMetaInformationGroupLength = 0 file_meta.FileMetaInformationVersion = b'\x00\x01' file_meta.MediaStorageSOPClassUID = sop_class_uid file_meta.MediaStorageSOPInstanceUID = sop_instance_uid file_meta.TransferSyntaxUID = transfer_syntax file_meta.ImplementationClassUID = implementation_uid file_meta.ImplementationVersionName = implementation_version # File Meta Information is always encoded as Explicit VR Little Endian file_meta.is_little_endian = True file_meta.is_implicit_VR = False return file_meta
def write_file_meta_info(fp: DicomIO, file_meta: FileMetaDataset, enforce_standard: bool = True) -> None: """Write the File Meta Information elements in `file_meta` to `fp`. If `enforce_standard` is ``True`` then the file-like `fp` should be positioned past the 128 byte preamble + 4 byte prefix (which should already have been written). **DICOM File Meta Information Group Elements** From the DICOM standard, Part 10, :dcm:`Section 7.1<part10/chapter_7.html#sect_7.1>`, any DICOM file shall contain a 128-byte preamble, a 4-byte DICOM prefix 'DICM' and (at a minimum) the following Type 1 DICOM Elements (from :dcm:`Table 7.1-1<part10/chapter_7.html#table_7.1-1>`): * (0002,0000) *File Meta Information Group Length*, UL, 4 * (0002,0001) *File Meta Information Version*, OB, 2 * (0002,0002) *Media Storage SOP Class UID*, UI, N * (0002,0003) *Media Storage SOP Instance UID*, UI, N * (0002,0010) *Transfer Syntax UID*, UI, N * (0002,0012) *Implementation Class UID*, UI, N If `enforce_standard` is ``True`` then (0002,0000) will be added/updated, (0002,0001) and (0002,0012) will be added if not already present and the other required elements will be checked to see if they exist. If `enforce_standard` is ``False`` then `file_meta` will be written as is after minimal validation checking. The following Type 3/1C Elements may also be present: * (0002,0013) *Implementation Version Name*, SH, N * (0002,0016) *Source Application Entity Title*, AE, N * (0002,0017) *Sending Application Entity Title*, AE, N * (0002,0018) *Receiving Application Entity Title*, AE, N * (0002,0102) *Private Information*, OB, N * (0002,0100) *Private Information Creator UID*, UI, N If `enforce_standard` is ``True`` then (0002,0013) will be added/updated. *Encoding* The encoding of the *File Meta Information* shall be *Explicit VR Little Endian*. Parameters ---------- fp : file-like The file-like to write the File Meta Information to. file_meta : pydicom.dataset.Dataset The File Meta Information elements. enforce_standard : bool If ``False``, then only the *File Meta Information* elements already in `file_meta` will be written to `fp`. If ``True`` (default) then a DICOM Standards conformant File Meta will be written to `fp`. Raises ------ ValueError If `enforce_standard` is ``True`` and any of the required *File Meta Information* elements are missing from `file_meta`, with the exception of (0002,0000), (0002,0001) and (0002,0012). ValueError If any non-Group 2 Elements are present in `file_meta`. """ validate_file_meta(file_meta, enforce_standard) if enforce_standard and 'FileMetaInformationGroupLength' not in file_meta: # Will be updated with the actual length later file_meta.FileMetaInformationGroupLength = 0 # Write the File Meta Information Group elements # first write into a buffer to avoid seeking back, that can be # expansive and is not allowed if writing into a zip file buffer = DicomBytesIO() buffer.is_little_endian = True buffer.is_implicit_VR = False write_dataset(buffer, file_meta) # If FileMetaInformationGroupLength is present it will be the first written # element and we must update its value to the correct length. if 'FileMetaInformationGroupLength' in file_meta: # Update the FileMetaInformationGroupLength value, which is the number # of bytes from the end of the FileMetaInformationGroupLength element # to the end of all the File Meta Information elements. # FileMetaInformationGroupLength has a VR of 'UL' and so has a value # that is 4 bytes fixed. The total length of when encoded as # Explicit VR must therefore be 12 bytes. file_meta.FileMetaInformationGroupLength = buffer.tell() - 12 buffer.seek(0) write_data_element(buffer, file_meta[0x00020000]) fp.write(buffer.getvalue())
def create_initial_rtss_from_ct(img_ds: pydicom.dataset.Dataset, filepath: Path, uid_list: list) -> pydicom.dataset.FileDataset: """ Pre-populate an RT Structure Set based on a single CT (or MR) and a list of image UIDs The caller should update the Structure Set Label, Name, and Description, which are set to "OnkoDICOM" plus the StudyID from the CT, and must add Structure Set ROI Sequence, ROI Contour Sequence, and RT ROI Observations Sequence Parameters ---------- img_ds : pydicom.dataset.Dataset A CT or MR image that the RT Structure Set will be "drawn" on uid_list : list list of UIDs (as strings) of the entire image volume that the RT SS references filepath: str A path where the RTStruct will be saved Returns ------- pydicom.dataset.FileDataset the half-baked RT SS, ready for Structure Set ROI Sequence, ROI Contour Sequence, and RT ROI Observations Sequence Raises ------ ValueError [description] """ if img_ds is None: raise ValueError("No CT data to initialize RT SS") now = datetime.datetime.now() dicom_date = now.strftime("%Y%m%d") dicom_time = now.strftime("%H%M") # File Meta module file_meta = FileMetaDataset() file_meta.FileMetaInformationGroupLength = 238 file_meta.FileMetaInformationVersion = b'\x00\x01' file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.481.3' file_meta.MediaStorageSOPInstanceUID = generate_uid() file_meta.TransferSyntaxUID = ImplicitVRLittleEndian validate_file_meta(file_meta) rt_ss = pydicom.dataset.FileDataset(filepath, {}, preamble=b"\0" * 128, file_meta=file_meta) rt_ss.fix_meta_info() top_level_tags_to_copy: list = [ Tag("PatientName"), Tag("PatientID"), Tag("PatientBirthDate"), Tag("PatientSex"), Tag("StudyDate"), Tag("StudyTime"), Tag("AccessionNumber"), Tag("ReferringPhysicianName"), Tag("StudyDescription"), Tag("StudyInstanceUID"), Tag("StudyID"), Tag("RequestingService"), Tag("PatientAge"), Tag("PatientSize"), Tag("PatientWeight"), Tag("MedicalAlerts"), Tag("Allergies"), Tag("PregnancyStatus"), Tag("FrameOfReferenceUID"), Tag("PositionReferenceIndicator"), Tag("InstitutionName"), Tag("InstitutionAddress"), Tag("OperatorsName") ] for tag in top_level_tags_to_copy: if tag in img_ds: rt_ss[tag] = deepcopy(img_ds[tag]) if rt_ss.StudyInstanceUID == "": raise ValueError( "The given dataset is missing a required tag 'StudyInstanceUID'") # RT Series Module rt_ss.SeriesDate = dicom_date rt_ss.SeriesTime = dicom_time rt_ss.Modality = "RTSTRUCT" rt_ss.OperatorsName = "" rt_ss.SeriesInstanceUID = pydicom.uid.generate_uid() rt_ss.SeriesNumber = "1" # General Equipment Module rt_ss.Manufacturer = "OnkoDICOM" rt_ss.ManufacturerModelName = "OnkoDICOM" # TODO: Pull this off build information in some way rt_ss.SoftwareVersions = "2021" # Frame of Reference module rt_ss.FrameOfReferenceUID = img_ds.FrameOfReferenceUID rt_ss.PositionReferenceIndicator = "" # Structure Set module # Best to modify the Structure Set Label with something more # interesting in the application. and populate the Name and # Description from the application also. rt_ss.StructureSetLabel = "OnkoDICOM rtss" rt_ss.StructureSetName = rt_ss.StructureSetLabel rt_ss.StructureSetDescription = "OnkoDICOM rtss of " + rt_ss.StudyID rt_ss.StructureSetDate = dicom_date rt_ss.StructureSetTime = dicom_time # Contour Image Sequence contour_image_sequence = [] for uid in uid_list: contour_image_sequence_item = pydicom.dataset.Dataset() contour_image_sequence_item.ReferencedSOPClassUID = img_ds.SOPClassUID contour_image_sequence_item.ReferencedSOPInstanceUID = uid contour_image_sequence.append(contour_image_sequence_item) # RT Referenced Series Sequence rt_referenced_series = pydicom.dataset.Dataset() rt_referenced_series.SeriesInstanceUID = img_ds.SeriesInstanceUID rt_referenced_series.ContourImageSequence = contour_image_sequence rt_referenced_series_sequence = [rt_referenced_series] # RT Referenced Study Sequence rt_referenced_study = pydicom.dataset.Dataset() rt_referenced_study.ReferencedSOPClassUID = "1.2.840.10008.3.1.2.3.1" rt_referenced_study.ReferencedSOPInstanceUID = img_ds.StudyInstanceUID rt_referenced_study.RTReferencedSeriesSequence = \ rt_referenced_series_sequence rt_referenced_study_sequence = [rt_referenced_study] # RT Referenced Frame Of Reference Sequence, Structure Set Module referenced_frame_of_reference = pydicom.dataset.Dataset() referenced_frame_of_reference.FrameOfReferenceUID = \ img_ds.FrameOfReferenceUID referenced_frame_of_reference.RTReferencedStudySequence = \ rt_referenced_study_sequence rt_ss.ReferencedFrameOfReferenceSequence = [referenced_frame_of_reference] # Sequence modules rt_ss.StructureSetROISequence = [] rt_ss.ROIContourSequence = [] rt_ss.RTROIObservationsSequence = [] # SOP Common module rt_ss.SOPClassUID = rt_ss.file_meta.MediaStorageSOPClassUID rt_ss.SOPInstanceUID = rt_ss.file_meta.MediaStorageSOPInstanceUID # Add required elements rt_ss.InstanceCreationDate = dicom_date rt_ss.InstanceCreationTime = dicom_time rt_ss.is_little_endian = True rt_ss.is_implicit_VR = True return rt_ss