Skip to content

Commit 14db121

Browse files
authored
Merge pull request #119 from pshriwise/batch-mode
Batch mode
2 parents 56a4558 + dcf6917 commit 14db121

9 files changed

Lines changed: 132 additions & 34 deletions

File tree

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pip install openmc-plotter
3030
From a directory containing an OpenMC model run:
3131

3232
```console
33-
$ openmc-plotter -d <path_to_openmc_model_dir>
33+
$ openmc-plotter <path_to_openmc_model_dir>
3434
```
3535

3636
or simply run
@@ -45,6 +45,15 @@ Once the viewer has opened, press `?` to view a variety of keyboard shortcuts.
4545

4646
![shortcuts](./screenshots/shortcuts.png)
4747

48+
## Batch Mode
49+
50+
Plot view (`.pltvw`) files generated in interactive sessions (see [Saving and Exporting](#saving-and-exporting))
51+
can be used to generate images from the command line without opening the plotter GUI.
52+
53+
```console
54+
$ openmc-plotter -b view1.pltvw view1.pltvw view1.pltvw
55+
```
56+
4857
## Features
4958

5059
### Tally Visualization

openmc_plotter/__main__.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ def main():
2424
ap.add_argument('model_path', nargs='?', default=os.curdir,
2525
help='Location of model XML file or a directory containing '
2626
'XML files (default is current dir)')
27+
ap.add_argument('-b', '--batch-mode', nargs='+', default=False,
28+
help='View files used to generate plots in batch mode')
2729

2830
args = ap.parse_args()
2931

@@ -44,7 +46,8 @@ def run_app(user_args):
4446
splash_pix = QtGui.QPixmap(path_splash)
4547
splash = QSplashScreen(splash_pix, QtCore.Qt.WindowStaysOnTopHint)
4648
splash.setMask(splash_pix.mask())
47-
splash.show()
49+
if not user_args.batch_mode:
50+
splash.show()
4851
app.processEvents()
4952
splash.setMask(splash_pix.mask())
5053
splash.showMessage("Loading Model...",
@@ -68,9 +71,17 @@ def run_app(user_args):
6871
mainWindow = MainWindow(font_metric, screen_size, user_args.model_path)
6972
# connect splashscreen to main window, close when main window opens
7073
mainWindow.loadGui(use_settings_pkl=user_args.ignore_settings)
71-
mainWindow.show()
74+
7275
splash.close()
7376

77+
if user_args.batch_mode:
78+
for view_file in user_args.batch_mode:
79+
mainWindow.saveBatchImage(view_file)
80+
mainWindow.close()
81+
sys.exit()
82+
else:
83+
mainWindow.show()
84+
7485
# connect interrupt signal to close call
7586
signal.signal(signal.SIGINT, lambda *args: mainWindow.close())
7687
# create timer that interrupts the Qt event loop

openmc_plotter/main_window.py

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def _openmcReload(threads=None, model_path='.'):
3636
args = ["-c"]
3737
if threads is not None:
3838
args += ["-s", str(threads)]
39-
args.append(model_path)
39+
args.append(str(model_path))
4040
openmc.lib.init(args)
4141
openmc.lib.settings.verbosity = 1
4242

@@ -159,7 +159,8 @@ def createMenuBar(self):
159159
self.saveImageAction.setShortcut("Ctrl+Shift+S")
160160
self.saveImageAction.setToolTip('Save plot image')
161161
self.saveImageAction.setStatusTip('Save plot image')
162-
self.saveImageAction.triggered.connect(self.saveImage)
162+
save_image_connector = partial(self.saveImage, filename=None)
163+
self.saveImageAction.triggered.connect(save_image_connector)
163164

164165
self.saveViewAction = QAction("Save &View...", self)
165166
self.saveViewAction.setShortcut(QtGui.QKeySequence.Save)
@@ -449,6 +450,21 @@ def updateWindowMenu(self):
449450
self.colorDialogAction.setChecked(self.colorDialog.isActiveWindow())
450451
self.mainWindowAction.setChecked(self.isActiveWindow())
451452

453+
def saveBatchImage(self, view_file):
454+
"""
455+
Loads a view in the GUI and generates an image
456+
457+
Parameters
458+
----------
459+
view_file : str or pathlib.Path
460+
The path to a view file that is compatible with the loaded model.
461+
"""
462+
# store the
463+
cv = self.model.currentView
464+
# load the view from file
465+
self.loadViewFile(view_file)
466+
self.plotIm.saveImage(view_file.replace('.pltvw', ''))
467+
452468
# Menu and shared methods
453469
def loadModel(self, reload=False, use_settings_pkl=True):
454470
if reload:
@@ -472,15 +488,14 @@ def loadModel(self, reload=False, use_settings_pkl=True):
472488
self.plotIm.model = self.model
473489
self.applyChanges()
474490

475-
def saveImage(self):
476-
filename, ext = QFileDialog.getSaveFileName(self,
477-
"Save Plot Image",
478-
"untitled",
479-
"Images (*.png)")
491+
def saveImage(self, filename=None):
492+
if filename is None:
493+
filename, ext = QFileDialog.getSaveFileName(self,
494+
"Save Plot Image",
495+
"untitled",
496+
"Images (*.png)")
480497
if filename:
481-
if "." not in filename:
482-
filename += ".png"
483-
self.plotIm.figure.savefig(filename, transparent=True)
498+
self.plotIm.saveImage(filename)
484499
self.statusBar().showMessage('Plot Image Saved', 5000)
485500

486501
def saveView(self):
@@ -497,26 +512,29 @@ def saveView(self):
497512
with open(filename, 'wb') as file:
498513
pickle.dump(saved, file)
499514

515+
def loadViewFile(self, filename):
516+
try:
517+
with open(filename, 'rb') as file:
518+
saved = pickle.load(file)
519+
except Exception:
520+
message = 'Error loading plot settings'
521+
saved = {'version': None,
522+
'current': None}
523+
if saved['version'] == self.model.version:
524+
self.model.activeView = saved['current']
525+
self.dock.updateDock()
526+
self.colorDialog.updateDialogValues()
527+
self.applyChanges()
528+
message = '{} settings loaded'.format(filename)
529+
else:
530+
message = 'Error loading plot settings. Incompatible model.'
531+
self.statusBar().showMessage(message, 5000)
532+
500533
def openView(self):
501534
filename, ext = QFileDialog.getOpenFileName(self, "Open View Settings",
502535
".", "*.pltvw")
503536
if filename:
504-
try:
505-
with open(filename, 'rb') as file:
506-
saved = pickle.load(file)
507-
except Exception:
508-
message = 'Error loading plot settings'
509-
saved = {'version': None,
510-
'current': None}
511-
if saved['version'] == self.model.version:
512-
self.model.activeView = saved['current']
513-
self.dock.updateDock()
514-
self.colorDialog.updateDialogValues()
515-
self.applyChanges()
516-
message = '{} settings loaded'.format(filename)
517-
else:
518-
message = 'Error loading plot settings. Incompatible model.'
519-
self.statusBar().showMessage(message, 5000)
537+
self.loadViewFile(filename)
520538

521539
def openStatePoint(self):
522540
# check for an alread-open statepoint

openmc_plotter/plotgui.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,18 @@ def _resize(self):
111111
self.resize(self.parent.width() * z,
112112
self.parent.height() * z)
113113

114+
def saveImage(self, filename):
115+
"""Save an image of the current view
116+
117+
Parameters
118+
----------
119+
filename : str or pathlib.Path
120+
Name of the image to save
121+
"""
122+
if "." not in str(filename):
123+
filename += ".png"
124+
self.figure.savefig(filename, transparent=True)
125+
114126
def getDataIndices(self, event):
115127
cv = self.model.currentView
116128

tests/setup_test/ref.png

26.7 KB
Loading

tests/setup_test/ref1.png

12.6 KB
Loading

tests/setup_test/test.pltvw

1.86 KB
Binary file not shown.

tests/setup_test/test.py

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,57 @@
1+
import filecmp
2+
import shutil
3+
4+
import pytest
5+
16
from openmc_plotter.main_window import MainWindow, _openmcReload
27

3-
def test_window(qtbot):
4-
_openmcReload()
8+
@pytest.fixture
9+
def run_in_tmpdir(tmpdir):
10+
orig = tmpdir.chdir()
11+
try:
12+
yield
13+
finally:
14+
orig.chdir()
515

6-
mw = MainWindow()
16+
def test_window(tmpdir, qtbot):
17+
orig = tmpdir.chdir()
18+
mw = MainWindow(model_path=orig)
19+
_openmcReload(model_path=orig)
720
mw.loadGui()
8-
mw.plotIm.figure.savefig("test.png")
9-
qtbot.addWidget(mw)
21+
22+
try:
23+
mw.saveImage(tmpdir / 'test.png')
24+
25+
qtbot.addWidget(mw)
26+
finally:
27+
orig.chdir()
28+
29+
filecmp.cmp(orig / 'ref.png', tmpdir / 'test.png')
30+
31+
mw.close()
32+
33+
def test_batch_image(tmpdir, qtbot):
34+
orig = tmpdir.chdir()
35+
36+
# move view file into tmpdir
37+
shutil.copy2(orig / 'test.pltvw', tmpdir)
38+
shutil.copy2(orig / 'test1.pltvw', tmpdir)
39+
40+
_openmcReload(model_path=orig)
41+
42+
mw = MainWindow(model_path=orig)
43+
mw.loadGui()
44+
45+
try:
46+
mw.saveBatchImage('test.pltvw')
47+
qtbot.addWidget(mw)
48+
49+
mw.saveBatchImage('test1.pltvw')
50+
qtbot.addWidget(mw)
51+
finally:
52+
orig.chdir()
53+
54+
filecmp.cmp(orig / 'ref.png', tmpdir / 'test.png')
55+
filecmp.cmp(orig / 'ref1.png', tmpdir / 'test1.png')
56+
57+
mw.close()

tests/setup_test/test1.pltvw

1.96 KB
Binary file not shown.

0 commit comments

Comments
 (0)