From 930d0f23098d4a49374a99eb1a39cb693d448269 Mon Sep 17 00:00:00 2001 From: Viktor Mai Date: Wed, 3 Jun 2026 17:31:55 -0500 Subject: [PATCH 1/7] Working improved plotter overlap info --- openmc_plotter/plotgui.py | 41 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/openmc_plotter/plotgui.py b/openmc_plotter/plotgui.py index 13dd69a..1d223ed 100644 --- a/openmc_plotter/plotgui.py +++ b/openmc_plotter/plotgui.py @@ -1,5 +1,6 @@ import io from functools import partial +import openmc from PySide6 import QtCore, QtGui from PySide6.QtWidgets import (QWidget, QPushButton, QHBoxLayout, QVBoxLayout, @@ -371,7 +372,45 @@ def mouseMoveEvent(self, event): if id == _VOID_REGION: domainInfo = ("VOID") elif id == _OVERLAP: - domainInfo = ("OVERLAP") + x_pix, y_pix = self.getDataIndices(event) + cell1, cell2, universe = openmc.lib.slice_plot_overlap_data(x_pix, y_pix) + + if len(cell1) > 0: + unique_cells = [] + seen = set() + + for c1, c2 in zip(cell1, cell2): + for cid in (c1, c2): + if cid not in seen: + seen.add(cid) + try: + cell_obj = self.model.activeView.cells[cid] + label = f'"{cell_obj.name}"' if cell_obj.name else f'cell {cid}' + except Exception: + label = f'cell {cid}' + unique_cells.append(label) + + max_names = 3 + if len(unique_cells) <= max_names: + if len(unique_cells) == 1: + domainInfo = f"OVERLAP: {unique_cells[0]}" + elif len(unique_cells) == 2: + domainInfo = f"OVERLAP: {unique_cells[0]} and {unique_cells[1]} have an overlap" + else: + domainInfo = ( + "OVERLAP: " + + ", ".join(unique_cells[:-1]) + + f", and {unique_cells[-1]} have an overlap" + ) + else: + shown = ", ".join(unique_cells[:max_names]) + remaining = len(unique_cells) - max_names + domainInfo = ( + f"OVERLAP: {shown}, and {remaining} more cells have an overlap" + ) + else: + domainInfo = "OVERLAP" + elif id != _NOT_FOUND and domain[id].name: domainInfo = ("{} {}{}: \"{}\"\t Density: {} g/cc\t" "Temperature: {} K".format( From cb32cdd7ad45c025087f4f90a6f6b43c0af18200 Mon Sep 17 00:00:00 2001 From: Viktor Mai Date: Thu, 25 Jun 2026 14:25:19 -0500 Subject: [PATCH 2/7] Changed name to slice_data --- openmc_plotter/plotgui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc_plotter/plotgui.py b/openmc_plotter/plotgui.py index 1d223ed..5eb778b 100644 --- a/openmc_plotter/plotgui.py +++ b/openmc_plotter/plotgui.py @@ -373,7 +373,7 @@ def mouseMoveEvent(self, event): domainInfo = ("VOID") elif id == _OVERLAP: x_pix, y_pix = self.getDataIndices(event) - cell1, cell2, universe = openmc.lib.slice_plot_overlap_data(x_pix, y_pix) + cell1, cell2, universe = openmc.lib.slice_data_overlap_info(x_pix, y_pix) if len(cell1) > 0: unique_cells = [] From 28fe62e3a1afbe5634c3fb808942a14c7ef7b67a Mon Sep 17 00:00:00 2001 From: Viktor Mai Date: Thu, 2 Jul 2026 10:17:33 -0500 Subject: [PATCH 3/7] Overlaps read from material id --- openmc_plotter/plotgui.py | 57 ++++++++++--------------------------- openmc_plotter/plotmodel.py | 17 +++++++++-- 2 files changed, 30 insertions(+), 44 deletions(-) diff --git a/openmc_plotter/plotgui.py b/openmc_plotter/plotgui.py index 5eb778b..062ec38 100644 --- a/openmc_plotter/plotgui.py +++ b/openmc_plotter/plotgui.py @@ -309,7 +309,10 @@ def getIDinfo(self, event): # check that the position is in the axes view if 0 <= yPos < self.model.currentView.v_res \ and 0 <= xPos and xPos < self.model.currentView.h_res: - id = self.model.ids[yPos, xPos] + if self.model.currentView.colorby == 'cell': + id = int(self.model.cell_ids[yPos, xPos]) + else: + id = int(self.model.mat_ids[yPos, xPos]) instance = self.model.instances[yPos, xPos] temp = "{:g}".format(self.model.property_data[yPos, xPos, 0]) density = "{:g}".format(self.model.property_data[yPos, xPos, 1]) @@ -355,7 +358,6 @@ def mouseMoveEvent(self, event): tallyInfo = "" if self.parent.underMouse(): - if domain_kind.lower() in _MODEL_PROPERTIES: line_val = float(properties[domain_kind.lower()]) line_val = max(line_val, 0.0) @@ -371,46 +373,17 @@ def mouseMoveEvent(self, event): instanceInfo = "" if id == _VOID_REGION: domainInfo = ("VOID") - elif id == _OVERLAP: - x_pix, y_pix = self.getDataIndices(event) - cell1, cell2, universe = openmc.lib.slice_data_overlap_info(x_pix, y_pix) - - if len(cell1) > 0: - unique_cells = [] - seen = set() - - for c1, c2 in zip(cell1, cell2): - for cid in (c1, c2): - if cid not in seen: - seen.add(cid) - try: - cell_obj = self.model.activeView.cells[cid] - label = f'"{cell_obj.name}"' if cell_obj.name else f'cell {cid}' - except Exception: - label = f'cell {cid}' - unique_cells.append(label) - - max_names = 3 - if len(unique_cells) <= max_names: - if len(unique_cells) == 1: - domainInfo = f"OVERLAP: {unique_cells[0]}" - elif len(unique_cells) == 2: - domainInfo = f"OVERLAP: {unique_cells[0]} and {unique_cells[1]} have an overlap" - else: - domainInfo = ( - "OVERLAP: " - + ", ".join(unique_cells[:-1]) - + f", and {unique_cells[-1]} have an overlap" - ) - else: - shown = ", ".join(unique_cells[:max_names]) - remaining = len(unique_cells) - max_names - domainInfo = ( - f"OVERLAP: {shown}, and {remaining} more cells have an overlap" - ) + elif id < _OVERLAP: + # Unpack the index and find it in overlap map + overlap_idx = int(_OVERLAP - int(id) - 1) + if overlap_idx in self.model.overlap_map: + universe, cell1, cell2 = self.model.overlap_map[overlap_idx] + domainInfo = ( + f"OVERLAP: Universe {universe}, " + f"Cells {cell1}/{cell2}" + ) else: - domainInfo = "OVERLAP" - + domainInfo = "OVERLAP (unknown region)" elif id != _NOT_FOUND and domain[id].name: domainInfo = ("{} {}{}: \"{}\"\t Density: {} g/cc\t" "Temperature: {} K".format( @@ -522,7 +495,7 @@ def contextMenuEvent(self, event): self.menu.addAction(self.main_window.redoAction) self.menu.addSeparator() - if int(id) not in (_NOT_FOUND, _OVERLAP) and \ + if int(id) not in (_NOT_FOUND) and int(id) >= _OVERLAP and \ cv.colorby not in _MODEL_PROPERTIES: # Domain ID diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index 95e01f2..c454731 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -324,6 +324,9 @@ def __init__(self, use_settings_pkl, model_path, default_res): self.property_data = None self.map_view_params = None + # Map to be populated by overlap functions + self.overlap_map = {} + self.version = __version__ # default statepoint value @@ -530,24 +533,34 @@ def makePlot(self, view: Optional["PlotView"] = None, filter=filter_cpp, ) self.map_view_params = self.view_params_payload(view) + else: self.geom_data = geom_data self.property_data = property_data self.map_view_params = self.view_params_payload(view) + overlap_info, n = openmc.lib.slice_data_overlap_info() + self.overlap_map = {} + for i in range(n): + self.overlap_map[i] = (overlap_info[i*3], overlap_info[i*3+1], overlap_info[i*3+2]) + # update current view cv = self.currentView = copy.deepcopy(view) # set model ids based on domain if cv.colorby == 'cell': - self.ids = self.cell_ids + self.ids = self.cell_ids.copy() domain = cv.cells source = self.modelCells else: - self.ids = self.mat_ids + self.ids = self.mat_ids.copy() domain = cv.materials source = self.modelMaterials + # Normalizes so that domain only sees -3, but + # overlap indices are still available in cell_ids + self.ids[self.ids < _OVERLAP] = _OVERLAP # new line + # generate colors if not present for cell_id, cell in cv.cells.items(): if cell.color is None: From 4cb77fc953780bb23778218f29ebba4dae802cce Mon Sep 17 00:00:00 2001 From: Viktor Mai Date: Thu, 2 Jul 2026 10:42:53 -0500 Subject: [PATCH 4/7] Includes named cells if available --- openmc_plotter/plotgui.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/openmc_plotter/plotgui.py b/openmc_plotter/plotgui.py index 062ec38..13aa91e 100644 --- a/openmc_plotter/plotgui.py +++ b/openmc_plotter/plotgui.py @@ -378,9 +378,17 @@ def mouseMoveEvent(self, event): overlap_idx = int(_OVERLAP - int(id) - 1) if overlap_idx in self.model.overlap_map: universe, cell1, cell2 = self.model.overlap_map[overlap_idx] + try: + name1 = self.model.activeView.cells[cell1].name or str(cell1) + except KeyError: + name1 = str(cell1) + try: + name2 = self.model.activeView.cells[cell2].name or str(cell2) + except KeyError: + name2 = str(cell2) domainInfo = ( f"OVERLAP: Universe {universe}, " - f"Cells {cell1}/{cell2}" + f"Cells {name1} and {name2}" ) else: domainInfo = "OVERLAP (unknown region)" From c9c0358658db520ab15c9fed9043851c2252acad Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 8 Jul 2026 12:10:46 -0500 Subject: [PATCH 5/7] Fix overlap info in color-by-cell view --- openmc_plotter/plotgui.py | 62 ++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/openmc_plotter/plotgui.py b/openmc_plotter/plotgui.py index 13aa91e..cb809df 100644 --- a/openmc_plotter/plotgui.py +++ b/openmc_plotter/plotgui.py @@ -309,10 +309,17 @@ def getIDinfo(self, event): # check that the position is in the axes view if 0 <= yPos < self.model.currentView.v_res \ and 0 <= xPos and xPos < self.model.currentView.h_res: + cell_id = int(self.model.cell_ids[yPos, xPos]) + mat_id = int(self.model.mat_ids[yPos, xPos]) if self.model.currentView.colorby == 'cell': - id = int(self.model.cell_ids[yPos, xPos]) + id = cell_id else: - id = int(self.model.mat_ids[yPos, xPos]) + id = mat_id + if id == _OVERLAP: + if cell_id < _OVERLAP: + id = cell_id + elif mat_id < _OVERLAP: + id = mat_id instance = self.model.instances[yPos, xPos] temp = "{:g}".format(self.model.property_data[yPos, xPos, 0]) density = "{:g}".format(self.model.property_data[yPos, xPos, 1]) @@ -340,6 +347,29 @@ def getIDinfo(self, event): return id, instance, properties, domain, domain_kind + def _overlapInfo(self, id): + if id == _OVERLAP: + return "OVERLAP" + + overlap_idx = int(_OVERLAP - int(id) - 1) + if overlap_idx not in self.model.overlap_map: + return "OVERLAP (unknown region)" + + universe, cell1, cell2 = self.model.overlap_map[overlap_idx] + try: + name1 = self.model.activeView.cells[cell1].name or str(cell1) + except KeyError: + name1 = str(cell1) + try: + name2 = self.model.activeView.cells[cell2].name or str(cell2) + except KeyError: + name2 = str(cell2) + + return ( + f"OVERLAP: Universe {universe}, " + f"Cells {name1} and {name2}" + ) + def mouseDoubleClickEvent(self, event): xCenter, yCenter = self.getPlotCoords(event.pos()) self.main_window.editPlotOrigin(xCenter, yCenter, apply=True) @@ -373,25 +403,8 @@ def mouseMoveEvent(self, event): instanceInfo = "" if id == _VOID_REGION: domainInfo = ("VOID") - elif id < _OVERLAP: - # Unpack the index and find it in overlap map - overlap_idx = int(_OVERLAP - int(id) - 1) - if overlap_idx in self.model.overlap_map: - universe, cell1, cell2 = self.model.overlap_map[overlap_idx] - try: - name1 = self.model.activeView.cells[cell1].name or str(cell1) - except KeyError: - name1 = str(cell1) - try: - name2 = self.model.activeView.cells[cell2].name or str(cell2) - except KeyError: - name2 = str(cell2) - domainInfo = ( - f"OVERLAP: Universe {universe}, " - f"Cells {name1} and {name2}" - ) - else: - domainInfo = "OVERLAP (unknown region)" + elif id <= _OVERLAP: + domainInfo = self._overlapInfo(id) elif id != _NOT_FOUND and domain[id].name: domainInfo = ("{} {}{}: \"{}\"\t Density: {} g/cc\t" "Temperature: {} K".format( @@ -503,8 +516,9 @@ def contextMenuEvent(self, event): self.menu.addAction(self.main_window.redoAction) self.menu.addSeparator() - if int(id) not in (_NOT_FOUND) and int(id) >= _OVERLAP and \ - cv.colorby not in _MODEL_PROPERTIES: + if (int(id) not in (_NOT_FOUND, _VOID_REGION) and + int(id) > _OVERLAP and + cv.colorby not in _MODEL_PROPERTIES): # Domain ID if domain[id].name: @@ -571,7 +585,7 @@ def contextMenuEvent(self, event): connector = partial(self.main_window.editBackgroundColor, apply=True) bgColorAction.triggered.connect(connector) - elif int(id) == _OVERLAP: + elif int(id) <= _OVERLAP: olapColorAction = self.menu.addAction( 'Edit Overlap Color...') olapColorAction.setToolTip('Edit overlap color') From 58e531c622fd50b033dc70978bf1cf718ed1de35 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 8 Jul 2026 14:19:48 -0500 Subject: [PATCH 6/7] Simplify ID logic and labels --- openmc_plotter/plotgui.py | 41 +++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/openmc_plotter/plotgui.py b/openmc_plotter/plotgui.py index cb809df..94db587 100644 --- a/openmc_plotter/plotgui.py +++ b/openmc_plotter/plotgui.py @@ -1,6 +1,5 @@ import io from functools import partial -import openmc from PySide6 import QtCore, QtGui from PySide6.QtWidgets import (QWidget, QPushButton, QHBoxLayout, QVBoxLayout, @@ -311,15 +310,7 @@ def getIDinfo(self, event): and 0 <= xPos and xPos < self.model.currentView.h_res: cell_id = int(self.model.cell_ids[yPos, xPos]) mat_id = int(self.model.mat_ids[yPos, xPos]) - if self.model.currentView.colorby == 'cell': - id = cell_id - else: - id = mat_id - if id == _OVERLAP: - if cell_id < _OVERLAP: - id = cell_id - elif mat_id < _OVERLAP: - id = mat_id + id = self._domainId(cell_id, mat_id) instance = self.model.instances[yPos, xPos] temp = "{:g}".format(self.model.property_data[yPos, xPos, 0]) density = "{:g}".format(self.model.property_data[yPos, xPos, 1]) @@ -347,6 +338,20 @@ def getIDinfo(self, event): return id, instance, properties, domain, domain_kind + def _domainId(self, cell_id, mat_id): + if self.model.currentView.colorby != 'cell': + return mat_id + if cell_id == _OVERLAP and mat_id < _OVERLAP: + return mat_id + return cell_id + + def _cellLabel(self, cell_id): + try: + name = self.model.activeView.cells[cell_id].name + except KeyError: + name = None + return f"{cell_id} ({name})" if name else str(cell_id) + def _overlapInfo(self, id): if id == _OVERLAP: return "OVERLAP" @@ -356,19 +361,9 @@ def _overlapInfo(self, id): return "OVERLAP (unknown region)" universe, cell1, cell2 = self.model.overlap_map[overlap_idx] - try: - name1 = self.model.activeView.cells[cell1].name or str(cell1) - except KeyError: - name1 = str(cell1) - try: - name2 = self.model.activeView.cells[cell2].name or str(cell2) - except KeyError: - name2 = str(cell2) - - return ( - f"OVERLAP: Universe {universe}, " - f"Cells {name1} and {name2}" - ) + label1 = self._cellLabel(cell1) + label2 = self._cellLabel(cell2) + return f"OVERLAP: Universe {universe}, Cells {label1} and {label2}" def mouseDoubleClickEvent(self, event): xCenter, yCenter = self.getPlotCoords(event.pos()) From ca91c82347cbd5928b9a37de7c88f1310c52d6ef Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 8 Jul 2026 15:28:11 -0500 Subject: [PATCH 7/7] Further simplifications --- openmc_plotter/plotgui.py | 16 ++++++---------- openmc_plotter/plotmodel.py | 12 +++++------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/openmc_plotter/plotgui.py b/openmc_plotter/plotgui.py index 94db587..1e080b2 100644 --- a/openmc_plotter/plotgui.py +++ b/openmc_plotter/plotgui.py @@ -310,7 +310,10 @@ def getIDinfo(self, event): and 0 <= xPos and xPos < self.model.currentView.h_res: cell_id = int(self.model.cell_ids[yPos, xPos]) mat_id = int(self.model.mat_ids[yPos, xPos]) - id = self._domainId(cell_id, mat_id) + if cell_id < _OVERLAP: + id = cell_id + else: + id = cell_id if self.model.currentView.colorby == 'cell' else mat_id instance = self.model.instances[yPos, xPos] temp = "{:g}".format(self.model.property_data[yPos, xPos, 0]) density = "{:g}".format(self.model.property_data[yPos, xPos, 1]) @@ -338,13 +341,6 @@ def getIDinfo(self, event): return id, instance, properties, domain, domain_kind - def _domainId(self, cell_id, mat_id): - if self.model.currentView.colorby != 'cell': - return mat_id - if cell_id == _OVERLAP and mat_id < _OVERLAP: - return mat_id - return cell_id - def _cellLabel(self, cell_id): try: name = self.model.activeView.cells[cell_id].name @@ -357,10 +353,10 @@ def _overlapInfo(self, id): return "OVERLAP" overlap_idx = int(_OVERLAP - int(id) - 1) - if overlap_idx not in self.model.overlap_map: + if not 0 <= overlap_idx < len(self.model.overlap_info): return "OVERLAP (unknown region)" - universe, cell1, cell2 = self.model.overlap_map[overlap_idx] + universe, cell1, cell2 = self.model.overlap_info[overlap_idx] label1 = self._cellLabel(cell1) label2 = self._cellLabel(cell2) return f"OVERLAP: Universe {universe}, Cells {label1} and {label2}" diff --git a/openmc_plotter/plotmodel.py b/openmc_plotter/plotmodel.py index c454731..6faf2d8 100644 --- a/openmc_plotter/plotmodel.py +++ b/openmc_plotter/plotmodel.py @@ -325,7 +325,7 @@ def __init__(self, use_settings_pkl, model_path, default_res): self.map_view_params = None # Map to be populated by overlap functions - self.overlap_map = {} + self.overlap_info = None self.version = __version__ @@ -533,16 +533,14 @@ def makePlot(self, view: Optional["PlotView"] = None, filter=filter_cpp, ) self.map_view_params = self.view_params_payload(view) - + else: self.geom_data = geom_data self.property_data = property_data self.map_view_params = self.view_params_payload(view) - overlap_info, n = openmc.lib.slice_data_overlap_info() - self.overlap_map = {} - for i in range(n): - self.overlap_map[i] = (overlap_info[i*3], overlap_info[i*3+1], overlap_info[i*3+2]) + # Get cell overlap information + self.overlap_info = openmc.lib.slice_data_overlap_info() # update current view cv = self.currentView = copy.deepcopy(view) @@ -557,7 +555,7 @@ def makePlot(self, view: Optional["PlotView"] = None, domain = cv.materials source = self.modelMaterials - # Normalizes so that domain only sees -3, but + # Normalizes so that domain only sees -3, but # overlap indices are still available in cell_ids self.ids[self.ids < _OVERLAP] = _OVERLAP # new line