matplotlib

Source code for utils.dcm_qt_tree

# dcm_qt_tree.py
"""View DICOM files in a tree using Qt and PySide"""
# Copyright (c) 2013 Padraig Looney
# This file is released under the pydicom (https://github.com/darcymason/pydicom)
# license, see the file license.txt available at
# (https://github.com/darcymason/pydicom)

import dicom
import sys

try:
    from PySide import QtGui
except ImportError:
    #print('Pyside not getting imported')
    pass

import collections


[docs]class DicomTree(object): def __init__(self, filename, model): """ Constructor for Dicom Tree """ self.filename = filename self.model = model self.title = "" self.patient_info = [] self.plan_info = [] self.pixel_array = None self.patient_dict = {"Patient's Name":"Name", "Patient ID":"ID", "Patient's Birth Date":"Birth Date", "Patient's Sex":"Sex"}
[docs] def get_patient_table(self): """ Creating patient information table """ tr = "" for key, value in self.patient_info: tr += ("<tr><th align='left'>"+key+":&nbsp;&nbsp;&nbsp;&nbsp;</th><td align='left'>"+value+"</td></tr>") table = "<table style='width:100%;' cellspacing='2' cellpadding='2'>"+tr+"</table>" return table
[docs] def get_plan_table(self): """ Creating plan information table """ tr = "" for key, value in self.plan_info: tr += ("<tr><th align='left'>"+key+":&nbsp;&nbsp;&nbsp;&nbsp;</th><td align='left'>"+str(value)+"</td></tr>") table = "<table style='width:100%;' cellspacing='2' cellpadding='2'>"+tr+"</table>" return table
[docs] def show_tree(self): """ Retrive all dicom data and assign it to tree model structure """ ds = self.dicom_to_dataset(self.filename) try: self.pixel_array = ds.pixel_array except: pass ds = self.anonymize(ds) dic = self.dataset_to_dic(ds) self.dic_to_model(dic) return self.model
#self.display(model)
[docs] def anonymize(self, dataset, new_person_name="anonymous", new_patient_id="id", remove_curves=True, remove_private_tags=True): """Replace data element values to partly anonymize a DICOM file. Note: completely anonymizing a DICOM file is very complicated; there are many things this example code does not address. USE AT YOUR OWN RISK. """ # Define call-back functions for the dataset.walk() function def PN_callback(ds, data_element): """Called from the dataset "walk" recursive function for all data elements.""" if data_element.VR == "PN": data_element.value = new_person_name def curves_callback(ds, data_element): """Called from the dataset "walk" recursive function for all data elements.""" if data_element.tag.group & 0xFF00 == 0x5000: del ds[data_element.tag] # Remove patient name and any other person names dataset.walk(PN_callback) # Change ID dataset.PatientID = new_patient_id # Remove data elements (should only do so if DICOM type 3 optional) # Use general loop so easy to add more later # Could also have done: del ds.OtherPatientIDs, etc. for name in ['OtherPatientIDs', 'OtherPatientIDsSequence']: if name in dataset: delattr(dataset, name) # Same as above but for blanking data elements that are type 2. for name in ['PatientBirthDate']: if name in dataset: dataset.data_element(name).value = '' # Remove private tags if function argument says to do so. Same for curves if remove_private_tags: dataset.remove_private_tags() if remove_curves: dataset.walk(curves_callback) return dataset
[docs] def array_to_model(self, array): """ Manipulation of dicom tree data """ model = QtGui.QStandardItemModel() parentItem = model.invisibleRootItem() for ntuple in array: tag = ntuple[0] value = ntuple[1] if isinstance(value, dict): self.recurse_dic_to_item(value, parentItem) else: item = QtGui.QStandardItem(tag + str(value)) parentItem.appendRow(item) return parentItem
def dic_to_model(self, dic): #model = QtGui.QStandardItemModel() parentItem = self.model.invisibleRootItem() self.recurse_dic_to_item(dic, parentItem) return self.model def dataset_to_array(self, dataset): array = [] for data_element in dataset: array.append(self.data_element_to_dic(data_element)) return array
[docs] def recurse_dic_to_item(self, dic, parent, title=""): """ Appending data into tree structure. """ for k in dic: v = dic[k] if isinstance(v, dict): if k.endswith("Sequence"): title = k.replace(" Sequence", "") if k.startswith("item"): num = str(int(k.rsplit()[-1])+1) k = "{} {}".format(title, num) #item = QtGui.QStandardItem(k + ':' + str(v)) item = QtGui.QStandardItem(k) parent.appendRow(self.recurse_dic_to_item(v, item, title)) else: item1 = QtGui.QStandardItem(k) item2 = QtGui.QStandardItem(str(v)) #item = QtGui.QStandardItem(k + ': ' + str(v)) #parent.appendRow(item) parent.appendRow([item1, item2]) return parent
def dicom_to_dataset(self, filename): dataset = dicom.read_file(filename, force=True) return dataset def data_element_to_dic(self, data_element): dic = collections.OrderedDict() if data_element.VR == "SQ": items = collections.OrderedDict() dic[data_element.name] = items i = 0 for dataset_item in data_element: items['item ' + str(i)] = self.dataset_to_dic(dataset_item) i += 1 elif data_element.name != 'Pixel Data': if "SOP Class UID" in data_element.name and self.title != "": self.title = data_element.value if data_element.name in self.patient_dict.keys(): self.patient_info.append((self.patient_dict.get(data_element.name), data_element.value)) if "Plan Label" in data_element.name: self.plan_info.append(("Plan Name", data_element.value)) if "Delivery Maximum Dose" == data_element.name: self.plan_info.append(("Dose rate", data_element.value*100)) dic[data_element.name] = data_element.value return dic def dataset_to_dic(self, dataset): dic = collections.OrderedDict() for data_element in dataset: dic.update(self.data_element_to_dic(data_element)) return dic def display(self, model): app = QtGui.QApplication.instance() if not app: # create QApplication if it doesnt exist app = QtGui.QApplication(sys.argv) tree = QtGui.QTreeView() tree.setModel(model) tree.show() app.exec_() return tree
def main(): filename = sys.argv[1] dicomTree = DicomTree(filename) dicomTree.show_tree() if __name__ == "__main__": main()