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

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

release cand

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