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

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

experiment mapping details

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