diff --git a/VERSION b/VERSION index 34a8f4f6e53bf4616f153fb322c38d2f9e9337c4..bf50b583b787819260fdbc7e8ca8c239702f950b 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -3.0.0b46 +3.0.0b47 diff --git a/doc/source/conf.py b/doc/source/conf.py index e93d11ef6d355b0ef1e50f194e951fbe444b5654..5be47d4f251acce395b89b90c2438a26db510b34 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -64,7 +64,7 @@ copyright = u'2016, BSC-CNS Earth Sciences Department' # The short X.Y version. version = '3.0b' # The full version, including alpha/beta/rc tags. -release = '3.0.0b46' +release = '3.0.0b47' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/earthdiagnostics/EarthDiagnostics.pdf b/earthdiagnostics/EarthDiagnostics.pdf index 3df515fab7606aaea1ecbb465bb139401c4a5041..6b099383f507b51964aa8a4dfb002e228a10964c 100644 Binary files a/earthdiagnostics/EarthDiagnostics.pdf and b/earthdiagnostics/EarthDiagnostics.pdf differ diff --git a/earthdiagnostics/ocean/interpolatecdo.py b/earthdiagnostics/ocean/interpolatecdo.py index 9d4b4011b3a00b4f9a87cbf6348a54bb7964b7fd..2eb47a4f25a738adee70904468bfdd2a2388c42c 100644 --- a/earthdiagnostics/ocean/interpolatecdo.py +++ b/earthdiagnostics/ocean/interpolatecdo.py @@ -1,11 +1,9 @@ # coding=utf-8 -from earthdiagnostics.constants import Basins -from earthdiagnostics.diagnostic import Diagnostic, DiagnosticOption, DiagnosticDomainOption, DiagnosticBoolOption, \ - DiagnosticVariableOption +from earthdiagnostics.diagnostic import * from earthdiagnostics.utils import Utils, TempFile -import numpy as np from earthdiagnostics.modelingrealm import ModelingRealm, ModelingRealms +import numpy as np class InterpolateCDO(Diagnostic): @@ -36,8 +34,15 @@ class InterpolateCDO(Diagnostic): alias = 'interpcdo' "Diagnostic alias for the configuration file" + BILINEAR = 'bilinear' + BICUBIC = 'bicubic' + CONSERVATIVE = 'conservative' + CONSERVATIVE2 = 'conservative2' + + METHODS = [BILINEAR, BICUBIC, CONSERVATIVE, CONSERVATIVE2] + def __init__(self, data_manager, startdate, member, chunk, domain, variable, target_grid, model_version, - mask_oceans, original_grid): + mask_oceans, original_grid, weights): Diagnostic.__init__(self, data_manager) self.startdate = startdate self.member = member @@ -51,6 +56,7 @@ class InterpolateCDO(Diagnostic): self.grid = target_grid self.mask_oceans = mask_oceans self.original_grid = original_grid + self.weights = weights def __eq__(self, other): return self.startdate == other.startdate and self.member == other.member and self.chunk == other.chunk and \ @@ -77,18 +83,81 @@ class InterpolateCDO(Diagnostic): options_available = (DiagnosticVariableOption('variable'), DiagnosticOption('target_grid', diags.config.experiment.atmos_grid.lower()), DiagnosticDomainOption('domain', ModelingRealms.ocean), + DiagnosticChoiceOption('method', InterpolateCDO.METHODS, InterpolateCDO.BILINEAR), DiagnosticBoolOption('mask_oceans', True), DiagnosticOption('original_grid', '')) options = cls.process_options(options, options_available) target_grid = cls._translate_ifs_grids_to_cdo_names(options['target_grid']) job_list = list() + weights = TempFile.get() + method = options['method'].lower() + temp = cls.get_sample_grid_file() + + if method == InterpolateCDO.BILINEAR: + Utils.cdo.genbil(target_grid, input=temp, output=weights) + elif method == InterpolateCDO.BICUBIC: + Utils.cdo.genbic(target_grid, input=temp, output=weights) + elif method == InterpolateCDO.CONSERVATIVE: + Utils.cdo.gencon(target_grid, input=temp, output=weights) + elif method == InterpolateCDO.CONSERVATIVE2: + Utils.cdo.gencon2(target_grid, input=temp, output=weights) + + target_grid = '{0}_{1}'.format(target_grid, method) + for startdate, member, chunk in diags.config.experiment.get_chunk_list(): job_list.append(InterpolateCDO(diags.data_manager, startdate, member, chunk, options['domain'], options['variable'], target_grid, diags.config.experiment.model_version, options['mask_oceans'], - options['original_grid'])) + options['original_grid'], weights)) return job_list + @classmethod + def get_sample_grid_file(cls): + temp = TempFile.get() + Utils.nco.ncks(input='mask.nc', output=temp, options='-O -v tmask,lat,lon,gphif,glamf') + handler = Utils.openCdf(temp) + lon = handler.variables['lon'] + lon.units = "degrees_east" + lon.long_name = "Longitude" + lon.nav_model = "Default grid" + lon.standard_name = "longitude" + lon.short_name = "lon" + lon.bounds = 'lon_bnds' + + lat = handler.variables['lat'] + lat.units = "degrees_north" + lat.long_name = "Latitude" + lat.nav_model = "Default grid" + lat.standard_name = "latitude" + lat.short_name = "lat" + lat.bounds = 'lat_bnds' + + handler.createDimension('bounds', 4) + + lon_bnds = handler.createVariable('lon_bnds', lon.datatype, ('j', 'i', 'bounds')) + corner_lat = handler.variables['glamf'][0, ...] + lon_bnds[:, :, 0] = corner_lat + lon_bnds[:, :, 1] = np.roll(corner_lat, 1, 0) + lon_bnds[:, :, 2] = np.roll(corner_lat, -1, 1) + lon_bnds[:, :, 3] = np.roll(lon_bnds[:, :, 1], -1, 1) + + lat_bnds = handler.createVariable('lat_bnds', lat.datatype, ('j', 'i', 'bounds')) + corner_lat = handler.variables['gphif'][0, ...] + lat_bnds[:, :, 0] = corner_lat + lat_bnds[:, :, 1] = np.roll(corner_lat, 1, 0) + lat_bnds[:, :, 2] = np.roll(corner_lat, 1, 1) + lat_bnds[:, :, 3] = np.roll(lat_bnds[:, :, 1], 1, 1) + lat_bnds[0, :, 1] = lat_bnds[1, 0, 1] - 1 + lat_bnds[0, :, 3] = lat_bnds[1, 0, 3] - 1 + + tmask = handler.variables['tmask'] + tmask.coordinates = 'time lev lat lon' + + handler.close() + + Utils.nco.ncks(input=temp, output=temp, options='-O -x -v gphif,glamf') + return temp + @classmethod def _translate_ifs_grids_to_cdo_names(cls, target_grid): if target_grid.upper().startswith('T159L'): @@ -105,19 +174,28 @@ class InterpolateCDO(Diagnostic): """ variable_file = self.data_manager.get_file(self.domain, self.variable, self.startdate, self.member, self.chunk, grid=self.original_grid) + handler = Utils.openCdf(variable_file) + var = handler.variables[self.variable] + + coordinates = list() + for dim in var.dimensions: + if dim == 'i': + coordinates.append('lat') + elif dim == 'j': + coordinates.append('lon') + else: + coordinates.append(dim) + var.coordinates = ' '.join(coordinates) if self.mask_oceans: - handler = Utils.openCdf(variable_file) - var = handler.variables[self.variable] + mask = Utils.get_mask(Basins.Global).astype(float) mask[mask == 0] = np.nan var[:] = mask * var[:] - handler.close() + handler.close() - cdo = Utils.cdo temp = TempFile.get() - cdo.remapbil(self.grid, input=variable_file, output=temp) - Utils.setminmax(temp, self.variable) + Utils.cdo.remap(','.join((self.grid.split('_')[0], self.weights)), input=variable_file, output=temp) self.send_file(temp, self.domain, self.variable, self.startdate, self.member, self.chunk, grid=self.grid) diff --git a/earthdiagnostics/ocean/regionmean.py b/earthdiagnostics/ocean/regionmean.py index 0a0d0b98c82b3e8f7b7b66e3532072ac1d9bb666..07954d7867c09d58b0c3c9c74514fa54e19c4bdf 100644 --- a/earthdiagnostics/ocean/regionmean.py +++ b/earthdiagnostics/ocean/regionmean.py @@ -59,7 +59,7 @@ class RegionMean(Diagnostic): self.box == other.box and self.variable == other.variable def __str__(self): - return 'Vertical mean Startdate: {0} Member: {1} Chunk: {2} Variable: {3} ' \ + return 'Region mean Startdate: {0} Member: {1} Chunk: {2} Variable: {3} ' \ 'Box: {4}'.format(self.startdate, self.member, self.chunk, self.variable, self.box) @classmethod