source: issm/trunk/src/m/consistency/checkfield.py@ 22758

Last change on this file since 22758 was 22758, checked in by Mathieu Morlighem, 7 years ago

merged trunk-jpl and trunk for revision 22757

File size: 9.3 KB
Line 
1import numpy as np
2import os
3from pairoptions import pairoptions
4import MatlabFuncs as m
5
6def checkfield(md,*args):
7 """
8 CHECKFIELD - check field consistency
9
10 Used to check model consistency.,
11 Requires:
12 'field' or 'fieldname' option. If 'fieldname' is provided, it will retrieve it from the model md. (md.(fieldname))
13 If 'field' is provided, it will assume the argument following 'field' is a numeric array.
14
15 Available options:
16 - NaN: 1 if check that there is no NaN
17 - size: [lines cols], NaN for non checked dimensions
18 - >: greater than provided value
19 - >=: greater or equal to provided value
20 - <: smallerthan provided value
21 - <=: smaller or equal to provided value
22 - < vec: smallerthan provided values on each vertex
23 - timeseries: 1 if check time series consistency (size and time)
24 - values: cell of strings or vector of acceptable values
25 - numel: list of acceptable number of elements
26 - cell: 1 if check that is cell
27 - empty: 1 if check that non empty
28 - message: overloaded error message
29
30 Usage:
31 md = checkfield(md,fieldname,options);
32 """
33
34 #get options
35 options=pairoptions(*args)
36
37 #get field from model
38 if options.exist('field'):
39 field=options.getfieldvalue('field')
40 fieldname=options.getfieldvalue('fieldname','no fieldname')
41 else:
42 fieldname=options.getfieldvalue('fieldname')
43 exec("field=md.{}".format(fieldname))
44
45 if isinstance(field,(bool,int,long,float)):
46 field=np.array([field])
47
48 #check empty
49 if options.exist('empty'):
50 if not field:
51 md = md.checkmessage(options.getfieldvalue('message',\
52 "field '%s' is empty" % fieldname))
53
54 #Check size
55 if options.exist('size'):
56 fieldsize=options.getfieldvalue('size')
57 if len(fieldsize) == 1:
58 if np.isnan(fieldsize[0]):
59 pass
60 elif np.ndim(field)==1:
61 if not np.size(field)==fieldsize[0]:
62 md = md.checkmessage(options.getfieldvalue('message',"field {} size should be {}".format(fieldname,fieldsize[0])))
63 else:
64 try:
65 exec("md.{}=field[:,0]".format(fieldname))
66 print('{} had a bad dimension, we fixed it but you should check it'.format(fieldname))
67 except IndexError:
68 md = md.checkmessage(options.getfieldvalue('message',"field {} should have {} dimension".format(fieldname,len(fieldsize))))
69 elif len(fieldsize) == 2:
70 if np.isnan(fieldsize[0]):
71 if not np.size(field,1)==fieldsize[1]:
72 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have %d columns" % (fieldname,fieldsize[1])))
73 elif np.isnan(fieldsize[1]):
74 if not np.size(field,0)==fieldsize[0]:
75 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have %d lines" % (fieldname,fieldsize[0])))
76 elif fieldsize[1]==1:
77 if (not np.size(field,0)==fieldsize[0]):
78 md = md.checkmessage(options.getfieldvalue('message',"field '%s' size should be %d x %d" % (fieldname,fieldsize[0],fieldsize[1])))
79 else:
80 if (not np.size(field,0)==fieldsize[0]) or (not np.size(field,1)==fieldsize[1]):
81 md = md.checkmessage(options.getfieldvalue('message',"field '%s' size should be %d x %d" % (fieldname,fieldsize[0],fieldsize[1])))
82
83 #Check numel
84 if options.exist('numel'):
85 fieldnumel=options.getfieldvalue('numel')
86 if (type(fieldnumel) == int and np.size(field) != fieldnumel) or (type(fieldnumel) == list and np.size(field) not in fieldnumel):
87 if len(fieldnumel)==1:
88 md = md.checkmessage(options.getfieldvalue('message',\
89 "field '%s' size should be %d" % (fieldname,fieldnumel)))
90 elif len(fieldnumel)==2:
91 md = md.checkmessage(options.getfieldvalue('message',\
92 "field '%s' size should be %d or %d" % (fieldname,fieldnumel[0],fieldnumel[1])))
93 else:
94 md = md.checkmessage(options.getfieldvalue('message',\
95 "field '%s' size should be %s" % (fieldname,fieldnumel)))
96
97 #check NaN
98 if options.getfieldvalue('NaN',0):
99 if np.any(np.isnan(field)):
100 md = md.checkmessage(options.getfieldvalue('message',\
101 "NaN values found in field '%s'" % fieldname))
102
103
104 #check Inf
105 if options.getfieldvalue('Inf',0):
106 if np.any(np.isinf(field)):
107 md = md.checkmessage(options.getfieldvalue('message',\
108 "Inf values found in field '%s'" % fieldname))
109
110
111 #check cell
112 if options.getfieldvalue('cell',0):
113 if not isinstance(field,(tuple,list,dict)):
114 md = md.checkmessage(options.getfieldvalue('message',\
115 "field '%s' should be a cell" % fieldname))
116
117 #check values
118 if options.exist('values'):
119 fieldvalues=options.getfieldvalue('values')
120 if False in m.ismember(field,fieldvalues):
121 if len(fieldvalues)==1:
122 md = md.checkmessage(options.getfieldvalue('message',\
123 "field '%s' value should be '%s'" % (fieldname,fieldvalues[0])))
124 elif len(fieldvalues)==2:
125 md = md.checkmessage(options.getfieldvalue('message',\
126 "field '%s' values should be '%s' or '%s'" % (fieldname,fieldvalues[0],fieldvalues[1])))
127 else:
128 md = md.checkmessage(options.getfieldvalue('message',\
129 "field '%s' should have values in %s" % (fieldname,fieldvalues)))
130
131 #check greater
132 if options.exist('>='):
133 lowerbound = options.getfieldvalue('>=')
134 field2 = np.reshape(field,(np.prod(np.shape(field)),1),order='F').copy()
135 if options.getfieldvalue('timeseries',0):
136 field2 = np.reshape(field[:-1],np.prod(np.shape(field[:-1])),1)
137
138 if options.getfieldvalue('singletimeseries',0):
139 field2 = np.reshape(field[0],np.prod(np.shape(field[0])),1)
140
141 if np.any(field2<lowerbound):
142 md = md.checkmessage(options.getfieldvalue('message',\
143 "field '%s' should have values above %d" % (fieldname,lowerbound)))
144
145 if options.exist('>'):
146 lowerbound=options.getfieldvalue('>')
147 field2 = np.reshape(field,(np.prod(np.shape(field)),1),order='F').copy()
148 if options.getfieldvalue('timeseries',0):
149 field2 = np.reshape(field[:-1],np.prod(np.shape(field[:-1])),1)
150
151 if options.getfieldvalue('singletimeseries',0):
152 field2 = np.reshape(field[0],np.prod(np.shape(field[0])),1)
153
154 if np.any(field2<=lowerbound):
155 md = md.checkmessage(options.getfieldvalue('message',\
156 "field '%s' should have values above %d" % (fieldname,lowerbound)))
157
158 #check smaller
159 if options.exist('<='):
160 upperbound=options.getfieldvalue('<=')
161 field2 = np.reshape(field,(np.prod(np.shape(field)),1),order='F').copy()
162 if options.getfieldvalue('timeseries',0):
163 field2 = np.reshape(field[:-1],np.prod(np.shape(field[:-1])),1)
164
165 if options.getfieldvalue('singletimeseries',0):
166 field2 = np.reshape(field[0],np.prod(np.shape(field[0])),1)
167
168 if np.any(field2>upperbound):
169 md = md.checkmessage(options.getfieldvalue('message',\
170 "field '%s' should have values below %d" % (fieldname,upperbound)))
171 if options.exist('<'):
172 upperbound=options.getfieldvalue('<')
173 field2 = np.reshape(field,(np.prod(np.shape(field)),1),order='F').copy()
174 if options.getfieldvalue('timeseries',0):
175 field2 = np.reshape(field[:-1],np.prod(np.shape(field[:-1])),1)
176
177 if options.getfieldvalue('singletimeseries',0):
178 field2 = np.reshape(field[0],np.prod(np.shape(field[0])),1)
179
180 if np.any(field2>=upperbound):
181 md = md.checkmessage(options.getfieldvalue('message',\
182 "field '%s' should have values below %d" % (fieldname,upperbound)))
183
184 #check file
185 if options.getfieldvalue('file',0):
186 if not os.path.exists(field):
187 md = md.checkmessage("file provided in '%s': '%s' does not exist" % (fieldname,field))
188
189 #Check row of strings
190 if options.exist('stringrow'):
191 if not isinstance(field,list):
192 md = md.checkmessage(options.getfieldvalue('message',\
193 "field '%s' should be a list" %fieldname))
194
195 #Check forcings (size and times)
196 if options.getfieldvalue('timeseries',0):
197 if np.size(field,0)==md.mesh.numberofvertices or np.size(field,0)==md.mesh.numberofelements:
198 if np.ndim(field)>1 and not np.size(field,1)==1:
199 md = md.checkmessage(options.getfieldvalue('message',\
200 "field '%s' should have only one column as there are md.mesh.numberofvertices lines" % fieldname))
201 elif np.size(field,0)==md.mesh.numberofvertices+1 or np.size(field,0)==md.mesh.numberofelements+1:
202 if np.ndim(field) > 1 and not all(field[-1,:]==np.sort(field[-1,:])):
203 md = md.checkmessage(options.getfieldvalue('message',\
204 "field '%s' columns should be sorted chronologically" % fieldname))
205 if np.ndim(field) > 1 and any(field[-1,0:-1]==field[-1,1:]):
206 md = md.checkmessage(options.getfieldvalue('message',\
207 "field '%s' columns must not contain duplicate timesteps" % fieldname))
208 else:
209 md = md.checkmessage(options.getfieldvalue('message',\
210 "field '%s' should have md.mesh.numberofvertices or md.mesh.numberofvertices+1 lines" % fieldname))
211
212 #Check single value forcings (size and times)
213 if options.getfieldvalue('singletimeseries',0):
214 if np.size(field,0)==2:
215 if not all(field[-1,:]==np.sort(field[-1,:])):
216 md = md.checkmessage(options.getfieldvalue('message',\
217 "field '%s' columns should be sorted chronologically" % fieldname))
218 if any(field[-1,0:-1]==field[-1,1:]):
219 md = md.checkmessage(options.getfieldvalue('message',\
220 "field '%s' columns must not contain duplicate timesteps" % fieldname))
221 elif np.size(field,0) == 1:
222 if np.ndim(field) > 1 and not np.size(field,1) == 1:
223 md = md.checkmessage(options.getfieldvalue('message',\
224 "field '%s' should be either a scalar or have 2 lines" % fieldname))
225 else:
226 md = md.checkmessage(options.getfieldvalue('message',\
227 "field '%s' should have 2 lines or be a scalar" % fieldname))
228
229 return md
230
231
Note: See TracBrowser for help on using the repository browser.