Newer
Older
"""Compute the sea ice extent , area and volume in both hemispheres or a specified region"""
Javier Vegas-Regidor
committed
import six
Javier Vegas-Regidor
committed
import iris
import iris.analysis
import iris.coords
Javier Vegas-Regidor
committed
import iris.util
from earthdiagnostics.constants import Basins
Javier Vegas-Regidor
committed
from earthdiagnostics.diagnostic import Diagnostic, DiagnosticBasinListOption, DiagnosticBoolOption
from earthdiagnostics.modelingrealm import ModelingRealms
from earthdiagnostics.utils import Utils, TempFile
Javier Vegas-Regidor
committed
# noinspection PyUnresolvedReferences
Javier Vegas-Regidor
committed
class Siasiesiv(Diagnostic):
Compute the sea ice extent , area and volume in both hemispheres or a specified region.
Parameters
----------
data_manager: DataManager
startdate: str
member: int
chunk: init
domain: ModellingRealm
variable: str
Javier Vegas-Regidor
committed
basin: list of Basin
alias = 'siasiesiv'
"Diagnostic alias for the configuration file"
e1t = None
e2t = None
gphit = None
def __init__(self, data_manager, startdate, member, chunk, masks, var_manager, data_convention, omit_vol):
Javier Vegas-Regidor
committed
Diagnostic.__init__(self, data_manager)
self.startdate = startdate
self.member = member
self.chunk = chunk
Javier Vegas-Regidor
committed
self.masks = masks
self.var_manager = var_manager
self.omit_volume = omit_vol
self.sic_varname = self.var_manager.get_variable('sic').short_name
self.sit_varname = self.var_manager.get_variable('sit').short_name
Javier Vegas-Regidor
committed
Javier Vegas-Regidor
committed
self.results = {}
for var in ('siarean', 'siareas', 'sivoln', 'sivols', 'siextentn', 'siextents'):
self.results[var] = {}
return 'Siasiesiv Startdate: {0.startdate} Member: {0.member} Chunk: {0.chunk} ' \
Javier Vegas-Regidor
committed
'Basins: {1} Omit volume: {0.omit_volume}'.format(self,
','.join(str(basin) for basin in self.masks.keys()))
def generate_jobs(cls, diags, options):
Create a job for each chunk to compute the diagnostic
:param diags: Diagnostics manager class
:type diags: Diags
:param options: basin
Javier Vegas-Regidor
committed
options_available = (DiagnosticBasinListOption('basins', [Basins().Global]),
DiagnosticBoolOption('omit_volume', False))
options = cls.process_options(options, options_available)
basins = options['basins']
if not basins:
Javier Vegas-Regidor
committed
Log.error('Basins not recognized')
return ()
Javier Vegas-Regidor
committed
masks = {}
basins.sort()
for basin in basins:
Javier Vegas-Regidor
committed
masks[basin] = Utils.get_mask(basin)
Javier Vegas-Regidor
committed
job_list = list()
for startdate, member, chunk in diags.config.experiment.get_chunk_list():
Javier Vegas-Regidor
committed
job_list.append(Siasiesiv(diags.data_manager, startdate, member, chunk, masks,
diags.config.var_manager, diags.config.data_convention,
options['omit_volume']))
Javier Vegas-Regidor
committed
e1t = iris.load_cube('mesh_hgr.nc', 'e1t')
e2t = iris.load_cube('mesh_hgr.nc', 'e2t')
Siasiesiv.area = e1t * e2t
Javier Vegas-Regidor
committed
return job_list
if not self.omit_volume:
self.sit = self.request_chunk(ModelingRealms.seaIce, self.sit_varname,
self.startdate, self.member, self.chunk)
self.sic = self.request_chunk(ModelingRealms.seaIce, self.sic_varname,
self.startdate, self.member, self.chunk)
if not self.omit_volume:
self._declare_var('sivols')
self._declare_var('sivoln')
self._declare_var('siareas')
self._declare_var('siextents')
self._declare_var('siarean')
self._declare_var('siextentn')
def _declare_var(self, var_name):
Javier Vegas-Regidor
committed
self.generated[var_name] = self.declare_chunk(ModelingRealms.seaIce, var_name,
self.startdate, self.member, self.chunk)
Javier Vegas-Regidor
committed
def compute(self):
coordinates = ' '.join(('time', 'leadtime', 'time_centered',
self.data_convention.lon_name, self.data_convention.lat_name))
Javier Vegas-Regidor
committed
handler = Utils.open_cdf(self.sic.local_file)
handler.variables[self.sic_varname].coordinates = coordinates
Javier Vegas-Regidor
committed
handler.close()
sic = iris.load_cube(self.sic.local_file)
if sic.units.origin == '%' and sic.data.max < 2:
Javier Vegas-Regidor
committed
sic.units = '1.0'
Javier Vegas-Regidor
committed
sic.convert_units('1.0')
sic *= Siasiesiv.area.data
extent = sic.data > 0.15
Javier Vegas-Regidor
committed
if not self.omit_volume:
handler = Utils.open_cdf(self.sit.local_file)
handler.variables[self.sit_varname].coordinates = coordinates
Javier Vegas-Regidor
committed
handler.close()
sit = iris.load_cube(self.sic.local_file)
Javier Vegas-Regidor
committed
for basin, mask in six.iteritems(self.masks):
self.results['siarean'][basin] = self.sum(sic, mask, north=True)
self.results['siareas'][basin] = self.sum(sic, mask, north=False)
Javier Vegas-Regidor
committed
if not self.omit_volume:
volume = sic * sit
self.results['sivoln'][basin] = self.sum(volume, mask, north=True)
self.results['sivols'][basin] = self.sum(volume, mask, north=False)
Javier Vegas-Regidor
committed
extent_mask = mask * extent
self.results['siextentn'][basin] = self.sum(sic, extent_mask, north=True)
self.results['siextents'][basin] = self.sum(sic, extent_mask, north=False)
Javier Vegas-Regidor
committed
self.save()
Javier Vegas-Regidor
committed
def sum(self, data, mask, north=True):
if north:
condition = data.coord('latitude').points > 0
else:
condition = data.coord('latitude').points < 0
weights = iris.util.broadcast_to_shape(condition, data.shape, data.coord_dims('latitude')) * mask
return data.collapsed(('latitude', 'longitude'), iris.analysis.SUM, weights=weights)
def save(self):
for var, basins in six.iteritems(self.results):
Javier Vegas-Regidor
committed
results = iris.cube.CubeList()
Javier Vegas-Regidor
committed
for basin, result in six.iteritems(basins):
result.var_name = var
if var.startswith('sivol'):
result.units = 'm^3'
else:
result.units = 'm^2'
result.add_aux_coord(iris.coords.AuxCoord(basin.name, var_name='region'))
Javier Vegas-Regidor
committed
results.append(result)
if not results:
continue
self._save_file(results.merge_cube(), self.generated[var])
Javier Vegas-Regidor
committed
def _save_file(self, data, generated_file):
temp = TempFile.get()
Javier Vegas-Regidor
committed
region = data.coord('region').points
data.remove_coord('region')
iris.save(data, temp, zlib=True)
Javier Vegas-Regidor
committed
handler = Utils.open_cdf(temp)
var = handler.createVariable('region2', str, ('region',))
var[...] = region
handler.close()
Utils.rename_variable(temp, 'region2', 'region', True)
generated_file.set_local_file(temp)