/usr/share/pyshared/drslib/cmip3.py is in python-drslib 0.3.0a3-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 | # BSD Licence
# Copyright (c) 2010, Science & Technology Facilities Council (STFC)
# All rights reserved.
#
# See the LICENSE file in the source distribution of this software for
# the full license text.
"""
A translator specific to CMIP3
The CMIP3 translation code is less complete than CMIP5. It focuses
on translating paths to DRS instances.
1. CMIP3 files or paths cannot be generated from DRS instances
2. the code doesn't use MIP tables to validate and deduce components
"""
import re
import logging
log = logging.getLogger(__name__)
import drslib.translate as T
from drslib.drs import DRS
from drslib.config import CMIP5_DRS, CMIP3_DRS
TranslationError = T.TranslationError
#!NOTE: there is no product component in CMIP3
# From Charlotte's wiki page
instmodel_map = {
'bcc_cm1': ('CMA', 'BCC-CM1'),
'bccr_bcm2_0': ('BCCR', 'BCM2'),
'cccma_cgcm3_1': ('CCCMA', 'CGCM3-1-T47'),
'cccma_cgcm3_1_t63': ('CCCMA','CGCM3-1-T63'),
'cnrm_cm3': ('CNRM','CM3'),
'miub_echo_g': ('MIUB-KMA','ECHO-G'),
'csiro_mk3_0': ('CSIRO','MK3'),
'csiro_mk3_5': ('CSIRO','MK3-5'),
'gfdl_cm2_0': ('GFDL','CM2'),
'gfdl_cm2_1': ('GFDL','CM2-1'),
'inmcm3_0': ('INM','CM3'),
'ipsl_cm4': ('IPSL','CM4'),
'iap_fgoals1_0_g': ('LASG','FGOALS-G1-0'),
'mpi_echam5': ('MPIM','ECHAM5'),
'mri_cgcm2_3_2a': ('MRI','CGCM2-3-2'),
'giss_aom': ('NASA','GISS-AOM'),
'giss_model_e_h': ('NASA','GISS-EH'),
'giss_model_e_r': ('NASA','GISS-ER'),
'ncar_ccsm3_0': ('NCAR','CCSM3'),
'ncar_pcm1': ('NCAR','PCM'),
'miroc3_2_hires': ('NIES','MIROC3-2-HI'),
'miroc3_2_medres': ('NIES','MIROC3-2-MED'),
'ukmo_hadcm3': ('UKMO','HADCM3'),
'ukmo_hadgem1': ('UKMO','HADGEM1'),
'ingv_echam4': ('INGV','ECHAM4'),
}
class InstituteModelTranslator(T.BaseComponentTranslator):
def path_to_drs(self, context):
instmodel = context.path_parts[CMIP3_DRS.PATH_INSTMODEL]
try:
institute, model = instmodel_map[instmodel]
except KeyError:
raise TranslationError('CMIP3 Institute/Model identifier %s not recognised' % instmodel)
context.set_drs_component('institute', institute)
context.set_drs_component('model', model)
def filename_to_drs(self, context):
pass
instmodel_t = InstituteModelTranslator()
class ExperimentTranslator(T.GenericComponentTranslator):
path_i = CMIP3_DRS.PATH_EXPERIMENT
file_i = None
component = 'experiment'
def _validate(self, s):
"""
@note: No validation is done. Any experiment is accepted
"""
return s
experiment_t = ExperimentTranslator()
class FrequencyTranslator(T.BaseComponentTranslator):
vocab = {'yr': 'yr', 'mo': 'mon', 'da': 'day', '3h': '3hr',
'fixed': 'fx'}
def path_to_drs(self, context):
cmip3_freq = context.path_parts[CMIP3_DRS.PATH_FREQUENCY]
try:
freq = self.vocab[cmip3_freq]
except KeyError:
raise TranslationError('CMIP3 frequency %s not recognised' % cmip3_freq)
context.set_drs_component('frequency', freq)
def filename_to_drs(self, context):
pass
frequency_t = FrequencyTranslator()
class RealmTranslator(T.GenericComponentTranslator):
path_i = CMIP5_DRS.PATH_REALM
file_i = None
component = 'realm'
# mapping cmip3 realms and variables and realms to cmip5
# http://metaforclimate.eu/trac/browser/cmip5q/trunk/CMIP5Outputs_to_Components
# realm_map = {'cmip3Realm': ('CMIP5Realm',),}
# atmos, ocean, land, landIce, seaIce, aerosol atmosChem, ocnBgchem
realm_map = {'atm': ('atmos', 'aerosol', 'atmosChem','land'),
'ice': ('seaIce',),
'land': ('land','landIce'),
'ocn': ('ocean',),
}
# CMIP3 atmos and land variables can map onto 4 different cmip5 realms.
# Assume CMIP3 atm variables map onto CMIP5 atmos realm unless they appear in this dictionary
var_map={'atmos': {'mrsos': 'land',
'trsult': 'aerosol',
'trsul': 'aerosol',
'tro3': 'atmosChem',
},
'land': {'sftgif': 'landIce',},
}
def path_to_drs(self, context):
cmip3_realm = context.path_parts[CMIP3_DRS.PATH_REALM]
try:
realm_list = self.realm_map[cmip3_realm]
except KeyError:
raise TranslationError('CMIP3 realm %s not recognised' % cmip3_realm)
realm = realm_list[0]
if len(realm_list) > 1:
variable = context.drs.variable
if variable is None:
raise TranslationError('CMIP3 realm %s cannot be deduced without variable' % cmip3_realm)
# Realm is replaced if it's in var_map
try:
realm = self.var_map[realm][variable]
except KeyError:
pass
context.set_drs_component('realm', realm)
realm_t = RealmTranslator()
class EnsembleTranslator(T.BaseComponentTranslator):
def path_to_drs(self, context):
r_str = context.path_parts[CMIP3_DRS.PATH_ENSEMBLE]
mo = re.match(r'run(\d+)', r_str)
if not mo:
raise TranslationError('Unrecognised CMIP3 ensemble identifier %s' % r_str)
ensemble = (int(mo.group(1)), None, None)
context.set_drs_component('ensemble', ensemble)
def filename_to_drs(self, context):
pass
ensemble_t = EnsembleTranslator()
class VariableTranslator(T.GenericComponentTranslator):
path_i = CMIP3_DRS.PATH_VARIABLE
file_i = None
component = 'variable'
def filename_to_drs(self, context):
table = context.file_parts[CMIP3_DRS.FILE_TABLE]
context.set_drs_component('table', table)
def _validate(self, s):
"""
@note: No validation is done. Any variable is accepted
"""
return s
variable_t = VariableTranslator()
#!NOTE: No version in CMIP3
#!TODO: Subset translator
class SubsetTranslator(T.BaseComponentTranslator):
"""
Subsets are irregular in CMIP3 so we just extract the irregular bit
and put it in DRS.extended.
"""
def filename_to_drs(self, context):
extended = context.file_parts[CMIP3_DRS.FILE_EXTENDED]
context.set_drs_component('extended', extended)
def path_to_drs(self, context):
pass
subset_t = SubsetTranslator()
class FnFixTranslator(T.BaseComponentTranslator):
"""
Fix problem filenames in the DRS structure.
"""
def drs_to_filepath(self, context):
pass
def path_to_drs(self, context):
pass
def filename_to_drs(self, context):
# Detect variables containing underscores and fix.
varbits = context.drs.variable.split('_')
if len(varbits) > 1 and context.drs.table == varbits[-1]:
extbits = context.drs.extended.split('_')
#context.drs.variable = '_'.join(varbits[:-1])
context.drs.table = extbits[0]
context.drs.extended = '_'.join(extbits[1:])
log.warn(('Variable containing underscore detected'
+'Setting variable=%s, table=%s, extended=%s')
% (context.drs.variable,
context.drs.table,
context.drs.extended))
fnfix_t = FnFixTranslator()
class CMIP3TranslatorContext(T.TranslatorContext):
"""
A customised context class for converting CMIP3 paths
CMIP3 filenames are irregular so we need to override some behaviour of
TranslatorContext.
"""
#!FIXME: This regular expression doesn't allow underscores in variable
# names. Unfortunately CMIP3 has them.
_fnrexp = re.compile(r'([a-zA-Z0-9]+)_([a-zA-Z0-9]+)(?:[._-](.*))?.nc$')
def __init__(self, filename=None, path=None, drs=None, table_store=None):
assert table_store is None
if path is None:
self.path_parts = [None] * 10
else:
self.path_parts = path.split('/')
self.file_parts = [None] * 7
if filename is not None:
# CMIP3 requires different filename parsing
mo = self._fnrexp.match(filename)
if not mo:
raise TranslationError('Unrecognised CMIP3 filename %s' % filename)
self.file_parts[CMIP3_DRS.PATH_VARIABLE] = mo.group(1)
self.file_parts[CMIP3_DRS.FILE_TABLE] = mo.group(2)
self.file_parts[CMIP3_DRS.FILE_EXTENDED] = mo.group(3)
if drs is None:
self.drs = DRS()
else:
self.drs = drs
class CMIP3Translator(T.Translator):
ContextClass = CMIP3TranslatorContext
translators = [instmodel_t,
experiment_t,
ensemble_t,
variable_t,
# Must be processed after variable
realm_t,
frequency_t,
subset_t,
# Fix some unusual CMIP3 filenames
fnfix_t,
]
def init_drs(self, drs=None):
if drs is None:
drs = DRS()
drs.activity = 'cmip3'
drs.version = 1
drs.product = 'output'
return drs
def make_translator(prefix):
return CMIP3Translator(prefix)
|