[401] | 1 | ## Python script to check model outputs within a given set of values from an external ASII file |
---|
| 2 | # L. Fita, LMD. April 2015 |
---|
| 3 | ## e.g. # checking_output.py -f histins.nc -v t2m -l 'limitsVariables.inf' |
---|
[403] | 4 | ## e.g. # python checking_output.py -f limit.nc -v SST,ALB -l 'limitsVariables.inf' |
---|
[401] | 5 | # NOTE: |
---|
| 6 | # `nc_var_tools.py' set of python scripts is required |
---|
| 7 | # can be found in subversion `http://svn.lmd.jussieu.fr/LMDZ_WRF/trunk/tools/nc_var_tools.py' |
---|
| 8 | import numpy as np |
---|
| 9 | from netCDF4 import Dataset as NetCDFFile |
---|
| 10 | import os |
---|
| 11 | import re |
---|
| 12 | from optparse import OptionParser |
---|
| 13 | import nc_var_tools as ncvar |
---|
| 14 | |
---|
| 15 | main = 'checking_output.py' |
---|
| 16 | version = 0.1 |
---|
| 17 | author = 'L. Fita' |
---|
| 18 | institution = 'Laboratoire de Meteorologie Dynamique' |
---|
| 19 | city = ' Paris' |
---|
| 20 | country = 'France' |
---|
| 21 | |
---|
| 22 | errormsg = 'ERROR -- error -- ERROR -- error' |
---|
| 23 | warnmsg = 'WARNING -- warning -- WARNING -- warning' |
---|
| 24 | |
---|
| 25 | fillValue = 1.e20 |
---|
| 26 | |
---|
| 27 | def compute_stddev(vals): |
---|
| 28 | """ Function to compute standard deviation |
---|
| 29 | vals= values |
---|
| 30 | """ |
---|
| 31 | fname = 'compute_stddev' |
---|
| 32 | |
---|
| 33 | mvals = np.mean(vals) |
---|
| 34 | m2vals = np.mean(vals*vals) |
---|
| 35 | |
---|
| 36 | stddev = np.sqrt(m2vals - mvals*mvals) |
---|
| 37 | |
---|
| 38 | return stddev |
---|
| 39 | |
---|
| 40 | def checking(cn,valc,vern,lval,Vn): |
---|
| 41 | """ Function to check a variable with |
---|
| 42 | cn= checking name |
---|
| 43 | valc= value to check |
---|
| 44 | vern= verification value |
---|
| 45 | lval= value to use for checking |
---|
| 46 | Vn= variable name |
---|
| 47 | """ |
---|
| 48 | fname = 'checking' |
---|
| 49 | |
---|
| 50 | VerN = vern[0:1] |
---|
| 51 | |
---|
| 52 | good = True |
---|
| 53 | if VerN == '<' and valc < lval: |
---|
| 54 | print warnmsg |
---|
| 55 | print ' ' + fname + " variable '" + vn + "' has a '" +cn+ "'",valc,vern,lval |
---|
| 56 | good = False |
---|
| 57 | elif VerN == '>' and valc > lval: |
---|
| 58 | print warnmsg |
---|
| 59 | print ' ' + fname + " variable '" + vn + "' has a '" +cn+ "'",valc,vern,lval |
---|
| 60 | good = False |
---|
| 61 | elif VerN == '%' and np.abs((valc-lval)*100./lval)>np.float(vern[1:len(vern)+1]): |
---|
| 62 | print warnmsg |
---|
| 63 | print ' ' + fname + " variable '" + vn + "' has a '" +cn+ "'", valc, '>', \ |
---|
| 64 | VerN, np.float(vern[1:len(vern)+1]), 'than',lval |
---|
| 65 | good = False |
---|
| 66 | |
---|
| 67 | return good |
---|
| 68 | |
---|
| 69 | |
---|
| 70 | ####### ###### ##### #### ### ## # |
---|
| 71 | |
---|
| 72 | parser = OptionParser() |
---|
| 73 | parser.add_option("-f", "--file", dest="ncfile", |
---|
| 74 | help="file to check", metavar="FILE") |
---|
| 75 | parser.add_option("-v", "--variable", dest="varns", |
---|
| 76 | help="var to check (',' list of variables; 'all', for all variables)", metavar="VALUE") |
---|
| 77 | parser.add_option("-l", "--ASCIIvarlimits", dest="lfile", |
---|
| 78 | help="ASCII file with the limits for the variables (long explanation with -l h)", metavar="FILE") |
---|
| 79 | |
---|
| 80 | (opts, args) = parser.parse_args() |
---|
| 81 | |
---|
| 82 | ####### ####### |
---|
| 83 | ## MAIN |
---|
| 84 | ####### |
---|
| 85 | |
---|
| 86 | # Available statistics |
---|
| 87 | Availablestats = ['min', 'max', 'mean', 'stddev'] |
---|
[402] | 88 | LAvailablestats = {'min':'minimum', 'max':'maximum', 'mean':'mean', \ |
---|
| 89 | 'stddev':'standard deviation'} |
---|
| 90 | |
---|
[401] | 91 | Availableverifs = ['<', '>', '%'] |
---|
[402] | 92 | SAvailableverifs = {'<':'lt', '>':'gt', '%':'percen'} |
---|
| 93 | LAvailableverifs = {'<':'smaller', '>':'bigger', '%':'percentage'} |
---|
[401] | 94 | |
---|
| 95 | ####### |
---|
| 96 | ofile = 'wrongvariables.nc' |
---|
| 97 | |
---|
| 98 | if not os.path.isfile(opts.ncfile): |
---|
| 99 | print errormsg |
---|
| 100 | print ' ' + main + ": file '" + opts.ncfile + "' does not exist !!" |
---|
| 101 | quit(-1) |
---|
| 102 | |
---|
| 103 | if opts.varns is None: |
---|
| 104 | print warnmsg |
---|
| 105 | print ' ' + main + ": no variables given!!" |
---|
| 106 | print ' checking all' |
---|
| 107 | varns = 'all' |
---|
| 108 | else: |
---|
| 109 | varns = opts.varns |
---|
| 110 | |
---|
| 111 | if opts.lfile is None: |
---|
| 112 | print warnmsg |
---|
| 113 | print ' ' + main + ": no ASCII file with limits for the variables is given!!" |
---|
| 114 | quit(-1) |
---|
| 115 | elif opts.lfile == 'h': |
---|
| 116 | print 'HELP: ASCII limits of the variables_____________' |
---|
| 117 | print 'First line: varname [stat1] [stat2] .... [statn]' |
---|
| 118 | print 'Second line: - [verif1] [verif2] ... [verifn]' |
---|
| 119 | print 'afterwards: [varname] [value1] [value2] ... [valuen]' |
---|
| 120 | print ' [stat]: statistics/parameter to compute. Has to exist wihin the script' |
---|
| 121 | print ' directly with an if or as function compute[stat]. Available ones are:' |
---|
| 122 | print ' ',Availablestats |
---|
| 123 | print ' [verif]: verification to make with the stat' |
---|
| 124 | print ' <: Error if variable has values smaller than the limit' |
---|
| 125 | print ' >: Error if variable has values bigger than the limit' |
---|
| 126 | print ' %N: Error if variable has values +/- N % than the limit' |
---|
| 127 | quit() |
---|
| 128 | |
---|
| 129 | ncobj = NetCDFFile(opts.ncfile, 'r') |
---|
| 130 | filevars = ncobj.variables.keys() |
---|
| 131 | |
---|
| 132 | # Getting variables names |
---|
| 133 | if varns == 'all': |
---|
| 134 | vns = filevars |
---|
| 135 | else: |
---|
| 136 | vns = opts.varns.split(',') |
---|
| 137 | |
---|
| 138 | Nvars = len(vns) |
---|
| 139 | print "From file '" + opts.ncfile + "' checking",Nvars,'variables...' |
---|
| 140 | |
---|
| 141 | # Getting ASCII file and its values |
---|
| 142 | ## |
---|
| 143 | # Assuming first line with something like varname min max mean stddev |
---|
| 144 | # Continuted with a line for each variable and value like: |
---|
| 145 | # t2m -70. 50. 20. 40. |
---|
| 146 | # (...) |
---|
| 147 | # It is required than this script some function called compute_[value] must be placed |
---|
| 148 | # '#' for comment |
---|
| 149 | olval = open(opts.lfile, 'r') |
---|
| 150 | ili = 0 |
---|
| 151 | statsverif = {} |
---|
| 152 | limitvals = {} |
---|
| 153 | |
---|
| 154 | for line in olval: |
---|
| 155 | linevals = ncvar.reduce_spaces(line) |
---|
| 156 | if len(linevals) != 0 and linevals[0][0:0] != '#': |
---|
| 157 | # print ili,linevals |
---|
| 158 | if ili == 0: |
---|
| 159 | NVals = len(linevals) - 1 |
---|
| 160 | stats = linevals[1:NVals + 1] |
---|
| 161 | elif ili == 1: |
---|
| 162 | for ist in range(NVals): |
---|
| 163 | statsverif[stats[ist]] = linevals[1+ist] |
---|
| 164 | else: |
---|
| 165 | limitvals[linevals[0]] = np.zeros((NVals), dtype=np.float) |
---|
| 166 | for ist in range(NVals): |
---|
| 167 | limitvals[linevals[0]][ist] = np.float(linevals[1+ist]) |
---|
| 168 | |
---|
| 169 | ili = ili + 1 |
---|
| 170 | |
---|
| 171 | # Checking stats to compute |
---|
| 172 | for st in stats: |
---|
| 173 | if not ncvar.searchInlist(Availablestats,st): |
---|
| 174 | print errormsg |
---|
| 175 | print ' ' + main + ": statistics/value '" + st + "' not ready!!" |
---|
| 176 | print ' available parameters:', Availablestats |
---|
| 177 | quit(-1) |
---|
| 178 | |
---|
| 179 | # Checking verifiaction to make |
---|
| 180 | for st in stats: |
---|
| 181 | verin = statsverif[st] |
---|
| 182 | if not ncvar.searchInlist(Availableverifs,verin[0:1]): |
---|
| 183 | print errormsg |
---|
| 184 | print ' ' + main + ": verification '" + verin + "' not ready!!" |
---|
| 185 | print ' available verifications:', Availableverifs |
---|
| 186 | quit(-1) |
---|
| 187 | |
---|
| 188 | print 'Checking',NVals,'parameters:',stats,'verifyed as:',statsverif.values() |
---|
| 189 | |
---|
[402] | 190 | # Creating output file |
---|
| 191 | oobj = NetCDFFile(ofile, 'w') |
---|
| 192 | |
---|
| 193 | # Dimensinos |
---|
| 194 | newdim = oobj.createDimension('stats', NVals) |
---|
| 195 | newdim = oobj.createDimension('verif', NVals) |
---|
| 196 | newdim = oobj.createDimension('checks', 2) |
---|
| 197 | newdim = oobj.createDimension('Lstring', 50) |
---|
| 198 | |
---|
| 199 | # Variables with Dimensions values |
---|
| 200 | newvar = oobj.createVariable('stats', 'c', ('stats', 'Lstring')) |
---|
| 201 | newattr = ncvar.basicvardef(newvar, 'stats', 'statistics/parameters used to check', \ |
---|
| 202 | '-') |
---|
| 203 | newvals = ncvar.writing_str_nc(newvar, stats, 50) |
---|
| 204 | |
---|
| 205 | newvar = oobj.createVariable('verifs', 'c', ('stats', 'Lstring')) |
---|
| 206 | newattr = ncvar.basicvardef(newvar, 'verifs', 'verifications used to check', '-') |
---|
| 207 | newvals = ncvar.writing_str_nc(newvar, stats, 50) |
---|
| 208 | |
---|
| 209 | newvar = oobj.createVariable('checks', 'c', ('checks', 'Lstring')) |
---|
| 210 | newattr = ncvar.basicvardef(newvar, 'checks', 'values used to check', '-') |
---|
| 211 | newvals = ncvar.writing_str_nc(newvar, ['computed', 'limits'], 50) |
---|
| 212 | |
---|
| 213 | # Global attributes |
---|
| 214 | newattr = ncvar.set_attribute(oobj, 'script', main) |
---|
| 215 | newattr = ncvar.set_attribute(oobj, 'version', version) |
---|
| 216 | newattr = ncvar.set_attribute(oobj, 'author', author) |
---|
| 217 | newattr = ncvar.set_attribute(oobj, 'institution', institution) |
---|
| 218 | newattr = ncvar.set_attribute(oobj, 'city', city) |
---|
| 219 | newattr = ncvar.set_attribute(oobj, 'country', country) |
---|
| 220 | |
---|
| 221 | newattr = ncvar.set_attribute(oobj, 'description', 'Variables from ' + opts.ncfile + \ |
---|
| 222 | ' with a wrong value according to ' + opts.lfile) |
---|
| 223 | |
---|
| 224 | oobj.sync() |
---|
| 225 | |
---|
[401] | 226 | # Getting netCDF file and its values |
---|
| 227 | ## |
---|
| 228 | valsstats = np.zeros((NVals,Nvars), dtype = np.float) |
---|
| 229 | wrongVars = {} |
---|
| 230 | iv = 0 |
---|
| 231 | for iv in range(Nvars): |
---|
| 232 | vn = vns[iv] |
---|
| 233 | print vn + '...' |
---|
| 234 | if not ncvar.searchInlist(filevars, vn): |
---|
| 235 | print errormsg |
---|
| 236 | print ' ' + main + ": file '" + opts.ncfile + "' does not have variable '" +\ |
---|
| 237 | vn + "' !!" |
---|
| 238 | quit(-1) |
---|
| 239 | |
---|
| 240 | vals = ncobj.variables[vn][:] |
---|
| 241 | wrongstats = [] |
---|
| 242 | for ist in range(NVals): |
---|
| 243 | stn = stats[ist] |
---|
[402] | 244 | Lstn = LAvailablestats[stn] |
---|
[401] | 245 | statpos = stats.index(stn) |
---|
| 246 | limitval = limitvals[vn][statpos] |
---|
| 247 | verif = statsverif[stn] |
---|
| 248 | # print ' ', ist, stn, ':',limitval,verif |
---|
| 249 | if stn == 'max': |
---|
| 250 | valsstats[ist,iv] = np.max(vals) |
---|
| 251 | elif stn == 'mean': |
---|
| 252 | valsstats[ist,iv] = np.mean(vals) |
---|
| 253 | elif stn == 'min': |
---|
| 254 | valsstats[ist,iv] = np.min(vals) |
---|
| 255 | elif stn == 'stddev': |
---|
| 256 | valsstats[ist,iv] = compute_stddev(vals) |
---|
| 257 | |
---|
| 258 | # checks |
---|
| 259 | if not checking(stn,valsstats[ist,iv],verif,limitval,vn): |
---|
[402] | 260 | vval = valsstats[ist,iv] |
---|
| 261 | Sverif = SAvailableverifs[verif[0:1]] |
---|
| 262 | Lverif = LAvailableverifs[verif[0:1]] |
---|
| 263 | if verif[0:1] != '<' and verif[0:1] != '>': |
---|
| 264 | Vverif = np.float(verif[1:len(verif)]) |
---|
| 265 | VverifS = str(Vverif) |
---|
| 266 | else: |
---|
| 267 | VverifS = '' |
---|
| 268 | |
---|
[401] | 269 | wrongstats.append(stn) |
---|
[402] | 270 | if not ncvar.searchInlist(oobj.variables.keys(), vn): |
---|
| 271 | oobj.close() |
---|
| 272 | ncvar.fvaradd(opts.ncfile + ':' + vn, ofile) |
---|
[401] | 273 | |
---|
[402] | 274 | oobj = NetCDFFile(ofile ,'a') |
---|
| 275 | vobj = oobj.variables[vn] |
---|
| 276 | if ncvar.searchInlist(vobj.ncattrs(),('units')): |
---|
| 277 | vunits = vobj.getncattr('units') |
---|
| 278 | else: |
---|
| 279 | vunits = '-' |
---|
| 280 | |
---|
| 281 | dims = vobj.dimensions |
---|
| 282 | # 1/0 Matrix with wrong values |
---|
| 283 | if stn == 'max': |
---|
| 284 | wrongvals = np.where(vals > limitval, 1, 0) |
---|
| 285 | newvar = oobj.createVariable(vn+'Wrong'+stn+Sverif, 'i', dims) |
---|
| 286 | newattr = ncvar.basicvardef(newvar, vn+'_wrong_'+stn+'_'+Sverif, \ |
---|
| 287 | 'wrong ' + vn + ' ' + str(vval) + ' ' + Lstn + ' ' + VverifS + ' '+\ |
---|
| 288 | Lverif + ' ' + str(limitval), vunits) |
---|
| 289 | newvar[:] = wrongvals |
---|
| 290 | elif stn == 'mean': |
---|
| 291 | newattr = ncvar.set_attribute(vobj, 'wrong_'+stn+'_'+Sverif+VverifS, \ |
---|
| 292 | 'wrong ' + vn + ' ' + str(vval) + ' ' + Lstn + ' ' + VverifS + ' '+\ |
---|
| 293 | Lverif + ' ' + str(limitval)) |
---|
| 294 | elif stn == 'min': |
---|
| 295 | wrongvals = np.where(vals < limitval, 1, 0) |
---|
| 296 | newvar = oobj.createVariable(vn+'Wrong'+stn+Sverif, 'i', dims) |
---|
| 297 | newattr = ncvar.basicvardef(newvar, vn+'_wrong_'+stn+'_'+Sverif, \ |
---|
| 298 | 'wrong ' + vn + ' ' + str(vval) + ' ' + Lstn + ' ' + VverifS + ' '+\ |
---|
| 299 | Lverif + ' ' + str(limitval), vunits) |
---|
| 300 | newvar[:] = wrongvals |
---|
| 301 | elif stn == 'stddev': |
---|
| 302 | newattr = ncvar.set_attribute(vobj, 'wrong_'+stn+'_'+Sverif+VverifS, \ |
---|
| 303 | 'wrong ' + vn + ' ' + str(vval) + ' ' + Lstn + ' ' + VverifS + ' '+\ |
---|
| 304 | Lverif + ' ' + str(limitval)) |
---|
| 305 | |
---|
[401] | 306 | if len(wrongstats) != 0: wrongVars[vn] = wrongstats |
---|
[402] | 307 | newattr = ncvar.set_attribute(vobj, 'wrong', \ |
---|
| 308 | ncvar.numVector_String(wrongVars[vn], ' ')) |
---|
[401] | 309 | |
---|
[402] | 310 | newvar = oobj.createVariable(vn + 'checks', 'f4', ('checks', 'stats')) |
---|
| 311 | newattr = ncvar.basicvardef(newvar, vn + '_checks', vn + \ |
---|
| 312 | ' computed/checked', vunits) |
---|
| 313 | for ist in range(NVals): |
---|
| 314 | newvar[:,ist] = [valsstats[ist,iv], limitvals[vn][ist]] |
---|
[401] | 315 | |
---|
[402] | 316 | oobj.sync() |
---|
| 317 | oobj.close() |
---|
| 318 | |
---|
[401] | 319 | # Results |
---|
| 320 | ## |
---|
| 321 | print ' Variables with Wrong results _______________________________________________' |
---|
| 322 | print wrongVars |
---|
| 323 | |
---|
[402] | 324 | print "succesfull writting of checking output file '" + ofile + "' !!" |
---|