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

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

fixed expts

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