Skip to content

Commit c6d565f

Browse files
authored
Merge pull request #1 from jpn--/master
pull in validator
2 parents c6c5d63 + ec0765a commit c6d565f

3 files changed

Lines changed: 222 additions & 3 deletions

File tree

api/openmatrix/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
# GLOBAL VARIABLES -----------
1010
__version__ = '0.3.3'
11-
__omx_version__ = '0.2'
11+
__omx_version__ = b'0.2'
1212

1313
# GLOBAL FUNCTIONS -----------
1414
def open_file(filename, mode='r', title='', root_uep='/',

api/openmatrix/validator.py

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
import os
2+
from . import open_file as _open_file
3+
4+
def pass_or_fail(ok):
5+
return("Pass" if ok else "Fail")
6+
7+
def open_file(filename):
8+
mat_file = _open_file(filename, "r")
9+
print("File contents:", filename)
10+
print(mat_file)
11+
return(mat_file)
12+
13+
def check1(mat_file, required=True, checknum=1):
14+
try:
15+
print('\nCheck 1: Has OMX_VERSION attribute set to 0.2')
16+
ok = mat_file.root._v_attrs['OMX_VERSION'] == b'0.2'
17+
print(" File version is 0.2:", pass_or_fail(ok))
18+
return(ok, required, checknum)
19+
except Exception as err:
20+
return (False, required, checknum, str(err))
21+
22+
def check2(mat_file, required=True, checknum=2):
23+
try:
24+
print('\nCheck 2: Has SHAPE array attribute set to two item integer array')
25+
ok = len(mat_file.root._v_attrs['SHAPE']) == 2
26+
print(" Length is 2:", pass_or_fail(ok))
27+
ok_2 = int(mat_file.root._v_attrs['SHAPE'][0]) == mat_file.root._v_attrs['SHAPE'][0]
28+
print(" First item is integer:", pass_or_fail(ok_2))
29+
ok_3 = int(mat_file.root._v_attrs['SHAPE'][1]) == mat_file.root._v_attrs['SHAPE'][1]
30+
print(" Second item is integer:", pass_or_fail(ok_3))
31+
print(' Shape:', mat_file.shape())
32+
return(ok * ok_2 * ok_3, required, checknum)
33+
except Exception as err:
34+
return (False, required, checknum, str(err))
35+
36+
def check3(mat_file, required=True, checknum=3):
37+
try:
38+
print('\nCheck 3: Has data group for matrices')
39+
ok = 'data' in map(lambda x: x._v_name, mat_file.list_nodes("/"))
40+
print(" Group:", pass_or_fail(ok))
41+
print(' Number of Matrices:', len(mat_file))
42+
print(' Matrix names:', mat_file.list_matrices())
43+
return(ok, required, checknum)
44+
except Exception as err:
45+
return (False, required, checknum, str(err))
46+
47+
def check4(mat_file, required=True, checknum=4):
48+
try:
49+
print("\nCheck 4: Matrix shape matches file shape")
50+
ok = True
51+
for matrix in mat_file.list_matrices():
52+
ok_2 = (mat_file[matrix].shape == mat_file.root._v_attrs['SHAPE']).all()
53+
print(" Matrix shape: ", matrix, ":", mat_file[matrix].shape, ":", pass_or_fail(ok_2))
54+
ok = ok * ok_2
55+
return(ok, required, checknum)
56+
except Exception as err:
57+
return (False, required, checknum, str(err))
58+
59+
def check5(mat_file, required=True, checknum=5):
60+
try:
61+
print('\nCheck 5: Uses common data types (float or int) for matrices')
62+
ok = True
63+
for matrix in mat_file.list_matrices():
64+
ok_2 = (mat_file[matrix].dtype == float) or (mat_file[matrix].dtype == int)
65+
print(" Matrix: ", matrix, ":", mat_file[matrix].dtype, ":", pass_or_fail(ok_2))
66+
ok = ok * ok_2
67+
return(ok, required, checknum)
68+
except Exception as err:
69+
return (False, required, checknum, str(err))
70+
71+
def check6(mat_file, required=True, checknum=6):
72+
try:
73+
print('\nCheck 6: Matrices chunked for faster I/O')
74+
ok = True
75+
for matrix in mat_file.list_matrices():
76+
ok_2 = True if mat_file[matrix].chunkshape is not None else False
77+
print(" Matrix chunkshape: ", matrix, ":", mat_file[matrix].chunkshape, ":", pass_or_fail(ok_2))
78+
ok = ok * ok_2
79+
return(ok, required, checknum)
80+
except Exception as err:
81+
return (False, required, checknum, str(err))
82+
83+
def check7(mat_file, required=False, checknum=7):
84+
try:
85+
print('\nCheck 7: Uses zlib compression if compression used')
86+
ok = True
87+
for matrix in mat_file.list_matrices():
88+
ok_2 = True if mat_file[matrix].filters.complib is not None else False
89+
if ok_2:
90+
ok_3 = mat_file[matrix].filters.complib == 'zlib'
91+
ok_2 = ok_2 * ok_3
92+
print(" Matrix compression library and level: ", matrix, ":", mat_file[matrix].filters.complib, ":", mat_file[matrix].filters.complevel, ":", pass_or_fail(ok_2))
93+
ok = ok * ok_2
94+
return(ok, required, checknum)
95+
except Exception as err:
96+
return (False, required, checknum, str(err))
97+
98+
def check8(mat_file, required=False, checknum=8):
99+
try:
100+
print("\nCheck 8: Has NA attribute if desired (but not required)")
101+
ok = True
102+
for matrix in mat_file.list_matrices():
103+
ok_2 = mat_file[matrix].attrs.__contains__("NA")
104+
print(" Matrix NA attribute: ", matrix, ":", pass_or_fail(ok_2))
105+
ok = ok * ok_2
106+
return(ok, required, checknum)
107+
except Exception as err:
108+
return (False, required, checknum, str(err))
109+
110+
def check9(mat_file, required=False, checknum=9):
111+
try:
112+
print('\nCheck 9: Has lookup group for labels/indexes if desired (but not required)')
113+
ok = 'lookup' in map(lambda x: x._v_name, mat_file.list_nodes("/"))
114+
print(" Group:", pass_or_fail(ok))
115+
if ok:
116+
print(' Number of Lookups:', len(mat_file.list_mappings()))
117+
print(' Lookups names:', mat_file.list_mappings())
118+
return(ok, required, checknum)
119+
except Exception as err:
120+
return (False, required, checknum, str(err))
121+
122+
def check10(mat_file, required=False, checknum=10):
123+
try:
124+
print("\nCheck 10: Lookup shapes are 1-d and match file shape")
125+
ok = False
126+
if 'lookup' in map(lambda x: x._v_name, mat_file.list_nodes("/")):
127+
ok = True
128+
for lookup in mat_file.list_mappings():
129+
this_shape = mat_file.get_node(mat_file.root.lookup, lookup).shape
130+
ok_2 = len(this_shape)==1 and this_shape[0] in mat_file.root._v_attrs['SHAPE']
131+
print(" Lookup: ", lookup, ":", this_shape, ":", pass_or_fail(ok_2))
132+
ok = ok * ok_2
133+
return(ok, required, checknum)
134+
except Exception as err:
135+
return (False, required, checknum, str(err))
136+
137+
def check11(mat_file, required=False, checknum=11):
138+
try:
139+
print('\nCheck 11: Uses common data types (int or str) for lookups')
140+
is_int = lambda x: x == int
141+
ok = False
142+
if 'lookup' in map(lambda x: x._v_name, mat_file.list_nodes("/")):
143+
ok = True
144+
for lookup in mat_file.list_mappings():
145+
try:
146+
ok_2 = all(map(lambda x: x == int(x), mat_file.mapping(lookup).keys()))
147+
except ValueError:
148+
ok_2 = None
149+
if not ok_2:
150+
ok_2 = all(map(lambda x: x == str(x), mat_file.mapping(lookup).keys()))
151+
if not ok_2:
152+
ok_2 = all(map(lambda x: x == bytes(x), mat_file.mapping(lookup).keys()))
153+
this_dtype = mat_file.get_node(mat_file.root.lookup, lookup).dtype
154+
print(" Lookup: ", lookup, ":",this_dtype,":", pass_or_fail(ok_2))
155+
ok = ok * ok_2
156+
return(ok, required, checknum)
157+
except Exception as err:
158+
return (False, required, checknum, str(err))
159+
160+
def check12(mat_file, required=False, checknum=12):
161+
try:
162+
print("\nCheck 12: Has Lookup DIM attribute of 0 (row) or 1 (column) if desired (but not required)")
163+
print(" Not supported at this time by the Python openmatrix package")
164+
ok = False
165+
if 'lookup' in map(lambda x: x._v_name, mat_file.list_nodes("/")):
166+
ok = False
167+
return(ok, required, checknum)
168+
except Exception as err:
169+
return (False, required, checknum, str(err))
170+
171+
172+
def run_checks(filename):
173+
if not os.path.exists(filename):
174+
raise FileNotFoundError(filename)
175+
try:
176+
mat_file = open_file(filename)
177+
except:
178+
print("Unable to open", filename, "using HDF5")
179+
else:
180+
try:
181+
results = []
182+
results.append(check1(mat_file))
183+
results.append(check2(mat_file))
184+
results.append(check3(mat_file))
185+
results.append(check4(mat_file))
186+
results.append(check5(mat_file))
187+
results.append(check6(mat_file))
188+
results.append(check7(mat_file))
189+
results.append(check8(mat_file))
190+
results.append(check9(mat_file))
191+
results.append(check10(mat_file))
192+
results.append(check11(mat_file))
193+
results.append(check12(mat_file))
194+
print("\nOverall result ")
195+
overall_ok = True
196+
for result in results:
197+
if len(result) == 4:
198+
print(" ERROR", result[3])
199+
else:
200+
print(" Check", result[2], ":", "Required" if result[1] else "Not required", ":", pass_or_fail(result[0]))
201+
if result[1]:
202+
overall_ok = overall_ok * result[0]
203+
print(" Overall : ", pass_or_fail(overall_ok))
204+
finally:
205+
mat_file.close()
206+
207+
208+
def command_line():
209+
import argparse
210+
parser = argparse.ArgumentParser()
211+
parser.add_argument('filename', nargs=1, type=str, action="store", help='Open Matrix file to validate')
212+
args = parser.parse_args()
213+
run_checks(args.filename[0])

api/setup.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
setup(
77
name='OpenMatrix',
88
keywords='openmatrix omx',
9-
version='0.3.4.1',
9+
version='0.3.5.0',
1010
author='Billy Charlton, Ben Stabler',
1111
author_email='billy@okbecause.com, benstabler@yahoo.com',
1212
packages=find_packages(),
@@ -20,5 +20,11 @@
2020
],
2121
classifiers=[
2222
'License :: OSI Approved :: Apache Software License'
23-
]
23+
],
24+
entry_points={
25+
'console_scripts': [
26+
'omx-validate = openmatrix.validator:command_line',
27+
],
28+
}
29+
2430
)

0 commit comments

Comments
 (0)