|
1
|
|
|
# -*- coding: utf-8 -*- |
|
2
|
|
|
# vim:fileencoding=utf-8 |
|
3
|
|
|
# |
|
4
|
|
|
# Copyright (c) 2020 Stefan Bender |
|
5
|
|
|
# |
|
6
|
|
|
# This module is part of sciapy. |
|
7
|
|
|
# sciapy is free software: you can redistribute it or modify |
|
8
|
|
|
# it under the terms of the GNU General Public License as published |
|
9
|
|
|
# by the Free Software Foundation, version 2. |
|
10
|
|
|
# See accompanying LICENSE file or http://www.gnu.org/licenses/gpl-2.0.html. |
|
11
|
|
|
"""Compare netcdf files |
|
12
|
|
|
|
|
13
|
|
|
Compare netcdf files, testing the variable attributes and values |
|
14
|
|
|
to ensure format compatibility. |
|
15
|
|
|
""" |
|
16
|
|
|
import sys |
|
17
|
|
|
import xarray as xr |
|
18
|
|
|
|
|
19
|
|
|
__all__ = ["nccmpattrs", "ncallclose", "ncequal", "ncidentical"] |
|
20
|
|
|
|
|
21
|
|
|
|
|
22
|
|
|
def cmpvarattrs(v1, v2): |
|
23
|
|
|
"""Compare variable attribute values""" |
|
24
|
|
|
msg = "" |
|
25
|
|
|
same = True |
|
26
|
|
|
for a in v1.attrs: |
|
27
|
|
|
a1 = getattr(v1, a, None) |
|
28
|
|
|
a2 = getattr(v2, a, None) |
|
29
|
|
|
if a2 is None or a2 != a1: |
|
30
|
|
|
msg = "{0}\nL\t{1}\t{2}\t{3}\nR\t{1}\t{2}\t{4}".format( |
|
31
|
|
|
msg, v1.name, a, a1, a2, |
|
32
|
|
|
) |
|
33
|
|
|
same = False |
|
34
|
|
|
return same, msg |
|
35
|
|
|
|
|
36
|
|
|
|
|
37
|
|
|
def nccmpattrs(file1, file2, ignore=[]): |
|
38
|
|
|
"""Compare variable attributes and global attributes""" |
|
39
|
|
|
msg = "" |
|
40
|
|
|
same = True |
|
41
|
|
|
with xr.open_dataset(file1) as ds1: |
|
42
|
|
|
ds2 = xr.open_dataset(file2) |
|
43
|
|
|
for v in ds1.variables: |
|
44
|
|
|
same, msg = cmpvarattrs(ds1[v], ds2[v]) |
|
45
|
|
|
for attr in ds1.attrs: |
|
46
|
|
|
lattr = getattr(ds1, attr) |
|
47
|
|
|
rattr = getattr(ds2, attr) |
|
48
|
|
|
if lattr != rattr and attr not in ignore: |
|
49
|
|
|
msg = "{0}\nL\t{1}\t{2}\nR\t{1}\t{3}".format( |
|
50
|
|
|
msg, attr, lattr, rattr, |
|
51
|
|
|
) |
|
52
|
|
|
same = False |
|
53
|
|
|
assert same, msg |
|
54
|
|
|
|
|
55
|
|
|
|
|
56
|
|
|
def ncallclose(file1, file2): |
|
57
|
|
|
with xr.open_dataset(file1) as ds1: |
|
58
|
|
|
ds2 = xr.open_dataset(file2) |
|
59
|
|
|
xr.testing.assert_allclose(ds1, ds2) |
|
60
|
|
|
|
|
61
|
|
|
|
|
62
|
|
|
def ncequal(file1, file2): |
|
63
|
|
|
with xr.open_dataset(file1) as ds1: |
|
64
|
|
|
ds2 = xr.open_dataset(file2) |
|
65
|
|
|
xr.testing.assert_equal(ds1, ds2) |
|
66
|
|
|
|
|
67
|
|
|
|
|
68
|
|
|
def ncidentical(file1, file2, ignore=[]): |
|
69
|
|
|
with xr.open_dataset(file1) as ds1: |
|
70
|
|
|
ds2 = xr.open_dataset(file2) |
|
71
|
|
|
for ign in ignore: |
|
72
|
|
|
del ds1.attrs[ign] |
|
73
|
|
|
del ds2.attrs[ign] |
|
74
|
|
|
xr.testing.assert_identical(ds1, ds2) |
|
75
|
|
|
|
|
76
|
|
|
|
|
77
|
|
|
if __name__ == "__main__": |
|
78
|
|
|
nccmpattrs(*sys.argv[1:]) |
|
79
|
|
|
ncallclose(*sys.argv[1:]) |
|
80
|
|
|
ncequal(*sys.argv[1:]) |
|
81
|
|
|
ncidentical(*sys.argv[1:]) |
|
82
|
|
|
|