source: CCCC/tags/1.2.5/ceda_cc/comp_mip.py @ 216

Subversion URL: http://proj.badc.rl.ac.uk/svn/exarch/CCCC/tags/1.2.5/ceda_cc/comp_mip.py@1241
Revision 216, 12.2 KB checked in by mjuckes, 6 years ago (diff)

updates to extractMipInfo.py

Line 
1from fcc_utils2 import mipTableScan
2from config_c4 import CC_CONFIG_DIR
3import re, os, string
4
5ml = ['CORDEX_3h', 'CORDEX_6h', 'CORDEX_Aday', 'CORDEX_day', 'CORDEX_grids', 'CORDEX_mon' ]
6ml = ['CORDEX_3h', 'CORDEX_6h', 'CORDEX_fx', 'CORDEX_day', 'CORDEX_mon', 'CORDEX_sem' ]
7newMip = 'SPECS'
8newMip = 'CORDEX'
9newMip = 'CCMI'
10ml2 = ['CMIP5_3hr', 'CMIP5_6hrPlev', 'CMIP5_Amon', 'CMIP5_cfDay', 'CMIP5_cfOff', 'CMIP5_day', 'CMIP5_grids', 'CMIP5_Lmon', 'CMIP5_OImon', 'CMIP5_Oyr',
11       'CMIP5_6hrLev', 'CMIP5_aero', 'CMIP5_cf3hr', 'CMIP5_cfMon', 'CMIP5_cfSites', 'CMIP5_fx', 'CMIP5_LImon', 'CMIP5_Oclim', 'CMIP5_Omon'] 
12ml2 = ['CMIP5_3hr', 'CMIP5_6hrPlev', 'CMIP5_Amon', 'CMIP5_cfDay', 'CMIP5_cfOff', 'CMIP5_day', 'CMIP5_grids', 'CMIP5_Lmon',
13       'CMIP5_6hrLev', 'CMIP5_aero', 'CMIP5_cf3hr', 'CMIP5_cfMon', 'CMIP5_cfSites', 'CMIP5_fx', 'CMIP5_LImon'] 
14
15cfsntab = 'cf/cf-standard-name-table.xml'
16cordex_dkrz = 'CORDEX_variables_requirement_table_upgedated-1.csv'
17cordex_dkrz = 'CORDEX_variables_requirement_table_all.csv'
18cordex_dkrz_pat = 'cordex_dkrz/CORDEX_variables_requirement_table_%s.csv'
19cordex_dkrz_pat = 'cordex_dkrz_oct/CORDEX_variables_requirement_table_%s.csv'
20re_sn = re.compile( 'entry id="(.*)"' )
21re_snax = re.compile( '</alias>' )
22re_snar = re.compile( '<entry_id>(.*)<' )
23re_sna = re.compile( 'alias id="(.*)"' )
24##alias id="atmosphere_water_vapor_content"
25##entry id="age_of_sea_ice"'
26def gen_sn_list( pathn ):
27  assert os.path.isfile( pathn ), '%s not found ' % pathn
28  inAlias = False
29  snl = []
30  snla = []
31  aliasses = {}
32  for l in open(pathn).readlines():
33    m = re_sn.findall(l )
34    if len(m) > 0:
35      for i in m:
36        snl.append( i )
37    m = re_sna.findall(l )
38    if len(m) > 0:
39      inAlias = True
40      for i in m:
41        snla.append( i )
42    if inAlias:
43      m = re_snax.findall(l )
44      if len(m) > 0:
45        inAlias = False
46      else:
47        m = re_snar.findall(l )
48        if len(m) > 0:
49          aliasses[snla[-1]] = m[0]
50          assert len(m) == 1, 'Unexpected length of results, %s [%s]' % (str(m),l)
51  ##<alias id="station_wmo_id">
52    ##<entry_id>platform_id</entry_id>
53  ##</alias>
54  return (snl,snla,aliasses)
55
56def tlist_to_dict( ll ):
57
58   ee = {} 
59   for l in ll:
60     ee[l[0]] = ( l[1], l[2] )
61   return ee
62
63class comp(object):
64
65  def __init__(self, snl, snla=None, ec1=None,tag=None):
66    self.id = 'comp'
67    self.snl = snl
68    self.snla = snla
69    self.ec1 = ec1
70    self.tag=tag
71
72
73  def comp(self, e1, e2,checkCellMethods=False,tag=None ):
74    self.tag=tag
75   
76    ##e1 = tlist_to_dict( t1 )
77    ##e2 = tlist_to_dict( t2 )
78    self.nn_sn = 0
79    thisSnl = []
80
81    checkAll = True
82    keys = e1.keys()
83    keys.sort()
84    self.nn_var = len(keys)
85    for k in keys:
86      e0 = 0
87      f2 = False
88      f3 = False
89      f4 = False
90      if e1[k][1]['standard_name'] in [None,'None']:
91        if e1[k][1].get('long_name',None) not in [None,'None']:
92          print 'WARNING[A]: standard name for %s [%s] not set' % (k,e1[k][1].get('long_name') )
93        else:
94          print 'WARNING[A]: standard name for %s not set' % k
95      else:
96        if e1[k][1]['standard_name'] not in self.snl:
97          if e1[k][1]['standard_name'] not in self.snla:
98            print 'ERROR[0]: standard name %s for %s [%s] not in snl or snla' % (e1[k][1]['standard_name'], k, e1[k][2] )
99          else:
100            print 'WARNING: standard name %s for %s not in snl' % (e1[k][1]['standard_name'], k )
101            if e1[k][1]['standard_name'] not in thisSnl:
102               thisSnl.append( e1[k][1]['standard_name'] )
103        else:
104            if e1[k][1]['standard_name'] not in thisSnl:
105               thisSnl.append( e1[k][1]['standard_name'] )
106
107      if self.ec1 != None:
108        if k not in self.ec1.keys():
109          print 'ERROR[1]: variable %s [%s] not in CORDEX variable requirements list' % (k,e1[k][2])
110          vrln = None
111        else:
112          vrln = self.ec1[k][1]
113          if e1[k][1]['long_name'] != self.ec1[k][1]:
114            f2 = True
115          if checkCellMethods: 
116            if e1[k][1]['cell_methods'] != self.ec1[k][3]:
117              if not (e1[k][1]['cell_methods']=="None" and string.strip(self.ec1[k][3]) == "time:"):
118                f3 = True
119          if checkAll: 
120            if (e1[k][1].has_key( 'positive' ) and self.ec1[k][4] == '') or ( (not e1[k][1].has_key( 'positive' )) and self.ec1[k][4] != ''):
121                f4 = True
122            elif e1[k][1].has_key( 'positive' ):
123              if e1[k][1]['positive'] != self.ec1[k][4]:
124                if not (e1[k][1]['positive']=="None" and string.strip(self.ec1[k][4]) == ""):
125                  f4 = True
126            if (e1[k][1].has_key( 'modeling_realm' ) and self.ec1[k][5] == '') or ( (not e1[k][1].has_key( 'modeling_realm' )) and self.ec1[k][5] != ''):
127                f4 = True
128            elif e1[k][1].has_key( 'modeling_realm' ):
129              if e1[k][1]['modeling_realm'] != self.ec1[k][5]:
130                if not (e1[k][1]['modeling_realm']=="None" and string.strip(self.ec1[k][5]) == ""):
131                  f4 = True
132       
133      self.nn_sn = len(thisSnl)
134      cks = ['units', 'long_name', 'standard_name']
135      suppress4B = True
136      if k in e2.keys():
137        if e1[k][1] != e2[k][1]:
138          ne1 = 0
139          nmm = []
140          for k2 in cks:
141             if e1[k][1][k2] != e2[k][1][k2]:
142                ne1 += 1
143                nmm.append(k2)
144          if ne1 > 0:
145                v1 = map( lambda x: e1[k][1][x], nmm )
146                v2 = map( lambda x: e2[k][1][x], nmm )
147                ##if k == 'clivi':
148                  ##print k, nmm, v1, v2
149                  ##print snaliasses.keys()
150                  ##print snaliasses.get(v1[0],'xxx')
151                  ##print snaliasses.get(v2[0],'xxx')
152                  ##raise
153                weakmatch = False
154                if nmm[0] == 'standard_name':
155                  if snaliasses.get(v1[0],'xxx') == v2[0] or snaliasses.get(v2[0],'xxx') == v1[0]:
156                    weakmatch = True
157                if weakmatch:
158                  print 'WARNING[4A*]: Anomaly between MIP tables: %s:: %s -- %s -- %s {%s} ' % (k, str(nmm), str(v1), str(v2), tag )
159                else:
160                  print 'ERROR[4A]: Anomaly between MIP tables: %s:: %s -- %s -- %s {%s} ' % (k, str(nmm), str(v1), str(v2), tag )
161          else:
162             if not suppress4B:
163                print 'ERROR[4B]: Anomaly between MIP tables: %s:: %s -- %s [%s]' % (k, str(e1[k][1]), str( e2[k][1] ), vrln )
164          e0 = 1
165        else:
166          ##print '%s OK -- %s -- %s' % (k,str(e1[k][1]), str( e2[k][1] ) )
167          e0 = 2
168      else:
169        ##print '%s not in table 2' % k
170        e0 = 3
171
172      xxx = k
173      if self.tag != None:
174         xxx += '[%s]' % self.tag
175      if self.ec1 != None:
176        if f2 and (e0 == 2):
177           print 'ERROR[2]: Difference between CORDEX/CMIP5 MIP tables and VR: %s:: %s [%s] --- %s' % (k,e1[k][1]['long_name'],e1[k][2], self.ec1[k][1])
178        elif f2 and (e0 == 3):
179           print 'ERROR[3]: Difference between CORDEX MIP tables and VR: %s:: %s [%s] --- %s' % (k,e1[k][1]['long_name'],e1[k][2], self.ec1[k][1])
180        elif f2:
181           print 'ERROR[5]: Difference between CORDEX MIP tables and VR %s: %s --- %s' % (xxx,e1[k][1]['long_name'], self.ec1[k][1])
182        if f3:
183           print 'ERROR[6]: Difference between CORDEX MIP tables and VR in cell_methods: %s:: %s --- %s' % (k,e1[k][1]['cell_methods'], self.ec1[k][3])
184        if f4:
185           print 'ERROR[7]: Difference between CORDEX MIP tables and VR in positive, realm: %s:: %s,%s --- %s' % (xxx,e1[k][1].get('positive','None'),e1[k][1].get('modeling_realm','None'), self.ec1[k][4:6])
186       
187base=CC_CONFIG_DIR
188print base
189snl,snla, snaliasses = gen_sn_list( os.path.join(base, cfsntab) )
190print 'Len snl = %s' % len(snl)
191
192dkrz_cordex_version = 4
193ec1 = {}
194if newMip == 'CORDEX':
195 if dkrz_cordex_version == 1:
196  ll = open( os.path.join(base, cordex_dkrz) ).readlines()
197  for l in ll[9:74]:
198    bits = string.split( l, ',' )
199    var = bits[1]
200    ln = bits[13]
201    sn = bits[14]
202    if sn not in snl + snla:
203      print 'ERROR: CORDEX DKRZ sn %s for %s not in snl/snla' % (sn, var)
204    ec1[var] = ( sn,ln)
205 elif dkrz_cordex_version == 2:
206  for tab in ['3hr','6hr','day','mon','sem','fx']:
207     ll = open( os.path.join(base, cordex_dkrz_pat % tab) ).readlines()
208     for l in ll[3:]:
209        bits = string.split( l, ',' )
210        if (tab != 'fx' and len( bits ) != 7) or (tab == 'fx' and len( bits ) != 5):
211          print 'cant safely parse %s [%s]' % (l,tab)
212#1,sund,Duration of Sunshine,duration_of_sunshine,s,sum,
213        var,ln,sn,units = bits[1:5]
214        if tab != 'fx':
215          cm,pos = bits[5:7]
216        else:
217          cm,pos = [None,None]
218        if sn not in snl + snla:
219           print 'ERROR: CORDEX DKRZ [%s] sn %s for %s not in snl/snla' % (tab,sn, var)
220        ec1[var] = ( sn,ln,units,cm,pos)
221 elif dkrz_cordex_version in [3,4]:
222  eeee = {}
223  eca = {}
224  ll = open( os.path.join(base, cordex_dkrz_pat % 'all') ).readlines()
225  for l in ll[2:]:
226        bits = string.split( string.strip(l), ',' )
227        if dkrz_cordex_version == 4:
228          bits = map( lambda x: string.strip(x, '"' ), bits)
229        if string.strip(bits[0]) == '':
230           break
231#1,sund,Duration of Sunshine,duration_of_sunshine,s,sum,
232        var,units = bits[1:3]
233        ln,sn,pos,realm   = bits[12:16]
234        if sn not in snl + snla:
235           print 'ERROR: CORDEX DKRZ [%s] sn %s for %s not in snl/snla' % ('all',sn, var)
236        assert pos in ['','up','down'], 'Unexpected value for pos [%s] in %s' % (pos,l)
237        eca[var] = ( units,ln,sn,pos,realm )
238
239  for tab in ['3hr','6hr','day','mon','sem','fx']:
240     ee  = {}
241     ll = open( os.path.join(base, cordex_dkrz_pat % tab) ).readlines()
242     for l in ll[2:]:
243        bits = string.split( l, ',' )
244        if dkrz_cordex_version == 4:
245          bits = map( lambda x: string.strip(x, '"' ), bits)
246        if string.strip(bits[0]) == '':
247           break
248#1,sund,Duration of Sunshine,duration_of_sunshine,s,sum,
249        var,cm = bits[1:3]
250        cm = 'time: ' + cm
251        units,ln,sn,pos,realm = eca[var] 
252        ec1[var] = ( sn,ln,units,cm,pos,realm)
253        ee[var] = ( sn,ln,units,cm,pos,realm)
254     eeee[tab] = ee
255
256if newMip == 'SPECS':
257  newMipDir = 'specs_vocabs/mip/'
258  mpat = 'SPECS_%s'
259  ml = ['SPECS_Amon', 'SPECS_fx', 'SPECS_Lmon', 'SPECS_Omon', 'SPECS_6hrLev', 'SPECS_day', 'SPECS_OImon']
260elif newMip == 'CCMI':
261  ml = ['CCMI1_Amon_v2_complete']
262  ml = ['CCMI1_annual_comp-v3.txt', 'CCMI1_daily_comp-v3.txt', 'CCMI1_fixed_comp-v2.txt', 'CCMI1_hourly_comp-v3.txt', 'CCMI1_monthly_comp-v3.txt']
263  ml = ['CCMI1_annual', 'CCMI1_daily', 'CCMI1_fixed', 'CCMI1_hourly', 'CCMI1_monthly']
264  mpat = 'CCMI1_%s_v1_complete'
265  newMipDir = 'ccmi1-cmor-tables/Tables/'
266  newMipDir = 'ccmi_vocabs/mip/'
267elif newMip == 'CORDEX':
268  newMipDir = 'cordex_vocabs/mip/'
269  mpat = 'CORDEX_%s'
270
271def validate( t,cc ):
272  if t == 'all':
273    l1 = {}
274    l2 = {}
275    for m in ml:
276      print 'base: ',base
277      l1 = ms.scan_table( open( os.path.join(base, newMipDir + m) ).readlines(), None, asDict=True, appendTo=l1, lax=True, tag=m, project=newMip)
278    ms.nn_tab = len(ml)
279    for m in ml2:
280      l2 = ms.scan_table( open( os.path.join(base, 'cmip5_vocabs/mip/' + m) ).readlines(), None, asDict=True, appendTo=l2, lax=True, tag=m, warn=False)
281    ms.nn_tab2 = len(ml2)
282    ccm = False
283    tag = " vs. cmip5"
284  else:
285    l2 = {}
286    for m in ml2:
287      l2 = ms.scan_table( open( os.path.join(base, 'cmip5_vocabs/mip/' + m) ).readlines(), None, asDict=True, appendTo=l2, lax=True, tag=m, warn=False)
288    k = { '3hr':'3h', '6hr':'6h' }.get( t,t )
289    l1 = ms.scan_table( open( os.path.join(base, newMipDir + mpat % k) ).readlines(), None, asDict=True, project=newMip)
290    ccm = True
291    tag = t
292  cc.comp( l1, l2, checkCellMethods=ccm, tag=tag )
293
294tlist = ['3hr','6hr','day','mon','sem','fx']
295tlist = ['Amon']
296tlist = ['Amon', 'fx', 'Lmon', 'Omon', '6hrLev', 'day', 'OImon']
297doAll = True
298if doAll:
299    ms = mipTableScan()
300    ec1 = None
301    c = comp( snl,snla=snla, ec1=ec1)
302    validate('all',c)
303    print """Number of tables=%s\nNumber of variables=%s\nNumber of standard names=%s\n""" % (ms.nn_tab,c.nn_var,c.nn_sn)
304    print ms.al
305else:
306  for tab in tlist:
307    ms = mipTableScan()
308    print 'Validating table %s ' % tab
309    if newMip in ['CCMI','SPECS']:
310      ec1 = None
311    else:
312      ec1=eeee[tab]
313      print eeee[tab].keys()
314    c = comp( snl,snla=snla, ec1=ec1)
315    validate(tab,c)
Note: See TracBrowser for help on using the repository browser.