LLNL-PyDV 3.4.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- llnl_pydv-3.4.3.dist-info/LICENSE +60 -0
- llnl_pydv-3.4.3.dist-info/METADATA +68 -0
- llnl_pydv-3.4.3.dist-info/RECORD +21 -0
- llnl_pydv-3.4.3.dist-info/WHEEL +4 -0
- llnl_pydv-3.4.3.dist-info/entry_points.txt +3 -0
- pydv/NOTES +57 -0
- pydv/README.md +27 -0
- pydv/__init__.py +1 -0
- pydv/curve.py +356 -0
- pydv/img/app_icon3.png +0 -0
- pydv/img/window-code-7.png +0 -0
- pydv/img/window-code-7@2x.png +0 -0
- pydv/pdv +17 -0
- pydv/pdv.py +8784 -0
- pydv/pdvnavbar.py +76 -0
- pydv/pdvplot.py +660 -0
- pydv/pdvutil.py +315 -0
- pydv/pydvpy.py +4491 -0
- pydv/scripts/date.txt +1 -0
- pydv/scripts/update_version_and_date.py +64 -0
- pydv/scripts/version.txt +1 -0
pydv/pdvplot.py
ADDED
|
@@ -0,0 +1,660 @@
|
|
|
1
|
+
# Copyright (c) 2011-2024, Lawrence Livermore National Security, LLC.
|
|
2
|
+
# Produced at the Lawrence Livermore National Laboratory
|
|
3
|
+
# Written by Mason Kwiat, Douglas S. Miller, and Kevin Griffin, Ephraim Rusu, Sarah El-Jurf, Jorge Moreno
|
|
4
|
+
# e-mail: eljurf1@llnl.gov, moreno45@llnl.gov
|
|
5
|
+
# LLNL-CODE-507071
|
|
6
|
+
# All rights reserved.
|
|
7
|
+
|
|
8
|
+
# This file is part of PyDV. For details, see <URL describing code and
|
|
9
|
+
# how to download source>. Please also read "Additional BSD Notice".
|
|
10
|
+
|
|
11
|
+
# Redistribution and use in source and binary forms, with or without
|
|
12
|
+
# modification, are permitted provided that the following conditions
|
|
13
|
+
# are met:
|
|
14
|
+
|
|
15
|
+
# Redistributions of source code must retain the above copyright
|
|
16
|
+
# notice, this list of conditions and the disclaimer below.
|
|
17
|
+
# Redistributions in binary form must reproduce the above copyright
|
|
18
|
+
# notice, this list of conditions and the disclaimer (as noted below)
|
|
19
|
+
# in the documentation and/or other materials provided with the
|
|
20
|
+
# distribution. Neither the name of the LLNS/LLNL nor the names of
|
|
21
|
+
# its contributors may be used to endorse or promote products derived
|
|
22
|
+
# from this software without specific prior written permission.
|
|
23
|
+
|
|
24
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
25
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
26
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
27
|
+
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LAWRENCE
|
|
28
|
+
# LIVERMORE NATIONAL SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR
|
|
29
|
+
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
30
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
31
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
|
32
|
+
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
33
|
+
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
34
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
35
|
+
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
36
|
+
# SUCH DAMAGE.
|
|
37
|
+
|
|
38
|
+
# Additional BSD Notice
|
|
39
|
+
|
|
40
|
+
# 1. This notice is required to be provided under our contract with
|
|
41
|
+
# the U.S. Department of Energy (DOE). This work was produced at
|
|
42
|
+
# Lawrence Livermore National Laboratory under Contract
|
|
43
|
+
# No. DE-AC52-07NA27344 with the DOE.
|
|
44
|
+
|
|
45
|
+
# 2. Neither the United States Government nor Lawrence Livermore
|
|
46
|
+
# National Security, LLC nor any of their employees, makes any
|
|
47
|
+
# warranty, express or implied, or assumes any liability or
|
|
48
|
+
# responsibility for the accuracy, completeness, or usefulness of any
|
|
49
|
+
# information, apparatus, product, or process disclosed, or represents
|
|
50
|
+
# that its use would not infringe privately-owned rights.
|
|
51
|
+
|
|
52
|
+
# 3. Also, reference herein to any specific commercial products,
|
|
53
|
+
# process, or services by trade name, trademark, manufacturer or
|
|
54
|
+
# otherwise does not necessarily constitute or imply its endorsement,
|
|
55
|
+
# recommendation, or favoring by the United States Government or
|
|
56
|
+
# Lawrence Livermore National Security, LLC. The views and opinions
|
|
57
|
+
# of authors expressed herein do not necessarily state or reflect
|
|
58
|
+
# those of the United States Government or Lawrence Livermore National
|
|
59
|
+
# Security, LLC, and shall not be used for advertising or product
|
|
60
|
+
# endorsement purposes.
|
|
61
|
+
|
|
62
|
+
import matplotlib.pyplot as plt
|
|
63
|
+
try:
|
|
64
|
+
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
|
|
65
|
+
except:
|
|
66
|
+
from matplotlib.backends.backend_qtagg import FigureCanvas
|
|
67
|
+
|
|
68
|
+
from os import path
|
|
69
|
+
|
|
70
|
+
# HPC Import
|
|
71
|
+
try:
|
|
72
|
+
from pdvnavbar import PyDVToolbar
|
|
73
|
+
import pdvutil
|
|
74
|
+
|
|
75
|
+
# Package Import
|
|
76
|
+
except ImportError:
|
|
77
|
+
from pydv.pdvnavbar import PyDVToolbar
|
|
78
|
+
from pydv import pdvutil
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
from matplotlib import style
|
|
82
|
+
stylesLoaded = True
|
|
83
|
+
except:
|
|
84
|
+
stylesLoaded = False
|
|
85
|
+
|
|
86
|
+
from matplotlib.backends import qt_compat
|
|
87
|
+
use_pyside = qt_compat.QT_API == qt_compat.QT_API_PYSIDE2
|
|
88
|
+
if use_pyside:
|
|
89
|
+
from PySide2.QtCore import Qt, QRect, Slot
|
|
90
|
+
from PySide2.QtGui import QIcon
|
|
91
|
+
from PySide2.QtWidgets import (QDialog, QVBoxLayout, QTextEdit, QScrollArea, QHBoxLayout, QPushButton,
|
|
92
|
+
QMessageBox, QTableWidgetItem, QAction, QAbstractItemView, QTableWidget,
|
|
93
|
+
QMainWindow)
|
|
94
|
+
else:
|
|
95
|
+
from PyQt5.QtCore import Qt, QRect, Slot
|
|
96
|
+
from PyQt5.QtGui import QIcon
|
|
97
|
+
from PyQt5.QtWidgets import (QDialog, QVBoxLayout, QTextEdit, QScrollArea, QHBoxLayout, QPushButton,
|
|
98
|
+
QMessageBox, QTableWidgetItem, QAction, QAbstractItemView, QTableWidget,
|
|
99
|
+
QMainWindow)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
PYDV_DIR = path.dirname(path.abspath(__file__))
|
|
103
|
+
try:
|
|
104
|
+
version_file = path.join(PYDV_DIR, '../scripts/version.txt')
|
|
105
|
+
with open(version_file, 'r') as fp:
|
|
106
|
+
pydv_version = fp.read()
|
|
107
|
+
|
|
108
|
+
except:
|
|
109
|
+
version_file = path.join(PYDV_DIR, 'scripts/version.txt')
|
|
110
|
+
with open(version_file, 'r') as fp:
|
|
111
|
+
pydv_version = fp.read()
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class Plotter(QMainWindow):
|
|
115
|
+
# PyDV
|
|
116
|
+
_pydvcmd = None
|
|
117
|
+
# Dialogs
|
|
118
|
+
_listDialog = None
|
|
119
|
+
_menuDialog = None
|
|
120
|
+
# Tables
|
|
121
|
+
_tableWidget = None
|
|
122
|
+
_menuTableWidget = None
|
|
123
|
+
# Actions
|
|
124
|
+
_listAction = None
|
|
125
|
+
_menuAction = None
|
|
126
|
+
_geomAction = None
|
|
127
|
+
|
|
128
|
+
_geometry = 'de'
|
|
129
|
+
|
|
130
|
+
canvas = None
|
|
131
|
+
style = 'ggplot'
|
|
132
|
+
plotChanged = False
|
|
133
|
+
fig = None
|
|
134
|
+
figcolor = 'white'
|
|
135
|
+
defaultPlotLayout = None
|
|
136
|
+
|
|
137
|
+
def __init__(self, pydvcmd):
|
|
138
|
+
QMainWindow.__init__(self)
|
|
139
|
+
|
|
140
|
+
here = path.abspath(path.dirname(__file__))
|
|
141
|
+
|
|
142
|
+
# Setup Application
|
|
143
|
+
self.setWindowTitle(f'Python Data Visualizer {pydv_version}')
|
|
144
|
+
self.setWindowIcon(QIcon(path.join(here, 'img/app_icon3.png')))
|
|
145
|
+
self._pydvcmd = pydvcmd
|
|
146
|
+
|
|
147
|
+
# Window geometry action
|
|
148
|
+
self._geomAction = QAction(self)
|
|
149
|
+
self._geomAction.triggered.connect(self.__setgeometry)
|
|
150
|
+
|
|
151
|
+
# View Menu
|
|
152
|
+
viewMenu = self.menuBar().addMenu('View')
|
|
153
|
+
|
|
154
|
+
self._listAction = QAction('List...', self)
|
|
155
|
+
self._listAction.triggered.connect(self.showCurvelistDialog)
|
|
156
|
+
viewMenu.addAction(self._listAction)
|
|
157
|
+
|
|
158
|
+
self._menuAction = QAction('Menu...', self)
|
|
159
|
+
self._menuAction.triggered.connect(self.showMenuDialog)
|
|
160
|
+
viewMenu.addAction(self._menuAction)
|
|
161
|
+
|
|
162
|
+
# Help Menu
|
|
163
|
+
helpMenu = self.menuBar().addMenu('Help')
|
|
164
|
+
|
|
165
|
+
# Copyright
|
|
166
|
+
copyrightAction = QAction('Copyright...', self)
|
|
167
|
+
copyrightAction.triggered.connect(self.__viewCopyright)
|
|
168
|
+
helpMenu.addAction(copyrightAction)
|
|
169
|
+
# About PyDV
|
|
170
|
+
aboutAction = QAction('&About PyDV', self)
|
|
171
|
+
aboutAction.setShortcut('ctrl+a')
|
|
172
|
+
aboutAction.triggered.connect(self.__aboutPyDV)
|
|
173
|
+
helpMenu.addAction(aboutAction)
|
|
174
|
+
# About QT
|
|
175
|
+
aboutQtAction = QAction('About &Qt', self)
|
|
176
|
+
aboutQtAction.triggered.connect(self.__aboutQt)
|
|
177
|
+
helpMenu.addAction(aboutQtAction)
|
|
178
|
+
|
|
179
|
+
# Styles
|
|
180
|
+
if stylesLoaded:
|
|
181
|
+
styles = plt.style.available
|
|
182
|
+
|
|
183
|
+
try:
|
|
184
|
+
idx = styles.index(self.style)
|
|
185
|
+
style.use(styles[idx])
|
|
186
|
+
except:
|
|
187
|
+
if len(styles) > 0:
|
|
188
|
+
self.style = styles[0]
|
|
189
|
+
style.use(self.style)
|
|
190
|
+
|
|
191
|
+
# Figure Canvas
|
|
192
|
+
self.fig = plt.figure(figsize=(1, 1))
|
|
193
|
+
self.current_axes = self.fig.subplots()
|
|
194
|
+
self.fig.set_facecolor(self.figcolor)
|
|
195
|
+
|
|
196
|
+
self.defaultPlotLayout = dict(vars(self.fig.subplotpars))
|
|
197
|
+
|
|
198
|
+
self.canvas = FigureCanvas(self.fig)
|
|
199
|
+
self.setCentralWidget(self.canvas)
|
|
200
|
+
|
|
201
|
+
toolbar = PyDVToolbar(self.canvas, self, True) # Add False as third parameter to turn off coordinates
|
|
202
|
+
self.addToolBar(toolbar)
|
|
203
|
+
|
|
204
|
+
def updatePlotGeometry(self, geometry='de'):
|
|
205
|
+
"""
|
|
206
|
+
Updates the size and location of the window. Using an action to trigger the update to
|
|
207
|
+
ensure that the resizing is happening on the main GUI thread.
|
|
208
|
+
"""
|
|
209
|
+
self._geometry = geometry
|
|
210
|
+
self._geomAction.trigger()
|
|
211
|
+
|
|
212
|
+
def updateDialogs(self):
|
|
213
|
+
"""
|
|
214
|
+
Updates the list and menu dialogs if visible.
|
|
215
|
+
"""
|
|
216
|
+
if self._listDialog is not None:
|
|
217
|
+
if self._listDialog.isVisible():
|
|
218
|
+
self._listAction.trigger()
|
|
219
|
+
|
|
220
|
+
if self._menuDialog is not None:
|
|
221
|
+
if self._menuDialog.isVisible():
|
|
222
|
+
self._menuAction.trigger()
|
|
223
|
+
|
|
224
|
+
########################################################################################################
|
|
225
|
+
# SLOTS
|
|
226
|
+
########################################################################################################
|
|
227
|
+
|
|
228
|
+
@Slot()
|
|
229
|
+
def showCurvelistDialog(self):
|
|
230
|
+
"""
|
|
231
|
+
Shows a dialog with the output of the list command in a table.
|
|
232
|
+
"""
|
|
233
|
+
refresh = True
|
|
234
|
+
|
|
235
|
+
if self._listDialog is None:
|
|
236
|
+
refresh = False
|
|
237
|
+
self._listDialog = QDialog(self)
|
|
238
|
+
self._listDialog.setWindowTitle("Curve List")
|
|
239
|
+
self._listDialog.setModal(False)
|
|
240
|
+
|
|
241
|
+
# Curves List
|
|
242
|
+
headerLabels = ['Plot Name', 'Label', 'X Label', 'Y Label', 'XMIN', 'XMAX',
|
|
243
|
+
'YMIN', 'YMAX', 'File Name', 'Sina Record ID']
|
|
244
|
+
rows = len(self._pydvcmd.plotlist)
|
|
245
|
+
cols = len(headerLabels)
|
|
246
|
+
|
|
247
|
+
# Create or clear table
|
|
248
|
+
if self._tableWidget is None:
|
|
249
|
+
self._tableWidget = QTableWidget(rows, cols, self)
|
|
250
|
+
self._tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
|
251
|
+
self._tableWidget.setHorizontalHeaderLabels(headerLabels)
|
|
252
|
+
self._tableWidget.setAlternatingRowColors(True)
|
|
253
|
+
self._tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
|
|
254
|
+
|
|
255
|
+
# Setup Right-click menu
|
|
256
|
+
self._tableWidget.setContextMenuPolicy(Qt.ActionsContextMenu)
|
|
257
|
+
deleteCurveAction = QAction("Delete selected curve(s)", self._tableWidget)
|
|
258
|
+
deleteCurveAction.triggered.connect(self.__deleteCurve)
|
|
259
|
+
self._tableWidget.addAction(deleteCurveAction)
|
|
260
|
+
else:
|
|
261
|
+
self._tableWidget.clearContents()
|
|
262
|
+
self._tableWidget.setRowCount(rows)
|
|
263
|
+
|
|
264
|
+
# Populate table with curves
|
|
265
|
+
row = 0
|
|
266
|
+
for c in self._pydvcmd.plotlist:
|
|
267
|
+
col = 0
|
|
268
|
+
|
|
269
|
+
# Plot Name
|
|
270
|
+
prefix = ''
|
|
271
|
+
if c.edited:
|
|
272
|
+
prefix = '*'
|
|
273
|
+
plotnameItem = QTableWidgetItem(self.tr("%s%s" % (prefix, c.plotname)))
|
|
274
|
+
plotnameItem.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
|
|
275
|
+
self._tableWidget.setItem(row, col, plotnameItem)
|
|
276
|
+
col += 1
|
|
277
|
+
|
|
278
|
+
# Label
|
|
279
|
+
labelItem = QTableWidgetItem(self.tr(pdvutil.truncate(c.name, self._pydvcmd.namewidth)))
|
|
280
|
+
self._tableWidget.setItem(row, col, labelItem)
|
|
281
|
+
col += 1
|
|
282
|
+
|
|
283
|
+
# X Label
|
|
284
|
+
xlabelItem = QTableWidgetItem(self.tr(pdvutil.truncate(c.xlabel, self._pydvcmd.namewidth)))
|
|
285
|
+
self._tableWidget.setItem(row, col, xlabelItem)
|
|
286
|
+
col += 1
|
|
287
|
+
|
|
288
|
+
# Y Label
|
|
289
|
+
ylabelItem = QTableWidgetItem(self.tr(pdvutil.truncate(c.ylabel, self._pydvcmd.namewidth)))
|
|
290
|
+
self._tableWidget.setItem(row, col, ylabelItem)
|
|
291
|
+
col += 1
|
|
292
|
+
|
|
293
|
+
# xmin
|
|
294
|
+
xminItem = QTableWidgetItem(self.tr("%.2e" % min(c.x)))
|
|
295
|
+
self._tableWidget.setItem(row, col, xminItem)
|
|
296
|
+
col += 1
|
|
297
|
+
|
|
298
|
+
# xmax
|
|
299
|
+
xmaxItem = QTableWidgetItem(self.tr("%.2e" % max(c.x)))
|
|
300
|
+
self._tableWidget.setItem(row, col, xmaxItem)
|
|
301
|
+
col += 1
|
|
302
|
+
|
|
303
|
+
# ymin
|
|
304
|
+
yminItem = QTableWidgetItem(self.tr("%.2e" % min(c.y)))
|
|
305
|
+
self._tableWidget.setItem(row, col, yminItem)
|
|
306
|
+
col += 1
|
|
307
|
+
|
|
308
|
+
# ymax
|
|
309
|
+
ymaxItem = QTableWidgetItem(self.tr("%.2e" % max(c.y)))
|
|
310
|
+
self._tableWidget.setItem(row, col, ymaxItem)
|
|
311
|
+
col += 1
|
|
312
|
+
|
|
313
|
+
# File Name
|
|
314
|
+
fnameItem = QTableWidgetItem(self.tr(c.filename))
|
|
315
|
+
self._tableWidget.setItem(row, col, fnameItem)
|
|
316
|
+
col += 1
|
|
317
|
+
|
|
318
|
+
# Sina Record ID
|
|
319
|
+
recidItem = QTableWidgetItem(self.tr(c.record_id))
|
|
320
|
+
self._tableWidget.setItem(row, col, recidItem)
|
|
321
|
+
|
|
322
|
+
row += 1
|
|
323
|
+
|
|
324
|
+
maxrows = rows
|
|
325
|
+
if rows > 10:
|
|
326
|
+
maxrows = 10
|
|
327
|
+
|
|
328
|
+
if not refresh:
|
|
329
|
+
# Layout
|
|
330
|
+
vbox = QVBoxLayout(self._listDialog)
|
|
331
|
+
|
|
332
|
+
# Scroll Bar
|
|
333
|
+
scroll = QScrollArea(self._listDialog)
|
|
334
|
+
scroll.setGeometry(QRect(10, 20, cols * 115, maxrows * 50))
|
|
335
|
+
scroll.setMinimumSize(150, 150)
|
|
336
|
+
scroll.setWidget(self._tableWidget)
|
|
337
|
+
scroll.setWidgetResizable(True)
|
|
338
|
+
vbox.addWidget(scroll)
|
|
339
|
+
|
|
340
|
+
hbox = QHBoxLayout(self._listDialog)
|
|
341
|
+
hbox.setAlignment(Qt.AlignCenter)
|
|
342
|
+
|
|
343
|
+
# Dismiss Button
|
|
344
|
+
okButton = QPushButton(self._listDialog)
|
|
345
|
+
okButton.clicked.connect(self._listDialog.close)
|
|
346
|
+
okButton.setMinimumSize(100, 20)
|
|
347
|
+
okButton.setMaximumSize(100, 20)
|
|
348
|
+
okButton.setText('Dismiss')
|
|
349
|
+
hbox.addWidget(okButton)
|
|
350
|
+
|
|
351
|
+
vbox.addLayout(hbox)
|
|
352
|
+
|
|
353
|
+
self._listDialog.resize(cols * 115, maxrows * 50)
|
|
354
|
+
if not self._listDialog.isVisible():
|
|
355
|
+
self._listDialog.show()
|
|
356
|
+
|
|
357
|
+
@Slot()
|
|
358
|
+
def showMenuDialog(self):
|
|
359
|
+
"""
|
|
360
|
+
Shows a dialog with the output of the menu command in a table.
|
|
361
|
+
"""
|
|
362
|
+
refresh = True
|
|
363
|
+
|
|
364
|
+
if self._menuDialog is None:
|
|
365
|
+
refresh = False
|
|
366
|
+
self._menuDialog = QDialog(self)
|
|
367
|
+
self._menuDialog.setWindowTitle("Menu")
|
|
368
|
+
self._menuDialog.setModal(False)
|
|
369
|
+
|
|
370
|
+
# Available Curves
|
|
371
|
+
headerLabels = ['Label', 'X Label', 'Y Label', 'XMIN', 'XMAX', 'YMIN', 'YMAX', 'File Name', 'Sina Record ID']
|
|
372
|
+
rows = len(self._pydvcmd.curvelist)
|
|
373
|
+
cols = len(headerLabels)
|
|
374
|
+
|
|
375
|
+
# Create or clear table
|
|
376
|
+
if self._menuTableWidget is None:
|
|
377
|
+
self._menuTableWidget = QTableWidget(rows, cols, self)
|
|
378
|
+
self._menuTableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
|
379
|
+
self._menuTableWidget.setHorizontalHeaderLabels(headerLabels)
|
|
380
|
+
self._menuTableWidget.setAlternatingRowColors(True)
|
|
381
|
+
self._menuTableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
|
|
382
|
+
|
|
383
|
+
# Setup Right-click menu
|
|
384
|
+
self._menuTableWidget.setContextMenuPolicy(Qt.ActionsContextMenu)
|
|
385
|
+
plotCurveAction = QAction("Plot selected curve(s)", self._menuTableWidget)
|
|
386
|
+
plotCurveAction.triggered.connect(self.__plotMenuCurve)
|
|
387
|
+
self._menuTableWidget.addAction(plotCurveAction)
|
|
388
|
+
|
|
389
|
+
deleteCurveAction = QAction("Delete selected curve(s)", self._menuTableWidget)
|
|
390
|
+
deleteCurveAction.triggered.connect(self.__deleteMenuCurve)
|
|
391
|
+
self._menuTableWidget.addAction(deleteCurveAction)
|
|
392
|
+
else:
|
|
393
|
+
self._menuTableWidget.clearContents()
|
|
394
|
+
self._menuTableWidget.setRowCount(rows)
|
|
395
|
+
|
|
396
|
+
# Populate table with curves
|
|
397
|
+
row = 0
|
|
398
|
+
for c in self._pydvcmd.curvelist:
|
|
399
|
+
col = 0
|
|
400
|
+
|
|
401
|
+
# Plot Name
|
|
402
|
+
# prefix = ''
|
|
403
|
+
# if c.edited:
|
|
404
|
+
# prefix = '*'
|
|
405
|
+
# plotnameItem = QTableWidgetItem(self.tr("%s%s" % (prefix, c.plotname)))
|
|
406
|
+
# plotnameItem.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
|
|
407
|
+
# self._menuTableWidget.setItem(row, col, plotnameItem)
|
|
408
|
+
# col += 1
|
|
409
|
+
|
|
410
|
+
# Label
|
|
411
|
+
labelItem = QTableWidgetItem(self.tr(pdvutil.truncate(c.name, self._pydvcmd.namewidth)))
|
|
412
|
+
self._menuTableWidget.setItem(row, col, labelItem)
|
|
413
|
+
col += 1
|
|
414
|
+
|
|
415
|
+
# X Label
|
|
416
|
+
xlabelItem = QTableWidgetItem(self.tr(pdvutil.truncate(c.xlabel, self._pydvcmd.namewidth)))
|
|
417
|
+
self._menuTableWidget.setItem(row, col, xlabelItem)
|
|
418
|
+
col += 1
|
|
419
|
+
|
|
420
|
+
# Y Label
|
|
421
|
+
ylabelItem = QTableWidgetItem(self.tr(pdvutil.truncate(c.ylabel, self._pydvcmd.namewidth)))
|
|
422
|
+
self._menuTableWidget.setItem(row, col, ylabelItem)
|
|
423
|
+
col += 1
|
|
424
|
+
|
|
425
|
+
# xmin
|
|
426
|
+
xminItem = QTableWidgetItem(self.tr("%.2e" % min(c.x)))
|
|
427
|
+
self._menuTableWidget.setItem(row, col, xminItem)
|
|
428
|
+
col += 1
|
|
429
|
+
|
|
430
|
+
# xmax
|
|
431
|
+
xmaxItem = QTableWidgetItem(self.tr("%.2e" % max(c.x)))
|
|
432
|
+
self._menuTableWidget.setItem(row, col, xmaxItem)
|
|
433
|
+
col += 1
|
|
434
|
+
|
|
435
|
+
# ymin
|
|
436
|
+
yminItem = QTableWidgetItem(self.tr("%.2e" % min(c.y)))
|
|
437
|
+
self._menuTableWidget.setItem(row, col, yminItem)
|
|
438
|
+
col += 1
|
|
439
|
+
|
|
440
|
+
# ymax
|
|
441
|
+
ymaxItem = QTableWidgetItem(self.tr("%.2e" % max(c.y)))
|
|
442
|
+
self._menuTableWidget.setItem(row, col, ymaxItem)
|
|
443
|
+
col += 1
|
|
444
|
+
|
|
445
|
+
# File Name
|
|
446
|
+
fnameItem = QTableWidgetItem(self.tr(c.filename))
|
|
447
|
+
self._menuTableWidget.setItem(row, col, fnameItem)
|
|
448
|
+
col += 1
|
|
449
|
+
|
|
450
|
+
# Sina Record ID
|
|
451
|
+
recidItem = QTableWidgetItem(self.tr(c.record_id))
|
|
452
|
+
self._menuTableWidget.setItem(row, col, recidItem)
|
|
453
|
+
|
|
454
|
+
row += 1
|
|
455
|
+
|
|
456
|
+
maxrows = rows
|
|
457
|
+
if rows > 10:
|
|
458
|
+
maxrows = 10
|
|
459
|
+
|
|
460
|
+
if not refresh:
|
|
461
|
+
# Layout
|
|
462
|
+
vbox = QVBoxLayout(self._menuDialog)
|
|
463
|
+
|
|
464
|
+
# Scroll Bar
|
|
465
|
+
scroll = QScrollArea(self._menuDialog)
|
|
466
|
+
scroll.setGeometry(QRect(10, 20, cols * 115, maxrows * 50))
|
|
467
|
+
scroll.setMinimumSize(150, 150)
|
|
468
|
+
scroll.setWidget(self._menuTableWidget)
|
|
469
|
+
scroll.setWidgetResizable(True)
|
|
470
|
+
vbox.addWidget(scroll)
|
|
471
|
+
|
|
472
|
+
hbox = QHBoxLayout(self._menuDialog)
|
|
473
|
+
hbox.setAlignment(Qt.AlignCenter)
|
|
474
|
+
|
|
475
|
+
# Dismiss Button
|
|
476
|
+
okButton = QPushButton(self._menuDialog)
|
|
477
|
+
okButton.clicked.connect(self._menuDialog.close)
|
|
478
|
+
okButton.setMinimumSize(100, 20)
|
|
479
|
+
okButton.setMaximumSize(100, 20)
|
|
480
|
+
okButton.setText('Dismiss')
|
|
481
|
+
hbox.addWidget(okButton)
|
|
482
|
+
|
|
483
|
+
vbox.addLayout(hbox)
|
|
484
|
+
|
|
485
|
+
self._menuDialog.resize(cols * 115, maxrows * 50)
|
|
486
|
+
if not self._menuDialog.isVisible():
|
|
487
|
+
self._menuDialog.show()
|
|
488
|
+
|
|
489
|
+
def __viewCopyright(self):
|
|
490
|
+
msg = self.tr('<b><p style="font-family:verdana;"> \
|
|
491
|
+
Copyright © 2011-2024, Lawrence Livermore National Security, LLC. \
|
|
492
|
+
Produced at the Lawrence Livermore National Laboratory</p> \
|
|
493
|
+
<p style="font-family:verdana;">Written by Jorge Moreno, Sarah El-Jurf, \
|
|
494
|
+
Ephraim Rusu, Kevin Griffin, Mason Kwiat, and Douglas S. Miller</p> \
|
|
495
|
+
<p style="font-family:verdana;">e-mail: eljurf1@llnl.gov, moreno45@llnl.gov</p> \
|
|
496
|
+
<p style="font-family:verdana;">LLNL-CODE-507071</p> \
|
|
497
|
+
<p style="font-family:verdana;">All rights reserved.</p></b> \
|
|
498
|
+
<p style="font-family:courier; font-size:80%;">This file is part of PyDV. \
|
|
499
|
+
For details, see <URL describing code and \
|
|
500
|
+
how to download source>. Please also read "Additional BSD Notice".</p> \
|
|
501
|
+
<p style="font-family:courier; font-size:80%;"> Redistribution and use in \
|
|
502
|
+
source and binary forms, with or without \
|
|
503
|
+
modification, are permitted provided that the following conditions are met:</p> \
|
|
504
|
+
<p style="font-family:courier; font-size:80%;"> Redistributions of source code \
|
|
505
|
+
must retain the above copyright \
|
|
506
|
+
notice, this list of conditions and the disclaimer below. \
|
|
507
|
+
Redistributions in binary form must reproduce the above copyright \
|
|
508
|
+
notice, this list of conditions and the disclaimer (as noted below) \
|
|
509
|
+
in the documentation and/or other materials provided with the \
|
|
510
|
+
distribution. Neither the name of the LLNS/LLNL nor the names of \
|
|
511
|
+
its contributors may be used to endorse or promote products derived \
|
|
512
|
+
from this software without specific prior written permission.</p> \
|
|
513
|
+
<p style="font-family:courier; font-size:80%;"> THIS SOFTWARE IS PROVIDED \
|
|
514
|
+
BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \
|
|
515
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \
|
|
516
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS \
|
|
517
|
+
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LAWRENCE \
|
|
518
|
+
LIVERMORE NATIONAL SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR \
|
|
519
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \
|
|
520
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \
|
|
521
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF \
|
|
522
|
+
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND \
|
|
523
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, \
|
|
524
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT \
|
|
525
|
+
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF \
|
|
526
|
+
SUCH DAMAGE.</p> \
|
|
527
|
+
<p style="font-family:courier; font-size:80%;">Additional BSD Notice</p> \
|
|
528
|
+
<p style="font-family:courier; font-size:80%;"> 1. This notice is required \
|
|
529
|
+
to be provided under our contract with \
|
|
530
|
+
the U.S. Department of Energy (DOE). This work was produced at \
|
|
531
|
+
Lawrence Livermore National Laboratory under Contract \
|
|
532
|
+
No. DE-AC52-07NA27344 with the DOE.</p> \
|
|
533
|
+
<p style="font-family:courier; font-size:80%;"> 2. Neither the United States \
|
|
534
|
+
Government nor Lawrence Livermore \
|
|
535
|
+
National Security, LLC nor any of their employees, makes any \
|
|
536
|
+
warranty, express or implied, or assumes any liability or \
|
|
537
|
+
responsibility for the accuracy, completeness, or usefulness of any \
|
|
538
|
+
information, apparatus, product, or process disclosed, or represents \
|
|
539
|
+
that its use would not infringe privately-owned rights.</p> \
|
|
540
|
+
<p style="font-family:courier; font-size:80%;"> 3. Also, reference herein to \
|
|
541
|
+
any specific commercial products, \
|
|
542
|
+
process, or services by trade name, trademark, manufacturer or \
|
|
543
|
+
otherwise does not necessarily constitute or imply its endorsement, \
|
|
544
|
+
recommendation, or favoring by the United States Government or \
|
|
545
|
+
Lawrence Livermore National Security, LLC. The views and opinions \
|
|
546
|
+
of authors expressed herein do not necessarily state or reflect \
|
|
547
|
+
those of the United States Government or Lawrence Livermore National \
|
|
548
|
+
Security, LLC, and shall not be used for advertising or product \
|
|
549
|
+
endorsement purposes.</p>')
|
|
550
|
+
|
|
551
|
+
# Copyright Dialog
|
|
552
|
+
copy_dialog = QDialog(self)
|
|
553
|
+
copy_dialog.setWindowTitle("PyDV Copyright")
|
|
554
|
+
copy_dialog.setModal(True)
|
|
555
|
+
|
|
556
|
+
# Layout
|
|
557
|
+
vbox = QVBoxLayout(copy_dialog)
|
|
558
|
+
|
|
559
|
+
# Copyright message
|
|
560
|
+
html_view = QTextEdit(copy_dialog)
|
|
561
|
+
html_view.setReadOnly(True)
|
|
562
|
+
html_view.setText(msg)
|
|
563
|
+
|
|
564
|
+
scroll = QScrollArea(copy_dialog)
|
|
565
|
+
scroll.setGeometry(QRect(10, 20, 280, 400))
|
|
566
|
+
scroll.setMinimumSize(150, 150)
|
|
567
|
+
scroll.setWidget(html_view)
|
|
568
|
+
scroll.setWidgetResizable(True)
|
|
569
|
+
vbox.addWidget(scroll)
|
|
570
|
+
|
|
571
|
+
# OK Button
|
|
572
|
+
hbox = QHBoxLayout(copy_dialog)
|
|
573
|
+
okButton = QPushButton(copy_dialog)
|
|
574
|
+
okButton.clicked.connect(copy_dialog.close)
|
|
575
|
+
okButton.setMinimumSize(100, 20)
|
|
576
|
+
okButton.setMaximumSize(100, 20)
|
|
577
|
+
okButton.setText('OK')
|
|
578
|
+
hbox.addWidget(okButton, Qt.AlignCenter)
|
|
579
|
+
vbox.addLayout(hbox)
|
|
580
|
+
|
|
581
|
+
copy_dialog.resize(300, 500)
|
|
582
|
+
copy_dialog.show()
|
|
583
|
+
|
|
584
|
+
def __aboutQt(self):
|
|
585
|
+
QMessageBox.aboutQt(self)
|
|
586
|
+
|
|
587
|
+
def __aboutPyDV(self):
|
|
588
|
+
QMessageBox.about(self,
|
|
589
|
+
self.tr('About PyDV'),
|
|
590
|
+
self.tr('<h2>About PyDV</h2>'
|
|
591
|
+
f'<p style="font-family:courier; font-size:40%;">version {pydv_version}</p>'
|
|
592
|
+
'<p style="font-family:verdana;"><a href="https://pydv.readthedocs.io/en/latest/">\
|
|
593
|
+
PyDV</a> is a 1D graphics tool, heavily based on the ULTRA plotting tool.</p>'
|
|
594
|
+
'<p style="font-family:courier; font-size:-1;">Copyright © 2011-2024, \
|
|
595
|
+
Lawrence Livermore National Security, LLC.</p>'
|
|
596
|
+
'<p style="font-family:veranda; font-size:80%;">Written by: \
|
|
597
|
+
Jorge Moreno, Sarah El-Jurf, \
|
|
598
|
+
Ephraim Rusu, Kevin Griffin, Mason Kwiat, and Douglas S. Miller</p>'
|
|
599
|
+
'<p style="font-family:veranda; font-size:80%;">email: eljurf1@llnl.gov, \
|
|
600
|
+
moreno45@llnl.gov</p>'
|
|
601
|
+
'<p style="font-family:veranda; font-size:60%;"><i>LLNL-CODE-507071, \
|
|
602
|
+
All rights reserved.</i></p>'))
|
|
603
|
+
|
|
604
|
+
def __deleteCurve(self):
|
|
605
|
+
rowcnt = len(self._tableWidget.selectionModel().selectedRows())
|
|
606
|
+
|
|
607
|
+
if rowcnt > 0:
|
|
608
|
+
if rowcnt == len(self._pydvcmd.plotlist):
|
|
609
|
+
print("erase")
|
|
610
|
+
self._pydvcmd.do_erase("erase")
|
|
611
|
+
else:
|
|
612
|
+
plotnames = str()
|
|
613
|
+
for index in self._tableWidget.selectionModel().selectedRows():
|
|
614
|
+
row = index.row()
|
|
615
|
+
plotnames += "%s " % self._pydvcmd.plotlist[row].plotname
|
|
616
|
+
|
|
617
|
+
print("delete %s" % plotnames)
|
|
618
|
+
self._pydvcmd.do_delete("%s" % plotnames)
|
|
619
|
+
|
|
620
|
+
self._pydvcmd.updateplot
|
|
621
|
+
|
|
622
|
+
def __deleteMenuCurve(self):
|
|
623
|
+
rowcnt = len(self._menuTableWidget.selectionModel().selectedRows())
|
|
624
|
+
|
|
625
|
+
if rowcnt > 0:
|
|
626
|
+
if rowcnt == len(self._pydvcmd.curvelist):
|
|
627
|
+
print("kill all")
|
|
628
|
+
self._pydvcmd.do_kill("all")
|
|
629
|
+
else:
|
|
630
|
+
menuindexes = str()
|
|
631
|
+
for index in self._menuTableWidget.selectionModel().selectedRows():
|
|
632
|
+
row = index.row()
|
|
633
|
+
menuindexes += "%d " % (row + 1)
|
|
634
|
+
|
|
635
|
+
print("kill %s" % menuindexes)
|
|
636
|
+
self._pydvcmd.do_kill("%s" % menuindexes)
|
|
637
|
+
|
|
638
|
+
def __plotMenuCurve(self):
|
|
639
|
+
rowcnt = len(self._menuTableWidget.selectionModel().selectedRows())
|
|
640
|
+
|
|
641
|
+
if rowcnt > 0:
|
|
642
|
+
plotnames = str()
|
|
643
|
+
|
|
644
|
+
for index in self._menuTableWidget.selectionModel().selectedRows():
|
|
645
|
+
row = index.row()
|
|
646
|
+
plotnames += " %d" % (row + 1)
|
|
647
|
+
|
|
648
|
+
print("curve%s" % plotnames)
|
|
649
|
+
self._pydvcmd.do_curve("%s" % plotnames)
|
|
650
|
+
self._pydvcmd.updateplot
|
|
651
|
+
|
|
652
|
+
def __setgeometry(self):
|
|
653
|
+
geometry = self._geometry
|
|
654
|
+
if geometry != 'de':
|
|
655
|
+
self.setGeometry(int(geometry[2]), int(geometry[3]), int(geometry[0]), int(geometry[1]))
|
|
656
|
+
else:
|
|
657
|
+
self.setGeometry(50, 50, 600, 500)
|
|
658
|
+
|
|
659
|
+
def closeEvent(self, event):
|
|
660
|
+
event.ignore()
|