Skip to content

Commit

Permalink
Missing 2m height coordinate and monotonicity for tasmin in CESM2 and…
Browse files Browse the repository at this point in the history
… CESM2-WACCM (ESMValGroup#2574)

Co-authored-by: Karen Garcia Perdomo <[email protected]>
Co-authored-by: Valeriu Predoi <[email protected]>
  • Loading branch information
3 people authored Nov 29, 2024
1 parent d8ad2f0 commit 8b4a63a
Show file tree
Hide file tree
Showing 8 changed files with 476 additions and 9 deletions.
187 changes: 183 additions & 4 deletions esmvalcore/cmor/_fixes/cmip6/cesm2.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from shutil import copyfile

import iris
import numpy as np
from netCDF4 import Dataset

Expand Down Expand Up @@ -160,7 +161,7 @@ class Tas(Prw):

def fix_metadata(self, cubes):
"""
Add height (2m) coordinate.
Add height (2m) coordinate and time coordinate.
Fix also done for prw.
Fix latitude_bounds and longitude_bounds data type and round to 4 d.p.
Expand All @@ -172,15 +173,72 @@ def fix_metadata(self, cubes):
Returns
-------
iris.cube.CubeList
iris.cube.CubeList, iris.cube.CubeList
"""
super().fix_metadata(cubes)
# Specific code for tas
cube = self.get_cube_from_list(cubes)
add_scalar_height_coord(cube)

return cubes
new_list = iris.cube.CubeList()
for cube in cubes:
try:
old_time = cube.coord("time")
except iris.exceptions.CoordinateNotFoundError:
new_list.append(cube)
else:
if old_time.is_monotonic():
new_list.append(cube)
else:
time_units = old_time.units
time_data = old_time.points

# erase erroneously copy-pasted points
time_diff = np.diff(time_data)
idx_neg = np.where(time_diff <= 0.0)[0]
while len(idx_neg) > 0:
time_data = np.delete(time_data, idx_neg[0] + 1)
time_diff = np.diff(time_data)
idx_neg = np.where(time_diff <= 0.0)[0]

# create the new time coord
new_time = iris.coords.DimCoord(
time_data,
standard_name="time",
var_name="time",
units=time_units,
)

# create a new cube with the right shape
dims = (
time_data.shape[0],
cube.coord("latitude").shape[0],
cube.coord("longitude").shape[0],
)
data = cube.data
new_data = np.ma.append(
data[: dims[0] - 1, :, :], data[-1, :, :]
)
new_data = new_data.reshape(dims)

tmp_cube = iris.cube.Cube(
new_data,
standard_name=cube.standard_name,
long_name=cube.long_name,
var_name=cube.var_name,
units=cube.units,
attributes=cube.attributes,
cell_methods=cube.cell_methods,
dim_coords_and_dims=[
(new_time, 0),
(cube.coord("latitude"), 1),
(cube.coord("longitude"), 2),
],
)

new_list.append(tmp_cube)

return new_list


class Sftlf(Fix):
Expand Down Expand Up @@ -286,3 +344,124 @@ def fix_metadata(self, cubes):
if z_coord.standard_name is None:
fix_ocean_depth_coord(cube)
return cubes


class Pr(Fix):
"""Fixes for pr."""

def fix_metadata(self, cubes):
"""Fix time coordinates.
Parameters
----------
cubes : iris.cube.CubeList
Cubes to fix
Returns
-------
iris.cube.CubeList
"""
new_list = iris.cube.CubeList()
for cube in cubes:
try:
old_time = cube.coord("time")
except iris.exceptions.CoordinateNotFoundError:
new_list.append(cube)
else:
if old_time.is_monotonic():
new_list.append(cube)
else:
time_units = old_time.units
time_data = old_time.points

# erase erroneously copy-pasted points
time_diff = np.diff(time_data)
idx_neg = np.where(time_diff <= 0.0)[0]
while len(idx_neg) > 0:
time_data = np.delete(time_data, idx_neg[0] + 1)
time_diff = np.diff(time_data)
idx_neg = np.where(time_diff <= 0.0)[0]

# create the new time coord
new_time = iris.coords.DimCoord(
time_data,
standard_name="time",
var_name="time",
units=time_units,
)

# create a new cube with the right shape
dims = (
time_data.shape[0],
cube.coord("latitude").shape[0],
cube.coord("longitude").shape[0],
)
data = cube.data
new_data = np.ma.append(
data[: dims[0] - 1, :, :], data[-1, :, :]
)
new_data = new_data.reshape(dims)

tmp_cube = iris.cube.Cube(
new_data,
standard_name=cube.standard_name,
long_name=cube.long_name,
var_name=cube.var_name,
units=cube.units,
attributes=cube.attributes,
cell_methods=cube.cell_methods,
dim_coords_and_dims=[
(new_time, 0),
(cube.coord("latitude"), 1),
(cube.coord("longitude"), 2),
],
)

new_list.append(tmp_cube)
return new_list


class Tasmin(Pr):
"""Fixes for tasmin."""

def fix_metadata(self, cubes):
"""Fix time and height 2m coordinates.
Fix for time coming from Pr.
Parameters
----------
cubes : iris.cube.CubeList
Cubes to fix
Returns
-------
iris.cube.CubeList
"""
for cube in cubes:
add_scalar_height_coord(cube, height=2.0)
return cubes


class Tasmax(Pr):
"""Fixes for tasmax."""

def fix_metadata(self, cubes):
"""Fix time and height 2m coordinates.
Fix for time coming from Pr.
Parameters
----------
cubes : iris.cube.CubeList
Cubes to fix
Returns
-------
iris.cube.CubeList
"""
for cube in cubes:
add_scalar_height_coord(cube, height=2.0)
return cubes
4 changes: 4 additions & 0 deletions esmvalcore/cmor/_fixes/cmip6/cesm2_fv2.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from .cesm2 import Cl as BaseCl
from .cesm2 import Fgco2 as BaseFgco2
from .cesm2 import Omon as BaseOmon
from .cesm2 import Pr as BasePr
from .cesm2 import Tas as BaseTas

Cl = BaseCl
Expand All @@ -25,3 +26,6 @@


Tas = BaseTas


Pr = BasePr
12 changes: 12 additions & 0 deletions esmvalcore/cmor/_fixes/cmip6/cesm2_waccm.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
from .cesm2 import Cl as BaseCl
from .cesm2 import Fgco2 as BaseFgco2
from .cesm2 import Omon as BaseOmon
from .cesm2 import Pr as BasePr
from .cesm2 import Tas as BaseTas
from .cesm2 import Tasmax as BaseTasmax
from .cesm2 import Tasmin as BaseTasmin


class Cl(BaseCl):
Expand Down Expand Up @@ -64,4 +67,13 @@ def fix_file(self, filepath, output_dir, add_unique_suffix=False):
Siconc = SiconcFixScalarCoord


Pr = BasePr


Tas = BaseTas


Tasmin = BaseTasmin


Tasmax = BaseTasmax
4 changes: 4 additions & 0 deletions esmvalcore/cmor/_fixes/cmip6/cesm2_waccm_fv2.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from ..common import SiconcFixScalarCoord
from .cesm2 import Fgco2 as BaseFgco2
from .cesm2 import Omon as BaseOmon
from .cesm2 import Pr as BasePr
from .cesm2 import Tas as BaseTas
from .cesm2_waccm import Cl as BaseCl
from .cesm2_waccm import Cli as BaseCli
Expand All @@ -27,3 +28,6 @@


Tas = BaseTas


Pr = BasePr
Loading

0 comments on commit 8b4a63a

Please sign in to comment.