From e42ecd9428ed0b1b8e41e7c4cbe69b0176c02ec4 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 9 Jun 2022 15:54:49 -0500 Subject: [PATCH 01/32] rough draft of only restoring view settings, not model settings - this does work --- openmc_plotter/main_window.py | 47 +++--- openmc_plotter/plotmodel.py | 307 ++++++++++++++++++++++------------ 2 files changed, 227 insertions(+), 127 deletions(-) diff --git a/openmc_plotter/main_window.py b/openmc_plotter/main_window.py index 4c089ac..cc391ab 100755 --- a/openmc_plotter/main_window.py +++ b/openmc_plotter/main_window.py @@ -21,7 +21,7 @@ except ImportError: _HAVE_VTK = False -from .plotmodel import PlotModel, DomainTableModel +from .plotmodel import PlotModel, DomainTableModel, PlotView from .plotgui import PlotImage, ColorDialog from .docks import DomainDock, TallyDock from .overlays import ShortcutsOverlay @@ -62,7 +62,7 @@ def __init__(self, self.font_metric = font self.setWindowTitle('OpenMC Plot Explorer') - def loadGui(self, use_settings_pkl=True): + def loadGui(self, use_settings_pkl=True, use_saved_view=True): self.pixmap = None self.zoom = 100 @@ -130,6 +130,8 @@ def loadGui(self, use_settings_pkl=True): QtCore.QTimer.singleShot(0, self.showCurrentView) self.plotIm.frozen = False + #print(dir(self.model)) + def event(self, event): # use pinch event to update zoom @@ -463,10 +465,12 @@ def loadModel(self, reload=False, use_settings_pkl=True): if reload: self.resetModels() else: + #if use_settings_pkl: + # self.restoreModelSettings() + self.model = PlotModel(use_settings_pkl) # create new plot model - self.model = PlotModel() - if use_settings_pkl: - self.restoreModelSettings() + + # update plot and model settings self.updateRelativeBases() @@ -1080,20 +1084,20 @@ def restoreModelSettings(self): with open('plot_settings.pkl', 'rb') as file: model = pickle.load(file) - # check if loaded cell/mat ids hash match the pkl file: - current_mat_xml_hash = hash_file('materials.xml') - current_geom_xml_hash = hash_file('geometry.xml') - if (current_mat_xml_hash != model.mat_xml_hash) or \ - (current_geom_xml_hash != model.geom_xml_hash): - # hashes do not match so ignore plot_settings.pkl file - msg_box = QMessageBox() - msg = "WARNING: Model has changed since storing plot " +\ - "settings. Ignoring previous plot settings." - msg_box.setText(msg) - msg_box.setIcon(QMessageBox.Warning) - msg_box.setStandardButtons(QMessageBox.Ok) - msg_box.exec_() - return + # # check if loaded cell/mat ids hash match the pkl file: + # current_mat_xml_hash = hash_file('materials.xml') + # current_geom_xml_hash = hash_file('geometry.xml') + # if (current_mat_xml_hash != model.mat_xml_hash) or \ + # (current_geom_xml_hash != model.geom_xml_hash): + # # hashes do not match so ignore plot_settings.pkl file + # msg_box = QMessageBox() + # msg = "WARNING: Model has changed since storing plot " +\ + # "settings. Ignoring previous plot settings." + # msg_box.setText(msg) + # msg_box.setIcon(QMessageBox.Warning) + # msg_box.setStandardButtons(QMessageBox.Ok) + # msg_box.exec_() + # return # do not replace model if the version is out of date if model.version != self.model.version: @@ -1114,7 +1118,7 @@ def restoreModelSettings(self): msg_box.exec_() self.model.statepoint = None - self.model.currentView = model.currentView + self.model.currentView = PlotView(restore_view=model.currentView) self.model.activeView = copy.deepcopy(model.currentView) self.model.previousViews = model.previousViews self.model.subsequentViews = model.subsequentViews @@ -1224,6 +1228,9 @@ def saveSettings(self): self.model.statepoint.close() pickle.dump(self.model, file) + #with open('view_settings.pkl', 'wb') as file: + # pickle.dump(self.model.currentView, file) + def exportTallyData(self): # show export tool dialog self.showExportDialog() diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 5d5759f..36647b7 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -1,8 +1,11 @@ from ast import literal_eval from collections import defaultdict import copy +from difflib import restore import itertools import threading +import os +import pickle from PySide2.QtWidgets import QItemDelegate, QColorDialog, QLineEdit, QMessageBox from PySide2.QtCore import QAbstractTableModel, QModelIndex, Qt, QSize, QEvent @@ -92,7 +95,7 @@ class PlotModel(): have unapplied changes """ - def __init__(self): + def __init__(self, use_settings_pkl): """ Initialize PlotModel class attributes """ # Retrieve OpenMC Cells/Materials @@ -116,10 +119,39 @@ def __init__(self): # reset random number seed for consistent # coloring when reloading a model reset_seed() - self.previousViews = [] self.subsequentViews = [] - self.defaultView = self.getDefaultView() + + if use_settings_pkl and os.path.isfile('plot_settings.pkl'): + with open('plot_settings.pkl', 'rb') as file: + model = pickle.load(file) + + # check GUI version + if model.version != self.version: + print("WARNING: previous plot settings are for a different " + "version of the GUI. They will be ignored.") + wrn_msg = "Existing version: {}, Current GUI version: {}" + print(wrn_msg.format(model.version, self.version)) + view = None + else: + view = model.currentView + + # restore statepoint file + try: + self.statepoint = model.statepoint + except OSError: + msg_box = QMessageBox() + msg = "Could not open statepoint file: \n\n {} \n" + msg_box.setText(msg.format(self.model.statepoint.filename)) + msg_box.setIcon(QMessageBox.Warning) + msg_box.setStandardButtons(QMessageBox.Ok) + msg_box.exec_() + self.statepoint = None + + self.defaultView = PlotView(restore_view=view) + else: + self.defaultView = self.getDefaultView() + self.currentView = copy.deepcopy(self.defaultView) self.activeView = copy.deepcopy(self.defaultView) @@ -651,8 +683,8 @@ def _do_op(array, tally_value, ax=0): return image_data, extents, data_min, data_max -class PlotView(openmc.lib.plot._PlotBase): - """ View settings for OpenMC plot. +class PlotViewIndependent(openmc.lib.plot._PlotBase): + """ View settings for OpenMC plot, independent of the model. Parameters ---------- @@ -701,10 +733,6 @@ class PlotView(openmc.lib.plot._PlotBase): Indicator of whether or not overlaps will be shown overlap_color : 3-tuple of int RGB color to apply for cell overlap regions - cells : Dict of DomainView instances - Dictionary of cell view settings by ID - materials : Dict of DomainView instances - Dictionary of material view settings by ID domainAlpha : float between 0 and 1 Alpha value of the geometry plot plotVisibile : bool @@ -735,110 +763,106 @@ class PlotView(openmc.lib.plot._PlotBase): Indicates whether or not tallies are displayed as contours tallyContourLevels : str Number of contours levels or explicit level values - selectedTally : str - Label of the currently selected tally """ - - def __init__(self, origin, width, height): + def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): """ Initialize PlotView attributes """ super().__init__() - # View Parameters - self.level = -1 - self.origin = origin - self.width = width - self.height = height - self.h_res = 1000 - self.v_res = 1000 - self.aspectLock = True - self.basis = 'xy' - - # Geometry Plot - self.colorby = 'material' - self.masking = True - self.maskBackground = (0, 0, 0) - self.highlighting = False - self.highlightBackground = (80, 80, 80) - self.highlightAlpha = 0.5 - self.highlightSeed = 1 - self.domainBackground = (50, 50, 50) - self.overlap_color = (255, 0, 0) - self.domainAlpha = 1.0 - self.domainVisible = True - self.outlines = False - self.colormaps = {'temperature': 'Oranges', 'density': 'Greys'} - # set defaults for color dialog - self.data_minmax = {prop: (0.0, 0.0) for prop in _MODEL_PROPERTIES} - self.user_minmax = {prop: (0.0, 0.0) for prop in _MODEL_PROPERTIES} - self.use_custom_minmax = {prop: False for prop in _MODEL_PROPERTIES} - self.data_indicator_enabled = {prop: False for prop in _MODEL_PROPERTIES} - self.color_scale_log = {prop: False for prop in _MODEL_PROPERTIES} - # Get model domain info - self.cells = self.getDomains('cell') - self.materials = self.getDomains('material') - - # Tally Viz Settings - self.tallyDataColormap = 'spectral' - self.tallyDataVisible = True - self.tallyDataAlpha = 1.0 - self.tallyDataIndicator = False - self.tallyDataUserMinMax = False - self.tallyDataMin = 0.0 - self.tallyDataMax = np.inf - self.tallyDataLogScale = False - self.tallyMaskZeroValues = False - self.clipTallyData = False - self.tallyValue = "Mean" - self.tallyContours = False - self.tallyContourLevels = "" - self.selectedTally = None - - def __hash__(self): - return hash(self.__dict__.__str__() + self.__str__()) - - @staticmethod - def getDomains(domain_type): - """ Return dictionary of domain settings. - - Retrieve cell or material ID numbers and names from .xml files - and convert to DomainView instances with default view settings. - - Parameters - ---------- - domain_type : {'cell', 'material'} - Type of domain to retrieve for dictionary + if restore_view is not None: + # View Parameters + self.level = restore_view.level + self.origin = restore_view.origin + self.width = restore_view.width + self.height = restore_view.height + self.h_res = restore_view.h_res + self.v_res = restore_view.v_res + self.aspectLock = restore_view.aspectLock + self.basis = restore_view.basis + + # Geometry Plot + self.colorby = restore_view.colorby + self.masking = restore_view.masking + self.maskBackground = restore_view.maskBackground + self.highlighting = restore_view.highlighting + self.highlightBackground = restore_view.highlightBackground + self.highlightAlpha = restore_view.highlightAlpha + self.highlightSeed = restore_view.highlightSeed + self.domainBackground = restore_view.domainBackground + self.overlap_color = restore_view.overlap_color + self.domainAlpha = restore_view.domainAlpha + self.domainVisible = restore_view.domainVisible + self.outlines = restore_view.outlines + self.colormaps = restore_view.colormaps + # set defaults for color dialog + self.data_minmax = restore_view.data_minmax + self.user_minmax = restore_view.user_minmax + self.use_custom_minmax =restore_view.use_custom_minmax + self.data_indicator_enabled =restore_view.data_indicator_enabled + self.color_scale_log = restore_view.color_scale_log + + # Tally Viz Settings + self.tallyDataColormap =restore_view.tallyDataColormap + self.tallyDataVisible =restore_view.tallyDataVisible + self.tallyDataAlpha =restore_view.tallyDataAlpha + self.tallyDataIndicator =restore_view.tallyDataIndicator + self.tallyDataUserMinMax = restore_view.tallyDataUserMinMax + self.tallyDataMin =restore_view.tallyDataMin + self.tallyDataMax =restore_view.tallyDataMax + self.tallyDataLogScale =restore_view.tallyDataLogScale + self.tallyMaskZeroValues = restore_view.tallyMaskZeroValues + self.clipTallyData = restore_view.clipTallyData + self.tallyValue = restore_view.tallyValue + self.tallyContours = restore_view.tallyContours + self.tallyContourLevels =restore_view.tallyContourLevels - Returns - ------- - domains : Dictionary of DomainView instances - Dictionary of cell/material DomainView instances keyed by ID - """ - - if domain_type not in ('cell', 'material'): - raise ValueError("Domain type, {}, requested is neither " - "'cell' nor 'material'.".format(domain_type)) - - lib_domain = None - if domain_type == 'cell': - lib_domain = openmc.lib.cells - elif domain_type == 'material': - lib_domain = openmc.lib.materials - - domains = {} - for domain, domain_obj in lib_domain.items(): - name = domain_obj.name - domains[domain] = DomainView(domain, name, random_rgb()) - - # always add void to a material domain at the end - if domain_type == 'material': - void_id = _VOID_REGION - domains[void_id] = DomainView(void_id, "VOID", - (255, 255, 255), - False, - False) - - return domains + else: + # set defaults + # View Parameters + self.level = -1 + self.origin = origin + self.width = width + self.height = height + self.h_res = 1000 + self.v_res = 1000 + self.aspectLock = True + self.basis = 'xy' + + # Geometry Plot + self.colorby = 'material' + self.masking = True + self.maskBackground = (0, 0, 0) + self.highlighting = False + self.highlightBackground = (80, 80, 80) + self.highlightAlpha = 0.5 + self.highlightSeed = 1 + self.domainBackground = (50, 50, 50) + self.overlap_color = (255, 0, 0) + self.domainAlpha = 1.0 + self.domainVisible = True + self.outlines = False + self.colormaps = {'temperature': 'Oranges', 'density': 'Greys'} + # set defaults for color dialog + self.data_minmax = {prop: (0.0, 0.0) for prop in _MODEL_PROPERTIES} + self.user_minmax = {prop: (0.0, 0.0) for prop in _MODEL_PROPERTIES} + self.use_custom_minmax = {prop: False for prop in _MODEL_PROPERTIES} + self.data_indicator_enabled = {prop: False for prop in _MODEL_PROPERTIES} + self.color_scale_log = {prop: False for prop in _MODEL_PROPERTIES} + + # Tally Viz Settings + self.tallyDataColormap = 'spectral' + self.tallyDataVisible = True + self.tallyDataAlpha = 1.0 + self.tallyDataIndicator = False + self.tallyDataUserMinMax = False + self.tallyDataMin = 0.0 + self.tallyDataMax = np.inf + self.tallyDataLogScale = False + self.tallyMaskZeroValues = False + self.clipTallyData = False + self.tallyValue = "Mean" + self.tallyContours = False + self.tallyContourLevels = "" def getDataLimits(self): return self.data_minmax @@ -897,6 +921,75 @@ def adopt_plotbase(self, view): self.v_res = self.v_res self.basis = view.basis +class PlotView(PlotViewIndependent): + """ View settings for OpenMC plot. + + Attributes + ---------- + cells : Dict of DomainView instances + Dictionary of cell view settings by ID + materials : Dict of DomainView instances + Dictionary of material view settings by ID + selectedTally : str + Label of the currently selected tally + """ + + def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): + """ Initialize PlotView attributes """ + super().__init__(origin=origin, width=width, height=height, restore_view=restore_view) + + # Get model domain info + self.cells = self.getDomains('cell') + self.materials = self.getDomains('material') + self.selectedTally = None + + def __hash__(self): + return hash(self.__dict__.__str__() + self.__str__()) + + @staticmethod + def getDomains(domain_type): + """ Return dictionary of domain settings. + + Retrieve cell or material ID numbers and names from .xml files + and convert to DomainView instances with default view settings. + + Parameters + ---------- + domain_type : {'cell', 'material'} + Type of domain to retrieve for dictionary + + Returns + ------- + domains : Dictionary of DomainView instances + Dictionary of cell/material DomainView instances keyed by ID + """ + + if domain_type not in ('cell', 'material'): + raise ValueError("Domain type, {}, requested is neither " + "'cell' nor 'material'.".format(domain_type)) + + lib_domain = None + if domain_type == 'cell': + lib_domain = openmc.lib.cells + elif domain_type == 'material': + lib_domain = openmc.lib.materials + + domains = {} + for domain, domain_obj in lib_domain.items(): + name = domain_obj.name + domains[domain] = DomainView(domain, name, random_rgb()) + + # always add void to a material domain at the end + if domain_type == 'material': + void_id = _VOID_REGION + domains[void_id] = DomainView(void_id, "VOID", + (255, 255, 255), + False, + False) + + return domains + + class DomainView(): """ Represents view settings for OpenMC cell or material. From a2535996b225366941b1618db6db006cd3a5dea3 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 9 Jun 2022 16:05:37 -0500 Subject: [PATCH 02/32] remove commented lines and functions that are no longer needed --- openmc_plotter/main_window.py | 69 +---------------------------------- openmc_plotter/plotmodel.py | 9 ++++- 2 files changed, 8 insertions(+), 70 deletions(-) diff --git a/openmc_plotter/main_window.py b/openmc_plotter/main_window.py index cc391ab..caba7e2 100755 --- a/openmc_plotter/main_window.py +++ b/openmc_plotter/main_window.py @@ -41,17 +41,6 @@ def _openmcReload(threads=None): openmc.lib.init(args) openmc.lib.settings.verbosity = 1 -def hash_file(filename): - # return the md5 hash of a file - h = hashlib.md5() - with open(filename,'rb') as file: - chunk = 0 - while chunk != b'': - # read 32768 bytes at a time - chunk = file.read(32768) - h.update(chunk) - return h.hexdigest() - class MainWindow(QMainWindow): def __init__(self, font=QtGui.QFontMetrics(QtGui.QFont()), @@ -62,7 +51,7 @@ def __init__(self, self.font_metric = font self.setWindowTitle('OpenMC Plot Explorer') - def loadGui(self, use_settings_pkl=True, use_saved_view=True): + def loadGui(self, use_settings_pkl=True): self.pixmap = None self.zoom = 100 @@ -465,11 +454,7 @@ def loadModel(self, reload=False, use_settings_pkl=True): if reload: self.resetModels() else: - #if use_settings_pkl: - # self.restoreModelSettings() self.model = PlotModel(use_settings_pkl) - # create new plot model - # update plot and model settings self.updateRelativeBases() @@ -1078,51 +1063,6 @@ def restoreWindowSettings(self): self.colorDialog.setVisible(is_visible) - def restoreModelSettings(self): - if os.path.isfile("plot_settings.pkl"): - - with open('plot_settings.pkl', 'rb') as file: - model = pickle.load(file) - - # # check if loaded cell/mat ids hash match the pkl file: - # current_mat_xml_hash = hash_file('materials.xml') - # current_geom_xml_hash = hash_file('geometry.xml') - # if (current_mat_xml_hash != model.mat_xml_hash) or \ - # (current_geom_xml_hash != model.geom_xml_hash): - # # hashes do not match so ignore plot_settings.pkl file - # msg_box = QMessageBox() - # msg = "WARNING: Model has changed since storing plot " +\ - # "settings. Ignoring previous plot settings." - # msg_box.setText(msg) - # msg_box.setIcon(QMessageBox.Warning) - # msg_box.setStandardButtons(QMessageBox.Ok) - # msg_box.exec_() - # return - - # do not replace model if the version is out of date - if model.version != self.model.version: - print("WARNING: previous plot settings are for a different " - "version of the GUI. They will be ignored.") - wrn_msg = "Existing version: {}, Current GUI version: {}" - print(wrn_msg.format(model.version, self.model.version)) - return - - try: - self.model.statepoint = model.statepoint - except OSError: - msg_box = QMessageBox() - msg = "Could not open statepoint file: \n\n {} \n" - msg_box.setText(msg.format(self.model.statepoint.filename)) - msg_box.setIcon(QMessageBox.Warning) - msg_box.setStandardButtons(QMessageBox.Ok) - msg_box.exec_() - self.model.statepoint = None - - self.model.currentView = PlotView(restore_view=model.currentView) - self.model.activeView = copy.deepcopy(model.currentView) - self.model.previousViews = model.previousViews - self.model.subsequentViews = model.subsequentViews - def resetModels(self): self.cellsModel = DomainTableModel(self.model.activeView.cells) self.materialsModel = DomainTableModel(self.model.activeView.materials) @@ -1219,18 +1159,11 @@ def saveSettings(self): if len(self.model.subsequentViews) > 10: self.model.subsequentViews = self.model.subsequentViews[-10:] - # get hashes for geometry.xml and material.xml at close - self.model.mat_xml_hash = hash_file('materials.xml') - self.model.geom_xml_hash = hash_file('geometry.xml') - with open('plot_settings.pkl', 'wb') as file: if self.model.statepoint: self.model.statepoint.close() pickle.dump(self.model, file) - #with open('view_settings.pkl', 'wb') as file: - # pickle.dump(self.model.currentView, file) - def exportTallyData(self): # show export tool dialog self.showExportDialog() diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 36647b7..47038b3 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -684,7 +684,7 @@ def _do_op(array, tally_value, ax=0): class PlotViewIndependent(openmc.lib.plot._PlotBase): - """ View settings for OpenMC plot, independent of the model. + """View settings for OpenMC plot, independent of the model. Parameters ---------- @@ -694,6 +694,8 @@ class PlotViewIndependent(openmc.lib.plot._PlotBase): Width of plot view in model units height : float Height of plot view in model units + restore_view : PlotView or PlotViewIndependent or None + view object with specified parameters to restore Attributes ---------- @@ -770,6 +772,8 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): super().__init__() if restore_view is not None: + # set parameters based on supplied view + # View Parameters self.level = restore_view.level self.origin = restore_view.origin @@ -818,6 +822,7 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): else: # set defaults + # View Parameters self.level = -1 self.origin = origin @@ -922,7 +927,7 @@ def adopt_plotbase(self, view): self.basis = view.basis class PlotView(PlotViewIndependent): - """ View settings for OpenMC plot. + """Setup the view of the model. Attributes ---------- From 0c6d89fa2569cb1d88145cc37c92fe9021305476 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 13 Jun 2022 11:51:38 -0500 Subject: [PATCH 03/32] remove unnecessary import --- openmc_plotter/plotmodel.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 47038b3..b514ee0 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -1,7 +1,6 @@ from ast import literal_eval from collections import defaultdict import copy -from difflib import restore import itertools import threading import os From 7ce9e4b0a2b66af773552a7327955cf1e4d497ad Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 22 Jun 2022 10:37:20 -0500 Subject: [PATCH 04/32] remove missed print statement Co-authored-by: Paul Romano --- openmc_plotter/main_window.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openmc_plotter/main_window.py b/openmc_plotter/main_window.py index caba7e2..2c0462a 100755 --- a/openmc_plotter/main_window.py +++ b/openmc_plotter/main_window.py @@ -119,8 +119,6 @@ def loadGui(self, use_settings_pkl=True): QtCore.QTimer.singleShot(0, self.showCurrentView) self.plotIm.frozen = False - #print(dir(self.model)) - def event(self, event): # use pinch event to update zoom From 5ee873b27ab76eec28e9ef6b614465d9c5e6d25b Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 22 Jun 2022 14:02:52 -0500 Subject: [PATCH 05/32] more streamlined to use composition over inheritance --- openmc_plotter/plotmodel.py | 186 ++++++++++++++++-------------------- 1 file changed, 83 insertions(+), 103 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index b514ee0..6a7961c 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -1,6 +1,7 @@ from ast import literal_eval from collections import defaultdict import copy +from curses import resize_term import itertools import threading import os @@ -147,7 +148,7 @@ def __init__(self, use_settings_pkl): msg_box.exec_() self.statepoint = None - self.defaultView = PlotView(restore_view=view) + self.defaultView = PlotView(restore_view=view.view_ind) else: self.defaultView = self.getDefaultView() @@ -227,8 +228,8 @@ def makePlot(self): """ cv = self.currentView = copy.deepcopy(self.activeView) - ids = openmc.lib.id_map(cv) - props = openmc.lib.property_map(cv) + ids = openmc.lib.id_map(cv.view_ind) + props = openmc.lib.property_map(cv.view_ind) self.cell_ids = ids[:, :, 0] self.instances = ids[:, :, 1] @@ -765,108 +766,58 @@ class PlotViewIndependent(openmc.lib.plot._PlotBase): tallyContourLevels : str Number of contours levels or explicit level values """ - def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): + def __init__(self, origin=(0, 0, 0), width=10, height=10): """ Initialize PlotView attributes """ super().__init__() - if restore_view is not None: - # set parameters based on supplied view - - # View Parameters - self.level = restore_view.level - self.origin = restore_view.origin - self.width = restore_view.width - self.height = restore_view.height - self.h_res = restore_view.h_res - self.v_res = restore_view.v_res - self.aspectLock = restore_view.aspectLock - self.basis = restore_view.basis - - # Geometry Plot - self.colorby = restore_view.colorby - self.masking = restore_view.masking - self.maskBackground = restore_view.maskBackground - self.highlighting = restore_view.highlighting - self.highlightBackground = restore_view.highlightBackground - self.highlightAlpha = restore_view.highlightAlpha - self.highlightSeed = restore_view.highlightSeed - self.domainBackground = restore_view.domainBackground - self.overlap_color = restore_view.overlap_color - self.domainAlpha = restore_view.domainAlpha - self.domainVisible = restore_view.domainVisible - self.outlines = restore_view.outlines - self.colormaps = restore_view.colormaps - # set defaults for color dialog - self.data_minmax = restore_view.data_minmax - self.user_minmax = restore_view.user_minmax - self.use_custom_minmax =restore_view.use_custom_minmax - self.data_indicator_enabled =restore_view.data_indicator_enabled - self.color_scale_log = restore_view.color_scale_log - - # Tally Viz Settings - self.tallyDataColormap =restore_view.tallyDataColormap - self.tallyDataVisible =restore_view.tallyDataVisible - self.tallyDataAlpha =restore_view.tallyDataAlpha - self.tallyDataIndicator =restore_view.tallyDataIndicator - self.tallyDataUserMinMax = restore_view.tallyDataUserMinMax - self.tallyDataMin =restore_view.tallyDataMin - self.tallyDataMax =restore_view.tallyDataMax - self.tallyDataLogScale =restore_view.tallyDataLogScale - self.tallyMaskZeroValues = restore_view.tallyMaskZeroValues - self.clipTallyData = restore_view.clipTallyData - self.tallyValue = restore_view.tallyValue - self.tallyContours = restore_view.tallyContours - self.tallyContourLevels =restore_view.tallyContourLevels - - else: - # set defaults - - # View Parameters - self.level = -1 - self.origin = origin - self.width = width - self.height = height - self.h_res = 1000 - self.v_res = 1000 - self.aspectLock = True - self.basis = 'xy' - - # Geometry Plot - self.colorby = 'material' - self.masking = True - self.maskBackground = (0, 0, 0) - self.highlighting = False - self.highlightBackground = (80, 80, 80) - self.highlightAlpha = 0.5 - self.highlightSeed = 1 - self.domainBackground = (50, 50, 50) - self.overlap_color = (255, 0, 0) - self.domainAlpha = 1.0 - self.domainVisible = True - self.outlines = False - self.colormaps = {'temperature': 'Oranges', 'density': 'Greys'} - # set defaults for color dialog - self.data_minmax = {prop: (0.0, 0.0) for prop in _MODEL_PROPERTIES} - self.user_minmax = {prop: (0.0, 0.0) for prop in _MODEL_PROPERTIES} - self.use_custom_minmax = {prop: False for prop in _MODEL_PROPERTIES} - self.data_indicator_enabled = {prop: False for prop in _MODEL_PROPERTIES} - self.color_scale_log = {prop: False for prop in _MODEL_PROPERTIES} - - # Tally Viz Settings - self.tallyDataColormap = 'spectral' - self.tallyDataVisible = True - self.tallyDataAlpha = 1.0 - self.tallyDataIndicator = False - self.tallyDataUserMinMax = False - self.tallyDataMin = 0.0 - self.tallyDataMax = np.inf - self.tallyDataLogScale = False - self.tallyMaskZeroValues = False - self.clipTallyData = False - self.tallyValue = "Mean" - self.tallyContours = False - self.tallyContourLevels = "" + # set defaults + + # View Parameters + self.level = -1 + self.origin = origin + self.width = width + self.height = height + self.h_res = 1000 + self.v_res = 1000 + self.aspectLock = True + self.basis = 'xy' + + # Geometry Plot + self.colorby = 'material' + self.masking = True + self.maskBackground = (0, 0, 0) + self.highlighting = False + self.highlightBackground = (80, 80, 80) + self.highlightAlpha = 0.5 + self.highlightSeed = 1 + self.domainBackground = (50, 50, 50) + self.overlap_color = (255, 0, 0) + self.domainAlpha = 1.0 + self.domainVisible = True + self.outlines = False + self.colormaps = {'temperature': 'Oranges', 'density': 'Greys'} + # set defaults for color dialog + self.data_minmax = {prop: (0.0, 0.0) for prop in _MODEL_PROPERTIES} + self.user_minmax = {prop: (0.0, 0.0) for prop in _MODEL_PROPERTIES} + self.use_custom_minmax = {prop: False for prop in _MODEL_PROPERTIES} + self.data_indicator_enabled = {prop: False for prop in _MODEL_PROPERTIES} + self.color_scale_log = {prop: False for prop in _MODEL_PROPERTIES} + + # Tally Viz Settings + self.tallyDataColormap = 'spectral' + self.tallyDataVisible = True + self.tallyDataAlpha = 1.0 + self.tallyDataIndicator = False + self.tallyDataUserMinMax = False + self.tallyDataMin = 0.0 + self.tallyDataMax = np.inf + self.tallyDataLogScale = False + self.tallyMaskZeroValues = False + self.clipTallyData = False + self.tallyValue = "Mean" + self.tallyContours = False + self.tallyContourLevels = "" def getDataLimits(self): return self.data_minmax @@ -925,7 +876,7 @@ def adopt_plotbase(self, view): self.v_res = self.v_res self.basis = view.basis -class PlotView(PlotViewIndependent): +class PlotView(): """Setup the view of the model. Attributes @@ -940,13 +891,42 @@ class PlotView(PlotViewIndependent): def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): """ Initialize PlotView attributes """ - super().__init__(origin=origin, width=width, height=height, restore_view=restore_view) + + if restore_view is not None: + self.view_ind = copy.copy(restore_view) + else: + self.view_ind = PlotViewIndependent(origin=origin, width=width, height=height) # Get model domain info self.cells = self.getDomains('cell') self.materials = self.getDomains('material') self.selectedTally = None + #@property # do property and setter for every attribute + #def basis(self): + # return self.view_ind.basis +# + #@basis.setter + #def basis(self, basis): + # self.view_ind.basis = basis + + def __getattr__(self, name): + if name in ['view_ind', 'cells', 'materials', 'selectedTally']: + if name not in self.__dict__: + raise AttributeError('error') + return self.__dict__[name] + #print(name, type(self.view_ind)) + return getattr(self.view_ind, name) + + def __setattr__(self, name, value): + #if name == 'view_ind': + # return + if name in ['view_ind', 'cells', 'materials', 'selectedTally']: + #self.__dict__[name] = value + super().__setattr__(name, value) + else: + setattr(self.view_ind, name, value) + def __hash__(self): return hash(self.__dict__.__str__() + self.__str__()) From 1b187f79831c72c313edaa5c641affb89ba1746a Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 22 Jun 2022 16:14:52 -0500 Subject: [PATCH 06/32] trying to asses view equality and populating ids --- openmc_plotter/plotmodel.py | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 6a7961c..6634db2 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -228,12 +228,21 @@ def makePlot(self): """ cv = self.currentView = copy.deepcopy(self.activeView) - ids = openmc.lib.id_map(cv.view_ind) - props = openmc.lib.property_map(cv.view_ind) - - self.cell_ids = ids[:, :, 0] - self.instances = ids[:, :, 1] - self.mat_ids = ids[:, :, 2] + pv = self.previousViews[-1] # pv will always be at least 1 to store current views, so only do this if len > 1 + print(cv.view_ind == pv.view_ind) + + if (len(self.previousViews) == 1 and cv.view_ind == pv.view_ind) or \ + (cv.view_ind != pv.view_ind): + print('here') + # we are at the first view and need to populate OR view has changed and need to populate + ids = openmc.lib.id_map(cv.view_ind) + props = openmc.lib.property_map(cv.view_ind) + self.cell_ids = ids[:, :, 0] + self.instances = ids[:, :, 1] + self.mat_ids = ids[:, :, 2] + else: + # take ids from last view?? + pass # set model ids based on domain if cv.colorby == 'cell': @@ -805,7 +814,7 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10): self.color_scale_log = {prop: False for prop in _MODEL_PROPERTIES} # Tally Viz Settings - self.tallyDataColormap = 'spectral' + self.tallyDataColormap = 'Spectral' self.tallyDataVisible = True self.tallyDataAlpha = 1.0 self.tallyDataIndicator = False @@ -819,6 +828,16 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10): self.tallyContours = False self.tallyContourLevels = "" + def __eq__(self, other): + if (isinstance(other, PlotViewIndependent)): + for name in self.__dict__: + if self.__dict__[name] != other.__dict__[name]: + print(name) + return False + return True + else: + return False + def getDataLimits(self): return self.data_minmax From 748baf8923b8801d2a419d35f734b8d39130bebf Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 23 Jun 2022 13:32:26 -0500 Subject: [PATCH 07/32] trying to separate just the view parameters from the rest of view independent - this does not work yet --- openmc_plotter/plotmodel.py | 93 +++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 35 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 6634db2..44711c0 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -107,6 +107,10 @@ def __init__(self, use_settings_pkl): self.ids = None self.instances = None + # ID and Props (curren) + self.__ids_map = None + self.__props_map = None + self.version = __VERSION__ # default statepoint value @@ -231,18 +235,19 @@ def makePlot(self): pv = self.previousViews[-1] # pv will always be at least 1 to store current views, so only do this if len > 1 print(cv.view_ind == pv.view_ind) - if (len(self.previousViews) == 1 and cv.view_ind == pv.view_ind) or \ - (cv.view_ind != pv.view_ind): - print('here') + if (self.__props_map is None) or (self.__ids_map is None) or (cv.view_ind != pv.view_ind): + print('generating new') # we are at the first view and need to populate OR view has changed and need to populate - ids = openmc.lib.id_map(cv.view_ind) - props = openmc.lib.property_map(cv.view_ind) - self.cell_ids = ids[:, :, 0] - self.instances = ids[:, :, 1] - self.mat_ids = ids[:, :, 2] + self.__ids_map = openmc.lib.id_map(cv.view_ind) + self.__props_map = openmc.lib.property_map(cv.view_ind) + self.cell_ids = self.__ids_map[:, :, 0] + self.instances = self.__ids_map[:, :, 1] + self.mat_ids = self.__ids_map[:, :, 2] else: - # take ids from last view?? - pass + print('no change') + print(cv.view_ind.__dict__) + print(pv.view_ind.__dict__) + #print(self.__ids_map) # set model ids based on domain if cv.colorby == 'cell': @@ -283,7 +288,7 @@ def makePlot(self): # set model image self.image = image # set model properties - self.properties = props + self.properties = self.__props_map # tally data self.tally_data = None @@ -691,8 +696,31 @@ def _do_op(array, tally_value, ax=0): return image_data, extents, data_min, data_max +class ViewParam(openmc.lib.plot._PlotBase): + def __init__(self, origin=(0, 0, 0), width=10, height=10): + super().__init__() + # View Parameters + self.level = -1 + self.origin = origin + self.width = width + self.height = height + self.h_res = 1000 + self.v_res = 1000 + self.basis = 'xy' + self.aspectLock = True + + def __eq__(self, other): + if (isinstance(other, ViewParam)): + print(sorted(self.__dict__)) + for name in self.__dict__: + if self.__dict__[name] != other.__dict__[name]: + return False + return True + else: + return False -class PlotViewIndependent(openmc.lib.plot._PlotBase): + +class PlotViewIndependent(): """View settings for OpenMC plot, independent of the model. Parameters @@ -778,10 +806,11 @@ class PlotViewIndependent(openmc.lib.plot._PlotBase): def __init__(self, origin=(0, 0, 0), width=10, height=10): """ Initialize PlotView attributes """ - super().__init__() - # set defaults + self.view_params = ViewParam(origin=origin, width=width, height=height) + # set defaults + """ # View Parameters self.level = -1 self.origin = origin @@ -789,8 +818,9 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10): self.height = height self.h_res = 1000 self.v_res = 1000 - self.aspectLock = True self.basis = 'xy' + self.aspectLock = True + """ # Geometry Plot self.colorby = 'material' @@ -828,15 +858,20 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10): self.tallyContours = False self.tallyContourLevels = "" - def __eq__(self, other): - if (isinstance(other, PlotViewIndependent)): - for name in self.__dict__: - if self.__dict__[name] != other.__dict__[name]: - print(name) - return False - return True + def __getattr__(self, name): + if name in ['level', 'origin', 'width', 'height', + 'h_res', 'v_res', 'basis']: + return getattr(self.view_params, name) + if name not in self.__dict__: + raise AttributeError('{} not in PlotViewIndependent dict'.format(name)) + return self.__dict__[name] + + def __setattr__(self, name, value): + if name in ['level', 'origin', 'width', 'height', + 'h_res', 'v_res', 'basis']: + setattr(self.view_params, name, value) else: - return False + super().__setattr__(name, value) def getDataLimits(self): return self.data_minmax @@ -921,27 +956,15 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): self.materials = self.getDomains('material') self.selectedTally = None - #@property # do property and setter for every attribute - #def basis(self): - # return self.view_ind.basis -# - #@basis.setter - #def basis(self, basis): - # self.view_ind.basis = basis - def __getattr__(self, name): if name in ['view_ind', 'cells', 'materials', 'selectedTally']: if name not in self.__dict__: raise AttributeError('error') return self.__dict__[name] - #print(name, type(self.view_ind)) return getattr(self.view_ind, name) def __setattr__(self, name, value): - #if name == 'view_ind': - # return if name in ['view_ind', 'cells', 'materials', 'selectedTally']: - #self.__dict__[name] = value super().__setattr__(name, value) else: setattr(self.view_ind, name, value) From b130f620f385a03d13b4e78233129a9b91bc1665 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 23 Jun 2022 16:10:08 -0500 Subject: [PATCH 08/32] separate out only the _PlotBase parameters and check those --- openmc_plotter/plotmodel.py | 52 +++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 44711c0..d586acd 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -230,24 +230,28 @@ def makePlot(self): Creates corresponding .xml files from user-chosen settings. Runs OpenMC in plot mode to generate new plot image. """ - cv = self.currentView = copy.deepcopy(self.activeView) pv = self.previousViews[-1] # pv will always be at least 1 to store current views, so only do this if len > 1 - print(cv.view_ind == pv.view_ind) - if (self.__props_map is None) or (self.__ids_map is None) or (cv.view_ind != pv.view_ind): - print('generating new') + print('*** NEW CALL TO MAKEPLOT ***') + print(cv.view_params == pv.view_params) + print('Previous View Parameters') + print(pv.view_params) + print('Current View Parameters') + print(cv.view_params) + + if (self.__props_map is None) or (self.__ids_map is None) or (cv.view_params != pv.view_params): + print('generating new id/prop map') # we are at the first view and need to populate OR view has changed and need to populate - self.__ids_map = openmc.lib.id_map(cv.view_ind) - self.__props_map = openmc.lib.property_map(cv.view_ind) - self.cell_ids = self.__ids_map[:, :, 0] - self.instances = self.__ids_map[:, :, 1] - self.mat_ids = self.__ids_map[:, :, 2] + self.__ids_map = openmc.lib.id_map(cv.view_params) + self.__props_map = openmc.lib.property_map(cv.view_params) + else: print('no change') - print(cv.view_ind.__dict__) - print(pv.view_ind.__dict__) - #print(self.__ids_map) + + self.cell_ids = self.__ids_map[:, :, 0] + self.instances = self.__ids_map[:, :, 1] + self.mat_ids = self.__ids_map[:, :, 2] # set model ids based on domain if cv.colorby == 'cell': @@ -707,18 +711,27 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10): self.h_res = 1000 self.v_res = 1000 self.basis = 'xy' - self.aspectLock = True + self.color_overlaps = False def __eq__(self, other): if (isinstance(other, ViewParam)): - print(sorted(self.__dict__)) - for name in self.__dict__: - if self.__dict__[name] != other.__dict__[name]: + for name in ['level', 'origin', 'width', 'height', 'h_res', + 'v_res', 'basis', 'color_overlaps']: + if self.__getattr__(name) != other.__getattr__(name): return False return True else: return False + def __getattr__(self, name): + if name not in self.__dict__: + raise AttributeError('{} not in ViewParam dict'.format(name)) + return self.__dict__[name] + + def __setattr__(self, name, value): + super().__setattr__(name, value) + self.__dict__[name] = value + class PlotViewIndependent(): """View settings for OpenMC plot, independent of the model. @@ -821,6 +834,7 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10): self.basis = 'xy' self.aspectLock = True """ + self.aspectLock = True # Geometry Plot self.colorby = 'material' @@ -860,7 +874,7 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10): def __getattr__(self, name): if name in ['level', 'origin', 'width', 'height', - 'h_res', 'v_res', 'basis']: + 'h_res', 'v_res', 'basis', 'color_overlaps']: return getattr(self.view_params, name) if name not in self.__dict__: raise AttributeError('{} not in PlotViewIndependent dict'.format(name)) @@ -868,7 +882,7 @@ def __getattr__(self, name): def __setattr__(self, name, value): if name in ['level', 'origin', 'width', 'height', - 'h_res', 'v_res', 'basis']: + 'h_res', 'v_res', 'basis', 'color_overlaps']: setattr(self.view_params, name, value) else: super().__setattr__(name, value) @@ -959,7 +973,7 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): def __getattr__(self, name): if name in ['view_ind', 'cells', 'materials', 'selectedTally']: if name not in self.__dict__: - raise AttributeError('error') + raise AttributeError('{} not in PlotView dict'.format(name)) return self.__dict__[name] return getattr(self.view_ind, name) From 95ef00e98cff423c82339407019ec1be649ef4b4 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Fri, 24 Jun 2022 09:13:49 -0500 Subject: [PATCH 09/32] only store necessary info for reload in pickle file --- openmc_plotter/main_window.py | 16 ++++++++-------- openmc_plotter/plotmodel.py | 14 +++++++------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/openmc_plotter/main_window.py b/openmc_plotter/main_window.py index 2c0462a..1c3d2cd 100755 --- a/openmc_plotter/main_window.py +++ b/openmc_plotter/main_window.py @@ -1151,16 +1151,16 @@ def closeEvent(self, event): self.saveSettings() def saveSettings(self): + if self.model.statepoint: + self.model.statepoint.close() - if len(self.model.previousViews) > 10: - self.model.previousViews = self.model.previousViews[-10:] - if len(self.model.subsequentViews) > 10: - self.model.subsequentViews = self.model.subsequentViews[-10:] - + pickle_data = { + 'version': self.model.version, + 'currentView_ind': self.model.currentView.view_ind, + 'statepoint': self.model.statepoint + } with open('plot_settings.pkl', 'wb') as file: - if self.model.statepoint: - self.model.statepoint.close() - pickle.dump(self.model, file) + pickle.dump(pickle_data, file) def exportTallyData(self): # show export tool dialog diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index d586acd..5d4ff9a 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -128,21 +128,21 @@ def __init__(self, use_settings_pkl): if use_settings_pkl and os.path.isfile('plot_settings.pkl'): with open('plot_settings.pkl', 'rb') as file: - model = pickle.load(file) + data = pickle.load(file) # check GUI version - if model.version != self.version: + if data['version'] != self.version: print("WARNING: previous plot settings are for a different " "version of the GUI. They will be ignored.") wrn_msg = "Existing version: {}, Current GUI version: {}" - print(wrn_msg.format(model.version, self.version)) - view = None + print(wrn_msg.format(data['version'], self.version)) + view_ind = None else: - view = model.currentView + view_ind = data['currentView_ind'] # restore statepoint file try: - self.statepoint = model.statepoint + self.statepoint = data['statepoint'] except OSError: msg_box = QMessageBox() msg = "Could not open statepoint file: \n\n {} \n" @@ -152,7 +152,7 @@ def __init__(self, use_settings_pkl): msg_box.exec_() self.statepoint = None - self.defaultView = PlotView(restore_view=view.view_ind) + self.defaultView = PlotView(restore_view=view_ind) else: self.defaultView = self.getDefaultView() From 4d371be9b5908d9289cfd9204edb269521e6d835 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 29 Jun 2022 10:29:00 -0500 Subject: [PATCH 10/32] cleaned up docstrings --- openmc_plotter/plotmodel.py | 70 ++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 5d4ff9a..663a000 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -701,8 +701,42 @@ def _do_op(array, tally_value, ax=0): return image_data, extents, data_min, data_max class ViewParam(openmc.lib.plot._PlotBase): + """Viewer settings that are needed for _PlotBase and are independent + of all other plotter/model settings. + + Parameters + ---------- + origin : 3-tuple of floats + Origin (center) of plot view + width: float + Width of plot view in model units + height : float + Height of plot view in model units + + Attributes + ---------- + origin : 3-tuple of floats + Origin (center) of plot view + width : float + Width of the plot view in model units + height : float + Height of the plot view in model units + h_res : int + Horizontal resolution of plot image + v_res : int + Vertical resolution of plot image + basis : {'xy', 'xz', 'yz'} + The basis directions for the plot + color_overlaps : bool + Indicator of whether or not overlaps will be shown + level : int + The universe level for the plot (default: -1 -> all universes shown) + """ + def __init__(self, origin=(0, 0, 0), width=10, height=10): + """Initialize ViewParam attributes""" super().__init__() + # View Parameters self.level = -1 self.origin = origin @@ -749,21 +783,9 @@ class PlotViewIndependent(): Attributes ---------- - origin : 3-tuple of floats - Origin (center) of plot view - width : float - Width of the plot view in model units - height : float - Height of the plot view in model units - h_res : int - Horizontal resolution of plot image - v_res : int - Vertical resolution of plot image aspectLock : bool Indication of whether aspect lock should be maintained to prevent image stretching/warping - basis : {'xy', 'xz', 'yz'} - The basis directions for the plot colorby : {'cell', 'material', 'temperature', 'density'} Indication of whether the plot should be colored by cell or material masking : bool @@ -781,8 +803,6 @@ class PlotViewIndependent(): is active domainBackground : 3-tuple of int RGB color to apply to plot background - color_overlaps : bool - Indicator of whether or not overlaps will be shown overlap_color : 3-tuple of int RGB color to apply for cell overlap regions domainAlpha : float between 0 and 1 @@ -816,27 +836,13 @@ class PlotViewIndependent(): tallyContourLevels : str Number of contours levels or explicit level values """ - def __init__(self, origin=(0, 0, 0), width=10, height=10): - """ Initialize PlotView attributes """ - + def __init__(self, origin=(0, 0, 0), width=10, height=10): + """Initialize PlotViewIndependent attributes""" self.view_params = ViewParam(origin=origin, width=width, height=height) - # set defaults - """ - # View Parameters - self.level = -1 - self.origin = origin - self.width = width - self.height = height - self.h_res = 1000 - self.v_res = 1000 - self.basis = 'xy' - self.aspectLock = True - """ - self.aspectLock = True - # Geometry Plot + self.aspectLock = True self.colorby = 'material' self.masking = True self.maskBackground = (0, 0, 0) @@ -958,7 +964,7 @@ class PlotView(): """ def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): - """ Initialize PlotView attributes """ + """Initialize PlotView attributes""" if restore_view is not None: self.view_ind = copy.copy(restore_view) From e9e92a0736a7a3d69c32426ae7a2c9064970aef6 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 6 Jul 2022 14:07:46 -0500 Subject: [PATCH 11/32] make view params attribute on plotview to simplify --- openmc_plotter/plotmodel.py | 48 ++++++++++--------------------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 663a000..cda8242 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -748,25 +748,11 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10): self.color_overlaps = False def __eq__(self, other): - if (isinstance(other, ViewParam)): - for name in ['level', 'origin', 'width', 'height', 'h_res', - 'v_res', 'basis', 'color_overlaps']: - if self.__getattr__(name) != other.__getattr__(name): - return False + if repr(self) == repr(other): return True else: return False - def __getattr__(self, name): - if name not in self.__dict__: - raise AttributeError('{} not in ViewParam dict'.format(name)) - return self.__dict__[name] - - def __setattr__(self, name, value): - super().__setattr__(name, value) - self.__dict__[name] = value - - class PlotViewIndependent(): """View settings for OpenMC plot, independent of the model. @@ -837,10 +823,8 @@ class PlotViewIndependent(): Number of contours levels or explicit level values """ - def __init__(self, origin=(0, 0, 0), width=10, height=10): + def __init__(self): """Initialize PlotViewIndependent attributes""" - self.view_params = ViewParam(origin=origin, width=width, height=height) - # Geometry Plot self.aspectLock = True self.colorby = 'material' @@ -878,21 +862,6 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10): self.tallyContours = False self.tallyContourLevels = "" - def __getattr__(self, name): - if name in ['level', 'origin', 'width', 'height', - 'h_res', 'v_res', 'basis', 'color_overlaps']: - return getattr(self.view_params, name) - if name not in self.__dict__: - raise AttributeError('{} not in PlotViewIndependent dict'.format(name)) - return self.__dict__[name] - - def __setattr__(self, name, value): - if name in ['level', 'origin', 'width', 'height', - 'h_res', 'v_res', 'basis', 'color_overlaps']: - setattr(self.view_params, name, value) - else: - super().__setattr__(name, value) - def getDataLimits(self): return self.data_minmax @@ -969,7 +938,9 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): if restore_view is not None: self.view_ind = copy.copy(restore_view) else: - self.view_ind = PlotViewIndependent(origin=origin, width=width, height=height) + self.view_ind = PlotViewIndependent() + + self.view_params = ViewParam(origin=origin, width=width, height=height) # Get model domain info self.cells = self.getDomains('cell') @@ -981,11 +952,18 @@ def __getattr__(self, name): if name not in self.__dict__: raise AttributeError('{} not in PlotView dict'.format(name)) return self.__dict__[name] - return getattr(self.view_ind, name) + elif name in ['level', 'origin', 'width', 'height', + 'h_res', 'v_res', 'basis', 'color_overlaps']: + return getattr(self.view_params, name) + else: + return getattr(self.view_ind, name) def __setattr__(self, name, value): if name in ['view_ind', 'cells', 'materials', 'selectedTally']: super().__setattr__(name, value) + elif name in ['level', 'origin', 'width', 'height', + 'h_res', 'v_res', 'basis', 'color_overlaps']: + setattr(self.view_params, name, value) else: setattr(self.view_ind, name, value) From 3e996c9d62f3486dddc95e8d09e0660697b85df9 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 6 Jul 2022 14:11:37 -0500 Subject: [PATCH 12/32] remove debugging print statements --- openmc_plotter/plotmodel.py | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index cda8242..ebe1cc0 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -231,24 +231,15 @@ def makePlot(self): Runs OpenMC in plot mode to generate new plot image. """ cv = self.currentView = copy.deepcopy(self.activeView) - pv = self.previousViews[-1] # pv will always be at least 1 to store current views, so only do this if len > 1 - - print('*** NEW CALL TO MAKEPLOT ***') - print(cv.view_params == pv.view_params) - print('Previous View Parameters') - print(pv.view_params) - print('Current View Parameters') - print(cv.view_params) - - if (self.__props_map is None) or (self.__ids_map is None) or (cv.view_params != pv.view_params): - print('generating new id/prop map') - # we are at the first view and need to populate OR view has changed and need to populate + pv = self.previousViews[-1] + + if (self.__props_map is None) or (self.__ids_map is None) or \ + (cv.view_params != pv.view_params): + # we are at the first view and need to populate OR + # view has changed and need to populate self.__ids_map = openmc.lib.id_map(cv.view_params) self.__props_map = openmc.lib.property_map(cv.view_params) - else: - print('no change') - self.cell_ids = self.__ids_map[:, :, 0] self.instances = self.__ids_map[:, :, 1] self.mat_ids = self.__ids_map[:, :, 2] From eb34f8b1d5ee5f43a2e97a33b8606f9597ccb490 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 7 Jul 2022 13:55:03 -0500 Subject: [PATCH 13/32] need to copy view params from previous view --- openmc_plotter/plotmodel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index ebe1cc0..bda78e9 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -928,10 +928,10 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): if restore_view is not None: self.view_ind = copy.copy(restore_view) + self.view_params = copy.copy(restore_view.view_params) else: self.view_ind = PlotViewIndependent() - - self.view_params = ViewParam(origin=origin, width=width, height=height) + self.view_params = ViewParam(origin=origin, width=width, height=height) # Get model domain info self.cells = self.getDomains('cell') From ac39180d32e98685740880dabcd013c6b5b16a63 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Thu, 7 Jul 2022 14:00:10 -0500 Subject: [PATCH 14/32] updated docstrings for new classes --- openmc_plotter/plotmodel.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index bda78e9..1d53d52 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -747,17 +747,6 @@ def __eq__(self, other): class PlotViewIndependent(): """View settings for OpenMC plot, independent of the model. - Parameters - ---------- - origin : 3-tuple of floats - Origin (center) of plot view - width: float - Width of plot view in model units - height : float - Height of plot view in model units - restore_view : PlotView or PlotViewIndependent or None - view object with specified parameters to restore - Attributes ---------- aspectLock : bool @@ -913,8 +902,23 @@ def adopt_plotbase(self, view): class PlotView(): """Setup the view of the model. + Parameters + ---------- + origin : 3-tuple of floats + Origin (center) of plot view + width: float + Width of plot view in model units + height : float + Height of plot view in model units + restore_view : PlotView or PlotViewIndependent or None + view object with specified parameters to restore + Attributes ---------- + view_ind : PlotViewIndependent instance + viewing parameters that are independent of the model + view_params : ViewParam instance + view parameters necesary for _PlotBase cells : Dict of DomainView instances Dictionary of cell view settings by ID materials : Dict of DomainView instances From 0ff3ed4848a2356ca1753bfd6b9fa696e13b810d Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Fri, 8 Jul 2022 09:40:02 -0500 Subject: [PATCH 15/32] Apply suggestions from code review Co-authored-by: Paul Romano --- openmc_plotter/plotmodel.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 1d53d52..8bd298e 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -739,12 +739,9 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10): self.color_overlaps = False def __eq__(self, other): - if repr(self) == repr(other): - return True - else: - return False + return repr(self) == repr(other) -class PlotViewIndependent(): +class PlotViewIndependent: """View settings for OpenMC plot, independent of the model. Attributes @@ -899,7 +896,7 @@ def adopt_plotbase(self, view): self.v_res = self.v_res self.basis = view.basis -class PlotView(): +class PlotView: """Setup the view of the model. Parameters From ed014f51a1eb422d7357b306be62fec93cb71b4b Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Fri, 8 Jul 2022 10:13:51 -0500 Subject: [PATCH 16/32] issue warning and ignore plot settings if load fails --- openmc_plotter/plotmodel.py | 62 +++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 8bd298e..8b60450 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -127,32 +127,42 @@ def __init__(self, use_settings_pkl): self.subsequentViews = [] if use_settings_pkl and os.path.isfile('plot_settings.pkl'): - with open('plot_settings.pkl', 'rb') as file: - data = pickle.load(file) - - # check GUI version - if data['version'] != self.version: - print("WARNING: previous plot settings are for a different " - "version of the GUI. They will be ignored.") - wrn_msg = "Existing version: {}, Current GUI version: {}" - print(wrn_msg.format(data['version'], self.version)) - view_ind = None - else: - view_ind = data['currentView_ind'] - - # restore statepoint file - try: - self.statepoint = data['statepoint'] - except OSError: - msg_box = QMessageBox() - msg = "Could not open statepoint file: \n\n {} \n" - msg_box.setText(msg.format(self.model.statepoint.filename)) - msg_box.setIcon(QMessageBox.Warning) - msg_box.setStandardButtons(QMessageBox.Ok) - msg_box.exec_() - self.statepoint = None - - self.defaultView = PlotView(restore_view=view_ind) + try: + with open('plot_settings.pkl', 'rb') as file: + data = pickle.load(file) + + # check GUI version + if data['version'] != self.version: + print("WARNING: previous plot settings are for a different " + "version of the GUI. They will be ignored.") + wrn_msg = "Existing version: {}, Current GUI version: {}" + print(wrn_msg.format(data['version'], self.version)) + view_ind = None + else: + view_ind = data['currentView_ind'] + + # restore statepoint file + try: + self.statepoint = data['statepoint'] + except OSError: + msg_box = QMessageBox() + msg = "Could not open statepoint file: \n\n {} \n" + msg_box.setText(msg.format(self.model.statepoint.filename)) + msg_box.setIcon(QMessageBox.Warning) + msg_box.setStandardButtons(QMessageBox.Ok) + msg_box.exec_() + self.statepoint = None + + self.defaultView = PlotView(restore_view=view_ind) + except AttributeError: + msg_box = QMessageBox() + msg = "WARNING: previous plot settings are incorrect format. " +\ + "will be ignored." + msg_box.setText(msg) + msg_box.setIcon(QMessageBox.Warning) + msg_box.setStandardButtons(QMessageBox.Ok) + msg_box.exec_() + self.defaultView = self.getDefaultView() else: self.defaultView = self.getDefaultView() From 81b41bbe2dc0a16c7ce72a9bf78f7b094e1af8b7 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Fri, 8 Jul 2022 10:14:50 -0500 Subject: [PATCH 17/32] typo --- openmc_plotter/plotmodel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 8b60450..895bcd2 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -157,7 +157,7 @@ def __init__(self, use_settings_pkl): except AttributeError: msg_box = QMessageBox() msg = "WARNING: previous plot settings are incorrect format. " +\ - "will be ignored." + "They will be ignored." msg_box.setText(msg) msg_box.setIcon(QMessageBox.Warning) msg_box.setStandardButtons(QMessageBox.Ok) From 8051d2faca90410b3942b39ebe9bc0d625f71ef3 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Fri, 8 Jul 2022 15:01:41 -0500 Subject: [PATCH 18/32] remove mistaken imports --- openmc_plotter/main_window.py | 2 +- openmc_plotter/plotmodel.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/openmc_plotter/main_window.py b/openmc_plotter/main_window.py index 1c3d2cd..77b4ab8 100755 --- a/openmc_plotter/main_window.py +++ b/openmc_plotter/main_window.py @@ -21,7 +21,7 @@ except ImportError: _HAVE_VTK = False -from .plotmodel import PlotModel, DomainTableModel, PlotView +from .plotmodel import PlotModel, DomainTableModel from .plotgui import PlotImage, ColorDialog from .docks import DomainDock, TallyDock from .overlays import ShortcutsOverlay diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 895bcd2..40a0c62 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -1,7 +1,6 @@ from ast import literal_eval from collections import defaultdict import copy -from curses import resize_term import itertools import threading import os From 3ab3f4be0cdfde96dd7c1de47aefe10b86f5456b Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Fri, 8 Jul 2022 15:08:22 -0500 Subject: [PATCH 19/32] ids_map and prop_map don't need to be private --- openmc_plotter/plotmodel.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 40a0c62..d700fa5 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -73,6 +73,10 @@ class PlotModel(): Dictionary mapping material IDs to openmc.Material instances ids : NumPy int array (v_res, h_res, 1) Mapping of plot coordinates to cell/material ID by pixel + ids_map : NumPy int32 array (v_res, h_res, 3) + Mapping of cell and material ids + props_map : Numpy float array (v_res, h_res, 3) + Mapping of cell temperatures and material densities image : NumPy int array (v_res, h_res, 3) The current RGB image data statepoint : StatePointModel @@ -107,8 +111,8 @@ def __init__(self, use_settings_pkl): self.instances = None # ID and Props (curren) - self.__ids_map = None - self.__props_map = None + self.ids_map = None + self.props_map = None self.version = __VERSION__ @@ -242,16 +246,16 @@ def makePlot(self): cv = self.currentView = copy.deepcopy(self.activeView) pv = self.previousViews[-1] - if (self.__props_map is None) or (self.__ids_map is None) or \ + if (self.props_map is None) or (self.ids_map is None) or \ (cv.view_params != pv.view_params): # we are at the first view and need to populate OR # view has changed and need to populate - self.__ids_map = openmc.lib.id_map(cv.view_params) - self.__props_map = openmc.lib.property_map(cv.view_params) + self.ids_map = openmc.lib.id_map(cv.view_params) + self.props_map = openmc.lib.property_map(cv.view_params) - self.cell_ids = self.__ids_map[:, :, 0] - self.instances = self.__ids_map[:, :, 1] - self.mat_ids = self.__ids_map[:, :, 2] + self.cell_ids = self.ids_map[:, :, 0] + self.instances = self.ids_map[:, :, 1] + self.mat_ids = self.ids_map[:, :, 2] # set model ids based on domain if cv.colorby == 'cell': @@ -292,7 +296,7 @@ def makePlot(self): # set model image self.image = image # set model properties - self.properties = self.__props_map + self.properties = self.props_map # tally data self.tally_data = None From 7e3ecd3f21e28c7adf7858b3bb742bf5373fd766 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 11 Jul 2022 09:26:57 -0500 Subject: [PATCH 20/32] wording changes Co-authored-by: Paul Romano Co-authored-by: Patrick Shriwise --- openmc_plotter/plotmodel.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index d700fa5..5f2cb3c 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -110,7 +110,7 @@ def __init__(self, use_settings_pkl): self.ids = None self.instances = None - # ID and Props (curren) + # Return values from id_map and property_map self.ids_map = None self.props_map = None @@ -159,7 +159,7 @@ def __init__(self, use_settings_pkl): self.defaultView = PlotView(restore_view=view_ind) except AttributeError: msg_box = QMessageBox() - msg = "WARNING: previous plot settings are incorrect format. " +\ + msg = "WARNING: previous plot settings are in an incompatible format. " +\ "They will be ignored." msg_box.setText(msg) msg_box.setIcon(QMessageBox.Warning) @@ -916,7 +916,7 @@ class PlotView: ---------- origin : 3-tuple of floats Origin (center) of plot view - width: float + width : float Width of plot view in model units height : float Height of plot view in model units From ca2eab5759edd93ce4a1edcc472eaa4812249cf1 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 11 Jul 2022 09:36:02 -0500 Subject: [PATCH 21/32] need to add view_params to list of attributes Co-authored-by: Paul Romano --- openmc_plotter/plotmodel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 5f2cb3c..b16f7a5 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -953,7 +953,7 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): self.selectedTally = None def __getattr__(self, name): - if name in ['view_ind', 'cells', 'materials', 'selectedTally']: + if name in ['view_ind', 'view_params', 'cells', 'materials', 'selectedTally']: if name not in self.__dict__: raise AttributeError('{} not in PlotView dict'.format(name)) return self.__dict__[name] @@ -964,7 +964,7 @@ def __getattr__(self, name): return getattr(self.view_ind, name) def __setattr__(self, name, value): - if name in ['view_ind', 'cells', 'materials', 'selectedTally']: + if name in ['view_ind', 'view_params', 'cells', 'materials', 'selectedTally']: super().__setattr__(name, value) elif name in ['level', 'origin', 'width', 'height', 'h_res', 'v_res', 'basis', 'color_overlaps']: From 6ad6cde1e4070b6cde957363bb360dccb9bda28c Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 11 Jul 2022 10:40:57 -0500 Subject: [PATCH 22/32] increment plotmodel version --- openmc_plotter/plotmodel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index b16f7a5..d37f68f 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -18,7 +18,7 @@ ID, NAME, COLOR, COLORLABEL, MASK, HIGHLIGHT = tuple(range(0, 6)) -__VERSION__ = "0.2.1" +__VERSION__ = "0.2.2" _VOID_REGION = -1 _NOT_FOUND = -2 From 08a9a382a7c8e19f94cc1829921a60745d501ee1 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 11 Jul 2022 10:44:36 -0500 Subject: [PATCH 23/32] simplify try/except statement --- openmc_plotter/plotmodel.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index d37f68f..613fc0c 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -130,10 +130,20 @@ def __init__(self, use_settings_pkl): self.subsequentViews = [] if use_settings_pkl and os.path.isfile('plot_settings.pkl'): - try: - with open('plot_settings.pkl', 'rb') as file: + with open('plot_settings.pkl', 'rb') as file: + try: data = pickle.load(file) + except AttributeError: + msg_box = QMessageBox() + msg = "WARNING: previous plot settings are in an incompatible format. " +\ + "They will be ignored." + msg_box.setText(msg) + msg_box.setIcon(QMessageBox.Warning) + msg_box.setStandardButtons(QMessageBox.Ok) + msg_box.exec_() + self.defaultView = self.getDefaultView() + else: # check GUI version if data['version'] != self.version: print("WARNING: previous plot settings are for a different " @@ -157,15 +167,7 @@ def __init__(self, use_settings_pkl): self.statepoint = None self.defaultView = PlotView(restore_view=view_ind) - except AttributeError: - msg_box = QMessageBox() - msg = "WARNING: previous plot settings are in an incompatible format. " +\ - "They will be ignored." - msg_box.setText(msg) - msg_box.setIcon(QMessageBox.Warning) - msg_box.setStandardButtons(QMessageBox.Ok) - msg_box.exec_() - self.defaultView = self.getDefaultView() + else: self.defaultView = self.getDefaultView() From 635fbf9a86d380079574fba37c04afcbabdcafa5 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 11 Jul 2022 11:23:06 -0500 Subject: [PATCH 24/32] use_settings_pkl in docstring --- openmc_plotter/plotmodel.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 613fc0c..d9a4e4c 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -63,6 +63,11 @@ class PlotModel(): """ Geometry and plot settings for OpenMC Plot Explorer model + Parameters + ---------- + use_settings_pkl : bool + If True, use plot_settings.pkl file to reload settings + Attributes ---------- geom : openmc.Geometry instance From 9990c726dc966c39e393be453a2284093da9c3af Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 11 Jul 2022 11:28:55 -0500 Subject: [PATCH 25/32] store full currentView so that view_ind and view_params are both saved --- openmc_plotter/main_window.py | 2 +- openmc_plotter/plotmodel.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openmc_plotter/main_window.py b/openmc_plotter/main_window.py index 77b4ab8..e568e07 100755 --- a/openmc_plotter/main_window.py +++ b/openmc_plotter/main_window.py @@ -1156,7 +1156,7 @@ def saveSettings(self): pickle_data = { 'version': self.model.version, - 'currentView_ind': self.model.currentView.view_ind, + 'currentView': self.model.currentView, 'statepoint': self.model.statepoint } with open('plot_settings.pkl', 'wb') as file: diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index d9a4e4c..c6c5667 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -155,9 +155,9 @@ def __init__(self, use_settings_pkl): "version of the GUI. They will be ignored.") wrn_msg = "Existing version: {}, Current GUI version: {}" print(wrn_msg.format(data['version'], self.version)) - view_ind = None + view = None else: - view_ind = data['currentView_ind'] + view = data['currentView'] # restore statepoint file try: @@ -171,7 +171,7 @@ def __init__(self, use_settings_pkl): msg_box.exec_() self.statepoint = None - self.defaultView = PlotView(restore_view=view_ind) + self.defaultView = PlotView(restore_view=view) else: self.defaultView = self.getDefaultView() @@ -927,7 +927,7 @@ class PlotView: Width of plot view in model units height : float Height of plot view in model units - restore_view : PlotView or PlotViewIndependent or None + restore_view : PlotView or None view object with specified parameters to restore Attributes @@ -948,7 +948,7 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): """Initialize PlotView attributes""" if restore_view is not None: - self.view_ind = copy.copy(restore_view) + self.view_ind = copy.copy(restore_view.view_ind) self.view_params = copy.copy(restore_view.view_params) else: self.view_ind = PlotViewIndependent() From 6a5f909d7fdf94173d38ce4f3fed2656de77b13a Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 11 Jul 2022 11:45:09 -0500 Subject: [PATCH 26/32] list of attribures as class attribute --- openmc_plotter/plotmodel.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index c6c5667..21553bb 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -944,6 +944,10 @@ class PlotView: Label of the currently selected tally """ + attrs = ('view_ind', 'view_params', 'cells', 'materials', 'selectedTally') + plotbase_attrs = ('level', 'origin', 'width', 'height', + 'h_res', 'v_res', 'basis', 'color_overlaps') + def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): """Initialize PlotView attributes""" @@ -960,21 +964,19 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): self.selectedTally = None def __getattr__(self, name): - if name in ['view_ind', 'view_params', 'cells', 'materials', 'selectedTally']: + if name in self.attrs: if name not in self.__dict__: raise AttributeError('{} not in PlotView dict'.format(name)) return self.__dict__[name] - elif name in ['level', 'origin', 'width', 'height', - 'h_res', 'v_res', 'basis', 'color_overlaps']: + elif name in self.plotbase_attrs: return getattr(self.view_params, name) else: return getattr(self.view_ind, name) def __setattr__(self, name, value): - if name in ['view_ind', 'view_params', 'cells', 'materials', 'selectedTally']: + if name in self.attrs: super().__setattr__(name, value) - elif name in ['level', 'origin', 'width', 'height', - 'h_res', 'v_res', 'basis', 'color_overlaps']: + elif name in self.plotbase_attrs: setattr(self.view_params, name, value) else: setattr(self.view_ind, name, value) From 05743d80bf00d5f2636879909985430d31d62c89 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 11 Jul 2022 12:06:15 -0500 Subject: [PATCH 27/32] restore domain properties if file hashes are unchanged as well --- openmc_plotter/main_window.py | 11 +++++++--- openmc_plotter/plotmodel.py | 41 ++++++++++++++++++++++++++++++----- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/openmc_plotter/main_window.py b/openmc_plotter/main_window.py index e568e07..d527678 100755 --- a/openmc_plotter/main_window.py +++ b/openmc_plotter/main_window.py @@ -3,7 +3,6 @@ import os import pickle from threading import Thread -import hashlib from PySide2 import QtCore, QtGui from PySide2.QtGui import QKeyEvent @@ -21,7 +20,7 @@ except ImportError: _HAVE_VTK = False -from .plotmodel import PlotModel, DomainTableModel +from .plotmodel import PlotModel, DomainTableModel, hash_file from .plotgui import PlotImage, ColorDialog from .docks import DomainDock, TallyDock from .overlays import ShortcutsOverlay @@ -1154,10 +1153,16 @@ def saveSettings(self): if self.model.statepoint: self.model.statepoint.close() + # get hashes for geometry.xml and material.xml at close + mat_xml_hash = hash_file('materials.xml') + geom_xml_hash = hash_file('geometry.xml') + pickle_data = { 'version': self.model.version, 'currentView': self.model.currentView, - 'statepoint': self.model.statepoint + 'statepoint': self.model.statepoint, + 'mat_xml_hash': mat_xml_hash, + 'geom_xml_hash': geom_xml_hash } with open('plot_settings.pkl', 'wb') as file: pickle.dump(pickle_data, file) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 21553bb..ffd39d4 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -5,6 +5,7 @@ import threading import os import pickle +import hashlib from PySide2.QtWidgets import QItemDelegate, QColorDialog, QLineEdit, QMessageBox from PySide2.QtCore import QAbstractTableModel, QModelIndex, Qt, QSize, QEvent @@ -60,6 +61,16 @@ 'Std. Dev.': 'std_dev', 'Rel. Error': 'rel_err'} +def hash_file(filename): + # return the md5 hash of a file + h = hashlib.md5() + with open(filename,'rb') as file: + chunk = 0 + while chunk != b'': + # read 32768 bytes at a time + chunk = file.read(32768) + h.update(chunk) + return h.hexdigest() class PlotModel(): """ Geometry and plot settings for OpenMC Plot Explorer model @@ -149,6 +160,8 @@ def __init__(self, use_settings_pkl): self.defaultView = self.getDefaultView() else: + restore_domains = False + # check GUI version if data['version'] != self.version: print("WARNING: previous plot settings are for a different " @@ -159,6 +172,14 @@ def __init__(self, use_settings_pkl): else: view = data['currentView'] + # get materials.xml and geometry.xml hashes to + # restore additional settings if possible + mat_xml_hash = hash_file('materials.xml') + geom_xml_hash = hash_file('geometry.xml') + if mat_xml_hash == data['mat_xml_hash'] and \ + geom_xml_hash == data['geom_xml_hash']: + restore_domains = True + # restore statepoint file try: self.statepoint = data['statepoint'] @@ -171,7 +192,8 @@ def __init__(self, use_settings_pkl): msg_box.exec_() self.statepoint = None - self.defaultView = PlotView(restore_view=view) + self.defaultView = PlotView(restore_view=view, + restore_domains=restore_domains) else: self.defaultView = self.getDefaultView() @@ -929,6 +951,9 @@ class PlotView: Height of plot view in model units restore_view : PlotView or None view object with specified parameters to restore + restore_domains : bool (optional) + If True and restore_view is provided, then also restore domain + properties. Default False. Attributes ---------- @@ -948,7 +973,8 @@ class PlotView: plotbase_attrs = ('level', 'origin', 'width', 'height', 'h_res', 'v_res', 'basis', 'color_overlaps') - def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): + def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None, + restore_domains=False): """Initialize PlotView attributes""" if restore_view is not None: @@ -959,9 +985,14 @@ def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None): self.view_params = ViewParam(origin=origin, width=width, height=height) # Get model domain info - self.cells = self.getDomains('cell') - self.materials = self.getDomains('material') - self.selectedTally = None + if restore_domains and restore_view is not None: + self.cells = restore_view.cells + self.materials = restore_view.materials + self.selectedTally = restore_view.selectedTally + else: + self.cells = self.getDomains('cell') + self.materials = self.getDomains('material') + self.selectedTally = None def __getattr__(self, name): if name in self.attrs: From 56e12dd9b02e575664ff68bd1bc1aef25314a987 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 11 Jul 2022 12:10:26 -0500 Subject: [PATCH 28/32] prop_map and properties attributes were redundant --- openmc_plotter/plotmodel.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index ffd39d4..fdebe48 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -91,7 +91,7 @@ class PlotModel(): Mapping of plot coordinates to cell/material ID by pixel ids_map : NumPy int32 array (v_res, h_res, 3) Mapping of cell and material ids - props_map : Numpy float array (v_res, h_res, 3) + properties : Numpy float array (v_res, h_res, 3) Mapping of cell temperatures and material densities image : NumPy int array (v_res, h_res, 3) The current RGB image data @@ -128,7 +128,7 @@ def __init__(self, use_settings_pkl): # Return values from id_map and property_map self.ids_map = None - self.props_map = None + self.properties = None self.version = __VERSION__ @@ -275,12 +275,12 @@ def makePlot(self): cv = self.currentView = copy.deepcopy(self.activeView) pv = self.previousViews[-1] - if (self.props_map is None) or (self.ids_map is None) or \ + if (self.properties is None) or (self.ids_map is None) or \ (cv.view_params != pv.view_params): # we are at the first view and need to populate OR # view has changed and need to populate self.ids_map = openmc.lib.id_map(cv.view_params) - self.props_map = openmc.lib.property_map(cv.view_params) + self.properties = openmc.lib.property_map(cv.view_params) self.cell_ids = self.ids_map[:, :, 0] self.instances = self.ids_map[:, :, 1] @@ -324,8 +324,7 @@ def makePlot(self): # set model image self.image = image - # set model properties - self.properties = self.props_map + # tally data self.tally_data = None From 90bf43501d864c7275100b92dac722e9f7d8bb8f Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 11 Jul 2022 12:27:42 -0500 Subject: [PATCH 29/32] adopt_plotbase must be in PlotView to be able to set params --- openmc_plotter/plotmodel.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index fdebe48..d17c273 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -920,22 +920,6 @@ def urc(self): z = self.origin[2] + self.height / 2.0 return x, y, z - def adopt_plotbase(self, view): - """ - Applies only the geometric aspects of a view to the current view - - Parameters - ---------- - - view : PlotView - View to take parameters from - """ - self.origin = view.origin - self.width = view.width - self.height = view.height - self.h_res = self.h_res - self.v_res = self.v_res - self.basis = view.basis class PlotView: """Setup the view of the model. @@ -1057,6 +1041,23 @@ def getDomains(domain_type): return domains + def adopt_plotbase(self, view): + """ + Applies only the geometric aspects of a view to the current view + + Parameters + ---------- + + view : PlotView + View to take parameters from + """ + self.origin = view.origin + self.width = view.width + self.height = view.height + self.h_res = view.h_res + self.v_res = view.v_res + self.basis = view.basis + class DomainView(): """ Represents view settings for OpenMC cell or material. From 882540558931d9c4eab98d559eaac77e9959a925 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Mon, 11 Jul 2022 12:43:30 -0500 Subject: [PATCH 30/32] make cell_ids, instances, and mat_ids properties --- openmc_plotter/plotmodel.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index d17c273..207a16b 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -124,7 +124,6 @@ def __init__(self, use_settings_pkl): # Cell/Material ID by coordinates self.ids = None - self.instances = None # Return values from id_map and property_map self.ids_map = None @@ -282,10 +281,6 @@ def makePlot(self): self.ids_map = openmc.lib.id_map(cv.view_params) self.properties = openmc.lib.property_map(cv.view_params) - self.cell_ids = self.ids_map[:, :, 0] - self.instances = self.ids_map[:, :, 1] - self.mat_ids = self.ids_map[:, :, 2] - # set model ids based on domain if cv.colorby == 'cell': self.ids = self.cell_ids @@ -732,6 +727,19 @@ def _do_op(array, tally_value, ax=0): return image_data, extents, data_min, data_max + @property + def cell_ids(self): + return self.ids_map[:, :, 0] + + @property + def instances(self): + return self.ids_map[:, :, 1] + + @property + def mat_ids(self): + return self.ids_map[:, :, 2] + + class ViewParam(openmc.lib.plot._PlotBase): """Viewer settings that are needed for _PlotBase and are independent of all other plotter/model settings. From ebe54604a8ab0c9ca1c0f43f636b99c992ba39d0 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 13 Jul 2022 13:51:53 -0500 Subject: [PATCH 31/32] make initial view the currentview and always create a default view --- openmc_plotter/plotmodel.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 207a16b..8f41142 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -144,6 +144,8 @@ def __init__(self, use_settings_pkl): self.previousViews = [] self.subsequentViews = [] + self.defaultView = self.getDefaultView() + if use_settings_pkl and os.path.isfile('plot_settings.pkl'): with open('plot_settings.pkl', 'rb') as file: try: @@ -156,7 +158,7 @@ def __init__(self, use_settings_pkl): msg_box.setIcon(QMessageBox.Warning) msg_box.setStandardButtons(QMessageBox.Ok) msg_box.exec_() - self.defaultView = self.getDefaultView() + self.currentView = copy.deepcopy(self.defaultView) else: restore_domains = False @@ -191,14 +193,13 @@ def __init__(self, use_settings_pkl): msg_box.exec_() self.statepoint = None - self.defaultView = PlotView(restore_view=view, + self.currentView = PlotView(restore_view=view, restore_domains=restore_domains) else: - self.defaultView = self.getDefaultView() + self.currentView = copy.deepcopy(self.defaultView) - self.currentView = copy.deepcopy(self.defaultView) - self.activeView = copy.deepcopy(self.defaultView) + self.activeView = copy.deepcopy(self.currentView) def openStatePoint(self, filename): self.statepoint = StatePointModel(filename, open_file=True) From 9ae7a7620b14625f1537b9dfc130b09097b02061 Mon Sep 17 00:00:00 2001 From: Kalin Kiesling Date: Wed, 13 Jul 2022 16:05:47 -0500 Subject: [PATCH 32/32] compare active and current views before updating current view to check if mapping needs to be called again --- openmc_plotter/plotmodel.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 8f41142..82b7d13 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -71,6 +71,8 @@ def hash_file(filename): chunk = file.read(32768) h.update(chunk) return h.hexdigest() + + class PlotModel(): """ Geometry and plot settings for OpenMC Plot Explorer model @@ -272,15 +274,17 @@ def makePlot(self): Creates corresponding .xml files from user-chosen settings. Runs OpenMC in plot mode to generate new plot image. """ + # update/call maps under 2 circumstances + # 1. this is the intial plot (ids_map/properties are None) + # 2. The active (desired) view differs from the current view parameters + if (self.currentView.view_params != self.activeView.view_params) or \ + (self.ids_map is None) or (self.properties is None): + # get ids from the active (desired) view + self.ids_map = openmc.lib.id_map(self.activeView.view_params) + self.properties = openmc.lib.property_map(self.activeView.view_params) + + # update current view cv = self.currentView = copy.deepcopy(self.activeView) - pv = self.previousViews[-1] - - if (self.properties is None) or (self.ids_map is None) or \ - (cv.view_params != pv.view_params): - # we are at the first view and need to populate OR - # view has changed and need to populate - self.ids_map = openmc.lib.id_map(cv.view_params) - self.properties = openmc.lib.property_map(cv.view_params) # set model ids based on domain if cv.colorby == 'cell':