source: CMIP6dreqbuild/trunk/src/framework/audit.py @ 1207

Subversion URL: http://proj.badc.rl.ac.uk/svn/exarch/CMIP6dreqbuild/trunk/src/framework/audit.py@1207
Revision 1207, 29.7 KB checked in by mjuckes, 2 years ago (diff)

updates£

Line 
1
2from dreqPy import dreq
3from dreqPy import misc_utils
4from ingest import mipTab
5##from ingest import loadcf
6import cmchecl
7import collections, sys, os, json
8
9def mapCoreAt(x):
10  if type(x) != type( 'x' ):
11    return '--no string--'
12  else:
13    return x
14
15realms = [
16        "aerosol",
17        "atmos",
18        "atmosChem",
19        "land",
20        "landIce",
21        "ocean",
22        "ocnBgChem",
23        "seaIce"
24    ]
25
26python2 = True
27if sys.version_info[0] == 3:
28  python2 = False
29
30if len(sys.argv) > 1:
31  lname = sys.argv[1]
32else:
33  lname = 'audit'
34logFarm = misc_utils.dreqLog(dir='logs')
35log = logFarm.getLog(lname)
36
37class c1(object):
38  def __init__(self):
39    self.a = collections.defaultdict( list )
40
41class checkUnits(object):
42
43  def __init__(self, cc, extra=None):
44    assert python2, 'The checkUnits module requires cf, which is not available in python 3'
45    import cf
46    if extra != None:
47      for k in sorted( extra.keys() ):
48        try:
49          a = cf.units.Units( k )
50        except:
51          log.warn( 'WARN.001.0004: bad units %s (%s)' % (k,str(extra[k])) )
52
53    for k in sorted( cc.keys() ):
54      try:
55        a = cf.units.Units( k )
56      except:
57        log.warn( 'Bad CF units: %s' % k )
58        a = None
59
60      if a != None:
61        for k2 in cc[k].a:
62          try:
63            b = cf.units.Units( k2 )
64          except:
65            b = None
66            log.warn( 'WARN.001.0003: unit invalid : %s .... %s: %s' % (k,k2,str( cc[k].a[k2]) ) )
67          if b != None and not a.equivalent(b):
68            log.warn( 'WARN.001.0002: unit mismatch: %s .... %s: %s' % (k,k2,str( cc[k].a[k2]) ) )
69
70def splitStr( s ):
71  if s == '':
72    return ['']
73  if s.find( ' ') == -1:
74    return [s,]
75  return s.split()
76
77class checkDims(object):
78
79  def __init__(self, dq):
80    """Generate list of used dimensions in ss;
81       Check against defined dimenions [todo]"""
82    ss = set()
83    self.cellm = set()
84    cc = collections.defaultdict(list)
85    duds = ('', '****', '?',)
86    for i in dq.coll['spatialShape'].items:
87      if i.dimensions != '':
88        for x in i.dimensions.split( '|' ):
89          if x in duds:
90            cc[x].append( i.uid )
91          else:
92            ss.add(x)
93    for i in dq.coll['temporalShape'].items:
94      if i.dimensions != '':
95        for x in i.dimensions.split( '|' ):
96          if x in duds:
97            cc[x].append( i.uid )
98          else:
99            ss.add(x)
100    for i in dq.coll['structure'].items:
101      self.cellm.add( i.cell_methods )
102      if 'odims' in i.__dict__:
103        if i.odims != '':
104          for x in i.odims.split( ' ' ):
105            if x in duds:
106              cc[x].append( i.uid )
107            else:
108              ss.add(x)
109      if 'coords' in i.__dict__:
110        if i.coords != '':
111          for x in i.coords.split( ' ' ):
112            if x in duds:
113              cc[x].append( i.uid )
114            else:
115              ss.add(x)
116
117    cellm = sorted( list( self.cellm ) )
118    for c in cellm:
119      log.info( 'cell_methods\t %s' % c )
120    log.info( str( sorted( list(ss) ) ) )
121    ll = set( [i.label for i in dq.coll['grids'].items] )
122    for x in ss:
123      if x not in ll:
124        log.error( 'ERROR: dimension not found: %s' % x )
125
126
127class auditor(object):
128  def __init__(self,dq):
129    self.dq = dq
130    self.run()
131
132  def run(self):
133    self.loadDraftNewVar()
134    self.audit_var()
135    self.audit_sn()
136    self.audit_cmv()
137    self.audit_rqv()
138    self.audit_rql()
139    self.audit_rqg()
140    self.audit_str()
141    self.audit_cm()
142    self.audit_expt()
143
144  def audit_expt(self):
145    file = '/home/mjuckes/Desktop/git//CMIP6_CVs/CMIP6_experiment_id.json'
146    ex = json.load( open( file ) )
147    ne = 0
148    ss = set()
149    for i in self.dq.coll['experiment'].items:
150      ss.add(i.label)
151      if i.label not in ex['experiment_id']:
152         log.error( 'ERROR.expt.00001: experiment name not found: %s' % (i.label) )
153         ne += 1
154    if ne == 0:
155       log.info( 'INFO.expt.00001: all experiment names valid' )
156
157    ne = 0
158    for k in ex['experiment_id']:
159      if k not in ss:
160         log.error( 'ERROR.expt.00002: experiment name not used: %s [%s]' % (k,ex['experiment_id'][k].get("activity_id",'__missing__') )  )
161         ne += 1
162    if ne == 0:
163       log.info( 'INFO.expt.00002: all experiment names used' )
164       
165  def audit_cm(self):
166    log.info( 'Running Cell Methods Audit' )
167    cc = cmchecl.check_cm()
168    nf = 0
169    for i in self.dq.coll['cellMethods'].items:
170      res = cc.test( i.cell_methods )
171      if not res:
172         log.error( 'ERROR.cm.00001: cannot parse cell methods: "%s" [%s]' % (i.cell_methods,i.label) )
173         nf += 1
174    if nf == 0:
175       log.info( 'INFO.cm.00001: all cell methods strings parsed by cmchecl' )
176
177    l1 = [i for i in self.dq.coll['structure'].items if i.cell_methods == ""]
178    ss = set()
179    if len( l1 ) > 0:
180      log.error( 'ERROR.cm.00010: %s blank cell methods in structure records: ' % len(l1) )
181      for i in l1:
182        log.error( 'ERROR.cm.00011: %s: %s' % ( i.label, i.title )  )
183    for i in l1:
184      if 'CMORvar' in self.dq.inx.iref_by_sect[i.uid].a:
185        for u in dq.inx.iref_by_sect[i.uid].a['CMORvar']:
186           ss.add(u)
187    if len(ss) > 0:
188      log.error( 'ERROR.cm.00020: %s CMOR vars affected ' % len(ss) )
189      for u in ss:
190        cmv = dq.inx.uid[u]
191        log.error( 'ERROR.cm.00021: Invalid cell methods: %s, %s, %s [%s]' % (cmv.label, cmv.title, cmv.mipTable, cmv.prov) )
192
193    aclim = dq.inx.uid['CellMethods::aclim'].uid
194    for ustr in dq.inx.iref_by_sect[aclim].a['structure']:
195      print 'INFO.aclim: checking %s vars' % len( dq.inx.iref_by_sect[ustr].a['CMORvar'] )
196      for ucmv in dq.inx.iref_by_sect[ustr].a['CMORvar']:
197        if dq.inx.uid[ucmv].frequency != 'monClim':
198          print 'ERROR.aclim.00001: %s, %s, %s, %s' % (ucmv,dq.inx.uid[ucmv].frequency,dq.inx.uid[ucmv].label,dq.inx.uid[ucmv].mipTable)
199
200  def audit_var(self):
201    cc = collections.defaultdict( list )
202    ss = collections.defaultdict( c1 )
203    ssx = collections.defaultdict( set )
204    umap = { 'Wm-2':'W m-2', 'string':''}
205    for i in self.dq.coll['var'].items:
206      cc[i.label].append(i)
207      if i.sn not in self.dq.inx.uid:
208         print 'SEVERE: standard name uid not valid: %s' % i.sn
209      else:
210        isn = self.dq.inx.uid[i.sn]
211        if isn._h.label != 'remarks':
212          u = umap.get( isn.units, isn.units )
213          ss[u].a[i.units].append( i.label )
214        else:
215          ssx[i.units].add( i.label )
216
217    ii = [k for k in cc if len(cc[k]) > 1]
218    log.warn( 'var.0001: %48s [%s]: %s' % ('Duplicate variable names',len( self.dq.coll['var'].items ),len(ii)) )
219    showDupVar=False
220    showDupVar=True
221    showDupVarBrief=False
222    if showDupVar:
223      for i in ii:
224        log.info(  '----- %s -----' % i )
225        for x in cc[i]:
226          log.info( '%s, %s, %s, %s' % ( x.label,x.title,x.sn,x.prov ))
227    elif showDupVarBrief:
228      lg.info( str( ii ))
229    self.cc = cc
230
231    if not python2:
232      log.warn( 'Skipping the units check .. not available in python3' )
233    else:
234      checkUnits( ss, extra=ssx )
235      pass
236   
237  def audit_str(self):
238    nms = 0
239    ss = set()
240    cc = collections.defaultdict( list )
241    for i in self.dq.coll['structure'].items:
242      cc[ (i.spid, i.tmid,i.odims,i.coords,i.cmid) ].append( i )
243      if i.cmid != '__unset__' and self.dq.inx.uid[i.cmid]._h.label == 'remarks' and i.cell_methods != '':
244        ss.add(i.cmid)
245        nms += 1
246    if nms > 0:
247      log.error( 'str.00010: missing cell methods records for %s records (%s)' % (nms, len(ss) ) )
248      log.error( 'str.00011: %s' % str( sorted(list(ss)) ) )
249    else:
250      log.info( 'str.00010: all structure methods have valid cmid' )
251
252    ks = [k for k in cc if len(cc[k]) > 1]
253    log.info( 'str.00020: count of repeated space/time structure: %s' % len(ks) )
254    if len(ks) > 0:
255      oo = open( 'structureRepeats.csv', 'w' )
256      for k in ks:
257        oo.write( '\t'.join( [mapCoreAt(x) for x in ['NEXT', k[0], k[1], k[2], k[3], self.dq.inx.uid[k[0]].label, self.dq.inx.uid[k[1]].label]] ) + '\n' )
258        for i in cc[k]:
259          oo.write( '\t'.join( [mapCoreAt(x) for x in ['+',i.uid, i.label, i.title, i.odims, i.coords, i.cell_methods, i.cell_measures, i.flag_meanings, i.spid ] ] ) + '\n' )
260      oo.close()
261
262  def saveRevisedNewVar(self,ll):
263    oo = open( 'revised_newvars.csv', 'w' )
264    for v in sorted( list( ll ) ):
265      oo.write( self.draftNewVar[v] )
266    oo.close()
267
268  def loadDraftNewVar(self):
269    self.draftNewVar = {}
270    for f in ['draft_newvars.csv','draft_newvars02.csv']:
271      ii = open( f, 'r' ).readlines()
272      ss = set()
273      for l in ii:
274        r = l.split( '\t' )
275        vn = r[0].strip()
276        assert vn not in ss, 'Duplicate variable name in %s: %s' % (f,vn)
277        ss.add(vn)
278        if vn in self.draftNewVar:
279          log.info( 'INFO.newvar.0001:  overwriting new var: %s' % vn )
280        self.draftNewVar[vn] = l
281   
282  def audit_cmv(self):
283    zmtabs = ['AERmonZ', 'E6hrZ', 'EdayZ', 'EmonZ']
284    mipt = mipTab.mipt()
285    zmtabsi = [mipt.invmap[x] for x in zmtabs]
286    ccmv = collections.defaultdict( list )
287    ccmv2 = collections.defaultdict( list )
288    ccmv4 = collections.defaultdict( list )
289    ccmv6 = collections.defaultdict( list )
290    ccp = collections.defaultdict( set )
291
292    cmlk = {}
293    zmstr = set()
294    for i in self.dq.coll['structure'].items:
295      cmlk[i.uid] = i.cell_methods
296      if i.cell_methods.find( 'longitude: mean' ) != -1 or i.cell_methods.find( 'global: mean' ):
297        zmstr.add( i.uid )
298    print 'ZMSTR', zmstr
299
300
301##
302## check that vars in AERmonZ, E6hrZ, EdayZ, EmonZ have cell_methods with longitude mean.
303##
304    nms = 0
305    ss = set()
306    badRealm = set()
307    badRealmNames = set()
308 
309    hasHeight = set( ['tas','uas','vas','huss','hurs','sfcwind','sfcwindMax','tasmax','tasmin','tasmaxCrop','tasminCrop','tasLut','hussLut'] )
310    chh = collections.defaultdict( set )
311
312    badzm = set()
313    badzmt = set()
314    spidmap = {'XY-AH':'XY-A/AH','XY-A':'XY-A/AH'}
315    for i in self.dq.coll['CMORvar'].items:
316      if i.mipTable in zmtabsi and (i.stid not in zmstr):
317        badzm.add( i.uid )
318        badzmt.add( i.mipTable )
319        log.error( 'cmv.00121: bad zonal mean variable: %s.%s, %s, %s, %s, %s' % (i.mipTable, i.label,i.uid, i.prov, i.stid, cmlk[i.stid]) )
320
321      ccp[ i.label ].add( i.positive )
322      ccmv[i.label].append(i)
323      ccmv4[ (i.frequency,i.label,i.stid)].append(i)
324      ccmv2[ (i.mipTable,i.label)].append(i)
325      if i.stid not in self.dq.inx.uid or self.dq.inx.uid[i.stid]._h.label == 'remarks':
326        ss.add( i.stid )
327        nms += 1
328      else:
329        st = self.dq.inx.uid[i.stid]
330        sp = self.dq.inx.uid[st.spid]
331        ccmv6[ (i.frequency,i.label,spidmap.get(sp.label,sp.label),st.tmid)].append((i,st))
332        if i.label in hasHeight:
333           if st.coords.find( 'height' ) == -1:
334             chh[ i.label ].add( i.uid )
335
336      for rr in i.modeling_realm.split():
337        if rr not in realms:
338          badRealm.add( (i.mipTable, i.label ) )
339          badRealmNames.add( (i.modeling_realm,rr) )
340    kkp = [k for k in ccp if len(ccp[k]) > 1]
341    if len(kkp) > 0:
342       log.error( 'cmv.00170: bad positive attributes: %s, %s' % (len( kkp ),str(kkp)) )
343    else:
344       log.info( 'cmv.00170: positive attributes OK' )
345
346    if len( chh ) > 0:
347       log.error( 'cmv.04170: near surface field without height coord: %s' % (len(chh) ) )
348       for k in sorted( list( chh.keys() ) ):
349         log.error( 'cmv.04171: without height coord: %s: %s' % (k,len(chh[k]) ) )
350    else:
351       log.info( 'cmv.04170: near surface fields OK (wrt height coord)' )
352         
353    if len( badzm ) > 0:
354       log.error( 'cmv.00120: bad zonal mean variables: %s, %s' % (len( badzm ),str(badzmt)) )
355    if len( badRealm ) > 0:
356      log.error( 'cmv.00030: bad modeling realms set in %s cmv records' % len( badRealm ) )
357      log.error( 'cmv.00031: bad modeling realms: %s' % str( sorted( list( badRealmNames) ) ) )
358      cc1 = collections.defaultdict( list )
359      for tab, lab in badRealm:
360        cc1[tab].append(lab)
361      for tab in sorted( cc1.keys() ):
362        log.error( 'cmv.00032: table %s: %s' % (tab,str(sorted(cc1[tab]))) )
363    else:
364      log.info( 'cmv.00030: modeling realms set ok cmv records' )
365
366    if nms > 0:
367      log.error( 'cmv.00010: missing variable structures for %s CMORvar records, bad stids: %s' % (nms,len(ss)) )
368      log.error( 'cmv.00011: bad stids: %s' % str( sorted( list( ss ) ) ) )
369    else:
370      log.info( 'cmv.00010: variable structures for all CMORvar records present' )
371
372    ii0 = [i for i in self.dq.coll['CMORvar'].items if i.mipTable == '']
373    if len(ii0) > 0:
374      log.error( 'cmv.00020: %48s [%s]: %s' % ('Empty MIP table in CMORvar',len(self.dq.coll['CMORvar'].items),len(ii0)) )
375    else:
376      log.info( 'cmv.00020: all CMORvar records have mip table defined' )
377
378    ii = [i for i in self.dq.coll['CMORvar'].items if self.dq.inx.uid[i.vid]._h.label == 'remarks']
379    if len(ii) == 0:
380      log.info( 'cmv.00200: all CMORvar records have valid vid' )
381    else:
382      ii1 = [i for i in ii if 'requestVar' in self.dq.inx.iref_by_sect[i.uid].a]
383      log.error( 'cmv.00200: %48s [%s]: %s (requested: %s)' % ('CMORvar records with bad vid',len(self.dq.coll['CMORvar'].items),len(ii),len(ii1)) )
384
385      iix2 = []
386      iix3 = []
387      for i in ii1:
388        ok = False
389        ok3 = False
390        for u in self.dq.inx.iref_by_sect[i.uid].a['requestVar']:
391          vg = self.dq.inx.uid[ self.dq.inx.uid[u].vgid ]
392          if vg._h.label != 'remarks':
393           ok = True
394           iix2.append(i)
395           if 'requestLink' in self.dq.inx.iref_by_sect[vg.uid].a:
396             iix3.append(i)
397      log.error( 'cmv.0021: of these: valid requestVarGroup: %s; valid requestLink(s): %s' %  (len(iix2),len(iix3)) )
398      rnv = set()
399      for i in iix3:
400        if i.label in self.draftNewVar:
401          log.error( 'cmv.0125: %s, %s, %s' % (i.uid,i.label,i.title) )
402          rnv.add( i.label )
403        else:
404          log.error( 'cmv.0122: %s, %s, %s' % (i.uid,i.label,i.title) )
405
406      if len( rnv ) > 0:
407        self.saveRevisedNewVar( rnv )
408       
409         
410    ii2 = [k for k in ccmv2 if len(ccmv2[k]) > 1]
411    if len(ii2) == 0:
412      log.info( 'cmv.0030: unique CMOR variable names OK' )
413    else:
414      log.error( 'cmv.0030: non-unique CMOR variable naming for %s records' % len(ii2) )
415      log.error( 'cmv.0031: %s' % str(ii2) )
416
417    ii4 = [k for k in ccmv4 if len(ccmv4[k]) > 1]
418    ii6 = [k for k in ccmv6 if len(ccmv6[k]) > 1]
419    ii4b = list()
420    ii6b = list()
421    for k in ii4:
422      if len(ccmv4[k]) == 2 and set( [i.mipTable[-3:] for i in ccmv4[k]] ) == set(['Ant','Gre']):
423        pass
424      else:
425        ii4b.append(k)
426
427    for k in ii6:
428      if len(ccmv6[k]) == 2 and set( [i.mipTable[-3:] for i,s in ccmv6[k]] ) == set(['Ant','Gre']):
429        pass
430      else:
431        ii6b.append(k)
432
433    if len(ii4b) == 0:
434      log.info( 'cmv.0040: unique CMOR variable usage [4] OK' )
435    else:
436      log.error( 'cmv.0040: non-unique CMOR variable usage possible for %s records' % len(ii4b) )
437      log.error( 'cmv.0041: %s' % str(ii4b) )
438      kk=0
439      oo = open( 'cmv_probDuplication.csv', 'w' )
440      for k in ii4b:
441        kk += 1
442        rec = ('NEXT\t%s\t' % kk ) + str( '\t'.join( k ) )
443        print 'INFO.cmvdup.00001: ',rec
444        oo.write( rec + '\n' )
445        vid = None
446        for i in ccmv4[k]:
447          assert vid == None or i.vid == vid, 'Unexpected vid variation ...: %s%s %s' % (i.label, i.vid, vid)
448          vid = i.vid
449          rec = '+\t%s\t%s\t%s\t%s\t%s' % (i.uid,i.mipTable,i.title,i.description,i.prov)
450          oo.write( rec + '\n' )
451          print 'INFO.cmvdup.00001: ',rec
452      oo.close()
453
454    if len(ii6b) == 0:
455      log.info( 'cmv.0060: unique CMOR variable usage [6] OK' )
456    else:
457      log.info( 'cmv.0060: unique CMOR variable issues [6] %s ' % len(ii6b) )
458      kk=0
459      ccx = collections.defaultdict( set )
460      for k in ii6b:
461        ss = set()
462        freq,label,spid,tmid = k
463        for i,st in ccmv6[k]:
464          ss.add( (st.uid,st.label,st.title) )
465        tt = tuple( sorted( list( ss ) ) )
466        ccx[tt].add( (freq,label) )
467      log.info( 'cmv.0061: unique CMOR variable issues [6.1] %s ' % len(ccx.keys()) )
468      for tt in ccx:
469        ll = [t[2] for t in tt]
470        log.info( 'cmv.0062: unique CMOR variable issues [6.2] %s: %s ' % ('; '.join(ll),str(ccx[tt]) ) )
471       
472      oo = open( 'cmv_probDuplication6.csv', 'w' )
473      for k in ii6b:
474        kk += 1
475        rec = ('NEXT\t%s\t' % kk ) + str( '\t'.join( k ) )
476        oo.write( rec + '\n' )
477        vid = None
478        for i,st in ccmv6[k]:
479          assert vid == None or i.vid == vid, 'Unexpected vid variation ...: %s%s %s' % (i.label, i.vid, vid)
480          vid = i.vid
481          rec = '+\t%s\t%s\t%s\t%s\t%s\t%s' % (i.uid,i.mipTable,i.title,st.title,i.description,i.prov)
482          oo.write( rec + '\n' )
483      oo.close()
484
485    ccmv3 = collections.defaultdict( list )
486    for t in ccmv2:
487      s = set()
488      for i in ccmv2[t]:
489        id = i.uid
490        if 'varRelLnk' in self.dq.inx.iref_by_sect[id].a:
491          for x in self.dq.inx.iref_by_sect[id].a['varRelLnk']:
492            s.add( x )
493      s = list(s)
494      if len(s) > 0:
495        ccmv3[t] = s
496
497    ii5 = [k for k in ii2 if k not in ccmv3 or len(ccmv2[k]) > len(ccmv3[k])]
498    cc4 = collections.defaultdict( list )
499    for t,v in ii2:
500      cc4[t].append( v )
501
502    ncmx = 0
503    for uid, cmorvar in self.dq.inx.CMORvar.uid.iteritems():
504        if cmorvar.modeling_realm in ['ocnBgChem', 'ocean']:
505            # Cell measures are attached to the structure that the cmorvar links to
506            cm = self.dq.inx.uid[cmorvar.stid].cell_measures
507            # check for areacello and ignore some edge cases
508            if 'areacello' not in cm and cm not in  ['', '--OPT', '--UGRID']:
509                print '{0.mipTable}/{0.label} : {1}'.format(cmorvar, cm)
510                log.error( 'cmv.01001: cell_measures error in ocean/ocnBgChem realms {0.mipTable}/{0.label} : {1}'.format(cmorvar, cm) )
511                ncmx += 1
512    if ncmx == 0:
513                log.info( 'cmv.01001: cell_measures checks passed' )
514
515     
516
517    log.warn( '%48s [%s]: %s [%s tables]' % ('Duplicate variables in CMORvar',len(self.dq.coll['CMORvar'].items),len(ii2), len( cc4.keys() ) ) )
518    showAllCmvErrors=False
519    showAllCmvErrors=True
520    if showAllCmvErrors:
521       rats = ['uid','label','title','description','frequency','mipTable','stid','prov','provNote']
522       oocm = open( 'cmvDup.csv', 'w' )
523       c1 = collections.defaultdict( list )
524       ##for i in ii2:
525         ##c1[i.prov].append( i.label )
526       ##log.warn( 'No MIP var: %s ... %s' % (str( sorted( [i.label for i in ii if i.label in self.cc] ) ), str(c1)))
527       for k in sorted( cc4.keys() ):
528         log.warn(  '%16s::  %s' % (k,str(sorted(cc4[k]))) )
529         for v in sorted(cc4[k]):
530             sv = set()
531             for i in ccmv2[ (k,v) ]:
532                sv.add(i.vid)
533
534             if len(list(sv)) == 1:
535               vun = True
536               vv = self.dq.inx.uid[ list(sv)[0] ]
537               oocm.write( '@VAR:\t\t\t%s\t%s\t%s\n' % (vv.label,vv.title,vv.description) )
538             else:
539               vun = False
540
541             for i in ccmv2[ (k,v) ]:
542                stt = self.dq.inx.uid[i.stid].title
543                if 'Temporal mean' in stt:
544                   if i.frequency == '3hr':
545                     i.title += ' [3 hour mean]'
546                xtra = ''
547                oocm.write( '\t\t' + '\t'.join( [str(i.__dict__[x]) for x in rats] ) + '\t%s%s\n' % (stt,xtra) )
548                if not vun:
549                  vv = self.dq.inx.uid[i.vid]
550                  xtra = '\t\t\t\t%s\t%s\t%s\n' % (vv.label,vv.title,vv.description)
551                  oocm.write(xtra)
552             oocm.write( '####\n' )
553       oocm.close()
554    t2_ii = ii[:]
555    self.ccmv = ccmv
556
557  def audit_sn(self):
558    sned = set()
559    for l in open( 'cfed_may2018b.txt' ).readlines():
560      sned.add( l.strip() )
561     
562    cc = collections.defaultdict( list )
563    cc2 = collections.defaultdict( int )
564    cc3 = collections.defaultdict( dict )
565    nrem = 0
566    snm = set()
567    snmm = collections.defaultdict( int )
568    for i in self.dq.coll['var'].items:
569      if 'CMORvar' in self.dq.inx.iref_by_sect[i.uid].a:
570        srq = set()
571        for u in self.dq.inx.iref_by_sect[i.uid].a['CMORvar']:
572          if 'requestVar' in self.dq.inx.iref_by_sect[u].a:
573            for uu in self.dq.inx.iref_by_sect[u].a['requestVar']:
574              rqv = self.dq.inx.uid[uu]
575              srq.add( rqv.priority )
576        if len(srq) > 0:
577          pm = min( srq )
578           
579          kk = i.sn
580          if kk not in self.dq.inx.uid:
581            print 'SEVERE: missing uid: %s' % kk
582          elif self.dq.inx.uid[kk]._h.label == 'remarks':
583            nrem += 1
584            snm.add(kk)
585           ## if pm == 1:
586            print 'MISSING STANDARD NAME: ',i.label, i.title, i.sn, i.provmip
587            snmm[pm] += 1
588            ppp = set()
589            for cmv in self.dq.inx.iref_by_sect[i.uid].a['CMORvar']:
590              for rqv in self.dq.inx.iref_by_sect[cmv].a['requestVar']:
591                ppp.add( self.dq.inx.uid[rqv].priority )
592           
593            cc2[i.provmip] += 1
594            cc3[i.provmip][i.label]=(i.title,i.sn,str(min(ppp)))
595          if i.procnote != []:
596            ll = sorted( i.procnote )
597            kk += ':' + '|'.join(ll )
598          cc[kk].append( i.uid )
599
600    log.warn( 'sn.001: Number of missing standard names: %s [for %s variables] {%s}' % (len(snm),nrem,str(snmm)) )
601    log.warn( 'sn.002: Number of missing standard names by MIP: %s ' % (str(cc2)) )
602    ll = []
603    for k in cc:
604      if len( cc[k] ) > 1:
605        ll.append( k )
606    oo = open( 'audit_sn_errors.csv', 'w' )
607    for k in sorted(cc3.keys()):
608      for v in sorted( cc3[k].keys() ):
609        t,s,p = cc3[k][v]
610        if s in sned:
611          m = 'Editor'
612        else:
613          m = ''
614        oo.write( '\t'.join( [k,v,t,s,p,m] ) + '\n' )
615    oo.close()
616
617    log.warn( 'sn.003: Duplicate use of standard names: %s' % len(ll) )
618    oo = open( 'audit_sn_repeats.csv', 'w' )
619    for k in sorted( ll ):
620      orc = [k,]
621      l1 = cc[k][:]
622      l2 = []
623      l1b = []
624      for u in cc[k]:
625        i = self.dq.inx.uid[u]
626        if i.prov == "CMIP6 endorsement [SIMIP]":
627          l2.append(u)
628        else:
629          l1b.append(u)
630      if len( l2) > 1:
631        log.error( 'WARN.simip.00001: repeat use of standard name in SIMIP: %s:: %s' % (k,str(l2)) )
632      if len(l2) == 1:
633        orc.append( '*' )
634      else:
635        orc.append( '' )
636
637      nnn = 0
638      for u in l2 +l1b:
639        i = self.dq.inx.uid[u]
640        if "CMORvar" not in self.dq.inx.iref_by_sect[u].a:
641           orc += [i.label +'**', i.title]
642        else:
643          nn = 0
644          for uu in self.dq.inx.iref_by_sect[u].a['CMORvar']:
645            cmv = self.dq.inx.uid[uu]
646            if 'requestVar' in self.dq.inx.iref_by_sect[uu].a:
647              nn += 1
648          if nn == 0:
649             orc += [i.label + '*', i.title]
650          else:
651             nnn += 1
652             orc += [i.label, i.title]
653         
654      if nnn > 1:
655        oo.write( '\t'.join( orc ) + '\n' )
656    oo.close()
657     
658  def audit_rqv(self):
659    cc = collections.defaultdict( list )
660    ccc = collections.defaultdict( set )
661    ccx = collections.defaultdict( set )
662    for i in self.dq.coll['requestVar'].items:
663      cc[ (i.vid,i.vgid) ].append( i )
664      ccc[ i.vgid ].add( (i.vid,i.priority) )
665    for k in ccc:
666      ccx[ tuple( sorted( list( ccc[k] ) ) ) ].add( k )
667    kk = [ k for k in ccx.keys() if len( ccx[k] ) > 1 ]
668
669    if len(kk) > 0:
670      oo = open( 'purgeRqvGroup.csv', 'w' )
671      for t in kk:
672        s1 = [k for k in ccx[t] if 'requestLink' not in self.dq.inx.iref_by_sect[k].a or len(self.dq.inx.iref_by_sect[k].a['requestLink'] ) == 0]
673        if len(s1) == len(ccx[t]):
674            if len(s1) == 0:
675              oo.write( '++++++++ pick [0]\n' )
676            else:
677              oo.write( '++++++++ pick\n' )
678        elif len(s1) == len(ccx[t])-1:
679            oo.write( '******** all\n' )
680        elif len(s1) > 0:
681            oo.write( '-------- all**\n' )
682        for k in s1:
683            i = self.dq.inx.uid[k]
684            oo.write( '\t'.join( [i.__dict__[x] for x in ['mip','label','title','uid','ref','refNote'] ] ) + '\n' )
685        if len( ccx[t] )-1 > len( s1 ):
686          oo.write( 'xxxxxxxx review\n' )
687          nn = 0
688          for k in ccx[t]:
689            if k not in s1:
690              i = self.dq.inx.uid[k]
691              nn += 1
692              oo.write( '\t'.join( [i.__dict__[x] for x in ['mip','label','title','uid','ref','refNote'] ] ) + '\n' )
693          if nn == 0:
694            oo.write( '!!!!!!!!!!!\n' )
695            oo.write( '\t'.join( s1 ) +'\n' )
696            oo.write( '\t'.join( ccx[t] ) +'\n' )
697        log.error( 'ERROR.rqv-group.00001: %s' % str(ccx[t]) )
698      oo.close()
699    else:
700       log.error( 'INFO.rqv-group.00001: no request group duplication' )
701
702   
703    tt = [t for t in cc.keys() if len( cc[t] ) > 1]
704    if len(tt) > 0:
705      cc2 = collections.defaultdict( list )
706      for t in tt:
707        s1 = set( [i.label for i in cc[t]] )
708        p1 = set( [i.priority for i in cc[t]] )
709        if len(s1) > 1:
710           log.error( 'ERROR.rqv-dup.9002: %s, %s' % (str(t),str(s1)) )
711        elif len(p1) > 1:
712           log.error( 'ERROR.rqv-dup.9003: %s, %s' % (str(t),str(p1)) )
713        else:
714          label = s1.pop()
715          s1 =  [i.mip for i in cc[t]] 
716          s2 = [m for m in s1 if m != 'CMIP5']
717          if len(s2) == 0:
718             cc2[label].append( (t,['CMIP5','CMIP5'] ) )
719          elif len(s2) == 1:
720             cc2[label].append( (t,[s2[0],'CMIP5'] ) )
721          else:
722             cc2[label].append( (t,sorted(s2) ) )
723      oo = open( 'rqvPrune.csv', 'w' )
724      for k in sorted( cc2.keys() ):
725         for a,b in cc2[k]:
726           log.error( 'ERROR.rqv-dup.0001: %s, %s' % (str(a),str(b)) )
727           try:
728             oo.write( '%s\t%s\t%s\t%s\t%s\n' % (k,a[0],a[1],b[0],b[1]) )
729           except:
730             print 'SEVERE: FAILED TO WRITE: ',k,a,b
731      oo.close()
732
733    ixx = [i for i in self.dq.coll['requestVar'].items if i.vid in self.dq.inx.uid]
734    if len(ixx) < len( self.dq.inx.uid ):
735       log.error( 'SEVERE.var.00301: request vars with bad links ....' )
736   
737    ii = [i for i in ixx if self.dq.inx.uid[i.vid]._h.label == 'remarks']
738    ii2 = [i for i in ii if i.label not in self.cc]
739    ii3 = [i.vgid for i in ii if self.dq.inx.uid[i.vgid]._h.label != 'remarks']
740##ii4: set of invalid requestVarGroup records
741    ii4 = [i for i in ii3 if 'requestLink' not in self.dq.inx.iref_by_sect[i].]
742######
743    ii5Info = 'Set of bad requestVar records linking to a valid requestVarGroup records.'
744    ii5 = [i for i in ii if i.vgid not in ii4]
745##ii6: set of bad requestVar records linking to a valid requestVarGroup records and no variable name match.
746    ii6 = [i for i in ii5 if i.label not in self.cc]
747    log.error( '%48s [%s]: %s [%s, %s, %s; %s]' % ('Bad variable links in requestVar',len(self.dq.coll['requestVar'].items),len(ii),len(ii2), len(ii5), len(ii6), len(ii4)) )
748    for iix,m in [(ii2,2),(ii5,5),(ii6,6),(ii4,4)]:
749      thisl = min( [len(iix),6] )
750      if thisl > 0:
751        print '>>>>>>>>>>> %s' % m
752        for i in iix[:thisl]:
753          if type(i) == type( 'x' ):
754            print i
755          else:
756            print i.label, i.uid
757    log.info ( str( ii5Info ))
758    svg = set()
759    for i in ii5:
760      log.info( 'ii5: %s' % str([i.label, i.title, i.uid, i.mip, self.dq.inx.uid[i.vgid].title] ) )
761      svg.add( i.vgid )
762    for i in ii2:
763      if i.vgid in self.dq.inx.uid and self.dq.inx.uid[i.vgid]._h.label != 'remarks':
764        xx = '%s [%s]' % (self.dq.inx.uid[i.vgid].title, i.vgid)
765      else:
766        xx = i.vgid
767      log.info( 'ii2: %s' % str([i.label, i.title, i.uid, i.mip, xx] ) )
768
769    log.warn( 'rvg.0010: requestVarGroups with bad request vars:' )
770    for u in sorted( list(svg) ):
771      log.warn( 'rvg.0011: %s: %s' % (u, self.dq.inx.uid[u].title ))
772
773    log.info( '    [# records]: # broken [var name not known, link to valid group, valid group and no var name; valid request groups' )
774    showAllRqvErrors=False
775    if showAllRqvErrors:
776      log.info( '%s\n%s' % (str( [i.label for i in ii if i.label in self.cc]), str( [i.label for i in ii2] ) ) )
777
778    ii1 = [i for i in ii if i.label in self.ccmv]
779    listBadRequestVar=False
780    if listBadRequestVar:
781      for i in ii1:
782        log.info( str( i.label,i.mip,i.table,[x.frequency for x in self.ccmv[i.label]] ) )
783
784  def audit_rql(self):
785    ii = [i for i in self.dq.coll['requestLink'].items if self.dq.inx.uid[i.refid]._h.label == 'remarks']
786    log.info( '%48s: %s (from %s)' % ('ERROR.rql.001: Bad request group links in requestLink',len(ii), len(self.dq.coll['requestLink'].items)) )
787    rql_detail=True
788    if rql_detail:
789      for i in ii:
790         log.info( '%s: %s, %s [%s]' % ('ERROR.rql.002: ',i.mip,i.label,i.uid) )
791
792  def audit_rqg(self):
793    ii = [i for i in self.dq.coll['requestVarGroup'].items if len( dq.inx.iref_by_sect[i.uid].a['requestVar'])  == 0]
794    ii1 = [i for i in ii if len( dq.inx.iref_by_sect[i.uid].a['requestLink'])  != 0]
795    log.info( '%48s: %s/%s (from %s)' % ('Request groups with no request links:',len(ii) - len(ii1),len(ii1), len(self.dq.coll['requestVarGroup'].items)) )
796    listEmptyRequestVarGroups=True
797    if listEmptyRequestVarGroups:
798      for i in ii1:
799        log.info ( 'INFO.rqgempty.0001: %s: %s, %s [%s]' % (i.label, i.title, i.mip, i.uid) )
800
801    ## check subhourly.
802    i = '33b0f666-a27a-11e6-bfbb-ac72891c3257'
803    cc = collections.defaultdict( dict )
804    for x in dq.inx.iref_by_sect[i].a['requestVar']:
805       cmv = dq.inx.uid[ dq.inx.uid[x].vid ]
806       st = dq.inx.uid[ cmv.stid ]
807       sp = dq.inx.uid[ st.spid ]
808       cc[sp.label][cmv.label] = cmv.uid
809    ne = 0
810    for k in sorted( cc.keys() ):
811      if k.find( 'XY' ) != -1:
812        log.error( 'ERROR.rvg.00002: bad shape in subhourly data: %s, %s' % (k,sorted( cc[k].keys() ) ) )
813        ne += 1
814    if ne == 0:
815      log.info( 'INFO.rvg.00002: sub hourly variable shapes OK' )
816
817##dq = dreq.loadDreq(manifest=None)
818dq = dreq.loadDreq(manifest='dreqManifest.txt')
819a = auditor( dq )
820cd = checkDims( dq )
Note: See TracBrowser for help on using the repository browser.