Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mesh annotations #153

Merged
merged 7 commits into from
Nov 23, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion openmc_plotter/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.4.0'
__version__ = '0.4.1'
51 changes: 51 additions & 0 deletions openmc_plotter/docks.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,57 @@ def __init__(self, model, font_metric, parent=None):
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)


class MeshAnnotationDock(PlotterDock):
"""Dock for mesh annotation options"""

def __init__(self, model, font_metric, parent=None):
super().__init__(model, font_metric, parent)

self.treeLayout = QVBoxLayout()
self.meshTree = QTreeWidget()
self.treeExpander = Expander("Meshes:", layout=self.treeLayout)
self.treeExpander.expand() # start with meshes expanded

self.meshTree.setColumnCount(1)

self.mesh_items = []
for mesh_id in self.model.cpp_mesh_ids():
mesh_item = QTreeWidgetItem(self.meshTree, (f'Mesh {mesh_id}',))
mesh_item.setFlags(mesh_item.flags() | QtCore.Qt.ItemIsUserCheckable)
mesh_item.setCheckState(0, QtCore.Qt.Unchecked)
self.mesh_items.append((mesh_id, mesh_item))
self.meshTree.addTopLevelItem(mesh_item)

self.meshTree.setHeaderHidden(True)

# Create submit button
self.applyButton = QPushButton("Apply Changes")
# Mac bug fix
self.applyButton.setMinimumHeight(self.font_metric.height() * 1.6)
self.applyButton.clicked.connect(self.main_window.applyChanges)

label = QLabel("Mesh Annotations")
self.treeLayout.addWidget(label)
self.treeLayout.addWidget(self.meshTree)
self.treeLayout.addWidget(HorizontalLine())
self.treeLayout.addWidget(self.applyButton)

self.optionsWidget = QWidget()
self.optionsWidget.setLayout(self.treeLayout)
self.setWidget(self.optionsWidget)

def get_checked_meshes(self):
return [id for id, item in self.mesh_items if item.checkState(0) == QtCore.Qt.Checked]

def update(self):
pass

def resizeEvent(self, event):
self.main_window.resizeEvent(event)

hideEvent = showEvent = moveEvent = resizeEvent


class DomainDock(PlotterDock):
"""
Domain options dock
Expand Down
32 changes: 31 additions & 1 deletion openmc_plotter/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

from .plotmodel import PlotModel, DomainTableModel, hash_model
from .plotgui import PlotImage, ColorDialog
from .docks import DomainDock, TallyDock
from .docks import DomainDock, TallyDock, MeshAnnotationDock
from .overlays import ShortcutsOverlay
from .tools import ExportDataDialog, SourceSitesDialog

Expand Down Expand Up @@ -91,6 +91,12 @@ def loadGui(self, use_settings_pkl=True):
self.tallyDock.setObjectName("Tally Options Dock")
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.tallyDock)

# Mesh Annotation Dock
self.meshAnnotationDock = MeshAnnotationDock(self.model, self.font_metric, self)
self.meshAnnotationDock.update()
self.meshAnnotationDock.setObjectName("Mesh Annotation Dock")
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.meshAnnotationDock)

# Color DialogtallyDock
self.colorDialog = ColorDialog(self.model, self.font_metric, self)
self.colorDialog.hide()
Expand Down Expand Up @@ -386,6 +392,12 @@ def createMenuBar(self):
self.tallyDockAction.setStatusTip('Toggle tally dock visibility')
self.tallyDockAction.triggered.connect(self.toggleTallyDockView)

self.meshAnnotationDockAction = QAction('Mesh &Annotation Dock', self)
self.meshAnnotationDockAction.setShortcut("Ctrl+E")
self.meshAnnotationDockAction.setToolTip('Toggle mesh annotation dock visibility')
self.meshAnnotationDockAction.setStatusTip('Toggle mesh annotation dock visibility')
self.meshAnnotationDockAction.triggered.connect(self.toggleMeshAnnotationDockView)

self.zoomAction = QAction('&Zoom...', self)
self.zoomAction.setShortcut('Alt+Shift+Z')
self.zoomAction.setToolTip('Edit zoom factor')
Expand All @@ -395,6 +407,7 @@ def createMenuBar(self):
self.viewMenu = self.mainMenu.addMenu('&View')
self.viewMenu.addAction(self.dockAction)
self.viewMenu.addAction(self.tallyDockAction)
self.viewMenu.addAction(self.meshAnnotationDockAction)
self.viewMenu.addSeparator()
self.viewMenu.addAction(self.zoomAction)
self.viewMenu.aboutToShow.connect(self.updateViewMenu)
Expand Down Expand Up @@ -624,6 +637,10 @@ def updateDataMenu(self):
elif hasattr(self, "closeStatePointAction"):
self.dataMenu.removeAction(self.closeStatePointAction)


def updateMeshAnnotations(self):
self.model.activeView.mesh_annotations = self.meshAnnotationDock.get_checked_meshes()

def plotSourceSites(self):
self.sourceSitesDialog.show()
self.sourceSitesDialog.raise_()
Expand All @@ -635,6 +652,7 @@ def applyChanges(self):
QApplication.processEvents()
if self.model.activeView.selectedTally is not None:
self.tallyDock.updateModel()
self.updateMeshAnnotations()
self.model.storeCurrent()
self.model.subsequentViews = []
self.plotIm.generatePixmap()
Expand Down Expand Up @@ -811,6 +829,18 @@ def toggleTallyDockView(self):
self.resizePixmap()
self.showMainWindow()

def toggleMeshAnnotationDockView(self):
if self.meshAnnotationDock.isVisible():
self.meshAnnotationDock.hide()
if not self.isMaximized() and not self.meshAnnotationDock.isFloating():
self.resize(self.width() - self.meshAnnotationDock.width(), self.height())
else:
self.meshAnnotationDock.setVisible(True)
if not self.isMaximized() and not self.meshAnnotationDock.isFloating():
self.resize(self.width() + self.meshAnnotationDock.width(), self.height())
self.resizePixmap()
self.showMainWindow()

def editZoomAct(self):
percent, ok = QInputDialog.getInt(self, "Edit Zoom", "Zoom Percent:",
self.dock.zoomBox.value(), 25, 2000)
Expand Down
1 change: 1 addition & 0 deletions openmc_plotter/overlays.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class ShortcutsOverlay(QWidget):
("Horizontal Scroll", "Alt+Scroll")],
"Menus": [("Hide/Show Geometry Dock", c_key + "+D"),
("Hide/Show Tally Dock", c_key + "+T"),
("Hide/Show Mesh Annotation Dock", c_key + "+E"),
("Reload Model", "Shift+" + c_key + "+R"),
("Quit", c_key + "+Q"),
("Display Shortcuts", "?")],
Expand Down
29 changes: 25 additions & 4 deletions openmc_plotter/plotgui.py
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,10 @@ def updatePixmap(self):
self.add_outlines()
self.plotSourceSites()

# annotate mesh boundaries
for mesh_id in cv.mesh_annotations:
self.annotate_mesh(mesh_id)

# always make sure the data bounds are set correctly
self.ax.set_xbound(data_bounds[0], data_bounds[1])
self.ax.set_ybound(data_bounds[2], data_bounds[3])
Expand All @@ -652,6 +656,26 @@ def updatePixmap(self):
self.draw()
return "Done"

def current_view_data_bounds(self):
cv = self.model.currentView
return [cv.origin[self.main_window.xBasis] - cv.width/2.,
cv.origin[self.main_window.xBasis] + cv.width/2.,
cv.origin[self.main_window.yBasis] - cv.height/2.,
cv.origin[self.main_window.yBasis] + cv.height/2.]

def annotate_mesh(self, mesh_id):
mesh_bins = self.model.mesh_plot_bins(mesh_id)

data_bounds = self.current_view_data_bounds()
self.mesh_contours = self.ax.contour(
mesh_bins,
origin='upper',
colors='k',
linestyles='solid',
levels=np.unique(mesh_bins),
extent=data_bounds
)

def plotSourceSites(self):
if not self.model.sourceSitesVisible or self.model.sourceSites is None:
return
Expand Down Expand Up @@ -681,10 +705,7 @@ def add_outlines(self):
# draw outlines as isocontours
if cv.outlines:
# set data extents for automatic reporting of pointer location
data_bounds = [cv.origin[self.main_window.xBasis] - cv.width/2.,
cv.origin[self.main_window.xBasis] + cv.width/2.,
cv.origin[self.main_window.yBasis] - cv.height/2.,
cv.origin[self.main_window.yBasis] + cv.height/2.]
data_bounds = self.current_view_data_bounds()
levels = np.unique(self.model.ids)
self.contours = self.ax.contour(self.model.ids,
origin='upper',
Expand Down
28 changes: 21 additions & 7 deletions openmc_plotter/plotmodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,23 @@ def _create_distribcell_image(self, tally, tally_value, scores, nuclides, cellin

return image_data, None, data_min, data_max

def cpp_mesh_ids(self):
return list(openmc.lib.meshes.keys())

def mesh_plot_bins(self, mesh_id, view: PlotView = None):
mesh = openmc.lib.meshes[mesh_id]

if view is None:
view = self.currentView

mesh_bins = mesh.get_plot_bins(
origin=view.origin,
width=(view.width, view.height),
basis=view.basis,
pixels=(view.h_res, view.v_res),
)
return mesh_bins

def _create_tally_mesh_image(
self, tally: openmc.Tally, tally_value: TallyValueType,
scores: Tuple[str], nuclides: Tuple[str], view: PlotView = None
Expand Down Expand Up @@ -746,12 +763,7 @@ def _do_op(array, tally_value, ax=0):

# Get mesh bins from openmc.lib
mesh_cpp = openmc.lib.meshes[mesh.id]
mesh_bins = mesh_cpp.get_plot_bins(
origin=origin,
width=(view.width, view.height),
basis=view.basis,
pixels=(view.h_res, view.v_res),
)
mesh_bins = self.mesh_plot_bins(mesh.id, view)
paulromano marked this conversation as resolved.
Show resolved Hide resolved

# Apply volume normalization
if view.tallyVolumeNorm:
Expand Down Expand Up @@ -1017,14 +1029,16 @@ class PlotView:
Label of the currently selected tally
"""

attrs = ('view_ind', 'view_params', 'cells', 'materials', 'selectedTally')
attrs = ('view_ind', 'view_params', 'cells', 'materials', 'selectedTally', 'mesh_annotations')
plotbase_attrs = ('level', 'origin', 'width', 'height',
'h_res', 'v_res', 'basis', 'llc', 'urc', 'color_overlaps')

def __init__(self, origin=(0, 0, 0), width=10, height=10, restore_view=None,
restore_domains=False, default_res=None):
"""Initialize PlotView attributes"""

self.mesh_annotations = []

if restore_view is not None:
self.view_ind = copy.copy(restore_view.view_ind)
self.view_params = copy.copy(restore_view.view_params)
Expand Down