source: CMIP6dreq/trunk/srcMisc/dreq_consol_tables.py @ 348

Subversion URL: http://proj.badc.rl.ac.uk/svn/exarch/CMIP6dreq/trunk/srcMisc/dreq_consol_tables.py@348
Revision 348, 18.6 KB checked in by mjuckes, 5 years ago (diff)

more updates

Line 
1"""Parsing adjusted CMIP5 tables.
2"""
3import string, shelve, uuid
4from fcc_utils2 import snlist
5import xlrd, string, shelve, os, re, sys
6import collections
7import xlutils, xlwt
8import xlutils.copy
9####
10import dreq_cfg
11from utils_wb import wbcp, workbook, uniCleanFunc
12
13nt__deckrq = collections.namedtuple( 'dckrq', ['control','AMIP','abrupt4xCO2','rq_1pctCO2','historical'] )
14nt__grptbl = collections.namedtuple( 'grptbl', ['grp','var','srcTable','freq','description','shape','levels','timeProc','mask','priority','mip','id'] )
15nt__newtbl = collections.namedtuple( 'newtbl', ['var','sn','stat','grid','units','long_name','description','priority','obs','mip','id'] )
16dd_rq = collections.defaultdict( dict )
17dd_tbl = collections.defaultdict( int )
18
19class tupsort:
20   def __init__(self,k=0):
21     self.k = k
22   def cmp(self,x,y):
23     return cmp( x[self.k], y[self.k] )
24
25def uniquify( ll ):
26  ll.sort()
27  l0 = [ll[0],]
28  for l in ll[1:]:
29    if l != l0[-1]:
30      l0.append(l)
31  return l0
32
33def getRowValues( ll, minLen=0 ):
34  oo = []
35  for i in ll:
36    oo.append( i.value )
37  if len(oo) >= minLen:
38    return oo[:minLen]
39  for i in range(minLen+1):
40    if len(oo) == minLen:
41      return oo
42    oo.append( '' )
43  return oo
44
45
46clabs = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
47def clab(n):
48  i = n/26
49  assert i < 26, 'Not ready for row number greater than 26*26'
50  if i == 0:
51    return clabs[n]
52  else:
53    return clabs[i-1] + clabs[ n - i*26]
54
55def getRow(sht):
56  ee = {}
57  for i in range(sht.nrows):
58    if sht.row(i)[0].ctype == 2 and str( sht.row(i)[0].value ) != '0.0':
59      l = map( lambda x: str( x.value ), sht.row(i) )
60      k = l[5]
61      try:
62        ee[k] = l
63      except:
64        print l
65        raise
66  return ee
67   
68def outvSer( ov ):
69  ll = []
70  for i in ov:
71    ll.append( '%s|%s|%s' % tuple( map( str, i) ) )
72  return string.join(ll, '; ' )
73def joinRec( rl, tab='\t', omit=[],lmax=None ):
74    l1 = len(rl)
75    if lmax != None and l1 > lmax:
76      l1 = lmax
77    rl0 = []
78    for i in range(l1):
79      if i not in omit:
80        rl0.append(string.strip(str(rl[i])))
81    return string.join( map( str, rl0), tab )
82 
83
84def lennbl(ll):
85  i = 0
86  ii = 0
87  for l in ll:
88    i+= 1
89    if l != '':
90      ii = i
91  return ii
92
93def  matchVals( thisv, valset ):
94  ll1 = []
95  ll2 = []
96  lk0 = []
97  kk = 0
98  for vals in valset:
99    l1 = min( [lennbl(thisv), lennbl(vals)] )
100    l2 = max( [lennbl(thisv), lennbl(vals)] )
101    ll = []
102    for i in range(l1):
103      ll.append( vals[i] == thisv[i] )
104    for i in range(l2-l1):
105      ll.append(False)
106    if all(ll):
107      return ll
108    k = 0
109    for l in ll:
110      if l:
111        k+=1
112    if ll[0]:
113      lk0.append( kk )
114     
115    ll1.append(k)
116    ll2.append(ll)
117    kk += 1
118  k0 = max( ll1 )
119  if len(lk0) > 0:
120    k0 = lk0[0]
121    return ll2[ k0 ]
122  return ll2[ ll1.index(k0) ]
123   
124class mipTable(object):
125
126  def __init__(self,id):
127     self.vars = collections.defaultdict( list )
128
129class rqsummary(object):
130  __doc__ = """Create a request summary table, by MIP and variable table.
131Creates a list of default dictionaries, one for each table. An entry for each MIP in each dictionary.
132"""
133
134  def __init__(self,exptInfo=None):
135    self.tablist = []
136    self.tabindx = {}
137    self.mips = collections.defaultdict( int )
138    self.vars = collections.defaultdict( list )
139    self.t = {}
140    self.records = []
141    self.exptInfo = exptInfo
142
143  def addTab(self,tab):
144    self.t[tab] = mipTable( tab )
145
146  def add(self,mip,path,tab):
147    self.tab = tab
148    return rq(mip,path,parent=self,tab=tab)
149
150  def addItem( self, mip, tab, nn ):
151    if not self.tabindx.has_key( tab ):
152      self.tabindx[tab] = len(self.tablist)
153      self.tablist.append( collections.defaultdict( int ) )
154    ix = self.tabindx[tab]
155    self.tablist[ix][mip] = nn
156    self.mips[mip] += 1
157
158  def checkVars(self):
159    keys = self.vars.keys()
160    keys.sort()
161    for k in keys:
162      if len( self.vars[k] ) == 1:
163        print k, 'singleton'
164      else:
165        li = self.vars[k]
166## getting a bit intricate here -- 3rd element is index of record row
167        ll = [self.records[li[0][2]], ]
168        aa = collections.defaultdict( list )
169        aa[0].append[0]
170       
171  def prep(self,mode='vars',tab=None):
172    if tab != None:
173      self.tab = tab
174    kk = 0
175    mips = self.mips.keys()
176    mips.sort()
177    keys = self.tabindx.keys()
178    keys.sort()
179    self.oorecs = []
180    if mode == 'vars':
181      keys = self.t[self.tab].vars.keys()
182      keys.sort()
183      for k in keys:
184        rec = [k,]
185        ee1 = collections.defaultdict( list )
186        ee2 = {}
187        for t in self.t[self.tab].vars[k]:
188          k0 = joinRec( self.records[t[2]], tab=',', omit=[7,16,23] )
189          ee1[k0].append( t )
190        if len(ee1.keys()) > 1:
191          for k1 in ee1.keys():
192              for t in ee1[k1]:
193                ee2[t[0]] = k1
194          k1 = ee1.keys()
195          ee3 = collections.defaultdict( list )
196          for t in self.t[self.tab].vars[k]:
197            ee3[k1.index( ee2[t[0]] ) ].append( '%s[%s]' % (t[0],t[1]) )
198            rec.append( '%s[%s]{%s}' % (t[0],t[1],k1.index( ee2[t[0]]) ) )
199          ##self.oorecs.append(rec)
200          for kkk in k1:
201            ix = ee1[kkk][0][2]
202            ik = k1.index(kkk)
203            rec = [k, string.join(ee3[ik],';'),]   + list(self.records[ix])
204            self.oorecs.append(rec)
205           
206  def showXls(self,wb,r0=3,offset=0):
207    r = r0
208    thisStj = 2
209    for rec in self.oorecs:
210      i = offset
211      for item in rec:
212        wb.putValue2( r,i, item )
213        i+= 1
214      thisStj = 5 - thisStj
215      r+= 1
216   
217  def show(self,oo,mode='vars',tab=None):
218    if tab != None:
219      self.tab = tab
220    kk = 0
221    mips = self.mips.keys()
222    mips.sort()
223    keys = self.tabindx.keys()
224    keys.sort()
225    if mode == 'vars':
226      for rec in self.oorecs:
227            srec = joinRec( rec) + '\t' 
228            oo.write( srec + '\n' )
229
230    elif mode == 'oldvars':
231      keys = self.t[self.tab].vars.keys()
232      keys.sort()
233      for k in keys:
234        rec = '%s\t' % k
235        ee1 = collections.defaultdict( list )
236        ee2 = {}
237        for t in self.t[self.tab].vars[k]:
238          k0 = joinRec( self.records[t[2]], tab=',', omit=[7,16,23] )
239          ee1[k0].append( t )
240        if len(ee1.keys()) > 1:
241          for k1 in ee1.keys():
242              for t in ee1[k1]:
243                ee2[t[0]] = k1
244          k1 = ee1.keys()
245          for t in self.t[self.tab].vars[k]:
246            rec += '%s[%s]{%s}\t' % (t[0],t[1],k1.index( ee2[t[0]]) )
247          oo.write( rec + '\n' )
248          for kkk in k1:
249            ix = ee1[kkk][0][2]
250            rec = '--%s--\t' % k1.index(kkk) + joinRec( self.records[ix] ) + '\t' 
251            oo.write( rec + '\n' )
252    else:
253     oo.write( ',' + string.join(mips, ',') + ',\n' )
254     for k in keys:
255      r = []
256      ix = self.tabindx[k]
257      for m in mips:
258        r.append( self.tablist[ix][m] )
259      if max(r) > 0:
260        rec = '%s,' % k
261        for i in r:
262          rec += '%s,' %  i
263        oo.write( rec + '\n' )
264
265
266#dd_rq = collections.defaultdict( dict )
267#dd_tbl = collections.defaultdict( int )
268class rq(object):
269
270  def __init__(self, mip,path, parent=None,tab=u'Omon' ):
271
272    self.mip = mip
273    self.nn = 0
274    self.wk1 = wbcp( inbook=path )
275    if tab in  self.wk1.sns:
276      self.tab = tab
277      self.wk1.focus( tab)
278      self.parent = parent
279      if not self.parent.t.has_key(tab):
280        self.parent.addTab(tab)
281      self.ok = self.parse01()
282    else:
283      self.ok = False
284
285  def parse01(self):
286
287    ee1 = collections.defaultdict( list )
288    for j in range(3,self.wk1.currentSi.nrows):
289      if self.wk1.currentSi.row(j)[0].ctype == 2:
290        v = string.strip( str( self.wk1.currentSi.row(j)[5].value ) )
291        ee1[v].append(j)
292    for j in range(3,self.wk1.currentSi.nrows):
293      rv = map( lambda x: x.value, self.wk1.currentSi.row(j) )
294      lr0 = len(rv)
295      for i in range(10):
296        if len(rv) < 26:
297           rv.append('')
298      if self.wk1.currentSi.row(j)[0].ctype == 2:
299        v = string.strip( str( self.wk1.currentSi.row(j)[5].value ) )
300        if v not in ['0.0','']:
301          if len(ee1[v]) > 1:
302             v += '__%s' % ['a','b'][ee1[v].index(j)]
303          ixr = len(self.parent.records )
304          self.parent.records.append( tuple(rv[1:]) )
305          p = int( rv[0] + 0.001 )
306          if lr0 > 24:
307            if self.wk1.currentSi.row(j)[24].ctype == 2:
308              yv = int( rv[24] + 0.001 )
309              assert yv in [0,1,2], 'Invalid value in column Y, j=%s,v=%s' % (j,v)
310              if yv == 0:
311                p = None
312              elif yv == 2:
313                p = 1
314            elif rv[24] != '':
315              print 'WARNING[1]:', self.mip, v, p, rv[24]
316         
317          if p != None:
318            self.parent.t[self.tab].vars[v].append( (self.mip,p,ixr) ) 
319            self.nn += 1
320
321    return True
322
323class main(object):
324  def __init__(self):
325    kk=3
326    self.idx = 0
327    self.sh = shelve.open( 'dreq_consol_tables_shelve_v20150631' )
328    self.shnv = shelve.open( 'dreq_consol_tables_nv_shelve_v20150631' )
329    self.shold = shelve.open( 'dreq_consol_tables_old_shelve_v20150631' )
330
331    base = '/home/martin/2014/wip/dreq/'
332    self.dir0 = '/home/martin/2014/wip/dreq/input/'
333    file = 'PMIP/CMIP6DataRequestCompilationTemplate_20141218_PMIP_v150228_final.xls'
334    file = 'C4MIP/CMIP6DataRequestCompilationTemplate_C4MIP_06March2015_submitted.xls'
335    fileTmpl = 'CMIP6DataRequestCompilationTemplate_20141218.xls'
336    self.newVars = 'CMIP6DataRequest_ConsolidatedNewVariables_20150631.xls'
337    self.nvd = {}
338
339    wk0 = wbcp( inbook=base+fileTmpl )
340    self.cfg = dreq_cfg.rqcfg()
341    wk0.focus( u'Experiments')
342    mlist = collections.defaultdict( list )
343    for i in range(2,wk0.currentSi.nrows):
344      mip = str(wk0.currentSi.row(i)[3].value)
345      vals = map( lambda x: x.value, wk0.currentSi.row(i) )
346      if mip != '':
347        mlist[mip].append( vals )
348   
349    self.mips = mlist.keys()
350    self.mips.sort()
351   
352    mipTrans ={ 'geoMIP':'GeoMIP' }
353    diagMips = ['DynVar','SIMIP']
354    k2 = self.cfg.ff.keys()
355    k2.sort()
356    nn = 0
357    for k in k2:
358      k = mipTrans.get( k,k)
359      if k not in self.mips and k not in diagMips:
360         print '%s not found' % k
361         nn += 1
362    assert nn == 0, 'MIP naming error?'
363
364    exptList = '/home/martin/Documents/CMIP6_ExpermentList_draft01April2015.xls'
365    wke = wbcp( exptList )
366    wke.focus( 'Experiments' )
367    expgs = collections.defaultdict( int )
368    expgsEns = collections.defaultdict( int )
369    expgsYpe = collections.defaultdict( int )
370    for k in range(2,wke.currentSi.nrows):
371      vals = map( lambda x: x.value, wke.currentSi.row(k) )
372      g = string.strip( vals[1] )
373      if g[:5] == 'DAMIP':
374        print '######',g,vals[12],vals[13]
375      expgs[g] += vals[13]
376      expgsEns[g] = vals[12]
377
378    for k in expgs.keys():
379      if expgsEns[k] == 0:
380        expgsYpe[k] = 0
381      else:
382        try:
383          expgsYpe[k] = expgs[k]/expgsEns[k]
384        except:
385          print k, expgs[k], expgsEns[k]
386          raise
387   
388    self.rqs= rqsummary(exptInfo=(expgs,expgsEns,expgsYpe))
389    self.exptInfo=(expgs,expgsEns,expgsYpe)
390
391  def loadNewVars(self):
392    assert os.path.isfile( self.newVars ), '%s not found' % self.newVars
393    wb = workbook(self.newVars)
394    sh = wb.book.sheet_by_name( 'New variables' )
395    oo = open( '/tmp/newvars.txt', 'w' )
396    for i in range(3,sh.nrows):
397      r = map( lambda x: x.value, sh.row(i) )
398      try:
399        oo.write( string.join(map(str,r) ) + '\n' )
400      except:
401        oo.write( r[0] + '  --- rest missing --- \n' )
402      if r[0] != '' and r[4] != '':
403        v = string.strip( str( r[4] ) )
404        if v[0] != '#':
405          bits = string.split(v,' ')
406          if len(bits) == 1:
407            m = str( r[0] )
408            p = 0
409            try:
410              if m == 'LUMIP':
411                p = int( r[12] )
412              else:
413                p = int( r[11] )
414            except:
415              print '!!!!!! Failed to read priority: ',v,m
416            if v[-2:] == '**':
417               v = v[:-2]
418            elif v[-1] == '!':
419               v = v[:-1]
420            if self.nvd.has_key(v):
421              print '#########',v,self.nvd[v],m,p
422            self.nvd[v] = [p,] + r
423    for v in self.nvd.keys():
424        k = str( uuid.uuid1() )
425        self.shnv[k] = self.nvd[v][:] + [k,]
426    oo.close()
427
428  def groups(self, vl3=None):
429    print self.cfg.ee.keys()
430    omit = ['ALL VARIABLES', 'Objectives','Experiments','Experiment Groups','Request scoping','New variables','__lists__']
431    keys = self.cfg.ee.keys()
432    keys.sort()
433    ee = {}
434    self.glist = []
435    for k in keys:
436        fn = self.cfg.ee[k]
437        path = '%s%s/%s' % (self.dir0,k,fn)
438        wb = workbook( path )
439        ss = []
440        for s in wb.sns:
441          if s not in omit:
442            ss.append(s)
443        for s in ss:
444          e1 = collections.defaultdict( int )
445          if s[:5] != 'CMIP5':
446           sh = wb.book.sheet_by_name( s ) 
447           ll = []
448           for i in range(sh.nrows):
449             thisr = sh.row(i)
450             tv = thisr[0].value
451             if tv[:10] == 'Short name':
452               ll.append(i)
453           assert len(ll) in [1,2], 'Could not parse sheet  %s, %s, %s' % (path,k,s)
454           if len(ll) == 1:
455## nt__grptbl = collections.namedtuple( 'grptbl', ['grp','var','srcTable','freq','description','shape','levels','timeProc','mask'] )
456             iv = 1
457             it = 0
458           else:
459             print '*************',k,s
460             iv = 0
461             it = -1
462             tv = sh.row(2)[1].value
463           irsh = 5
464           for i in range(ll[-1]+1,sh.nrows):
465             thisr = sh.row(i)
466             if iv == 1:
467                 ##self.ntr = nt__grptbl._make( getRowValues( thisr, minLen=9 ) + [105,k,''] )
468                lll = getRowValues( thisr, minLen=9 ) + [105,k,'']
469             else:
470                lll = getRowValues( thisr, minLen=10 ) + [k,'']
471                lll[1] = lll[0]
472                lll[0] = tv
473             if it >= 0:
474               tv = thisr[it].value
475             v = thisr[iv].value
476             bits = string.split(v, ' ')
477             if len(bits) > 1:
478               v = bits[0]
479             t = thisr[2].value
480             if t[:6] == "CMIP5_":
481               t = t[6:]
482             if len(string.split(t, ' ')) > 1:
483               t2 = string.split(t, ' ')[1]
484               t = string.split(t, ' ')[0]
485             else: 
486               t2 = None
487             if t in ['OImon','day','Omon'] and t2 != None:
488               v2 = string.strip(t2)[1:-1]
489             else:
490               v2 = None
491
492             if v == '*':
493               if t in self.cmip5sns:
494                 print 'INFO[1a]: bulk copy of external sheet %s' % t
495               elif t in ss:
496                 print 'INFO[1b]: bulk copy of internal sheet %s' % t
497
498             elif len(v) == 0 or v[0] == '#':
499               pass
500             else:
501
502               if vl3 != None:
503                 if vl3.has_key(v):
504                   id = vl3[v][7]
505                 elif v2 != None and vl3.has_key(v2):
506                   id = vl3[v2][7]
507                 else:
508                   id = None
509
510               if t in self.cmip5sns:
511                 p = 9
512                 if self.rqs.t.has_key(t):
513                   if self.rqs.t[t].vars.has_key(v):
514                     p = self.rqs.t[t].vars[v][0][1]
515                   elif v2 != None and self.rqs.t[t].vars.has_key(v2):
516                     p = self.rqs.t[t].vars[v2][0][1]
517                     ##print '%s old name for %s' % (v2,v)
518                   else:
519                     p = 8
520                 
521               else:
522                 if string.lower(t)[:3] == 'new' or t == '':
523                   p = self.nvd.get( v, [0,7] )[1]
524                   if p == 7:
525                     p = self.nvd.get( v + '!', [0,7] )[1]
526                   if p != 7:
527                     self.idx += 1
528                     id = 'mv.010.%4.4i' % self.idx
529               if id == None and p < 7:
530                  print 'WARNING[1]: no id for %s' % v
531               elif id == None:
532                  print 'WARNING[2]: no id, no variable defn for %s' % v
533               elif p > 6:
534                  print 'WARNING[3.%s]: no variable defn for %s ' % (p,v)
535               ts = string.strip(thisr[irsh].value)
536               if string.strip(tv) != '':
537                 e1['%s:%s' % (ts,p)] += 1
538
539### complete ntr and save to shelf.
540             lll[9] = p
541             self.ntr = nt__grptbl._make( lll )
542             ku = str( uuid.uuid1() )
543             lll[11] = ku
544             self.sh[ku] = tuple( lll )
545###   MIP, group, size, dictionary -- # items in each shape.
546           self.glist.append( (k, s, ll, e1) )
547
548  def run1(self,nmip=0):
549    self.cfg.ff['CMIP5'] = ['/data/work/documents/CMIP5_standard_output.xls']
550    wb = workbook( self.cfg.ff['CMIP5'][0] )
551    wb.sns.sort()
552    omit1 = [u'dims', u'general', u'other output',u'CFMIP output']
553    sns = []
554    for s in wb.sns:
555      if s not in omit1:
556        sns.append(s)
557
558    self.cmip5sns = sns[:]
559    k2 = self.cfg.ff.keys()
560    k2.sort()
561    k2.append( 'CMIP5' )
562
563    amips = ['CMIP5'] + self.mips
564    if nmip > 0 and nmip < len(amips):
565       amips = amips[:nmip]
566    for s in sns:
567     for k in amips:
568      if k in k2:
569        for fn in self.cfg.ff[k]:
570          if k == 'CMIP5':
571            path = fn
572          else:
573            path = '%s%s/%s' % (self.dir0,k,fn)
574          thisrq = self.rqs.add( k, path,s )
575          if thisrq.ok:
576            print k,path,s,thisrq.ok, thisrq.nn
577          else:
578            print k,path,s,thisrq.ok
579
580  def run2(self):
581    init=False
582    if init:
583      wbx = wbcp( '/home/martin/Documents/MIPTableSheetTemplate.xls' )
584    else:
585      wbx = wbcp( 'CMIP6_DataRequest_CMIP5changes_blank.xls' )
586
587    for s in sns:
588      keys = self.rqs.t[s].vars.keys()
589      keys.sort()
590      ##for k in keys:
591         ##print k, self.rqs.t[s].vars[k]
592      self.rqs.prep( tab=s )
593      print s, len(self.rqs.oorecs)
594      if len(self.rqs.oorecs) > 0:
595         if init:
596           wbx.copy_sheet( 0, s )
597           wbx.focus( s, old='Template' )
598         else:
599           wbx.focus( s )
600           self.rqs.showXls(wbx,r0=2,offset=0)
601   
602         for i in range( min( 5, len( self.rqs.oorecs) ) ):
603           print self.rqs.oorecs[i]
604   
605         oo = open( 'dreq2/request2_%s.csv' % s, 'w' )
606         self.rqs.show( oo, tab=s )
607         oo.close()
608
609    wbx.write( 'CMIP6_DataRequest_CMIP5changes.xls' )
610
611vl3 = {}
612wb3 = workbook( 'vlsc5b_v20150631.xls' )
613sh = wb3.book.sheet_by_name( 'Sheet1' )
614m = main()
615for i in range(sh.nrows):
616  r = map( lambda x: string.strip(str(uniCleanFunc(x.value))), sh.row(i) )
617  if len(r) < 9 or r[8] == '':
618    vl3[r[1]] = tuple( r[:8] )
619  m.shold[r[0]] = r
620
621m.run1(nmip=1)
622m.loadNewVars()
623m.groups( vl3=vl3)
624k = m.sh.keys()[4]
625print '##############################################'
626print k
627print m.sh[k]
628m.sh.close()
629m.shnv.close()
630m.shold.close()
631
632print m.idx
Note: See TracBrowser for help on using the repository browser.