lixiaojun
2025-04-25 03b6ae3d20508dccf1c7fd7ee4e1c2e02c3a1da1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# -*- coding: utf-8 -*-
 
#
#  __init__.py - nrtest_epanet module
#  Author:     Michael E. Tryby
#              US EPA - ORD/NRMRL
#
 
'''
Numerical regression testing (nrtest) plugin for comparing EPANET binary results 
files and EPANET text based report files. 
'''
 
# system imports
import itertools as it
 
# third party imports
import header_detail_footer as hdf
import numpy as np
 
# project import
import nrtest_epanet.output_reader as ordr
 
 
__author__ = "Michael Tryby"
__copyright__ = "None"
__credits__ = "Colleen Barr, Maurizio Cingi, Mark Gray, David Hall, Bryant McDonnell"
__license__ = "CC0 1.0 Universal"
 
__version__ = "0.5.0"
__date__ = "September 6, 2017"
 
__maintainer__ = "Michael Tryby"
__email__ = "tryby.michael@epa.gov"
__status  = "Development"
 
 
def epanet_allclose_compare(path_test, path_ref, rtol, atol):
    ''' 
    Compares results in two EPANET binary files using the comparison criteria 
    described in the numpy assert_allclose documentation. 
            
        (test_value - ref_value) <= atol + rtol * abs(ref_value) 
    
    Returns true if all of the results in the two binary files meet the 
    comparison criteria; otherwise, an AssertionError is thrown. 
    
    Numpy allclose is quite expensive to evaluate. Test and reference results 
    are checked to see if they are equal before being compared using the 
    allclose criteria. This reduces comparison times significantly. 
    
    Arguments: 
        path_test - path to result file being tested
        path_ref  - path to reference result file
        rtol - relative tolerance
        atol - absolute tolerance
    
    Returns: 
        True
                
    Raises:
        ValueError()
        AssertionError()
        ...
    '''
    for (test, ref) in it.izip(ordr.output_generator(path_test), 
                               ordr.output_generator(path_ref)):
        
        if len(test[0]) != len(ref[0]):
            raise ValueError('Inconsistent lengths')
        
        # Skip over arrays that are equal
        if np.array_equal(test[0], ref[0]):
            continue
        else:
            np.testing.assert_allclose(test[0], ref[0], rtol, atol)
 
    return True
 
 
def epanet_mincdd_compare(path_test, path_ref, rtol, atol):
    '''
    Compares the results of two EPANET binary files using a correct decimal
    digits (cdd) comparison criteria:
 
           min cdd(test, ref) >= atol
 
    Returns true if min cdd in the file is greater than or equal to atol,
    otherwise an AssertionError is thrown.
 
    Arguments:
        path_test - path to result file being testedgit
        path_ref  - path to reference result file
        rtol - ignored
        atol - minimum allowable cdd value (i.e. 3)
 
    Returns:
        True
 
    Raises:
        ValueError()
        AssertionError()
    '''
    min_cdd = 100.0
 
    for (test, ref) in it.izip(ordr.output_generator(path_test), 
                               ordr.output_generator(path_ref)):
 
        if len(test[0]) != len(ref[0]):
            raise ValueError('Inconsistent lengths')
 
        # Skip over arrays that are equal
        if np.array_equal(test[0], ref[0]):
            continue
        else:
            diff = np.fabs(np.subtract(test[0], ref[0]))
            idx = np.unravel_index(np.argmax(diff), diff.shape)
 
            if diff[idx] != 0.0:
                tmp = - np.log10(diff[idx])
 
                if tmp < min_cdd:
                    min_cdd = tmp;
 
    if np.floor(min_cdd) >= atol:
        return True
    else:
        raise AssertionError('min_cdd=%d less than atol=%g' % (min_cdd, atol))
 
 
def epanet_report_compare(path_test, path_ref, rtol, atol):
    '''
    Compares results in two report files ignoring contents of header and footer.
    
    Note: Header is 11 lines with report summary turned off. This test will fail 
    if the report summary is turned on because a time stamp is being written 
    immediately after it.  
    
    Arguments: 
        path_test - path to result file being tested
        path_ref  - path to reference result file
        rtol - ignored
        atol - ignored
    
    Returns: 
        True or False
        
    Raises: 
        HeaderError()
        FooterError()
        RunTimeError()
        ...
    '''
    HEADER = 10 
    FOOTER = 2
 
    with open(path_test ,'r') as ftest, open(path_ref, 'r') as fref:
        
        for (test_line, ref_line) in it.izip(hdf.parse(ftest, HEADER, FOOTER)[1], 
                                             hdf.parse(fref, HEADER, FOOTER)[1]): 
        
            if test_line != ref_line: 
                return False
 
    return True