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

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

misc 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    self.records.append( (mip,tab,expt, rid,nn, nexmax, nenmax, nymax,treset,info) )
114
115  def show(self,oo):
116    mips = self.mips.keys()
117    mips.sort()
118    keys = self.tabindx.keys()
119    keys.sort()
120    oo.write( ',' + string.join(mips, ',') + ',\n' )
121    for k in keys:
122      r = []
123      ix = self.tabindx[k]
124      for m in mips:
125        r.append( self.tablist[ix][m] )
126      print k,r
127      if max(r) > 0:
128        rec = '%s,' % k
129        for i in r:
130          rec += '%s,' %  i
131        oo.write( rec + '\n' )
132
133  def loadGroups(self):
134    wb = workbook( 'ingest/sortedVarGroups.xls' )
135    ## label, mip, -, -, -, title, refNote, uid, ref
136    sh = wb.book.sheet_by_name( 'Sheet1' )
137    self.groupset = {}
138    for i in range( sh.nrows ):
139      rr = [x.value.strip() for x in sh.row(i)]
140      label, mip, a1, a2, a3, title, refNote, uid, ref = rr[:9]
141      assert uid not in self.groupset, 'Duplicate uid: %s:: %s,%s' % (uid,str(self.groupset[uid]),str(rr))
142      self.groupset[uid] = (uid,mip,label,title,ref,refNote)
143
144class rq(object):
145
146  def __init__(self, parent=None, idir=None ):
147    if idir == None:
148      idir='../src/framework/inSh'
149    self.parent = parent
150    sh = shelve.open('%s/sh__requestScoping' % idir, 'r' )
151    sh0 = shelve.open('%s/sh__requestScoping_0' % idir, 'r' )
152    sh1 = shelve.open('%s/sh__requestScoping_1' % idir, 'r' )
153    cc = collections.defaultdict( list )
154    ee = dict()
155    ff = dict()
156    mips = set()
157    for k in sh0.keys():
158      if k[0] != '_' and k[-3:] == '__0':
159        k1 = k[:-1] + '1'
160        k1b = k[:36]
161        assert k1b in self.parent.groupset, 'Group uid not recognised: %s, %s' % (k,str(sh0[k]))
162        if k1 in sh1:
163           mip1, vgid = sh1[k1]
164           assert vgid == k1b, 'mismatch in vgid found ... %s, %s' % (vgid,k1b)
165       
166        uid = k[:-3]
167        mip, rec = sh0[k]
168        cc[mip].append( (uid,rec,k1b) )
169        r4il, r4 = sh['__headings__'][mip]
170        ee[mip] = nt__pr4info._make( r4il )
171        ff[mip] = r4
172        mips.add(mip)
173
174    sh.close()
175    sh0.close()
176    sh1.close()
177    print 'MIPS:: ',sorted( list( mips ) )
178    for mip in sorted( list( mips ) ):
179      self.mip = mip
180##
181## r4 is the headings row, r4i is the parsed information.
182##
183      self.parse02( cc[mip], ee[mip], ff[mip] )
184
185  def parse02(self,recl,r4i,r4):
186
187    self.mipl = None
188    self.nbl = None
189##
190    for uid,rv,vgid in recl:
191        tab = rv[0]
192        if '%s.%s' % (self.mip,tab) in localMaps.groupExpand:
193          tabl = localMaps.groupExpand[ '%s.%s' % (self.mip,tab) ]
194        elif not( len(tab) > 0 and tab[0] == '#'):
195          tabl = [tab,]
196        else:
197          tabl = []
198        for tab in tabl:
199          grid = rv[3]
200          gok = rv[r4i.mode-2]
201          comment = rv[r4i.mode-1]
202          obj0 = rv[r4i.mode]
203          bb = string.split(obj0, ':' )
204          if len(bb) > 1:
205            obj = bb[0]
206            preset = int( bb[1] )
207          else:
208            obj = obj0
209            preset = -1
210          opt = rv[1]
211          opar = rv[2]
212          nbl = False
213          if not tab in ['',u'']:
214            if self.mip != 'DCPP':
215              for je in range(5):
216                j1 = r4i.ixcntl + je*2
217                ok = self.readDeckColPair( rv[j1:j1+2], rv[0], j1, 160, expt=string.strip(r4[j1]), rid=uid )
218                if ok:
219                  nbl = True
220            for je in r4i.ownix:
221                ok = self.readDeckColPair( rv[je:je+2], rv[0], je, 100, expt=string.strip(r4[je]), rid=uid )
222                if ok:
223                  nbl = True
224            for jei in range( len(r4i.othix) ):
225                je = r4i.othix[jei]
226                tr = r4i.treset[jei]
227                ok = self.readDeckColPair( rv[je:je+3], rv[0], je, 100, expt=string.strip(r4[je+1]), rid=uid,mode=3,treset=tr )
228                if ok:
229                  nbl = True
230### add row if non-blank element found
231          if nbl:
232              if preset != -1:
233                print 'INFO.preset.00001: setting preset: ',rv
234              uid = self.parent.addRow( self.mip, tab, obj, grid, gok, comment, opt=opt, opar=opar, uid=uid, preset=preset, vgid=vgid )
235    return True
236
237  def readDeckColPair( self,data, tab, ix, nydef, expt=None, rid=None, mode=2, treset=None ):
238      assert mode in [2,3], 'Only modes 2,3 supported, not mode=%s' % mode
239      ##this = map( lambda x: x.value, self.wk1.currentSi.row(j)[ix:ix+mode] )
240      this = data
241##  if this element is empty, return .. nothing to do.
242      if all( [x in {u'','',0,0.0} for x in this] ):
243        return False
244
245      if mode == 2:
246        snens, sny = this
247        cmt = '2:%s:%s:' % (snens,sny)
248      else:
249        snex, snens, sny = this
250        cmt = '3:%s:%s:%s:' % (snex,snens,sny)
251
252      nex = 0
253      nexmax = -999
254      if mode == 3:
255        print '######### MODE = 3: %s' % str(this)
256        if type( snex ) in  {type(u' '),type(' ')}:
257          if snex[:3] in {u'all',u'ALL'}:
258            nex = 5
259            nexmax = -1
260          elif snex[:3] in {u'tbd',u'TBD','tbd','TBD'}:
261            print 'WARN:005.0001: tbd encountered in experiment number'
262            nex = 5
263            cmt += '*'
264          else:
265            print 'ERROR.001.0010: string in experiment number: %s' % snex
266            nex = 0
267            cmt += '*'
268        else:
269          print 'WARN:005.0002: experiment number .... need to check consistency etc: %s' % self.mip
270          nex = int(snex)
271          nexmax = nex
272        if type(nex) not in {type(1.), type(1)}:
273          print 'ERROR.099.0100: non integer nex: %s:: %s:: %s' % (str(this),snex, type(snex))
274          raise
275
276      try:
277        if snens in [ u'all', u'ALL']:
278          nens = 1
279          nenmax = -1
280        elif snens == '':
281          nens = 0
282          nenmax = -999
283        elif snens == 'O':
284          nens = 0
285          nenmax = -999
286          print 'WARNING: *O* (oh) entered for ensemble number: %s, %s' % (self.mip, tab)
287        else:
288          nens = int( snens )
289          nenmax = nens
290
291        if sny in [ u'all', u'ALL']:
292          ny = nydef
293          ony = 'all'
294          nymax = -1
295        elif sny in knownSlices:
296          ny = knownSlices[sny]
297          nymax = ny
298        elif sny == '':
299          ny = 0
300          ony = 0
301          nymax = -999
302        elif type(sny) in [type('x'),type(u'x')]:
303            s = sny
304            if sny[:-2] in knownSlices and sny[-2:] == '**':
305              ny = knownSlices[sny[:-2]]
306              nymax = ny
307            elif string.find( s, '\n' ) != -1:
308              bits = string.split( s, '\n' )
309              ny = int( bits[0] )
310              nymax = ny
311              cmt += '*'
312              print 'WARN.001.0001: [%s] truncating time period option: %s' % (self.mip, str(s) )
313            else:
314              x = string.split( s )[0]
315              if string.find( x, '-' ) != -1:
316                bb = string.split(x, '-' )
317                ny = int(bb[1])-int(bb[0])
318                print 'WARN.001.0002: [%s] truncating time period option: %s' % (self.mip, str(s) )
319                nymax = ny
320              elif string.find( x, '/' ) != -1:
321                bb = string.split(x, '/' )
322                ny = int(bb[0])
323                print 'WARN.001.0003: [%s] truncating time period option: %s' % (self.mip, str(s) )
324                nymax = ny
325              elif x[:4] == 'Last':
326                x = string.split( s )[1]
327                print 'WARN.001.0005: [%s] time period option read as string: %s' % (self.mip, str(s) )
328                ny = int( x )
329                nymax = ny
330              else:
331                print 'WARN.001.0004: [%s] time period option read as string: %s' % (self.mip, str(s) )
332                ny = int( x )
333                nymax = ny
334        else:
335          ny = sny
336          nymax = ny
337
338        if type( ny ) in [type( 'x' ),type( u'x' )]:
339          bits = string.split(ny) 
340          if bits[1] == u'period':
341            bb = string.split( bits[0], '-' )
342            ny = int(bb[1]) - int(bb[0])
343            raise
344
345        try:
346          if mode == 2:
347            ntot = nens*ny
348          else:
349            ntot = nex*nens*ny
350          if type(ntot) not in {type(1.), type(1)}:
351            print 'ERROR.099.0101: non integer ntot: %s:: %s' % (str([mode,nex,nens,ny]),str(this))
352            raise
353        except:
354          print self.mip, tab, nens, ny
355          raise
356
357        self.parent.addItem( self.mip, tab, ntot, nexmax, nenmax, nymax, expt=expt, rid=rid, treset=treset, info=sny )
358        return True
359      except:
360        print 'ERROR.002.0001: Failed trying to scan deck column pair.'
361        print self.mip,expt
362        raise
363
364class main(object):
365  def __init__(self,rqs, odir='sh20150827'):
366    self.rqs = rqs
367    self.rqs.loadGroups()
368    self.rqs.add()
369
370    oo = open( 'request02.csv', 'w' )
371    self.rqs.show( oo )
372    oo.close()
373
374    self.odir = odir
375
376  def rvg(self):
377### requestVarGroup = mip, label, title, uuid
378### requestLinks = vgid, objective, grid, gridreq, comment, uuid -- inherits label and title
379    sh = shelve.open( '%s/requestVarGroup02' % self.odir, 'n' )
380    sh['__info__'] = { 'label':'requestVarGroup', 'title':'Identify variable groups' }
381    sh['__cols__'] = [ 'uuid', 'mip', 'label','title','ref','refNote']
382## rows from "request scoping" analysed in *ingest* package of dreqPy
383    for u in self.rqs.groupset:
384        sh[str(u)] = self.rqs.groupset[u]
385    sh.close()
386
387  def rql(self):
388    s1 = set()
389    sh = shelve.open( '%s/requestLinks02' % self.odir, 'n' )
390    sh['__info__'] = { 'label':'requestLinks', 'title':'Links from variable groups to a request id' }
391    sh['__cols__'] = [ 'uid', 'mip', 'tab','objective','grid','gridreq','comment','opt','opar', 'preset', 'vgid']
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    sh.close()
400    sh = shelve.open( '%s/requestItems02' % self.odir, 'n' )
401    sh['__info__'] = { 'label':'requestItems', 'title':'Specification for a single experiment' , \
402         'comment':'Currently only has number of years -- need to include more details' }
403    sh['__cols__'] = [ 'mip', 'tab', 'expt','rlid','ny', 'nexmax', 'nenmax', 'nymax','treset','info']
404    ##('AerChemMIP', u'Omon_3d', u'CMIP6 historical', 'ad74be9a-26ef-11e5-8d9b-ac72891c3257', 0.0)
405    for i in self.rqs.records:
406      if type(i[4]) not in ( type(0), type(1.) ):
407          print 'ERROR.099.0001: non-integer ny: %s' % str(i)
408      expt = i[2]
409      if string.find( expt, '(' ) != -1:
410        expt = string.strip( expt[:string.find( expt, '(' )] )
411      if i[3] not in s1:
412        print 'SEVERE.005.00009: bad link ',i
413      if expt in deckExptMap or string.find( expt, ',' ) != -1 or (string.find( expt, ' ' ) != -1 and expt != "CMIP6 historical"):
414        il = list(i)
415        print 'INFO.expt.01001: %s, %s' % (expt, str(il) )
416        if expt in deckExptMap:
417          if type(i[-1]) in [type(''),type(u'')] and i[-1][-2:] == '**':
418            il[-1] = i[-1][:-2]
419            bits = deckExptMapStar[expt]
420          else:
421            bits = deckExptMap[expt]
422        else:
423          bits = map( lambda x: string.strip(x), string.split( expt, ',' ) )
424        print 'INFO.expt.00006: ',il, bits
425        for b in bits:
426          assert len(b) > 1, 'Bad parsing of experiment name: %s' % str( i )
427          il[2] = b
428          bb = dreq_utils.labcoerce(b)
429          k = str( uuid.uuid1() )
430          sh[k] =  il[:] 
431     
432      else:
433        k = str( uuid.uuid1() )
434        if expt != i[2]:
435          il = list(i)
436          il[2] = expt
437          sh[k] =  il[:] 
438        else:
439          sh[k] =  i[:] 
440    sh.close()
441
442if __name__ == '__main__':
443  rqs= rqsummary( idir='../inSh')
444  m = main( rqs, odir='../inSh' )
445  m.rvg()
446  m.rql()
Note: See TracBrowser for help on using the repository browser.