source: CMIP6dreqbuild/trunk/src/framework/ingest/expts.py @ 1027

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

cand

Line 
1import utils_wb
2import os
3import json, re, collections, string
4import sys
5##sys.path.append( <path to dirFoo> )
6sys.path.insert(0, '../dreqPy/' )
7##from dreqPy import dreq
8import dreq
9
10import exptMaps as em
11
12fmip = re.compile( '([a-zA-Z0-9]{1,10}MIP|DCPP)' )
13EXPTFILE='/data/tmp/svn3/exarch/CMIP6dreqbuild/trunk/src/framework/ingest/CMIP6_Experiments_v50.xlsx'
14EXPTFILE='/data/work/tmp/git/esdoc-docs/cmip6/experiments/spreadsheet/experiments.xlsx'
15## experiments sheet copied and pasted to resolve internal references.
16EXPTFILE='CMIP6_experiments_esdoc_190517.xlsx'
17
18class ktEx(object):
19  ##def __init__(self, file='/data/work/tmp/git/CMIP6_CVs/CMIP6_experiment_id.json' ):
20  def __init__(self, file='CMIP6_experiment_id.json' ): 
21    assert os.path.isfile( file ),'File %s not found' % file
22    ex = json.load( open( file ) )
23    ##self.expts = ex['CV']['experiment_ids']
24    self.expts = ex['experiment_id']
25    self.mip = {}
26    for k in self.expts:
27      m0 = self.expts[k]['activity_id'][0]
28      m = fmip.match( m0 )
29      assert m != None, 'No activity for experiment %s' % k
30      self.mip[k] = m.groups()[0]
31
32class esdocEx(object):
33  def __init__(self,file=EXPTFILE ):
34    assert os.path.isfile( file ),'File %s not found' % file
35    self.wb = utils_wb.workbook( file )
36    self.load()
37
38  def parseTempCon( self, tcon ):
39    if tcon[-14:] == 'yrsAfterSpinUp':
40      return int( tcon[:-14] )
41    if tcon[-3:] != 'yrs':
42      if tcon == '1790-1858':
43        return 68
44      else:
45        print 'SEVERE: badly formatted time constraint: ',tcon,self.rown,self.experiment
46        return 0
47    elif tcon == '2014-present N yrs':
48      return 4
49    else:
50      t1 = tcon[:-3].strip()
51      if t1.find( ' ' ) != -1:
52        t1 = t1.split( ' ' )[-1]
53      if t1.find( '.' ) != -1:
54        return float( t1 )
55      return int (t1 )
56
57  def load(self):
58    sht = self.wb.book.sheet_by_name( 'experiment' )
59    cc = {}
60    self.alias = {}
61    self.edesc = {}
62    self.dn = []
63    self.mip = {}
64    for i in range(2,sht.nrows):
65      self.rown = i
66      r = [x.value for x in sht.row(i)]
67      if r[0] != '':
68       en = r[2]
69       des = r[5]
70       self.edesc[en] = des
71       self.experiment = en
72       if en.strip() not in [ 'N/A', 'n/a', '', ' ']:
73        tcon = r[30]
74        nyrs = self.parseTempCon( tcon )
75        m = fmip.match( r[0] )
76        if m != None:
77          mip = m.groups()[0]
78        else:
79          mip = '---'
80        if en in cc:
81          print 'SEVERE:  DUPLICATE EXPERIMENT NAME (ES-DOC): %s::\n %s\n ----- \n%s ' % (en,str(cc[en]),str(r))
82          self.dn.append(en)
83        cc[en] = r
84        self.mip[en] = mip
85        if r[3] != '':
86          onms = r[3].split( ',' )
87          self.alias[r[2]] = set( onms )
88
89    ee = {}
90    for x in set(self.dn):
91      ee[x] = cc.pop(x)
92    self.expts = cc
93    self.exptsDup = ee
94
95    print '%s records scanned' % len(cc.keys() )
96    print self.dn
97
98esDcppMap1 = [u'dcppC-amv-extrop-minus', u'dcppC-amv-extrop-plus', u'dcppC-amv-minus', u'dcppC-amv-plus', u'dcppC-amv-trop-minus', u'dcppC-amv-trop-plus', u'dcppC-ipv-minus', u'dcppC-ipv-plus', u'dcppC-pac']
99ktDcppMap1 = [u'dcppC-amv-ExTrop-neg', u'dcppC-amv-ExTrop-pos', u'dcppC-amv-neg', u'dcppC-amv-pos', u'dcppC-amv-Trop-neg', u'dcppC-amv-Trop-pos',  u'dcppC-ipv-neg', u'dcppC-ipv-pos', u'dcppC-pac-control']
100
101lMaps = { 
102         'piClim-histaerO3':'piClim-histaer03',
103         'land-fut':'land-future',
104         u'dcppC-forecast-addAgung':'forecast-Agung',
105         u'dcppC-forecast-addElChichon':u'forecast-ElChichon',
106         u'dcppC-forecast-addPinatubo':u'forecast-Pinatubo',
107         u'dcppC-amv-trop-minus':'amv-minus-trop',
108         u'dcppC-amv-trop-plus':'amv-plus-trop',
109         u'ssp126-ssp37Lu':u'ssp126-ssp370Lu',
110         u'ssp37-ssp126Lu':u'ssp370-ssp126Lu'}
111
112for i in range( len( esDcppMap1 ) ):
113   lMaps[esDcppMap1[i]] = ktDcppMap1[i]
114
115rqMaps = {}
116for k in em.exptMap:
117  for i in em.exptMap[k]:
118    assert i not in rqMaps
119    rqMaps[i] = em.exptMap[k][i]
120
121class request(object):
122  def __init__(self,xc):
123    dq = dreq.loadDreq()
124    self.mapped = set()
125    self.mappedbymip = collections.defaultdict( set )
126    self.missing = set()
127    self.incomplete = set()
128    self.used = set()
129    self.ok = set()
130    cc = collections.defaultdict( list )
131    for k in rqMaps:
132      assert k not in xc.mapToKt
133      xc.mapToKt[k] = rqMaps[k]
134    for i in dq.coll['experiment'].items:
135      if i.label not in xc.mapToKt:
136        if i.label in xc.kt.expts:
137          self.incomplete.add( i.label )
138          self.used.add( i.label )
139        else:
140          self.missing.add( i.label )
141          cc[i.mip].append( i.label )
142      else:
143        self.used.add( xc.mapToKt[i.label] )
144        if xc.mapToKt[i.label] != i.label:
145          self.mapped.add(i.label)
146          self.mappedbymip[i.mip].add((i.label,xc.mapToKt[i.label]))
147        else:
148          self.ok.add( i.label )
149    print '%s experiments: %s ok, %s mapped, %s unknown: ' % (len( dq.coll['experiment'].items ), len(self.ok), len( self.mapped), len( self.missing) )
150    print 'Request experiments not found: %s' % (len(self.missing) )
151    ccu = collections.defaultdict( list )
152    for k in xc.kt.expts:
153      if k not in self.used:
154        ccu[xc.kt.mip[k]].append( k )
155    for m in sorted( cc.keys() ):
156      print 'UNMATCHED: %s: %s' % (m, sorted( cc[m] ) )
157      if m in ccu:
158        print '--- UNUSED: %s' % (sorted( ccu[m] ) )
159    for m in sorted( self.mappedbymip.keys() ):
160      print 'MAPPED: %s:: %s' % (m,sorted( list(self.mappedbymip[m])))
161
162
163class checker(object):
164  def __init__(self):
165    self.es = esdocEx()
166    self.kt = ktEx()
167  def xcheck(self):
168    es = self.es
169    kt = self.kt
170    nf = []
171    matchByOther = {}
172    lcMatch = {}
173    pMatch = {}
174    mMatch = {}
175    s0 = set()
176    for k in es.expts:
177      if k in kt.expts:
178        s0.add(k)
179      else:
180        done = False
181        if k in es.alias:
182          s1 = [o for o in es.alias[k] if o in kt.expts]
183          assert len(s1) <= 1, 'Multiple aliases found for %s%s' % (k, str(s1) )
184          if len(s1) != 0:
185            matchByOther[k] = s1[0]
186            done = True
187        if not done:
188          if k[:4] == 'dcpp':
189            k1 = string.split(k,'-',maxsplit=1)[-1]
190            if k1 in kt.expts:
191              pMatch[k] = k1
192              done = True
193          if k in lMaps:
194            if lMaps[k] in kt.expts:
195              mMatch[k] = lMaps[k]
196              done = True
197        if not done:
198            nf.append( k )
199    print '%s ES-DOC experiments not found in PCMDI experiment CV' % len(nf)
200    print sorted( nf )
201    self.nf = nf
202
203    nf2 = []
204    for k in kt.expts:
205      if k not in es.expts:
206        nf2.append( k )
207    print '%s experiments not found in ES-DOC experiment list' % len(nf2)
208    print sorted( nf2 )
209    self.nf2 = nf2
210
211    ee = {}
212    ee2 = {}
213    for x in nf:
214      ee[x.lower()] = x
215    for x in nf2:
216      ee2[x.lower()] = x
217
218    s = set()
219    for x in ee:
220      if x in ee2:
221        lcMatch[ee[x]] = ee2[x]
222        s.add( ee2[x] )
223
224    rf = [x for x in nf if x not in lcMatch]
225    print 'Lower case matches: %s' % str( lcMatch )
226    print 'Mapped matches (PCMDI->ES-DOC) [%s]: %s' % (len(mMatch.keys()),str( mMatch ))
227    print '%s ESDOC experiments not found in PCMDI experiment CV after lc' % len(rf)
228    print '%s straight matches [%s,%s]' % (len(s0),len(es.expts),len(kt.expts))
229    indMatch = set()
230    for x in matchByOther, lcMatch, pMatch, mMatch:
231      for k in x:
232        indMatch.add( x[k] )
233    rf2 = [x for x in nf2 if x not in indMatch]
234    print '%s PCMDI experiments not found in ES-DOC experiment list indirect matches [%s]' % (len(rf2), len(set(rf2)))
235    cc = collections.defaultdict( set )
236    print ' ----- IN ES-DOC ONLY: '
237    for k in rf:
238      cc[ es.mip[k] ].add( k )
239    cc2 = collections.defaultdict( set )
240    for k in rf2:
241      cc2[ kt.mip[k] ].add( k )
242    for m in sorted( list (cc.keys() ) ):
243      print m, '[ES-DOC]', sorted( list( cc[m] ) )
244      if m in cc2:
245          print m, '[PCMDI]', sorted( list( cc2[m] ) )
246    for m in cc2:
247      if m not in cc:
248          print m, '[PCMDI]', sorted( list( cc2[m] ) )
249
250    self.mapToKt = {}
251    for x in (matchByOther, lcMatch, pMatch, mMatch):
252      for k in x:
253        self.mapToKt[k] = x[k]
254    for k in s0:
255      self.mapToKt[k] = k
256    for k in es.alias:
257      if k in self.mapToKt:
258        for x in es.alias[k]:
259          self.mapToKt[x] = self.mapToKt[k]
260     
261    return es, kt, matchByOther, lcMatch, pMatch, mMatch, rf , s0
262
263xc = checker()
264
265es,kt, mo, lcm, pm, mm, rf, s0 = xc.xcheck()
266rq = request( xc )
267sa = set()
268for x in  mo, lcm, pm, mm, rf, s0:
269  print len(x)
270  for k in x:
271    sa.add( k )
272print len(sa)
273kk = {k for k in es.expts if k not in sa}
274print kk
275print 'ESDOC expts: %s [%s]' % (len(es.expts),len(kk))
276if len(mo.keys()) > 0:
277  print '%s matches through other name: ' % len( mo.keys())
278  print mo
279if len(lcm.keys()) > 0:
280  print '%s lower case matches' % len( lcm.keys())
281  print lcm
282if len(pm.keys()) > 0:
283  print '%s part matches' % len( pm.keys())
284  print pm
285if len(mm.keys()) > 0:
286  print '%s mapped matches' % len( mm.keys())
287  print mm
288
289ee = {}
290for k in rq.mapped:
291  ##if k not in xc.kt.expts:
292    ee[k] = xc.mapToKt[k]
293for k in mm:
294  ee[k] = mm[k]
295for k in lcm:
296  ee[k] = lcm[k]
297oo = open( 'exptNameMaps.json', 'w' )
298json.dump( {'info':{'title':'Updating experiment names in data request'}, 'maps':ee}, oo, indent=4, sort_keys=True )
299oo.close()
300oo = open( 'exptDesc.json', 'w' )
301json.dump( {'info':{'title':'Updating experiment descriptions from ESDOC'}, 'maps':xc.es.edesc}, oo, indent=4, sort_keys=True )
302oo.close()
303
304
305## from PCMDI github ...
Note: See TracBrowser for help on using the repository browser.