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

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

merged trunk-jpl and trunk for revision 23187

File size: 10.0 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 if np.size(lowerbound)>1: #checking elementwise
135 if any(field<upperbound):
136 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
137 else:
138 minval=np.nanmin(field)
139 if options.getfieldvalue('timeseries',0):
140 minval=np.nanmin(field[:-1])
141 elif options.getfieldvalue('singletimeseries',0):
142 if np.size(field)==1: #some singletimeseries are just one value
143 minval=field
144 else:
145 minval=np.nanmin(field[0])
146
147 if minval<lowerbound:
148 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values above %d" % (fieldname,lowerbound)))
149
150 if options.exist('>'):
151 lowerbound=options.getfieldvalue('>')
152 if np.size(lowerbound)>1: #checking elementwise
153 if any(field<=upperbound):
154 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
155 else:
156 minval=np.nanmin(field)
157 if options.getfieldvalue('timeseries',0) :
158 minval=np.nanmin(field[:-1])
159 elif options.getfieldvalue('singletimeseries',0):
160 if np.size(field)==1: #some singletimeseries are just one value
161 minval=field
162 else:
163 minval=np.nanmin(field[0])
164
165 if minval<=lowerbound:
166 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values above %d" % (fieldname,lowerbound)))
167
168 #check smaller
169 if options.exist('<='):
170 upperbound=options.getfieldvalue('<=')
171 if np.size(upperbound)>1: #checking elementwise
172 if any(field>upperbound):
173 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
174 else:
175 maxval=np.nanmax(field)
176 if options.getfieldvalue('timeseries',0):
177 maxval=np.nanmax(field[:-1])
178 elif options.getfieldvalue('singletimeseries',0):
179 if np.size(field)==1: #some singletimeseries are just one value
180 maxval=field
181 else:
182 maxval=np.nanmax(field[0])
183 if maxval>upperbound:
184 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
185
186 if options.exist('<'):
187 upperbound=options.getfieldvalue('<')
188 if np.size(upperbound)>1: #checking elementwise
189 if any(field>=upperbound):
190 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
191
192 else:
193 maxval=np.nanmax(field)
194 if options.getfieldvalue('timeseries',0):
195 maxval=np.nanmax(field[:-1])
196 elif options.getfieldvalue('singletimeseries',0):
197 if np.size(field)==1: #some singletimeseries are just one value
198 maxval=field.copy()
199 else:
200 maxval=np.nanmax(field[0])
201
202 if maxval>=upperbound:
203 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
204
205 #check file
206 if options.getfieldvalue('file',0):
207 if not os.path.exists(field):
208 md = md.checkmessage("file provided in '%s': '%s' does not exist" % (fieldname,field))
209
210 #Check row of strings
211 if options.exist('stringrow'):
212 if not isinstance(field,list):
213 md = md.checkmessage(options.getfieldvalue('message',\
214 "field '%s' should be a list" %fieldname))
215
216 #Check forcings (size and times)
217 if options.getfieldvalue('timeseries',0):
218 if np.size(field,0)==md.mesh.numberofvertices or np.size(field,0)==md.mesh.numberofelements:
219 if np.ndim(field)>1 and not np.size(field,1)==1:
220 md = md.checkmessage(options.getfieldvalue('message',\
221 "field '%s' should have only one column as there are md.mesh.numberofvertices lines" % fieldname))
222 elif np.size(field,0)==md.mesh.numberofvertices+1 or np.size(field,0)==md.mesh.numberofelements+1:
223 if np.ndim(field) > 1 and not all(field[-1,:]==np.sort(field[-1,:])):
224 md = md.checkmessage(options.getfieldvalue('message',\
225 "field '%s' columns should be sorted chronologically" % fieldname))
226 if np.ndim(field) > 1 and any(field[-1,0:-1]==field[-1,1:]):
227 md = md.checkmessage(options.getfieldvalue('message',\
228 "field '%s' columns must not contain duplicate timesteps" % fieldname))
229 else:
230 md = md.checkmessage(options.getfieldvalue('message',\
231 "field '%s' should have md.mesh.numberofvertices or md.mesh.numberofvertices+1 lines" % fieldname))
232
233 #Check single value forcings (size and times)
234 if options.getfieldvalue('singletimeseries',0):
235 if np.size(field,0)==2:
236 if not all(field[-1,:]==np.sort(field[-1,:])):
237 md = md.checkmessage(options.getfieldvalue('message',\
238 "field '%s' columns should be sorted chronologically" % fieldname))
239 if any(field[-1,0:-1]==field[-1,1:]):
240 md = md.checkmessage(options.getfieldvalue('message',\
241 "field '%s' columns must not contain duplicate timesteps" % fieldname))
242 elif np.size(field,0) == 1:
243 if np.ndim(field) > 1 and not np.size(field,1) == 1:
244 md = md.checkmessage(options.getfieldvalue('message',\
245 "field '%s' should be either a scalar or have 2 lines" % fieldname))
246 else:
247 md = md.checkmessage(options.getfieldvalue('message',\
248 "field '%s' should have 2 lines or be a scalar" % fieldname))
249
250 return md
Note: See TracBrowser for help on using the repository browser.