tnccmp.py - pism - [fork] customized build of PISM, the parallel ice sheet model (tillflux branch)
(HTM) git clone git://src.adamsgaard.dk/pism
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) LICENSE
---
tnccmp.py (5124B)
---
1 #!/usr/bin/env python3
2 from sys import argv, exit
3 from getopt import getopt, GetoptError
4
5 # @package nccmp
6 # Compares NetCDF files by absolute max norms of difference of variables
7 ##
8 # Without options,
9 # \code
10 # nccmp.py foo.nc bar.nc
11 # \endcode
12 # compares all the variables in \c foo.nc and \c bar.nc.
13 ##
14 # Option \c -v allows selecting varibles to compare:
15 # \code
16 # nccmp.py -v thk,velbar_mag foo.nc bar.nc
17 # \endcode
18 # only compares \c thk and \c velbar_mag.
19 ##
20 # Option \c -t sets the tolerance:
21 # \code
22 # nccmp.py -t 1e-6 foo.nc bar.nc
23 # \endcode
24 # compares all the variables using the tolerance of 1e-6.
25 ##
26 # Finally, option \c -x \b excludes variables given with \c -v, instead of
27 # selecting them for comparison.
28 ##
29 # Run with --help to get a "usage" message.
30
31 tol = 0.0 # default tolerance is perfection
32
33
34 def success(relative):
35 if relative:
36 print("Files are the same within relative tolerance %.1e" % tol)
37 else:
38 print("Files are the same within tolerance %.1e" % tol)
39 exit(0)
40
41
42 def failure():
43 print("Files are different.")
44 exit(1)
45
46
47 usage = """nccmp.py compares NetCDF files by absolute max norms of difference of variables
48 usage:
49 nccmp.py foo.nc bar.nc compare all variables
50 nccmp.py -v A,B foo.nc bar.nc compare variables A and B
51 nccmp.py -x -v C foo.nc bar.nc compare all variables except C
52 nccmp.py -t 1e-6 foo.nc bar.nc use tolerance 1e-6 instead of default of 0"""
53
54
55 def usagefailure(message):
56 print(message)
57 print()
58 print(usage)
59 exit(2)
60
61
62 def compare_vars(nc1, nc2, name, tol, relative=False):
63 from numpy import squeeze, isnan, ma, finfo, fabs
64 import numpy
65
66 try:
67 var1 = ma.array(squeeze(nc1.variables[name][:]))
68 except:
69 usagefailure("ERROR: VARIABLE '%s' NOT FOUND IN FILE 1" % name)
70 try:
71 var2 = ma.array(squeeze(nc2.variables[name][:]))
72 except:
73 usagefailure("ERROR: VARIABLE '%s' NOT FOUND IN FILE 2" % name)
74
75 try:
76 mask = var1.mask | var2.mask
77 except:
78 usagefailure("ERROR: VARIABLE '%s' OF INCOMPATIBLE SHAPES (?) IN FILES" % name)
79
80 if mask.all():
81 print('Variable %10s: no values to compare.' % name)
82 return
83
84 var1 = ma.array(var1, mask=mask)
85 var2 = ma.array(var2, mask=mask)
86
87 try:
88 delta = abs(var1 - var2).max()
89 except TypeError:
90 if (var1 == var2).all():
91 delta = 0
92 else:
93 delta = 1
94
95 if relative:
96 denom = max(abs(var1).max(), abs(var2).max())
97 print("Variable %s: difference = %e, denominator = %e" % (name, delta, denom))
98 if denom > 0:
99 delta = delta / denom
100 print(" Relative difference = %e" % (delta))
101
102 # The actual check:
103 #
104 # Sometimes delta ends up being a denormalized number, which is zero
105 # for all practical purposes, but is not zero, so we give up on
106 # bit-for-bit equality here.
107 if delta > tol:
108 if tol == 0.0 and delta < 10 * finfo(float).tiny:
109 print("Variable %s: Treating %e as zero." % (name, delta))
110 return
111 print("Variable %s: delta = %e, tol = %e" % (name, delta, tol))
112 failure()
113
114
115 def compare(file1, file2, variables, exclude, tol, relative):
116 try:
117 from netCDF4 import Dataset as NC
118 except:
119 print("netCDF4 is not installed!")
120 exit(1)
121
122 print("Comparing %s and %s" % (file1, file2))
123
124 from numpy import unique, r_
125
126 try:
127 nc1 = NC(file1, 'r')
128 except:
129 usagefailure("ERROR: FILE '%s' CANNOT BE OPENED FOR READING" % file1)
130 try:
131 nc2 = NC(file2, 'r')
132 except:
133 usagefailure("ERROR: FILE '%s' CANNOT BE OPENED FOR READING" % file2)
134
135 if (exclude == False):
136 if len(variables) == 0:
137 vars1 = list(nc1.variables.keys())
138 vars2 = list(nc2.variables.keys())
139 variables = unique(r_[vars1, vars2])
140
141 for each in variables:
142 compare_vars(nc1, nc2, each, tol, relative)
143 else:
144 vars1 = list(nc1.variables.keys())
145 vars2 = list(nc2.variables.keys())
146 vars = unique(r_[vars1, vars2])
147
148 for each in vars:
149 if (each in variables):
150 continue
151 compare_vars(nc1, nc2, each, tol, relative)
152
153
154 if __name__ == "__main__":
155 from numpy import double
156 try:
157 opts, args = getopt(argv[1:], "t:v:xr", ["help", "usage"])
158 except GetoptError:
159 usagefailure('ERROR: INCORRECT COMMAND LINE ARGUMENTS FOR nccmp.py')
160 file1 = ""
161 file2 = ""
162 variables = []
163 exclude = False
164 relative = False
165 for (opt, arg) in opts:
166 if opt == "-t":
167 tol = double(arg)
168 if opt == "-x":
169 exclude = True
170 if opt == "-r":
171 relative = True
172 if opt == "-v":
173 variables = arg.split(",")
174 if opt in ("--help", "--usage"):
175 print(usage)
176 exit(0)
177
178 if len(args) != 2:
179 usagefailure('ERROR: WRONG NUMBER OF ARGUMENTS FOR nccmp.py')
180
181 compare(args[0], args[1], variables, exclude, tol, relative)
182
183 success(relative)