-
Notifications
You must be signed in to change notification settings - Fork 48
Added new Extract surface preprocessor #1048
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 10 commits
6f977cd
e47fc4a
66147bc
22e6f4b
a68937b
b9b5800
3c7b0c0
c6c8e36
a027d96
cb78b9c
0b04d4e
319ba19
053cfc0
96fc7e4
deb6918
2f729e9
d644526
da8cf7e
574f9f8
4378116
54a5105
0c539c3
5f5bb10
a5a933b
d471de2
6eb521c
c17f85b
7df08ee
87b5f48
b53a991
3611451
a87d290
3f1b881
8d3bf2d
443208f
62d091a
e2c76b1
ad9b702
6909061
c88898b
a7bccf8
439ce43
3961cfc
893aaaf
c9cdbe4
f0637f2
fc61e06
09543a0
92a6207
3676f66
3b1c0a2
845cc8d
b562249
993ceaa
fc60589
ce87c3c
15807ae
0947529
ca850b1
d4a2552
2b32a17
b50b094
fae8f0c
f200c14
2d13465
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -295,6 +295,68 @@ def volume_statistics( | |
| return _create_cube_time(src_cube, result, times) | ||
|
|
||
|
|
||
| def extract_surface(cube): | ||
| """ | ||
| Extact the surface layer from a 3D cube. | ||
|
|
||
| Extracts the entire layer along the z axis where the z coordinate is | ||
| the minimum of the absolute value of the z-axis dimensions points. | ||
|
|
||
| Requires a cube with a z axis. | ||
|
|
||
| This assumes that the surface is the closest layer to zero. | ||
| This assumption is usually true in the ocean, but may not be the | ||
| case in all models for all z-axes. | ||
|
|
||
| In the case of temporally or spatially varying depth grid, | ||
| (ie the depth array is 3D or 4D), the surface layer is determined | ||
| using the mean of the depth points along the time, latitude and | ||
| longitude axes. This preprocessor may also behave strangely | ||
| if the z axis data are not monotonic, or unusual in some other way. | ||
|
|
||
| The preprocessor extract_layer can also do this, but it may be | ||
| much slower and more memory intensie as it regrids. | ||
| It is more robust to variability in the grid definitions. | ||
|
|
||
| Arguments | ||
|
ledm marked this conversation as resolved.
Outdated
|
||
| --------- | ||
|
ledm marked this conversation as resolved.
Outdated
|
||
| cube: iris.cube.Cube | ||
| input cube. | ||
|
|
||
| Returns | ||
| ------- | ||
| iris.cube.Cube | ||
| collapsed cube. | ||
|
|
||
| """ | ||
| # Get the z axis. | ||
| zcoord = cube.coord(axis='Z') | ||
| positive = zcoord.attributes['positive'] | ||
|
|
||
| # Get the Z points: | ||
| if zcoord.points.ndim == 1: | ||
| points = zcoord.points | ||
| elif zcoord.points.ndim == 3: | ||
| points = zcoord.points.mean(axis=[1, 2]) | ||
| elif zcoord.points.ndim == 4: | ||
| points = zcoord.points.mean(axis=[0, 2, 3]) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. either way, maybe add an exception if any of the dims are not the ones you analyze
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right. The problem with that (and this method as a whole) is that it makes assumptions about the z-axis position. For instance, what if you have a cube with dimensions (time, depth, latitude) ie a meridional transect? The preprocessor would fail. Maybe instead of that, we could replace this if-else loop with something more generic? |
||
|
|
||
| # Calculate the surface layer index: | ||
| surf = np.abs(points).argmin() | ||
|
|
||
| # Get the z axis dimension in the cude: | ||
| zcoord_dim = cube.coord_dims(zcoord) | ||
| if zcoord_dim in [0, (0,)]: | ||
| return cube[surf] | ||
|
|
||
| if zcoord_dim in [1, (1,)]: | ||
| return cube[:, surf] | ||
|
|
||
| logger.error('Condition not recognised: postive: %s , zcoord_dim: %s, ' | ||
| 'surface level: %s', positive, zcoord_dim, surf) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is a very cryptic exception, could you reformulate for the user to understand what actually is wrong pls? |
||
| return cube | ||
|
|
||
|
|
||
| def depth_integration(cube): | ||
| """ | ||
| Determine the total sum over the vertical component. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,7 +10,9 @@ | |
| from esmvalcore.preprocessor._volume import (volume_statistics, | ||
| depth_integration, | ||
| extract_trajectory, | ||
| extract_transect, extract_volume) | ||
| extract_transect, | ||
| extract_volume, | ||
| extract_surface) | ||
|
|
||
|
|
||
| class Test(tests.Test): | ||
|
|
@@ -19,6 +21,7 @@ class Test(tests.Test): | |
| def setUp(self): | ||
| """Prepare tests""" | ||
| coord_sys = iris.coord_systems.GeogCS(iris.fileformats.pp.EARTH_RADIUS) | ||
| data0 = np.ones((2, 2)) | ||
| data1 = np.ones((3, 2, 2)) | ||
| data2 = np.ma.ones((2, 3, 2, 2)) | ||
| data3 = np.ma.ones((4, 3, 2, 2)) | ||
|
|
@@ -61,6 +64,9 @@ def setUp(self): | |
| units='degrees_north', | ||
| coord_system=coord_sys) | ||
|
|
||
| coords_spec2 = [(lats2, 0), (lons2, 1)] | ||
| self.grid_2d = iris.cube.Cube(data0, dim_coords_and_dims=coords_spec2) | ||
|
|
||
| coords_spec3 = [(zcoord, 0), (lats2, 1), (lons2, 2)] | ||
| self.grid_3d = iris.cube.Cube(data1, dim_coords_and_dims=coords_spec3) | ||
|
|
||
|
|
@@ -152,6 +158,13 @@ def test_extract_trajectory(self): | |
| expected = np.ones((3, 2)) | ||
| self.assert_array_equal(result.data, expected) | ||
|
|
||
| def test_extract_surface(self): | ||
| """Tests to extract the surface from a 3D and 4D cube.""" | ||
| result = extract_surface(self.grid_3d) | ||
| self.assert_array_equal(result.data, self.grid_2d.data) | ||
| result2 = extract_surface(self.grid_4d) | ||
| self.assert_array_equal(self.grid_4d[:, 0, :, :].data, result2.data) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do you have a case for 1D as well? |
||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| unittest.main() | ||
Uh oh!
There was an error while loading. Please reload this page.