def extractStudyDetails(inputImageFile): """Reads and extracts Patient's Basic Info from a DICOM file. """ studyList = [] dicomfile = inputImageFile tracker = set() trackerID='' for i, dfile in enumerate(dicomfile): studyDetails = {} ds = dicomio.read_file(dfile) if ds[0x00200010]: # print(ds[0x00200010]) trackerID = str(ds.StudyID) if trackerID in tracker: '' else: studyDetails["StudyID"]= ds.StudyID studyDetails["StudyDescription"]=ds.StudyDescription studyDetails["StudyDate"]= datetime.strptime(ds.StudyDate, '%Y%m%d') studyDetails["PatientID"]=ds.PatientID tracker.add(str(ds.StudyID)) studyList.append(studyDetails) else: '' return studyList
def run(path): # Используем Python одним потоком start_time = time.time() paths = find_all_files(path) for file_path in paths: if os.path.isdir(file_path): continue dcm = dicomio.read_file(file_path, specific_tags=REQUIRED_TAGS) tags_py = { t: dcm.get(t) if t in dcm else DEFAULT_TAG_VAL for t in REQUIRED_TAGS } py_long = time.time() - start_time # ---------------------------------------- # Используем Rust start_time = time.time() _ = py_dcm_finder_rs.load_dcm_files_in_dir(path, REQUIRED_TAGS, DEFAULT_TAG_VAL) rust_long = time.time() - start_time # ---------------------------------------- # Используем Python c multiprocessing start_time = time.time() find_and_read_dcm_in_dir_multiproc(path) multi_py_long = time.time() - start_time # ---------------------------------------- print(f"Всего файлов в папке: {len(paths)}") print("─" * 42) print(f"| {'Python одним процессом':25} | {f'{py_long:.5f}':10} |") print(f"| {'Rust вызванный из python':25} | {f'{rust_long:.5f}':10} |") print(f"| {'Python мульти процес.':25} | {f'{multi_py_long:.5f}':10} |") print("─" * 42)
def __init__(self, dataset, memmap_pixel_array=False): self.memmap_pixel_array = memmap_pixel_array if isinstance(dataset, Dataset): self.ds = dataset elif isinstance(dataset, (string_types, BytesIO)): try: with open(dataset, "rb") as fp: self.ds = read_file(fp, defer_size=100, force=True, stop_before_pixels=memmap_pixel_array) if memmap_pixel_array: self.offset = fp.tell() + 8 except: # Raise the error for the calling method to handle raise else: # Sometimes DICOM files may not have headers, # but they should always have a SOPClassUID # to declare what type of file it is. # If the file doesn't have a SOPClassUID, # then it probably isn't DICOM. if not "SOPClassUID" in self.ds: raise AttributeError else: raise AttributeError if memmap_pixel_array: self.filename = dataset self.pixel_array = self.get_pixel_array else: if "PixelData" in self.ds: self.pixel_array = self.ds.pixel_array
def extractPatientDetails(inputImageFile): """Reads and extracts Patient's Basic Info from a DICOM file. """ PatientList = [] dicomfile = inputImageFile tracker = set() for i, dfile in enumerate(dicomfile): patientDetails = {} ds = dicomio.read_file(dfile) trackerID = str(ds.PatientID) if trackerID in tracker: '' else: patientDetails["PatientID"]=ds.PatientID patientDetails["PatientName"]= str.replace(str(ds.PatientName),'^',' ') patientDetails["PatientSex"]=ds.PatientSex if ds[0x00101010]: patientDetails["PatientReportedAge"]=ds.PatientAge else: patientDetails["PatientReportedAge"]='' dob = datetime.strptime(ds.PatientBirthDate , '%Y%m%d') sod = datetime.strptime(ds.StudyDate, '%Y%m%d') patientDetails["PatientBirthDate"]= dob patientDetails['Age_Days']= str.replace(str(sod-dob),'days, 0:00:00','') tracker.add(str(ds.PatientID)) PatientList.append(patientDetails) return PatientList
def test_trait_names(self): """Test Dataset.trait_names contains element keywords""" test_file = get_testdata_files('CT_small.dcm')[0] ds = read_file(test_file, force=True) names = ds.trait_names() assert 'PatientName' in names assert 'save_as' in names assert 'PixelData' in names
def test_trait_names(self): """Test Dataset.trait_names contains element keywords""" test_file = os.path.join(DATA_ROOT, 'test_files', 'CT_small.dcm') ds = read_file(test_file, force=True) names = ds.trait_names() assert 'PatientName' in names assert 'save_as' in names assert 'PixelData' in names
def read_file(*args, **kwargs): global read_file from pydicom.dicomio import read_file import warnings msg = ("The read_file function has moved to pydicom.dicomio. " "Please use 'from pydicom import dicomio; dicomio.read_file(...)'") warnings.warn(msg, DeprecationWarning) return read_file(*args, **kwargs)
def getTagObject(self, index): """Get the object storing tag information from Dicom file at the given index.""" if index not in self.tagcache: dcm = dicomio.read_file(self.filenames[index], stop_before_pixels=True) self.tagcache[index] = dcm return self.tagcache[index]
def load_dicom_file(filename, queue): """Load the Dicom file `filename` and put an abbreviated tag->value map onto `queue`.""" try: dcm = dicomio.read_file(filename, stop_before_pixels=True) tags = {t: dcm.get(t) for t in LOAD_TAGS if t in dcm} queue.put((filename, tags)) except errors.InvalidDicomError: pass
def extractSeriesDetails(inputImageFile): """Reads and extracts Patient's Basic Info from a DICOM file. """ seriesList = [] dicomfile = inputImageFile tracker = set() for i, dfile in enumerate(dicomfile): seriesDetails = {} ds = dicomio.read_file(dfile) trackerID = str(ds.SeriesInstanceUID) if trackerID in tracker: '' else: seriesDetails["SeriesID"]=ds.SeriesInstanceUID seriesDetails["SeriesDescription"]=ds.SeriesDescription if ds[0x00080060]: seriesDetails["Modality"]=ds.Modality else: seriesDetails["Modality"]='' if ds[0x00200010]: seriesDetails["StudyID"]=ds.StudyID else: seriesDetails["StudyID"]='' # if ds[0x00181030]: # seriesDetails["ProtocolName"]=ds.ProtocolName # else: # seriesDetails["ProtocolName"]='' # if ds[0x00540500]: # seriesDetails["SliceProgressionDirection"]=ds.SliceProgressionDirection # else: # seriesDetails["SliceProgressionDirection"]='' # if ds[0x00280010]: # seriesDetails["Rows"]=ds.Rows # else: # seriesDetails["Rows"]='' # if ds[0x00280011]: # seriesDetails["Columns"]=ds.Columns # else: # seriesDetails["Columns"]='' seriesDetails["PatientID"]=ds.PatientID tracker.add(str(ds.SeriesInstanceUID)) seriesList.append(seriesDetails) return seriesList
def loadDicomFiles(filenames, queue): """Load the Dicom files `filenames' and put an abbreviated tag->value map for each onto `queue'.""" for filename in filenames: try: dcm = dicomio.read_file(filename, stop_before_pixels=True) tags = {t: dcm.get(t) for t in loadTags if t in dcm} queue.put((filename, tags)) except errors.InvalidDicomError: pass
def testEqualityFileMeta(self): """Dataset: equality returns correct value if with metadata""" d = read_file(self.test_file) e = read_file(self.test_file) self.assertTrue(d == e) e.is_implicit_VR = not e.is_implicit_VR self.assertFalse(d == e) e.is_implicit_VR = not e.is_implicit_VR self.assertTrue(d == e) e.is_little_endian = not e.is_little_endian self.assertFalse(d == e) e.is_little_endian = not e.is_little_endian self.assertTrue(d == e) e.filename = 'test_filename.dcm' self.assertFalse(d == e)
def testEqualityFileMeta(self): """Dataset: equality returns correct value if with metadata""" d = read_file(self.test_file) e = read_file(self.test_file) self.assertTrue(d == e) e.is_implicit_VR = not e.is_implicit_VR self.assertFalse(d == e) e.is_implicit_VR = not e.is_implicit_VR self.assertTrue(d == e) e.is_little_endian = not e.is_little_endian self.assertFalse(d == e) e.is_little_endian = not e.is_little_endian self.assertTrue(d == e) e.filename = "test_filename.dcm" self.assertFalse(d == e)
def testLatin1(self): """charset: can read and decode latin_1 file........................""" ds = dicomio.read_file(latin1_file) ds.decode() # Make sure don't get unicode encode error on converting to string expected = u'Buc^J\xe9r\xf4me' got = ds.PatientName self.assertEqual(expected, got, "Expected %r, got %r" % (expected, got))
def test_get_item(self): """Test Dataset.get_item""" ds = Dataset() ds.CommandGroupLength = 120 # 0000,0000 ds.SOPInstanceUID = '1.2.3.4' # 0008,0018 # Test non-deferred read assert ds.get_item(0x00000000) == ds[0x00000000] assert ds.get_item(0x00000000).value == 120 assert ds.get_item(0x00080018) == ds[0x00080018] assert ds.get_item(0x00080018).value == '1.2.3.4' # Test deferred read test_file = get_testdata_files('MR_small.dcm')[0] ds = read_file(test_file, force=True, defer_size='0.8 kB') ds_ref = read_file(test_file, force=True) # get_item will follow the deferred read branch assert ds.get_item((0x7fe00010)).value == ds_ref.PixelData
def testRead(self): """Unicode: Can read a file with unicode characters in name...""" uni_name = u'test°' # verify first that we could encode file name in this environment try: _ = uni_name.encode(sys.getfilesystemencoding()) except UnicodeEncodeError: print("SKIP: Environment doesn't support unicode filenames") return try: dicomio.read_file(uni_name) except UnicodeEncodeError: self.fail("UnicodeEncodeError generated for unicode name") # ignore file doesn't exist error except IOError: pass
def testEncodingWithSpecificTags(self): """Encoding is correctly applied even if Specific Character Set is not in specific tags...""" ds = dicomio.read_file(jp_file, specific_tags=['PatientName']) ds.decode() self.assertEqual(1, len(ds)) expected = ('Yamada^Tarou=' '\033$B;3ED\033(B^\033$BB@O:\033(B=' '\033$B$d$^$@\033(B^\033$B$?$m$&\033(B') self.assertEqual(expected, ds.PatientName)
def testNestedCharacterSets(self): """charset: can read and decode SQ with different encodings.........""" ds = dicomio.read_file(sq_encoding_file) ds.decode() # These datasets inside of the SQ cannot be decoded with default_encoding # OR UTF-8 (the parent dataset's encoding). Instead, we make sure that it # is decoded using the (0008,0005) tag of the dataset expected = u'\uff94\uff8f\uff80\uff9e^\uff80\uff9b\uff73=\u5c71\u7530^\u592a\u90ce=\u3084\u307e\u3060^\u305f\u308d\u3046' got = ds[0x32, 0x1064][0].PatientName self.assertEqual(expected, got, "Expected %r, got %r" % (expected, got))
def test_set_convert_private_elem_from_raw(self): """Test Dataset.__setitem__ with a raw private element""" test_file = get_testdata_files('CT_small.dcm')[0] ds = read_file(test_file, force=True) # 'tag VR length value value_tell is_implicit_VR is_little_endian' elem = RawDataElement((0x0043, 0x1029), 'OB', 2, b'\x00\x01', 0, True, True) ds.__setitem__((0x0043, 0x1029), elem) assert ds[(0x0043, 0x1029)].value == b'\x00\x01' assert type(ds[(0x0043, 0x1029)]) == DataElement
def __init__(self, dataset, memmap_pixel_array=False): """Initialize DicomParser from a pydicom Dataset or DICOM file. Parameters ---------- dataset : pydicom Dataset or filename pydicom dataset object or DICOM file location memmap_pixel_array : bool, optional Enable pixel array access via memory mapping, by default False Raises ------ AttributeError Raised if SOPClassUID is not present in the pydicom Dataset AttributeError Raised if the DICOM file or pydicom Dataset cannot be read """ self.memmap_pixel_array = memmap_pixel_array if isinstance(dataset, Dataset): self.ds = dataset elif isinstance(dataset, (string_types, BytesIO)): try: with open(dataset, "rb") as fp: self.ds = read_file(fp, defer_size=100, force=True, stop_before_pixels=memmap_pixel_array) if memmap_pixel_array: self.offset = fp.tell() + 8 except Exception: # Raise the error for the calling method to handle raise else: # Sometimes DICOM files may not have headers, # but they should always have a SOPClassUID # to declare what type of file it is. # If the file doesn't have a SOPClassUID, # then it probably isn't DICOM. if "SOPClassUID" not in self.ds: raise AttributeError else: raise AttributeError # Remove the PixelData attribute if it is not set. # i.e. RTStruct does not contain PixelData and its presence can confuse # the parser if "PixelData" in self.ds and self.ds.PixelData is None: delattr(self.ds, 'PixelData') if memmap_pixel_array: self.filename = dataset self.pixel_array = self.get_pixel_array else: if "PixelData" in self.ds: self.pixel_array = self.ds.pixel_array
def getPixelData(self, index): """Get the pixel data array for file at position `index` in self.filenames, or None if no pixel data.""" if index not in self.imgcache: try: dcm = dicomio.read_file(self.filenames[index]) rslope = float(dcm.get("RescaleSlope", 1) or 1) rinter = float(dcm.get("RescaleIntercept", 0) or 0) img = dcm.pixel_array * rslope + rinter except: img = None # exceptions indicate that the pixel data doesn't exist or isn't readable so ignore self.imgcache[index] = img return self.imgcache[index]
def getPixelData(self, index): '''Get the pixel data Numpy array for file at position `index` in self.filenames, or None if there is no pixel data.''' if index not in self.imgcache: img = None try: dcm = dicomio.read_file(self.filenames[index]) rslope = float(dcm.get('RescaleSlope', 1) or 1) rinter = float(dcm.get('RescaleIntercept', 0) or 0) img = dcm.pixel_array * rslope + rinter except Exception: pass # exceptions indicate that the pixel data doesn't exist or isn't readable so ignore self.imgcache[index] = img return self.imgcache[index]
def loadDicomZip(filename, statusfunc=lambda s, c, n: None): """ Load Dicom images from given zip file `filename'. This uses the status callback `statusfunc' like loadDicomDir(). Loaded files will have their pixel data thus avoiding the need to reload the zip file when an image is viewed but is at the expense of load time and memory. Return value is a sequence of DicomSeries objects in no particular order. """ series = {} count = 0 with zipfile.ZipFile(filename) as z: names = z.namelist() numfiles = len(names) for n in names: nfilename = "%s?%s" % (filename, n) s = BytesIO(z.read(n)) try: dcm = dicomio.read_file(s) except: pass # ignore files which aren't Dicom files, various exceptions raised so no concise way to do this else: seriesid = dcm.get("SeriesInstanceUID", "???") if seriesid not in series: series[seriesid] = DicomSeries(seriesid, nfilename) # need to load image data now since we don't want to reload the zip file later when an image is viewed try: # attempt to create the image matrix, store None if this doesn't work rslope = float(dcm.get("RescaleSlope", 1) or 1) rinter = float(dcm.get("RescaleIntercept", 0) or 0) img = dcm.pixel_array * rslope + rinter except: img = None s = series[seriesid] s.addFile(nfilename, dcm) s.tagcache[len(s.filenames) - 1] = dcm s.imgcache[len(s.filenames) - 1] = img count += 1 # update status only 100 times, doing it too frequently really slows things down if numfiles < 100 or count % (numfiles // 100) == 0: statusfunc("Loading DICOM files", count, numfiles) statusfunc("", 0, 0) return list(series.values())
def _load_dicom_files(filenames: str, queue): """Для DICOM-файлов из списка filenames загружаем минимальный набор тегов и помещаем в очередь.""" for filename in filenames: try: dcm = dicomio.read_file(filename, specific_tags=REQUIRED_TAGS) tags = { t: dcm.get(t) if t in dcm else DEFAULT_TAG_VAL for t in REQUIRED_TAGS } queue.put((filename, tags)) except errors.InvalidDicomError: pass except AttributeError: pass except: pass
def getPixelData(self, index): '''Get the pixel data Numpy array for file at position `index` in self.filenames, or None if there is no pixel data.''' if index not in self.imgcache: img = None try: dcm = dicomio.read_file(self.filenames[index]) if dcm.pixel_array is not None: rslope = float(dcm.get('RescaleSlope', 1)) rinter = float(dcm.get('RescaleIntercept', 0)) img = dcm.pixel_array * rslope + rinter except Exception: pass self.imgcache[index] = img return self.imgcache[index]
def anonymize_folder(folder, new_patient_name="Anonymous", verbose=True): """ Anonymizes all dicom files inside a given folder. By default, the patient name attribute is replaced by "Anonymous" but an alternative name can be provided as an argument to the function. NOTE: Assumes all files in the folder belong to the same patient. Currently, the following DICOM fields are anonymised: RTPlanTime, ReviewTime, StudyTime, RTPlanDate, ReviewDate, StudyDate, PatientBirthDate, PatientName, PatientID, StudyID, ReviewerName. """ files = match_dicom(folder) times = ["RTPlanTime", "ReviewTime", "StudyTime"] dates = ["RTPlanDate", "ReviewDate", "StudyDate", "PatientBirthDate"] # Not guaranteed to be unique, but they're not UIDs so it shouldn't matter. new_patientID = "ANON" + str(random.randint(0, 1000000)) new_studyID = "ANON" + str(random.randint(0, 1000000)) for dicomfile in files: try: df = dicom.read_file(dicomfile) if verbose: print "Anonymizing %s" % dicomfile if "PatientName" in df: df.PatientName = new_patient_name if "PatientID" in df: df.PatientID = new_patientID if "StudyID" in df: df.StudyID = new_studyID if "ReviewerName" in df: df.ReviewerName = "ANON" for date in dates: if date in df: setattr(df, date, "19000101") for time in times: if time in df: setattr(df, time, "111111") df.save_as(dicomfile) except dicom.filereader.InvalidDicomError: pass
def _imread_dcm(filename): """Open DICOM image with pydicom and return a NumPy array""" try: # pydicom 1.0 from pydicom import dicomio except ImportError: # pydicom 0.9 import dicom as dicomio dcm = dicomio.read_file(filename, force=True) # ********************************************************************** # The following is necessary until pydicom numpy support is improved: # (after that, a simple: 'arr = dcm.PixelArray' will work the same) format_str = "%sint%s" % ( ("u", "")[dcm.PixelRepresentation], dcm.BitsAllocated) try: dtype = np.dtype(format_str) except TypeError: raise TypeError("Data type not understood by NumPy: " "PixelRepresentation=%d, BitsAllocated=%d" % (dcm.PixelRepresentation, dcm.BitsAllocated)) arr = np.fromstring(dcm.PixelData, dtype) try: # pydicom 0.9.3: dcm_is_little_endian = dcm.isLittleEndian except AttributeError: # pydicom 0.9.4: dcm_is_little_endian = dcm.is_little_endian if dcm_is_little_endian != (sys.byteorder == "little"): arr.byteswap(True) if hasattr(dcm, "NumberofFrames") and dcm.NumberofFrames > 1: if dcm.SamplesperPixel > 1: arr = arr.reshape(dcm.SamplesperPixel, dcm.NumberofFrames, dcm.Rows, dcm.Columns) else: arr = arr.reshape(dcm.NumberofFrames, dcm.Rows, dcm.Columns) else: if dcm.SamplesperPixel > 1: if dcm.BitsAllocated == 8: arr = arr.reshape(dcm.SamplesperPixel, dcm.Rows, dcm.Columns) else: raise NotImplementedError( "This code only handles " "SamplesPerPixel > 1 if Bits Allocated = 8") else: arr = arr.reshape(dcm.Rows, dcm.Columns) # ********************************************************************** return arr
def get_tag(dicomPath1, dicomPath2): dcm = pydicom.dcmread(dicomPath1) # 选择一个普通的非压缩dcm文件作为转换模板 image = sitk.ReadImage(dicomPath2) image_array = sitk.GetArrayFromImage(image) np_array = np.int16(image_array) image_array = np.squeeze(np_array) # 读取有压缩分段的dcm图像数据 dataset = pydicom.dcmread(dicomPath2) # 用来修改Tag,图像读写相关的tag都要改 dcm.data_element('PixelSpacing').value = dataset.data_element( 'PixelSpacing').value dcm.data_element('RescaleIntercept').value = dataset.data_element( 'RescaleIntercept').value dcm.data_element('RescaleSlope').value = dataset.data_element( 'RescaleSlope').value dcm.PixelData = image_array.tobytes() dcm.save_as(dicomPath2) dcm = dicomio.read_file(dicomPath2) return dcm.StudyDescription
def _imread_dcm(filename): """Open DICOM image with pydicom and return a NumPy array""" try: # pydicom 1.0 from pydicom import dicomio except ImportError: # pydicom 0.9 import dicom as dicomio dcm = dicomio.read_file(filename, force=True) # ********************************************************************** # The following is necessary until pydicom numpy support is improved: # (after that, a simple: 'arr = dcm.PixelArray' will work the same) format_str = '%sint%s' % (('u', '')[dcm.PixelRepresentation], dcm.BitsAllocated) try: dtype = np.dtype(format_str) except TypeError: raise TypeError("Data type not understood by NumPy: " "PixelRepresentation=%d, BitsAllocated=%d" % ( dcm.PixelRepresentation, dcm.BitsAllocated)) arr = np.fromstring(dcm.PixelData, dtype) try: # pydicom 0.9.3: dcm_is_little_endian = dcm.isLittleEndian except AttributeError: # pydicom 0.9.4: dcm_is_little_endian = dcm.is_little_endian if dcm_is_little_endian != (sys.byteorder == 'little'): arr.byteswap(True) if hasattr(dcm, 'NumberofFrames') and dcm.NumberofFrames > 1: if dcm.SamplesperPixel > 1: arr = arr.reshape(dcm.SamplesperPixel, dcm.NumberofFrames, dcm.Rows, dcm.Columns) else: arr = arr.reshape(dcm.NumberofFrames, dcm.Rows, dcm.Columns) else: if dcm.SamplesperPixel > 1: if dcm.BitsAllocated == 8: arr = arr.reshape(dcm.SamplesperPixel, dcm.Rows, dcm.Columns) else: raise NotImplementedError("This code only handles " "SamplesPerPixel > 1 if Bits Allocated = 8") else: arr = arr.reshape(dcm.Rows, dcm.Columns) # ********************************************************************** return arr
def build_dcm_dict(dcmpath, fn_dict, image_dict_pkl="image_dict.pkl"): slice_location = [] trigger_time = [] image_dict = {} hash_value = hashlib.sha1(dcmpath).hexdigest() #count = 0 for dirname, subdirlist, filelist in os.walk(dcmpath): for filen in filelist: filePath = os.path.join(dirname,filen) #print(filePath) #print(dirname, subdirlist, filelist) #print(filePath) #print(f.SliceLocation) try: f = dicomio.read_file(filePath, stop_before_pixels=True) except Exception as e: print(str(e)) print("error: {0}".format(filen)) continue #dictionary of images if (f.TriggerTime not in image_dict.keys()): image_dict[f.TriggerTime] = {} if (f.SliceLocation not in image_dict[f.TriggerTime].keys()): image_dict[f.TriggerTime][f.SliceLocation] = {} for fn_key in fn_dict.keys(): if( fn_key not in image_dict[f.TriggerTime][f.SliceLocation].keys()): image_dict[f.TriggerTime][f.SliceLocation][fn_key] = {} #print(fn_key, filen, fn_dict[fn_key]) if (fnmatch.fnmatch(filen, fn_dict[fn_key])): #print('did i get here') if (f.SOPInstanceUID not in image_dict[f.TriggerTime][f.SliceLocation][fn_key].keys()): image_dict[f.TriggerTime][f.SliceLocation][fn_key][f.SOPInstanceUID] = [filePath] #print(image_dict[fn_key]) if (f.TriggerTime not in trigger_time): trigger_time.append(f.TriggerTime) if (f.SliceLocation not in slice_location): slice_location.append(f.SliceLocation) print("writing {0} to current working directory".format(image_dict_pkl)) with open(os.path.join(os.getcwd(), image_dict_pkl), "wb") as pkl_f: pickle.dump(hash_value, pkl_f, -1) pickle.dump(image_dict, pkl_f, -1) return image_dict
def convert_dcm_to_csv(id_label_map, input_filename, output_filename): print("Start to convert dcm: {} to csv: {}".format(input_filename, output_filename)) ds = dicomio.read_file(input_filename) image_ndarray = ds.pixel_array label = id_label_map[ds.PatientID] csv_content = "{},".format(label) # Example: 512 * 512 for i in image_ndarray: for j in i: csv_content += "{},".format(j) csv_content = csv_content[:-1] + "\n" with open(output_filename, "w") as f: f.write(csv_content) print("Successfully convert dcm: {} to csv: {}".format( input_filename, output_filename))
def convert_dcm_to_csv(id_label_map, input_filename, output_filename): print("Start to convert dcm: {} to csv: {}".format(input_filename, output_filename)) ds = dicomio.read_file(input_filename) image_ndarray = ds.pixel_array label = id_label_map[ds.PatientID] csv_content = "{},".format(label) # Example: 512 * 512 for i in image_ndarray: for j in i: csv_content += "{},".format(j) csv_content = csv_content[:-1] + "\n" with open(output_filename, "w") as f: f.write(csv_content) print("Successfully convert dcm: {} to csv: {}".format(input_filename, output_filename))
def __init__(self, dataset): if isinstance(dataset, Dataset): self.ds = dataset elif isinstance(dataset, (string_types, BytesIO)): try: self.ds = \ read_file(dataset, defer_size=100, force=True) except: # Raise the error for the calling method to handle raise else: # Sometimes DICOM files may not have headers, # but they should always have a SOPClassUID # to declare what type of file it is. # If the file doesn't have a SOPClassUID, # then it probably isn't DICOM. if not "SOPClassUID" in self.ds: raise AttributeError else: raise AttributeError
def __init__(self, dataset): if isinstance(dataset, Dataset): self.ds = dataset elif isinstance(dataset, string_types): try: self.ds = \ read_file(dataset, defer_size=100, force=True) except: # Raise the error for the calling method to handle raise else: # Sometimes DICOM files may not have headers, # but they should always have a SOPClassUID # to declare what type of file it is. # If the file doesn't have a SOPClassUID, # then it probably isn't DICOM. if not "SOPClassUID" in self.ds: raise AttributeError else: raise AttributeError
def loadDicomZip(filename, statusfunc=lambda s, c, n: None): series = {} count = 0 with zipfile.ZipFile(filename) as z: names = z.namelist() numfiles = len(names) for n in names: nfilename = '%s?%s' % (filename, n) s = StringIO(z.read(n)) try: dcm = dicomio.read_file(s) except: pass # ignore files which aren't Dicom files else: seriesid = dcm.get('SeriesInstanceUID', '???') if seriesid not in series: series[seriesid] = DicomSeries(seriesid, nfilename) try: # attempt to create the image matrix, store None if this doesn't work rslope = float(dcm.get('RescaleSlope', 1) or 1) rinter = float(dcm.get('RescaleIntercept', 0) or 0) img = dcm.pixel_array * rslope + rinter except: img = None s = series[seriesid] s.addFile(nfilename, dcm) s.tagcache[len(s.filenames) - 1] = dcm s.imgcache[len(s.filenames) - 1] = img count += 1 # update status only 100 times, doing it too frequently really slows things down if numfiles < 100 or count % (numfiles // 100) == 0: statusfunc('Loading DICOM files', count, numfiles) statusfunc('', 0, 0) return list(series.values())
def read_file(*args, **kwargs): global read_file from pydicom.dicomio import read_file return read_file(*args, **kwargs)
def create_image_volume(image_dict, mri_2_cfd_map, image_type, return_coord=True): trigger_t = mri_2_cfd_map[0] slice_location = image_dict[trigger_t].keys() dcm_files = [] for loc in slice_location: for image_id in image_dict[trigger_t][loc][image_type].keys(): dcm_files.append(image_dict[trigger_t][loc][image_type][image_id][0]) path_loc = zip(dcm_files, slice_location) path_loc.sort(key=lambda x: x[1]) dcm_files, slice_location = zip(*path_loc) #print(slice_location) # get reference image #print(len(dcm_files), dcm_files) ref_image = dicomio.read_file(dcm_files[0]) # load dimensions based on the number of rows columns and slices const_pixel_dims = (int(ref_image.Rows), int(ref_image.Columns), len(dcm_files)) #check it whether image has been interpolated if (hasattr(ref_image, 'SpacingBetweenSlices')): if(ref_image.SpacingBetweenSlices < ref_image.SliceThickness): z_spacing = float(ref_image.SpacingBetweenSlices) else: z_spacing = float(ref_image.SliceThickness) else: z_spacing = float(ref_image.SliceThickness) # the array is sized based on 'const_pixel_dims array_dicom = np.zeros(const_pixel_dims, dtype=np.float64) #ref_image.pixel_array.dtype) print(array_dicom.shape) #loop through all the DICOM FILES for filenamedcm in dcm_files: #read the file ds = dicomio.read_file(filenamedcm) #store the raw image data array_dicom[:, :, dcm_files.index(filenamedcm)] = ( np.asarray(ds.pixel_array, dtype=np.float64) * ( np.float64(ds.RescaleSlope)) + np.float64(ds.RescaleIntercept)) #testindx = np.where(array_dicom !=0) #minx = np.min(testindx[0]) #miny = np.min(testindx[1]) #minz = np.min(testindx[2]) #maxx = np.max(testindx[0]) #maxy = np.max(testindx[1]) #maxz = np.max(testindx[2]) if (return_coord == True): # load spacing values in mm const_pixel_spacing = (float(ref_image.PixelSpacing[0]), float(ref_image.PixelSpacing[1]), z_spacing) x = np.arange(const_pixel_spacing[0]/2.0, (const_pixel_dims[0]+1)*const_pixel_spacing[0]-1.0, const_pixel_spacing[0]) y = np.arange(const_pixel_spacing[1]/2.0, (const_pixel_dims[1]+1)*const_pixel_spacing[1]-1.0, const_pixel_spacing[1]) z = np.arange(const_pixel_spacing[2]/2.0, (const_pixel_dims[2]+1)*const_pixel_spacing[2]-1.0, const_pixel_spacing[2]) return array_dicom, x,y,z else: return array_dicom
dicom_test = np.testing.dec.skipif(not have_dicom, "could not import pydicom") from .. import dicomwrappers as didw from .. import dicomreaders as didr from ...volumeutils import endian_codes from unittest import TestCase from nose.tools import assert_true, assert_false, assert_equal, assert_not_equal, assert_raises from numpy.testing import assert_array_equal, assert_array_almost_equal IO_DATA_PATH = pjoin(dirname(__file__), "data") DATA_FILE = pjoin(IO_DATA_PATH, "siemens_dwi_1000.dcm.gz") DATA_FILE_PHILIPS = pjoin(IO_DATA_PATH, "philips_mprage.dcm.gz") if have_dicom: DATA = read_file(gzip.open(DATA_FILE)) DATA_PHILIPS = read_file(gzip.open(DATA_FILE_PHILIPS)) else: DATA = None DATA_PHILIPS = None DATA_FILE_B0 = pjoin(IO_DATA_PATH, "siemens_dwi_0.dcm.gz") DATA_FILE_SLC_NORM = pjoin(IO_DATA_PATH, "csa_slice_norm.dcm") DATA_FILE_DEC_RSCL = pjoin(IO_DATA_PATH, "decimal_rescale.dcm") DATA_FILE_4D = pjoin(IO_DATA_PATH, "4d_multiframe_test.dcm") # This affine from our converted image was shown to match our image spatially # with an image from SPM DICOM conversion. We checked the matching with SPM # check reg. We have flipped the first and second rows to allow for rows, cols # transpose in current return compared to original case. EXPECTED_AFFINE = np.array( # do this for philips? [
def de_sensitive(path, write_to): dc = dicomio.read_file(path, force=True) for tag in info_deleted: if tag in dc: del dc[dc.data_element(tag).tag] dicomio.write_file(write_to, dc)
from .. import dicomwrappers as didw from .. import dicomreaders as didr from ...volumeutils import endian_codes from unittest import TestCase from nose.tools import (assert_true, assert_false, assert_equal, assert_not_equal, assert_raises) from numpy.testing import assert_array_equal, assert_array_almost_equal IO_DATA_PATH = pjoin(dirname(__file__), 'data') DATA_FILE = pjoin(IO_DATA_PATH, 'siemens_dwi_1000.dcm.gz') DATA_FILE_PHILIPS = pjoin(IO_DATA_PATH, 'philips_mprage.dcm.gz') if have_dicom: DATA = read_file(gzip.open(DATA_FILE)) DATA_PHILIPS = read_file(gzip.open(DATA_FILE_PHILIPS)) else: DATA = None DATA_PHILIPS = None DATA_FILE_B0 = pjoin(IO_DATA_PATH, 'siemens_dwi_0.dcm.gz') DATA_FILE_SLC_NORM = pjoin(IO_DATA_PATH, 'csa_slice_norm.dcm') DATA_FILE_DEC_RSCL = pjoin(IO_DATA_PATH, 'decimal_rescale.dcm') DATA_FILE_4D = pjoin(IO_DATA_PATH, '4d_multiframe_test.dcm') # This affine from our converted image was shown to match our image spatially # with an image from SPM DICOM conversion. We checked the matching with SPM # check reg. We have flipped the first and second rows to allow for rows, cols # transpose in current return compared to original case. EXPECTED_AFFINE = np.array( # do this for philips? [[-1.796875, 0, 0, 115], [0, -1.79684984, -0.01570896, 135.028779],
def transform2(iminfo1): cos = iminfo1.ImageOrientationPatient cosines = [np.float64(val) for val in cos] ipp = iminfo1.ImagePositionPatient normal = [0., 0., 0.] normal[0] = cosines[1]*cosines[5] - cosines[2]*cosines[4] normal[1] = cosines[2]*cosines[3] - cosines[0]*cosines[5] normal[2] = cosines[0]*cosines[4] - cosines[1]*cosines[3] #print(normal) dist = 0.0 for i in range(3): dist += normal[i]*np.float64(ipp[i]) #print(dist) return dist if __name__ == '__main__': dcm_path = "/home/ksansom/caseFiles/mri/images/0.4/102" #dcm_path = "/Users/sansomk/caseFiles/mri/E431791260_merge/0.4/102" ds1 = dicomio.read_file(os.path.join(dcm_path, 'E431791260S201I001.dcm')) ds2 = dicomio.read_file(os.path.join(dcm_path, 'E431791260S201I002.dcm')) M, Rot = getTransformMatrix(ds1, ds2) print(M) print(Rot) dist1 = transform2(ds1) dist2 = transform2(ds2) print(dist2-dist1)
def testExplicitISO2022_IR6(self): """charset: can decode file with multi-valued data elements.........""" ds = dicomio.read_file(explicit_ir6_file) ds.decode()
from pydicom import dicomio directory = "/media/carlos/CE2CDDEF2CDDD317/concursos/cancer/stage 1 samples/" patient = "0a0c32c9e08cc2ea76a71649de56be6d" ds = dicomio.read_file(directory + patient + "/0a67f9edb4915467ac16a565955898d3.dcm") # plan dataset print "name:", ds.PatientName print "dir setup:", ds.dir( "setup") # get a list of tags with "setup" somewhere in the name print ds #print ds.PatientSetupSequence[0] #ds.PatientSetupSequence[0].PatientPosition = "HFP" #ds.save_as("rtplan2.dcm")
('?' lines from difflib removed - no use here) """ #import sys from pydicom import dicomio import difflib # only used as a script #if len(sys.argv) != 3: # print(usage) # sys.exit() file1 = "/Users/sansomk/caseFiles/mri/E431791260_FlowVol_01/flow/FlowX_001.dcm" file2 = "/Users/sansomk/caseFiles/mri/E431791260_FlowVol_01/flow/FlowZ_001.dcm" datasets = (dicomio.read_file(file1, force=True), dicomio.read_file(file2, force=True)) # diflib compare functions require a list of lines, each terminated with newline character # massage the string representation of each dicom dataset into this form: rep = [] for dataset in datasets: lines = str(dataset).split("\n") lines = [line + "\n" for line in lines] # add the newline to end rep.append(lines) diff = difflib.Differ() for line in diff.compare(rep[0], rep[1]): if line[0] != "?": print(line)
def testStandardFile(self): """charset: can read and decode standard file without special char..""" ds = dicomio.read_file(normal_file) ds.decode()
def testMultiPN(self): """charset: can decode file with multi-valued data elements.........""" ds = dicomio.read_file(multiPN_file) ds.decode()
################################################################################ if __name__ == '__main__': #dcm_path = "/home/sansomk/caseFiles/mri/images/E431791260_Merge/0.4/102" #dcm_path = "/home/sansomk/caseFiles/mri/images/E431791260_FlowVol_01/mag" #dcm_path = "/home/ksansom/caseFiles/mri/images/0.4/102/" dcm_path = "/Users/sansomk/caseFiles/mri/E431791260_merge/0.4/102" dcm_files = [] slice_location = [] acq_N = [] trig_count = 0 for dirname, subdirlist, filelist in os.walk(dcm_path): for filen in filelist: filePath = os.path.join(dirname, filen) try: #print(filePath) f = dicomio.read_file(filePath, stop_before_pixels=True) except Exception as e: print(str(e)) print("error: {0}".format(filen)) if (hasattr(f, "TriggerTime")): if (f.TriggerTime < 1.0 and filePath not in dcm_files): dcm_files.append(filePath) slice_location.append(f.SliceLocation) acq_N.append(f.AcquisitionNumber) else: trig_count += 1 dcm_files.append(filePath) slice_location.append(f.SliceLocation) acq_N.append(f.AcquisitionNumber) if (trig_count > 0):