def __init__(self, filename_or_obj, dataset, preamble=None, file_meta=None, is_implicit_VR=True, is_little_endian=True): """Initialize a DICOMDIR dataset read from a DICOM file Carries forward all the initialization from FileDataset class :param filename: full path and filename to the file. Use None if is a BytesIO. :param dataset: some form of dictionary, usually a Dataset from read_dataset() :param preamble: the 128-byte DICOM preamble :param file_meta: the file meta info dataset, as returned by _read_file_meta, or an empty dataset if no file meta information is in the file :param is_implicit_VR: True if implicit VR transfer syntax used; False if explicit VR. Default is True. :param is_little_endian: True if little-endian transfer syntax used; False if big-endian. Default is True. """ # Usually this class is created through filereader.read_partial, # and it checks class SOP, but in case of direct creation, # check here also if file_meta: class_uid = file_meta.MediaStorageSOPClassUID if not class_uid == "Media Storage Directory Storage": print(class_uid, type(class_uid)) msg = "SOP Class is not Media Storage Directory (DICOMDIR)" raise InvalidDicomError(msg) FileDataset.__init__(self, filename_or_obj, dataset, preamble, file_meta, is_implicit_VR=True, is_little_endian=True) self.parse_records()
def gen_slice_dicom_file(self,outdir, n, imageinfo,image_2d, \ sop_instance_uid,slice_dataset,meta_dataset): """ give the imageinfo,image_2d,sop_instance_uid, then export the data to single slice. slice_dataset: all the tag in it """ #get the image pixel array dim2 = image_2d.dimensions array_1d = image_2d.point_data.scalars.to_array() pixel_array = np.reshape(array_1d,(dim2[0],dim2[1])) # pixel_array = np.reshape(array_1d,(dim3[0],dim3[1])) slice_dataset.PixelData = pixel_array.tostring() slice_dataset.is_little_endian = True slice_dataset.is_implicit_VR = True #update the slice_dataset by imageinfo imageinfo.update_dataset(slice_dataset) meta_dataset.MediaStorageSOPInstanceUID = sop_instance_uid slice_dataset.SOPInstanceUID = sop_instance_uid #**************************************************** #Write out dicom image file fn_prefix = self.export_property.file_name_prefix fn_sufix = self.export_property.file_name_suffix out_file_name =outdir + '/' + fn_prefix \ + str(n) + '.' + fn_sufix out_version = self.export_property.export_style if out_version == 'Dicom CTImage' or 'EcliseTPS-CTImage': # fds = FileDataset(out_file_name, slice_dataset) # fds.save_as(out_file_name) # Create the FileDataset instance (initially no data elements, but file_meta supplied) # fds = FileDataset(out_file_name, slice_dataset,file_meta=meta_dataset, preamble="\0"*128) fds.save_as(out_file_name)
def __init__(self, filename_or_obj, dataset, preamble=None, file_meta=None, is_implicit_VR=True, is_little_endian=True): """Initialize a DICOMDIR dataset read from a DICOM file Carries forward all the initialization from FileDataset class :param filename: full path and filename to the file. Use None if is a BytesIO. :param dataset: some form of dictionary, usually a Dataset from read_dataset() :param preamble: the 128-byte DICOM preamble :param file_meta: the file meta info dataset, as returned by _read_file_meta, or an empty dataset if no file meta information is in the file :param is_implicit_VR: True if implicit VR transfer syntax used; False if explicit VR. Default is True. :param is_little_endian: True if little-endian transfer syntax used; False if big-endian. Default is True. """ # Usually this class is created through filereader.read_partial, # and it checks class SOP, but in case of direct creation, # check here also if file_meta: class_uid = file_meta.MediaStorageSOPClassUID if not class_uid == "Media Storage Directory Storage": print class_uid, type(class_uid) msg = "SOP Class is not Media Storage Directory (DICOMDIR)" raise InvalidDicomError(msg) FileDataset.__init__(self, filename_or_obj, dataset, preamble, file_meta, is_implicit_VR=True, is_little_endian=True) self.parse_records()
def write_dicom(pixel_array, filename, ds_copy, ds_ori, volume_number, series_number, sop_id): """Write data in dicom file and copy the header from different dicoms. :param pixel_array: data to write in a dicom :param filename: file name for the dicom :param ds_copy: pydicom object of the dicom to copy info from :param ds_ori: pydicom object of the dicom where the array comes from :param volume_number: numero of volume being processed :param series_number: number of the series being written :param sop_id: SOPID for the dicom :return: None """ # Set to zero negatives values in the image: pixel_array[pixel_array < 0] = 0 # Set the DICOM dataset file_meta = Dataset() file_meta.MediaStorageSOPClassUID = 'Secondary Capture Image Storage' file_meta.MediaStorageSOPInstanceUID = ds_ori.SOPInstanceUID file_meta.ImplementationClassUID = ds_ori.SOPClassUID ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0"*128) # Copy the tag from the original DICOM for tag, value in ds_ori.items(): if tag != ds_ori.data_element("PixelData").tag: ds[tag] = value # Other tags to set ds.SeriesNumber = series_number ds.SeriesDescription = ds_ori.SeriesDescription + ' reg_f3d' sop_uid = sop_id + str(datetime.datetime.now()).replace('-', '')\ .replace(':', '')\ .replace('.', '')\ .replace(' ', '') ds.SOPInstanceUID = sop_uid[:-1] ds.ProtocolName = ds_ori.ProtocolName ds.InstanceNumber = volume_number+1 # Copy from T2 the orientation tags: ds.PatientPosition = ds_copy.PatientPosition ds[0x18, 0x50] = ds_copy[0x18, 0x50] # Slice Thicknes ds[0x18, 0x88] = ds_copy[0x18, 0x88] # Spacing Between Slices ds[0x18, 0x1312] = ds_copy[0x18, 0x1312] # In-plane Phase Encoding ds[0x20, 0x32] = ds_copy[0x20, 0x32] # Image Position ds[0x20, 0x37] = ds_copy[0x20, 0x37] # Image Orientation ds[0x20, 0x1041] = ds_copy[0x20, 0x1041] # Slice Location ds[0x28, 0x10] = ds_copy[0x28, 0x10] # rows ds[0x28, 0x11] = ds_copy[0x28, 0x11] # columns ds[0x28, 0x30] = ds_copy[0x28, 0x30] # Pixel spacing # Set the Image pixel array if pixel_array.dtype != np.uint16: pixel_array = pixel_array.astype(np.uint16) ds.PixelData = pixel_array.tostring() # Save the image ds.save_as(filename)
def getSeriesRecord ( self, recordID=None, seriesUID=None, accessionNumber=None, patientID=None ): whereClause = None queryArg = None # set SQL where clause to search database if recordID is not None: whereClause = " WHERE id = ? " queryArg = recordID elif seriesUID is not None: whereClause = " WHERE SeriesInstanceUID = ? " queryArg = seriesUID elif accessionNumber is not None: whereClause = " WHERE AccessionNumber = ? " queryArg = accessionNumber elif patientID is not None: whereClause = " WHERE PatientID = ? " queryArg = patientID else: return None # get series record from database qFind = "SELECT * FROM %s %s LIMIT 1" % (self.settings.dbTblSeries, whereClause) series = None with self.dbCon: dbCur = self.dbCon.cursor() dbCur.execute( qFind, (queryArg,) ) series = dbCur.fetchone() # check record exists if series is None: print "Can't get series record with given arg: %s" % str(queryArg) return None # create new DICOM object dcm = FileDataset(None,{},None) # fill object from record for dcmHeaderTag in self.settings.tagsToRecord: tagName = DicomDictionary[dcmHeaderTag][4] if series[tagName]: setattr( dcm, tagName, series[tagName] ) # add record ID dcm.recordID = series['id'] return dcm
def read_partial(fileobj, stop_when=None, defer_size=None, force=False): """Parse a DICOM file until a condition is met ``read_partial`` is normally not called directly. Use ``read_file`` instead, unless you need to stop on some condition other than reaching pixel data. :arg fileobj: a file-like object. This function does not close it. :arg stop_when: a callable which takes tag, VR, length, and returns True or False. If stop_when returns True, read_data_element will raise StopIteration. If None (default), then the whole file is read. :returns: a set instance """ # Read preamble -- raise an exception if missing and force=False preamble = read_preamble(fileobj, force) file_meta_dataset = Dataset() # Assume a transfer syntax, correct it as necessary is_implicit_VR = True is_little_endian = True if preamble: file_meta_dataset = _read_file_meta_info(fileobj) transfer_syntax = file_meta_dataset.TransferSyntaxUID if transfer_syntax == dicom.UID.ImplicitVRLittleEndian: pass elif transfer_syntax == dicom.UID.ExplicitVRLittleEndian: is_implicit_VR = False elif transfer_syntax == dicom.UID.ExplicitVRBigEndian: is_implicit_VR = False is_little_endian = False elif transfer_syntax == dicom.UID.DeflatedExplicitVRLittleEndian: # See PS3.6-2008 A.5 (p 71) # when written, the entire dataset following # the file metadata was prepared the normal way, # then "deflate" compression applied. # All that is needed here is to decompress and then # use as normal in a file-like object zipped = fileobj.read() # -MAX_WBITS part is from comp.lang.python answer: # groups.google.com/group/comp.lang.python/msg/e95b3b38a71e6799 unzipped = zlib.decompress(zipped, -zlib.MAX_WBITS) fileobj = BytesIO(unzipped) # a file-like object is_implicit_VR = False else: # Any other syntax should be Explicit VR Little Endian, # e.g. all Encapsulated (JPEG etc) are ExplVR-LE # by Standard PS 3.5-2008 A.4 (p63) is_implicit_VR = False else: # no header -- use the is_little_endian, implicit assumptions file_meta_dataset.TransferSyntaxUID = dicom.UID.ImplicitVRLittleEndian try: dataset = read_dataset(fileobj, is_implicit_VR, is_little_endian, stop_when=stop_when, defer_size=defer_size) except EOFError as e: pass # error already logged in read_dataset return FileDataset(fileobj, dataset, preamble, file_meta_dataset, is_implicit_VR, is_little_endian)
def OnReceiveStore(SOPClass, DS): print "Received C-STORE", DS.PatientName try: # do something with dataset. For instance, store it. file_meta = Dataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' file_meta.MediaStorageSOPInstanceUID = "1.2.3" # !! Need valid UID here file_meta.ImplementationClassUID = "1.2.3.4" # !!! Need valid UIDs here filename = '%s/%s.dcm' % (tempfile.gettempdir(), DS.SOPInstanceUID) ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0" * 128) ds.update(DS) ds.save_as(filename) print "File %s written" % filename except: pass # must return appropriate status return SOPClass.Success
def write_dicom(pixel_array, filename, ds_copy, ds_ori, volume_number, series_number, sop_id): """Write a dicom from a pixel_array (numpy). :param pixel_array: 2D numpy ndarray. If pixel_array is larger than 2D, errors. :param filename: string name for the output file. :param ds_copy: pydicom object with the header that need to be copy :param ds_ori: original pydicom object of the pixel_array :param volume_number: number of the volume being processed :param series_number: number of the series being processed :param sop_id: SOPInstanceUID for the DICOM """ # Set to zero negatives values in the image: pixel_array[pixel_array < 0] = 0 # Set the DICOM dataset file_meta = Dataset() file_meta.MediaStorageSOPClassUID = 'Secondary Capture Image Storage' file_meta.MediaStorageSOPInstanceUID = ds_ori.SOPInstanceUID file_meta.ImplementationClassUID = ds_ori.SOPClassUID ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0"*128) # Copy the tag from the original DICOM for tag, value in ds_ori.items(): if tag != ds_ori.data_element("PixelData").tag: ds[tag] = value # Other tags to set ds.SeriesNumber = series_number ds.SeriesDescription = ds_ori.SeriesDescription + ' reg_f3d' sop_uid = sop_id + str(datetime.datetime.now()).replace('-', '')\ .replace(':', '')\ .replace('.', '')\ .replace(' ', '') ds.SOPInstanceUID = sop_uid[:-1] ds.ProtocolName = ds_ori.ProtocolName ds.InstanceNumber = volume_number+1 # Copy from T2 the orientation tags: for tag in TAGS_TO_COPY: if tag in ds_copy: ds[tag] = ds_copy[tag] # Set the Image pixel array if pixel_array.dtype != np.uint16: pixel_array = pixel_array.astype(np.uint16) ds.PixelData = pixel_array.tostring() # Save the image ds.save_as(filename)
def OnReceiveStore(self, SOPClass, DS): # sleep(0.1) rl.info('Received C-STORE') # do something with dataset. For instance, store it on disk. file_meta = Dataset() file_meta.MediaStorageSOPClassUID = DS.SOPClassUID file_meta.MediaStorageSOPInstanceUID = UID.generate_uid() #DS.SOPInstanceUID # !! Need valid UID here file_meta.ImplementationClassUID = UID.pydicom_root_UID #"1.2.3.4" # !!! Need valid UIDs here file_path = directory.joinPath([self.StorePath, str(DS.SeriesDate), str(DS.SeriesDescription)]) if fmriQA.is_dicom_dict_QA(DS): directory.createPath(file_path) filename = directory.joinPath([file_path, "I%05d" % DS.get('InstanceNumber') + '.'+config.DATA_EXT]) ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0" * 128) ds.update(DS) ds.is_little_endian = True ds.is_implicit_VR = True # print ds - prints all DICOM tags contained in the file prior its saving ds.save_as(filename) if directory.isFile(filename): rl.info('File %s written' % filename) # must return appropriate status return SOPClass.Success else: return SOPClass.UnableToProcess rl.error('File %s failed to write' % filename) else: return SOPClass.IdentifierDoesNotMatchSOPClass rl.warning('The sent file was not recognised as QA file (%s)' % filename)
def OnReceiveStore(self, SOPClass, ds): # do something with dataset. For instance, store it. self.logger.debug( "Received C-STORE SeriesInstanceUID:'%s', SOPInstanceUID:'%s''" % (ds.SeriesInstanceUID, ds.SOPInstanceUID)) file_meta = Dataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' # !! Need valid UID herecopy_dicom file_meta.MediaStorageSOPInstanceUID = "1.2.3" # !!! Need valid UIDs here file_meta.ImplementationClassUID = "1.2.3.4" folder = os.path.join(self.import_folder, ds.StudyID) if not os.path.isdir(folder): os.makedirs(folder) filename = '%s/%s.dcm' % (folder, ds.SOPInstanceUID) fileds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0" * 128) fileds.update(ds) fileds.save_as(filename) self.logger.info("file %s written" % filename) if self.onDicomSaved: self.logger.info("calling callback") self.onDicomSaved(filename) # must return appropriate status return SOPClass.Success
def create_dcm(filename,patname='BarcoQC',patid='112233'): textfile = open(filename,'rb') filename = os.path.splitext(filename)[0]+'.dcm' print "Output filename:", filename # Populate required values for file meta information file_meta = Dataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.104.1' # NM Image Storage misschien beter OT file_meta.MediaStorageSOPInstanceUID = "1.2.3" # !! Need valid UID here for real work file_meta.ImplementationClassUID = "1.2.3.4" # !!! Need valid UIDs here print "Setting dataset values..." # Create the FileDataset instance (initially no data elements, but file_meta supplied) ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0"*128) # Add the data elements -- not trying to set all required here. Check DICOM standard ds.PatientName = patname ds.PatientID = patid #datestring = extract_date(textfile) #print datestring #ds.InstanceCreationDate = datestring # Set the transfer syntax ds.is_little_endian = True ds.is_implicit_VR = True #doctag = dicom.tag.Tag(("0042","0011")) doctag = dicom.tag.Tag(("0001","9999")) ds.add_new(doctag,'OB', textfile.read()) print "Writing test file", filename ds.save_as(filename) print "File saved."
def __init__(self, file_path, preamble=None, file_meta=None, is_implicit_VR=True, is_little_endian=True): """ :param file_path: str Full path and filename to the file. Use None if is a BytesIO. :param header_fields: subset of DICOM header fields to be stored here, the rest will be ignored. :param dataset: some form of dictionary, usually a Dataset from read_dataset() :param preamble: the 128-byte DICOM preamble :param file_meta: dataset The file meta info dataset, as returned by _read_file_meta, or an empty dataset if no file meta information is in the file :param is_implicit_VR: bool True if implicit VR transfer syntax used; False if explicit VR. Default is True. :param is_little_endian: bool True if little-endian transfer syntax used; False if big-endian. Default is True. """ try: dcm = dicom.read_file(file_path, force=True) FileDataset.__init__(self, file_path, dcm, preamble, file_meta, is_implicit_VR, is_little_endian) self.file_path = os.path.abspath(file_path) except Exception as exc: log.exception('Error reading file {0}.'.format(file_path))
def OnReceiveStore(SOPClass, DS): #print "Received C-STORE" # do something with dataset. For instance, store it on disk. file_meta = Dataset() file_meta.MediaStorageSOPClassUID = DS.SOPClassUID file_meta.MediaStorageSOPInstanceUID = "1.2.3" # !! Need valid UID here file_meta.ImplementationClassUID = "1.2.3.4" # !!! Need valid UIDs here filename = '%s/%s.dcm' % (tempfile.gettempdir(), DS.SOPInstanceUID) ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0" * 128) ds.update(DS) ds.is_little_endian = True ds.is_implicit_VR = True ds.save_as(filename) #print "File %s written" % filename # must return appropriate status return SOPClass.Success
def OnReceiveStore(SOPClass, DS): print "Received C-STORE" # do something with dataset. For instance, store it. file_meta = Dataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' # CT Image Storage file_meta.MediaStorageSOPInstanceUID = "1.2.3" # !! Need valid UID here for real work file_meta.ImplementationClassUID = "1.2.3.4" # !!! Need valid UIDs here filename = '/tmp/%s.dcm' % DS.SOPInstanceUID ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0" * 128) ds.update(DS) ds.is_little_endian = True ds.is_implicit_VR = True ds.save_as(filename) print "File %s written" % filename # must return appropriate status return 0
def OnReceiveStore(SOPClass, DS): print "Received C-STORE" # do something with dataset. For instance, store it on disk. file_meta = Dataset() file_meta.MediaStorageSOPClassUID = DS.SOPClassUID file_meta.MediaStorageSOPInstanceUID = DS.SOPInstanceUID # Change to my own UID via dicom.UID.generate_uid() though I should make sure such genereated UIDs use my orgroot. file_meta.ImplementationClassUID = "1.2.826.0.1.3680043.9.5066.0" # My UID for my implementation, with a '.0' appended to it to represent development testing, ie the UID I got from Medical Connections. file_meta.ImplementationVersionName = "DICOMMETRICS-DEV" # My implementation version name. Remember to change this for each version. Remember to correspondingly change the ImplementationClassUID too. filename = '%s/%s.dcm' % (tempfile.gettempdir(), DS.SOPInstanceUID) ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0" * 128) ds.update(DS) ds.is_little_endian = True ds.is_implicit_VR = True ds.save_as(filename) print "File %s written" % filename # must return appropriate status return SOPClass.Success
def OnReceiveStore(SOPClass, DS): print "Received C-STORE" # do something with dataset. For instance, store it. file_meta = Dataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' # CT Image Storage file_meta.MediaStorageSOPInstanceUID = "1.2.3" # !! Need valid UID here for real work file_meta.ImplementationClassUID = "1.2.3.4" # !!! Need valid UIDs here filename = '/tmp/%s.dcm' % DS.SOPInstanceUID ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0"*128) ds.update(DS) ds.is_little_endian = True ds.is_implicit_VR = True ds.save_as(filename) print "File %s written" % filename # must return appropriate status return 0
def OnReceiveStore(SOPClass, DS): file_meta = Dataset() file_meta.MediaStorageSOPClassUID = DS.SOPClassUID file_meta.MediaStorageSOPInstanceUID = DS.SOPInstanceUID file_meta.ImplementationClassUID = DS.SOPClassUID filename = os.path.join( constants.dicom_dir, foldername, DS.SOPInstanceUID + ".dcm") print "making file ", filename ds = FileDataset( filename, {}, file_meta=file_meta, preamble="\0" * 128) ds.update(DS) ds.is_little_endian = True ds.is_implicit_VR = True ds.save_as(filename) # print "File %s written" % filename # must return appropriate status return SOPClass.Success
def onReceiveStore(self, sopClass, receivedDs): """ """ self._logger.debug("Received C-STORE: " + receivedDs.PatientName) try: # DICOM header (metadata) file_meta = Dataset() file_meta.MediaStorageSOPClassUID = receivedDs.SOPClassUID file_meta.MediaStorageSOPInstanceUID = receivedDs.SOPInstanceUID # TransferSyntaxUID # pydicom root UID + 1 file_meta.ImplementationClassUID = "1.2.826.0.1.3680043.8.498.1" path = self.downloadDir + os.sep + receivedDs.PatientID # Patient ID is the root folder if os.path.isdir(path) == False: os.mkdir(path) path = path + os.sep + receivedDs.StudyInstanceUID # DICOM study separated to subfolder under patient if os.path.isdir(path) == False: os.mkdir(path) filename = path + os.sep + receivedDs.Modality + "." + receivedDs.SOPInstanceUID + ".dcm" # Create a DICOM file ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0" * 128) ds.update(receivedDs) ds.save_as(filename) self._fileCounter = self._fileCounter + 1 self._logger.debug("File written to: " + filename) if self._guiThread: self._guiThread.emit(QtCore.SIGNAL("log(QString)"), "File written to: " + filename) self._guiThread.emit(QtCore.SIGNAL("taskUpdated"), self._fileCounter) except Exception, err: self._logger.error(str(err))
def make_up_file_dataset(filename, ds, implement_instance_uid='1.2.826.0.1.3680043.9.6991'): """ 把裸Dataset对象ds装载为可以存储的FileDataSet对象. :param filename: str 文件名 :param ds: Dataset dicom对象 :param implement_instance_uid: str icoom 中的 file_meta部分的实例实现的前缀, 需自行申请的前缀, 随意写也不会影响使用 :return: FileDataset 可保存的dataset对象 """ meta = Dataset() meta.MediaStorageSOPClassUID = ds.SOPClassUID meta.MediaStorageSOPInstanceUID = ds[0x0008, 0x0018].value meta.ImplementationClassUID = implement_instance_uid fds = FileDataset(filename, {}, file_meta=meta, preamble=b"\0" * 128) fds.update(ds) fds.is_little_endian = True fds.is_implicit_VR = True return fds
def convert(self,imagefile,dicomfile,ox=0,oy=0,oz=0,xv=[1,0,0],yv=[0,1,0]): file_meta = Dataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.7' # file_meta.MediaStorageSOPInstanceUID = dicom.UID.generate_uid() file_meta.ImplementationClassUID = file_meta.MediaStorageSOPInstanceUID # Create the FileDataset instance (initially no data elements, but file_meta supplied) ds = FileDataset(dicomfile, {}, file_meta=file_meta, preamble=b"\0" * 128) img = Image.open(imagefile) # Add the data elements -- not trying to set all required here. Check DICOM standard ds.PatientName = str(imagefile) val = np.random.randint(1,99999) ds.PatientID = '%05d' % (val) ds.SOPInstanceUID = dicom.UID.generate_uid() ds.add_new(Tag(0x20, 0x32), 'DS', [ox,oy,oz]) ds.add_new(Tag(0x20, 0x37),'DS', xv+yv) ds.Columns = img.size[0] #img width ds.Rows = img.size[1] #img height #This is specific to the type of jpeg encoding #These parameters were obtained from the dicom created by using img2dcm tool of dcmtk #They seem to work for PIL loaded files if img.mode == 'L': ds.SamplesPerPixel=1 ds.PhotometricInterpretation= 'MONOCHROME2' # Should match img.mode elif img.mode == 'RGB': ds.SamplesPerPixel=3 ds.PhotometricInterpretation= 'RGB' # Should match img.mode ds.PixelSpacing = [1,1,1] ds.BitsAllocated= 8 ds.BitsStored=8 ds.HighBit=7 ds.PixelRepresentation=0 ds.LossyImageCompression='01' ds.LossyImageCompressionMethod= 'ISO_10918_1' #ds.TransferSyntaxIndex = '1.2.840.10008.1.2' ds.PixelData = np.array(img).tostring() ds.save_as(dicomfile)
def testImpl_LE_deflen_write(self): """Scratch Write for implicit VR little endian, defined length SQ's""" from dicom.test._write_stds import impl_LE_deflen_std_hex as std file_ds = FileDataset("test", self.ds) self.compare_write(std, file_ds)
with open("/envoyai/input/circle-pos-x") as f: cir_pos_x = int(f.read()) # load circle y parameter with open("/envoyai/input/circle-pos-y") as f: cir_pos_y = int(f.read()) # load the input image input_dicom = dicom.read_file("/envoyai/input/input-image") # generate series uid series_instance_uid = dicom.UID.generate_uid() # create the bare output dicom file_meta = gsps.get_gsps_file_metadata() ds_out = FileDataset("image.pre", {}, file_meta=file_meta, preamble=b"\0" * 128) # set the content description and general study fields gsps.set_content_desription(ds_out, "Presentation State for image") gsps.set_gsps_general_study_info(ds_out, file_meta, series_instance_uid) # copy patient, study, series data from input image gsps.copy_details_from_input_dicom(ds_out, input_dicom) gsps.set_referenced_image_info(ds_out, input_dicom.SeriesInstanceUID, input_dicom.SOPClassUID, input_dicom.SOPInstanceUID) # calculate coordinates for annotation and anchor point input_rows = input_dicom.Rows input_columns = input_dicom.Columns anchor_point = [input_columns / 2, input_rows / 2]
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 write_dicom(pixel_array, filename): file_meta = Dataset() file_meta.MediaStorageSOPClassUID = 'Secondary Capture Image Storage' file_meta.MediaStorageSOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684' file_meta.MediaStorageSOPInstanceUID += '411017669021768385720736873780' file_meta.ImplementationClassUID = '1.3.6.1.4.1.9590.100.1.0.100.4.0' ds = FileDataset(filename, {}, file_meta=file_meta, preamble=b"\0"*128) ds.Modality = 'MR' ds.ContentDate = str(date.today()).replace('-', '') ds.ContentTime = str(time()) ds.StudyInstanceUID = '1.3.6.1.4.1.9590.100.1.1.1243139774123601752342712' ds.StudyInstanceUID += '87472804872093' ds.SeriesInstanceUID = '1.3.6.1.4.1.9590.100.1.1.369231118011061003403421' ds.SeriesInstanceUID += '859172643143649' ds.SOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385' ds.SOPInstanceUID += '720736873780' ds.SOPClassUID = 'Secondary Capture Image Storage' ds.SecondaryCaptureDeviceManufctur = 'Python 3.3.5' # Options ds.InstitutionName = "Imperial College London" ds.RepetitionTime = 300 # These are the necessary imaging components of the FileDataset object. ds.SamplesPerPixel = 1 ds.PhotometricInterpretation = "MONOCHROME2" ds.PixelRepresentation = 0 ds.HighBit = 15 ds.BitsStored = 16 ds.BitsAllocated = 16 ds.Columns = pixel_array.shape[1] ds.Rows = pixel_array.shape[0] ds.PixelData = pixel_array.tostring() ds.save_as(filename) return 0
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
#Create each dcm file and copy data from ^^ for i in range(n): dsOld = dicom.read_file(fileNames[i], force=True) #force required??? Talk to Ken. filename = r"%i.dcm" % (i+1) # Following 10 lines adapted from pydicom makenew.py examaple: Darcy Mason. # Populate required values for file meta information file_meta = Dataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' # CT Image Storage file_meta.MediaStorageSOPInstanceUID = "1.2.3" # !! Need valid UID here for real work file_meta.ImplementationClassUID = "1.2.3.4" # !!! Need valid UIDs here # Create the FileDataset instance (initially no data elements, but file_meta supplied) ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0"*128) ds.SpecificCharacterSet = dsOld.SpecificCharacterSet ds.ImageType = dsOld.ImageType ds.SOPInstanceUID = dsOld.SOPInstanceUID ds.SOPClassUID = dsOld.SOPClassUID ds.StudyDate = dsOld.StudyDate ds.StudyTime = dsOld.StudyTime ds.StudyInstanceUID = dsOld.StudyInstanceUID ds.SeriesInstanceUID = dsOld.SeriesInstanceUID ds.StudyID = dsOld.StudyID ds.SeriesNumber = dsOld.SeriesNumber #Reverse order for viewing standard. ds.InstanceNumber = dsOld.InstanceNumber ds.FrameofReferenceUID = dsOld.FrameofReferenceUID
def write_dicom(pixel_array, filename, ds_ori, series_number, sop_id, nb_acq, project, subject, session): """Write a dicom from a pixel_array (numpy). :param pixel_array: 2D numpy ndarray. If pixel_array is larger than 2D, errors. :param filename: string name for the output file. :param ds_ori: original pydicom object of the pixel_array :param series_number: number of the series being processed :param sop_id: SOPInstanceUID for the DICOM :param nb_acq: acquisition number :param project: project name on XNAT :param subject: subject name on XNAT :param session: session name on XNAT """ # Set the DICOM dataset file_meta = Dataset() file_meta.MediaStorageSOPClassUID = 'Secondary Capture Image Storage' file_meta.MediaStorageSOPInstanceUID = ds_ori.SOPInstanceUID file_meta.ImplementationClassUID = ds_ori.file_meta.ImplementationClassUID ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0"*128) # Copy UID from dicom ds.InstanceCreatorUID = ds_ori.InstanceCreatorUID ds.SOPClassUID = ds_ori.SOPClassUID # ds.ReferencedStudySequence = ds_ori.ReferencedStudySequence ds.StudyInstanceUID = ds_ori.StudyInstanceUID ds.SeriesInstanceUID = ds_ori.SeriesInstanceUID # Other tags to set ds.SeriesNumber = series_number sop_uid = sop_id + str(datetime.datetime.now()).replace('-', '')\ .replace(':', '')\ .replace('.', '')\ .replace(' ', '') ds.SOPInstanceUID = sop_uid[:-1] ds.ProtocolName = 'ADC Map %d' % nb_acq ds.SeriesDescription = 'ADC Map %d' % nb_acq ds.PatientName = subject ds.PatientID = session # Set SeriesDate/ContentDate now = datetime.date.today() ds.SeriesDate = '%d%02d%02d' % (now.year, now.month, now.day) ds.ContentDate = '%d%02d%02d' % (now.year, now.month, now.day) ds.Modality = 'MR' ds.StudyDescription = project ds.AcquisitionNumber = 1 ds.SamplesperPixel = 1 ds.PhotometricInterpretation = 'MONOCHROME2' ds.SecondaryCaptureDeviceManufctur = 'Python 2.7.11' ds.NumberOfFrames = pixel_array.shape[2] ds.PixelRepresentation = 0 ds.HighBit = 15 ds.BitsStored = 8 ds.BitsAllocated = 8 ds.SmallestImagePixelValue = pixel_array.min() ds.LargestImagePixelValue = pixel_array.max() ds.Columns = pixel_array.shape[0] ds.Rows = pixel_array.shape[1] # Organise the array: pixel_array2 = np.zeros((pixel_array.shape[0]*pixel_array.shape[2], pixel_array.shape[1])) for i in range(pixel_array.shape[2]): pixel_array2[pixel_array.shape[0]*i:pixel_array.shape[0]*(i+1), :] = pixel_array[:, :, i] # Set the Image pixel array if pixel_array2.dtype != np.uint8: pixel_array2 = pixel_array2.astype(np.uint8) ds.PixelData = pixel_array2.tostring() # Save the image ds.save_as(filename)
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
else: homedir = os.path.expanduser("~") filename = os.path.join(homedir, "test.dcm") filename2 = os.path.join(homedir, "test-explBig.dcm") print "Setting file meta information..." # Populate required values for file meta information file_meta = Dataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' # CT Image Storage file_meta.MediaStorageSOPInstanceUID = "1.2.3" # !! Need valid UID here for real work file_meta.ImplementationClassUID = "1.2.3.4" # !!! Need valid UIDs here print "Setting dataset values..." # Create the FileDataset instance (initially no data elements, but file_meta supplied) ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\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 print "Writing test file", filename ds.save_as(filename) print "File saved." # Write as a different transfer syntax ds.file_meta.TransferSyntaxUID = dicom.UID.ExplicitVRBigEndian #XXX shouldn't need this but pydicom 0.9.5 bug not recognizing transfer syntax
else: homedir = os.path.expanduser("~") filename = os.path.join(homedir, "test.dcm") filename2 = os.path.join(homedir, "test-explBig.dcm") print "Setting file meta information..." # Populate required values for file meta information file_meta = Dataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' # CT Image Storage file_meta.MediaStorageSOPInstanceUID = "1.2.3" # !! Need valid UID here for real work file_meta.ImplementationClassUID = "1.2.3.4" # !!! Need valid UIDs here print "Setting dataset values..." # Create the FileDataset instance (initially no data elements, but file_meta supplied) ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\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 print "Writing test file", filename ds.save_as(filename) print "File saved." # Write as a different transfer syntax ds.file_meta.TransferSyntaxUID = dicom.UID.ExplicitVRBigEndian #XXX shouldn't need this but pydicom 0.9.5 bug not recognizing transfer syntax
def write_dicom(arguments, pixel_array, meta_arr=[]): """ Function to create completely new DICOM file. :param arguments: Dictionary containing input parameters. :param pixel_array: 2D or 3D numpy array containing pixel values. :param meta_arr: An array contaning parsed meta data. :return: """ #TODO:Check the possibility to use UID generator instead hardcoded ones. file_meta = Dataset() # The Secondary Capture (SC) Image Information Object Definition (IOD) specifies images that are converted from # a non-DICOM format to a modality independent DICOM format. 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' # Since we don't want to store any additional info in the header, we set it to x00 ds = FileDataset(arguments['out_file'], {}, file_meta=file_meta, preamble=b'0' * 128) # Type of equipment that originally acquired the data. ds.Modality = 'WSD' # Setting the date and time ds.ContentDate = str(datetime.date.today()).replace('-', '') ds.ContentTime = str(time.time()) # milliseconds since the epoch # Keep scrolling :) ds.SOPClassUID = 'Secondary Capture Image Storage' ds.SOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780' 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.369231118011061003403421859172643143649' # Manufacturer ds.SecondaryCaptureDeviceManufctur = 'NCBJ' # These are the necessary imaging components of the FileDataset object. # Number of color channels. ds.SamplesPerPixel = 1 # It defines what does every color channel hold ds.PhotometricInterpretation = "MONOCHROME2" # ds.PixelRepresentation = 0 ds.HighBit = 15 # Here meta-data is put into the Data Set. It can override hardcoded values, but parameters providided as program # arguments will be inserted no matter what is in the meta-data file. ds = write_meta(meta_arr, ds) # How many bits are allocated to store pixel info ds.BitsAllocated = arguments['bytes_per_pix'] * 8 # How many bits are used to store pixel info ds.BitsStored = arguments['bytes_per_pix'] * 8 # Whether signed or unsigned numbers are used if arguments['is_signed']: ds.PixelRepresentation = 1 else: ds.PixelRepresentation = 0 # Read from data the dimensions. if len(pixel_array.shape) == 3: ds.NumberOfFrames = pixel_array.shape[0] ds.Columns = pixel_array.shape[1] ds.Rows = pixel_array.shape[2] else: ds.Columns = pixel_array.shape[0] ds.Rows = pixel_array.shape[1] try: err_str = '[ERROR] The file could not be created because of: ' data_type = recognize_type(arguments['bytes_per_pix'], arguments['is_signed'], arguments['is_float']) if pixel_array.dtype != data_type: pixel_array = pixel_array.astype(data_type) ds.PixelData = pixel_array.tostring() ds.save_as(arguments['out_file'].replace('.dcm', '') + '.dcm') print('[INFO] Writing to DICOM file is complete!') except ValueError as ve: print(err_str + 'ValueError ' + str(ve)) sys.exit(1) except FileExistsError as fe: print(err_str + 'FileExistsError ' + str(fe)) sys.exit(1) except Exception as e: print(err_str + str(e)) sys.exit(1)
def create_dicom_plan(self): """ Create a dummy DICOM RT-plan object. The only data which is forwarded to this object, is self.patient_name. :returns: a DICOM RT-plan object. """ 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 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.SOPClassUID = '1.2.840.10008.5.1.4.1.1.2' # CT Image Storage # 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._pl_dicom_series_instance_uid may be either set in __init__ when creating new object # Series Instance UID might be different than Series Instance UID for CTs ds.SeriesInstanceUID = self._plan_dicom_series_instance_uid ds.Modality = "RTPLAN" ds.SeriesDescription = 'RT Plan' ds.RTPlanDate = datetime.datetime.today().strftime('%Y%m%d') ds.RTPlanGeometry = '' ds.RTPlanLabel = 'B1' ds.RTPlanTime = datetime.datetime.today().strftime('%H%M%S') structure_ref = Dataset() structure_ref.RefdSOPClassUID = '1.2.840.10008.5.1.4.1.1.481.3' # RT Structure Set Storage structure_ref.RefdSOPInstanceUID = '1.2.3' ds.RefdStructureSets = Sequence([structure_ref]) dose_ref = Dataset() dose_ref.DoseReferenceNumber = 1 dose_ref.DoseReferenceStructureType = 'SITE' dose_ref.DoseReferenceType = 'TARGET' dose_ref.TargetPrescriptionDose = self.target_dose dose_ref.DoseReferenceDescription = "TUMOR" ds.DoseReferences = Sequence([dose_ref]) return ds
def write_dicom(pixel_array, index, filename): ## This code block was taken from the output of a MATLAB secondary ## capture. I do not know what the long dotted UIDs mean, but ## this code works. target_dir = '/'.join(filename.split('/')[:-1]) print(target_dir) mkdir_p(target_dir) file_meta = Dataset() ds = FileDataset(filename, {},file_meta = file_meta) ds.ContentDate = str(datetime.date.today()).replace('-','') ds.ContentTime = str(time.time()) #milliseconds since the epoch ## These are the necessary imaging components of the FileDataset object. ds.SamplesPerPixel = 1 ds.InstanceNumber = index #ds.PhotometricInterpretation = bytes("MONOCHROME2", "UTF-8") ds.PixelRepresentation = 0 ds.HighBit = 15 ds.BitsStored = 16 ds.BitsAllocated = 16 #ds.SmallestImagePixelValue = bytes('\\x00\\x00', 'UTF-8') #ds.LargestImagePixelValue = bytes('\\xff\\xff', 'UTF-8') ds.Columns = pixel_array.shape[1] ds.Rows = pixel_array.shape[0] if pixel_array.dtype != np.uint16: pixel_array = pixel_array.astype(np.uint16) ds.PixelData = pixel_array.tostring() ds.save_as(filename)
def WriteDCMFile(pixel_array,filename): file_meta = Dataset() file_meta.MediaStorageSOPClassUID = 'RT 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.Modality = 'RTIMAGE' ds.ContentDate = str(datetime.date.today()).replace('-','') ds.ContentTime = str(time.time()) #milliseconds since the epoch 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.369231118011061003403421859172643143649' ds.SOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780' ds.SOPClassUID = 'RT Image Storage' ds.SecondaryCaptureDeviceManufacturer = 'Varian Medical Systems' ## These are the necessary imaging components of the FileDataset object. ds.SamplesPerPixel = 1 ds.ImagePlanePixelSpacing=[0.392,0.392] 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 =1024# pixel_array.shape[0] ds.Rows =764# pixel_array.shape[1] ds.RescaleSlope=1.0 ds.RescaleIntercept=1.0 # if type(pixel_array) != np.uint16: # pixel_array =np.uint16(pixel_array) ds.PixelData = pixel_array ds.save_as(filename,write_like_original=True) return
def writeDicom(pixel_array, filename): """ Source: https://codedump.io/share/qCDN4fOKcTAS/1/create-pydicom-file-from-numpy-array INPUTS: pixel_array: 2D numpy ndarray. If pixel_array is larger than 2D, errors. filename: string name for the output file. """ ## This code block was taken from the output of a MATLAB secondary ## capture. I do not know what the long dotted UIDs mean, but ## this code works. 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=b'\x00' * 128) ds.Modality = 'WSD' ds.ContentDate = str(datetime.date.today()).replace('-', '') ds.ContentTime = str(time.time()) #milliseconds since the epoch 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.369231118011061003403421859172643143649' ds.SOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780' ds.SOPClassUID = 'Secondary Capture Image Storage' ds.SecondaryCaptureDeviceManufctur = 'Python 2.7.3' ## These are the necessary imaging components of the FileDataset object. ds.SamplesPerPixel = 1 ds.PhotometricInterpretation = "MONOCHROME2" ds.PixelRepresentation = 0 ds.HighBit = 15 ds.BitsStored = 16 ds.BitsAllocated = 16 ds.Columns = pixel_array.shape[0] ds.Rows = pixel_array.shape[1] if pixel_array.dtype != np.uint16: pixel_array = pixel_array.astype(np.uint16) ds.PixelData = pixel_array.tostring() ds.save_as(filename) return
def write_dicom(pixel_array, filename): """ INPUTS: pixel_array: 2D or 3D numpy ndarray. filename: string name for the output file. """ file_meta = Dataset() file_meta.MediaStorageSOPClassUID = '1.1' file_meta.MediaStorageSOPInstanceUID = '1.2' file_meta.ImplementationClassUID = '1.3' ds = FileDataset(filename, {}, file_meta=file_meta, preamble=b'\x00' * 128) ds.Modality = 'PET' # imaging modality name ds.ContentDate = str(datetime.date.today()).replace('-', '') ds.ContentTime = str(time.time()) # milliseconds since the epoch ds.StudyInstanceUID = '1.3' ds.SeriesInstanceUID = '1.3' ds.SOPInstanceUID = '1.3' ds.SOPClassUID = 'Secondary Capture Image Storage' ds.SecondaryCaptureDeviceManufctur = 'Python 3.7.5' # Patient-related data ds.PatientName = 'Wawrzyniec L. Dobrucki' ds.PatientID = 'M12345' ds.PatientSex = 'M' ds.PatientBirthDate = '12/12/12' ds.SeriesNumber = 5 ds.SeriesDescription = 'test image' ds.SliceThickness = '0.5' # slice thickness in mm ds.PixelSpacing = '0.5' # pixel spacing or size in mm # These are the necessary imaging components of the FileDataset object. ds.SamplesPerPixel = 1 ds.PhotometricInterpretation = "MONOCHROME2" ds.PixelRepresentation = 0 # unsigned (default) ds.HighBit = 15 ds.BitsStored = 16 # default ds.BitsAllocated = 16 # default ds.NumberOfFrames = 216 # number of frames for 3D files # ds.SmallestImagePixelValue = '\\x00\\x00' # ds.LargestImagePixelValue = '\\xff\\xff' ds.Columns = pixel_array.shape[0] ds.Rows = pixel_array.shape[1] if pixel_array.dtype != np.uint16: pixel_array = pixel_array.astype(np.uint16) ds.PixelData = pixel_array.tostring() ds.save_as(filename) return
def writeDicomFiles(self, filename): for i in range( 1, len(self.PA) ): #Image 0 is a null image for default display and will not be written out fileName = filename + str(i) + ".dcm" # print ("printing dicom file " + fileName) # Populate required values for file meta information 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' # Create the FileDataset instance (initially no data elements, but file_meta supplied) ds = FileDataset(fileName, {}, file_meta=file_meta, preamble="\0" * 128) ds.Modality = 'MR' ds.ContentDate = str(datetime.date.today()).replace('-', '') ds.ContentTime = str(time.time()) #milliseconds since the epoch 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.369231118011061003403421859172643143649' ds.SOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780' ds.SOPClassUID = 'MR Image Storage' ds.SecondaryCaptureDeviceManufctur = 'Python 2.7.3' ## These are the necessary imaging components of the FileDataset object. 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' #Add MRI data elements ds.bValue = self.bValue[i] ds.Columns = self.Columns[i] ds.FoVX = self.FoVX[i] ds.FoVY = self.FoVY[i] ds.ImageOrientationPatient = self.ImagePosition[i].tolist() ds.InstitutionName = self.InstitutionName[i] ds.PixelBandwidth = self.PixelBandwidth[i] ds.PixelSpacing = [self.PixelSpacingY[i], self.PixelSpacingX[i]] ds.Rows = self.Rows[i] ds.PatientName = self.PatientName[i] ds.PatientID = "123456" ds.ProtocolName = self.ProtocolName[i] ds.RepetitionTime = self.TR[i] ds.SeriesDescription = self.SeriesDescription[i] ds.EchoTime = self.TE[i] ds.FlipAngle = self.FA[i] ds.InversionTime = self.TI[i] ds.ImageOrientationPatient[3:6] = self.ColumnDirection[i].tolist() ds.ImageOrientationPatient[:3] = self.RowDirection[i].tolist() ds.MagneticFieldStrength = self.MagneticFieldStrength[i] ds.Manufacturer = self.Manufacturer[i] pixel_array = np.transpose(self.PA[i]) #numpy pixel array if self.DataType[i].lower() == "phase": pixel_array = ( pixel_array + np.pi ) * 10000 # phase data -pi to pi is converted to 0 to 10000pi #print "Adjusting phase to 16 bit integer" if pixel_array.dtype != np.uint16: pixel_array = pixel_array.astype(np.uint16) ds.PixelData = pixel_array.tostring() # image byte data # Set the transfer syntax ds.is_little_endian = True ds.is_implicit_VR = True ds.save_as(fileName)
def copyCTtoRTDose(self, path, ds, doseData, imageRow, imageCol, sliceCount, dgs): # Create a RTDose file for broadcasting. file_meta = Dataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.481.2' # CT Image Storage # Needs valid UID file_meta.MediaStorageSOPInstanceUID = ds.file_meta.MediaStorageSOPInstanceUID file_meta.ImplementationClassUID = ds.file_meta.ImplementationClassUID #create DICOM RT-Dose object. rtdose = FileDataset(path + '/rtdose.dcm', {}, file_meta=file_meta, preamble="\0"*128) #No DICOM object standard. Use only required to avoid errors with viewers. rtdose.SOPInstanceUID = ds.SOPInstanceUID rtdose.SOPClassUID = '1.2.840.10008.5.1.4.1.1.481.2' rtdose.file_meta.TransferSyntaxUID = ds.file_meta.TransferSyntaxUID rtdose.PatientsName = ds.PatientsName rtdose.PatientID = ds.PatientID rtdose.PatientsBirthDate = ds.PatientsBirthDate #Crashed caused if no sex. try: rtdose.PatientsSex = ds.PatientsSex except: rtdose.PatientsSex, ds.PatientsSex = 'O', 'O' self.data.update({'images':ds}) rtdose.StudyDate = ds.StudyDate rtdose.StudyTime = ds.StudyTime rtdose.StudyInstanceUID = ds.StudyInstanceUID rtdose.SeriesInstanceUID = ds.SeriesInstanceUID rtdose.StudyID = ds.StudyID rtdose.SeriesNumber = ds.SeriesNumber rtdose.Modality = 'RTDOSE' rtdose.ImagePositionPatient = ds.ImagePositionPatient rtdose.ImageOrientationPatient = ds.ImageOrientationPatient rtdose.FrameofReferenceUID = ds.FrameofReferenceUID rtdose.PositionReferenceIndicator = ds.PositionReferenceIndicator rtdose.PixelSpacing = ds.PixelSpacing rtdose.SamplesperPixel = 1 rtdose.PhotometricInterpretation = 'MONOCHROME2' rtdose.NumberofFrames = sliceCount rtdose.Rows = imageRow rtdose.Columns = imageCol rtdose.BitsAllocated = 32 rtdose.BitsStored = 32 rtdose.HighBit = 31 rtdose.PixelRepresentation = 0 rtdose.DoseUnits = 'GY' rtdose.DoseType = 'PHYSICAL' rtdose.DoseSummationType = 'FRACTION' #In case spaceing tag is missing. if not ds.has_key('SpacingBetweenSlices'): ds.SpacingBetweenSlices = ds.SliceThickness #Ensure patient pos is on "Last slice". if fnmatch.fnmatch(ds.PatientPosition, 'FF*'): #For compliance with dicompyler update r57d9155cc415 which uses a reverssed slice ordering. doseData = doseData[::-1] rtdose.ImagePositionPatient[2] = ds.ImagePositionPatient[2] elif fnmatch.fnmatch(ds.PatientPosition, 'HF*'): rtdose.ImagePositionPatient[2] = ds.ImagePositionPatient[2] - (sliceCount-1)*ds.SpacingBetweenSlices #Create Type A(Relative) GFOV. rtdose.GridFrameOffsetVector = list(np.arange(0., sliceCount*ds.SpacingBetweenSlices,ds.SpacingBetweenSlices)) #Scaling from int to physical dose rtdose.DoseGridScaling = dgs #Store images in pixel_array(int) & Pixel Data(raw). rtdose.pixel_array = doseData rtdose.PixelData = doseData.tostring() #Tag required by dicompyler. plan_meta = Dataset() rtdose.ReferencedRTPlans = [] rtdose.ReferencedRTPlans.append([]) rtdose.ReferencedRTPlans[0] = plan_meta rtdose.ReferencedRTPlans[0].ReferencedSOPClassUID = 'RT Plan Storage' rtdose.ReferencedRTPlans[0].ReferencedSOPInstanceUID = ds.SOPInstanceUID #Create RTPlan to acticate DVH file_meta = Dataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.481.5' # RT Plan Storage file_meta.MediaStorageSOPInstanceUID = ds.file_meta.MediaStorageSOPInstanceUID file_meta.ImplementationClassUID = ds.file_meta.ImplementationClassUID #create DICOM RT-Plan object. rtPlan = FileDataset(path + '/rtplan.dcm', {}, file_meta=file_meta, preamble="\0"*128) #No DICOM object standard. Use only required to avoid errora with viewers. rtPlan.SOPInstanceUID = ds.SOPInstanceUID rtPlan.SOPClassUID = '1.2.840.10008.5.1.4.1.1.481.5' rtPlan.ReferencedSOPInstanceUID = ds.SOPInstanceUID #Need to change rtPlan.file_meta.TransferSyntaxUID = ds.file_meta.TransferSyntaxUID rtPlan.PatientsName = ds.PatientsName rtPlan.PatientID = ds.PatientID rtPlan.PatientsSex = ds.PatientsSex rtPlan.PatientsBirthDate = ds.PatientsBirthDate rtPlan.RTPlanLabel = 'Simulation' rtPlan.RTPlanDate = ds.StudyDate rtPlan.RTPlanTime = ds.StudyTime rtPlan.Modality = 'RTPLAN' rtPlan.StudyInstanceUID = ds.StudyInstanceUID rtPlan.SeriesInstanceUID = ds.SeriesInstanceUID rtPlan.StudyID = ds.StudyID rtPlan.SeriesNumber = ds.SeriesNumber return rtdose, rtPlan
def write_dicom(pixel_array, filename, ds_ori, series_number, sop_id, series_description): """Write a dicom from a pixel_array (numpy). :param pixel_array: 2D numpy ndarray. If pixel_array is larger than 2D, errors. :param filename: string name for the output file. :param ds_ori: original pydicom object of the pixel_array :param series_number: number of the series being processed :param sop_id: SOPInstanceUID for the DICOM :param series_description: series description for Osirix display """ # Set the DICOM dataset file_meta = Dataset() file_meta.MediaStorageSOPClassUID = 'Secondary Capture Image Storage' file_meta.MediaStorageSOPInstanceUID = ds_ori.SOPInstanceUID file_meta.ImplementationClassUID = ds_ori.SOPClassUID ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0"*128) # Copy the tag from the original DICOM for tag, d_obj in ds_ori.items(): if tag != ds_ori.data_element("PixelData").tag: ds[tag] = d_obj # Other tags to set ds.SeriesNumber = series_number sop_uid = sop_id + str(datetime.datetime.now()).replace('-', '')\ .replace(':', '')\ .replace('.', '')\ .replace(' ', '') ds.SOPInstanceUID = sop_uid[:-1] ds.ProtocolName = '%s Verdict MAP' % series_description # Set SeriesDate/ContentDate now = datetime.date.today() ds.SeriesDate = '%d%02d%02d' % (now.year, now.month, now.day) ds.ContentDate = '%d%02d%02d' % (now.year, now.month, now.day) ds.Modality = 'MR' ds.ConversionType = 'WSD' ds.StudyDescription = 'INNOVATE' ds.SeriesDescription = series_description ds.AcquisitionNumber = 1 ds.SamplesperPixel = 1 ds.PhotometricInterpretation = 'MONOCHROME2' ds.SecondaryCaptureDeviceManufctur = 'Python 2.7.3' nb_frames = pixel_array.shape[2]*pixel_array.shape[3] ds.NumberOfFrames = nb_frames ds.PixelRepresentation = 0 ds.HighBit = 15 ds.BitsStored = 8 ds.BitsAllocated = 8 ds.SmallestImagePixelValue = pixel_array.min() ds.LargestImagePixelValue = pixel_array.max() ds.Columns = pixel_array.shape[0] ds.Rows = pixel_array.shape[1] # Fixing the sequence if the number of frames was less than the original # it happens if we remove the last volume for phillips data (mean) if ds_ori.NumberOfFrames > nb_frames: new_seq = Sequence() for i in xrange(0, ds_ori.NumberOfFrames): if i % 5 == 0: # take one slice for each (14) new_seq.append(ds_ori[0x5200, 0x9230][i]) ds[0x5200, 0x9230].value = new_seq # Organise the array: pixel_array2 = np.zeros((pixel_array.shape[0]*pixel_array.shape[2], pixel_array.shape[1])) for i in range(pixel_array.shape[2]): pixel_array2[pixel_array.shape[0]*i:pixel_array.shape[0]*(i+1), :] = pixel_array[:, :, i, 0] # Set the Image pixel array if pixel_array2.dtype != np.uint8: pixel_array2 = pixel_array2.astype(np.uint8) ds.PixelData = pixel_array2.tostring() # Save the image ds.save_as(filename)
def WriteDICOM_slice(self, pixel_array,filename, itemnumber=0, PhotometricInterpretation="MONOCHROME2"): from dicom.dataset import Dataset, FileDataset import numpy as np import datetime, time """ INPUTS: pixel_array: 2D numpy ndarray. If pixel_array is larger than 2D, errors. filename: string name for the output file. """ ## This code block was taken from the output of a MATLAB secondary ## capture. I do not know what the long dotted UIDs mean, but ## this code works. 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.Modality = 'WSD' ds.ContentDate = str(datetime.date.today()).replace('-','') ds.ContentTime = str(time.time()) #milliseconds since the epoch 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.369231118011061003403421859172643143649' ds.SOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780' ds.SOPClassUID = 'Secondary Capture Image Storage' ds.SecondaryCaptureDeviceManufctur = 'Python 2.7.3' ## These are the necessary imaging components of the FileDataset object. ds.SamplesPerPixel = 1 if PhotometricInterpretation=="MONOCHROME2": ds.PhotometricInterpretation = "MONOCHROME2" ds.PixelRepresentation = 0 ds.HighBit = 15 ds.BitsStored = 16 ds.BitsAllocated = 16 ds.SmallestImagePixelValue = '\\x00\\x00' ds.LargestImagePixelValue = '\\xff\\xff' elif PhotometricInterpretation=="RGB": ds.PhotometricInterpretation = "MONOCHROME2" ds.PixelRepresentation = 0 ds.HighBit = 15 ds.BitsStored = 16 ds.BitsAllocated = 16 ds.SmallestImagePixelValue = '\\x00\\x00' ds.LargestImagePixelValue = '\\xff\\xff' pixel_array = pixel_array[0] print pixel_array.shape ds.Columns = pixel_array.shape[0] ds.ItemNumber = str(itemnumber) ds.InstanceNumber = str(itemnumber) ds.SliceLocation = str(itemnumber) ds.Rows = pixel_array.shape[1] if pixel_array.dtype != np.uint16: pixel_array = pixel_array.astype(np.uint16) ds.PixelData = pixel_array.tostring() ds.save_as(filename) return filename
def saveDicomFile(filename, patientName, patientId, gender, birthday, imageArray, transpose=False): meta = Dataset() SOPClassUID = "1.2.840.10008.5.1.4.1.1.2" # sop class UID dla obrazow CT meta.MediaStorageSOPClassUID = SOPClassUID # Wygenerowany unikalny UID date=datetime.datetime.now().strftime('%Y%m%d') # Obecny czas time=datetime.datetime.now().strftime('%H%M%S.%f') # Obecny czas randomUId = SOPClassUID + "."+date+time # Wygenerowany unikalny UID meta.MediaStorageSOPInstanceUID = randomUId # Wygenerowany unikalny UID meta.ImplementationClassUID = randomUId+"."+"1" # Wygenerowany unikalny UID dataSet = FileDataset(filename, {}, file_meta=meta, preamble=b"\0"*128) # Utworzenie obiektu DICOM dataSet.PatientName = patientName # Imie pacjenta dataSet.PatientID=patientId # Id pacjenta dataSet.PatientBirthDate = birthday # Data urodzenia pacjenta dataSet.PatientSex = gender # Plec pacjenta dataSet.is_little_endian=True dataSet.is_implicit_VR=True dataSet.ContentDate = date # Czas utworzenia pliku (YYYY:MM:DD) dataSet.StudyDate = date # Czas ostatniego otworzenia obrazu (YYYY-MM-DD) dataSet.StudyTime = time # Czas ostatniego otworzenia obrazu (HH:MM:SS) dataSet.ContentTime=time # Czas utworzenia pliku (HH:MM:SS) dataSet.StudyInstanceUID = randomUId+"."+"2" # Wygenerowany unikalny UID dataSet.SeriesInstanceUID = randomUId+"."+"3" # Wygenerowany unikalny UID dataSet.SOPInstanceUID = randomUId+"."+"4" # Wygenerowany unikalny UID dataSet.SOPClassUID = "CT."+date+time # Wygenerowany unikalny UID dataSet.SamplesPerPixel = 1 # Liczba kanałów. 1 - dla skali szarosci dataSet.PhotometricInterpretation = "MONOCHROME2" # MONOCHROE - obraz jest w skali szarości, 2 - maksymalna wartosc wskazuje kolor bialy dataSet.PixelRepresentation = 0 # 0 - wartosci sa tylko dodatnie (unsigned) 1 - wartosci sa tez ujemne dataSet.HighBit = 15 # Najważniejszy bit w pliku z obrazem dataSet.BitsStored = 16 # Liczba bitow na jedna wartosc w obrazie dataSet.BitsAllocated = 16 # Liczba bitow na jedna wartosc ktora jest zaalokowana dla obrazu dataSet.SmallestImagePixelValue = b'\\x00\\x00' # Wskazanie minimalnej wartosci dla kanalu dataSet.LargestImagePixelValue = b'\\xff\\xff' # Wskazanie maksymalnej wartosci dla kanalu dataSet.Rows = imageArray.shape[1] # Liczba wierszy dataSet.Columns = imageArray.shape[0] # Liczba kolumn if imageArray.dtype != np.uint16: # Sprawdzenie czy wartosci sa w przedziale [0,255] imageArray = skimage.img_as_uint(imageArray) # Zamiana na wartosci w przedziale [0,255] if transpose == True: # Zamiana wierszy i kolumn (opcjonalne) dataSet.Rows = imageArray.shape[0] dataSet.Columns = imageArray.shape[1] dataSet.PixelData = imageArray.tostring() # Zapisanie obrazu dataSet.save_as(filename) # Zapisanie pliku na dysku
def writeDicomFiles(self, filename): for i in range(1,len(self.PA)): #Image 0 is a null image for default display and will not be written out fileName = filename + str(i) + ".dcm" # print ("printing dicom file " + fileName) # Populate required values for file meta information 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' # Create the FileDataset instance (initially no data elements, but file_meta supplied) ds = FileDataset(fileName, {}, file_meta=file_meta, preamble="\0"*128) ds.Modality = 'MR' ds.ContentDate = str(datetime.date.today()).replace('-','') ds.ContentTime = str(time.time()) #milliseconds since the epoch 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.369231118011061003403421859172643143649' ds.SOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780' ds.SOPClassUID = 'MR Image Storage' ds.SecondaryCaptureDeviceManufctur = 'Python 2.7.3' ## These are the necessary imaging components of the FileDataset object. 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' #Add MRI data elements ds.bValue= self.bValue[i] ds.Columns=self.Columns[i] ds.FoVX=self.FoVX[i] ds.FoVY=self.FoVY[i] ds.ImageOrientationPatient=self.ImagePosition[i].tolist() ds.InstitutionName=self.InstitutionName[i] ds.PixelBandwidth= self.PixelBandwidth[i] ds.PixelSpacing =[self.PixelSpacingY[i],self.PixelSpacingX[i]] ds.Rows= self.Rows[i] ds.PatientName = self.PatientName[i] ds.PatientID = "123456" ds.ProtocolName=self.ProtocolName[i] ds.RepetitionTime = self.TR[i] ds.SeriesDescription=self.SeriesDescription[i] ds.EchoTime = self.TE[i] ds.FlipAngle= self.FA[i] ds.InversionTime=self.TI[i] ds.ImageOrientationPatient[3:6]=self.ColumnDirection[i].tolist() ds.ImageOrientationPatient[:3]=self.RowDirection[i].tolist() ds.MagneticFieldStrength = self.MagneticFieldStrength[i] ds.Manufacturer = self.Manufacturer[i] pixel_array=np.transpose(self.PA[i]) #numpy pixel array if self.DataType[i].lower() == "phase" : pixel_array=(pixel_array+np.pi) *10000 # phase data -pi to pi is converted to 0 to 10000pi #print "Adjusting phase to 16 bit integer" if pixel_array.dtype != np.uint16: pixel_array = pixel_array.astype(np.uint16) ds.PixelData = pixel_array.tostring() # image byte data # Set the transfer syntax ds.is_little_endian = True ds.is_implicit_VR = True ds.save_as(fileName)
file_meta.PixelRepresentation = 0 file_meta.BitsAllocated = 8 # Binary = 1 file_meta.BitsStored = 8 # Binary = 1 file_meta.HighBit = 7 # Binary = 0 file_meta.SegmentationType = 'FRACTIONAL' #FRACTIONAL or BINARY file_meta.SegmentationFractionalType = 'OCCUPANCY' #Can be OCCUPANCY or PROBABILITY file_meta.MaximumFractionalValue = 116 # 116 is the number of labels in AAL file_meta.SegmentSequence = 'AAL' # List of segments? file_meta.SegmentNumber = 1 #Number identifying the segment print "Setting dataset values..." # Create the FileDataset instance (initially no data elements, but file_meta supplied) ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0"*128) # Add the data elements -- not trying to set all required here. Check DICOM standard ds.PatientsName = "Test^Firstname" ds.PatientID = "123456" # Populate required values for file meta information ds.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.66.4' # Segmentation SOP Class ds.MediaStorageSOPInstanceUID = "1.2.840.10008.5.1.4.1.1.66.4" # !! Need valid UID here for real work ds.ImplementationClassUID = "1.2.840.10008.5.1.4.1.1.66.4" # !!! Need valid UIDs here # Required for Segmentation IOD ds.Modality = 'SEG' ds.SeriesNumber = '001' ds.ImageType = '1' # Derived = 1, Primary = 2
def fileOutput(infilename, PLOT=False): noiseAmp = 150 #units are "HA". See file in slack. cellLocations = read_CA_output(infilename, noiseAmp) outfilename = datetime.now().strftime("%y-%m-%d-%H%M.dcm") # Populate required values for file meta information file_meta = Dataset() file_meta.FileMetaInformationGroupLength = 190 file_meta.FileMetaInformationVersion = '\x00\x01' file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' # CT Image Storage file_meta.MediaStorageSOPInstanceUID = '1.3.6.1.4.1.9590.100.1.2.115051905812620145920373971792360190180' file_meta.TransferSyntaxUID = '1.2.840.10008.1.2' file_meta.ImplementationClassUID = '1.2.40.0.13.1.1' file_meta.ImplementationVersionName = 'dcm4che-2.0' ds = FileDataset(outfilename, {}, file_meta=file_meta, preamble="\0" * 128) # Set the transfer syntax ds.is_little_endian = True ds.is_implicit_VR = True #Set the data that we copied from another dicom file setAttributes(ds) # Set the image's data equal to that from our CA output ds.Rows = cellLocations.shape[0] ds.Columns = cellLocations.shape[1] if cellLocations.dtype != np.uint16: ds.PixelData = cellLocations.astype(np.uint16).tostring() else: ds.PixelData = cellLocations.tostring() ds.SmallestImagePixelValue = struct.pack( "<i", nmin ) #'\\x00\\x00': struct.pack("<H",0), w/ little_endian=True https://docs.python.org/2/library/struct.html#byte-order-size-and-alignment ds.LargestImagePixelValue = struct.pack( "<i", nmax) #'\\xff\\xff': struct.pack("<H",65535) ds.save_as(outfilename) if (PLOT): plt.imshow(ds.pixel_array, cmap=plt.cm.bone) plt.show()
def write_dicom(pixel_array, filename, series_number, fdf_info, series_description, project, subject, session): """Write a dicom from a pixel_array (numpy). :param pixel_array: 2D numpy ndarray. If pixel_array is larger than 2D, errors. :param filename: string name for the output file. :param ds_ori: original pydicom object of the pixel_array :param series_number: number of the series being processed :param series_description: series description for Osirix display :param project: XNAT Project ID :param subject: XNAT Subject label :param session: XNAT Session label """ # Variables pixel_array = np.rot90(pixel_array) pixel_array = np.rot90(pixel_array) pixel_array = np.rot90(pixel_array) # less than zero # pixel_array[pixel_array < 0] = 0 now = datetime.datetime.now() date = '%d%02d%02d' % (now.year, now.month, now.day) sop_id = '1.2.840.10008.5.1.4.1.1.4.%s' % date ti = str(time.time()) uid = sop_id + ti # Other tags to set sop_uid = sop_id + str(now).replace('-', '')\ .replace(':', '')\ .replace('.', '')\ .replace(' ', '') # Number of frames size = pixel_array.shape nb_frames = None if len(size) == 3: nb_frames = size[2] elif len(size) == 4: nb_frames = size[2]*size[3] # Create the ds object file_meta = Dataset() file_meta.MediaStorageSOPClassUID = 'Secondary Capture Image Storage' file_meta.MediaStorageSOPInstanceUID = sop_id file_meta.ImplementationClassUID = '1.2.840.10008.5.1.4.1.1.4' ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0"*128) ds.SeriesDate = '%d%02d%02d' % (now.year, now.month, now.day) ds.ContentDate = '%d%02d%02d' % (now.year, now.month, now.day) ds.ContentTime = str(time.time()) # milliseconds since the epoch ds.StudyInstanceUID = uid ds.SeriesInstanceUID = uid # Other tags to set ds.SOPInstanceUID = sop_uid[:-1] ds.SOPClassUID = 'Secondary Capture Image Storage' ds.SecondaryCaptureDeviceManufctur = 'Python 2.7.3' # These are the necessary imaging components of the FileDataset object. ds.Modality = 'MR' ds.ConversionType = 'WSD' ds.SamplesPerPixel = 1 ds.PhotometricInterpretation = "MONOCHROME2" ds.PixelRepresentation = 0 ds.HighBit = 15 ds.BitsStored = 16 ds.BitsAllocated = 16 ds.Columns = pixel_array.shape[0] ds.Rows = pixel_array.shape[1] ds.ProtocolName = '%s 9.4T' % series_description ds.StudyDescription = project ds.PatientsName = subject ds.PatientID = session ds.SeriesDescription = series_description ds.SeriesNumber = 1 ds.SmallestImagePixelValue = pixel_array.min() ds.LargestImagePixelValue = pixel_array.max() ds.AcquisitionNumber = 1 ds.SamplesperPixel = 1 ds.PixelSpacing = '%s\%s' % (fdf_info['spacing'][0], fdf_info['spacing'][1]) ds.SpacingBetweenSlices = float(fdf_info['spacing'][2]) ds.ImageOrientation = '\\'.join(fdf_info['orientation']) ds.PatientPosition = '\\'.join(fdf_info['origin']) if nb_frames: ds.NumberOfFrames = nb_frames # Organise the array: if len(size) == 3: pixel_array2 = np.zeros((size[0]*size[2], size[1])) for i in range(size[2]): pixel_array2[size[0]*i:size[0]*(i+1), :] = pixel_array[:, :, i] elif len(size) > 3: pixel_array2 = np.zeros((size[0]*size[2]*size[3], size[1])) for i in range(size[2]): for j in range(size[3]): pixel_array2[size[0]*j+i*size[3]*size[0]: size[0]*(j+1)+i*size[3]*size[0], :] = pixel_array[:, :, i, j] else: pixel_array2 = pixel_array # Set the Image pixel array if pixel_array2.dtype != np.uint16: pixel_array2 = pixel_array2.astype(np.uint16) print pixel_array2.max() print pixel_array2.min() ds.PixelData = pixel_array2.tostring() # Save the image ds.save_as(filename)
def write_dicom(pixel_array, filename): 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.Modality = 'WSD' ds.ContentDate = str(datetime.date.today()).replace('-', '') ds.ContentTime = str(time.time()) #milliseconds since the epoch 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.369231118011061003403421859172643143649' ds.SOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780' ds.SOPClassUID = 'Secondary Capture Image Storage' ds.SecondaryCaptureDeviceManufctur = 'Python 2.7.3' ## These are the necessary imaging components of the FileDataset object. 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] if pixel_array.dtype != np.uint16: pixel_array = pixel_array.astype(np.uint16) ds.PixelData = pixel_array.tostring() ds.save_as(filename)
def write_dicom_mask(img_slice, ds, slice_no, outputdirectory, mask_suffix, filepattern=".dcm"): ds_slice = ds[slice_no] series_number = ds_slice[0x0020, 0x0011].value base_fname = str(slice_no).zfill(6) filename = outputdirectory + os.path.sep + base_fname + "_" + str( series_number) + mask_suffix + filepattern ds = FileDataset(filename, ds_slice, file_meta=ds_slice.file_meta, preamble=b"\0" * 128) ds.SOPInstanceUID = ds_slice.SOPInstanceUID ds.SOPClassUID = "1.2.840.10008.5.1.4.1.1.2" ds.StudyID = "123" ds.PatientName = "Liver^Larry^H" # Set the transfer syntax ds.is_little_endian = True ds.is_implicit_VR = False # These are the necessary imaging components of the FileDataset object. (rows, cols) = img_slice.shape ds.SamplesPerPixel = 1 ds.PhotometricInterpretation = "MONOCHROME2" ds.PixelRepresentation = 0 ds.HighBit = 15 ds.BitsStored = 16 ds.BitsAllocated = 16 ds.Columns = cols ds.Rows = rows ds.PixelData = img_slice.tobytes() image_type_val = ds_slice[0x0008, 0x0008].value image_type_val_str = "\\".join(str(x) for x in image_type_val) image_type_val_str2 = image_type_val_str.replace("ORIGINAL", "DERIVED", 1) ds.ImageType = image_type_val_str2 # display components ds.WindowCenter = [0] # 0028,1050 Window Center ds.WindowWidth = [1] # 0028,1051 Window Width ds.RescaleIntercept = 0 # 0028,1052 Rescale Intercept: 0 ds.RescaleSlope = 1 # 0028,1053 Rescale Slope: 1 ds.save_as(filename)
def create_dicom(private_tag, payload, filename, dcmconfig): """ Function creates minimal dicom file from scratch with required tags and stores payload (string) in the specified private tag. """ PatientID = dcmconfig['patid'] PatientName = dcmconfig['patname'] StudyDescription = dcmconfig['studydes'] SeriesDescription = dcmconfig['seriesdes'] StationName = dcmconfig['stationname'] StudyDate = dcmconfig['studydate'].strftime('%Y%m%d') StudyTime = dcmconfig['studytime'].strftime('%H%M%S') # create empty dicomfile file_meta = Dataset() # Raw Data Storage file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.66' # unieke uid's file_meta.MediaStorageSOPInstanceUID = dicom.UID.generate_uid() file_meta.ImplementationClassUID = dicom.UID.generate_uid() ds = FileDataset(filename, {},file_meta = file_meta,preamble="\0"*128) ds.SOPClassUID = '1.2.840.10008.5.1.4.1.1.7' # secondary capture SOP UID ds.SOPInstanceUID = file_meta.MediaStorageSOPInstanceUID ds.StudyInstanceUID = dicom.UID.generate_uid() ds.SeriesInstanceUID = dicom.UID.generate_uid() ds.PatientID = PatientID ds.PatientName = PatientName ds.StudyDescription = StudyDescription ds.SeriesDescription = SeriesDescription ds.StationName = StationName ds.Modality = 'OT' ds.StudyDate = StudyDate ds.SeriesDate = ds.StudyDate ds.ContentDate = ds.StudyDate ds.StudyTime = ds.SeriesTime = ds.ContentTime = StudyTime ds.add_new(private_tag,'OB', payload) return ds
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 _write_numpy_2_dicom(pixel_array, dcmfilename): filename = dcmfilename[dcmfilename.index('-') + 1:dcmfilename.index('.mhd')] print(filename) for i in range(pixel_array.shape[0]): file_meta = Dataset() file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2' # CT Image Storage file_meta.MediaStorageSOPInstanceUID = "1.2.3" # !! Need valid UID here for real work file_meta.ImplementationClassUID = "1.2.3.4" # !!! Need valid UIDs here ds = FileDataset(dcmfilename, {}, file_meta=file_meta, preamble="\0" * 128) ds.Modality = 'WSD' ds.ContentDate = str(datetime.date.today()).replace('-', '') ds.ContentTime = str(time.time()) # milliseconds since the epoch 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.369231118011061003403421859172643143649' ds.SOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780' ds.SOPClassUID = 'Secondary Capture Image Storage' ds.SecondaryCaptureDeviceManufctur = 'Python 2.7.3' ## These are the necessary imaging components of the FileDataset object. 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[1] ds.Rows = pixel_array.shape[2] ds.PixelData = pixel_array[i].tostring() dcm = "{0}{1}-{2}.dcm".format(output_path, filename, i) print("dcm filename = %s,shape = %s" % (dcm, pixel_array[0].shape)) ds.save_as(dcm)
def process_mrs_ge(pfile_dir): # Make a top-level instance and hide in top left corner, get filepath # root = Tkinter.Tk() # root.geometry('0x0+0+0') # root.attributes("-topmost", 1) # pfile_dir = tkFileDialog.askdirectory(parent=root) # root.attributes("-topmost", 0) # root.destroy() print('Working...') root_dir = os.path.abspath(os.path.join(pfile_dir, os.pardir)) pat_name = os.path.split(os.path.dirname(pfile_dir))[1] filelist = glob.glob(pfile_dir + '/*.7') filelist.extend(glob.glob(pfile_dir + '/*.anon')) for fname in filelist: try: print('') print(fname) fbin = open(fname, 'rb') sw_ver = int( str(struct.unpack('f', fbin.read(4))[0]).split('.')[0]) print('software version: ' + str(sw_ver)) s = fbin.read() if s.find('PROBE-P') > 0: seqtype = 'PRESS' elif s.find('PROBE-S') > 0: seqtype = 'STEAM' else: print('WARNING: acquisition type not recognised!') if sw_ver < 26: fbin.seek(82) pt_sz = struct.unpack('<h', fbin.read(2))[0] fbin.seek(1468) hdr_sz = struct.unpack('<i', fbin.read(4))[0] if sw_ver == 15: fbin.seek(144580) # FOR REV 15 elif sw_ver == 16: fbin.seek(144628) # FOR REV 16 elif sw_ver > 19: fbin.seek(148404) # FOR REV 20 & 24 te = struct.unpack('<i', fbin.read(4))[0] if sw_ver == 15: fbin.seek(144572) # FOR REV 15 elif sw_ver == 16: fbin.seek(144620) # FOR REV 16 elif sw_ver > 19 and sw_ver < 26: fbin.seek(148396) # FOR REV 20 & 24 tr = struct.unpack('<i', fbin.read(4))[0] fbin.seek(148712) exam_no = struct.unpack('<i', fbin.read(4))[0] fbin.seek(148724) series_no = struct.unpack('<i', fbin.read(4))[0] fbin.seek(424) c_freq = struct.unpack('<i', fbin.read(4))[0] fbin.seek(200) st_rcv = struct.unpack('<h', fbin.read(2))[0] fbin.seek(202) en_rcv = struct.unpack('<h', fbin.read(2))[0] fbin.seek(70) nechoes = struct.unpack('<h', fbin.read(2))[0] fbin.seek(72) navs = struct.unpack('<h', fbin.read(2))[0] fbin.seek(74) nframes = struct.unpack('<h', fbin.read(2))[0] n_rcv = (en_rcv - st_rcv) + 1 # pfile=headers.Pfile.from_file(fname) # frm_sz=pfile.acq_x_res*2*pt_sz # echo_size=frm_sz*pfile.acq_y_Res # slice_size=echo_size*nechoes # data_sz=pfile.acq_x_res*2*(pfile.acq_y_Res-1) fbin.seek(102) acq_x_res = struct.unpack('<h', fbin.read(2))[0] fbin.seek(104) acq_y_Res = struct.unpack('<h', fbin.read(2))[0] fbin.seek(216) bandwidth = struct.unpack('<f', fbin.read(4))[0] # if sw_ver == 15: # fbin.seek(948) # FOR REV 15 # elif sw_ver == 16: # fbin.seek(948) # FOR REV 16 # elif sw_ver > 19: # fbin.seek(948) # FOR REV 20 & 24 fbin.seek(232) ws_nsa = struct.unpack('<f', fbin.read(4))[0] elif sw_ver == 26: fbin.seek(158) pt_sz = struct.unpack('<h', fbin.read(2))[0] fbin.seek(4) hdr_sz = struct.unpack('<i', fbin.read(4))[0] fbin.seek(199244) # FOR REV 26 te = struct.unpack('<i', fbin.read(4))[0] fbin.seek(199236) # FOR REV 26 tr = struct.unpack('<i', fbin.read(4))[0] fbin.seek(196428) exam_no = struct.unpack('<i', fbin.read(4))[0] fbin.seek(194068) series_no = struct.unpack('<i', fbin.read(4))[0] fbin.seek(504) c_freq = struct.unpack('<i', fbin.read(4))[0] fbin.seek(264) st_rcv = struct.unpack('<h', fbin.read(2))[0] fbin.seek(266) en_rcv = struct.unpack('<h', fbin.read(2))[0] fbin.seek(146) nechoes = struct.unpack('<h', fbin.read(2))[0] fbin.seek(148) navs = struct.unpack('<h', fbin.read(2))[0] fbin.seek(2520) nframes = struct.unpack('<h', fbin.read(2))[0] n_rcv = (en_rcv - st_rcv) + 1 # pfile=headers.Pfile.from_file(fname) # frm_sz=pfile.acq_x_res*2*pt_sz # echo_size=frm_sz*pfile.acq_y_Res # slice_size=echo_size*nechoes # data_sz=pfile.acq_x_res*2*(pfile.acq_y_Res-1) fbin.seek(156) acq_x_res = struct.unpack('<h', fbin.read(2))[0] fbin.seek(180) acq_y_Res = struct.unpack('<h', fbin.read(2))[0] fbin.seek(280) bandwidth = struct.unpack('<f', fbin.read(4))[0] fbin.seek(296) ws_nsa = struct.unpack('<f', fbin.read(4))[0] ws_avgs = int(ws_nsa) / int(navs) frm_sz = acq_x_res * 2 * pt_sz echo_size = frm_sz * acq_y_Res slice_size = echo_size * nechoes data_sz = acq_x_res * 2 * (acq_y_Res - 1) #off_raw is the offset in bytes to the start of the raw data off_raw = hdr_sz + frm_sz w_avgs = acq_y_Res - 1 - ws_avgs print('Number of water ref frames : ' + str(w_avgs)) print('Number of data frames : ' + str(ws_avgs)) fbin.seek(off_raw) raw_data = np.zeros(data_sz) frame_data = np.zeros(shape=(int(acq_y_Res - 1), int(acq_x_res), int(n_rcv)), dtype=np.int64) frame_data = frame_data.view(np.complex64) rot_frame_data = np.zeros(shape=(int(acq_y_Res - 1), int(acq_x_res), int(n_rcv)), dtype=np.float64) rot_frame_data = rot_frame_data.view(np.complex64) fid_norm = np.zeros(shape=(int(acq_y_Res - 1), int(acq_x_res), int(n_rcv)), dtype=np.float64) fid_norm = fid_norm.view(np.complex64) summed_signal = np.zeros(shape=(int(acq_y_Res - 1) * int(acq_x_res)), dtype=np.float64) summed_signal = summed_signal.view(np.complex64) for receiver in range(0, n_rcv): fbin.seek(off_raw + (slice_size * receiver)) for element in range(0, data_sz): raw_data[element] = struct.unpack('<i', fbin.read(4))[0] for frm in range(0, int(acq_y_Res - 1)): row_off = frm * acq_x_res * 2 for pt in range(0, int(acq_x_res)): frame_data[frm, pt, receiver] = raw_data[ (2 * pt) + row_off] + 1j * raw_data[(2 * pt) + 1 + row_off] fbin.close() amp = np.zeros(n_rcv, dtype=np.int64) amp = amp.view(np.complex64) amp = frame_data[0, 5, :] ang = np.zeros(n_rcv) fid_w = np.zeros(n_rcv) for n in range(0, n_rcv): ang[n] = cmath.phase(list(frame_data[0, 5, :])[n]) # print(ang) ph_dif = ang - ang[0] for receiver in range(0, n_rcv): rot_frame_data[:, :, receiver] = frame_data[:, :, receiver] * np.exp( -1j * ph_dif[receiver]) for receiver in range(0, n_rcv): fid_w[receiver] = abs(amp[receiver]) / np.sqrt( sum(abs(amp * amp))) # fid_w[receiver]=abs(amp[receiver])/sum(abs(amp)) # fid_w=np.max(np.abs(frame_data[1,:,:]),axis=0)/np.sqrt(np.sum(np.max(np.abs(frame_data[1,:,:]),axis=0)*np.max(np.abs(frame_data[1,:,:]),axis=0))) # fid_w=np.abs(np.max(frame_data[0,:,:],axis=0))/(np.sum(np.abs(np.max(frame_data[0,:,:],axis=0)))) fid_norm[:, :, receiver] = rot_frame_data[:, :, receiver] * fid_w[receiver] summed_signal = np.sum(fid_norm, axis=2) #fbin.close() #raw_data=raw_data.astype(np.int64) print('coil weightings:') print(fid_w) output_data_ws = [] for pt in range(w_avgs * int(acq_x_res), np.size(summed_signal)): output_data_ws.append( np.float64(np.imag(summed_signal.flatten()[pt]))) output_data_ws.append( np.float64(np.real(summed_signal.flatten()[pt]))) output_data_w = [] for pt in range(0, w_avgs * int(acq_x_res)): output_data_w.append( np.float64(np.imag(summed_signal.flatten()[pt]))) output_data_w.append( np.float64(np.real(summed_signal.flatten()[pt]))) file_meta = Dataset() file_meta.MediaStorageSOPClassUID = 'MRSpectroscopyStorage' file_meta.MediaStorageSOPInstanceUID = dicom.UID.generate_uid() file_meta.ImplementationClassUID = dicom.UID.generate_uid() ds_ws = FileDataset(fname + '_dcm', {}, file_meta=file_meta, preamble="\0" * 128) ds_ws.Modality = 'MR' ds_ws.ContentDate = str(datetime.date.today()).replace('-', '') ds_ws.ContentTime = str(time.time()) #milliseconds since the epoch ds_ws.StudyInstanceUID = dicom.UID.generate_uid() ds_ws.SeriesInstanceUID = dicom.UID.generate_uid() ds_ws.SOPInstanceUID = dicom.UID.generate_uid() ds_ws.SOPClassUID = 'MRSpectroscopyStorage' ds_ws.SecondaryCaptureDeviceManufctur = 'Python 2.7.3' ds_ws.VolumeLocalizationTechnique = seqtype ds_ws.RepetitionTime = tr / 1000 ## These are the necessary imaging components of the FileDataset object. ds_ws.Columns = 1 ds_ws.Rows = 1 ds_ws.DataPointColumns = int(acq_x_res) ds_ws.SpectroscopyAcquisitionDataColumns = ds_ws.DataPointColumns ds_ws.DataPointRows = ws_avgs ds_ws.SpectroscopyData = output_data_ws ds_ws.ImageType = ['ORIGINAL', 'PRIMARY', 'SPECTROSCOPY', 'NONE'] ds_ws.SpectralWidth = bandwidth ds_ws.SeriesNumber = series_no ds_ws.ProtocolName = fname.split('\\')[-1].split( '.')[0] + '_SVS_TR' + str(int(tr / 1000)) + '_TE' + str( int(te / 1000)) c_freq2 = c_freq / 10000000.0 ds_ws.TransmitterFrequency = c_freq2 ds_ws.EffectiveEchoTime = te / 1000 ds_ws.EchoTime = te / 1000 ds_ws.WaterReferencedPhaseCorrection = 'N' if w_avgs > 0: file_meta_w = Dataset() file_meta_w.MediaStorageSOPClassUID = 'MRSpectroscopyStorage' file_meta_w.MediaStorageSOPInstanceUID = dicom.UID.generate_uid( ) file_meta_w.ImplementationClassUID = dicom.UID.generate_uid() ds_w = FileDataset(fname + '_dcm', {}, file_meta=file_meta, preamble="\0" * 128) ds_w.Modality = 'MR' ds_w.ContentDate = str(datetime.date.today()).replace('-', '') ds_w.ContentTime = str( time.time()) #milliseconds since the epoch ds_w.StudyInstanceUID = dicom.UID.generate_uid() ds_w.SeriesInstanceUID = dicom.UID.generate_uid() ds_w.SOPInstanceUID = dicom.UID.generate_uid() ds_w.SOPClassUID = 'MRSpectroscopyStorage' ds_w.SecondaryCaptureDeviceManufctur = 'Python 2.7.3' ds_w.VolumeLocalizationTechnique = seqtype ## These are the necessary imaging components of the FileDataset object. ds_w.Columns = 1 ds_w.Rows = 1 ds_w.DataPointColumns = int(acq_x_res) ds_w.SpectroscopyAcquisitionDataColumns = ds_w.DataPointColumns ds_w.DataPointRows = w_avgs ds_w.SpectroscopyData = output_data_w ds_w.ImageType = [ 'ORIGINAL', 'PRIMARY', 'SPECTROSCOPY', 'NONE' ] ds_w.SpectralWidth = bandwidth ds_w.SeriesNumber = series_no ds_w.ProtocolName = fname.split('\\')[-1].split( '.')[0] + '_SVS_TR' + str(int(tr / 1000)) + '_TE' + str( int(te / 1000)) c_freq2 = c_freq / 10000000.0 ds_w.TransmitterFrequency = c_freq2 ds_w.EffectiveEchoTime = te / 1000 ds_w.EchoTime = te / 1000 ds_w.RepetitionTime = tr / 1000 ds_w.WaterReferencedPhaseCorrection = 'N' if not os.path.exists( str(root_dir) + '/' + str(pat_name) + '_PREPROC_LCM'): os.makedirs( str(root_dir) + '/' + str(pat_name) + '_PREPROC_LCM') # if not os.path.exists(str(root_dir)+'/'+str(pat_name)+'_LCM_Results'): # os.makedirs(str(root_dir)+'/'+str(pat_name)+'_LCM_Results') ds_ws.save_as( str(root_dir) + '/' + str(pat_name) + '_PREPROC_LCM/' + str(ds_ws.ProtocolName)) if w_avgs > 0: ds_w.save_as( str(root_dir) + '/' + str(pat_name) + '_PREPROC_LCM/' + str(ds_w.ProtocolName) + '_WATER') except AttributeError: print('...') except IOError: print 'no such file' print('DONE!')
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