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.
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 &copy; 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 &copy; 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()