source: lmdz_wrf/trunk/tools/checking_output.py @ 2831

Last change on this file since 2831 was 2407, checked in by lfita, 6 years ago

update and working version of the script

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