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
RevLine 
[21341]1import numpy as np
[12842]2import os
[17806]3from pairoptions import pairoptions
4import MatlabFuncs as m
[12842]5
[17806]6def checkfield(md,*args):
[12842]7 """
8 CHECKFIELD - check field consistency
9
[17806]10 Used to check model consistency.,
[23189]11 Requires:
12 'field' or 'fieldname' option. If 'fieldname' is provided, it will retrieve it from the model md. (md.(fieldname))
[17806]13 If 'field' is provided, it will assume the argument following 'field' is a numeric array.
14
[12943]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
[19105]23 - timeseries: 1 if check time series consistency (size and time)
[12943]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
[12842]29
[12943]30 Usage:
31 md = checkfield(md,fieldname,options);
[12842]32 """
33
34 #get options
35 options=pairoptions(*args)
36
37 #get field from model
[17806]38 if options.exist('field'):
39 field=options.getfieldvalue('field')
40 fieldname=options.getfieldvalue('fieldname','no fieldname')
41 else:
[23189]42 fieldname=options.getfieldvalue('fieldname')
[21341]43 exec("field=md.{}".format(fieldname))
[17806]44
[13043]45 if isinstance(field,(bool,int,long,float)):
[21341]46 field=np.array([field])
[12842]47
48 #check empty
[12943]49 if options.exist('empty'):
[12842]50 if not field:
51 md = md.checkmessage(options.getfieldvalue('message',\
52 "field '%s' is empty" % fieldname))
53
54 #Check size
[12943]55 if options.exist('size'):
[12842]56 fieldsize=options.getfieldvalue('size')
[21341]57 if len(fieldsize) == 1:
58 if np.isnan(fieldsize[0]):
[13023]59 pass
[21341]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))))
[12943]69 elif len(fieldsize) == 2:
[21341]70 if np.isnan(fieldsize[0]):
71 if not np.size(field,1)==fieldsize[1]:
[21729]72 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have %d columns" % (fieldname,fieldsize[1])))
[21341]73 elif np.isnan(fieldsize[1]):
74 if not np.size(field,0)==fieldsize[0]:
[21729]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])))
[12943]79 else:
[21341]80 if (not np.size(field,0)==fieldsize[0]) or (not np.size(field,1)==fieldsize[1]):
[21729]81 md = md.checkmessage(options.getfieldvalue('message',"field '%s' size should be %d x %d" % (fieldname,fieldsize[0],fieldsize[1])))
[23189]82
[12842]83 #Check numel
[12943]84 if options.exist('numel'):
[12842]85 fieldnumel=options.getfieldvalue('numel')
[22758]86 if (type(fieldnumel) == int and np.size(field) != fieldnumel) or (type(fieldnumel) == list and np.size(field) not in fieldnumel):
[12842]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):
[21341]99 if np.any(np.isnan(field)):
[12842]100 md = md.checkmessage(options.getfieldvalue('message',\
101 "NaN values found in field '%s'" % fieldname))
102
[22758]103
[20500]104 #check Inf
105 if options.getfieldvalue('Inf',0):
[21341]106 if np.any(np.isinf(field)):
[20500]107 md = md.checkmessage(options.getfieldvalue('message',\
108 "Inf values found in field '%s'" % fieldname))
109
[22758]110
[12842]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
[12943]118 if options.exist('values'):
[12842]119 fieldvalues=options.getfieldvalue('values')
[17806]120 if False in m.ismember(field,fieldvalues):
[12842]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
[12943]132 if options.exist('>='):
[22758]133 lowerbound = options.getfieldvalue('>=')
[23189]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])
[22758]146
[23189]147 if minval<lowerbound:
148 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values above %d" % (fieldname,lowerbound)))
[22758]149
[12943]150 if options.exist('>'):
[12842]151 lowerbound=options.getfieldvalue('>')
[23189]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])
[22758]164
[23189]165 if minval<=lowerbound:
166 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values above %d" % (fieldname,lowerbound)))
[22758]167
[12842]168 #check smaller
[12943]169 if options.exist('<='):
[12842]170 upperbound=options.getfieldvalue('<=')
[23189]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)))
[22758]185
[12943]186 if options.exist('<'):
[12842]187 upperbound=options.getfieldvalue('<')
[23189]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)))
[22758]191
[23189]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])
[22758]201
[23189]202 if maxval>=upperbound:
203 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
[12842]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
[16560]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
[12842]216 #Check forcings (size and times)
[19105]217 if options.getfieldvalue('timeseries',0):
[22758]218 if np.size(field,0)==md.mesh.numberofvertices or np.size(field,0)==md.mesh.numberofelements:
[21341]219 if np.ndim(field)>1 and not np.size(field,1)==1:
[12842]220 md = md.checkmessage(options.getfieldvalue('message',\
221 "field '%s' should have only one column as there are md.mesh.numberofvertices lines" % fieldname))
[22758]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,:])):
[12842]224 md = md.checkmessage(options.getfieldvalue('message',\
225 "field '%s' columns should be sorted chronologically" % fieldname))
[22758]226 if np.ndim(field) > 1 and any(field[-1,0:-1]==field[-1,1:]):
[12842]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
[20500]233 #Check single value forcings (size and times)
234 if options.getfieldvalue('singletimeseries',0):
[21341]235 if np.size(field,0)==2:
236 if not all(field[-1,:]==np.sort(field[-1,:])):
[20500]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))
[22758]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))
[20500]246 else:
247 md = md.checkmessage(options.getfieldvalue('message',\
[22758]248 "field '%s' should have 2 lines or be a scalar" % fieldname))
[20500]249
[12842]250 return md
Note: See TracBrowser for help on using the repository browser.