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

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

candidate

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_oth'
88          else:
89              sg = 'day_ss'
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    oo = open( 'sn_changes.csv', 'w' )
138    for f in fl:
139      mip = f.split( '_' )[-1]
140      sh = shelve.open( f, 'r' )
141      ks = [k for k in sh.keys() if k[0] != '_']
142      for k in ks:
143        if k not in self.vars:
144          kml.append((mip,sh[k]))
145          print 'MISSING NEW: %s, %s, %s' % (k,f,str(sh[k]))
146        else:
147         try:
148          print f,k,sh[k]
149          sn0 = sh[k][1]
150          sn = self.vars[k][2]
151          units = str(sh[k][4])
152          title = sh[k][5]
153          desc = sh[k][6]
154          if sn0 != sn:
155            a0 = sn0 in cf.names or sn0 in cf.alias
156            a = sn in cf.names or sn in cf.alias
157            if a and a0:
158              if sn in cf.names and sn0 in cf.names:
159                print 'WARN.standard_name.00001: template standard names different from ref: [%s] %s: %s -- %s' % (mip, k, sn0, sn)
160                oo.write( '\t'.join( ['','1',mip,k,units,'',sn0,cf.names[sn0][1],sn,cf.names[sn][1],title,desc] ) + '\n' )
161              elif sn in cf.alias and sn0 in cf.names:
162                print 'WARN.standard_name.00002: replace sn alias with new ....: [%s] %s: %s -- %s' % (mip, k, sn0, sn)
163                oo.write( '\t'.join( ['','2',mip,k,units,'',sn0,cf.names[sn0][1],sn,'',title,desc] ) + '\n' )
164              elif sn in cf.names and sn0 in cf.alias:
165                print 'WARN.standard_name.00003: attempt to replace sn new with alias ....: [%s] %s: %s -- %s' % (mip, k, sn0, sn)
166                oo.write( '\t'.join( ['','3',mip,k,units,'',sn0,cf.names[cf.alias[sn0]][1],sn,cf.names[sn][1],title,desc] ) + '\n' )
167              elif sn in cf.alias and sn0 in cf.alias:
168                print 'WARN.standard_name.00004: two aliasses ...... : [%s] %s: %s -- %s' % (mip, k, sn0, sn)
169                oo.write( '\t'.join( ['','4',mip,k,units,'',sn0,cf.names[cf.alias[sn0]][1],sn,'',title,desc] ) + '\n' )
170              else:
171                assert False, 'Should not be able to reach this code'
172            elif not a0:
173              print 'INFO.standard_name.000005: ignoring incorrect standard name in template: [%s] %s: %s -- %s' % (mip, k, sn0, sn)
174            elif not a:
175              print 'WARN.standard_name.00006: standard name needs updating: [%s] %s: %s -- %s' % (mip, k, sn0, sn)
176              if sn0 in cf.names:
177                oo.write( '\t'.join( ['','6',mip,k,units,'',sn0,cf.names[sn0][1],sn,'',title,desc] ) + '\n' )
178              else:
179                oo.write( '\t'.join( ['','7',mip,k,units,'',sn0,cf.names[cf.alias[sn0]][1],sn,'',title,desc] ) + '\n' )
180         except:
181          print f,k,sh[k]
182          raise
183    oo.close()
184             
185
186    ixmip = 6
187    ixprov = 5
188    ixuid = 9
189    if len( kml) > 0:
190      oo = open( 'draft_newvars.csv', 'w' )
191      targ2src = ['Short name', 'Long Name', 'description/comments', None, None, None, None, 'CF standard_name', 'units', None, 'Priority']
192      srcHead = ['Short name', 'CF standard_name', 'standard name status', 'Native grid', 'units', 'Long Name', 'description/comments', 'Priority', 'associated observational dataset']
193      ixTarg2src = []
194      for i in range( len( targ2src ) ):
195        if targ2src[i] == None:
196           ixTarg2src.append( None )
197        else:
198           ixTarg2src.append( srcHead.index( targ2src[i] ) )
199##[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, '']
200      for mip,irec in kml:
201        orec = []
202        for i in range( len( targ2src ) ):
203          if ixTarg2src[i] != None:
204            orec.append( uniCleanFunc(irec[ixTarg2src[i]], tostring=True) )
205          else:
206            orec.append( '' )
207        orec[ixmip] = mip
208        orec[ixprov] = 'CMIP6 [%s]' % mip
209        orec[ixuid] = str( uuid.uuid1() )
210        oo.write( '\t'.join( orec ) + '\n' )
211      oo.close()
212
213class cmvRef(object):
214  def __init__(self):
215    self.byUid = {}
216    self.byTab = collections.defaultdict( dict )
217    for l in open( 'ingest/cmvRef_01.beta.32.csv' ).readlines():
218      lab, tab, ttl, uid = l.strip().split( '\t' )
219      assert uid not in self.byUid, 'DUPLICATE UID: %s' % uid
220      self.byUid[uid] = (lab,tab,ttl)
221      if lab in self.byTab[tab]:
222        print 'ERROR.cmvRef.001: duplicate variable name in cmv table: %s,%s' % (tab,lab)
223      self.byTab[tab][lab] = uid
224
225class revTabChk(object):
226
227  def __init__(self,sdir='inSh'):
228    """Review and consolidate revised tables, as ingested into shelves, and annotate records"""
229    assert os.path.isdir( sdir ), 'Input directory not found: %s' % inSH
230    self.ref = refTabChk()
231    fl = sorted( glob.glob( '%s/sh__so_*' % sdir ) )
232    tref = util_varGroups.varGroupSs()
233    vref = util_varGroups.ref()
234    tref.loadGroups()
235    tprobs = set()
236    self.sh = shelve.open( '%s/sh__consol01_revTabs' % sdir, 'n' )
237    self.sh['__cols__'] = ['var', 'table', 'mip', 'vid', 'priority','vgid']
238    self.sh['__info__'] = {'label':'revTable', 'title':'Revised variable table records generated by ingest.util_anal.revTabChk'}
239    cc = collections.defaultdict( int )
240    vgmaps = {'Oyr':'OMIP-Oyr','OImon':'SIMIP-seaicemon'}
241    kkk = 0
242    for f in fl:
243#
244#  CMIP5 and OMIP tables go in as reference tables, and so should not be duplicated here.
245#
246      ss = set()
247      sso = set()
248      if f.find( 'CMIP5' ) == -1 and  f.find( 'OMIP' ) == -1:
249        sh = shelve.open( f, 'r' )
250        for k in sh.keys():
251          if k[0] != '_':
252            assert k not in self.sh, 'Duplicate key in revised table items: %s' % k
253
254            vgl = sh[k][1].replace( '_', '-' )
255            try:
256              vn = sh[k][0]
257            except:
258              print sh['__cols__']
259              print k
260              print sh[k]
261              raise
262            if vn not in vref.vars:
263              print 'WARN.cmv.99999: var name not found: %s:: %s' % (vn,str(sh[k]))
264            ss.add(vgl)
265            if vgl in ['cf3hr-grid', 'cfMon-3dmod', 'cfMon-2dmod']:
266              if vgl not in sso:
267                print 'Warning: skipping ',sh[k]
268                sso.add( vgl )
269              vgid = '__unset__01__'
270            else:
271              vgl1 = vgmaps.get( vgl, vgl )
272              if vgl1 not in tref.uidByLabel:
273                if 'CMIP5-%s' % vgl1 in tref.uidByLabel:
274                   vgl1 = 'CMIP5-%s' % vgl1
275
276              if vgl1 not in tref.uidByLabel:
277                print 'SEVERE.requestvar.00001: group not found: %s: %s, %s' % (vgl,f,str(sh[k]))
278                vgid = '__vgid_not_found__'
279              else:
280                vgid = tref.uidByLabel[vgl1]
281                cc[vgl1] += 1
282            vid = sh[k][3]
283            if sh[k][2] not in knownMips:
284               print 'SEVERE.requestvar.00002 unknown MIP: %s:: %s' % (f, str( sh[k] ) )
285            self.sh[k]  = sh[k][:] + [vgid,]
286            print 'INFO.revisedcmv.00001; ',self.sh[k], k
287            if vid in self.ref.cmv:
288              sg = self.ref.cmv[vid][-1]
289              if sg not in [ '',None]:
290                sgs = sg.split('_')[-1]
291                vgl2 = '%s-%s' % (vgl1,sgs)
292                if vgl2 in tref.uidByLabel:
293                  vg2 = tref.uidByLabel[vgl2]
294                  rr = sh[k][:] + [vg2,]
295                  rr[1] = rr[1] + '_' + sgs
296                  k2 = str( uuid.uuid1() )
297                  if rr[2] not in knownMips:
298                    print 'SEVERE.requestvar.00003 unknown MIP: %s:: %s' % (f, str( rr ) )
299                  self.sh[k2] = rr
300                else:
301                  print 'INFO.sg.00050: not found; ',vgl2, sg, sh[k]
302              else:
303                  print 'INFO.sg.00060: no subgroup; ',vgl, sg, sh[k]
304            else:
305                  print 'INFO.sg.00070: no cmv; ',sh[k],f
306            kkk += 1
307        sh.close()
308        print f, ss
309    self.sh.close()
310    for k in sorted( tref.uidByLabel.keys() ):
311      print k, cc[k]
312    for k in cc:
313      if k not in tref.uidByLabel:
314         print 'ERROR: ',k, cc[k]
315    print 'TOTAL VARS REQUESTED HERE: ',kkk
316
317class refTabChk(object):
318
319  def __init__(self,sdir='inSh'):
320    """Review reference tables, as ingested into shelves, and annotate records"""
321    assert os.path.isdir( sdir ), 'Input directory not found: %s' % inSH
322    fl = sorted( glob.glob( '%s/sh__refso_*' % sdir ) )
323    tprobs = set()
324    self.sh = shelve.open( '%s/sh__consol01_refTabs' % sdir, 'n' )
325    self.cmv = dict()
326    self.cmvtv = dict()
327    self.tabInfo = util_gen.tableInfo()
328    self.sh['__cols__'] = self.tabInfo.oh
329    self.sh['__info__'] = {'label':'refTable', 'title':'Reference variable table records generated by ingest.util_anal.refTabChk'}
330    itab = self.tabInfo.oh.index( 'mipTable' )
331    icmv = self.tabInfo.oh.index( 'var' )
332    iix = self.tabInfo.oh.index( 'rowIndex' )
333    iv = self.tabInfo.oh.index( 'out_name' )
334    iu = self.tabInfo.oh.index( 'units' )
335    ivid = self.tabInfo.oh.index( 'vid' )
336    idim = self.tabInfo.oh.index( 'dimensions' )
337    iln = self.tabInfo.oh.index( 'title' )
338    ides = self.tabInfo.oh.index( 'comment' )
339    iss = self.tabInfo.oh.index( 'ssect' )
340    isn = self.tabInfo.oh.index( 'sn' )
341    igpid = self.tabInfo.oh.index( 'gpid' )
342    vref = util_varGroups.ref()
343    tref = util_varGroups.varGroupSs()
344    tref.loadGroups()
345    vmsgs = set()
346    dnrix = []
347    for x in ['var','title','comment',None,None,None,None,'sn','units',None,'priority']:
348      if x == None:
349        dnrix.append( None )
350      else:
351        dnrix.append( self.tabInfo.oh.index(x) )
352     
353    cf = loadcf.cf()
354    gtm = set()
355    sss = set()
356    oonv = None
357    vml = []
358    oo = open( 'sn_changes_ref.csv', 'w' )
359    for f in fl:
360      self.actions = collections.defaultdict(int)
361      self.file = f
362      mip = f.split( '_' )[-1]
363      sh = shelve.open( f, 'r' )
364      ks = [k for k in sh if k[0] != '_']
365      for k in ks:
366       rr = sh[k][:]
367       uid = rr[0]
368       var = rr[iv]
369       units = rr[iu]
370       title = rr[iln]
371       desc = rr[ides]
372       if var.find( '_' ) != -1:
373         print 'ERROR.var.00001: underscore in variable: %s' % str(rr)
374         var = var.replace( '_', '' )
375         rr[iv] = var
376       if var not in varBlackList:
377        try:
378         tab = rr[itab]
379         tab = tref.mapGroupName(tab,'')
380         if var not in vref.vars:
381           if var not in vmsgs:
382              print 'SEVERE.vars.00010: var not found: %s [%s]' % (var,tab)
383              vmsgs.add( var )
384              if oonv == None:
385                oonv = open( 'draft_newvars02.csv', 'w' )
386              ov = []
387              for ix in dnrix:
388                if ix == None:
389                  ov.append( '' )
390                else:
391                  ov.append( str( rr[ix] ) )
392              ov[9] = uid
393              ov[6] = mip
394              ov[5] = 'CMIP6 Endorsement [%s]' % mip
395              oonv.write( '\t'.join( ov ) + '\n' )
396           vid = '-'
397         else:
398           sn0 = rr[isn]
399           sn = vref.vars[var][2]
400           if sn != sn0:
401            a0 = sn0 in cf.names or sn0 in cf.alias
402            a = sn in cf.names or sn in cf.alias
403            if a and a0:
404              if sn in cf.names and sn0 in cf.names:
405                print 'WARN.standard_name.10001: template standard names different from ref: [%s] %s: %s -- %s' % (mip, var, sn0, sn)
406                oo.write( '\t'.join( ['','11',mip,var,units,k,sn0,cf.names[sn0][1],sn,cf.names[sn][1],title,desc] ) + '\n' )
407                vml.append( (mip,var,'1',sn,sn0) )
408              elif sn in cf.alias and sn0 in cf.names:
409                print 'WARN.standard_name.10002: replace sn alias with new ....: [%s] %s: %s -- %s' % (mip, var, sn0, sn)
410                oo.write( '\t'.join( ['','12',mip,var,units,k,sn0,cf.names[sn0][1],sn,'',title,desc] ) + '\n' )
411                vml.append( (mip,var,'2',sn,sn0) )
412              elif sn in cf.names and sn0 in cf.alias:
413                print 'WARN.standard_name.10003: attempt to replace sn new with alias ....: [%s] %s: %s -- %s' % (mip, var, sn0, sn)
414                oo.write( '\t'.join( ['','13',mip,var,units,k,sn0,cf.names[cf.alias[sn0]][1],sn,cf.names[sn][1],title,desc] ) + '\n' )
415              elif sn in cf.alas and sn0 in cf.alias:
416                print 'WARN.standard_name.10004: two aliasses ...... : [%s] %s: %s -- %s' % (mip, var, sn0, sn)
417                oo.write( '\t'.join( ['','14',mip,var,units,k,sn0,cf.names[cf.alias[sn0]][1],sn,'',title,desc] ) + '\n' )
418              else:
419                assert False, 'Should not be able to reach this code'
420            elif not a0:
421              print 'INFO.standard_name.100005: ignoring incorrect standard name in template: [%s] %s: %s -- %s' % (mip, var, sn0, sn)
422            elif not a:
423              print 'WARN.standard_name.10006: standard name needs updating: [%s] %s: %s -- %s' % (mip, var, sn0, sn)
424              if sn0 in cf.names:
425                oo.write( '\t'.join( ['','16',mip,var,units,k,sn0,cf.names[sn0][1],sn,'',title,desc] ) + '\n' )
426              else:
427                oo.write( '\t'.join( ['','17',mip,var,units,k,sn0,cf.names[cf.alias[sn0]][1],sn,'',title,desc] ) + '\n' )
428              vml.append( (mip,var,'6',sn,sn0) )
429           
430           vid = vref.vars[var][0]
431
432         if tab not in tref.groupset:
433           print 'SEVERE.tables.00001: tab not found: %s' % tab
434           gpid = '-'
435         else:
436           gpid = tref.groupset[tab][0]
437           gtm.add( (tab,tref.groupset[tab]) )
438        except:
439         print k, sh[k]
440         print itab,iv
441         raise
442        if tab not in tab2freq:
443         tprobs.add(tab)
444        rr[igpid] = gpid
445        rr[ivid] = vid
446        rr[-1] = int( float(rr[-1]) )
447        sg = ''
448       ## check to see if this table has sections, and identify which section this variable is in if appropriate
449        print 'INFO.sg.01001: ',tab,tab in self.tabInfo.tabChildren
450        if rr[iss] != '':
451          sg = rr[iss]
452          sg1 = sg.replace( '_', '-' )
453          if sg1 in ['cf3hr-grid','Amon-oth']:
454             sgid = '_na_'
455          else:
456            assert sg1 in tref.groupset, 'Subgroup not found in groupset: %s,%s' % (tab,sg1)
457            sgid = tref.groupset[sg1][0]
458          rr[iss] = (sg,sgid)
459          print 'INFO.sg.00003: ',sg,sgid
460        elif tab in self.tabInfo.tabChildren:
461         if tab in ['Omon','Oyr']:
462           sg = getSubGroupO(tab, var,rr[idim],rr[iln],rr[iix])
463         else:
464           sg = getSubGroup(tab, var,rr[idim],rr[iln],rr[iix])
465         print 'INFO.sg.00001: ',tab,var,rr[idim],rr[iix], sg
466         if sg != None:
467           sg1 = sg.replace( '_', '-' )
468           if sg1 in ['Amon-oth']:
469             sgid = '_na_'
470           else:
471             assert sg1 in tref.groupset, 'Subgroup not found in groupset: %s, %s' % (tab,sg)
472             sgid = tref.groupset[sg1][0]
473           rr[iss] = (sg,sgid)
474           if (sg,sgid) not in sss:
475             sss.add( (sg,sgid) )
476             print 'INFO.sg.00002: ',sg,sgid
477         else:
478           assert rr[iss] == '', 'Corrupted subgroup element: %s,%s,%s' % (iss,rr[iss],str(rr))
479         
480        self.cmv[uid] = (tab, var, rr[idim], rr[iix], rr[iln],sg)
481        self.cmvtv[(tab,var)] = uid
482        if var == 'intppcalc':
483          print rr
484        if var in {'*','include Oyr 3D tracers'}:
485          print 'ERROR.copy.00890: ',f,rr
486        if k != uid:
487          print 'SEVERE.uid.00020: uid/k mismatch: ',k,rr
488
489        if var == 'msftmyz':
490           print 'INFO.msftmyz.00001: ',vid, rr
491        self.sh[k] = rr[:]
492
493    oo.close()
494    if oonv != None:
495      oonv.close()
496    print gtm
497    self.sh['__source__'] = fl
498    self.sh.close()
499    print 'UNMAPPED tabs (to freq): ',tprobs
500
501    if len( vml ) > 0:
502      oo = open( 'varStandardNameUpdates.csv', 'w' )
503      for vm in vml:
504        oo.write( '\t'.join( vm ) + '\n' )
505      oo.close()
506
507class dynGrps(object):
508  def __init__(self,rftc):
509    sdir = 'inSh'
510    sh = shelve.open( '%s/sh__requestScoping' % sdir )
511    sh0 = shelve.open( '%s/sh__requestScoping_0' % sdir, 'r' )
512    for k in sh0:
513      mip, rec = sh0[k]
514      print mip,rec
515
516class varGroupChk(object):
517  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']
518  def __init__(self,sdir='inSh'):
519    """Review var groups, as ingested into shelves, and annotate records"""
520    assert os.path.isdir( sdir ), 'Input directory not found: %s' % inSH
521    self.ref = ref()
522    self.shl = {}
523    self.group2uid = {}
524    self.vgss = util_varGroups.varGroupSs()
525    self.vgss.loadGroups()
526    self.vgss.setUid()
527    self.vgss.checkMaps()
528    self.varsetoo = None
529    self.grps = set()
530    self.tbls = set()
531    self.frqs = set()
532    self.nnew = 0
533    self.nc5 = 0
534    self.noth = 0
535    self.ots = set()
536    isFirst = True
537    #self.sh = shelve.open( '%s/sh__consol01_grp' % sdir, 'n' )
538    self.sh = shelve.open( '%s/sh__consol01_groupItems' % sdir, 'n' )
539    self.shdvg = shelve.open( '%s/sh__consol01_dynVarGroup_requestVars' % sdir, 'n' )
540
541    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'}
542    self.shdvg['__cols__'] = ['vid', 'title', 'label', 'priority', 'vgid', 'mip']
543
544    self.sh['__info__'] = {'label':'GroupItemsBeta', 'title':'Group Item records generated by ingest.util_anal.varGroupChk'}
545    self.sh['__cols__'] = ['group', 'var', 'table', 'freq', 'descriptionEx', 'shape', 'levels', 'tstyle', 'mask', 'misc', 'mip', 'uid', 'oldv', 'rowIndex', 'var2', 'new', 'gpid', 'vkey', 'vid']
546    self.mg = dict()
547    self.checkRequestedGroups()
548
549    fl = sorted( glob.glob( '%s/sh__grp_*' % sdir ) )
550    for f in fl:
551      self.scanFile(f,isFirst)
552      isFirst = False
553
554    self.sh.close()
555    self.shdvg.close()
556    if self.varsetoo != None:
557      self.varsetoo.close()
558
559    sh = shelve.open( '%s/sh__requestScoping_1' % sdir,'n' )
560    for k in self.group2uid:
561       mip, uid, new = self.group2uid[k]
562       sh['%s__1' % str(k)] = (mip, uid )
563    sh.close()
564
565    for kkk in sorted(self.mg.keys()):
566      print 'WARNING: possible problem identifying group: ',self.mg[kkk]
567    print 'groups: ',self.grps
568    print 'tables: ',self.tbls
569    print 'frequencies: ',self.frqs
570    print 'nrefs to new: %s, cmip5: %s, other: %s' % (self.nnew, self.nc5, self.noth)
571    print 'other tables: ',self.ots
572    for k in self.shl:
573      self.shl[k].close()
574
575  def scanFile(self,f,isFirst):
576      self.actions = collections.defaultdict(int)
577      self.file = f
578      self.shl[f] = shelve.open( f, 'r' )
579      self.mip = self.shl[f]['__info__']['label']
580      if isFirst:
581        print self.shl[f]['__cols__']
582      ks = [k for k in self.shl[f].keys() if k[0] != '_']
583
584      for k in ks:
585        r = self.shl[f][k]
586        self.grps.add(r[0])
587        self.tbls.add(r[2])
588        self.frqs.add(r[3])
589        var = r[1].strip()
590        if var != r[1]:
591          print 'WARNING.blanks.0001: *%s* and *%s (%s,%s)' % (var,r[1],r[0],f)
592        extra = {}
593        trc = 0
594        if r[2] == 'new' or r[2][:2] == 'em':
595          extra['mode'] = 'new'
596          self.nnew +=1
597          trc = 1
598          if var not in self.ref.vars:
599            if var.find('_') != -1:
600              v2 = var.replace('_','')
601              if v2 in self.ref.vars:
602                print 'WARN: %s should be replaced with %s' % (var,v2)
603            print 'ERROR.missing.0001: variable not found: ',var,r[0],f
604            trc = 10
605          else:
606            if r[9] == '':
607              p1 = -1
608            else:
609              p1 = int( r[9] )
610            trc = 11
611            p2 = int( self.ref.vars[var][1] )
612            if p1 not in [1,2,3]:
613              if p2 in [1,2,3]:
614                extra['priority'] = p2
615              else:
616                print 'ERROR.priority.0001: %s (%s::%s), ref: %s, templ: %s' % (var,r[0],f,p2,p1)
617
618        elif r[2] in self.cmip5Tables or r[2][:5] == 'CMIP5' and r[2][6:] in self.cmip5Tables:
619          trc = 11
620          extra['mode'] = 'CMIP5'
621          self.nc5 += 1
622          if var not in self.ref.vars:
623            print 'ERROR.missing.0003: variable not found: ',var,r[0],f
624        else:
625          extra['mode'] = 'OTHER MIP'
626          self.noth += 1
627          self.ots.add( r[2] )
628          if var not in self.ref.vars:
629            print 'ERROR.missing.0002: variable not found: ',var,r[0],f
630##
631## but this is the MIP variable id ...... need the CMOR variable ID ?? ...
632##
633        vid = self.ref.vars.get(var,[None,])[0]
634         
635        if var == 'sidmassgrowthbot':
636           print 'INFO.sidmass...',r, extra
637        self.consol(k,r,vid,extra)
638      for k in sorted( self.actions.keys() ):
639           print 'ACTIONS: %s: %s -- %s' % (f,k,self.actions[k])
640
641
642  def varsets(self, thisuid, i1, refuid, i2, title ):
643    if self.varsetoo == None:
644      self.varsetoo = open('varsets.txt','w' )
645    self.varsetoo.write( '\t'.join(  [thisuid, str(i1), refuid, str(i2), title] ) + '\n' )
646 
647  def consol(self,rk,rr,vid,extra):
648##['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']
649##
650## following is provided by sx2.py:
651##['group', 'var', 'table', 'freq', 'descriptionEx', 'shape', 'levels', 'tstyle', 'mask', 'misc', 'mip', 'uid', 'rowIndex', 'new', 'gpid', 'vkey', 'vid']
652## need to add vid (info found above), vgid, "new" flag, (also above), and "vkey".
653
654    rset = []
655    r = list(rr)
656    if 'priority' in extra:
657       r[9] = extra['priority']
658    elif r[9] == '':
659       r[9] = -1
660    else:
661       r[9] = int( r[9] )
662
663    if not self.vgss.matchGroup(r[0],self.mip):
664        print 'ERROR.group.00006: group not found: %s [%s]' % (r[0],self.mip)
665        self.mg[r[0]] = (self.mip,r)
666        gpid = '__noGroupFound__'
667        new = 0
668    else:
669        print 'INFO.group.00007: group found: %s (%s):: %s, %s' % (r[0],self.mip,self.vgss.groupName, self.vgss.groupMatch )
670        if r[0] in self.group2uid:
671          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]]) )
672        else:
673          self.group2uid[r[0]] = self.vgss.groupMatchRes
674        gpid = str(self.vgss.groupMatchRes[1] )
675        isnew = self.vgss.groupMatchRes[2] == 'new'
676        if isnew:
677          new = 1
678        else:
679          new = -1
680
681    il = 6
682    idx = 4
683    ixp = 9
684    iu = 11
685    assert r[iu] == rk, 'CONFUSED ABOUT UIDs? %s, %s' % (rk,r[iu])
686    var2 = r[1]
687    if r[il] in  {u'17 (or 23 )', u'17 (or 23)', u'17 (or23)', u'10/17/23'}:
688       self.actions['Create 17/23 level pair'] += 1
689       if r[il] == u'10/17/23':
690                lev0 = 10
691                levsp = [19,23]
692       else:
693                lev0 = 19
694                levsp = [23,]
695       r[ixp] = 1
696       r[il] = lev0
697       var2 = var2 + str( lev0 )
698       p = 1
699       for lp in levsp:
700                 p += 1
701                 rr0 = r + [r[1] + str(lp),]
702                 rr0[ixp] = p
703                 rr0[il] = lp
704                 rr0[iu] = str( uuid.uuid1() )
705                 rr = rr0 + [new, gpid, 0, vid]
706                 if r[1] == 'hus':
707                    print 'INFO.hus.00202: ',rr
708                 rset.append( rr )
709                 self.varsets(rr0[iu], 2, rr[iu], 1, 'variables at multiple vertical resolutions' )
710
711    elif r[il] in [u'Model levels or plev_27', u'Model levels or 27Plevs',u'27',27.]:
712               self.actions['27 level variant of variable name created' ] += 1
713               var2 += '27'
714               r[il] = 27
715    elif r[idx].find( '850 hPa' ) != -1:
716               if r[1][-3:] != '850':
717                  self.actions['850mb variant of variable generated'] += 1
718                  var2 += '850'
719    elif type( r[il] ) == type(1.) and r[il] == 7. and r[10] == 'HighResMIPxxxxx' and r[5] != 'XYZKT':
720                  ### no idea why this code is here ... added xxxx above t mae sure it is not executed.
721                  print 'INFO.7h.0001: ',r
722                  self.actions['Shape modified to XYZKT*'] += 1
723                  r[5] = r[5] + '*'
724                  r[il] = '7h'
725    r += [var2,new, gpid, 0, vid]
726    rset.append( r )
727    if r[10] != 'OMIP':
728      for ri in rset:
729        self.consol_sub01( ri, extra )
730    else:
731      self.actions['OMIP records skipped'] += 1
732
733  def consol_sub01( self, r, extra ):
734    """Write our a requestItem record, which is split into a CMORvar and requestVar in isd3b.py"""
735    iu = 11
736    assert r[iu] not  in self.sh
737    assert len(r) == len( self.sh['__cols__'] ), 'Bad record length .. %s'  % str(r)
738    print 'INFO.requestitem.00001: ',r
739    self.sh[r[iu]] = r[:]
740
741  def checkRequestedGroups(self,sdir='inSh'):
742    sh = shelve.open( '%s/sh__requestScoping' % sdir, 'r' )
743    sh0 = shelve.open( '%s/sh__requestScoping_0' % sdir, 'n' )
744    cc = collections.defaultdict( int )
745    ff = set()
746    for mip in sorted( sh['__records__'].keys() ):
747      reqg = sh['__records__'][mip]
748      reqgd = dict()
749      self.mip = mip
750      for rec in reqg:
751        g = rec[0]
752        if g[:5] == 'CMIP5':
753         g = g[6:]
754        g0 = g
755        t = self.vgss.recChk(rec,mip)
756        dyngrp = t[0]
757        if dyngrp:
758          mtab, g = t[2]
759        if not self.vgss.matchGroup(g,self.mip) and not dyngrp:
760          print 'FAILED to match request group: ',self.mip,rec
761          ff.add( (self.mip,g) )
762        else:
763          print 'INFO.group.00008: group found: %s (%s):: %s, %s' % (g,self.mip,self.vgss.groupName, self.vgss.groupMatch )
764          assert self.vgss.groupMatchRes != None,  'Should have results from matchGroup here!!'
765          reqgd[g] = self.vgss.groupMatchRes
766          uid = str(self.vgss.groupMatchRes[1] )
767          rec[0] = self.vgss.groupName
768          kkk = '%s__%2.2i__%s' % (uid,cc[uid],0)
769          cc[uid] += 1
770          assert kkk not in sh0, 'Duplicate key for request link record: %s' % kkk
771          sh0[kkk] = [self.mip, rec ]
772          print 'INFO.vgrp.00001: ',kkk,self.mip,rec
773          if dyngrp:
774            self.saveDynGrp(g,mtab,uid)
775##
776## need to generate request variables for dynamic groups here (those detected via vgss )
777## would be nice to stage things ... create variable database and then add requests ....
778## "all at once" risks mis-alignments ...
779##
780## need to fill in details on dynamic groups after completion of scan of new groups.   
781##
782##
783    sh.close()
784    sh0.close()
785    if len(ff) > 0:
786      oo = open( 'varGroupSuggestions.csv', 'w' )
787      for t in sorted( list( ff ) ):
788        oo.write( '%s\t%s' % t )
789        oo.write( '\t%s\n' % str( uuid.uuid1() ) )
790      oo.close()
791
792  def saveDynGrp(self,glab,tab,rgid):
793    this = self.vgss.s2[glab]
794    print 'INFO.dyngrp.00001: ',rgid,this, glab
795    for k in this:
796      if k[0] != '_':
797        if this[k] == None:
798          print 'ERROR.dyngrp.00002: variable not found: ',rgid,k, glab
799        else:
800          vid, priority = this[k]
801          rec = [vid, '%s: %s' % (glab,k), k, priority, rgid, self.mip] 
802          uid = str(uuid.uuid1() )
803          self.shdvg[uid] = rec
804
Note: See TracBrowser for help on using the repository browser.