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

Subversion URL: http://proj.badc.rl.ac.uk/svn/exarch/CMIP6dreqbuild/trunk/src/framework/audit.py@1291
Revision 1291, 34.6 KB checked in by mjuckes, 11 months ago (diff)

01.00.29 candidate

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