source: CCCC/trunk/ceda_cc/config_c4.py @ 869

Subversion URL: http://proj.badc.rl.ac.uk/svn/exarch/CCCC/trunk/ceda_cc/config_c4.py@869
Revision 869, 26.5 KB checked in by mjuckes, 3 years ago (diff)

added option to specify files in a text file, one file name per line

Line 
1"""config_c4
2##########
3USAGE:
4import config_c4
5
6This module sets some basic variables, including some vocabulary lists.
7"""
8import string
9import utils_c4 as utils
10import os
11import os.path as op
12import shutil, collections
13from versionConfig import version, versionComment
14
15NT_project = collections.namedtuple( 'project', ['id','v'] )
16NT_fnParts = collections.namedtuple( 'fnParts', ['len','fxLen','unfLen','checkTLen','ixDomain','ixFreq'] )
17
18##############################################################################
19# Configure config-file paths
20#
21# All configuration directories, e.g. cmip5_vocabs, are looked for in a single
22# parent directory.  This is the "config" directory within the package unless
23# the environment variable CC_CONFIG_DIR is set.
24
25HERE = op.dirname(__file__)
26CC_CONFIG_DEFAULT_DIR = op.join(HERE, 'config')
27CC_CONFIG_DIR = os.environ.get('CC_CONFIG_DIR', CC_CONFIG_DEFAULT_DIR)
28
29##############################################################################
30
31validCmip5Experiments = ['1pctCO2', 'abrupt4xCO2', 'amip', 'amip4K', 'amip4xCO2', 'amipFuture', 'aqua4K', 'aqua4xCO2', 'aquaControl', 'decadal1959', 'decadal1960', 'decadal1961', 'decadal1962', 'decadal1963', 'decadal1964', 'decadal1965', 'decadal1966', 'decadal1967', 'decadal1968', 'decadal1969', 'decadal1970', 'decadal1971', 'decadal1972', 'decadal1973', 'decadal1974', 'decadal1975', 'decadal1976', 'decadal1977', 'decadal1978', 'decadal1979', 'decadal1980', 'decadal1981', 'decadal1982', 'decadal1983', 'decadal1984', 'decadal1985', 'decadal1986', 'decadal1987', 'decadal1988', 'decadal1989', 'decadal1990', 'decadal1991', 'decadal1992', 'decadal1993', 'decadal1994', 'decadal1995', 'decadal1996', 'decadal1997', 'decadal1998', 'decadal1999', 'decadal2000', 'decadal2001', 'decadal2002', 'decadal2003', 'decadal2004', 'decadal2005', 'decadal2006', 'decadal2007', 'decadal2008', 'decadal2009', 'decadal2010', 'decadal2011', 'decadal2012', 'esmControl', 'esmFdbk1', 'esmFdbk2', 'esmFixClim1', 'esmFixClim2', 'esmHistorical', 'esmrcp85', 'historical', 'historicalExt', 'historicalGHG', 'historicalMisc', 'historicalNat', 'lgm', 'midHolocene', 'noVolc1960', 'noVolc1965', 'noVolc1970', 'noVolc1975', 'noVolc1980', 'noVolc1985', 'noVolc1990', 'noVolc1995', 'noVolc2000', 'noVolc2005', 'past1000', 'piControl', 'rcp26', 'rcp45', 'rcp60', 'rcp85', 'sst2020', 'sst2030', 'sst2090', 'sst2090rcp45', 'sstClim', 'sstClim4xCO2', 'sstClimAerosol', 'sstClimSulfate', 'volcIn2010']
32
33validCordexExperiment = validCmip5Experiments + ['evaluation']
34
35
36validCmip5Frequencies = ['fx','yr','monClim','mon','day','6hr','3hr','subhr']
37validCordexFrequencies = ['fx','sem','mon','day','6hr','3hr']
38validSpecsFrequencies = ['fx','mon','day','6hr']
39validCcmiFrequencies = ['fx','yr','mon','day','hr','subhr']
40validSpecsExptFamilies = map( lambda x: string.strip( x ), 
41                              open( op.join(CC_CONFIG_DIR, 'specs_vocabs/exptFamily.txt' )).readlines() )
42
43validCordexDomainsL = [ 'SAM-44', 'CAM-44', 'NAM-44', 'EUR-44', 'AFR-44', 'WAS-44', 'EAS-44', 'CAS-44', 'AUS-44', 'ANT-44', 'ARC-44', 'MED-44']
44validCordexDomainsLi = map( lambda x: x + 'i', validCordexDomainsL )
45validCordexDomainsH = ['EUR-11']
46validCordexDomains = validCordexDomainsL + validCordexDomainsLi + validCordexDomainsH
47
48plevRequired = ['clh', 'clm', 'cll', 'ua850', 'va850', 'ta850', 'hus850', 'ua500', 'va500', 'ta500', 'zg500', 'ua200', 'va200', 'ta200', 'zg200']
49plevBndsRequired = ['clh', 'clm', 'cll']
50heightRequired = ['tas','tasmax','tasmin','huss','sfcWind','sfcWindmax','wsgsmax','uas','vas']
51
52
53ii = open( op.join(CC_CONFIG_DIR, 'cordex_vocabs/GCMModelName.txt' )).readlines()
54validGcmNames = []
55for l in ii:
56  if l[0] != '#' and len( string.strip(l) ) > 0:
57    validGcmNames.append( string.split(l)[0] )
58
59ii = open( op.join(CC_CONFIG_DIR, 'cordex_vocabs/RCMModelName.txt' )).readlines()
60validRcmNames = []
61validInstNames = []
62for l in ii:
63  if l[0] != '#' and len( string.strip(l) ) > 0:
64    bits = string.split(l)
65    validRcmNames.append( bits[0] )
66    validInstNames.append( bits[1] )
67
68plevValues = {'clh':22000, 'clm':56000, 'cll':84000}
69for i in [200,500,850]:
70  for v in ['zg','ua', 'va', 'ta', 'hus']:
71    k = '%s%s' % (v,i)
72    plevValues[k] = i*100
73
74heightRequired = ['tas', 'tasmax', 'tasmin', 'huss', 'sfcWind', 'sfcWindmax', 'wsgsmax', 'uas', 'vas']
75heightValues = {}
76heightRange = {}
77for v in heightRequired:
78  if v in ['tas', 'tasmax', 'tasmin', 'huss']:
79    heightValues[v] = 2
80  else:
81    heightValues[v] = 10
82  heightRange[v] = (1.5,10.)
83
84ii = open( op.join(CC_CONFIG_DIR, 'cordex_vocabs/cordex_domains.csv' )).readlines()
85keys = ['name','tag','res','grid_np_lon','grid_np_lat','nlon','nlat','w','e','s','n']
86rotatedPoleGrids = {}
87for l in ii[2:16]:
88  bits = string.split(string.strip(l),',')
89  ee = {}
90  i = 0
91  for k in keys:
92    if k in ['nlon','nlat']:
93      ee[k] = int(bits[i])
94    elif k in ['grid_np_lon','grid_np_lat','w','e','s','n','res']:
95      if bits[i] != 'N/A':
96        ee[k] = float(bits[i])
97      else:
98        ee[k] = bits[i]
99    else:
100      ee[k] = bits[i]
101    i += 1
102    rotatedPoleGrids[bits[1]] = ee
103
104##Area,Name, deg,Nlon,Nlat,West8,East8,South8,North8,
105keys = ['name','tag','res','nlon','nlat','w','e','s','n']
106interpolatedGrids = {}
107for l in ii[18:33]:
108  bits = string.split(string.strip(l),',')
109  ee = {}
110  i = 0
111  for k in keys:
112    if k in ['nlon','nlat']:
113      ee[k] = int(bits[i])
114    elif k in ['w','e','s','n','res']:
115        ee[k] = float(bits[i])
116    else:
117      ee[k] = bits[i]
118    i += 1
119    interpolatedGrids[bits[1]] = ee
120
121class readVocab(object):
122  """readVocab:
123  A general class to read in vocabulary lists ("code lists" in ISO 19115 terminology) from a variety of structured text files.
124  """
125
126  def __init__(self,dir):
127    self.dir = dir
128
129  def driver(self,tt):
130    if tt[0] == "simpleList":
131      tx = tt + (None,None,None,None)
132      return self.getSimpleList( tx[1],bit=tx[2],omt=tx[3],options=tx[4] )
133    else:
134      print 'readVocab.driver: option %s not recgnised' % tt[0]
135
136  def getEvalAssign(self, file ):
137    ii = open('%s/%s/%s' % (CC_CONFIG_DIR, self.dir,file) )
138    ll = []
139    for l in ii.readlines():
140      if l[0] != '#':
141        ll.append( l )
142    assert len(ll) == 1, 'Too many lines in %s' % file 
143    try:
144      return eval( ll[0] )
145    except:
146      print 'Failed to evaluate configuration line from %s:\n%s' % (file,l[0])
147      raise
148
149  def getSimpleList(self,file,bit=None,omt=None,options=None):
150    ii = open('%s/%s/%s' % (CC_CONFIG_DIR, self.dir,file) )
151    oo = []
152    if options == None:
153      olist = []
154    else:
155      olist = string.split(options,',')
156
157    if 'returnMappings' in olist:
158      assert bit in [0, -1], 'only support returnMappings for bit = -1 or 0'
159      ee = {}
160
161    for l in ii.readlines():
162      if l[0] != '#':
163        ll = string.strip(l)
164        if omt == 'last':
165          oo.append(string.join(string.split(ll)[:-1]))
166        elif bit == None:
167          oo.append(ll)
168        else:
169          if 'returnMappings' in olist:
170            bb = string.split(ll)
171            if bit == -1:
172              ee[bb[-1]] = string.join( bb[:-1] )
173            else:
174              ee[bb[0]] = string.join( bb[1:] )
175            oo.append( bb[bit] )
176          else:
177            oo.append(string.split(ll)[bit])
178
179    if 'noneMap' in olist:
180      oo = map( lambda x: {'None':None}.get(x,x), oo )
181
182    if 'returnMappings' in olist:
183      return oo, ee
184    else:
185      return oo
186
187validSpecsInstitutions = ['IC3', 'MPI-M', 'KNMI', 'UOXF', 'CNRM-CERFACS', 'ENEA', 'MOHC', 'SMHI', 'IPSL', 'UREAD', 'ECWMF']
188
189class projectConfig(object):
190  """projectConfig:
191  Set project specific configuration options.
192 
193  USAGE
194  =====
195  pcfg = projectConfig( <project id>[, version=..] )
196
197  Creates a "pcfg" object which contains attributes used in the code, including vocabulary lists.
198  """
199
200  def __init__(self, project, version=-1):
201    knownProjects = ['CMIP5','CCMI','CORDEX','SPECS','ESA-CCI', '__dummy']
202    assert project in knownProjects, 'Project %s not in knownProjects %s' % (project, str(knownProjects))
203
204    self.project = project
205    self.fNameSep = '_'
206    self.varIndex = 0
207    self.fnvdict = None
208    self.varTables='CMIP'
209    self.checkVarType = True
210    self.projectV = NT_project(project,version)
211    self.gridSpecTol = 0.01
212## default encoding of time range in file names: YYYY[MM[DD[HH]]]-YYYY[MM[DD[HH]]]
213    self.trangeType = 'CMIP'
214    self.controlledFnParts = []
215    if project == 'CORDEX':
216      self.requiredGlobalAttributes = [ 'institute_id', 'contact', 'rcm_version_id', 'product', 'CORDEX_domain', 'creation_date', \
217             'frequency', 'model_id', 'driving_model_id', 'driving_experiment', 'driving_model_ensemble_member', 'experiment_id']
218      self.controlledGlobalAttributes = ['frequency', 'driving_experiment_name', 'project_id', 'CORDEX_domain', 'driving_model_id', 'model_id', 'institute_id','driving_model_ensemble_member','rcm_version_id']
219      self.globalAttributesInFn = [None,'CORDEX_domain','driving_model_id','experiment_id','driving_model_ensemble_member','model_id','rcm_version_id']
220      self.requiredVarAttributes = ['long_name', 'standard_name', 'units']
221      self.drsMappings = {'variable':'@var','institute':'institute_id', 'product':'product', 'experiment':'experiment_id', \
222                        'ensemble':'driving_model_ensemble_member', 'model':'model_id', 'driving_model':'driving_model_id', \
223                        'frequency':'frequency', \
224                        'project':'project_id', 'domain':'CORDEX_domain', 'model_version':'rcm_version_id' }
225
226    elif project == 'SPECS':
227      lrdr = readVocab( 'specs_vocabs/')
228      self.requiredGlobalAttributes = lrdr.driver( ('simpleList', 'globalAts.txt' ) )
229      self.exptFamilies = lrdr.driver( ('simpleList', 'exptFamily.txt', 0 ) )
230      self.validInstitutions = lrdr.driver( ('simpleList', 'validInstitutions_sv0101.txt' ) )
231      self.realm = lrdr.driver( ('simpleList', 'realm_sv0101.txt' ) )
232      self.controlledGlobalAttributes = lrdr.driver( ('simpleList', 'controlledGlobalAttributes_sv0101.txt' ) )
233                       ##'initialization_method','physics_version','realization']
234      self.globalAttributesInFn = lrdr.driver( ('simpleList', 'globalAttributesInFn_sv0101.txt',None,None,'noneMap' ) )
235      self.requiredVarAttributes = ['long_name', 'standard_name', 'units']
236      oo, self.drsMappings = lrdr.driver( ('simpleList', 'drsMappings_sv0101.txt',0,None,'returnMappings' ) )
237
238      ##self.drsMappings = {'variable':'@var', 'institute':'institute_id', 'product':'product', 'experiment':'experiment_id', \
239                        ##'ensemble':'@ensemble', 'model':'model_id', 'realm':'modeling_realm', \
240                        ##'frequency':'frequency', 'start_date':'@forecast_reference_time', \
241                        ##'table':'@mip_id',
242                        ##'project':'project_id'}
243
244    elif project == 'CMIP5':
245      lrdr = readVocab( 'cmip5_vocabs/')
246      self.requiredGlobalAttributes = [ 'contact', 'product', 'creation_date', 'tracking_id', \
247              'experiment_id']
248      ##self.requiredGlobalAttributes = lrdr.getSimpleList( 'globalAts.txt' )
249      self.controlledGlobalAttributes = [ 'project_id','experiment_id', 'frequency','Conventions','modeling_realm', \
250                       'initialization_method','physics_version','realization']
251      self.globalAttributesInFn = [None,'@mip_id','model_id','experiment_id','@ensemble']
252#sic_Oimon_EC-Earth2_seaIceBestInit_S19910501_series1_r1i1p1_199501-199502.nc
253## mip_id derived from global attribute Table_id (CMOR convention); experiment family derived from experiment_id, ensemble derived from rip attributes.
254      self.requiredVarAttributes = ['long_name', 'standard_name', 'units']
255## key: DRS element name, value: global attribute name or tag for mapping from file information ("@....").
256      self.drsMappings = {'variable':'@var', 'institute':'institute_id', 'product':'product', 'experiment':'experiment_id', \
257                        'ensemble':'@ensemble', 'model':'model_id', 'realm':'modeling_realm', \
258                        'frequency':'frequency',  'table':'@mip_id',
259                        'project':'project_id'}
260
261    elif project == 'CCMI':
262      lrdr = readVocab( 'ccmi_vocabs/')
263      self.requiredGlobalAttributes = [ 'creation_date', 'tracking_id', 'forcing', 'model_id', 'parent_experiment_id', 'parent_experiment_rip', 'branch_time', 'contact', 'institute_id' ]
264      self.requiredGlobalAttributes = lrdr.getSimpleList( 'globalAts.txt', bit=0 )
265      self.controlledGlobalAttributes = [ 'experiment_id', 'project', 'frequency' ]
266      self.globalAttributesInFn = [None,'@mip_id','model_id','experiment_id','@ensemble']
267      self.requiredVarAttributes = ['long_name', 'units']
268      self.drsMappings = {'variable':'@var', 'institute':'institute_id', 'product':'product', 'experiment':'experiment_id', \
269                        'ensemble':'@ensemble', 'model':'model_id', 'realm':'modeling_realm', \
270                        'frequency':'frequency',  'table':'@mip_id',
271                        'project':'project_id'}
272
273    elif project == 'ESA-CCI':
274      lrdr = readVocab( 'esacci_vocabs/')
275      self.varTables='FLAT'
276      self.fNameSep = '-'
277      self.checkVarType = False
278      self.requiredGlobalAttributes = lrdr.getSimpleList( 'requiredGlobalAts.txt', bit=0 )
279      self.controlledGlobalAttributes = ['platform','sensor','project','Conventions','institution','cdm_data_type','time_coverage_duration','spatial_resolution' ]
280      self.controlledFnParts = ['level','cciProject','var','version']
281      self.requiredVarAttributes = ['long_name', 'standard_name', 'units']
282      self.drsMappings = {'variable':'#var','platform':'platform','sensor':'sensor','level':'#level', \
283                'standard_name':'*standard_name', \
284                'activity':'=CLIPC', \
285                'algorithm':'$algorithm:unset', 'frequency':'$frequency', \
286                'spatial_resolution':'spatial_resolution', 'ecv':'@ecv','version':'#version','convention_version':'#gdsv'}
287      self.globalAttributesInFn = [None,]
288    elif project == '__dummy':
289      self.requiredGlobalAttributes = map( lambda x: 'ga%s' % x, range(10) )
290      self.controlledGlobalAttributes = [ ]
291      self.globalAttributesInFn = [None,'ga2', 'ga3', 'ga4' ]
292      self.requiredVarAttributes = ['long_name', 'standard_name', 'units']
293      self.drsMappings = {'variable':'@var'}
294
295####### used in checkStandardDims
296
297    self.plevRequired = plevRequired
298    self.plevValues = plevValues
299    self.heightRequired = heightRequired
300    self.heightValues = heightValues
301    self.heightRange = heightRange
302
303####### used in checkGrids
304    self.rotatedPoleGrids = rotatedPoleGrids
305    self.interpolatedGrids = interpolatedGrids
306    self.doCheckGrids = self.projectV.id in ['CORDEX',]
307
308####### used in checkFileName (freqIndex also used in checkByVar)
309
310    if self.projectV.id == 'CORDEX':
311      self.fnParts = NT_fnParts( len=[8,9], fxLen=[8,],  unfLen=[9,], checkTLen=True, ixDomain=1, ixFreq=7 )
312    elif self.projectV.id == 'CMIP5':
313      self.fnParts = NT_fnParts( len=[5,6], fxLen=[5,],  unfLen=[6,], checkTLen=False, ixDomain=None, ixFreq=None )
314    elif self.projectV.id == 'SPECS':
315      self.fnParts = lrdr.getEvalAssign( 'fnParts_sv0101.txt' )
316    elif self.projectV.id == 'CCMI':
317      self.fnParts = NT_fnParts( len=[5,6], fxLen=[5,],  unfLen=[6,], checkTLen=False, ixDomain=None, ixFreq=None )
318    elif self.projectV.id == 'ESA-CCI':
319      self.fnParts = NT_fnParts( len=[7,8,9], fxLen=[0,],  unfLen=[7,8,9,], checkTLen=False, ixDomain=None, ixFreq=None )
320      self.trangeType = 'ESA-CCI'
321    elif self.projectV.id == '__dummy':
322      self.fnParts = NT_fnParts( len=[4,5], fxLen=[4,],  unfLen=[5,], checkTLen=False, ixDomain=None, ixFreq=1 )
323
324    self.fnPartsOkLen = self.fnParts.len
325    self.fnPartsOkFixedLen = self.fnParts.fxLen
326    self.fnPartsOkUnfixedLen = self.fnParts.unfLen
327    self.checkTrangeLen = self.fnParts.checkTLen
328    self.domainIndex = self.fnParts.ixDomain
329    self.freqIndex = self.fnParts.ixFreq
330
331
332    self.defaults = { 'variableDataType':'float' }
333######## used in mipVocabs
334    if self.projectV.id == 'CORDEX':
335       self.mipVocabDir = op.join(CC_CONFIG_DIR, 'cordex_vocabs/mip/')
336       self.mipVocabTl = ['fx','sem','mon','day','6h','3h']
337       self.mipVocabVgmap = {'6h':'6hr','3h':'3hr'}
338       self.mipVocabFnpat = 'CORDEX_%s'
339    elif self.projectV.id == 'CMIP5':
340       self.mipVocabDir = op.join(CC_CONFIG_DIR, 'cmip5_vocabs/mip/')
341       self.mipVocabTl = ['fx','Oyr','Oclim','Omon','Amon','Lmon','LImon','OImon','cfMon','aero','cfDay','day','cfOff','cfSites','6hrLev','6hrPlev','3hr','cf3hr']
342       self.mipVocabVgmap = {}
343       self.mipVocabFnpat = 'CMIP5_%s'
344       self.defaults['variableDataType'] = None 
345    elif self.projectV.id == 'SPECS':
346       self.mipVocabDir = op.join(CC_CONFIG_DIR, 'specs_vocabs/mip/')
347       self.mipVocabTl = ['fx','Omon','Amon','Lmon','OImon','day','6hr']
348       self.mipVocabVgmap = {}
349       self.mipVocabFnpat = 'SPECS_%s'
350    elif self.projectV.id == 'CCMI':
351       self.mipVocabDir = op.join(CC_CONFIG_DIR, 'ccmi_vocabs/mip/')
352       self.mipVocabTl = ['fixed','annual','monthly','daily','hourly','satdaily']
353       self.mipVocabVgmap = {'fixed':'fx','annual':'yr','monthly':'mon','daily':'day','hourly':'hr','satdaily':'day'}
354       self.mipVocabFnpat = 'CCMI1_%s'
355    elif self.projectV.id == 'ESA-CCI':
356       self.mipVocabDir = op.join(CC_CONFIG_DIR, 'esacci_vocabs/')
357       self.mipVocabTl = []
358       self.mipVocabVgmap = { 'ESACCI':'ESACCI' }
359       self.mipVocabFnpat = 'variableInFile.txt'
360    else:
361       self.mipVocabDir = None
362       self.mipVocabTl = ['day', 't2']
363       self.mipVocabVgmap = {}
364       self.mipVocabFnpat = None
365    self.mipVocabPars = [self.mipVocabDir, self.mipVocabTl, self.mipVocabVgmap, self.mipVocabFnpat]
366
367######## used in checkByVar
368    if self.project == 'CORDEX':
369      self.groupIndex = 7
370    elif self.project in ['CMIP5','CCMI','SPECS','__dummy']:
371      self.groupIndex = 1
372    elif self.project in ['ESA-CCI']:
373      self.fnvdict = { 'SSTskin':{'v':'sea_surface_temperature', 'sn':'sea_surface_skin_temperature'} }
374      self.fnoptions = {'groupIndex':[1,0], 'trangeIndex':[0,-2] }
375      self.fnoptions['inFn'] = [[None,'*activity','*level','*project','*var','*product','*additional','*gdsv','*version'],
376                                ['*activity','*project','*level','*var','*additional',None,'*version']]
377      self.fnoptions['varIndex'] = [4,3]
378##Indicative Date>[<Indicative Time>]-ESACCI-<Processing Level>_<CCI Project>-<Data Type>-<Product String>[- <Additional Segregator>][-v<GDS version>]-fv<File version>.nc
379##ESACCI-<CCI Project>-<Processing Level>-<Data Type>-<Product String>[-<Additional Segregator>]-<IndicativeDate>[<Indicative Time>]-fv<File version>.nc
380
381    self.trangeIndex = -1
382
383    self.getVocabs()
384    test = False
385    if test:
386      for k in self.vocabs['variable'].varcons.keys():
387        for k2 in self.vocabs['variable'].varcons[k].keys():
388          if "height2m" in self.vocabs['variable'].varcons[k][k2].get( '_dimension',[]):
389            print 'config_c4: %s , %s: %s' % (k,k2,str(self.vocabs['variable'].varcons[k][k2]['_dimension'] ) )
390
391    ##assert self.project != 'CCMI', 'Not completely set up for CCMI yet'
392
393  def getExtraAtts(self):
394
395    eafile = self.mipVocabDir + 'extraAtts.txt'
396    self.extraAtts = {}
397    if os.path.isfile( eafile ):
398      for l in open( eafile ).readlines():
399        if l[0] != '#':
400          if l[0] == "@":
401            p1,p2 = string.split( l[1:], '|' )
402          else:
403            p1,p2 = None, l
404          bits = map( string.strip, string.split(p2,',') )
405          id = '%s.%s' % (bits[0],bits[1])
406          if p1 != None:
407            id += ':%s' % p1
408          ee = {}
409          for b in bits[2:]:
410            bb = string.split(b,'=')
411            ee[bb[0]] = bb[1]
412          self.extraAtts[id] = ee
413
414  def getVocabs(self):
415  ## "Returns a dictionary of vocabulary details for the project provided."
416    if self.projectV.id == 'SPECS':
417               ##'experiment_id':utils.patternControl( 'experiment_id', "(?P<val>.*)[0-9]{4}", list=validSpecsExptFamilies ), \
418      vocabs = { 'variable':utils.mipVocab(self), \
419               'Conventions':utils.listControl( 'Conventions', ['CF-1.6'] ), \
420               'frequency':utils.listControl( 'frequency', validSpecsFrequencies ), \
421               'experiment_id':utils.listControl( 'experiment_id', validSpecsExptFamilies ), \
422               'initialization_method':utils.patternControl( 'initialization_method', "[0-9]+" ), \
423               'physics_version':utils.patternControl( 'physics_version', "[0-9]+" ), \
424               'realization':utils.patternControl( 'realization', "[0-9]+" ), \
425               'startdate':utils.patternControl( 'startdate', "S[0-9]{8}" ), \
426               ## 'associated_experiment':utils.patternControl( 'associated_experment', "(?P<val>(N/A|(decadal|seasonal): r\*i[0-9]{1,4}p[0-9]{1,4}))" ), \
427               'project_id':utils.listControl( 'project_id', ['SPECS', 'NMME-SPECS'] ), \
428               ## 'institution':utils.listControl( 'institution', validSpecsInstitutions ), \
429               'modeling_realm':utils.listControl( 'realm', self.realm, split=True ), \
430             }
431    elif self.projectV.id == 'CMIP5':
432               ##'experiment_id':utils.patternControl( 'experiment_id', "(?P<val>.*)[0-9]{4}", list=validSpecsExptFamilies ), \
433      lrdr = readVocab( 'cmip5_vocabs/')
434      vocabs = { 'variable':utils.mipVocab(self), \
435               'Conventions':utils.listControl( 'Conventions', ['CF-1.4','CF-1.5'] ), \
436               'experiment_id':utils.listControl( 'experiment_id', lrdr.getSimpleList( 'experiments.txt' ) ), \
437               'institute_id':utils.listControl( 'institute_id', lrdr.getSimpleList( 'institutes.txt' ) ), \
438               'model_id':utils.listControl( 'model_id', lrdr.getSimpleList( 'models.txt' ) ), \
439               'frequency':utils.listControl( 'frequency', validCmip5Frequencies ), \
440               'initialization_method':utils.patternControl( 'initialization_method', "[0-9]+" ), \
441               'physics_version':utils.patternControl( 'physics_version', "[0-9]+" ), \
442               'realization':utils.patternControl( 'realization', "[0-9]+" ), \
443               'project_id':utils.listControl( 'project_id', ['CMIP5'] ), \
444               ## 'institution':utils.listControl( 'institution', validSpecsInstitutions ), \
445               'modeling_realm':utils.listControl( 'realm', ['atmos', 'ocean', 'land', 'landIce', 'seaIce', 'aerosol', 'atmosChem', 'ocnBgchem'], split=True ), \
446             }
447    elif self.projectV.id == 'CCMI':
448   
449      lrdr = readVocab( 'ccmi_vocabs/')
450      vocabs = { 'variable':utils.mipVocab(self), \
451               'frequency':utils.listControl( 'frequency', validCcmiFrequencies ), \
452               'experiment_id':utils.listControl( 'experiment_id', lrdr.getSimpleList( 'ccmi_experiments.txt', bit=-1 ) ), \
453## do not preserve or check relation between model and institution.
454               'institution':utils.listControl( 'institution', lrdr.getSimpleList( 'models_insts.txt', bit=1 ) ), \
455               'model_id':utils.listControl( 'model_id', lrdr.getSimpleList( 'models_insts.txt', bit=0 ) ), \
456               'modeling_realm':utils.listControl( 'realm', ['atmos', 'ocean', 'land', 'landIce', 'seaIce', 'aerosol', 'atmosChem', 'ocnBgchem'] ), \
457               'project_id':utils.listControl( 'project_id', ['CCMI'] ) }
458
459    elif self.projectV.id == 'ESA-CCI':
460      lrdr = readVocab( 'esacci_vocabs/')
461      cciProjectList, self.ecvMappings = lrdr.getSimpleList( 'cciProject.txt', bit=-1, options='returnMappings' )
462      vocabs = { 'variable':utils.mipVocab(self), \
463               'version':utils.patternControl( 'version',  '^(fv[0-9]+(\.[0-9]+){0,1})$', examples=['fv1.1'] ), \
464               'level':utils.listControl( 'level', lrdr.getSimpleList( 'procLevel01.txt', bit=0 ) ), \
465               'platform':utils.listControl( 'platforms', lrdr.getSimpleList( 'platforms.txt', bit=0), enumeration=True, split=True, splitVal=',' ), \
466               'institution':utils.listControl( 'institution', lrdr.getSimpleList( 'institutions.txt', omt='last' ) ), \
467               'Conventions':utils.patternControl( 'Conventions', '^CF-1.[56789](,.*){0,1}$', examples=['CF-1.6'] ), \
468               'sensor':utils.listControl( 'sensors', lrdr.getSimpleList( 'sensors.txt', bit=0 ), enumeration=True, split=True, splitVal=',' ), \
469               'cdm_data_type':utils.listControl( 'cdm_data_type', lrdr.getSimpleList( 'threddsDataType.txt', bit=0 ) ), \
470               'time_coverage_duration':utils.patternControl( 'time_coverage_duration',  'ISO8601 duration', cls='ISO',examples=['P1Y'] ), \
471               'spatial_resolution':utils.patternControl( 'spatial_resolution',  '([0-9]+(.[0-9]+){0,1})[\s]*(km|m|degree).*', examples=['20km','1 km at nadir'] ), \
472               'project':utils.listControl( 'project', ['Climate Change Initiative - European Space Agency','CLIPC','ESA GlobSnow-2'] ), \
473               'cciProject':utils.listControl( 'cciproject', cciProjectList ), \
474               'var':utils.listControl( 'var', lrdr.getSimpleList( 'variables.txt', bit=-1 ) ) \
475             }
476    elif self.projectV.id == '__dummy':
477      vocabs = { 'variable':utils.mipVocab(self,dummy=True) }
478    else:
479      vocabs = { 'variable':utils.mipVocab(self), \
480           'driving_experiment_name':utils.listControl( 'driving_experiment_name', validCordexExperiment ), \
481           'project_id':utils.listControl( 'project_id', ['CORDEX'] ), \
482           'CORDEX_domain':utils.listControl( 'CORDEX_domain',  validCordexDomains ), \
483           'driving_model_id':utils.listControl( 'driving_model_id',  validGcmNames ), \
484           'driving_model_ensemble_member':utils.patternControl( 'driving_model_ensemble_member',  'r[0-9]+i[0-9]+p[0-9]+' ), \
485           'rcm_version_id':utils.patternControl( 'rcm_version_id',  '[a-zA-Z0-9-]+' ), \
486           'model_id':utils.listControl( 'model_id',  validRcmNames ), \
487           'institute_id':utils.listControl( 'institute_id',  validInstNames ), \
488           'frequency':utils.listControl( 'frequency', validCordexFrequencies ) }
489
490    self.vocabs = vocabs
491
492
493  def setEsaCciFNType(self,id):
494      if id in [1,2]:
495        id1 = 1
496      else:
497        id1 = id
498      self.groupIndex =  self.fnoptions['groupIndex'][id1]
499      self.trangeIndex = self.fnoptions['trangeIndex'][id1]
500      self.globalAttributesInFn = self.fnoptions['inFn'][id1]
501      self.varIndex = self.fnoptions['varIndex'][id1]
502
503
504def copy_config(dest_dir):
505   """
506   Copy the current default configuration directory into a separate directory.
507
508   The directory <ceda_cc-package-dir>/config is copied to `dest_dir`.
509   This is useful when ceda-cc is installed as a Python package and the user may
510   not know where the config directory is stored.
511
512   :param dest_dir: should be a path to a directory which does not yet exist. 
513       The configuration directory will be copied to this path.
514
515   """
516   shutil.copytree(CC_CONFIG_DEFAULT_DIR, dest_dir)
Note: See TracBrowser for help on using the repository browser.