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

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

localise data input

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