diff --git a/src/SimNDT/gui/treeWidget.py b/src/SimNDT/gui/treeWidget.py new file mode 100644 index 0000000..db65548 --- /dev/null +++ b/src/SimNDT/gui/treeWidget.py @@ -0,0 +1,367 @@ +__author__ = 'Miguel Molero' + +from PySide.QtCore import * +from PySide.QtGui import * + +from SimNDT.gui.constants import * +import numpy as np + +from SimNDT.core.constants import * +from SimNDT.gui import HelperMethods + +from SimNDT.gui.Warnings import WarningParms + + +class MySignal(QObject): + sig = Signal() + + +class TreeWidget(QTreeWidget): + def __init__(self, parent=None): + + super(TreeWidget, self).__init__(parent) + + self.setGeometry(QRect(0, 0, 350, 840)) + self.setHeaderLabels(["", ""]) + self.setMaximumWidth(650) + self.setMinimumWidth(150) + # self.setRootIsDecorated(True) + self.setAlternatingRowColors(True) + self.setColumnCount(2) + self.header().resizeSection(0, 300) + + self.setContextMenuPolicy(Qt.CustomContextMenu) + self.customContextMenuRequested.connect(self.showContextMenu) + + self.doubleClicked.connect(self.onDoubleClick) + self.itemChanged.connect(self.onItemChanged) + + self.actionDeleteObject = HelperMethods.createAction(self, "Delete Selected Object", self.deleteObject, + icon="delete.png") + + self.deleteDone = MySignal() + + def onDoubleClick(self, index): + item = self.currentItem() + item._editing=1 + + # Change od editable tree items (attributes, Geom. Objects) + def onItemChanged(self, item, col): + if hasattr(item,'_editing') and item._editing==1: + item._editing=0 + label = item._userData[0] + value = item._userData[1] + obj = item._userData[2] + # alayws (re)select the item which was edited (TAB jumps to next row and we loose the _editing flag) + self.setCurrentItem(item) + + if label == '# Cycles': + if obj.N_Cycles is not None: + obj.N_Cycles = int(item.text(1)) + item._userData[1] = obj.N_Cycles + elif label == 'Angle': + obj.theta = float(item.text(1)) + item._userData[1] = obj.theta + elif label == 'Amplitude': + obj.Amplitude = float(item.text(1)) + item._userData[1] = obj.Amplitude + elif label == 'Border Offset': + obj.BorderOffset = float(item.text(1)) + item._userData[1] = obj.BorderOffset + elif label == 'Center X': + obj.x0 = float(item.text(1)) + item._userData[1] = obj.x0 + elif label == 'Center Y': + obj.y0 = float(item.text(1)) + item._userData[1] = obj.y0 + elif label == 'Center Offset': + obj.CenterOffset = float(item.text(1)) + item._userData[1] = obj.CenterOffset + elif label == 'Frequency (MHz)': + obj.Frequency = float(item.text(1))/1e-6 + item._userData[1] = obj.Frequency*1e-6 + elif label == 'Label': + obj.Label = int(item.text(1)) + item._userData[1] = obj.Label + elif label == 'Radius': + obj.r = float(item.text(1)) + item._userData[1] = obj.r + elif label == 'Semi-Major': + obj.a = float(item.text(1)) + item._userData[1] = obj.a + elif label == 'Semi-Minor': + obj.b = float(item.text(1)) + item._userData[1] = obj.b + elif label == 'Size': + obj.Size = float(item.text(1)) + item._userData[1] = obj.Size + elif label == 'Simulation Time': + obj.SimulationTime = float(item.text(1))/1e6 + item._userData[1] = obj.SimulationTime*1e6 + else: + msgbox=WarningParms("Parameter "+label+" cannot be modified") + msgbox.exec_() + + def deleteObject(self): + + print("delete", self.index) + print + self.SimNDT_ObjectList.pop(self.index) + self.SimNDT_Scenario.resetImage() + for obj in self.SimNDT_ObjectList: + self.SimNDT_Scenario.addObject(obj) + + if len(self.SimNDT_ObjectList) == 0: + self.SimNDT_ObjectList = None + + self.deleteDone.sig.emit() + + def showContextMenu(self, pos): + item = self.itemAt(pos) + menu = QMenu() + it = QTreeWidgetItem.UserType + 1 + + if item.type() == it: # Object Item + HelperMethods.addActions(menu, self.actionDeleteObject) + self.index = item.parent().indexOfChild(item) + + menu.exec_(self.mapToGlobal(pos)) + + def update(self, SimNDT_Scenario, + SimNDT_ObjectList, + SimNDT_Materials, + SimNDT_Boundaries, + SimNDT_Inspection, + SimNDT_Source, + SimNDT_Transducers, + SimNDT_Signal, + SimNDT_Simulation): + + self.clear() + # Scenario + + + if SimNDT_Scenario: + self.SimNDT_Scenario = SimNDT_Scenario + + scenario_tree = QTreeWidgetItem(self) + scenario_tree.setChildIndicatorPolicy(QTreeWidgetItem.DontShowIndicatorWhenChildless) + + scenario_tree.setText(0, "Scenario") + scenario_tree.setFont(0, QFont(FONT_NAME, FONT_SIZE_1, QFont.Bold)) + scenario_tree.setIcon(0, QIcon(":/newImage.png")) + + # Dimensions + dimensions_tree = QTreeWidgetItem(scenario_tree) + dimensions_tree.setText(0, "Dimensions") + dimensions_tree.setFont(0, QFont(FONT_NAME, FONT_SIZE_2, QFont.Normal)) + + scenario_labels = ("Width", "Height", "Pixel/mm", "Label", "Geometric Model Size") + modelSize = "%d x %d" % (SimNDT_Scenario.M, SimNDT_Scenario.N) + print + "SIZE Scenario", SimNDT_Scenario.I.shape + scenario_values = (SimNDT_Scenario.Width, SimNDT_Scenario.Height, + SimNDT_Scenario.Pixel_mm, SimNDT_Scenario.Label, modelSize) + self.populateTree(dimensions_tree, scenario_labels, scenario_values,None) + + labels_tree = QTreeWidgetItem(scenario_tree) + numLabels = np.size(np.unique(SimNDT_Scenario.I)) + labels_tree.setText(0, "Labels in Scenario") + labels_labels = ("Total Number", "Labels") + labels_values = (numLabels, str(np.unique(SimNDT_Scenario.I))) + labels_tree.setFont(0, QFont(FONT_NAME, FONT_SIZE_2, QFont.Normal)) + self.populateTree(labels_tree, labels_labels, labels_values,None) + + self.expandItem(scenario_tree) + + # Objects + if SimNDT_ObjectList: + + ItemType1 = QTreeWidgetItem.UserType + 1 + self.SimNDT_ObjectList = SimNDT_ObjectList + + objects_tree = QTreeWidgetItem(scenario_tree) + objects_tree.setText(0, "Objects") + objects_tree.setFont(0, QFont(FONT_NAME, FONT_SIZE_2, QFont.Normal)) + for item in SimNDT_ObjectList: + objects_parent = QTreeWidgetItem(objects_tree, ItemType1) + objects_parent.setText(0, item.Name) + if item.Name == "ellipse": + objects_labels = ("Center X", "Center Y", "Semi-Major", "Semi-Minor", "Angle", "Label") + objects_values = (item.x0, item.y0, item.a, item.b, item.theta, item.Label) + if item.Name == "circle": + objects_labels = ("Center X", "Center Y", "Radius", "Label") + objects_values = (item.x0, item.y0, item.r, item.Label) + if item.Name == 'rectangle': + objects_labels = ("Center X", "Center Y", "Width", "Height", "Label") + objects_values = (item.x0, item.y0, item.W, item.H, item.Label) + if item.Name == 'square': + objects_labels = ("Center X", "Center Y", "Side", "Label") + objects_values = (item.x0, item.y0, item.L, item.Label) + + self.populateTree(objects_parent, objects_labels, objects_values,item) + self.expandItem(objects_tree) + + # Materials + if SimNDT_Materials is not None: + material_tree = QTreeWidgetItem(self) + material_tree.setText(0, "Materials") + material_tree.setFont(0, QFont(FONT_NAME, FONT_SIZE_1, QFont.Bold)) + material_tree.setIcon(0, QIcon(":/material.png")) + + materials_label = (RHO, "VL", "VT", "H%s (GPa)" % LAMBDA, "H%s (GPa)" % MU, "Label") + + for item in SimNDT_Materials: + materials_parent = QTreeWidgetItem(material_tree) + materials_parent.setText(0, item.Name) + materials_parent.setFont(0, QFont(FONT_NAME, FONT_SIZE_2, QFont.Normal)) + + materials_values = ("%0.2f" % (item.Rho), "%0.2f" % (item.VL), "%0.2f" % (item.VT), "%0.2f" % (item.Eta_v), "%0.2f" % (item.Eta_s), item.Label) + self.populateTree(materials_parent, materials_label, materials_values,None) + + self.expandItem(material_tree) + + # Boundaries + if SimNDT_Boundaries is not None: + boundaries_tree = QTreeWidgetItem(self) + boundaries_tree.setText(0, "Boundaries") + boundaries_tree.setFont(0, QFont(FONT_NAME, FONT_SIZE_1, QFont.Bold)) + boundaries_tree.setIcon(0, QIcon(":/boundary.png")) + + for item in SimNDT_Boundaries: + boundaries_parent = QTreeWidgetItem(boundaries_tree) + boundaries_parent.setText(0, item.Name) + boundaries_parent.setFont(0, QFont(FONT_NAME, FONT_SIZE_2, QFont.Normal)) + + boundaries_label = ("Layer", "Size") + size = item.Size if item.BC == BC.AbsorbingLayer else None + boundaries_values = (BC.keys[item.BC], size) + self.populateTree(boundaries_parent, boundaries_label, boundaries_values,None) + self.expandItem(boundaries_tree) + + # Inspections + if SimNDT_Inspection is not None: + + if SimNDT_Inspection.Name == "LinearScan": + method = SimNDT_Inspection + Name = SimNDT_Inspection.Name + ": " + SimNDT_Inspection.Method + + + else: + method = SimNDT_Inspection + Name = method.Name + + source = SimNDT_Source + + inspection_tree = QTreeWidgetItem(self) + inspection_tree.setText(0, "Inspection Method") + inspection_tree.setFont(0, QFont(FONT_NAME, FONT_SIZE_1, QFont.Bold)) + + if SimNDT_Inspection.Name == "LinearScan": + inspection_tree.setIcon(0, QIcon(":/linearScan.png")) + elif SimNDT_Inspection.Name == "Tomography": + inspection_tree.setIcon(0, QIcon(":/tomoSetup.png")) + else: + inspection_tree.setIcon(0, QIcon(":/singleLaunch.png")) + + inspection_parent = QTreeWidgetItem(inspection_tree) + + inspection_parent.setText(0, Name) + inspection_parent.setFont(0, QFont(FONT_NAME, FONT_SIZE_2, QFont.Normal)) + inspection_label = ("Longitudinal Source", "Shear Source") + inspection_values = (bool(source.Longitudinal), bool(source.Shear)) + self.populateTree(inspection_parent, inspection_label, inspection_values,None) + + transductor_tree = QTreeWidgetItem(inspection_parent) + transductor_tree.setText(0, "Emisor Transducer") + transductor_tree.setFont(0, QFont(FONT_NAME, FONT_SIZE_2, QFont.Normal)) + if method.Name == "Tomography": + transductor_label = ("Size", "Point Source", "Windowed Source") + transductor_values = (SimNDT_Transducers[0].Size, + bool(SimNDT_Transducers[0].PointSource), + bool(SimNDT_Transducers[0].Window)) + else: + transductor_label = ("Size", "Center Offset", "Border Offset", "Point Source", "Windowed Source") + transductor_values = (SimNDT_Transducers[0].Size, + SimNDT_Transducers[0].CenterOffset, + SimNDT_Transducers[0].BorderOffset, + bool(SimNDT_Transducers[0].PointSource), + bool(SimNDT_Transducers[0].Window)) + self.populateTree(transductor_tree, transductor_label, transductor_values,SimNDT_Transducers[0]) + + signal_tree = QTreeWidgetItem(inspection_parent) + signal_tree.setText(0, "Signal") + signal_tree.setFont(0, QFont(FONT_NAME, FONT_SIZE_2, QFont.Normal)) + signal_tree.setIcon(0, QIcon(":/signal.png")) + + if SimNDT_Signal.Name == "GaussianSine": + signal_label = ("Type", "Amplitude", "Frequency (MHz)", "# Cycles") + signal_values = (SimNDT_Signal.Name, SimNDT_Signal.Amplitude, + SimNDT_Signal.Frequency * 1e-6, SimNDT_Signal.N_Cycles) + else: + signal_label = ("Type", "Amplitude", "Frequency (MHz)", "# Cycles") + signal_values = (SimNDT_Signal.Name, SimNDT_Signal.Amplitude, + SimNDT_Signal.Frequency * 1e-6) + + self.populateTree(signal_tree, signal_label, signal_values,SimNDT_Signal) + + self.expandItem(signal_tree) + self.expandItem(inspection_tree) + self.expandItem(inspection_parent) + + # Simulation + if SimNDT_Simulation is not None: + simulation_tree = QTreeWidgetItem(self) + simulation_tree.setText(0, "Simulation Parameters") + simulation_tree.setFont(0, QFont(FONT_NAME, FONT_SIZE_1, QFont.Bold)) + simulation_tree.setIcon(0, QIcon(":/simModel.png")) + + simulation_label = ("Time Scale", "Max. Frequency (MHz)", "Points/Cycle", + "Simulation Time (%ss)" % MU, "Device", "OpenCL", + "dx (mm)", "dt (%ss)" % MU, "Numerical Model Size") + + freq = SimNDT_Simulation.MaxFreq * 1e-6 + dx = "%.4f" % (SimNDT_Simulation.dx * 1e3) + dt = "%.4f" % (SimNDT_Simulation.dt * 1e6) + simTime = SimNDT_Simulation.SimulationTime * 1e6 + modelSize = "%d x %d" % (SimNDT_Simulation.MRI, SimNDT_Simulation.NRI) + + Platform = False if SimNDT_Simulation.Platform == "Serial" else True + + simulation_values = (SimNDT_Simulation.TimeScale, freq, + SimNDT_Simulation.PointCycle, simTime, + SimNDT_Simulation.Device, Platform, + dx, dt, modelSize) + + self.populateTree(simulation_tree, simulation_label, simulation_values,SimNDT_Simulation) + + self.expandItem(simulation_tree) + + def populateTree(self, parent, labels, values, obj): + + for i, j in zip(labels, values): + if j is None: + continue + item = QTreeWidgetItem(parent) + if obj != None: + item._userData = [ + i, + j, + obj + ] + item._editing=0 + item.setText(0, i) + item.setFont(0, QFont(FONT_NAME, FONT_SIZE_2, QFont.Normal)) + if isinstance(j, bool): + if j is True: + item.setText(1, MARK) + else: + item.setText(1, CROSS) + else: + item.setText(1, str(j)) + if obj != None: + item.setFlags(item.flags() | Qt.ItemIsEditable) + + item.setFont(1, QFont(FONT_NAME, FONT_SIZE_3, QFont.Normal)) + + self.expandItem(parent)