source: CCCC/tags/0.1/comp_mip.py @ 157

Subversion URL: http://proj.badc.rl.ac.uk/svn/exarch/CCCC/tags/0.1/comp_mip.py@283
Revision 157, 10.8 KB checked in by mjuckes, 6 years ago (diff)

adding MIP table comparison code

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