From e7516ce50009416d1d90e34635b4fa929f22f2ac Mon Sep 17 00:00:00 2001 From: sbosse Date: Wed, 28 Aug 2024 21:42:53 +0200 Subject: [PATCH] Wed 28 Aug 21:38:52 CEST 2024 --- src/SimNDT/gui/MainWindow.py | 836 +++++++++++++++++++++++++++++++++++ 1 file changed, 836 insertions(+) create mode 100644 src/SimNDT/gui/MainWindow.py diff --git a/src/SimNDT/gui/MainWindow.py b/src/SimNDT/gui/MainWindow.py new file mode 100644 index 0000000..a214051 --- /dev/null +++ b/src/SimNDT/gui/MainWindow.py @@ -0,0 +1,836 @@ +import sys, os, datetime +import numpy as np +from scipy.io import savemat, loadmat + +from PySide.QtCore import * +from PySide.QtGui import * + +from SimNDT.gui.ui_mainwindow import Ui_MainWindow + +from SimNDT.gui import HelperMethods +from SimNDT.gui import managerFile + +from SimNDT.gui.managerDialogsController import ManagerDialogs +from SimNDT.gui.managerPlotsController import ManagerPlots +from SimNDT.gui.Warnings import WarningParms +from SimNDT.gui.checkOpenCL import isOpenCL + +from SimNDT.gui.statusBarWidget import StatusBarWidget +from SimNDT.gui.treeWidget import TreeWidget +from SimNDT.gui.helpForm import HelpForm + +from SimNDT.graphics.graphicView import GraphicView + +from SimNDT.core.scenario import Scenario +from SimNDT.core.material import Material +from SimNDT.core.boundary import Boundary +from SimNDT.core.geometryObjects import Ellipse, Circle, Inclusions, Rectangle, Square +from SimNDT.core.geometryObjects import Concrete2Phase, Concrete2PhaseImmersion, Concrete3Phase, Concrete3PhaseImmersion +from SimNDT.core.inspectionMethods import Source, LinearScan, Transmission, PulseEcho, Tomography +from SimNDT.core.signal import Signals +from SimNDT.core.receivers import Receivers +from SimNDT.core.transducer import Transducer +from SimNDT.core.simulation import Simulation + + +import jsonpickle +import math + +YEAR = 2080 +MONTH = 12 + + +class Info: + def __init__(self): + self.version = "0.63.2" + self.date = "07-05-2024" + + +info = Info() + +class MainWindow(QMainWindow, Ui_MainWindow, ManagerDialogs, ManagerPlots): + def __init__(self, parent=None): + + super(MainWindow, self).__init__(parent) + self.setupUi(self) + self.init() + + self.createMenus() + self.createToolBar() + self.setupGraphicView() + self.setupStatusBar() + self.tree() + self.setupConnections() + self.initSettings() + + isOpenCL(self.statusBarWidget.openclIcon, self.statusBarWidget.openclLabel) + self.OnLicence() + + self.updateFileMenu() + + self.OpenSimFile = False + QTimer.singleShot(0, self.loadInitialFile) + + if self.filename is None: + self.initSim() + + def OnLicence(self): + year = datetime.datetime.today().year + month = datetime.datetime.today().month + if year >= YEAR and month >= MONTH: + dial = WarningParms('Get the new version!!!!, please contact to: sbosse@uni-bremen.de') + if dial.exec_(): + self.close() + sys.exit() + + def createObjects(self): + + self.SimNDT_Scenario = None + self.SimNDT_ObjectList = None + self.SimNDT_Materials = None + self.SimNDT_Boundaries = None + self.SimNDT_Transducers = None + self.SimNDT_Inspection = None + self.SimNDT_Source = None + self.SimNDT_Signal = None + self.SimNDT_Simulation = None + self.SimNDT_Receivers = None + self.SimNDT_SnapShots = None + + self.SimNDT_ConcreteMicrostructure = None + + def setupConnections(self): + self.actionNew_Geometry_Model.triggered.connect(self.newGeometryModel) + self.actionPreview_Labeled_Scenario.triggered.connect(self.previewScenario) + self.actionAdd_Ellipse.triggered.connect(self.addEllipse) + self.actionAdd_Rectangle.triggered.connect(self.addRectangle) + self.actionShow_Scenario.triggered.connect(self.showScenario) + self.actionLoad_Scenario_From_Image.triggered.connect(self.loadImage) + self.actionRotate_The_Scenario_90_Clockwise.triggered.connect(self.rotateScenarioClockwise) + self.actionRotate_The_Scenario_90_Counter_Clockwise.triggered.connect(self.rotateScenarioCounterClockwise) + + self.actionTwo_Phase_Model_Dry_Case.triggered.connect(self.twoPhaseModelDryCase) + self.actionThree_Phase_Model_Dry_Case.triggered.connect(self.threePhaseModelDryCase) + self.actionTwo_Phase_Model_Immersion_Case.triggered.connect(self.twoPhaseModelImmersionCase) + self.actionThree_Phase_Model_Immersion_Case.triggered.connect(self.threePhaseModelImmersionCase) + + self.actionMaterials_Setup.triggered.connect(self.materialSetup) + self.actionBoundaty_Conditions_Setup.triggered.connect(self.boundarySetup) + self.actionSingle_Launch_Inspection.triggered.connect(self.singleLaunchSetup) + self.actionLinear_Scan_Inspections.triggered.connect(self.linearScanSetup) + self.actionTomography_Inspections.triggered.connect(self.tomographySetup) + self.actionSignal.triggered.connect(self.signalSetup) + self.actionSimulation_Setup.triggered.connect(self.simulationSetup) + self.actionCheck_Simulation_Setup.triggered.connect(self.checkSimulation) + self.actionRun_Simulation.triggered.connect(self.runSimulation) + + self.actionPlot_Receiver_Signals_SingleLaunch.triggered.connect(self.plotSingleLaunch) + self.actionPlot_Receiver_Signals_Spectra.triggered.connect(self.spectraSingleLaunch) + self.actionPlot_Receivers_Signals_LinearScan.triggered.connect(self.plotLinearScan) + self.actionPlot_Receivers_Signals_Tomography.triggered.connect(self.plotTomoSignals) + + self.actionCreate_Video_from_Images.triggered.connect(self.generateVideo) + + self.GraphicView.refreshZoom.zoomed.connect(self.statusBarWidget.zoomSpinBox.setValue) + + def init(self): + + self.SimNDT_Info = Info() + self.SimNDT_Check = False + + self.dirty = False + self.reset = False + self.filename = None + self.recentFiles = [] + + self.StopSimulation = False + self.PauseSimulation = False + + self.setGeometry(100, 100, 900, 600) + self.setMinimumSize(400, 400) + + self.setWindowTitle('SimNDT2 v' + self.SimNDT_Info.version) + self.setWindowFlags(self.windowFlags()) + + def setTitle(self, fname): + title = os.path.basename(fname) + self.setWindowTitle('SimNDT2 v' + self.SimNDT_Info.version + ': ' + title) + + def loadInitialFile(self): + settings = QSettings() + fname = settings.value("LastFile") + if fname and QFile.exists(fname): + self.loadFile(fname) + + def createMenus(self): + + newFileAction = HelperMethods.createAction(self, "&New Simulation", self.fileNew, + QKeySequence.New, "document-new.png", self.tr("New Simulation File")) + fileOpenAction = HelperMethods.createAction(self, "&Open existing Simulation", self.fileOpen, + QKeySequence.Open, 'document-open.png', + self.tr("Open an existing Simulation")) + fileSaveAction = HelperMethods.createAction(self, "&Save Simulation", self.fileSave, + QKeySequence.Save, "document-save.png", + self.tr("Save the current Simulation")) + fileSaveAsAction = HelperMethods.createAction(self, "Save &As", self.fileSaveAs, + QKeySequence.SaveAs, icon="document-save-as.png", + tip=self.tr("Save Simulation File As")) + + fileOpenAction.setIcon(self.style().standardIcon(QStyle.SP_DirOpenIcon)) + # fileSaveAction.setIcon(self.style().standardIcon(QStyle.SP_FileDialogNewFolder)) + + + fileImportJSONAction = HelperMethods.createAction(self, "&Import from .json", self.importJSON, + QKeySequence.Open, 'document-open.png', + self.tr("Import .json Simulation")) + fileExportJSONAction = HelperMethods.createAction(self, "Export in .json File", self.exportJSON, + "Ctrl+J", icon="exportMatlab.png", + tip=self.tr("Export in .json File")) + + fileExportMatlabAction = HelperMethods.createAction(self, "Export in .mat File", self.exportMatlab, + "Ctrl+E", icon="exportMatlab.png", + tip=self.tr("Export in .mat File")) + + fileResetAction = HelperMethods.createAction(self, "Reset Settings", self.resetSettings, icon="reset.png") + + fileQuitAction = HelperMethods.createAction(self, "&Quit", self.close, + "Ctrl+Q", "close", self.tr("Close the application")) + + self.fileMenuActions = (newFileAction, fileOpenAction, + fileSaveAction, fileSaveAsAction, fileImportJSONAction, fileExportJSONAction, fileExportMatlabAction, None, fileResetAction, + fileQuitAction) + + HelperMethods.setEnabled(self.fileMenuActions[2:4], False) + HelperMethods.setEnabled(self.fileMenuActions[5:6], False) + self.connect(self.menuFile, SIGNAL("aboutToShow()"), self.updateFileMenu) + + self.geometryMenuActions = ( + self.actionNew_Geometry_Model, None, self.actionAdd_Ellipse, self.actionAdd_Rectangle, + self.actionShow_Scenario, None, self.actionShow_Scenario, + self.actionLoad_Scenario_From_Image, None, self.actionPreview_Labeled_Scenario, + self.actionRotate_The_Scenario_90_Clockwise, self.actionRotate_The_Scenario_90_Counter_Clockwise) + + HelperMethods.setEnabled(self.menuNew_Simulation_Scenario, False) + HelperMethods.setEnabled(self.geometryMenuActions, False) + + self.configurationMenuActions = (self.actionMaterials_Setup, self.actionBoundaty_Conditions_Setup) + HelperMethods.setEnabled(self.configurationMenuActions, False) + + self.inspectionMenuActions = ( + self.actionSingle_Launch_Inspection, self.actionLinear_Scan_Inspections, self.actionTomography_Inspections) + inspectionGroup = QActionGroup(self) + HelperMethods.addActions(inspectionGroup, self.inspectionMenuActions) + + HelperMethods.setEnabled(self.menuInspection_Setup, False) + HelperMethods.setEnabled(self.actionSimulation_Setup, False) + HelperMethods.setEnabled(self.actionCheck_Simulation_Setup, False) + HelperMethods.setEnabled(self.actionRun_Simulation, False) + + self.actionSignal = HelperMethods.createAction(self, "&Signal Setup", self.signalSetup, + "Ctrl+Shift+p", "signal.png", self.tr("Signal Setup")) + + self.simulationMenuActions = (self.actionNew_Geometry_Model, self.actionMaterials_Setup, + self.actionBoundaty_Conditions_Setup, self.actionSingle_Launch_Inspection, + self.actionLinear_Scan_Inspections, self.actionTomography_Inspections, + self.actionSimulation_Setup, self.actionCheck_Simulation_Setup, + self.actionRun_Simulation) + + self.menuPlotting_Tools.menuAction().setVisible(False) + + # self.menuAdd_Microstructure.menuAction().setVisible(False) + # self.menuTools.menuAction().setVisible(False) + + + helpAboutAction = HelperMethods.createAction(self, "&About SimNDT", self.helpAbout) + helpHelpAction = HelperMethods.createAction(self, self.tr("&Help"), self.helpHelp, QKeySequence.HelpContents) + + helpMenu = self.menubar.addMenu(self.tr("&Help")) + HelperMethods.addActions(helpMenu, (helpAboutAction, helpHelpAction)) + + def updateFileMenu(self): + + self.menuFile.clear() + HelperMethods.addActions(self.menuFile, self.fileMenuActions[0:-2]) + current = self.filename if self.filename is not None else None + recentFiles = [] + + for fname in self.recentFiles: + if fname != current and QFile.exists(fname): + recentFiles.append(fname) + if recentFiles: + self.menuFile.addSeparator() + for i, fname in enumerate(recentFiles): + action = QAction(QIcon(":/logo_SimNDT.png"), "&%d %s" % ( + i + 1, QFileInfo(fname).fileName()), self) + action.setData(fname) + self.connect(action, SIGNAL("triggered()"), + self.loadFile) + self.menuFile.addAction(action) + + self.menuFile.addSeparator() + self.menuFile.addAction(self.fileMenuActions[-2]) + self.menuFile.addAction(self.fileMenuActions[-1]) + + def okToContinue(self): + + if self.dirty: + reply = QMessageBox.question(self, + "SimNDT - Unsaved Changes", + "Save unsaved changes?", + QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) + + if reply == QMessageBox.Cancel: + return False + elif reply == QMessageBox.Yes: + self.fileSave() + return True + + def loadFile(self, fname=None): + + if fname is None: + action = self.sender() + if isinstance(action, QAction): + fname = action.data() + if not self.okToContinue(): + return + else: + return + + if fname: + self.filename = None + self.addRecentFile(fname) + self.filename = fname + self.dirty = False + HelperMethods.setEnabled(self.fileMenuActions[2:4], True) + HelperMethods.setEnabled(self.fileMenuActions[5:6], True) + self.setTitle(fname) + if fname.endswith('.json'): + self.importSim(fname) + else: + self.openSim() + + def addRecentFile(self, fname): + + if fname is None: + return + + if not self.recentFiles.count(fname): + self.recentFiles.insert(0, fname) + while len(self.recentFiles) > 9: + self.recentFiles.pop() + + def createToolBar(self): + + self.fileToolBar = self.addToolBar("File Tools") + self.fileToolBar.setObjectName("FileToolBar") + HelperMethods.addActions(self.fileToolBar, self.fileMenuActions[:-2]) + + def simulationToolBar(self, numWidgets): + + if not hasattr(self, 'SimToolBar'): + self.SimToolBar = QToolBar(self.tr("Simulation Tools")) + self.SimToolBar.setObjectName("SimToolBar") + self.SimToolBar.setAllowedAreas( + Qt.TopToolBarArea | Qt.BottomToolBarArea | Qt.LeftToolBarArea | Qt.RightToolBarArea) + + self.SimToolBar.clear() + HelperMethods.addActions(self.SimToolBar, self.simulationMenuActions[0:numWidgets]) + self.addToolBar(Qt.TopToolBarArea, self.SimToolBar) + + def geometryToolBar(self, reset=False, LoadImage=False): + if not hasattr(self, 'GeometryToolBar'): + self.GeometryToolBar = QToolBar(self.tr("Geometry Tools")) + self.GeometryToolBar.setObjectName("GeometryToolBar") + self.GeometryToolBar.setAllowedAreas( + Qt.TopToolBarArea | Qt.BottomToolBarArea | Qt.LeftToolBarArea | Qt.RightToolBarArea) + + self.GeometryToolBar.clear() + if LoadImage: + HelperMethods.addActions(self.GeometryToolBar, self.geometryMenuActions[4]) + self.addToolBar(Qt.RightToolBarArea, self.GeometryToolBar) + return + + if reset: + return + else: + HelperMethods.addActions(self.GeometryToolBar, self.geometryMenuActions[2:]) + # self.addToolBarBreak(Qt.TopToolBarArea) + self.addToolBar(Qt.RightToolBarArea, self.GeometryToolBar) + + def setupGraphicView(self): + + self.GraphicView = GraphicView(self) + self.setCentralWidget(self.GraphicView) + + def setupStatusBar(self): + + self.status = self.statusBar() + self.status.setSizeGripEnabled(False) + + self.statusBarWidget = StatusBarWidget() + self.connect(self.statusBarWidget.zoomSpinBox, SIGNAL("valueChanged(int)"), self.GraphicView, + SLOT("setZoom(int)")) + + self.status.insertPermanentWidget(0, self.statusBarWidget.statusFrame) + self.status.showMessage("Ready", 15000) + + self.connect(self.statusBarWidget.StopStatusBar, SIGNAL("clicked()"), self.stopFunc) + self.connect(self.statusBarWidget.StartPauseStatusBar, SIGNAL("clicked()"), self.startPauseFunc) + + self.StopSimulation = False + self.PauseSimulation = False + + def tree(self): + + self.treeWidget = TreeWidget() + self.treeDockWidget = QDockWidget(self.tr("Simulation Parameters")) + self.treeDockWidget.setObjectName("treeDockWidget") + self.treeDockWidget.setWidget(self.treeWidget) + self.treeDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) + + self.treeWidget.deleteDone.sig.connect(self.updateUI) + + def initSettings(self): + + settings = QSettings() + self.recentFiles = [] # settings.value("RecentFiles",[]) + size = settings.value("MainWindow/Size", QSize(900, 600)) + position = settings.value("MainWindow/Position", QPoint(50, 50)) + self.restoreState(settings.value("MainWindow/State")) + zoom = float(settings.value("Graphics/Zoom", 100.0)) + + if self.recentFiles is None: + self.recentFiles = [] + + self.resize(size) + self.move(position) + + # self.GraphicView.setupZoom(zoom) + self.statusBarWidget.zoomSpinBox.setValue(zoom) + + def resetSettings(self): + + settings = QSettings() + settings.clear() + self.reset = True + self.close() + + def fileNew(self): + + if not self.okToContinue(): + return + + fname = managerFile.fileNew(self.filename) + + if fname: + HelperMethods.setEnabled(self.fileMenuActions[2:4], True) + self.filename = fname + self.dirty = True + self.setTitle(fname) + self.newSim() + + def fileOpen(self): + + if not self.okToContinue(): + return + + fname = managerFile.fileOpen(self.filename) + if fname: + self.loadFile(fname) + + def fileSave(self): + + if self.filename is None: + self.fileSaveAs() + else: + self.dirty = False + self.saveSim() + + def fileSaveAs(self): + + fname = managerFile.fileSaveAs(self.filename) + + if fname: + if "." not in fname: + fname += ".sim" + + self.addRecentFile(fname) + self.filename = fname + self.setTitle(self.filename) + self.saveSim() + + def importJSON(self): + + fname = managerFile.importJSON(self.filename) + + if fname: + if "." not in fname: + fname += ".json" + + self.importSim(fname) + + def exportMatlab(self): + + fname = managerFile.exportMatlab(self.filename) + + if fname: + if "." not in fname: + fname += ".mat" + + self.exportSimulation(fname) + + def exportJSON(self): + + fname = managerFile.exportJSON(self.filename) + + if fname: + if "." not in fname: + fname += ".json" + + self.exportSimulation(fname) + + def initSim(self): + + self.createObjects() + self.treeWidget.clear() + + self.statusBarWidget.zoomSpinBox.setVisible(False) + self.GraphicView.clearUpdate() + self.removeDockWidget(self.treeDockWidget) + + def newSim(self): + + self.initSim() + + self.simulationToolBar(1) + self.geometryToolBar(reset=True) + + HelperMethods.setEnabled(self.menuNew_Simulation_Scenario, True) + HelperMethods.setEnabled(self.geometryMenuActions[0], True) + HelperMethods.setEnabled(self.geometryMenuActions[4], True) + + # Show loadImage in Geometric Toolbar + self.geometryToolBar(LoadImage=True) + self.updateUI() + + def openSim(self): + data2load = {} + data2load = loadmat(self.filename, squeeze_me=True, struct_as_record=False) + + self.OpenSimFile = True + if "Info" in data2load: + self.SimNDT_Info = HelperMethods.mat2Obj(data2load["Info"], Info()) + + if "Scenario" in data2load: + Width = getattr(data2load["Scenario"], 'Width') + Height = getattr(data2load["Scenario"], 'Height') + Pixel_mm = getattr(data2load["Scenario"], 'Pixel_mm') + Label = getattr(data2load["Scenario"], 'Label') + self.SimNDT_Scenario = Scenario(Width=Width, Height=Height, Pixel_mm=Pixel_mm, Label=Label) + self.SimNDT_Scenario = HelperMethods.mat2Obj(data2load["Scenario"], self.SimNDT_Scenario) + + self.SimNDT_Materials = HelperMethods.loadDataFromList(data2load, 'Materials', Material()) + self.SimNDT_Boundaries = HelperMethods.loadDataFromList(data2load, "Boundaries", Boundary()) + self.SimNDT_Transducers = HelperMethods.loadDataFromList(data2load, "Transducers", Transducer()) + + geoLabels = ["ellipse", "circle", "square", "rectangle"] + geoObjects = [Ellipse(), Circle(), Square(), Rectangle()] + self.SimNDT_ObjectList = HelperMethods.loadDataFromListWithLabels(data2load, 'GeometricObjects', geoLabels, + geoObjects) + + ConcreteLabels = ["Concrete2Phase", "Concrete2PhaseImmersion", "Concrete3Phase", "Concrete3PhaseImmersion"] + ConcreteObjects = [Concrete2Phase(), Concrete2PhaseImmersion(), Concrete3Phase(), Concrete3PhaseImmersion()] + + if "ConcreteMicrostructure" in data2load: + self.SimNDT_ConcreteMicrostructure = HelperMethods.loadDataWithLabels(data2load, 'ConcreteMicrostructure', + ConcreteLabels, ConcreteObjects) + + if "Inspection" in data2load: + inspLabels = ['Transmission', 'PulseEcho', 'LinearScan', 'Tomography'] + inspObjects = [Transmission(), PulseEcho(), LinearScan(), Tomography()] + self.SimNDT_Inspection = HelperMethods.loadDataWithLabels(data2load, "Inspection", inspLabels, inspObjects) + + if "Source" in data2load: + self.SimNDT_Source = HelperMethods.mat2Obj(data2load["Source"], Source()) + + if "Signal" in data2load: + self.SimNDT_Signal = HelperMethods.mat2Obj(data2load["Signal"], Signals()) + + if "Simulation" in data2load: + self.SimNDT_Simulation = HelperMethods.mat2Obj(data2load["Simulation"], Simulation()) + + if "Receivers" in data2load: + self.SimNDT_Receivers = HelperMethods.mat2Obj(data2load["Receivers"], Receivers()) + + self.setPlotInspectionsMenu() + + self.updateUI() + + def importSim(self,filename): + data2load = {} + with open(filename, 'r') as file: + data2load = jsonpickle.decode(file.read()) # loadmat(self.filename, squeeze_me=True, struct_as_record=False) + + self.OpenSimFile = True + self.filename = filename + + if "Info" in data2load: + self.SimNDT_Info = data2load["Info"] + + if "Scenario" in data2load: + Width = getattr(data2load["Scenario"], 'Width') + Height = getattr(data2load["Scenario"], 'Height') + Pixel_mm = getattr(data2load["Scenario"], 'Pixel_mm') + Label = getattr(data2load["Scenario"], 'Label') + self.SimNDT_Scenario = Scenario(Width=Width, Height=Height, Pixel_mm=Pixel_mm, Label=Label) + self.SimNDT_Scenario = data2load["Scenario"] + + self.SimNDT_Materials = data2load['Materials'] + self.SimNDT_Boundaries = data2load["Boundaries"] + self.SimNDT_Transducers = data2load["Transducers"] + + self.SimNDT_ObjectList = data2load['GeometricObjects'] + + if "Inspection" in data2load: + self.SimNDT_Inspection = data2load["Inspection"] + + if "Source" in data2load: + self.SimNDT_Source = data2load["Source"] + + if "Signal" in data2load: + self.SimNDT_Signal = data2load["Signal"] + + if "Simulation" in data2load: + self.SimNDT_Simulation = data2load["Simulation"] + + if "Receivers" in data2load: + self.SimNDT_Receivers = data2load["Receivers"] + + self.setPlotInspectionsMenu() + + self.updateUI() + + def saveSim(self): + self._saveSimulation(self.filename) + + def exportSimulation(self, filename): + self._saveSimulation(filename) + + def _saveSimulation(self, filename): + + data2save = {} + + if self.SimNDT_Info is not None: + data2save['Info'] = self.SimNDT_Info + + if self.SimNDT_Scenario is not None: + data2save['Scenario'] = self.SimNDT_Scenario + + if self.SimNDT_ObjectList is not None: + data2save["GeometricObjects"] = self.SimNDT_ObjectList + + if self.SimNDT_ConcreteMicrostructure is not None: + data2save["ConcreteMicrostructure"] = self.SimNDT_ConcreteMicrostructure + + if self.SimNDT_Materials is not None: + data2save["Materials"] = self.SimNDT_Materials + + if self.SimNDT_Boundaries is not None: + data2save["Boundaries"] = self.SimNDT_Boundaries + + if self.SimNDT_Transducers is not None: + data2save["Transducers"] = self.SimNDT_Transducers + + if self.SimNDT_Inspection is not None: + data2save["Inspection"] = self.SimNDT_Inspection + + if self.SimNDT_Source is not None: + data2save["Source"] = self.SimNDT_Source + + if self.SimNDT_Signal is not None: + data2save["Signal"] = self.SimNDT_Signal + + if self.SimNDT_Simulation is not None: + data2save["Simulation"] = self.SimNDT_Simulation + + if self.SimNDT_Receivers is not None: + data2save["Receivers"] = self.SimNDT_Receivers + + if filename.endswith('.json'): + # savemat('/tmp/_simndt.mat', data2save, appendmat=False) + # mat2json('/tmp/_simndt.mat',filename) + with open(filename, 'w') as f: + f.write(jsonpickle.encode(data2save)) + else: + savemat(filename, data2save, appendmat=False) + self.dirty = False + + def stopFunc(self): + self.StopSimulation = True + + def startPauseFunc(self): + self.PauseSimulation = not self.PauseSimulation + if self.PauseSimulation: + self.statusBarWidget.StartPauseStatusBar.setIcon(QIcon(":/play.png")) + else: + self.statusBarWidget.StartPauseStatusBar.setIcon(QIcon(":/pause.png")) + + def helpAbout(self): + + QMessageBox.about(self, "About SimNDT", + """ SimNDT v{0}X, date: {1} +

Copyright © 2014 M. Molero (original author v0.52)

+

Copyright © 2024 Dr. Stefan Bosse (> 0.60)

+

Ultrasonic Simulation Software - Plus +

info: +

sbosse@uni-bremen.de +

+

+

if you use SimNDT Software in your research, we would appreciate the citation of the following article: +

M. Molero, U. Iturraran-Viveros, S. Sofia, M.G. Hernandez, +

Optimized OpenCL implementation of the Elastodynamic Finite Integration Technique for viscoelastic media, +

Computer Physics Communications Volume 185, Issue 10, October 2014, Pages 2683-2696 + """.format(info.version, info.date)) + + def helpHelp(self): + + dlg = HelpForm("index.html", self) + dlg.show() + + def closeEvent(self, event): + + if self.reset: + return + + if self.okToContinue(): + settings = QSettings() + filename = self.filename if self.filename is not None else None + settings.setValue("LastFile", filename) + recentFiles = self.recentFiles if self.recentFiles else None + settings.setValue("RecentFiles", recentFiles) + settings.setValue("MainWindow/Size", self.size()) + settings.setValue("MainWindow/Position", self.pos()) + settings.setValue("MainWindow/State", self.saveState()) + settings.setValue("Graphics/Zoom", self.GraphicView.getZoom()) + + else: + event.ignore() + + def setPlotInspectionsMenu(self): + + HelperMethods.setEnabled(self.actionPlot_Receiver_Signals_SingleLaunch, False) + HelperMethods.setEnabled(self.actionPlot_Receiver_Signals_Spectra, False) + + HelperMethods.setEnabled(self.actionPlot_Receivers_Signals_LinearScan, False) + HelperMethods.setEnabled(self.actionPlot_Receivers_Signals_Tomography, False) + + Name = self.SimNDT_Inspection.Name + if Name == "Transmission" or Name == "PulseEcho": + self.menuPlotting_Tools.menuAction().setVisible(True) + HelperMethods.setEnabled(self.actionPlot_Receiver_Signals_SingleLaunch, True) + elif Name == "LinearScan": + self.menuPlotting_Tools.menuAction().setVisible(True) + HelperMethods.setEnabled(self.actionPlot_Receivers_Signals_LinearScan, True) + elif Name == 'Tomography': + self.menuPlotting_Tools.menuAction().setVisible(True) + HelperMethods.setEnabled(self.actionPlot_Receivers_Signals_Tomography, True) + + def updateUI(self): + + if self.SimNDT_Scenario is not None: + try: + self.GraphicView.imshow(self.SimNDT_Scenario.I) + except Exception as e: + msgBox = WarningParms("Unable to display GRAPHICS!!!. Incompatible Graphic Card, %s" % e) + if msgBox.exec_(): + sys.exit() + + HelperMethods.setEnabled(self.menuNew_Simulation_Scenario, True) + HelperMethods.setEnabled(self.fileMenuActions[2:5], True) + HelperMethods.setEnabled(self.geometryMenuActions[0:], True) + HelperMethods.setEnabled(self.configurationMenuActions[0], True) + + self.addDockWidget(Qt.LeftDockWidgetArea, self.treeDockWidget) + self.treeDockWidget.show() + + self.geometryToolBar() + self.simulationToolBar(2) + self.statusBarWidget.zoomSpinBox.setVisible(True) + + if self.SimNDT_Materials is not None: + HelperMethods.setEnabled(self.configurationMenuActions[1], True) + self.simulationToolBar(3) + + if self.SimNDT_Boundaries is not None: + if np.size(self.SimNDT_Scenario.Iabs) == 1: + self.GraphicView.imshow(self.SimNDT_Scenario.Iabs) + else: + self.GraphicView.imshow(self.SimNDT_Scenario.Iabs) + HelperMethods.setEnabled(self.menuInspection_Setup, True) + HelperMethods.setEnabled(self.inspectionMenuActions[:], True) + self.simulationToolBar(6) + + if self.SimNDT_Inspection is not None: + HelperMethods.setEnabled(self.simulationMenuActions[6], True) + self.simulationToolBar(7) + + if self.SimNDT_Simulation is not None: + HelperMethods.setEnabled(self.simulationMenuActions[7], True) + self.simulationToolBar(8) + + if self.SimNDT_Check: + HelperMethods.setEnabled(self.actionRun_Simulation, True) + if not self.OpenSimFile: + self.simulationToolBar(9) + + self.treeWidget.update(self.SimNDT_Scenario, + self.SimNDT_ObjectList, + self.SimNDT_Materials, + self.SimNDT_Boundaries, + self.SimNDT_Inspection, + self.SimNDT_Source, + self.SimNDT_Transducers, + self.SimNDT_Signal, + self.SimNDT_Simulation) + def showScenario(self): + self.SimNDT_Scenario.resetImage() + + for obj in self.SimNDT_ObjectList: + self.SimNDT_Scenario.addObject(obj) + + if self.SimNDT_Boundaries is not None: + self.SimNDT_Scenario.createBoundaries(self.SimNDT_Boundaries) + + self.updateUI() + # @blab+ Add transducer as circle and show I/Iabs copy + I=self.SimNDT_Scenario.addTransducer(self.SimNDT_Scenario.Width/2+self.SimNDT_Transducers[0].CenterOffset, + self.SimNDT_Transducers[0].BorderOffset, + self.SimNDT_Transducers[0].Size, 240) + if self.SimNDT_SnapShots is not None: + if len(self.SimNDT_SnapShots.sensorShape) == 2: + xn = self.SimNDT_Scenario.Width + yn = self.SimNDT_Scenario.Height + dx = 1 # sensor delta + dy = 1 + ox = 0 # offset + oy = 0 + # size of sensor matrix + sx = self.SimNDT_SnapShots.sensorShape[0] + sy = self.SimNDT_SnapShots.sensorShape[1] + S = np.zeros([sy,sx]) + if len(self.SimNDT_SnapShots.sensorPlacement) == 4: + p=self.SimNDT_SnapShots.sensorPlacement + ox=p[0] + dx=p[1] + oy=p[2] + dy=p[3] + else: + ox=dx=round(xn/(sx+1.0)) + oy=dy=round(yn/(sy+1.0)) + for x in range(0,sx): + for y in range(0,sy): + self.SimNDT_Scenario.addSensor(I,ox+x*dx,oy+y*dy,10, 255) + self.GraphicView.clearUpdate() + self.GraphicView.imshow(I) + +