source: CMIP6dreqbuild/trunk/src/framework/ingest/util_anal.py @ 903

Subversion URL: http://proj.badc.rl.ac.uk/svn/exarch/CMIP6dreqbuild/trunk/src/framework/ingest/util_anal.py@903
Revision 903, 30.7 KB checked in by mjuckes, 3 years ago (diff)

misc updates

Line 
1
2from xceptions import baseException
3import shelve, glob, os, uuid, collections, string
4from utils_wb import workbook, uniCleanFunc
5import util_varGroups
6import util_gen
7import loadcf
8
9varBlackList = ['tasAdjust','tsAdjust','pslAdjust','prAdjust']
10
11tab2freq = {u'CMIP5_cfOff':'subhr', u'CORDEX_mon':'mon', u'SPECS_day':'day', u'CMIP5_day':'day', \
12                  u'PMIP3_OImon':'mon', u'CORDEX_day':'day', u'CMIP5_LImon':'mon', u'CMIP5_OImon':'mon', \
13                  u'CMIP5_Lmon':'mon', u'CMIP5_3hr':'3hr', u'CMIP5_Omon':'mon', u'PMIP3_OIclim':'monClim', \
14                  u'PMIP3_fx':'fx', u'CORDEX_fx':'fx', u'PMIP3_LImon':'mon', u'CMIP5_6hrPlev':'6hr', u'PMIP3_Lmon':'mon', \
15                  u'PMIP3_Amon':'mon', u'SPECS_Omon':'mon', u'CCMI1_fixed':'fx', u'PMIP3_Aclim':'monClim', u'CMIP5_6hrLev':'6hr', \
16                  u'CMIP5_Oclim':'monClim', u'PMIP3_LIclim':'monClim', u'CCMI1_monthly':'mon', u'CMIP5_fx':'fx', \
17                  u'CMIP5_cfDay':'day', u'CORDEX_6h':'6hr', u'PMIP3_day':'day', u'SPECS_OImon':'mon', u'CMIP5_cfMon':'mon', \
18                  u'CORDEX_sem':'monClim', u'SPECS_6hr':'6hr', u'CMIP5_cfSites':'subhr', u'CCMI1_hourly':'hr', u'CMIP5_aero':'mon', \
19                  u'CMIP5_Amon':'mon', u'PMIP3_Omon':'mon', u'CCMI1_daily':'day', u'SPECS_fx':'fx', u'PMIP3_Lclim':'monClim', \
20                  u'DCPP-day':'day',  \
21                  u'PMIP3_Oclim':'monClim', u'SPECS_Amon':'mon', u'SPECS_Lmon':'mon', u'CMIP5_cf3hr':'3hr', u'CORDEX_3h':'3hr', \
22                  'OImon':'mon', 'Omon_oth':'mon', 'Omon':'mon',  'Oyr':'yr', 'Omon_3d':'mon', \
23                  u'CCMI1_annual':'yr', u'CMIP5_Oyr':'yr', \
24                   'Oclim':'monClim', \
25                   'cfMon':'mon', \
26                  u'cf3hr':'3hr', u'Amon':'mon', u'aero':'mon', u'aero_3d':'mon', u'6hrPlev':'6hr', u'aero_oth':'mon', \
27                  u'cf3hr_grid':'3hr', u'LImon':'mon', u'cfSites':'subhr', u'day_oth':'day', u'cfDay_2d':'day', u'day':'day' }
28
29knownMips = ['CMIP', 'AerChemMIP', 'C4MIP', 'CFMIP', 'DAMIP', 'DCPP', 'FAFMIP', 'GeoMIP', 'GMMIP', 'HighResMIP', 'ISMIP6', 'LS3MIP', 'LUMIP', 'OMIP', 'PMIP', 'RFMIP', 'ScenarioMIP', 'VolMIP', 'CORDEX', 'DynVar', 'SIMIP', 'VIACSAB']
30
31##
32## want to match up with input/vars_... and  where is cmv uid fixed ????
33##
34##
35## need to migrate new vars into input/vars_ ... especially from LUMIP ...
36##
37## new variables which need to be added have been identified. No check for modifications (and no clear workflow here)...
38## ned to check .. a few appear spurious .. and then generate csv records ... for manual copy ...
39##
40##
41##
42## add AerChemMip and VIACS to stuff scanned and checked below .....
43
44def getSubGroup(s, var,dims,ttl,ix):
45        sg = None
46        if s == 'Oyr' and ix < 60:
47          sg = 'Oyr_3dtr'
48        elif s == 'Amon':
49          if string.find( dims, 'lev' ) == -1 and string.find( dims, 'longitude latitude') != -1:
50            sg = 'Amon_2d'
51          else:
52            sg  = 'Amon_oth'
53        elif s == 'Omon':
54          if string.find( dims, 'longitude latitude olevel' ) != -1:
55            sg = 'Omon_3d'
56          else:
57            sg = 'Omon_oth'
58        elif s == 'cfMon':
59          if ttl[:5] in ['ISCCP','PARAS','CALIP']:
60            sg = 'cfMon_sim'
61          elif var[-3:] == 'co2':
62            if string.find( dims, 'longitude latitude alev' ) != -1:
63              sg = 'cfMon_3dmod'
64            else:
65              sg = 'cfMon_2dmod'
66          else:
67            sg = 'cfMon_3dstd'
68        elif s == 'cfDay':
69          bits = '|'.split( dims )
70
71          if string.find( dims, 'longitude|latitude' ) != -1 and len(bits) > 2 and bits[2] in ['alev','alevel','alevhalf','alt40','plev7','alt40','plev7c']:
72              sg = 'cfDay_3d'
73          else:
74              sg = 'cfDay_2d'
75        elif s == 'cf3hr':
76          if  dims.find( 'longitude|latitude' ) != -1:
77              sg = 'cf3hr_grid'
78          else:
79              sg = 'cf3hr_sim'
80        elif s == 'aero':
81          if dims.find( 'longitude|latitude|alevel' ) != -1:
82              sg = 'aero_3d'
83          else:
84              sg = 'aero_oth'
85        elif s == 'day':
86          if ix < 28:
87              sg = 'day_ss'
88          else:
89              sg = 'day_oth'
90        return sg
91def getSubGroupO(sn, var,dims,ttl,ix):
92                 sg = None
93                 if sn == 'Oyr' and ix < 65:
94                   sg = 'Oyr_3dtr'
95                 elif sn == 'Omon':
96                   if string.find( dims, 'longitude latitude olevel' ) != -1:
97                     sg = 'Omon_3d'
98                   else:
99                     sg = 'Omon_oth'
100                 elif sn == 'cfMon':
101                   if ttl[:5] in ['ISCCP','PARAS','CALIP']:
102                     sg = 'cfMon_sim'
103                   elif var[-3:] == 'co2':
104                     if string.find( dims, 'longitude latitude alev' ) != -1:
105                       sg = 'cfMon_3dmod'
106                     else:
107                       sg = 'cfMon_2dmod'
108                   else:
109                     sg = 'cfMon_3dstd'
110                 elif sn == 'cfDay':
111                   bits = ' '.split( dims )
112                   if string.find( dims, 'longitude latitude' ) != -1 and len(bits) > 2 and bits[2] in ['alev','alevel','alevhalf','alt40','plev7','alt40']:
113                       sg = 'cfDay_3d'
114                   else:
115                       sg = 'cfDay_2d'
116                 elif sn == 'cf3hr':
117                   if dims.find( 'longitude latitude' ) != -1:
118                       sg = 'cf3hr_grid'
119                   else:
120                       sg = 'cf3hr_sim'
121                 return sg
122
123class ref(object):
124  def __init__(self,sdir='inSh'):
125    dir1 = '/data/tmp/svn3/exarch/CMIP6dreqbuild/trunk/src/workbook'
126    wb = workbook( '%s/%s' % (dir1,'inputs/vars_20160721.xls') )
127    self.vars = {}
128    s1 = wb.book.sheet_by_name(u'var')
129    su = set()
130    cf = loadcf.cf()
131    for i in range( s1.nrows ):
132      r = s1.row(i)
133      assert r[0] not in self.vars, 'DUPLICATE VARIABLE: %s' % str(r)
134      self.vars[r[0].value] = (r[9].value,r[10].value,r[7].value)
135    fl = sorted( glob.glob( '%s/sh__newVar_*' % sdir ) )
136    kml = []
137    for f in fl:
138      mip = f.split( '_' )[-1]
139      sh = shelve.open( f, 'r' )
140      ks = [k for k in sh.keys() if k[0] != '_']
141      for k in ks:
142        if k not in self.vars:
143          kml.append((mip,sh[k]))
144          print 'MISSING NEW: %s, %s, %s' % (k,f,str(sh[k]))
145        else:
146          sn0 = sh[k][1]
147          sn = self.vars[k][2]
148          if sn0 != sn:
149            a0 = sn0 in cf.names or sn0 in cf.alias
150            a = sn in cf.names or sn in cf.alias
151            if a and a0:
152              if sn in cf.names and sn0 in cf.names:
153                print 'WARN.standard_name.00001: template standard names different from ref: [%s] %s: %s -- %s' % (mip, k, sn0, sn)
154              elif sn in cf.alias and sn0 in cf.names:
155                print 'WARN.standard_name.00002: replace sn alias with new ....: [%s] %s: %s -- %s' % (mip, k, sn0, sn)
156              elif sn in cf.names and sn0 in cf.alias:
157                print 'WARN.standard_name.00003: attempt to replace sn new with alias ....: [%s] %s: %s -- %s' % (mip, k, sn0, sn)
158              elif sn in cf.alas and sn0 in cf.alias:
159                print 'WARN.standard_name.00004: two aliasses ...... : [%s] %s: %s -- %s' % (mip, k, sn0, sn)
160              else:
161                assert False, 'Should not be able to reach this code'
162            elif not a0:
163              print 'INFO.standard_name.000005: ignoring incorrect standard name in template: [%s] %s: %s -- %s' % (mip, k, sn0, sn)
164            elif not a:
165              print 'WARN.standard_name.00006: standard name needs updating: [%s] %s: %s -- %s' % (mip, k, sn0, sn)
166             
167
168    ixmip = 6
169    ixprov = 5
170    ixuid = 9
171    if len( kml) > 0:
172      oo = open( 'draft_newvars.csv', 'w' )
173      targ2src = ['Short name', 'Long Name', 'description/comments', None, None, None, None, 'CF standard_name', 'units', None, 'Priority']
174      srcHead = ['Short name', 'CF standard_name', 'standard name status', 'Native grid', 'units', 'Long Name', 'description/comments', 'Priority', 'associated observational dataset']
175      ixTarg2src = []
176      for i in range( len( targ2src ) ):
177        if targ2src[i] == None:
178           ixTarg2src.append( None )
179        else:
180           ixTarg2src.append( srcHead.index( targ2src[i] ) )
181##[u'fClAntLut ', '', u'new', u'atmos', u'kg C m-2 s-1', u'carbon from land clearing for land use tile that enters anthropogenic pools', u'If  a model has explicit anthropogenic pools, clearance should not include fire', 1.0, '']
182      for mip,irec in kml:
183        orec = []
184        for i in range( len( targ2src ) ):
185          if ixTarg2src[i] != None:
186            orec.append( uniCleanFunc(irec[ixTarg2src[i]], tostring=True) )
187          else:
188            orec.append( '' )
189        orec[ixmip] = mip
190        orec[ixprov] = 'CMIP6 [%s]' % mip
191        orec[ixuid] = str( uuid.uuid1() )
192        oo.write( '\t'.join( orec ) + '\n' )
193      oo.close()
194
195class cmvRef(object):
196  def __init__(self):
197    self.byUid = {}
198    self.byTab = collections.defaultdict( dict )
199    for l in open( 'ingest/cmvRef_01.beta.32.csv' ).readlines():
200      lab, tab, ttl, uid = l.strip().split( '\t' )
201      assert uid not in self.byUid, 'DUPLICATE UID: %s' % uid
202      self.byUid[uid] = (lab,tab,ttl)
203      if lab in self.byTab[tab]:
204        print 'ERROR.cmvRef.001: duplicate variable name in cmv table: %s,%s' % (tab,lab)
205      self.byTab[tab][lab] = uid
206
207class revTabChk(object):
208
209  def __init__(self,sdir='inSh'):
210    """Review and consolidate revised tables, as ingested into shelves, and annotate records"""
211    assert os.path.isdir( sdir ), 'Input directory not found: %s' % inSH
212    self.ref = refTabChk()
213    fl = sorted( glob.glob( '%s/sh__so_*' % sdir ) )
214    tref = util_varGroups.varGroupSs()
215    vref = util_varGroups.ref()
216    tref.loadGroups()
217    tprobs = set()
218    self.sh = shelve.open( '%s/sh__consol01_revTabs' % sdir, 'n' )
219    self.sh['__cols__'] = ['var', 'table', 'mip', 'vid', 'priority','vgid']
220    self.sh['__info__'] = {'label':'revTable', 'title':'Revised variable table records generated by ingest.util_anal.revTabChk'}
221    cc = collections.defaultdict( int )
222    vgmaps = {'Oyr':'OMIP-Oyr','OImon':'SIMIP-seaicemon'}
223    kkk = 0
224    for f in fl:
225#
226#  CMIP5 and OMIP tables go in as reference tables, and so should not be duplicated here.
227#
228      ss = set()
229      sso = set()
230      if f.find( 'CMIP5' ) == -1 and  f.find( 'OMIP' ) == -1:
231        sh = shelve.open( f, 'r' )
232        for k in sh.keys():
233          if k[0] != '_':
234            assert k not in self.sh, 'Duplicate key in revised table items: %s' % k
235
236            vgl = sh[k][1].replace( '_', '-' )
237            try:
238              vn = sh[k][0]
239            except:
240              print sh['__cols__']
241              print k
242              print sh[k]
243              raise
244            if vn not in vref.vars:
245              print 'WARN.cmv.99999: var name not found: %s:: %s' % (vn,str(sh[k]))
246            ss.add(vgl)
247            if vgl in ['cf3hr-grid', 'cfMon-3dmod', 'cfMon-2dmod']:
248              if vgl not in sso:
249                print 'Warning: skipping ',sh[k]
250                sso.add( vgl )
251              vgid = '__unset__01__'
252            else:
253              vgl1 = vgmaps.get( vgl, vgl )
254              if vgl1 not in tref.uidByLabel:
255                if 'CMIP5-%s' % vgl1 in tref.uidByLabel:
256                   vgl1 = 'CMIP5-%s' % vgl1
257
258              if vgl1 not in tref.uidByLabel:
259                print 'SEVERE.requestvar.00001: group not found: %s: %s, %s' % (vgl,f,str(sh[k]))
260                vgid = '__vgid_not_found__'
261              else:
262                vgid = tref.uidByLabel[vgl1]
263                cc[vgl1] += 1
264            vid = sh[k][3]
265            if sh[k][2] not in knownMips:
266               print 'SEVERE.requestvar.00002 unknown MIP: %s:: %s' % (f, str( sh[k] ) )
267            self.sh[k]  = sh[k][:] + [vgid,]
268            print 'INFO.revisedcmv.00001; ',self.sh[k], k
269            if vid in self.ref.cmv:
270              sg = self.ref.cmv[vid][-1]
271              if sg not in [ '',None]:
272                sgs = sg.split('_')[-1]
273                vgl2 = '%s-%s' % (vgl1,sgs)
274                if vgl2 in tref.uidByLabel:
275                  vg2 = tref.uidByLabel[vgl2]
276                  rr = sh[k][:] + [vg2,]
277                  rr[1] = rr[1] + '_' + sgs
278                  k2 = str( uuid.uuid1() )
279                  if rr[2] not in knownMips:
280                    print 'SEVERE.requestvar.00003 unknown MIP: %s:: %s' % (f, str( rr ) )
281                  self.sh[k2] = rr
282                else:
283                  print 'INFO.sg.00050: not found; ',vgl2, sg, sh[k]
284              else:
285                  print 'INFO.sg.00060: no subgroup; ',vgl, sg, sh[k]
286            else:
287                  print 'INFO.sg.00070: no cmv; ',sh[k],f
288            kkk += 1
289        sh.close()
290        print f, ss
291    self.sh.close()
292    for k in sorted( tref.uidByLabel.keys() ):
293      print k, cc[k]
294    for k in cc:
295      if k not in tref.uidByLabel:
296         print 'ERROR: ',k, cc[k]
297    print 'TOTAL VARS REQUESTED HERE: ',kkk
298
299class refTabChk(object):
300
301  def __init__(self,sdir='inSh'):
302    """Review reference tables, as ingested into shelves, and annotate records"""
303    assert os.path.isdir( sdir ), 'Input directory not found: %s' % inSH
304    fl = sorted( glob.glob( '%s/sh__refso_*' % sdir ) )
305    tprobs = set()
306    self.sh = shelve.open( '%s/sh__consol01_refTabs' % sdir, 'n' )
307    self.cmv = dict()
308    self.cmvtv = dict()
309    self.tabInfo = util_gen.tableInfo()
310    self.sh['__cols__'] = self.tabInfo.oh
311    self.sh['__info__'] = {'label':'refTable', 'title':'Reference variable table records generated by ingest.util_anal.refTabChk'}
312    itab = self.tabInfo.oh.index( 'mipTable' )
313    icmv = self.tabInfo.oh.index( 'var' )
314    iix = self.tabInfo.oh.index( 'rowIndex' )
315    iv = self.tabInfo.oh.index( 'out_name' )
316    ivid = self.tabInfo.oh.index( 'vid' )
317    idim = self.tabInfo.oh.index( 'dimensions' )
318    iln = self.tabInfo.oh.index( 'title' )
319    iss = self.tabInfo.oh.index( 'ssect' )
320    isn = self.tabInfo.oh.index( 'sn' )
321    igpid = self.tabInfo.oh.index( 'gpid' )
322    vref = util_varGroups.ref()
323    tref = util_varGroups.varGroupSs()
324    tref.loadGroups()
325    vmsgs = set()
326    dnrix = []
327    for x in ['var','title','comment',None,None,None,None,'sn','units',None,'priority']:
328      if x == None:
329        dnrix.append( None )
330      else:
331        dnrix.append( self.tabInfo.oh.index(x) )
332     
333    cf = loadcf.cf()
334    gtm = set()
335    sss = set()
336    oonv = None
337    vml = []
338    for f in fl:
339      self.actions = collections.defaultdict(int)
340      self.file = f
341      mip = f.split( '_' )[-1]
342      sh = shelve.open( f, 'r' )
343      ks = [k for k in sh if k[0] != '_']
344      for k in ks:
345       rr = sh[k][:]
346       uid = rr[0]
347       var = rr[iv]
348       if var.find( '_' ) != -1:
349         print 'ERROR.var.00001: underscore in variable: %s' % str(rr)
350         var = var.replace( '_', '' )
351         rr[iv] = var
352       if var not in varBlackList:
353        try:
354         tab = rr[itab]
355         tab = tref.mapGroupName(tab,'')
356         if var not in vref.vars:
357           if var not in vmsgs:
358              print 'SEVERE.vars.00010: var not found: %s [%s]' % (var,tab)
359              vmsgs.add( var )
360              if oonv == None:
361                oonv = open( 'draft_newvars02.csv', 'w' )
362              ov = []
363              for ix in dnrix:
364                if ix == None:
365                  ov.append( '' )
366                else:
367                  ov.append( str( rr[ix] ) )
368              ov[9] = uid
369              ov[6] = mip
370              ov[5] = 'CMIP6 Endorsement [%s]' % mip
371              oonv.write( '\t'.join( ov ) + '\n' )
372           vid = '-'
373         else:
374           sn0 = rr[isn]
375           sn = vref.vars[var][2]
376           if sn != sn0:
377            a0 = sn0 in cf.names or sn0 in cf.alias
378            a = sn in cf.names or sn in cf.alias
379            if a and a0:
380              if sn in cf.names and sn0 in cf.names:
381                print 'WARN.standard_name.10001: template standard names different from ref: [%s] %s: %s -- %s' % (mip, var, sn0, sn)
382                vml.append( (mip,var,'1',sn,sn0) )
383              elif sn in cf.alias and sn0 in cf.names:
384                print 'WARN.standard_name.10002: replace sn alias with new ....: [%s] %s: %s -- %s' % (mip, var, sn0, sn)
385                vml.append( (mip,var,'2',sn,sn0) )
386              elif sn in cf.names and sn0 in cf.alias:
387                print 'WARN.standard_name.10003: attempt to replace sn new with alias ....: [%s] %s: %s -- %s' % (mip, var, sn0, sn)
388              elif sn in cf.alas and sn0 in cf.alias:
389                print 'WARN.standard_name.10004: two aliasses ...... : [%s] %s: %s -- %s' % (mip, var, sn0, sn)
390              else:
391                assert False, 'Should not be able to reach this code'
392            elif not a0:
393              print 'INFO.standard_name.100005: ignoring incorrect standard name in template: [%s] %s: %s -- %s' % (mip, var, sn0, sn)
394            elif not a:
395              print 'WARN.standard_name.10006: standard name needs updating: [%s] %s: %s -- %s' % (mip, var, sn0, sn)
396              vml.append( (mip,var,'6',sn,sn0) )
397           
398           vid = vref.vars[var][0]
399
400         if tab not in tref.groupset:
401           print 'SEVERE.tables.00001: tab not found: %s' % tab
402           gpid = '-'
403         else:
404           gpid = tref.groupset[tab][0]
405           gtm.add( (tab,tref.groupset[tab]) )
406        except:
407         print k, sh[k]
408         print itab,iv
409         raise
410        if tab not in tab2freq:
411         tprobs.add(tab)
412        rr[igpid] = gpid
413        rr[ivid] = vid
414        rr[-1] = int( float(rr[-1]) )
415        sg = ''
416       ## check to see if this table has sections, and identify which section this variable is in if appropriate
417        print 'INFO.sg.01001: ',tab,tab in self.tabInfo.tabChildren
418        if rr[iss] != '':
419          sg = rr[iss]
420          sg1 = sg.replace( '_', '-' )
421          if sg1 in ['cf3hr-grid','Amon-oth']:
422             sgid = '_na_'
423          else:
424            assert sg1 in tref.groupset, 'Subgroup not found in groupset: %s,%s' % (tab,sg1)
425            sgid = tref.groupset[sg1][0]
426          rr[iss] = (sg,sgid)
427          print 'INFO.sg.00003: ',sg,sgid
428        elif tab in self.tabInfo.tabChildren:
429         if tab in ['Omon','Oyr']:
430           sg = getSubGroupO(tab, var,rr[idim],rr[iln],rr[iix])
431         else:
432           sg = getSubGroup(tab, var,rr[idim],rr[iln],rr[iix])
433         print 'INFO.sg.00001: ',tab,var,rr[idim],rr[iix], sg
434         if sg != None:
435           sg1 = sg.replace( '_', '-' )
436           if sg1 in ['Amon-oth']:
437             sgid = '_na_'
438           else:
439             assert sg1 in tref.groupset, 'Subgroup not found in groupset: %s, %s' % (tab,sg)
440             sgid = tref.groupset[sg1][0]
441           rr[iss] = (sg,sgid)
442           if (sg,sgid) not in sss:
443             sss.add( (sg,sgid) )
444             print 'INFO.sg.00002: ',sg,sgid
445         else:
446           assert rr[iss] == '', 'Corrupted subgroup element: %s,%s,%s' % (iss,rr[iss],str(rr))
447         
448        self.cmv[uid] = (tab, var, rr[idim], rr[iix], rr[iln],sg)
449        self.cmvtv[(tab,var)] = uid
450        if var == 'intppcalc':
451          print rr
452        if var in {'*','include Oyr 3D tracers'}:
453          print 'ERROR.copy.00890: ',f,rr
454        if k != uid:
455          print 'SEVERE.uid.00020: uid/k mismatch: ',k,rr
456
457        if var == 'msftmyz':
458           print 'INFO.msftmyz.00001: ',vid, rr
459        self.sh[k] = rr[:]
460    if oonv != None:
461      oonv.close()
462    print gtm
463    self.sh['__source__'] = fl
464    self.sh.close()
465    print 'UNMAPPED tabs (to freq): ',tprobs
466
467    if len( vml ) > 0:
468      oo = open( 'varStandardNameUpdates.csv', 'w' )
469      for vm in vml:
470        oo.write( '\t'.join( vm ) + '\n' )
471      oo.close()
472
473class dynGrps(object):
474  def __init__(self,rftc):
475    sdir = 'inSh'
476    sh = shelve.open( '%s/sh__requestScoping' % sdir )
477    sh0 = shelve.open( '%s/sh__requestScoping_0' % sdir, 'r' )
478    for k in sh0:
479      mip, rec = sh0[k]
480      print mip,rec
481
482class varGroupChk(object):
483  cmip5Tables = [u'3hr', u'6hrLev', u'6hrPlev', u'Amon', u'LImon', u'Lmon', u'OImon', u'Oclim', u'Omon', u'Oyr', u'aero', u'cf3hr', u'cfDay', u'cfMon', u'cfOff', u'cfSites', u'day', u'fx']
484  def __init__(self,sdir='inSh'):
485    """Review var groups, as ingested into shelves, and annotate records"""
486    assert os.path.isdir( sdir ), 'Input directory not found: %s' % inSH
487    self.ref = ref()
488    self.shl = {}
489    self.group2uid = {}
490    self.vgss = util_varGroups.varGroupSs()
491    self.vgss.loadGroups()
492    self.vgss.setUid()
493    self.vgss.checkMaps()
494    self.varsetoo = None
495    self.grps = set()
496    self.tbls = set()
497    self.frqs = set()
498    self.nnew = 0
499    self.nc5 = 0
500    self.noth = 0
501    self.ots = set()
502    isFirst = True
503    #self.sh = shelve.open( '%s/sh__consol01_grp' % sdir, 'n' )
504    self.sh = shelve.open( '%s/sh__consol01_groupItems' % sdir, 'n' )
505    self.shdvg = shelve.open( '%s/sh__consol01_dynVarGroup_requestVars' % sdir, 'n' )
506
507    self.shdvg['__info__'] = {'label':'dynVarGroup_requestVars', 'title':'Request variable records for dynamically generated variable groups (through variable names listed in request scoping). Generated by ingest.util_anal.varGroupChk'}
508    self.shdvg['__cols__'] = ['vid', 'title', 'label', 'priority', 'vgid', 'mip']
509
510    self.sh['__info__'] = {'label':'GroupItemsBeta', 'title':'Group Item records generated by ingest.util_anal.varGroupChk'}
511    self.sh['__cols__'] = ['group', 'var', 'table', 'freq', 'descriptionEx', 'shape', 'levels', 'tstyle', 'mask', 'misc', 'mip', 'uid', 'oldv', 'rowIndex', 'var2', 'new', 'gpid', 'vkey', 'vid']
512    self.mg = dict()
513    self.checkRequestedGroups()
514
515    fl = sorted( glob.glob( '%s/sh__grp_*' % sdir ) )
516    for f in fl:
517      self.scanFile(f,isFirst)
518      isFirst = False
519
520    self.sh.close()
521    self.shdvg.close()
522    if self.varsetoo != None:
523      self.varsetoo.close()
524
525    sh = shelve.open( '%s/sh__requestScoping_1' % sdir,'n' )
526    for k in self.group2uid:
527       mip, uid, new = self.group2uid[k]
528       sh['%s__1' % str(k)] = (mip, uid )
529    sh.close()
530
531    for kkk in sorted(self.mg.keys()):
532      print 'WARNING: possible problem identifying group: ',self.mg[kkk]
533    print 'groups: ',self.grps
534    print 'tables: ',self.tbls
535    print 'frequencies: ',self.frqs
536    print 'nrefs to new: %s, cmip5: %s, other: %s' % (self.nnew, self.nc5, self.noth)
537    print 'other tables: ',self.ots
538    for k in self.shl:
539      self.shl[k].close()
540
541  def scanFile(self,f,isFirst):
542      self.actions = collections.defaultdict(int)
543      self.file = f
544      self.shl[f] = shelve.open( f, 'r' )
545      self.mip = self.shl[f]['__info__']['label']
546      if isFirst:
547        print self.shl[f]['__cols__']
548      ks = [k for k in self.shl[f].keys() if k[0] != '_']
549
550      for k in ks:
551        r = self.shl[f][k]
552        self.grps.add(r[0])
553        self.tbls.add(r[2])
554        self.frqs.add(r[3])
555        var = r[1].strip()
556        if var != r[1]:
557          print 'WARNING.blanks.0001: *%s* and *%s (%s,%s)' % (var,r[1],r[0],f)
558        extra = {}
559        trc = 0
560        if r[2] == 'new' or r[2][:2] == 'em':
561          extra['mode'] = 'new'
562          self.nnew +=1
563          trc = 1
564          if var not in self.ref.vars:
565            if var.find('_') != -1:
566              v2 = var.replace('_','')
567              if v2 in self.ref.vars:
568                print 'WARN: %s should be replaced with %s' % (var,v2)
569            print 'ERROR.missing.0001: variable not found: ',var,r[0],f
570            trc = 10
571          else:
572            if r[9] == '':
573              p1 = -1
574            else:
575              p1 = int( r[9] )
576            trc = 11
577            p2 = int( self.ref.vars[var][1] )
578            if p1 not in [1,2,3]:
579              if p2 in [1,2,3]:
580                extra['priority'] = p2
581              else:
582                print 'ERROR.priority.0001: %s (%s::%s), ref: %s, templ: %s' % (var,r[0],f,p2,p1)
583
584        elif r[2] in self.cmip5Tables or r[2][:5] == 'CMIP5' and r[2][6:] in self.cmip5Tables:
585          trc = 11
586          extra['mode'] = 'CMIP5'
587          self.nc5 += 1
588          if var not in self.ref.vars:
589            print 'ERROR.missing.0003: variable not found: ',var,r[0],f
590        else:
591          extra['mode'] = 'OTHER MIP'
592          self.noth += 1
593          self.ots.add( r[2] )
594          if var not in self.ref.vars:
595            print 'ERROR.missing.0002: variable not found: ',var,r[0],f
596##
597## but this is the MIP variable id ...... need the CMOR variable ID ?? ...
598##
599        vid = self.ref.vars.get(var,[None,])[0]
600         
601        if var == 'sidmassgrowthbot':
602           print 'INFO.sidmass...',r, extra
603        self.consol(k,r,vid,extra)
604      for k in sorted( self.actions.keys() ):
605           print 'ACTIONS: %s: %s -- %s' % (f,k,self.actions[k])
606
607
608  def varsets(self, thisuid, i1, refuid, i2, title ):
609    if self.varsetoo == None:
610      self.varsetoo = open('varsets.txt','w' )
611    self.varsetoo.write( '\t'.join(  [thisuid, str(i1), refuid, str(i2), title] ) + '\n' )
612 
613  def consol(self,rk,rr,vid,extra):
614##['Short name of group', 'Variable short name', 'Table', 'Frequency', 'Description extension (optional)', 'Shape', 'Levels', 'Time mean, point or climatology', 'Mask (optional)', 'Priority', 'MIP','uid','rowIndex', 'Prev. Var Name']
615##
616## following is provided by sx2.py:
617##['group', 'var', 'table', 'freq', 'descriptionEx', 'shape', 'levels', 'tstyle', 'mask', 'misc', 'mip', 'uid', 'rowIndex', 'new', 'gpid', 'vkey', 'vid']
618## need to add vid (info found above), vgid, "new" flag, (also above), and "vkey".
619
620    rset = []
621    r = list(rr)
622    if 'priority' in extra:
623       r[9] = extra['priority']
624    elif r[9] == '':
625       r[9] = -1
626    else:
627       r[9] = int( r[9] )
628
629    if not self.vgss.matchGroup(r[0],self.mip):
630        print 'ERROR.group.00006: group not found: %s [%s]' % (r[0],self.mip)
631        self.mg[r[0]] = (self.mip,r)
632        gpid = '__noGroupFound__'
633        new = 0
634    else:
635        print 'INFO.group.00007: group found: %s (%s):: %s, %s' % (r[0],self.mip,self.vgss.groupName, self.vgss.groupMatch )
636        if r[0] in self.group2uid:
637          assert self.vgss.groupMatchRes == self.group2uid[r[0]], 'Mismatch in group lookup ..%s [%s,%s]' % (r[0], str(self.vgss.groupMatchRes), str(self.group2uid[r[0]]) )
638        else:
639          self.group2uid[r[0]] = self.vgss.groupMatchRes
640        gpid = str(self.vgss.groupMatchRes[1] )
641        isnew = self.vgss.groupMatchRes[2] == 'new'
642        if isnew:
643          new = 1
644        else:
645          new = -1
646
647    il = 6
648    idx = 4
649    ixp = 9
650    iu = 11
651    assert r[iu] == rk, 'CONFUSED ABOUT UIDs? %s, %s' % (rk,r[iu])
652    var2 = r[1]
653    if r[il] in  {u'17 (or 23 )', u'17 (or 23)', u'17 (or23)', u'10/17/23'}:
654       self.actions['Create 17/23 level pair'] += 1
655       if r[il] == u'10/17/23':
656                lev0 = 10
657                levsp = [19,23]
658       else:
659                lev0 = 19
660                levsp = [23,]
661       r[ixp] = 1
662       r[il] = lev0
663       var2 = var2 + str( lev0 )
664       p = 1
665       for lp in levsp:
666                 p += 1
667                 rr0 = r + [r[1] + str(lp),]
668                 rr0[ixp] = p
669                 rr0[il] = lp
670                 rr0[iu] = str( uuid.uuid1() )
671                 rr = rr0 + [new, gpid, 0, vid]
672                 if r[1] == 'hus':
673                    print 'INFO.hus.00202: ',rr
674                 rset.append( rr )
675                 self.varsets(rr0[iu], 2, rr[iu], 1, 'variables at multiple vertical resolutions' )
676
677    elif r[il] in [u'Model levels or plev_27', u'Model levels or 27Plevs',u'27',27.]:
678               self.actions['27 level variant of variable name created' ] += 1
679               var2 += '27'
680               r[il] = 27
681    elif r[idx].find( '850 hPa' ) != -1:
682               if r[1][-3:] != '850':
683                  self.actions['850mb variant of variable generated'] += 1
684                  var2 += '850'
685    elif type( r[il] ) == type(1.) and r[il] == 7. and r[10] == 'HighResMIPxxxxx' and r[5] != 'XYZKT':
686                  ### no idea why this code is here ... added xxxx above t mae sure it is not executed.
687                  print 'INFO.7h.0001: ',r
688                  self.actions['Shape modified to XYZKT*'] += 1
689                  r[5] = r[5] + '*'
690                  r[il] = '7h'
691    r += [var2,new, gpid, 0, vid]
692    rset.append( r )
693    if r[10] != 'OMIP':
694      for ri in rset:
695        self.consol_sub01( ri, extra )
696    else:
697      self.actions['OMIP records skipped'] += 1
698
699  def consol_sub01( self, r, extra ):
700    """Write our a requestItem record, which is split into a CMORvar and requestVar in isd3b.py"""
701    iu = 11
702    assert r[iu] not  in self.sh
703    assert len(r) == len( self.sh['__cols__'] ), 'Bad record length .. %s'  % str(r)
704    print 'INFO.requestitem.00001: ',r
705    self.sh[r[iu]] = r[:]
706
707  def checkRequestedGroups(self,sdir='inSh'):
708    sh = shelve.open( '%s/sh__requestScoping' % sdir, 'r' )
709    sh0 = shelve.open( '%s/sh__requestScoping_0' % sdir, 'n' )
710    cc = collections.defaultdict( int )
711    ff = set()
712    for mip in sorted( sh['__records__'].keys() ):
713      reqg = sh['__records__'][mip]
714      reqgd = dict()
715      self.mip = mip
716      for rec in reqg:
717        g = rec[0]
718        if g[:5] == 'CMIP5':
719         g = g[6:]
720        g0 = g
721        t = self.vgss.recChk(rec,mip)
722        dyngrp = t[0]
723        if dyngrp:
724          mtab, g = t[2]
725        if not self.vgss.matchGroup(g,self.mip) and not dyngrp:
726          print 'FAILED to match request group: ',self.mip,rec
727          ff.add( (self.mip,g) )
728        else:
729          print 'INFO.group.00008: group found: %s (%s):: %s, %s' % (g,self.mip,self.vgss.groupName, self.vgss.groupMatch )
730          assert self.vgss.groupMatchRes != None,  'Should have results from matchGroup here!!'
731          reqgd[g] = self.vgss.groupMatchRes
732          uid = str(self.vgss.groupMatchRes[1] )
733          rec[0] = self.vgss.groupName
734          kkk = '%s__%2.2i__%s' % (uid,cc[uid],0)
735          cc[uid] += 1
736          assert kkk not in sh0, 'Duplicate key for request link record: %s' % kkk
737          sh0[kkk] = [self.mip, rec ]
738          print 'INFO.vgrp.00001: ',kkk,self.mip,rec
739          if dyngrp:
740            self.saveDynGrp(g,mtab,uid)
741##
742## need to generate request variables for dynamic groups here (those detected via vgss )
743## would be nice to stage things ... create variable database and then add requests ....
744## "all at once" risks mis-alignments ...
745##
746## need to fill in details on dynamic groups after completion of scan of new groups.   
747##
748##
749    sh.close()
750    sh0.close()
751    if len(ff) > 0:
752      oo = open( 'varGroupSuggestions.csv', 'w' )
753      for t in sorted( list( ff ) ):
754        oo.write( '%s\t%s' % t )
755        oo.write( '\t%s\n' % str( uuid.uuid1() ) )
756      oo.close()
757
758  def saveDynGrp(self,glab,tab,rgid):
759    this = self.vgss.s2[glab]
760    print 'INFO.dyngrp.00001: ',rgid,this, glab
761    for k in this:
762      if k[0] != '_':
763        if this[k] == None:
764          print 'ERROR.dyngrp.00002: variable not found: ',rgid,k, glab
765        else:
766          vid, priority = this[k]
767          rec = [vid, '%s: %s' % (glab,k), k, priority, rgid, self.mip] 
768          uid = str(uuid.uuid1() )
769          self.shdvg[uid] = rec
770
Note: See TracBrowser for help on using the repository browser.