import numpy as np
import os
from issm.pairoptions import pairoptions
import issm.MatlabFuncs as m
[docs]def checkfield(md,*args):
"""
CHECKFIELD - check field consistency
Used to check model consistency.,
Requires:
'field' or 'fieldname' option. If 'fieldname' is provided, it will retrieve it from the model md. (md.(fieldname))
If 'field' is provided, it will assume the argument following 'field' is a numeric array.
Available options:
- NaN: 1 if check that there is no NaN
- size: [lines cols], NaN for non checked dimensions
- >: greater than provided value
- >=: greater or equal to provided value
- <: smallerthan provided value
- <=: smaller or equal to provided value
- < vec: smallerthan provided values on each vertex
- timeseries: 1 if check time series consistency (size and time)
- values: cell of strings or vector of acceptable values
- numel: list of acceptable number of elements
- cell: 1 if check that is cell
- empty: 1 if check that non empty
- message: overloaded error message
Usage:
md = checkfield(md,fieldname,options);
"""
#get options
options=pairoptions(*args)
#get field from model
if options.exist('field'):
field=options.getfieldvalue('field')
fieldname=options.getfieldvalue('fieldname','no fieldname')
else:
fieldname=options.getfieldvalue('fieldname')
exec("field=md.{}".format(fieldname))
if isinstance(field,(bool,int,long,float)):
field=np.array([field])
#check empty
if options.exist('empty'):
if not field:
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' is empty" % fieldname))
#Check size
if options.exist('size'):
fieldsize=options.getfieldvalue('size')
if len(fieldsize) == 1:
if np.isnan(fieldsize[0]):
pass
elif np.ndim(field)==1:
if not np.size(field)==fieldsize[0]:
md = md.checkmessage(options.getfieldvalue('message',"field {} size should be {}".format(fieldname,fieldsize[0])))
else:
try:
exec("md.{}=field[:,0]".format(fieldname))
print('{} had a bad dimension, we fixed it but you should check it'.format(fieldname))
except IndexError:
md = md.checkmessage(options.getfieldvalue('message',"field {} should have {} dimension".format(fieldname,len(fieldsize))))
elif len(fieldsize) == 2:
if np.isnan(fieldsize[0]):
if not np.size(field,1)==fieldsize[1]:
md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have %d columns" % (fieldname,fieldsize[1])))
elif np.isnan(fieldsize[1]):
if not np.size(field,0)==fieldsize[0]:
md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have %d lines" % (fieldname,fieldsize[0])))
elif fieldsize[1]==1:
if (not np.size(field,0)==fieldsize[0]):
md = md.checkmessage(options.getfieldvalue('message',"field '%s' size should be %d x %d" % (fieldname,fieldsize[0],fieldsize[1])))
else:
if (not np.size(field,0)==fieldsize[0]) or (not np.size(field,1)==fieldsize[1]):
md = md.checkmessage(options.getfieldvalue('message',"field '%s' size should be %d x %d" % (fieldname,fieldsize[0],fieldsize[1])))
#Check numel
if options.exist('numel'):
fieldnumel=options.getfieldvalue('numel')
if np.size(field) not in fieldnumel:
if len(fieldnumel)==1:
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' size should be %d" % (fieldname,fieldnumel)))
elif len(fieldnumel)==2:
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' size should be %d or %d" % (fieldname,fieldnumel[0],fieldnumel[1])))
else:
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' size should be %s" % (fieldname,fieldnumel)))
#check NaN
if options.getfieldvalue('NaN',0):
if np.any(np.isnan(field)):
md = md.checkmessage(options.getfieldvalue('message',\
"NaN values found in field '%s'" % fieldname))
#check Inf
if options.getfieldvalue('Inf',0):
if np.any(np.isinf(field)):
md = md.checkmessage(options.getfieldvalue('message',\
"Inf values found in field '%s'" % fieldname))
#check cell
if options.getfieldvalue('cell',0):
if not isinstance(field,(tuple,list,dict)):
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' should be a cell" % fieldname))
#check values
if options.exist('values'):
fieldvalues=options.getfieldvalue('values')
if False in m.ismember(field,fieldvalues):
if len(fieldvalues)==1:
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' value should be '%s'" % (fieldname,fieldvalues[0])))
elif len(fieldvalues)==2:
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' values should be '%s' or '%s'" % (fieldname,fieldvalues[0],fieldvalues[1])))
else:
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' should have values in %s" % (fieldname,fieldvalues)))
#check greater
if options.exist('>='):
lowerbound=options.getfieldvalue('>=')
if np.any(field<lowerbound):
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' should have values above %d" % (fieldname,lowerbound)))
if options.exist('>'):
lowerbound=options.getfieldvalue('>')
if np.any(field<=lowerbound):
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' should have values above %d" % (fieldname,lowerbound)))
#check smaller
if options.exist('<='):
upperbound=options.getfieldvalue('<=')
if np.any(field>upperbound):
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' should have values below %d" % (fieldname,upperbound)))
if options.exist('<'):
upperbound=options.getfieldvalue('<')
if np.any(field>=upperbound):
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' should have values below %d" % (fieldname,upperbound)))
#check file
if options.getfieldvalue('file',0):
if not os.path.exists(field):
md = md.checkmessage("file provided in '%s': '%s' does not exist" % (fieldname,field))
#Check row of strings
if options.exist('stringrow'):
if not isinstance(field,list):
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' should be a list" %fieldname))
#Check forcings (size and times)
if options.getfieldvalue('timeseries',0):
if np.size(field,0)==md.mesh.numberofvertices:
if np.ndim(field)>1 and not np.size(field,1)==1:
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' should have only one column as there are md.mesh.numberofvertices lines" % fieldname))
elif np.size(field,0)==md.mesh.numberofvertices+1 or np.size(field,0)==2:
if not all(field[-1,:]==np.sort(field[-1,:])):
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' columns should be sorted chronologically" % fieldname))
if any(field[-1,0:-1]==field[-1,1:]):
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' columns must not contain duplicate timesteps" % fieldname))
else:
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' should have md.mesh.numberofvertices or md.mesh.numberofvertices+1 lines" % fieldname))
#Check single value forcings (size and times)
if options.getfieldvalue('singletimeseries',0):
if np.size(field,0)==2:
if not all(field[-1,:]==np.sort(field[-1,:])):
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' columns should be sorted chronologically" % fieldname))
if any(field[-1,0:-1]==field[-1,1:]):
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' columns must not contain duplicate timesteps" % fieldname))
else:
md = md.checkmessage(options.getfieldvalue('message',\
"field '%s' should have 2 lines" % fieldname))
return md