diff --git a/VERSION b/VERSION index 3b8d36d048a75e8c8029a5d1e1862b68c705cc91..36e483b9bacf72c32a85cf4b5776664796565a67 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -3.0.0b48 +3.0.0b49 diff --git a/diags.conf b/diags.conf index 7e2588c97ef559000a1066e8f0e7ce46c4611e9f..360863d0e9d557fb0dd17e6cf3d658c046d51206 100644 --- a/diags.conf +++ b/diags.conf @@ -15,7 +15,7 @@ CON_FILES = /esnas/autosubmit/con_files/ # Diagnostics to run, space separated. You must provide for each one the name and the parameters (comma separated) or # an alias defined in the ALIAS section (see more below). If you are using the diagnostics just to CMORize, leave it # empty -DIAGS = mxl +DIAGS = simdim,atmos,tas # DIAGS = OHC # Frequency of the data you want to use by default. Some diagnostics do not use this value: i.e. monmean always stores # its results at monthly frequency (obvious) and has a parameter to specify input's frequency. @@ -69,7 +69,7 @@ SERVER_URL = https://earth.bsc.es/thredds [EXPERIMENT] # Experiments parameters as defined in CMOR standard INSTITUTE = BSC -MODEL = EC-EARTH +MODEL = EC-EARTH3 # Model version: Available versions MODEL_VERSION =Ec3.2_O1L75 # Atmospheric output timestep in hours @@ -85,12 +85,12 @@ OCEAN_TIMESTEP = 6 # if 2, fc00 # CHUNK_SIZE is the size of each data file, given in months # CHUNKS is the number of chunks. You can specify less chunks than present on the experiment -EXPID = a0c2 +EXPID = t01b STARTDATES = 19900101 MEMBERS = 0 MEMBER_DIGITS = 1 -CHUNK_SIZE = 12 -CHUNKS = 2 +CHUNK_SIZE = 1 +CHUNKS = 1 # CHUNKS = 1 diff --git a/doc/source/codedoc/general.rst b/doc/source/codedoc/general.rst index d4fc8ea0828502b7a6869ed4f71b02a66e0be836..f0898e42bb5b54c33e877444e4052e4dfb6a4c48 100644 --- a/doc/source/codedoc/general.rst +++ b/doc/source/codedoc/general.rst @@ -44,6 +44,12 @@ earthdiagnostics.general.scale :show-inheritance: :members: +earthdiagnostics.general.simplify_dimensions +-------------------------------------------- +.. automodule:: earthdiagnostics.general.simplify_dimensions + :show-inheritance: + :members: + earthdiagnostics.general.yearlymean ----------------------------------- .. automodule:: earthdiagnostics.general.yearlymean diff --git a/doc/source/conf.py b/doc/source/conf.py index 11b03e3fc37db004bd0dc0a67acfee087fb68c1f..5d7802d79b29258f96438d320b734e6fa5822b2f 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.0b48' +release = '3.0.0b49' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/source/diagnostic_list.rst b/doc/source/diagnostic_list.rst index 2376a8ec6d13234f2f1146d105fab15b21fa2299..f8f2d7efd93672c330ca9d8f5b016b93a9163f3b 100644 --- a/doc/source/diagnostic_list.rst +++ b/doc/source/diagnostic_list.rst @@ -179,6 +179,27 @@ Options: List of frequencies ('-' separated) to apply the scale on. Default is the frequency defined globally for all the diagnostics +simdim +~~~~~~ + +Convert i j files to lon lat when there is no interpolation required, +i.e. lon is constant over i and lat is constat over j + + + See :class:`~earthdiagnostics.general.simplify_dimensions.SimplifyDimensions` + +Options: +******** + +1. Domain: + Variable domain + +2. Variable: + Variable name + +5. Grid = '': + Variable grid. Only required in case that you want to use interpolated data. + yearlymean ~~~~~~~~~~ Calculates the daily mean for a given variable. See :class:`~earthdiagnostics.general.yearlymean.YearlyMean` diff --git a/earthdiagnostics/EarthDiagnostics.pdf b/earthdiagnostics/EarthDiagnostics.pdf index 84ba83795edf9d553ff19d365793f917ce4f7169..dc5c298bf25b273e73c94819f3bf6cc9564415c2 100644 Binary files a/earthdiagnostics/EarthDiagnostics.pdf and b/earthdiagnostics/EarthDiagnostics.pdf differ diff --git a/earthdiagnostics/cmorizer.py b/earthdiagnostics/cmorizer.py index 6ab160179198b43da919f77b252213db9cd2286a..76bbf50d93a08a0b4e1b8c393b404a8804a5c59d 100644 --- a/earthdiagnostics/cmorizer.py +++ b/earthdiagnostics/cmorizer.py @@ -128,8 +128,9 @@ class Cmorizer(object): else: sign = 1 - handler.variables[varname][:] = sign * handler.variables[varname][:] / total_seconds - handler.units = '{0} {1}'.format(handler.units, 's-1') + var_handler = handler.variables[varname] + var_handler[:] = sign * var_handler[:] / total_seconds + var_handler.units = '{0} {1}'.format(var_handler.units, 's-1') handler.close() def _unpack_tar_file(self, tarfile): diff --git a/earthdiagnostics/earthdiags.py b/earthdiagnostics/earthdiags.py index 625421a086507c3fff8709b4eea5aef1be2faf2f..2fb423fba227f0a8e6cfffb4a020c2845c3ec085 100755 --- a/earthdiagnostics/earthdiags.py +++ b/earthdiagnostics/earthdiags.py @@ -248,11 +248,12 @@ class EarthDiags(object): Diagnostic.register(DailyMean) Diagnostic.register(MonthlyMean) Diagnostic.register(YearlyMean) - Diagnostic.register(Rewrite) + Diagnostic.register(SimplifyDimensions) Diagnostic.register(Relink) Diagnostic.register(RelinkAll) Diagnostic.register(Scale) Diagnostic.register(Attribute) + Diagnostic.register(SimplifyDimensions) @staticmethod def _register_ocean_diagnostics(): diff --git a/earthdiagnostics/general/__init__.py b/earthdiagnostics/general/__init__.py index 2696ef623ab57bca72ccd6ebbf86243973988d1d..96be392dee4fb6951f742899d15767baa0b5deab 100644 --- a/earthdiagnostics/general/__init__.py +++ b/earthdiagnostics/general/__init__.py @@ -7,3 +7,4 @@ from earthdiagnostics.general.relink import Relink from earthdiagnostics.general.scale import Scale from earthdiagnostics.general.attribute import Attribute from earthdiagnostics.general.relinkall import RelinkAll +from earthdiagnostics.general.simplify_dimensions import SimplifyDimensions diff --git a/earthdiagnostics/general/simplify_dimensions.py b/earthdiagnostics/general/simplify_dimensions.py new file mode 100644 index 0000000000000000000000000000000000000000..5323f0039d6a29d0543e1603f20a1a81e363c8cb --- /dev/null +++ b/earthdiagnostics/general/simplify_dimensions.py @@ -0,0 +1,132 @@ +# coding=utf-8 +from earthdiagnostics.diagnostic import Diagnostic, DiagnosticOption, DiagnosticDomainOption, DiagnosticVariableOption +from earthdiagnostics.modelingrealm import ModelingRealm +from earthdiagnostics.utils import Utils, TempFile +import numpy as np + + +class SimplifyDimensions(Diagnostic): + """ + Convert i j files to lon lat when there is no interpolation required, + i.e. lon is constant over i and lat is constat over j + + :original author: Javier Vegas-Regidor + + :created: April 2017 + + :param data_manager: data management object + :type data_manager: DataManager + :param startdate: startdate + :type startdate: str + :param member: member number + :type member: int + :param chunk: chunk's number + :type chunk: int + :param variable: variable's name + :type variable: str + :param domain: variable's domain + :type domain: ModelingRealm + """ + + alias = 'simdim' + "Diagnostic alias for the configuration file" + + def __init__(self, data_manager, startdate, member, chunk, domain, variable, grid): + Diagnostic.__init__(self, data_manager) + self.startdate = startdate + self.member = member + self.chunk = chunk + self.variable = variable + self.domain = domain + self.grid = grid + + def __str__(self): + return 'Simplify dimension Startdate: {0} Member: {1} Chunk: {2} ' \ + 'Variable: {3}:{4} Grid: {5}'.format(self.startdate, self.member, self.chunk, self.domain, self.variable, + self.grid) + + def __eq__(self, other): + return self.startdate == other.startdate and self.member == other.member and self.chunk == other.chunk and \ + self.domain == other.domain and self.variable == other.variable and self.grid == self.grid + + @classmethod + def generate_jobs(cls, diags, options): + """ + Creates a job for each chunk to compute the diagnostic + + :param diags: Diagnostics manager class + :type diags: Diags + :param options: variable, domain, grid + :type options: list[str] + :return: + """ + options_available = (DiagnosticDomainOption('domain'), + DiagnosticVariableOption('variable'), + DiagnosticOption('grid', '')) + options = cls.process_options(options, options_available) + job_list = list() + for startdate, member, chunk in diags.config.experiment.get_chunk_list(): + job_list.append(SimplifyDimensions(diags.data_manager, startdate, member, chunk, + options['domain'], options['variable'], options['grid'])) + return job_list + + def compute(self): + """ + Runs the diagnostic + """ + variable_file = self.data_manager.get_file(self.domain, self.variable, self.startdate, self.member, self.chunk, + grid=self.grid) + + handler = Utils.openCdf(variable_file) + if not 'i' in handler.dimensions: + raise Exception('Variable {0.domain}:{0.variable} does not have i,j dimensions'.format(self)) + lat = handler.variables['lat'] + lat_values = lat[:, 0:1] + if np.any(lat[:] - lat_values != 0): + raise Exception('Latitude is not constant over i dimension for variable {0.domain}:{0.variable}'.format(self)) + + lon = handler.variables['lon'] + lon_values = lon[0:1, :] + if np.any(lon[:] - lon != 0): + raise Exception('Longitude is not constant over j dimension for variable {0.domain}:{0.variable}'.format(self)) + + temp = TempFile.get() + new_file = Utils.openCdf(temp, 'w') + for dim in handler.dimensions.keys(): + if dim in ('lat', 'lon', 'i', 'j'): + continue + Utils.copy_dimension(handler, new_file, dim, new_names={'i': 'lon', 'j': 'lat'}) + + new_file.createDimension('lon', handler.dimensions['i'].size) + new_file.createDimension('lat', handler.dimensions['j'].size) + + for var in handler.variables.keys(): + if var in ('lat', 'lon', 'i', 'j', 'lat_vertices', 'lon_vertices'): + continue + Utils.copy_variable(handler, new_file, var, new_names={'i': 'lon', 'j': 'lat'}) + + self._create_var('lon', lon_values, handler, new_file) + self._create_var('lat', lat_values, handler, new_file) + handler.close() + + self.send_file(variable_file, self.domain, self.variable, self.startdate, self.member, self.chunk, + grid=self.grid) + + def _create_var(self, var_name, var_values, source, destiny): + old_var = source.variables[var_name] + new_var = destiny.createVariable(var_name, old_var.dtype, dimensions=(var_name, )) + new_var[:] = var_values + Utils.copy_attributes(new_var, old_var) + + vertices_name = '{0}_vertices'.format(var_name) + + if vertices_name in source.variables: + var_vertices = source.variables[vertices_name] + if var_name == 'lon': + vertices_values = var_vertices[0:1, ...] + else: + vertices_values = var_vertices[:, 0:1, :] + new_lat_vertices = destiny.createVariable(vertices_name, var_vertices.dtype, dimensions=(var_name, 'vertices')) + new_lat_vertices[:] = vertices_values + Utils.copy_attributes(new_lat_vertices, var_vertices) +