1
+ import ast
1
2
import numpy as np
2
3
from qtpy .QtCore import Qt
4
+ from qtpy .QtGui import QDoubleValidator
3
5
from qtpy .QtWidgets import (QWidget , QVBoxLayout , QListWidget , QSplitter , QDialogButtonBox , QHBoxLayout ,
4
- QDialog , QLabel , QCheckBox )
6
+ QDialog , QLabel , QCheckBox , QLineEdit , QComboBox )
5
7
6
- from larray import (LArray , Session , Axis , X , stack , full , full_like , zeros_like ,
7
- nan , isnan , larray_nan_equal , nan_equal )
8
+ from larray import LArray , Session , Axis , stack , full_like , nan , larray_nan_equal , element_equal
8
9
from larray_editor .utils import ima , replace_inf , _
9
10
from larray_editor .arraywidget import ArrayEditorWidget
10
11
@@ -16,6 +17,7 @@ def __init__(self, parent=None):
16
17
17
18
layout = QVBoxLayout ()
18
19
self .setLayout (layout )
20
+
19
21
# max diff label
20
22
maxdiff_layout = QHBoxLayout ()
21
23
maxdiff_layout .addWidget (QLabel ('maximum absolute relative difference:' ))
@@ -26,36 +28,80 @@ def __init__(self, parent=None):
26
28
27
29
self .arraywidget = ArrayEditorWidget (self , data = None , readonly = True , bg_gradient = 'red-white-blue' )
28
30
31
+ # show difference only
29
32
diff_checkbox = QCheckBox (_ ('Differences Only' ))
30
33
diff_checkbox .stateChanged .connect (self .display )
31
34
self .diff_checkbox = diff_checkbox
32
35
self .arraywidget .btn_layout .addWidget (diff_checkbox )
33
36
37
+ # absolute/relative tolerance
38
+ tolerance_layout = QHBoxLayout ()
39
+ tooltip = """Element i of two arrays are considered as equal if they satisfy the following equation:
40
+ abs(array1[i] - array2[i]) <= (absolute_tol + relative_tol * abs(array2[i]))"""
41
+
42
+ tolerance_label = QLabel ("tolerance:" )
43
+ tolerance_label .setToolTip (tooltip )
44
+ self .arraywidget .btn_layout .addWidget (tolerance_label )
45
+
46
+ tolerance_combobox = QComboBox ()
47
+ tolerance_combobox .addItems (["absolute" , "relative" ])
48
+ tolerance_combobox .setToolTip (tooltip )
49
+ tolerance_combobox .currentTextChanged .connect (self .update_isequal )
50
+ tolerance_layout .addWidget (tolerance_combobox )
51
+ self .tolerance_combobox = tolerance_combobox
52
+
53
+ tolerance_line_edit = QLineEdit ()
54
+ tolerance_line_edit .setValidator (QDoubleValidator ())
55
+ tolerance_line_edit .setPlaceholderText ("1e-8" )
56
+ tolerance_line_edit .setMaximumWidth (80 )
57
+ tolerance_line_edit .setToolTip ("Press Enter to activate the new tolerance value" )
58
+ tolerance_line_edit .editingFinished .connect (self .update_isequal )
59
+ tolerance_layout .addWidget (tolerance_line_edit )
60
+ self .tolerance_line_edit = tolerance_line_edit
61
+
62
+ self .arraywidget .btn_layout .addLayout (tolerance_layout )
63
+
64
+ # add local arraywidget to layout
65
+ self .arraywidget .btn_layout .addStretch ()
34
66
layout .addWidget (self .arraywidget )
35
67
36
68
self .array = None
69
+ self .array0 = None
37
70
self .isequal = None
38
71
self .bg_value = None
39
72
self .stack_axis = None
40
73
74
+ # override keyPressEvent to prevent pressing Enter after changing the tolerance value
75
+ # in associated QLineEdit to close the parent dialog box
76
+ def keyPressEvent (self , event ):
77
+ if event .key () == Qt .Key_Enter or event .key () == Qt .Key_Return :
78
+ return
79
+ QWidget .keyPressEvent (self , event )
80
+
41
81
def set_data (self , arrays , stack_axis ):
42
82
assert all (np .isscalar (a ) or isinstance (a , LArray ) for a in arrays )
43
83
self .stack_axis = stack_axis
44
84
try :
45
85
self .array = stack (arrays , stack_axis )
46
- array0 = self .array [stack_axis .i [0 ]]
86
+ self . array0 = self .array [stack_axis .i [0 ]]
47
87
except Exception as e :
48
88
self .array = LArray (str (e ))
49
- array0 = self .array
89
+ self .array0 = self .array
90
+ self .update_isequal ()
91
+
92
+ def update_isequal (self ):
50
93
try :
51
- self .isequal = nan_equal (self .array , array0 )
94
+ tol_str = self .tolerance_line_edit .text ()
95
+ tol = ast .literal_eval (tol_str ) if tol_str else 0
96
+ atol , rtol = (tol , 0 ) if self .tolerance_combobox .currentText () == "absolute" else (0 , tol )
97
+ self .isequal = element_equal (self .array , self .array0 , rtol = rtol , atol = atol , nan_equals = True )
52
98
except TypeError :
53
- self .isequal = self .array == array0
99
+ self .isequal = self .array == self . array0
54
100
55
101
try :
56
102
with np .errstate (divide = 'ignore' , invalid = 'ignore' ):
57
- diff = self .array - array0
58
- reldiff = diff / array0
103
+ diff = self .array - self . array0
104
+ reldiff = diff / self . array0
59
105
# this is necessary for nan, inf and -inf (because inf - inf = nan, not 0)
60
106
# this is more precise than divnot0, it only ignore 0 / 0, not x / 0
61
107
reldiff [self .isequal ] = 0
0 commit comments