Draft
Show file tree
Hide file tree
Changes from all 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
31 changes: 30 additions & 1 deletion openmc_plotter/main_window.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -378,6 +378,16 @@ def createMenuBar(self):
self.overlapAct.toggled.connect(overlap_connector)
self.editMenu.addAction(self.overlapAct)

self.undefinedAct = QAction('Enable Undefined Region Coloring', self)
self.undefinedAct.setShortcut('Ctrl+I')
self.undefinedAct.setCheckable(True)
self.undefinedAct.setToolTip('Toggle undefined regions')
self.undefinedAct.setStatusTip('Toggle display of undefined '
'(not found) regions when enabled')
undefined_connector = partial(self.toggleUndefined, apply=True)
self.undefinedAct.toggled.connect(undefined_connector)
self.editMenu.addAction(self.undefinedAct)

self.outlineAct = QAction('Enable Domain Outlines', self)
self.outlineAct.setShortcut('Ctrl+U')
self.outlineAct.setCheckable(True)
Expand DownExpand Up@@ -438,14 +448,15 @@ def updateEditMenu(self):
self.restoreAction.setDisabled(not changed)

toggle_actions = (self.maskingAction, self.highlightingAct,
self.outlineAct, self.overlapAct)
self.outlineAct, self.overlapAct, self.undefinedAct)
# Temporarily block signals to avoid triggering plot update
for action in toggle_actions:
action.blockSignals(True)
self.maskingAction.setChecked(self.model.currentView.masking)
self.highlightingAct.setChecked(self.model.currentView.highlighting)
self.outlineAct.setChecked(self.model.currentView.outlinesCell)
self.overlapAct.setChecked(self.model.currentView.color_overlaps)
self.undefinedAct.setChecked(self.model.currentView.color_undefined)
for action in toggle_actions:
action.blockSignals(False)

Expand DownExpand Up@@ -742,6 +753,12 @@ def toggleOverlaps(self, state, apply=False):
if apply:
self.applyChanges()

def toggleUndefined(self, state, apply=False):
self.model.activeView.color_undefined = bool(state)
self.colorDialog.updateUndefined()
if apply:
self.applyChanges()

def editColorMap(self, colormap_name, property_type, apply=False):
self.model.activeView.colormaps[property_type] = colormap_name
self.plotIm.updateColorMap(colormap_name, property_type)
Expand DownExpand Up@@ -935,6 +952,18 @@ def editOverlapColor(self, apply=False):
if apply:
self.applyChanges()

def editUndefinedColor(self, apply=False):
current_color = self.model.activeView.undefined_color
dlg = QColorDialog(self)
dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color))
if dlg.exec():
new_color = dlg.currentColor().getRgb()[:3]
self.model.activeView.undefined_color = new_color
self.colorDialog.updateUndefinedColor()

if apply:
self.applyChanges()

def editBackgroundColor(self, apply=False):
current_color = self.model.activeView.domainBackground
dlg = QColorDialog(self)
Expand Down
1 change: 1 addition & 0 deletions openmc_plotter/overlays.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@ class ShortcutsOverlay(QWidget):
("Toggle Masking", c_key + "+M"),
("Toggle Highlighting", c_key + "+L"),
("Toggle Overlap Coloring", c_key + "+P"),
("Toggle Undefined Coloring", c_key + "+I"),
("Toggle Domain Outlines", c_key + "+U"),
("Set XY Basis", "Alt+X"),
("Set YZ Basis", "Alt+Y"),
Expand Down
58 changes: 56 additions & 2 deletions openmc_plotter/plotgui.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -361,6 +361,22 @@ def _overlapInfo(self, id):
label2 = self._cellLabel(cell2)
return f"OVERLAP: Universe {universe}, Cells {label1} and {label2}"

def _isUndefinedInternal(self, event):
"""Whether the pixel under the event is an internal undefined region."""
if self.model.undefined_internal is None:
return False
xPos, yPos = self.getDataIndices(event)
cv = self.model.currentView
if not (0 <= yPos < cv.v_res and 0 <= xPos < cv.h_res):
return False
return bool(self.model.undefined_internal[yPos, xPos])

def _undefinedInfo(self, event):
"""Status-bar text for an undefined (not-found) pixel, if classified."""
if self._isUndefinedInternal(event):
return "WARNING: undefined internal region"
return ""

def mouseDoubleClickEvent(self, event):
xCenter, yCenter = self.getPlotCoords(event.pos())
self.main_window.editPlotOrigin(xCenter, yCenter, apply=True)
Expand DownExpand Up@@ -414,7 +430,7 @@ def mouseMoveEvent(self, event):
density,
temperature))
else:
domainInfo = ""
domainInfo = self._undefinedInfo(event)

if self.model.tally_data is not None:
tid, value = self.getTallyInfo(event)
Expand DownExpand Up@@ -568,7 +584,16 @@ def contextMenuEvent(self, event):

if cv.colorby not in _MODEL_PROPERTIES:
self.menu.addSeparator()
if int(id) == _NOT_FOUND:
if int(id) == _NOT_FOUND and self._isUndefinedInternal(event):
undefColorAction = self.menu.addAction(
'Edit Undefined Color...')
undefColorAction.setToolTip('Edit undefined color')
undefColorAction.setStatusTip(
'Edit plot undefined region color')
connector = partial(self.main_window.editUndefinedColor,
apply=True)
undefColorAction.triggered.connect(connector)
elif int(id) == _NOT_FOUND:
bgColorAction = self.menu.addAction(
'Edit Background Color...')
bgColorAction.setToolTip('Edit background color')
Expand DownExpand Up@@ -598,6 +623,7 @@ def contextMenuEvent(self, event):
self.menu.addAction(self.main_window.maskingAction)
self.menu.addAction(self.main_window.highlightingAct)
self.menu.addAction(self.main_window.overlapAct)
self.menu.addAction(self.main_window.undefinedAct)
self.menu.addSeparator()
self.menu.addAction(self.main_window.dockAction)

Expand DownExpand Up@@ -1125,6 +1151,17 @@ def createGeneralTab(self):
self.overlapColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.overlapColorButton.clicked.connect(main_window.editOverlapColor)

# Undefined (not-found) region plotting
self.undefinedCheck = QCheckBox('', self)
undefined_connector = partial(main_window.toggleUndefined)
self.undefinedCheck.stateChanged.connect(undefined_connector)

self.undefinedColorButton = QPushButton()
self.undefinedColorButton.setCursor(QtCore.Qt.PointingHandCursor)
self.undefinedColorButton.setFixedWidth(button_width)
self.undefinedColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.undefinedColorButton.clicked.connect(main_window.editUndefinedColor)

self.colorResetButton = QPushButton("&Reset Colors")
self.colorResetButton.setCursor(QtCore.Qt.PointingHandCursor)
self.colorResetButton.clicked.connect(main_window.resetColors)
Expand All@@ -1147,6 +1184,9 @@ def createGeneralTab(self):
formLayout.addRow('Show Overlaps:', self.overlapCheck)
formLayout.addRow('Overlap Color:', self.overlapColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Show Undefined:', self.undefinedCheck)
formLayout.addRow('Undefined Color:', self.undefinedColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Color Plot By:', self.colorbyBox)
formLayout.addRow('Universe Level:', self.universeLevelBox)
formLayout.addRow(self.colorResetButton, None)
Expand DownExpand Up@@ -1314,6 +1354,8 @@ def updateDialogValues(self):
self.updateDomainTabs()
self.updateOverlap()
self.updateOverlapColor()
self.updateUndefined()
self.updateUndefinedColor()

def updateMasking(self):
masking = self.model.activeView.masking
Expand DownExpand Up@@ -1383,10 +1425,22 @@ def updateOverlap(self):
if colorby in ('cell', 'material'):
self.overlapCheck.setChecked(overlap_val)

def updateUndefinedColor(self):
color = self.model.activeView.undefined_color
self.undefinedColorButton.setStyleSheet("border-radius: 8px;"
"background-color: rgb%s" % (str(color)))

def updateUndefined(self):
colorby = self.model.activeView.colorby
undefined_val = self.model.activeView.color_undefined
if colorby in ('cell', 'material'):
self.undefinedCheck.setChecked(undefined_val)

def updateColorBy(self):
colorby = self.model.activeView.colorby
self.colorbyBox.setCurrentText(colorby)
self.overlapCheck.setEnabled(colorby in ("cell", "material"))
self.undefinedCheck.setEnabled(colorby in ("cell", "material"))
self.universeLevelBox.setEnabled(colorby == 'cell')

def updateUniverseLevel(self):
Expand Down
31 changes: 31 additions & 0 deletions openmc_plotter/plotmodel.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -327,6 +327,12 @@ def __init__(self, use_settings_pkl, model_path, default_res):
# Map to be populated by overlap functions
self.overlap_info = None

# Boolean mask of internal undefined (not-found) regions, populated by
# makePlot when undefined-region coloring is enabled. Internal regions
# are enclosed by defined geometry (potentially unsafe); external
# (boundary-connected) undefined regions are intentionally ignored.
self.undefined_internal = None

self.version = __version__

# default statepoint value
Expand DownExpand Up@@ -585,6 +591,18 @@ def makePlot(self, view: Optional["PlotView"] = None,
if dom.highlight:
image[self.ids == int(id)] = cv.highlightBackground

# Classify and color undefined (not-found) regions. Only internal
# regions (holes enclosed by defined geometry) are flagged as a
# warning; external regions connect to the slice boundary and are
# left untouched.
self.undefined_internal = None
if cv.color_undefined:
_, _, internal = \
openmc.Model._classify_undefined_regions(self.cell_ids)
if internal is not None:
self.undefined_internal = internal
image[internal] = cv.undefined_color

# set model image
self.image = image

Expand DownExpand Up@@ -1228,6 +1246,11 @@ class PlotViewIndependent:
RGB color to apply to plot background
overlap_color : 3-tuple of int
RGB color to apply for cell overlap regions
color_undefined : bool
Indicator of whether or not internal undefined (not-found) regions
will be shown
undefined_color : 3-tuple of int
RGB color to apply for internal (enclosed) undefined regions
domainAlpha : float between 0 and 1
Alpha value of the geometry plot
plotVisibile : bool
Expand DownExpand Up@@ -1277,6 +1300,9 @@ def __init__(self):
self.highlightSeed = 1
self.domainBackground = (50, 50, 50)
self.overlap_color = (255, 0, 0)
# Undefined (not-found) region coloring (internal regions only)
self.color_undefined = False
self.undefined_color = (255, 165, 0)
self.domainAlpha = 1.0
self.domainVisible = True
self.outlinesCell = False
Expand DownExpand Up@@ -1314,6 +1340,11 @@ def __setstate__(self, state):
self.outlinesCell = False
if not hasattr(self, 'outlinesMat'):
self.outlinesMat = False
# Undefined region coloring (added in a later version)
if not hasattr(self, 'color_undefined'):
self.color_undefined = False
if not hasattr(self, 'undefined_color'):
self.undefined_color = (255, 165, 0)
# Migrate old boolean attributes to new tallyDataMinMaxType
if not hasattr(self, 'tallyDataMinMaxType'):
if getattr(self, 'tallyDataUserMinMax', False):
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
31 changes: 30 additions & 1 deletion openmc_plotter/main_window.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -378,6 +378,16 @@ def createMenuBar(self):
self.overlapAct.toggled.connect(overlap_connector)
self.editMenu.addAction(self.overlapAct)

self.undefinedAct = QAction('Enable Undefined Region Coloring', self)
self.undefinedAct.setShortcut('Ctrl+I')
self.undefinedAct.setCheckable(True)
self.undefinedAct.setToolTip('Toggle undefined regions')
self.undefinedAct.setStatusTip('Toggle display of undefined '
'(not found) regions when enabled')
undefined_connector = partial(self.toggleUndefined, apply=True)
self.undefinedAct.toggled.connect(undefined_connector)
self.editMenu.addAction(self.undefinedAct)

self.outlineAct = QAction('Enable Domain Outlines', self)
self.outlineAct.setShortcut('Ctrl+U')
self.outlineAct.setCheckable(True)
Expand DownExpand Up@@ -438,14 +448,15 @@ def updateEditMenu(self):
self.restoreAction.setDisabled(not changed)

toggle_actions = (self.maskingAction, self.highlightingAct,
self.outlineAct, self.overlapAct)
self.outlineAct, self.overlapAct, self.undefinedAct)
# Temporarily block signals to avoid triggering plot update
for action in toggle_actions:
action.blockSignals(True)
self.maskingAction.setChecked(self.model.currentView.masking)
self.highlightingAct.setChecked(self.model.currentView.highlighting)
self.outlineAct.setChecked(self.model.currentView.outlinesCell)
self.overlapAct.setChecked(self.model.currentView.color_overlaps)
self.undefinedAct.setChecked(self.model.currentView.color_undefined)
for action in toggle_actions:
action.blockSignals(False)

Expand DownExpand Up@@ -742,6 +753,12 @@ def toggleOverlaps(self, state, apply=False):
if apply:
self.applyChanges()

def toggleUndefined(self, state, apply=False):
self.model.activeView.color_undefined = bool(state)
self.colorDialog.updateUndefined()
if apply:
self.applyChanges()

def editColorMap(self, colormap_name, property_type, apply=False):
self.model.activeView.colormaps[property_type] = colormap_name
self.plotIm.updateColorMap(colormap_name, property_type)
Expand DownExpand Up@@ -935,6 +952,18 @@ def editOverlapColor(self, apply=False):
if apply:
self.applyChanges()

def editUndefinedColor(self, apply=False):
current_color = self.model.activeView.undefined_color
dlg = QColorDialog(self)
dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color))
if dlg.exec():
new_color = dlg.currentColor().getRgb()[:3]
self.model.activeView.undefined_color = new_color
self.colorDialog.updateUndefinedColor()

if apply:
self.applyChanges()

def editBackgroundColor(self, apply=False):
current_color = self.model.activeView.domainBackground
dlg = QColorDialog(self)
Expand Down
1 change: 1 addition & 0 deletions openmc_plotter/overlays.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@ class ShortcutsOverlay(QWidget):
("Toggle Masking", c_key + "+M"),
("Toggle Highlighting", c_key + "+L"),
("Toggle Overlap Coloring", c_key + "+P"),
("Toggle Undefined Coloring", c_key + "+I"),
("Toggle Domain Outlines", c_key + "+U"),
("Set XY Basis", "Alt+X"),
("Set YZ Basis", "Alt+Y"),
Expand Down
58 changes: 56 additions & 2 deletions openmc_plotter/plotgui.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -361,6 +361,22 @@ def _overlapInfo(self, id):
label2 = self._cellLabel(cell2)
return f"OVERLAP: Universe {universe}, Cells {label1} and {label2}"

def _isUndefinedInternal(self, event):
"""Whether the pixel under the event is an internal undefined region."""
if self.model.undefined_internal is None:
return False
xPos, yPos = self.getDataIndices(event)
cv = self.model.currentView
if not (0 <= yPos < cv.v_res and 0 <= xPos < cv.h_res):
return False
return bool(self.model.undefined_internal[yPos, xPos])

def _undefinedInfo(self, event):
"""Status-bar text for an undefined (not-found) pixel, if classified."""
if self._isUndefinedInternal(event):
return "WARNING: undefined internal region"
return ""

def mouseDoubleClickEvent(self, event):
xCenter, yCenter = self.getPlotCoords(event.pos())
self.main_window.editPlotOrigin(xCenter, yCenter, apply=True)
Expand DownExpand Up@@ -414,7 +430,7 @@ def mouseMoveEvent(self, event):
density,
temperature))
else:
domainInfo = ""
domainInfo = self._undefinedInfo(event)

if self.model.tally_data is not None:
tid, value = self.getTallyInfo(event)
Expand DownExpand Up@@ -568,7 +584,16 @@ def contextMenuEvent(self, event):

if cv.colorby not in _MODEL_PROPERTIES:
self.menu.addSeparator()
if int(id) == _NOT_FOUND:
if int(id) == _NOT_FOUND and self._isUndefinedInternal(event):
undefColorAction = self.menu.addAction(
'Edit Undefined Color...')
undefColorAction.setToolTip('Edit undefined color')
undefColorAction.setStatusTip(
'Edit plot undefined region color')
connector = partial(self.main_window.editUndefinedColor,
apply=True)
undefColorAction.triggered.connect(connector)
elif int(id) == _NOT_FOUND:
bgColorAction = self.menu.addAction(
'Edit Background Color...')
bgColorAction.setToolTip('Edit background color')
Expand DownExpand Up@@ -598,6 +623,7 @@ def contextMenuEvent(self, event):
self.menu.addAction(self.main_window.maskingAction)
self.menu.addAction(self.main_window.highlightingAct)
self.menu.addAction(self.main_window.overlapAct)
self.menu.addAction(self.main_window.undefinedAct)
self.menu.addSeparator()
self.menu.addAction(self.main_window.dockAction)

Expand DownExpand Up@@ -1125,6 +1151,17 @@ def createGeneralTab(self):
self.overlapColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.overlapColorButton.clicked.connect(main_window.editOverlapColor)

# Undefined (not-found) region plotting
self.undefinedCheck = QCheckBox('', self)
undefined_connector = partial(main_window.toggleUndefined)
self.undefinedCheck.stateChanged.connect(undefined_connector)

self.undefinedColorButton = QPushButton()
self.undefinedColorButton.setCursor(QtCore.Qt.PointingHandCursor)
self.undefinedColorButton.setFixedWidth(button_width)
self.undefinedColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.undefinedColorButton.clicked.connect(main_window.editUndefinedColor)

self.colorResetButton = QPushButton("&Reset Colors")
self.colorResetButton.setCursor(QtCore.Qt.PointingHandCursor)
self.colorResetButton.clicked.connect(main_window.resetColors)
Expand All@@ -1147,6 +1184,9 @@ def createGeneralTab(self):
formLayout.addRow('Show Overlaps:', self.overlapCheck)
formLayout.addRow('Overlap Color:', self.overlapColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Show Undefined:', self.undefinedCheck)
formLayout.addRow('Undefined Color:', self.undefinedColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Color Plot By:', self.colorbyBox)
formLayout.addRow('Universe Level:', self.universeLevelBox)
formLayout.addRow(self.colorResetButton, None)
Expand DownExpand Up@@ -1314,6 +1354,8 @@ def updateDialogValues(self):
self.updateDomainTabs()
self.updateOverlap()
self.updateOverlapColor()
self.updateUndefined()
self.updateUndefinedColor()

def updateMasking(self):
masking = self.model.activeView.masking
Expand DownExpand Up@@ -1383,10 +1425,22 @@ def updateOverlap(self):
if colorby in ('cell', 'material'):
self.overlapCheck.setChecked(overlap_val)

def updateUndefinedColor(self):
color = self.model.activeView.undefined_color
self.undefinedColorButton.setStyleSheet("border-radius: 8px;"
"background-color: rgb%s" % (str(color)))

def updateUndefined(self):
colorby = self.model.activeView.colorby
undefined_val = self.model.activeView.color_undefined
if colorby in ('cell', 'material'):
self.undefinedCheck.setChecked(undefined_val)

def updateColorBy(self):
colorby = self.model.activeView.colorby
self.colorbyBox.setCurrentText(colorby)
self.overlapCheck.setEnabled(colorby in ("cell", "material"))
self.undefinedCheck.setEnabled(colorby in ("cell", "material"))
self.universeLevelBox.setEnabled(colorby == 'cell')

def updateUniverseLevel(self):
Expand Down
31 changes: 31 additions & 0 deletions openmc_plotter/plotmodel.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -327,6 +327,12 @@ def __init__(self, use_settings_pkl, model_path, default_res):
# Map to be populated by overlap functions
self.overlap_info = None

# Boolean mask of internal undefined (not-found) regions, populated by
# makePlot when undefined-region coloring is enabled. Internal regions
# are enclosed by defined geometry (potentially unsafe); external
# (boundary-connected) undefined regions are intentionally ignored.
self.undefined_internal = None

self.version = __version__

# default statepoint value
Expand DownExpand Up@@ -585,6 +591,18 @@ def makePlot(self, view: Optional["PlotView"] = None,
if dom.highlight:
image[self.ids == int(id)] = cv.highlightBackground

# Classify and color undefined (not-found) regions. Only internal
# regions (holes enclosed by defined geometry) are flagged as a
# warning; external regions connect to the slice boundary and are
# left untouched.
self.undefined_internal = None
if cv.color_undefined:
_, _, internal = \
openmc.Model._classify_undefined_regions(self.cell_ids)
if internal is not None:
self.undefined_internal = internal
image[internal] = cv.undefined_color

# set model image
self.image = image

Expand DownExpand Up@@ -1228,6 +1246,11 @@ class PlotViewIndependent:
RGB color to apply to plot background
overlap_color : 3-tuple of int
RGB color to apply for cell overlap regions
color_undefined : bool
Indicator of whether or not internal undefined (not-found) regions
will be shown
undefined_color : 3-tuple of int
RGB color to apply for internal (enclosed) undefined regions
domainAlpha : float between 0 and 1
Alpha value of the geometry plot
plotVisibile : bool
Expand DownExpand Up@@ -1277,6 +1300,9 @@ def __init__(self):
self.highlightSeed = 1
self.domainBackground = (50, 50, 50)
self.overlap_color = (255, 0, 0)
# Undefined (not-found) region coloring (internal regions only)
self.color_undefined = False
self.undefined_color = (255, 165, 0)
self.domainAlpha = 1.0
self.domainVisible = True
self.outlinesCell = False
Expand DownExpand Up@@ -1314,6 +1340,11 @@ def __setstate__(self, state):
self.outlinesCell = False
if not hasattr(self, 'outlinesMat'):
self.outlinesMat = False
# Undefined region coloring (added in a later version)
if not hasattr(self, 'color_undefined'):
self.color_undefined = False
if not hasattr(self, 'undefined_color'):
self.undefined_color = (255, 165, 0)
# Migrate old boolean attributes to new tallyDataMinMaxType
if not hasattr(self, 'tallyDataMinMaxType'):
if getattr(self, 'tallyDataUserMinMax', False):
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
31 changes: 30 additions & 1 deletion openmc_plotter/main_window.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -378,6 +378,16 @@ def createMenuBar(self):
self.overlapAct.toggled.connect(overlap_connector)
self.editMenu.addAction(self.overlapAct)

self.undefinedAct = QAction('Enable Undefined Region Coloring', self)
self.undefinedAct.setShortcut('Ctrl+I')
self.undefinedAct.setCheckable(True)
self.undefinedAct.setToolTip('Toggle undefined regions')
self.undefinedAct.setStatusTip('Toggle display of undefined '
'(not found) regions when enabled')
undefined_connector = partial(self.toggleUndefined, apply=True)
self.undefinedAct.toggled.connect(undefined_connector)
self.editMenu.addAction(self.undefinedAct)

self.outlineAct = QAction('Enable Domain Outlines', self)
self.outlineAct.setShortcut('Ctrl+U')
self.outlineAct.setCheckable(True)
Expand DownExpand Up@@ -438,14 +448,15 @@ def updateEditMenu(self):
self.restoreAction.setDisabled(not changed)

toggle_actions = (self.maskingAction, self.highlightingAct,
self.outlineAct, self.overlapAct)
self.outlineAct, self.overlapAct, self.undefinedAct)
# Temporarily block signals to avoid triggering plot update
for action in toggle_actions:
action.blockSignals(True)
self.maskingAction.setChecked(self.model.currentView.masking)
self.highlightingAct.setChecked(self.model.currentView.highlighting)
self.outlineAct.setChecked(self.model.currentView.outlinesCell)
self.overlapAct.setChecked(self.model.currentView.color_overlaps)
self.undefinedAct.setChecked(self.model.currentView.color_undefined)
for action in toggle_actions:
action.blockSignals(False)

Expand DownExpand Up@@ -742,6 +753,12 @@ def toggleOverlaps(self, state, apply=False):
if apply:
self.applyChanges()

def toggleUndefined(self, state, apply=False):
self.model.activeView.color_undefined = bool(state)
self.colorDialog.updateUndefined()
if apply:
self.applyChanges()

def editColorMap(self, colormap_name, property_type, apply=False):
self.model.activeView.colormaps[property_type] = colormap_name
self.plotIm.updateColorMap(colormap_name, property_type)
Expand DownExpand Up@@ -935,6 +952,18 @@ def editOverlapColor(self, apply=False):
if apply:
self.applyChanges()

def editUndefinedColor(self, apply=False):
current_color = self.model.activeView.undefined_color
dlg = QColorDialog(self)
dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color))
if dlg.exec():
new_color = dlg.currentColor().getRgb()[:3]
self.model.activeView.undefined_color = new_color
self.colorDialog.updateUndefinedColor()

if apply:
self.applyChanges()

def editBackgroundColor(self, apply=False):
current_color = self.model.activeView.domainBackground
dlg = QColorDialog(self)
Expand Down
1 change: 1 addition & 0 deletions openmc_plotter/overlays.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@ class ShortcutsOverlay(QWidget):
("Toggle Masking", c_key + "+M"),
("Toggle Highlighting", c_key + "+L"),
("Toggle Overlap Coloring", c_key + "+P"),
("Toggle Undefined Coloring", c_key + "+I"),
("Toggle Domain Outlines", c_key + "+U"),
("Set XY Basis", "Alt+X"),
("Set YZ Basis", "Alt+Y"),
Expand Down
58 changes: 56 additions & 2 deletions openmc_plotter/plotgui.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -361,6 +361,22 @@ def _overlapInfo(self, id):
label2 = self._cellLabel(cell2)
return f"OVERLAP: Universe {universe}, Cells {label1} and {label2}"

def _isUndefinedInternal(self, event):
"""Whether the pixel under the event is an internal undefined region."""
if self.model.undefined_internal is None:
return False
xPos, yPos = self.getDataIndices(event)
cv = self.model.currentView
if not (0 <= yPos < cv.v_res and 0 <= xPos < cv.h_res):
return False
return bool(self.model.undefined_internal[yPos, xPos])

def _undefinedInfo(self, event):
"""Status-bar text for an undefined (not-found) pixel, if classified."""
if self._isUndefinedInternal(event):
return "WARNING: undefined internal region"
return ""

def mouseDoubleClickEvent(self, event):
xCenter, yCenter = self.getPlotCoords(event.pos())
self.main_window.editPlotOrigin(xCenter, yCenter, apply=True)
Expand DownExpand Up@@ -414,7 +430,7 @@ def mouseMoveEvent(self, event):
density,
temperature))
else:
domainInfo = ""
domainInfo = self._undefinedInfo(event)

if self.model.tally_data is not None:
tid, value = self.getTallyInfo(event)
Expand DownExpand Up@@ -568,7 +584,16 @@ def contextMenuEvent(self, event):

if cv.colorby not in _MODEL_PROPERTIES:
self.menu.addSeparator()
if int(id) == _NOT_FOUND:
if int(id) == _NOT_FOUND and self._isUndefinedInternal(event):
undefColorAction = self.menu.addAction(
'Edit Undefined Color...')
undefColorAction.setToolTip('Edit undefined color')
undefColorAction.setStatusTip(
'Edit plot undefined region color')
connector = partial(self.main_window.editUndefinedColor,
apply=True)
undefColorAction.triggered.connect(connector)
elif int(id) == _NOT_FOUND:
bgColorAction = self.menu.addAction(
'Edit Background Color...')
bgColorAction.setToolTip('Edit background color')
Expand DownExpand Up@@ -598,6 +623,7 @@ def contextMenuEvent(self, event):
self.menu.addAction(self.main_window.maskingAction)
self.menu.addAction(self.main_window.highlightingAct)
self.menu.addAction(self.main_window.overlapAct)
self.menu.addAction(self.main_window.undefinedAct)
self.menu.addSeparator()
self.menu.addAction(self.main_window.dockAction)

Expand DownExpand Up@@ -1125,6 +1151,17 @@ def createGeneralTab(self):
self.overlapColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.overlapColorButton.clicked.connect(main_window.editOverlapColor)

# Undefined (not-found) region plotting
self.undefinedCheck = QCheckBox('', self)
undefined_connector = partial(main_window.toggleUndefined)
self.undefinedCheck.stateChanged.connect(undefined_connector)

self.undefinedColorButton = QPushButton()
self.undefinedColorButton.setCursor(QtCore.Qt.PointingHandCursor)
self.undefinedColorButton.setFixedWidth(button_width)
self.undefinedColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.undefinedColorButton.clicked.connect(main_window.editUndefinedColor)

self.colorResetButton = QPushButton("&Reset Colors")
self.colorResetButton.setCursor(QtCore.Qt.PointingHandCursor)
self.colorResetButton.clicked.connect(main_window.resetColors)
Expand All@@ -1147,6 +1184,9 @@ def createGeneralTab(self):
formLayout.addRow('Show Overlaps:', self.overlapCheck)
formLayout.addRow('Overlap Color:', self.overlapColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Show Undefined:', self.undefinedCheck)
formLayout.addRow('Undefined Color:', self.undefinedColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Color Plot By:', self.colorbyBox)
formLayout.addRow('Universe Level:', self.universeLevelBox)
formLayout.addRow(self.colorResetButton, None)
Expand DownExpand Up@@ -1314,6 +1354,8 @@ def updateDialogValues(self):
self.updateDomainTabs()
self.updateOverlap()
self.updateOverlapColor()
self.updateUndefined()
self.updateUndefinedColor()

def updateMasking(self):
masking = self.model.activeView.masking
Expand DownExpand Up@@ -1383,10 +1425,22 @@ def updateOverlap(self):
if colorby in ('cell', 'material'):
self.overlapCheck.setChecked(overlap_val)

def updateUndefinedColor(self):
color = self.model.activeView.undefined_color
self.undefinedColorButton.setStyleSheet("border-radius: 8px;"
"background-color: rgb%s" % (str(color)))

def updateUndefined(self):
colorby = self.model.activeView.colorby
undefined_val = self.model.activeView.color_undefined
if colorby in ('cell', 'material'):
self.undefinedCheck.setChecked(undefined_val)

def updateColorBy(self):
colorby = self.model.activeView.colorby
self.colorbyBox.setCurrentText(colorby)
self.overlapCheck.setEnabled(colorby in ("cell", "material"))
self.undefinedCheck.setEnabled(colorby in ("cell", "material"))
self.universeLevelBox.setEnabled(colorby == 'cell')

def updateUniverseLevel(self):
Expand Down
31 changes: 31 additions & 0 deletions openmc_plotter/plotmodel.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -327,6 +327,12 @@ def __init__(self, use_settings_pkl, model_path, default_res):
# Map to be populated by overlap functions
self.overlap_info = None

# Boolean mask of internal undefined (not-found) regions, populated by
# makePlot when undefined-region coloring is enabled. Internal regions
# are enclosed by defined geometry (potentially unsafe); external
# (boundary-connected) undefined regions are intentionally ignored.
self.undefined_internal = None

self.version = __version__

# default statepoint value
Expand DownExpand Up@@ -585,6 +591,18 @@ def makePlot(self, view: Optional["PlotView"] = None,
if dom.highlight:
image[self.ids == int(id)] = cv.highlightBackground

# Classify and color undefined (not-found) regions. Only internal
# regions (holes enclosed by defined geometry) are flagged as a
# warning; external regions connect to the slice boundary and are
# left untouched.
self.undefined_internal = None
if cv.color_undefined:
_, _, internal = \
openmc.Model._classify_undefined_regions(self.cell_ids)
if internal is not None:
self.undefined_internal = internal
image[internal] = cv.undefined_color

# set model image
self.image = image

Expand DownExpand Up@@ -1228,6 +1246,11 @@ class PlotViewIndependent:
RGB color to apply to plot background
overlap_color : 3-tuple of int
RGB color to apply for cell overlap regions
color_undefined : bool
Indicator of whether or not internal undefined (not-found) regions
will be shown
undefined_color : 3-tuple of int
RGB color to apply for internal (enclosed) undefined regions
domainAlpha : float between 0 and 1
Alpha value of the geometry plot
plotVisibile : bool
Expand DownExpand Up@@ -1277,6 +1300,9 @@ def __init__(self):
self.highlightSeed = 1
self.domainBackground = (50, 50, 50)
self.overlap_color = (255, 0, 0)
# Undefined (not-found) region coloring (internal regions only)
self.color_undefined = False
self.undefined_color = (255, 165, 0)
self.domainAlpha = 1.0
self.domainVisible = True
self.outlinesCell = False
Expand DownExpand Up@@ -1314,6 +1340,11 @@ def __setstate__(self, state):
self.outlinesCell = False
if not hasattr(self, 'outlinesMat'):
self.outlinesMat = False
# Undefined region coloring (added in a later version)
if not hasattr(self, 'color_undefined'):
self.color_undefined = False
if not hasattr(self, 'undefined_color'):
self.undefined_color = (255, 165, 0)
# Migrate old boolean attributes to new tallyDataMinMaxType
if not hasattr(self, 'tallyDataMinMaxType'):
if getattr(self, 'tallyDataUserMinMax', False):
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
31 changes: 30 additions & 1 deletion openmc_plotter/main_window.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -378,6 +378,16 @@ def createMenuBar(self):
self.overlapAct.toggled.connect(overlap_connector)
self.editMenu.addAction(self.overlapAct)

self.undefinedAct = QAction('Enable Undefined Region Coloring', self)
self.undefinedAct.setShortcut('Ctrl+I')
self.undefinedAct.setCheckable(True)
self.undefinedAct.setToolTip('Toggle undefined regions')
self.undefinedAct.setStatusTip('Toggle display of undefined '
'(not found) regions when enabled')
undefined_connector = partial(self.toggleUndefined, apply=True)
self.undefinedAct.toggled.connect(undefined_connector)
self.editMenu.addAction(self.undefinedAct)

self.outlineAct = QAction('Enable Domain Outlines', self)
self.outlineAct.setShortcut('Ctrl+U')
self.outlineAct.setCheckable(True)
Expand DownExpand Up@@ -438,14 +448,15 @@ def updateEditMenu(self):
self.restoreAction.setDisabled(not changed)

toggle_actions = (self.maskingAction, self.highlightingAct,
self.outlineAct, self.overlapAct)
self.outlineAct, self.overlapAct, self.undefinedAct)
# Temporarily block signals to avoid triggering plot update
for action in toggle_actions:
action.blockSignals(True)
self.maskingAction.setChecked(self.model.currentView.masking)
self.highlightingAct.setChecked(self.model.currentView.highlighting)
self.outlineAct.setChecked(self.model.currentView.outlinesCell)
self.overlapAct.setChecked(self.model.currentView.color_overlaps)
self.undefinedAct.setChecked(self.model.currentView.color_undefined)
for action in toggle_actions:
action.blockSignals(False)

Expand DownExpand Up@@ -742,6 +753,12 @@ def toggleOverlaps(self, state, apply=False):
if apply:
self.applyChanges()

def toggleUndefined(self, state, apply=False):
self.model.activeView.color_undefined = bool(state)
self.colorDialog.updateUndefined()
if apply:
self.applyChanges()

def editColorMap(self, colormap_name, property_type, apply=False):
self.model.activeView.colormaps[property_type] = colormap_name
self.plotIm.updateColorMap(colormap_name, property_type)
Expand DownExpand Up@@ -935,6 +952,18 @@ def editOverlapColor(self, apply=False):
if apply:
self.applyChanges()

def editUndefinedColor(self, apply=False):
current_color = self.model.activeView.undefined_color
dlg = QColorDialog(self)
dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color))
if dlg.exec():
new_color = dlg.currentColor().getRgb()[:3]
self.model.activeView.undefined_color = new_color
self.colorDialog.updateUndefinedColor()

if apply:
self.applyChanges()

def editBackgroundColor(self, apply=False):
current_color = self.model.activeView.domainBackground
dlg = QColorDialog(self)
Expand Down
1 change: 1 addition & 0 deletions openmc_plotter/overlays.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@ class ShortcutsOverlay(QWidget):
("Toggle Masking", c_key + "+M"),
("Toggle Highlighting", c_key + "+L"),
("Toggle Overlap Coloring", c_key + "+P"),
("Toggle Undefined Coloring", c_key + "+I"),
("Toggle Domain Outlines", c_key + "+U"),
("Set XY Basis", "Alt+X"),
("Set YZ Basis", "Alt+Y"),
Expand Down
58 changes: 56 additions & 2 deletions openmc_plotter/plotgui.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -361,6 +361,22 @@ def _overlapInfo(self, id):
label2 = self._cellLabel(cell2)
return f"OVERLAP: Universe {universe}, Cells {label1} and {label2}"

def _isUndefinedInternal(self, event):
"""Whether the pixel under the event is an internal undefined region."""
if self.model.undefined_internal is None:
return False
xPos, yPos = self.getDataIndices(event)
cv = self.model.currentView
if not (0 <= yPos < cv.v_res and 0 <= xPos < cv.h_res):
return False
return bool(self.model.undefined_internal[yPos, xPos])

def _undefinedInfo(self, event):
"""Status-bar text for an undefined (not-found) pixel, if classified."""
if self._isUndefinedInternal(event):
return "WARNING: undefined internal region"
return ""

def mouseDoubleClickEvent(self, event):
xCenter, yCenter = self.getPlotCoords(event.pos())
self.main_window.editPlotOrigin(xCenter, yCenter, apply=True)
Expand DownExpand Up@@ -414,7 +430,7 @@ def mouseMoveEvent(self, event):
density,
temperature))
else:
domainInfo = ""
domainInfo = self._undefinedInfo(event)

if self.model.tally_data is not None:
tid, value = self.getTallyInfo(event)
Expand DownExpand Up@@ -568,7 +584,16 @@ def contextMenuEvent(self, event):

if cv.colorby not in _MODEL_PROPERTIES:
self.menu.addSeparator()
if int(id) == _NOT_FOUND:
if int(id) == _NOT_FOUND and self._isUndefinedInternal(event):
undefColorAction = self.menu.addAction(
'Edit Undefined Color...')
undefColorAction.setToolTip('Edit undefined color')
undefColorAction.setStatusTip(
'Edit plot undefined region color')
connector = partial(self.main_window.editUndefinedColor,
apply=True)
undefColorAction.triggered.connect(connector)
elif int(id) == _NOT_FOUND:
bgColorAction = self.menu.addAction(
'Edit Background Color...')
bgColorAction.setToolTip('Edit background color')
Expand DownExpand Up@@ -598,6 +623,7 @@ def contextMenuEvent(self, event):
self.menu.addAction(self.main_window.maskingAction)
self.menu.addAction(self.main_window.highlightingAct)
self.menu.addAction(self.main_window.overlapAct)
self.menu.addAction(self.main_window.undefinedAct)
self.menu.addSeparator()
self.menu.addAction(self.main_window.dockAction)

Expand DownExpand Up@@ -1125,6 +1151,17 @@ def createGeneralTab(self):
self.overlapColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.overlapColorButton.clicked.connect(main_window.editOverlapColor)

# Undefined (not-found) region plotting
self.undefinedCheck = QCheckBox('', self)
undefined_connector = partial(main_window.toggleUndefined)
self.undefinedCheck.stateChanged.connect(undefined_connector)

self.undefinedColorButton = QPushButton()
self.undefinedColorButton.setCursor(QtCore.Qt.PointingHandCursor)
self.undefinedColorButton.setFixedWidth(button_width)
self.undefinedColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.undefinedColorButton.clicked.connect(main_window.editUndefinedColor)

self.colorResetButton = QPushButton("&Reset Colors")
self.colorResetButton.setCursor(QtCore.Qt.PointingHandCursor)
self.colorResetButton.clicked.connect(main_window.resetColors)
Expand All@@ -1147,6 +1184,9 @@ def createGeneralTab(self):
formLayout.addRow('Show Overlaps:', self.overlapCheck)
formLayout.addRow('Overlap Color:', self.overlapColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Show Undefined:', self.undefinedCheck)
formLayout.addRow('Undefined Color:', self.undefinedColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Color Plot By:', self.colorbyBox)
formLayout.addRow('Universe Level:', self.universeLevelBox)
formLayout.addRow(self.colorResetButton, None)
Expand DownExpand Up@@ -1314,6 +1354,8 @@ def updateDialogValues(self):
self.updateDomainTabs()
self.updateOverlap()
self.updateOverlapColor()
self.updateUndefined()
self.updateUndefinedColor()

def updateMasking(self):
masking = self.model.activeView.masking
Expand DownExpand Up@@ -1383,10 +1425,22 @@ def updateOverlap(self):
if colorby in ('cell', 'material'):
self.overlapCheck.setChecked(overlap_val)

def updateUndefinedColor(self):
color = self.model.activeView.undefined_color
self.undefinedColorButton.setStyleSheet("border-radius: 8px;"
"background-color: rgb%s" % (str(color)))

def updateUndefined(self):
colorby = self.model.activeView.colorby
undefined_val = self.model.activeView.color_undefined
if colorby in ('cell', 'material'):
self.undefinedCheck.setChecked(undefined_val)

def updateColorBy(self):
colorby = self.model.activeView.colorby
self.colorbyBox.setCurrentText(colorby)
self.overlapCheck.setEnabled(colorby in ("cell", "material"))
self.undefinedCheck.setEnabled(colorby in ("cell", "material"))
self.universeLevelBox.setEnabled(colorby == 'cell')

def updateUniverseLevel(self):
Expand Down
31 changes: 31 additions & 0 deletions openmc_plotter/plotmodel.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -327,6 +327,12 @@ def __init__(self, use_settings_pkl, model_path, default_res):
# Map to be populated by overlap functions
self.overlap_info = None

# Boolean mask of internal undefined (not-found) regions, populated by
# makePlot when undefined-region coloring is enabled. Internal regions
# are enclosed by defined geometry (potentially unsafe); external
# (boundary-connected) undefined regions are intentionally ignored.
self.undefined_internal = None

self.version = __version__

# default statepoint value
Expand DownExpand Up@@ -585,6 +591,18 @@ def makePlot(self, view: Optional["PlotView"] = None,
if dom.highlight:
image[self.ids == int(id)] = cv.highlightBackground

# Classify and color undefined (not-found) regions. Only internal
# regions (holes enclosed by defined geometry) are flagged as a
# warning; external regions connect to the slice boundary and are
# left untouched.
self.undefined_internal = None
if cv.color_undefined:
_, _, internal = \
openmc.Model._classify_undefined_regions(self.cell_ids)
if internal is not None:
self.undefined_internal = internal
image[internal] = cv.undefined_color

# set model image
self.image = image

Expand DownExpand Up@@ -1228,6 +1246,11 @@ class PlotViewIndependent:
RGB color to apply to plot background
overlap_color : 3-tuple of int
RGB color to apply for cell overlap regions
color_undefined : bool
Indicator of whether or not internal undefined (not-found) regions
will be shown
undefined_color : 3-tuple of int
RGB color to apply for internal (enclosed) undefined regions
domainAlpha : float between 0 and 1
Alpha value of the geometry plot
plotVisibile : bool
Expand DownExpand Up@@ -1277,6 +1300,9 @@ def __init__(self):
self.highlightSeed = 1
self.domainBackground = (50, 50, 50)
self.overlap_color = (255, 0, 0)
# Undefined (not-found) region coloring (internal regions only)
self.color_undefined = False
self.undefined_color = (255, 165, 0)
self.domainAlpha = 1.0
self.domainVisible = True
self.outlinesCell = False
Expand DownExpand Up@@ -1314,6 +1340,11 @@ def __setstate__(self, state):
self.outlinesCell = False
if not hasattr(self, 'outlinesMat'):
self.outlinesMat = False
# Undefined region coloring (added in a later version)
if not hasattr(self, 'color_undefined'):
self.color_undefined = False
if not hasattr(self, 'undefined_color'):
self.undefined_color = (255, 165, 0)
# Migrate old boolean attributes to new tallyDataMinMaxType
if not hasattr(self, 'tallyDataMinMaxType'):
if getattr(self, 'tallyDataUserMinMax', False):
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
31 changes: 30 additions & 1 deletion openmc_plotter/main_window.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -378,6 +378,16 @@ def createMenuBar(self):
self.overlapAct.toggled.connect(overlap_connector)
self.editMenu.addAction(self.overlapAct)

self.undefinedAct = QAction('Enable Undefined Region Coloring', self)
self.undefinedAct.setShortcut('Ctrl+I')
self.undefinedAct.setCheckable(True)
self.undefinedAct.setToolTip('Toggle undefined regions')
self.undefinedAct.setStatusTip('Toggle display of undefined '
'(not found) regions when enabled')
undefined_connector = partial(self.toggleUndefined, apply=True)
self.undefinedAct.toggled.connect(undefined_connector)
self.editMenu.addAction(self.undefinedAct)

self.outlineAct = QAction('Enable Domain Outlines', self)
self.outlineAct.setShortcut('Ctrl+U')
self.outlineAct.setCheckable(True)
Expand DownExpand Up@@ -438,14 +448,15 @@ def updateEditMenu(self):
self.restoreAction.setDisabled(not changed)

toggle_actions = (self.maskingAction, self.highlightingAct,
self.outlineAct, self.overlapAct)
self.outlineAct, self.overlapAct, self.undefinedAct)
# Temporarily block signals to avoid triggering plot update
for action in toggle_actions:
action.blockSignals(True)
self.maskingAction.setChecked(self.model.currentView.masking)
self.highlightingAct.setChecked(self.model.currentView.highlighting)
self.outlineAct.setChecked(self.model.currentView.outlinesCell)
self.overlapAct.setChecked(self.model.currentView.color_overlaps)
self.undefinedAct.setChecked(self.model.currentView.color_undefined)
for action in toggle_actions:
action.blockSignals(False)

Expand DownExpand Up@@ -742,6 +753,12 @@ def toggleOverlaps(self, state, apply=False):
if apply:
self.applyChanges()

def toggleUndefined(self, state, apply=False):
self.model.activeView.color_undefined = bool(state)
self.colorDialog.updateUndefined()
if apply:
self.applyChanges()

def editColorMap(self, colormap_name, property_type, apply=False):
self.model.activeView.colormaps[property_type] = colormap_name
self.plotIm.updateColorMap(colormap_name, property_type)
Expand DownExpand Up@@ -935,6 +952,18 @@ def editOverlapColor(self, apply=False):
if apply:
self.applyChanges()

def editUndefinedColor(self, apply=False):
current_color = self.model.activeView.undefined_color
dlg = QColorDialog(self)
dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color))
if dlg.exec():
new_color = dlg.currentColor().getRgb()[:3]
self.model.activeView.undefined_color = new_color
self.colorDialog.updateUndefinedColor()

if apply:
self.applyChanges()

def editBackgroundColor(self, apply=False):
current_color = self.model.activeView.domainBackground
dlg = QColorDialog(self)
Expand Down
1 change: 1 addition & 0 deletions openmc_plotter/overlays.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@ class ShortcutsOverlay(QWidget):
("Toggle Masking", c_key + "+M"),
("Toggle Highlighting", c_key + "+L"),
("Toggle Overlap Coloring", c_key + "+P"),
("Toggle Undefined Coloring", c_key + "+I"),
("Toggle Domain Outlines", c_key + "+U"),
("Set XY Basis", "Alt+X"),
("Set YZ Basis", "Alt+Y"),
Expand Down
58 changes: 56 additions & 2 deletions openmc_plotter/plotgui.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -361,6 +361,22 @@ def _overlapInfo(self, id):
label2 = self._cellLabel(cell2)
return f"OVERLAP: Universe {universe}, Cells {label1} and {label2}"

def _isUndefinedInternal(self, event):
"""Whether the pixel under the event is an internal undefined region."""
if self.model.undefined_internal is None:
return False
xPos, yPos = self.getDataIndices(event)
cv = self.model.currentView
if not (0 <= yPos < cv.v_res and 0 <= xPos < cv.h_res):
return False
return bool(self.model.undefined_internal[yPos, xPos])

def _undefinedInfo(self, event):
"""Status-bar text for an undefined (not-found) pixel, if classified."""
if self._isUndefinedInternal(event):
return "WARNING: undefined internal region"
return ""

def mouseDoubleClickEvent(self, event):
xCenter, yCenter = self.getPlotCoords(event.pos())
self.main_window.editPlotOrigin(xCenter, yCenter, apply=True)
Expand DownExpand Up@@ -414,7 +430,7 @@ def mouseMoveEvent(self, event):
density,
temperature))
else:
domainInfo = ""
domainInfo = self._undefinedInfo(event)

if self.model.tally_data is not None:
tid, value = self.getTallyInfo(event)
Expand DownExpand Up@@ -568,7 +584,16 @@ def contextMenuEvent(self, event):

if cv.colorby not in _MODEL_PROPERTIES:
self.menu.addSeparator()
if int(id) == _NOT_FOUND:
if int(id) == _NOT_FOUND and self._isUndefinedInternal(event):
undefColorAction = self.menu.addAction(
'Edit Undefined Color...')
undefColorAction.setToolTip('Edit undefined color')
undefColorAction.setStatusTip(
'Edit plot undefined region color')
connector = partial(self.main_window.editUndefinedColor,
apply=True)
undefColorAction.triggered.connect(connector)
elif int(id) == _NOT_FOUND:
bgColorAction = self.menu.addAction(
'Edit Background Color...')
bgColorAction.setToolTip('Edit background color')
Expand DownExpand Up@@ -598,6 +623,7 @@ def contextMenuEvent(self, event):
self.menu.addAction(self.main_window.maskingAction)
self.menu.addAction(self.main_window.highlightingAct)
self.menu.addAction(self.main_window.overlapAct)
self.menu.addAction(self.main_window.undefinedAct)
self.menu.addSeparator()
self.menu.addAction(self.main_window.dockAction)

Expand DownExpand Up@@ -1125,6 +1151,17 @@ def createGeneralTab(self):
self.overlapColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.overlapColorButton.clicked.connect(main_window.editOverlapColor)

# Undefined (not-found) region plotting
self.undefinedCheck = QCheckBox('', self)
undefined_connector = partial(main_window.toggleUndefined)
self.undefinedCheck.stateChanged.connect(undefined_connector)

self.undefinedColorButton = QPushButton()
self.undefinedColorButton.setCursor(QtCore.Qt.PointingHandCursor)
self.undefinedColorButton.setFixedWidth(button_width)
self.undefinedColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.undefinedColorButton.clicked.connect(main_window.editUndefinedColor)

self.colorResetButton = QPushButton("&Reset Colors")
self.colorResetButton.setCursor(QtCore.Qt.PointingHandCursor)
self.colorResetButton.clicked.connect(main_window.resetColors)
Expand All@@ -1147,6 +1184,9 @@ def createGeneralTab(self):
formLayout.addRow('Show Overlaps:', self.overlapCheck)
formLayout.addRow('Overlap Color:', self.overlapColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Show Undefined:', self.undefinedCheck)
formLayout.addRow('Undefined Color:', self.undefinedColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Color Plot By:', self.colorbyBox)
formLayout.addRow('Universe Level:', self.universeLevelBox)
formLayout.addRow(self.colorResetButton, None)
Expand DownExpand Up@@ -1314,6 +1354,8 @@ def updateDialogValues(self):
self.updateDomainTabs()
self.updateOverlap()
self.updateOverlapColor()
self.updateUndefined()
self.updateUndefinedColor()

def updateMasking(self):
masking = self.model.activeView.masking
Expand DownExpand Up@@ -1383,10 +1425,22 @@ def updateOverlap(self):
if colorby in ('cell', 'material'):
self.overlapCheck.setChecked(overlap_val)

def updateUndefinedColor(self):
color = self.model.activeView.undefined_color
self.undefinedColorButton.setStyleSheet("border-radius: 8px;"
"background-color: rgb%s" % (str(color)))

def updateUndefined(self):
colorby = self.model.activeView.colorby
undefined_val = self.model.activeView.color_undefined
if colorby in ('cell', 'material'):
self.undefinedCheck.setChecked(undefined_val)

def updateColorBy(self):
colorby = self.model.activeView.colorby
self.colorbyBox.setCurrentText(colorby)
self.overlapCheck.setEnabled(colorby in ("cell", "material"))
self.undefinedCheck.setEnabled(colorby in ("cell", "material"))
self.universeLevelBox.setEnabled(colorby == 'cell')

def updateUniverseLevel(self):
Expand Down
31 changes: 31 additions & 0 deletions openmc_plotter/plotmodel.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -327,6 +327,12 @@ def __init__(self, use_settings_pkl, model_path, default_res):
# Map to be populated by overlap functions
self.overlap_info = None

# Boolean mask of internal undefined (not-found) regions, populated by
# makePlot when undefined-region coloring is enabled. Internal regions
# are enclosed by defined geometry (potentially unsafe); external
# (boundary-connected) undefined regions are intentionally ignored.
self.undefined_internal = None

self.version = __version__

# default statepoint value
Expand DownExpand Up@@ -585,6 +591,18 @@ def makePlot(self, view: Optional["PlotView"] = None,
if dom.highlight:
image[self.ids == int(id)] = cv.highlightBackground

# Classify and color undefined (not-found) regions. Only internal
# regions (holes enclosed by defined geometry) are flagged as a
# warning; external regions connect to the slice boundary and are
# left untouched.
self.undefined_internal = None
if cv.color_undefined:
_, _, internal = \
openmc.Model._classify_undefined_regions(self.cell_ids)
if internal is not None:
self.undefined_internal = internal
image[internal] = cv.undefined_color

# set model image
self.image = image

Expand DownExpand Up@@ -1228,6 +1246,11 @@ class PlotViewIndependent:
RGB color to apply to plot background
overlap_color : 3-tuple of int
RGB color to apply for cell overlap regions
color_undefined : bool
Indicator of whether or not internal undefined (not-found) regions
will be shown
undefined_color : 3-tuple of int
RGB color to apply for internal (enclosed) undefined regions
domainAlpha : float between 0 and 1
Alpha value of the geometry plot
plotVisibile : bool
Expand DownExpand Up@@ -1277,6 +1300,9 @@ def __init__(self):
self.highlightSeed = 1
self.domainBackground = (50, 50, 50)
self.overlap_color = (255, 0, 0)
# Undefined (not-found) region coloring (internal regions only)
self.color_undefined = False
self.undefined_color = (255, 165, 0)
self.domainAlpha = 1.0
self.domainVisible = True
self.outlinesCell = False
Expand DownExpand Up@@ -1314,6 +1340,11 @@ def __setstate__(self, state):
self.outlinesCell = False
if not hasattr(self, 'outlinesMat'):
self.outlinesMat = False
# Undefined region coloring (added in a later version)
if not hasattr(self, 'color_undefined'):
self.color_undefined = False
if not hasattr(self, 'undefined_color'):
self.undefined_color = (255, 165, 0)
# Migrate old boolean attributes to new tallyDataMinMaxType
if not hasattr(self, 'tallyDataMinMaxType'):
if getattr(self, 'tallyDataUserMinMax', False):
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
31 changes: 30 additions & 1 deletion openmc_plotter/main_window.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -378,6 +378,16 @@ def createMenuBar(self):
self.overlapAct.toggled.connect(overlap_connector)
self.editMenu.addAction(self.overlapAct)

self.undefinedAct = QAction('Enable Undefined Region Coloring', self)
self.undefinedAct.setShortcut('Ctrl+I')
self.undefinedAct.setCheckable(True)
self.undefinedAct.setToolTip('Toggle undefined regions')
self.undefinedAct.setStatusTip('Toggle display of undefined '
'(not found) regions when enabled')
undefined_connector = partial(self.toggleUndefined, apply=True)
self.undefinedAct.toggled.connect(undefined_connector)
self.editMenu.addAction(self.undefinedAct)

self.outlineAct = QAction('Enable Domain Outlines', self)
self.outlineAct.setShortcut('Ctrl+U')
self.outlineAct.setCheckable(True)
Expand DownExpand Up@@ -438,14 +448,15 @@ def updateEditMenu(self):
self.restoreAction.setDisabled(not changed)

toggle_actions = (self.maskingAction, self.highlightingAct,
self.outlineAct, self.overlapAct)
self.outlineAct, self.overlapAct, self.undefinedAct)
# Temporarily block signals to avoid triggering plot update
for action in toggle_actions:
action.blockSignals(True)
self.maskingAction.setChecked(self.model.currentView.masking)
self.highlightingAct.setChecked(self.model.currentView.highlighting)
self.outlineAct.setChecked(self.model.currentView.outlinesCell)
self.overlapAct.setChecked(self.model.currentView.color_overlaps)
self.undefinedAct.setChecked(self.model.currentView.color_undefined)
for action in toggle_actions:
action.blockSignals(False)

Expand DownExpand Up@@ -742,6 +753,12 @@ def toggleOverlaps(self, state, apply=False):
if apply:
self.applyChanges()

def toggleUndefined(self, state, apply=False):
self.model.activeView.color_undefined = bool(state)
self.colorDialog.updateUndefined()
if apply:
self.applyChanges()

def editColorMap(self, colormap_name, property_type, apply=False):
self.model.activeView.colormaps[property_type] = colormap_name
self.plotIm.updateColorMap(colormap_name, property_type)
Expand DownExpand Up@@ -935,6 +952,18 @@ def editOverlapColor(self, apply=False):
if apply:
self.applyChanges()

def editUndefinedColor(self, apply=False):
current_color = self.model.activeView.undefined_color
dlg = QColorDialog(self)
dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color))
if dlg.exec():
new_color = dlg.currentColor().getRgb()[:3]
self.model.activeView.undefined_color = new_color
self.colorDialog.updateUndefinedColor()

if apply:
self.applyChanges()

def editBackgroundColor(self, apply=False):
current_color = self.model.activeView.domainBackground
dlg = QColorDialog(self)
Expand Down
1 change: 1 addition & 0 deletions openmc_plotter/overlays.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@ class ShortcutsOverlay(QWidget):
("Toggle Masking", c_key + "+M"),
("Toggle Highlighting", c_key + "+L"),
("Toggle Overlap Coloring", c_key + "+P"),
("Toggle Undefined Coloring", c_key + "+I"),
("Toggle Domain Outlines", c_key + "+U"),
("Set XY Basis", "Alt+X"),
("Set YZ Basis", "Alt+Y"),
Expand Down
58 changes: 56 additions & 2 deletions openmc_plotter/plotgui.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -361,6 +361,22 @@ def _overlapInfo(self, id):
label2 = self._cellLabel(cell2)
return f"OVERLAP: Universe {universe}, Cells {label1} and {label2}"

def _isUndefinedInternal(self, event):
"""Whether the pixel under the event is an internal undefined region."""
if self.model.undefined_internal is None:
return False
xPos, yPos = self.getDataIndices(event)
cv = self.model.currentView
if not (0 <= yPos < cv.v_res and 0 <= xPos < cv.h_res):
return False
return bool(self.model.undefined_internal[yPos, xPos])

def _undefinedInfo(self, event):
"""Status-bar text for an undefined (not-found) pixel, if classified."""
if self._isUndefinedInternal(event):
return "WARNING: undefined internal region"
return ""

def mouseDoubleClickEvent(self, event):
xCenter, yCenter = self.getPlotCoords(event.pos())
self.main_window.editPlotOrigin(xCenter, yCenter, apply=True)
Expand DownExpand Up@@ -414,7 +430,7 @@ def mouseMoveEvent(self, event):
density,
temperature))
else:
domainInfo = ""
domainInfo = self._undefinedInfo(event)

if self.model.tally_data is not None:
tid, value = self.getTallyInfo(event)
Expand DownExpand Up@@ -568,7 +584,16 @@ def contextMenuEvent(self, event):

if cv.colorby not in _MODEL_PROPERTIES:
self.menu.addSeparator()
if int(id) == _NOT_FOUND:
if int(id) == _NOT_FOUND and self._isUndefinedInternal(event):
undefColorAction = self.menu.addAction(
'Edit Undefined Color...')
undefColorAction.setToolTip('Edit undefined color')
undefColorAction.setStatusTip(
'Edit plot undefined region color')
connector = partial(self.main_window.editUndefinedColor,
apply=True)
undefColorAction.triggered.connect(connector)
elif int(id) == _NOT_FOUND:
bgColorAction = self.menu.addAction(
'Edit Background Color...')
bgColorAction.setToolTip('Edit background color')
Expand DownExpand Up@@ -598,6 +623,7 @@ def contextMenuEvent(self, event):
self.menu.addAction(self.main_window.maskingAction)
self.menu.addAction(self.main_window.highlightingAct)
self.menu.addAction(self.main_window.overlapAct)
self.menu.addAction(self.main_window.undefinedAct)
self.menu.addSeparator()
self.menu.addAction(self.main_window.dockAction)

Expand DownExpand Up@@ -1125,6 +1151,17 @@ def createGeneralTab(self):
self.overlapColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.overlapColorButton.clicked.connect(main_window.editOverlapColor)

# Undefined (not-found) region plotting
self.undefinedCheck = QCheckBox('', self)
undefined_connector = partial(main_window.toggleUndefined)
self.undefinedCheck.stateChanged.connect(undefined_connector)

self.undefinedColorButton = QPushButton()
self.undefinedColorButton.setCursor(QtCore.Qt.PointingHandCursor)
self.undefinedColorButton.setFixedWidth(button_width)
self.undefinedColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.undefinedColorButton.clicked.connect(main_window.editUndefinedColor)

self.colorResetButton = QPushButton("&Reset Colors")
self.colorResetButton.setCursor(QtCore.Qt.PointingHandCursor)
self.colorResetButton.clicked.connect(main_window.resetColors)
Expand All@@ -1147,6 +1184,9 @@ def createGeneralTab(self):
formLayout.addRow('Show Overlaps:', self.overlapCheck)
formLayout.addRow('Overlap Color:', self.overlapColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Show Undefined:', self.undefinedCheck)
formLayout.addRow('Undefined Color:', self.undefinedColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Color Plot By:', self.colorbyBox)
formLayout.addRow('Universe Level:', self.universeLevelBox)
formLayout.addRow(self.colorResetButton, None)
Expand DownExpand Up@@ -1314,6 +1354,8 @@ def updateDialogValues(self):
self.updateDomainTabs()
self.updateOverlap()
self.updateOverlapColor()
self.updateUndefined()
self.updateUndefinedColor()

def updateMasking(self):
masking = self.model.activeView.masking
Expand DownExpand Up@@ -1383,10 +1425,22 @@ def updateOverlap(self):
if colorby in ('cell', 'material'):
self.overlapCheck.setChecked(overlap_val)

def updateUndefinedColor(self):
color = self.model.activeView.undefined_color
self.undefinedColorButton.setStyleSheet("border-radius: 8px;"
"background-color: rgb%s" % (str(color)))

def updateUndefined(self):
colorby = self.model.activeView.colorby
undefined_val = self.model.activeView.color_undefined
if colorby in ('cell', 'material'):
self.undefinedCheck.setChecked(undefined_val)

def updateColorBy(self):
colorby = self.model.activeView.colorby
self.colorbyBox.setCurrentText(colorby)
self.overlapCheck.setEnabled(colorby in ("cell", "material"))
self.undefinedCheck.setEnabled(colorby in ("cell", "material"))
self.universeLevelBox.setEnabled(colorby == 'cell')

def updateUniverseLevel(self):
Expand Down
31 changes: 31 additions & 0 deletions openmc_plotter/plotmodel.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -327,6 +327,12 @@ def __init__(self, use_settings_pkl, model_path, default_res):
# Map to be populated by overlap functions
self.overlap_info = None

# Boolean mask of internal undefined (not-found) regions, populated by
# makePlot when undefined-region coloring is enabled. Internal regions
# are enclosed by defined geometry (potentially unsafe); external
# (boundary-connected) undefined regions are intentionally ignored.
self.undefined_internal = None

self.version = __version__

# default statepoint value
Expand DownExpand Up@@ -585,6 +591,18 @@ def makePlot(self, view: Optional["PlotView"] = None,
if dom.highlight:
image[self.ids == int(id)] = cv.highlightBackground

# Classify and color undefined (not-found) regions. Only internal
# regions (holes enclosed by defined geometry) are flagged as a
# warning; external regions connect to the slice boundary and are
# left untouched.
self.undefined_internal = None
if cv.color_undefined:
_, _, internal = \
openmc.Model._classify_undefined_regions(self.cell_ids)
if internal is not None:
self.undefined_internal = internal
image[internal] = cv.undefined_color

# set model image
self.image = image

Expand DownExpand Up@@ -1228,6 +1246,11 @@ class PlotViewIndependent:
RGB color to apply to plot background
overlap_color : 3-tuple of int
RGB color to apply for cell overlap regions
color_undefined : bool
Indicator of whether or not internal undefined (not-found) regions
will be shown
undefined_color : 3-tuple of int
RGB color to apply for internal (enclosed) undefined regions
domainAlpha : float between 0 and 1
Alpha value of the geometry plot
plotVisibile : bool
Expand DownExpand Up@@ -1277,6 +1300,9 @@ def __init__(self):
self.highlightSeed = 1
self.domainBackground = (50, 50, 50)
self.overlap_color = (255, 0, 0)
# Undefined (not-found) region coloring (internal regions only)
self.color_undefined = False
self.undefined_color = (255, 165, 0)
self.domainAlpha = 1.0
self.domainVisible = True
self.outlinesCell = False
Expand DownExpand Up@@ -1314,6 +1340,11 @@ def __setstate__(self, state):
self.outlinesCell = False
if not hasattr(self, 'outlinesMat'):
self.outlinesMat = False
# Undefined region coloring (added in a later version)
if not hasattr(self, 'color_undefined'):
self.color_undefined = False
if not hasattr(self, 'undefined_color'):
self.undefined_color = (255, 165, 0)
# Migrate old boolean attributes to new tallyDataMinMaxType
if not hasattr(self, 'tallyDataMinMaxType'):
if getattr(self, 'tallyDataUserMinMax', False):
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
31 changes: 30 additions & 1 deletion openmc_plotter/main_window.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -378,6 +378,16 @@ def createMenuBar(self):
self.overlapAct.toggled.connect(overlap_connector)
self.editMenu.addAction(self.overlapAct)

self.undefinedAct = QAction('Enable Undefined Region Coloring', self)
self.undefinedAct.setShortcut('Ctrl+I')
self.undefinedAct.setCheckable(True)
self.undefinedAct.setToolTip('Toggle undefined regions')
self.undefinedAct.setStatusTip('Toggle display of undefined '
'(not found) regions when enabled')
undefined_connector = partial(self.toggleUndefined, apply=True)
self.undefinedAct.toggled.connect(undefined_connector)
self.editMenu.addAction(self.undefinedAct)

self.outlineAct = QAction('Enable Domain Outlines', self)
self.outlineAct.setShortcut('Ctrl+U')
self.outlineAct.setCheckable(True)
Expand DownExpand Up@@ -438,14 +448,15 @@ def updateEditMenu(self):
self.restoreAction.setDisabled(not changed)

toggle_actions = (self.maskingAction, self.highlightingAct,
self.outlineAct, self.overlapAct)
self.outlineAct, self.overlapAct, self.undefinedAct)
# Temporarily block signals to avoid triggering plot update
for action in toggle_actions:
action.blockSignals(True)
self.maskingAction.setChecked(self.model.currentView.masking)
self.highlightingAct.setChecked(self.model.currentView.highlighting)
self.outlineAct.setChecked(self.model.currentView.outlinesCell)
self.overlapAct.setChecked(self.model.currentView.color_overlaps)
self.undefinedAct.setChecked(self.model.currentView.color_undefined)
for action in toggle_actions:
action.blockSignals(False)

Expand DownExpand Up@@ -742,6 +753,12 @@ def toggleOverlaps(self, state, apply=False):
if apply:
self.applyChanges()

def toggleUndefined(self, state, apply=False):
self.model.activeView.color_undefined = bool(state)
self.colorDialog.updateUndefined()
if apply:
self.applyChanges()

def editColorMap(self, colormap_name, property_type, apply=False):
self.model.activeView.colormaps[property_type] = colormap_name
self.plotIm.updateColorMap(colormap_name, property_type)
Expand DownExpand Up@@ -935,6 +952,18 @@ def editOverlapColor(self, apply=False):
if apply:
self.applyChanges()

def editUndefinedColor(self, apply=False):
current_color = self.model.activeView.undefined_color
dlg = QColorDialog(self)
dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color))
if dlg.exec():
new_color = dlg.currentColor().getRgb()[:3]
self.model.activeView.undefined_color = new_color
self.colorDialog.updateUndefinedColor()

if apply:
self.applyChanges()

def editBackgroundColor(self, apply=False):
current_color = self.model.activeView.domainBackground
dlg = QColorDialog(self)
Expand Down
1 change: 1 addition & 0 deletions openmc_plotter/overlays.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@ class ShortcutsOverlay(QWidget):
("Toggle Masking", c_key + "+M"),
("Toggle Highlighting", c_key + "+L"),
("Toggle Overlap Coloring", c_key + "+P"),
("Toggle Undefined Coloring", c_key + "+I"),
("Toggle Domain Outlines", c_key + "+U"),
("Set XY Basis", "Alt+X"),
("Set YZ Basis", "Alt+Y"),
Expand Down
58 changes: 56 additions & 2 deletions openmc_plotter/plotgui.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -361,6 +361,22 @@ def _overlapInfo(self, id):
label2 = self._cellLabel(cell2)
return f"OVERLAP: Universe {universe}, Cells {label1} and {label2}"

def _isUndefinedInternal(self, event):
"""Whether the pixel under the event is an internal undefined region."""
if self.model.undefined_internal is None:
return False
xPos, yPos = self.getDataIndices(event)
cv = self.model.currentView
if not (0 <= yPos < cv.v_res and 0 <= xPos < cv.h_res):
return False
return bool(self.model.undefined_internal[yPos, xPos])

def _undefinedInfo(self, event):
"""Status-bar text for an undefined (not-found) pixel, if classified."""
if self._isUndefinedInternal(event):
return "WARNING: undefined internal region"
return ""

def mouseDoubleClickEvent(self, event):
xCenter, yCenter = self.getPlotCoords(event.pos())
self.main_window.editPlotOrigin(xCenter, yCenter, apply=True)
Expand DownExpand Up@@ -414,7 +430,7 @@ def mouseMoveEvent(self, event):
density,
temperature))
else:
domainInfo = ""
domainInfo = self._undefinedInfo(event)

if self.model.tally_data is not None:
tid, value = self.getTallyInfo(event)
Expand DownExpand Up@@ -568,7 +584,16 @@ def contextMenuEvent(self, event):

if cv.colorby not in _MODEL_PROPERTIES:
self.menu.addSeparator()
if int(id) == _NOT_FOUND:
if int(id) == _NOT_FOUND and self._isUndefinedInternal(event):
undefColorAction = self.menu.addAction(
'Edit Undefined Color...')
undefColorAction.setToolTip('Edit undefined color')
undefColorAction.setStatusTip(
'Edit plot undefined region color')
connector = partial(self.main_window.editUndefinedColor,
apply=True)
undefColorAction.triggered.connect(connector)
elif int(id) == _NOT_FOUND:
bgColorAction = self.menu.addAction(
'Edit Background Color...')
bgColorAction.setToolTip('Edit background color')
Expand DownExpand Up@@ -598,6 +623,7 @@ def contextMenuEvent(self, event):
self.menu.addAction(self.main_window.maskingAction)
self.menu.addAction(self.main_window.highlightingAct)
self.menu.addAction(self.main_window.overlapAct)
self.menu.addAction(self.main_window.undefinedAct)
self.menu.addSeparator()
self.menu.addAction(self.main_window.dockAction)

Expand DownExpand Up@@ -1125,6 +1151,17 @@ def createGeneralTab(self):
self.overlapColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.overlapColorButton.clicked.connect(main_window.editOverlapColor)

# Undefined (not-found) region plotting
self.undefinedCheck = QCheckBox('', self)
undefined_connector = partial(main_window.toggleUndefined)
self.undefinedCheck.stateChanged.connect(undefined_connector)

self.undefinedColorButton = QPushButton()
self.undefinedColorButton.setCursor(QtCore.Qt.PointingHandCursor)
self.undefinedColorButton.setFixedWidth(button_width)
self.undefinedColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.undefinedColorButton.clicked.connect(main_window.editUndefinedColor)

self.colorResetButton = QPushButton("&Reset Colors")
self.colorResetButton.setCursor(QtCore.Qt.PointingHandCursor)
self.colorResetButton.clicked.connect(main_window.resetColors)
Expand All@@ -1147,6 +1184,9 @@ def createGeneralTab(self):
formLayout.addRow('Show Overlaps:', self.overlapCheck)
formLayout.addRow('Overlap Color:', self.overlapColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Show Undefined:', self.undefinedCheck)
formLayout.addRow('Undefined Color:', self.undefinedColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Color Plot By:', self.colorbyBox)
formLayout.addRow('Universe Level:', self.universeLevelBox)
formLayout.addRow(self.colorResetButton, None)
Expand DownExpand Up@@ -1314,6 +1354,8 @@ def updateDialogValues(self):
self.updateDomainTabs()
self.updateOverlap()
self.updateOverlapColor()
self.updateUndefined()
self.updateUndefinedColor()

def updateMasking(self):
masking = self.model.activeView.masking
Expand DownExpand Up@@ -1383,10 +1425,22 @@ def updateOverlap(self):
if colorby in ('cell', 'material'):
self.overlapCheck.setChecked(overlap_val)

def updateUndefinedColor(self):
color = self.model.activeView.undefined_color
self.undefinedColorButton.setStyleSheet("border-radius: 8px;"
"background-color: rgb%s" % (str(color)))

def updateUndefined(self):
colorby = self.model.activeView.colorby
undefined_val = self.model.activeView.color_undefined
if colorby in ('cell', 'material'):
self.undefinedCheck.setChecked(undefined_val)

def updateColorBy(self):
colorby = self.model.activeView.colorby
self.colorbyBox.setCurrentText(colorby)
self.overlapCheck.setEnabled(colorby in ("cell", "material"))
self.undefinedCheck.setEnabled(colorby in ("cell", "material"))
self.universeLevelBox.setEnabled(colorby == 'cell')

def updateUniverseLevel(self):
Expand Down
31 changes: 31 additions & 0 deletions openmc_plotter/plotmodel.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -327,6 +327,12 @@ def __init__(self, use_settings_pkl, model_path, default_res):
# Map to be populated by overlap functions
self.overlap_info = None

# Boolean mask of internal undefined (not-found) regions, populated by
# makePlot when undefined-region coloring is enabled. Internal regions
# are enclosed by defined geometry (potentially unsafe); external
# (boundary-connected) undefined regions are intentionally ignored.
self.undefined_internal = None

self.version = __version__

# default statepoint value
Expand DownExpand Up@@ -585,6 +591,18 @@ def makePlot(self, view: Optional["PlotView"] = None,
if dom.highlight:
image[self.ids == int(id)] = cv.highlightBackground

# Classify and color undefined (not-found) regions. Only internal
# regions (holes enclosed by defined geometry) are flagged as a
# warning; external regions connect to the slice boundary and are
# left untouched.
self.undefined_internal = None
if cv.color_undefined:
_, _, internal = \
openmc.Model._classify_undefined_regions(self.cell_ids)
if internal is not None:
self.undefined_internal = internal
image[internal] = cv.undefined_color

# set model image
self.image = image

Expand DownExpand Up@@ -1228,6 +1246,11 @@ class PlotViewIndependent:
RGB color to apply to plot background
overlap_color : 3-tuple of int
RGB color to apply for cell overlap regions
color_undefined : bool
Indicator of whether or not internal undefined (not-found) regions
will be shown
undefined_color : 3-tuple of int
RGB color to apply for internal (enclosed) undefined regions
domainAlpha : float between 0 and 1
Alpha value of the geometry plot
plotVisibile : bool
Expand DownExpand Up@@ -1277,6 +1300,9 @@ def __init__(self):
self.highlightSeed = 1
self.domainBackground = (50, 50, 50)
self.overlap_color = (255, 0, 0)
# Undefined (not-found) region coloring (internal regions only)
self.color_undefined = False
self.undefined_color = (255, 165, 0)
self.domainAlpha = 1.0
self.domainVisible = True
self.outlinesCell = False
Expand DownExpand Up@@ -1314,6 +1340,11 @@ def __setstate__(self, state):
self.outlinesCell = False
if not hasattr(self, 'outlinesMat'):
self.outlinesMat = False
# Undefined region coloring (added in a later version)
if not hasattr(self, 'color_undefined'):
self.color_undefined = False
if not hasattr(self, 'undefined_color'):
self.undefined_color = (255, 165, 0)
# Migrate old boolean attributes to new tallyDataMinMaxType
if not hasattr(self, 'tallyDataMinMaxType'):
if getattr(self, 'tallyDataUserMinMax', False):
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
31 changes: 30 additions & 1 deletion openmc_plotter/main_window.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -378,6 +378,16 @@ def createMenuBar(self):
self.overlapAct.toggled.connect(overlap_connector)
self.editMenu.addAction(self.overlapAct)

self.undefinedAct = QAction('Enable Undefined Region Coloring', self)
self.undefinedAct.setShortcut('Ctrl+I')
self.undefinedAct.setCheckable(True)
self.undefinedAct.setToolTip('Toggle undefined regions')
self.undefinedAct.setStatusTip('Toggle display of undefined '
'(not found) regions when enabled')
undefined_connector = partial(self.toggleUndefined, apply=True)
self.undefinedAct.toggled.connect(undefined_connector)
self.editMenu.addAction(self.undefinedAct)

self.outlineAct = QAction('Enable Domain Outlines', self)
self.outlineAct.setShortcut('Ctrl+U')
self.outlineAct.setCheckable(True)
Expand DownExpand Up@@ -438,14 +448,15 @@ def updateEditMenu(self):
self.restoreAction.setDisabled(not changed)

toggle_actions = (self.maskingAction, self.highlightingAct,
self.outlineAct, self.overlapAct)
self.outlineAct, self.overlapAct, self.undefinedAct)
# Temporarily block signals to avoid triggering plot update
for action in toggle_actions:
action.blockSignals(True)
self.maskingAction.setChecked(self.model.currentView.masking)
self.highlightingAct.setChecked(self.model.currentView.highlighting)
self.outlineAct.setChecked(self.model.currentView.outlinesCell)
self.overlapAct.setChecked(self.model.currentView.color_overlaps)
self.undefinedAct.setChecked(self.model.currentView.color_undefined)
for action in toggle_actions:
action.blockSignals(False)

Expand DownExpand Up@@ -742,6 +753,12 @@ def toggleOverlaps(self, state, apply=False):
if apply:
self.applyChanges()

def toggleUndefined(self, state, apply=False):
self.model.activeView.color_undefined = bool(state)
self.colorDialog.updateUndefined()
if apply:
self.applyChanges()

def editColorMap(self, colormap_name, property_type, apply=False):
self.model.activeView.colormaps[property_type] = colormap_name
self.plotIm.updateColorMap(colormap_name, property_type)
Expand DownExpand Up@@ -935,6 +952,18 @@ def editOverlapColor(self, apply=False):
if apply:
self.applyChanges()

def editUndefinedColor(self, apply=False):
current_color = self.model.activeView.undefined_color
dlg = QColorDialog(self)
dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color))
if dlg.exec():
new_color = dlg.currentColor().getRgb()[:3]
self.model.activeView.undefined_color = new_color
self.colorDialog.updateUndefinedColor()

if apply:
self.applyChanges()

def editBackgroundColor(self, apply=False):
current_color = self.model.activeView.domainBackground
dlg = QColorDialog(self)
Expand Down
1 change: 1 addition & 0 deletions openmc_plotter/overlays.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@ class ShortcutsOverlay(QWidget):
("Toggle Masking", c_key + "+M"),
("Toggle Highlighting", c_key + "+L"),
("Toggle Overlap Coloring", c_key + "+P"),
("Toggle Undefined Coloring", c_key + "+I"),
("Toggle Domain Outlines", c_key + "+U"),
("Set XY Basis", "Alt+X"),
("Set YZ Basis", "Alt+Y"),
Expand Down
58 changes: 56 additions & 2 deletions openmc_plotter/plotgui.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -361,6 +361,22 @@ def _overlapInfo(self, id):
label2 = self._cellLabel(cell2)
return f"OVERLAP: Universe {universe}, Cells {label1} and {label2}"

def _isUndefinedInternal(self, event):
"""Whether the pixel under the event is an internal undefined region."""
if self.model.undefined_internal is None:
return False
xPos, yPos = self.getDataIndices(event)
cv = self.model.currentView
if not (0 <= yPos < cv.v_res and 0 <= xPos < cv.h_res):
return False
return bool(self.model.undefined_internal[yPos, xPos])

def _undefinedInfo(self, event):
"""Status-bar text for an undefined (not-found) pixel, if classified."""
if self._isUndefinedInternal(event):
return "WARNING: undefined internal region"
return ""

def mouseDoubleClickEvent(self, event):
xCenter, yCenter = self.getPlotCoords(event.pos())
self.main_window.editPlotOrigin(xCenter, yCenter, apply=True)
Expand DownExpand Up@@ -414,7 +430,7 @@ def mouseMoveEvent(self, event):
density,
temperature))
else:
domainInfo = ""
domainInfo = self._undefinedInfo(event)

if self.model.tally_data is not None:
tid, value = self.getTallyInfo(event)
Expand DownExpand Up@@ -568,7 +584,16 @@ def contextMenuEvent(self, event):

if cv.colorby not in _MODEL_PROPERTIES:
self.menu.addSeparator()
if int(id) == _NOT_FOUND:
if int(id) == _NOT_FOUND and self._isUndefinedInternal(event):
undefColorAction = self.menu.addAction(
'Edit Undefined Color...')
undefColorAction.setToolTip('Edit undefined color')
undefColorAction.setStatusTip(
'Edit plot undefined region color')
connector = partial(self.main_window.editUndefinedColor,
apply=True)
undefColorAction.triggered.connect(connector)
elif int(id) == _NOT_FOUND:
bgColorAction = self.menu.addAction(
'Edit Background Color...')
bgColorAction.setToolTip('Edit background color')
Expand DownExpand Up@@ -598,6 +623,7 @@ def contextMenuEvent(self, event):
self.menu.addAction(self.main_window.maskingAction)
self.menu.addAction(self.main_window.highlightingAct)
self.menu.addAction(self.main_window.overlapAct)
self.menu.addAction(self.main_window.undefinedAct)
self.menu.addSeparator()
self.menu.addAction(self.main_window.dockAction)

Expand DownExpand Up@@ -1125,6 +1151,17 @@ def createGeneralTab(self):
self.overlapColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.overlapColorButton.clicked.connect(main_window.editOverlapColor)

# Undefined (not-found) region plotting
self.undefinedCheck = QCheckBox('', self)
undefined_connector = partial(main_window.toggleUndefined)
self.undefinedCheck.stateChanged.connect(undefined_connector)

self.undefinedColorButton = QPushButton()
self.undefinedColorButton.setCursor(QtCore.Qt.PointingHandCursor)
self.undefinedColorButton.setFixedWidth(button_width)
self.undefinedColorButton.setFixedHeight(self.font_metric.height() * 1.5)
self.undefinedColorButton.clicked.connect(main_window.editUndefinedColor)

self.colorResetButton = QPushButton("&Reset Colors")
self.colorResetButton.setCursor(QtCore.Qt.PointingHandCursor)
self.colorResetButton.clicked.connect(main_window.resetColors)
Expand All@@ -1147,6 +1184,9 @@ def createGeneralTab(self):
formLayout.addRow('Show Overlaps:', self.overlapCheck)
formLayout.addRow('Overlap Color:', self.overlapColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Show Undefined:', self.undefinedCheck)
formLayout.addRow('Undefined Color:', self.undefinedColorButton)
formLayout.addRow(HorizontalLine())
formLayout.addRow('Color Plot By:', self.colorbyBox)
formLayout.addRow('Universe Level:', self.universeLevelBox)
formLayout.addRow(self.colorResetButton, None)
Expand DownExpand Up@@ -1314,6 +1354,8 @@ def updateDialogValues(self):
self.updateDomainTabs()
self.updateOverlap()
self.updateOverlapColor()
self.updateUndefined()
self.updateUndefinedColor()

def updateMasking(self):
masking = self.model.activeView.masking
Expand DownExpand Up@@ -1383,10 +1425,22 @@ def updateOverlap(self):
if colorby in ('cell', 'material'):
self.overlapCheck.setChecked(overlap_val)

def updateUndefinedColor(self):
color = self.model.activeView.undefined_color
self.undefinedColorButton.setStyleSheet("border-radius: 8px;"
"background-color: rgb%s" % (str(color)))

def updateUndefined(self):
colorby = self.model.activeView.colorby
undefined_val = self.model.activeView.color_undefined
if colorby in ('cell', 'material'):
self.undefinedCheck.setChecked(undefined_val)

def updateColorBy(self):
colorby = self.model.activeView.colorby
self.colorbyBox.setCurrentText(colorby)
self.overlapCheck.setEnabled(colorby in ("cell", "material"))
self.undefinedCheck.setEnabled(colorby in ("cell", "material"))
self.universeLevelBox.setEnabled(colorby == 'cell')

def updateUniverseLevel(self):
Expand Down
31 changes: 31 additions & 0 deletions openmc_plotter/plotmodel.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -327,6 +327,12 @@ def __init__(self, use_settings_pkl, model_path, default_res):
# Map to be populated by overlap functions
self.overlap_info = None

# Boolean mask of internal undefined (not-found) regions, populated by
# makePlot when undefined-region coloring is enabled. Internal regions
# are enclosed by defined geometry (potentially unsafe); external
# (boundary-connected) undefined regions are intentionally ignored.
self.undefined_internal = None

self.version = __version__

# default statepoint value
Expand DownExpand Up@@ -585,6 +591,18 @@ def makePlot(self, view: Optional["PlotView"] = None,
if dom.highlight:
image[self.ids == int(id)] = cv.highlightBackground

# Classify and color undefined (not-found) regions. Only internal
# regions (holes enclosed by defined geometry) are flagged as a
# warning; external regions connect to the slice boundary and are
# left untouched.
self.undefined_internal = None
if cv.color_undefined:
_, _, internal = \
openmc.Model._classify_undefined_regions(self.cell_ids)
if internal is not None:
self.undefined_internal = internal
image[internal] = cv.undefined_color

# set model image
self.image = image

Expand DownExpand Up@@ -1228,6 +1246,11 @@ class PlotViewIndependent:
RGB color to apply to plot background
overlap_color : 3-tuple of int
RGB color to apply for cell overlap regions
color_undefined : bool
Indicator of whether or not internal undefined (not-found) regions
will be shown
undefined_color : 3-tuple of int
RGB color to apply for internal (enclosed) undefined regions
domainAlpha : float between 0 and 1
Alpha value of the geometry plot
plotVisibile : bool
Expand DownExpand Up@@ -1277,6 +1300,9 @@ def __init__(self):
self.highlightSeed = 1
self.domainBackground = (50, 50, 50)
self.overlap_color = (255, 0, 0)
# Undefined (not-found) region coloring (internal regions only)
self.color_undefined = False
self.undefined_color = (255, 165, 0)
self.domainAlpha = 1.0
self.domainVisible = True
self.outlinesCell = False
Expand DownExpand Up@@ -1314,6 +1340,11 @@ def __setstate__(self, state):
self.outlinesCell = False
if not hasattr(self, 'outlinesMat'):
self.outlinesMat = False
# Undefined region coloring (added in a later version)
if not hasattr(self, 'color_undefined'):
self.color_undefined = False
if not hasattr(self, 'undefined_color'):
self.undefined_color = (255, 165, 0)
# Migrate old boolean attributes to new tallyDataMinMaxType
if not hasattr(self, 'tallyDataMinMaxType'):
if getattr(self, 'tallyDataUserMinMax', False):
Expand Down
Loading