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(), var)
Javier Vegas-Regidor
committed
def _save_file(self, data, var):
generated_file = self.generated[var]
temp = TempFile.get()
Javier Vegas-Regidor
committed
region = data.coord('region').points
data.remove_coord('region')
iris.save(data, temp, zlib=True)
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
if len(region) > 1:
Utils.rename_variable(temp, 'dim0', 'region', False)
handler = Utils.open_cdf(temp)
var = handler.createVariable('region2', str, ('region',))
var[...] = region
handler.close()
Utils.rename_variable(temp, 'region2', 'region', True)
else:
handler = Utils.open_cdf(temp)
if 'region' not in handler.dimensions:
new_file = TempFile.get()
new_handler = Utils.open_cdf(new_file, 'w')
new_handler.createDimension('region', 1)
for dimension in handler.dimensions:
Utils.copy_dimension(handler, new_handler, dimension)
for variable in handler.variables.keys():
if variable in (var, 'region'):
continue
Utils.copy_variable(handler, new_handler, variable)
old_var = handler.variables[var]
new_var = new_handler.createVariable(var, old_var.dtype, ('region',) + old_var.dimensions,
zlib=True, fill_value=1.0e20)
Utils.copy_attributes(new_var, old_var)
new_var[0, :] = old_var[:]
new_var = new_handler.createVariable('region', str, ('region',))
new_var[0] = region[0]
new_handler.close()
os.remove(temp)
temp = new_file
handler.close()
generated_file.set_local_file(temp)