source: CMIP6dreqbuild/trunk/src/framework/ingest/dreq_consol_dreq2.py @ 947

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

updates

Line 
1import string, uuid, shelve
2from fcc_utils2 import snlist
3import xlrd, string, shelve, os, re, sys
4import collections
5from utils_wb import workbook
6####
7import dreq_cfg
8import dreq_utils
9import utils_wb
10
11knownSlices = {'piControl020':20, 'piControl030':30, 'piControl050':50, 'piControl140':140, 'piControl165':165, 'piControl200':200,
12               'clim20':20, 'hist65':65, 'hist55':55, 'abrupt30':30, 'abrupt5':5, 'piControl030a':30, 'hist35':35}
13
14nt__pr4info = collections.namedtuple( 'r4info', ['ixcntl','ixh','ix0','ixm','ownix','ownhr','othix','othhr','mode','treset'] )
15
16deckExptMap = {'CMIP6 historical':['historical','esm-hist','historical-ext','esm-hist-ext'],
17               'control':['piControl','esm-piControl'], 'AMIP':['amip'], 'abrupt4xCO2':['abrupt-4xCO2',] }
18deckExptMapStar = {'CMIP6 historical':['historical','historical-ext'],
19               'control':['piControl']}
20
21class localMaps(object):
22##
23## expand groups in request row ...
24##   .. duplicates all request items
25##
26    groupExpand = {'ISMIP6.icesheetmon':['LImonant','LImongre'],
27                   'ISMIP6.icesheetyear':['LIyrant','LIyrgre'],
28                   'ISMIP6.icesheetfx':['LIfxant','LIfxgre']}
29
30base = '/home/martin/2014/wip/dreq/'
31dir0 = '/home/martin/2014/wip/dreq/input/'
32
33class rqsummary(object):
34  __doc__ = """Create a request summary table, by MIP and variable table.
35Creates a list of default dictionaries, one for each table. An entry for each MIP in each dictionary.
36"""
37  def __init__(self,exptInfo=None,idir=None):
38    self.idir = idir
39    self.tablist = []
40    self.tabindx = {}
41    self.mips = collections.defaultdict( int )
42    self.exptInfo = exptInfo
43    self.rowList = []
44    self.records = []
45    self.tsliceMap = {}
46    self.tsliceMap['DAMIP'] = {'18 (1850, 1860, ..,  2010, 2020)':'DAMIP18', 'all':None, \
47             '8\n(2030, 2040, .., 2090, 2100)':'DAMIP8', \
48             '61\n(1960-2020)':'DAMIP61', \
49             '60\n(1961-2020)':'DAMIP60', \
50             '40\n(2041-2060, 2081-2100)':'DAMIP40', \
51             '40\n(2026-2045, 2081-2100) xx':'DAMIP40x', '20\n(2081-2100)':'DAMIP20', '42\n(1979-2020)':'DAMIP42' }
52    self.tsliceMap['SIMIP'] = {'Last 100':'piControl100' }
53    self.tsliceMap['VolMIP'] = {'3 (start)':'VolMIP3'}
54    self.tsliceMap['RFMIP'] = {'4 (RFMIP_slice1)':'RFMIP4'}
55    self.tsliceMaps = dict()
56    for k in self.tsliceMap:
57      for x in self.tsliceMap[k]:
58        self.tsliceMaps[x] = k
59
60  def add(self):
61    return rq(parent=self, idir=self.idir)
62
63  def addRow( self, mip, tab, obj, grid, gok, comment,opt='',opar='',uid=None, preset=-2, vgid=None ):
64    if uid == None:
65      k = str( uuid.uuid1() )
66    else:
67      k = uid
68    self.rowList.append( (k,mip,tab, obj, grid, gok, comment, opt, opar, preset, vgid) )
69    return k
70
71  def addItem( self, mip, tab, nn, nexmax, nenmax, nymax, expt=None, rid=None, treset=None, info=None ):
72    if not self.tabindx.has_key( tab ):
73      self.tabindx[tab] = len(self.tablist)
74      self.tablist.append( collections.defaultdict( int ) )
75    ix = self.tabindx[tab]
76    self.tablist[ix][mip] = nn
77    self.mips[mip] += 1
78    if type(info) in [type(''), type(u'')]:
79      if info in ['','all','ALL']:
80         info = 'all'
81      else:
82         if info in knownSlices:
83           info = '_slice_%s' % info
84         elif info[-2:] == '**' and info[:-2] in knownSlices:
85           ##if nn not in deckExptMapStar:
86             ##print 'SEVERE.exptmap.00001: error in parsing of request item: %s: %s' % (nn, info)
87           info = '_slice_%s' % info
88         elif info not in self.tsliceMaps:
89           print 'ERROR.tslice.00001: map not found [%s]: %s' % (mip, info.replace( '\n', '\\n' ) )
90         else:
91           if self.tsliceMaps[info] not in [mip,'generic']:
92              print 'ERROR.tslice.00002: map found for wrong mip [%s]: %s:: %s' % (mip, info.replace( '\n', '\\n' ), self.tsliceMaps[info] )
93           else:
94              xx = self.tsliceMaps[info]
95              info = '_slice_%s' % self.tsliceMap[xx][info]
96    else:
97        ny = float(info)
98        if expt == 'control':
99          if ny > 400:
100            print 'INFO.tslice-ctl.000001: resetting %s -> all' % ny
101            info = 'all'
102          else:
103            print 'INFO.tslice-ctl.000001: %s requesting years %s' % (mip,ny)
104            info = '_slice_piControl%3.3i' % ny
105        elif expt == 'CMIP6 historical':
106          if ny > 150:
107            print 'INFO.tslice-his.000001: resetting %s -> all' % ny
108            info = 'all'
109          else:
110            print 'INFO.tslice-his.000001: %s requesting years %s' % (mip,ny)
111            info = '_slice_historical%3.3i' % ny
112    self.records.append( (mip,tab,expt, rid,nn, nexmax, nenmax, nymax,treset,info) )
113
114  def show(self,oo):
115    mips = self.mips.keys()
116    mips.sort()
117    keys = self.tabindx.keys()
118    keys.sort()
119    oo.write( ',' + string.join(mips, ',') + ',\n' )
120    for k in keys:
121      r = []
122      ix = self.tabindx[k]
123      for m in mips:
124        r.append( self.tablist[ix][m] )
125      print k,r
126      if max(r) > 0:
127        rec = '%s,' % k
128        for i in r:
129          rec += '%s,' %  i
130        oo.write( rec + '\n' )
131
132  def loadGroups(self):
133    wb = workbook( 'ingest/sortedVarGroups.xls' )
134    ## label, mip, -, -, -, title, refNote, uid, ref
135    sh = wb.book.sheet_by_name( 'Sheet1' )
136    self.groupset = {}
137    for i in range( sh.nrows ):
138      rr = [x.value.strip() for x in sh.row(i)]
139      label, mip, a1, a2, a3, title, refNote, uid, ref = rr[:9]
140      assert uid not in self.groupset, 'Duplicate uid: %s:: %s,%s' % (uid,str(self.groupset[uid]),str(rr))
141      self.groupset[uid] = (uid,mip,label,title,ref,refNote)
142
143class rq(object):
144
145  def __init__(self, parent=None, idir=None ):
146    if idir == None:
147      idir='../src/framework/inSh'
148    self.parent = parent
149    sh = shelve.open('%s/sh__requestScoping' % idir, 'r' )
150    sh0 = shelve.open('%s/sh__requestScoping_0' % idir, 'r' )
151    sh1 = shelve.open('%s/sh__requestScoping_1' % idir, 'r' )
152    cc = collections.defaultdict( list )
153    ee = dict()
154    ff = dict()
155    mips = set()
156    for k in sh0.keys():
157      if k[0] != '_' and k[-3:] == '__0':
158        k1 = k[:-1] + '1'
159        k1b = k[:36]
160        assert k1b in self.parent.groupset, 'Group uid not recognised: %s, %s' % (k,str(sh0[k]))
161        if k1 in sh1:
162           mip1, vgid = sh1[k1]
163           assert vgid == k1b, 'mismatch in vgid found ... %s, %s' % (vgid,k1b)
164       
165        uid = k[:-3]
166        mip, rec = sh0[k]
167        cc[mip].append( (uid,rec,k1b) )
168        r4il, r4 = sh['__headings__'][mip]
169        ee[mip] = nt__pr4info._make( r4il )
170        ff[mip] = r4
171        mips.add(mip)
172
173    sh.close()
174    sh0.close()
175    sh1.close()
176    print 'MIPS:: ',sorted( list( mips ) )
177    for mip in sorted( list( mips ) ):
178      self.mip = mip
179##
180## r4 is the headings row, r4i is the parsed information.
181##
182      self.parse02( cc[mip], ee[mip], ff[mip] )
183
184  def parse02(self,recl,r4i,r4):
185
186    self.mipl = None
187    self.nbl = None
188##
189    for uid,rv,vgid in recl:
190        tab = rv[0]
191        if '%s.%s' % (self.mip,tab) in localMaps.groupExpand:
192          tabl = localMaps.groupExpand[ '%s.%s' % (self.mip,tab) ]
193        elif not( len(tab) > 0 and tab[0] == '#'):
194          tabl = [tab,]
195        else:
196          tabl = []
197        for tab in tabl:
198          grid = rv[3]
199          gok = rv[r4i.mode-2]
200          comment = rv[r4i.mode-1]
201          obj0 = rv[r4i.mode]
202          bb = string.split(obj0, ':' )
203          if len(bb) > 1:
204            obj = bb[0]
205            preset = int( bb[1] )
206          else:
207            obj = obj0
208            preset = -1
209          opt = rv[1]
210          opar = rv[2]
211          nbl = False
212          if not tab in ['',u'']:
213            if self.mip != 'DCPP':
214              for je in range(5):
215                j1 = r4i.ixcntl + je*2
216                ok = self.readDeckColPair( rv[j1:j1+2], rv[0], j1, 160, expt=string.strip(r4[j1]), rid=uid )
217                if ok:
218                  nbl = True
219            for je in r4i.ownix:
220                ok = self.readDeckColPair( rv[je:je+2], rv[0], je, 100, expt=string.strip(r4[je]), rid=uid )
221                if ok:
222                  nbl = True
223            for jei in range( len(r4i.othix) ):
224                je = r4i.othix[jei]
225                tr = r4i.treset[jei]
226                ok = self.readDeckColPair( rv[je:je+3], rv[0], je, 100, expt=string.strip(r4[je+1]), rid=uid,mode=3,treset=tr )
227                if ok:
228                  nbl = True
229### add row if non-blank element found
230          if nbl:
231              if preset != -1:
232                print 'INFO.preset.00001: setting preset: ',rv
233              uid = self.parent.addRow( self.mip, tab, obj, grid, gok, comment, opt=opt, opar=opar, uid=uid, preset=preset, vgid=vgid )
234    return True
235
236  def readDeckColPair( self,data, tab, ix, nydef, expt=None, rid=None, mode=2, treset=None ):
237      assert mode in [2,3], 'Only modes 2,3 supported, not mode=%s' % mode
238      ##this = map( lambda x: x.value, self.wk1.currentSi.row(j)[ix:ix+mode] )
239      this = data
240##  if this element is empty, return .. nothing to do.
241      if all( [x in {u'','',0,0.0} for x in this] ):
242        return False
243
244      if mode == 2:
245        snens, sny = this
246        cmt = '2:%s:%s:' % (snens,sny)
247      else:
248        snex, snens, sny = this
249        cmt = '3:%s:%s:%s:' % (snex,snens,sny)
250
251      nex = 0
252      nexmax = -999
253      if mode == 3:
254        print '######### MODE = 3: %s' % str(this)
255        if type( snex ) in  {type(u' '),type(' ')}:
256          if snex[:3] in {u'all',u'ALL'}:
257            nex = 5
258            nexmax = -1
259          elif snex[:3] in {u'tbd',u'TBD','tbd','TBD'}:
260            print 'WARN:005.0001: tbd encountered in experiment number'
261            nex = 5
262            cmt += '*'
263          else:
264            print 'ERROR.001.0010: string in experiment number: %s' % snex
265            nex = 0
266            cmt += '*'
267        else:
268          print 'WARN:005.0002: experiment number .... need to check consistency etc: %s' % self.mip
269          nex = int(snex)
270          nexmax = nex
271        if type(nex) not in {type(1.), type(1)}:
272          print 'ERROR.099.0100: non integer nex: %s:: %s:: %s' % (str(this),snex, type(snex))
273          raise
274
275      try:
276        if snens in [ u'all', u'ALL']:
277          nens = 1
278          nenmax = -1
279        elif snens == '':
280          nens = 0
281          nenmax = -999
282        elif snens == 'O':
283          nens = 0
284          nenmax = -999
285          print 'WARNING: *O* (oh) entered for ensemble number: %s, %s' % (self.mip, tab)
286        else:
287          nens = int( snens )
288          nenmax = nens
289
290        if sny in [ u'all', u'ALL']:
291          ny = nydef
292          ony = 'all'
293          nymax = -1
294        elif sny in knownSlices:
295          ny = knownSlices[sny]
296          nymax = ny
297        elif sny == '':
298          ny = 0
299          ony = 0
300          nymax = -999
301        elif type(sny) in [type('x'),type(u'x')]:
302            s = sny
303            if sny[:-2] in knownSlices and sny[-2:] == '**':
304              ny = knownSlices[sny[:-2]]
305              nymax = ny
306            elif string.find( s, '\n' ) != -1:
307              bits = string.split( s, '\n' )
308              ny = int( bits[0] )
309              nymax = ny
310              cmt += '*'
311              print 'WARN.001.0001: [%s] truncating time period option: %s' % (self.mip, str(s) )
312            else:
313              x = string.split( s )[0]
314              if string.find( x, '-' ) != -1:
315                bb = string.split(x, '-' )
316                ny = int(bb[1])-int(bb[0])
317                print 'WARN.001.0002: [%s] truncating time period option: %s' % (self.mip, str(s) )
318                nymax = ny
319              elif string.find( x, '/' ) != -1:
320                bb = string.split(x, '/' )
321                ny = int(bb[0])
322                print 'WARN.001.0003: [%s] truncating time period option: %s' % (self.mip, str(s) )
323                nymax = ny
324              elif x[:4] == 'Last':
325                x = string.split( s )[1]
326                print 'WARN.001.0005: [%s] time period option read as string: %s' % (self.mip, str(s) )
327                ny = int( x )
328                nymax = ny
329              else:
330                print 'WARN.001.0004: [%s] time period option read as string: %s' % (self.mip, str(s) )
331                ny = int( x )
332                nymax = ny
333        else:
334          ny = sny
335          nymax = ny
336
337        if type( ny ) in [type( 'x' ),type( u'x' )]:
338          bits = string.split(ny) 
339          if bits[1] == u'period':
340            bb = string.split( bits[0], '-' )
341            ny = int(bb[1]) - int(bb[0])
342            raise
343
344        try:
345          if mode == 2:
346            ntot = nens*ny
347          else:
348            ntot = nex*nens*ny
349          if type(ntot) not in {type(1.), type(1)}:
350            print 'ERROR.099.0101: non integer ntot: %s:: %s' % (str([mode,nex,nens,ny]),str(this))
351            raise
352        except:
353          print self.mip, tab, nens, ny
354          raise
355
356        self.parent.addItem( self.mip, tab, ntot, nexmax, nenmax, nymax, expt=expt, rid=rid, treset=treset, info=sny )
357        return True
358      except:
359        print 'ERROR.002.0001: Failed trying to scan deck column pair.'
360        print self.mip,expt
361        raise
362
363class main(object):
364  def __init__(self,rqs, odir='sh20150827'):
365    self.rqs = rqs
366    self.rqs.loadGroups()
367    self.rqs.add()
368
369    oo = open( 'request02.csv', 'w' )
370    self.rqs.show( oo )
371    oo.close()
372
373    self.odir = odir
374
375  def rvg(self):
376### requestVarGroup = mip, label, title, uuid
377### requestLinks = vgid, objective, grid, gridreq, comment, uuid -- inherits label and title
378    sh = shelve.open( '%s/requestVarGroup02' % self.odir, 'n' )
379    sh['__info__'] = { 'label':'requestVarGroup', 'title':'Identify variable groups' }
380    sh['__cols__'] = [ 'uuid', 'mip', 'label','title','ref','refNote']
381## rows from "request scoping" analysed in *ingest* package of dreqPy
382    for u in self.rqs.groupset:
383        sh[str(u)] = self.rqs.groupset[u]
384    sh.close()
385
386  def rql(self):
387    s1 = set()
388    sh = shelve.open( '%s/requestLinks02' % self.odir, 'n' )
389    sh['__info__'] = { 'label':'requestLinks', 'title':'Links from variable groups to a request id' }
390    sh['__cols__'] = [ 'uid', 'mip', 'tab','objective','grid','gridreq','comment','opt','opar', 'preset', 'vgid']
391    print 'INFO.rql.000101: number of rows: %s' % len( self.rqs.rowList )
392    for i in self.rqs.rowList:
393      assert i[-1] in self.rqs.groupset, 'vgid not found for %s' % str(i)
394      assert i[0] not in sh, 'duplicate uid found in requestlinks'
395      sh[i[0]] = i[:]
396      if i[3] in {'',u''}:
397        print 'ERROR.099.0060: Blank objective: %s' % str(i)
398      s1.add( i[0] )
399      print 'INFO.dcd.00401: ',i[0],i[1],i[2],i[-1]
400    sh.close()
401    print 'INFO.rqi.000101: number of rows: %s' % len( self.rqs.records )
402    sh = shelve.open( '%s/requestItems02' % self.odir, 'n' )
403    sh['__info__'] = { 'label':'requestItems', 'title':'Specification for a single experiment' , \
404         'comment':'Currently only has number of years -- need to include more details' }
405    sh['__cols__'] = [ 'mip', 'tab', 'expt','rlid','ny', 'nexmax', 'nenmax', 'nymax','treset','info']
406    ##('AerChemMIP', u'Omon_3d', u'CMIP6 historical', 'ad74be9a-26ef-11e5-8d9b-ac72891c3257', 0.0)
407    nro = 0
408    cc = dict()
409    for i in self.rqs.records:
410      if type(i[4]) not in ( type(0), type(1.) ):
411          print 'ERROR.099.0001: non-integer ny: %s' % str(i)
412      expt = i[2]
413      if string.find( expt, '(' ) != -1:
414        expt = string.strip( expt[:string.find( expt, '(' )] )
415      if i[3] not in s1:
416        print 'SEVERE.005.00009: bad link ',i
417      if expt in deckExptMap or string.find( expt, ',' ) != -1 or (string.find( expt, ' ' ) != -1 and expt != "CMIP6 historical"):
418        il = list(i)
419        print 'INFO.expt.01001: %s, %s' % (expt, str(il) )
420        if expt in deckExptMap:
421          if type(i[-1]) in [type(''),type(u'')] and i[-1][-2:] == '**':
422            il[-1] = i[-1][:-2]
423            bits = deckExptMapStar[expt]
424          else:
425            bits = deckExptMap[expt]
426        else:
427          bits = map( lambda x: string.strip(x), string.split( expt, ',' ) )
428        print 'INFO.expt.00006: ',il, bits
429        for b in bits:
430          assert len(b) > 1, 'Bad parsing of experiment name: %s' % str( i )
431          il[2] = b
432          bb = dreq_utils.labcoerce(b)
433          k = str( uuid.uuid1() )
434          sh[k] =  il[:] 
435          ttt = (il[2],il[3])
436          if ttt in cc:
437            print 'WARN.rqi.00101: duplicate: %s -- %s' % (str(il),str(cc[ttt]))
438          cc[ttt] = il
439          nro += 1
440     
441      else:
442        k = str( uuid.uuid1() )
443        if expt != i[2]:
444          il = list(i)
445          il[2] = expt
446          sh[k] =  il[:] 
447          nro += 1
448          ttt = (il[2],il[3])
449          if ttt in cc:
450            print 'WARN.rqi.00102: duplicate: %s -- %s' % (str(il),str(cc[ttt]))
451          cc[ttt] = il
452        else:
453          sh[k] =  i[:] 
454          nro += 1
455          ttt = (i[2],i[3])
456          if ttt in cc:
457            print 'WARN.rqi.00103: duplicate: %s -- %s' % (str(i),str(cc[ttt]))
458          cc[ttt] = i
459    sh.close()
460    print 'INFO.rqi.000102: number of records written: %s' % nro
461
462if __name__ == '__main__':
463  rqs= rqsummary( idir='../inSh')
464  m = main( rqs, odir='../inSh' )
465  m.rvg()
466  m.rql()
Note: See TracBrowser for help on using the repository browser.