Coverage for src/CSET/operators/regrid.py: 100%

32 statements  

« prev     ^ index     » next       coverage.py v7.5.4, created at 2024-07-01 15:05 +0000

1# Copyright 2024 Met Office and contributors. 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14 

15"""Operators to regrid cubes.""" 

16 

17import iris 

18import iris.cube 

19import numpy as np 

20 

21from CSET.operators._utils import get_cube_yxcoordname 

22 

23 

24def regrid_onto_cube( 

25 incube: iris.cube.Cube, target: iris.cube.Cube, method: str, **kwargs 

26) -> iris.cube.Cube: 

27 """Regrid a cube, projecting onto a target cube. 

28 

29 Cube must have at least 2 dimensions. 

30 

31 Arguments 

32 ---------- 

33 incube: Cube 

34 An iris cube of the data to regrid. As a minimum, it needs to be 2D with a latitude, 

35 longitude coordinates. 

36 target: Cube 

37 An iris cube of the data to regrid onto. It needs to be 2D with a latitude, 

38 longitude coordinate. 

39 method: str 

40 Method used to regrid onto, etc. Linear will use iris.analysis.Linear() 

41 

42 Returns 

43 ------- 

44 iris.cube.Cube 

45 An iris cube of the data that has been regridded. 

46 

47 Raises 

48 ------ 

49 ValueError 

50 If a unique x/y coordinate cannot be found 

51 NotImplementedError 

52 If the cubes grid, or the method for regridding, is not yet supported. 

53 

54 Notes 

55 ----- 

56 Currently rectlinear grids (uniform) are supported. 

57 """ 

58 # Get y,x coord names 

59 y_coord, x_coord = get_cube_yxcoordname(incube) 

60 

61 # List of supported grids - check if it is compatible 

62 supported_grids = (iris.coord_systems.GeogCS,) 

63 if not isinstance(incube.coord(x_coord).coord_system, supported_grids): 

64 raise NotImplementedError( 

65 f"Does not currently support {incube.coord(x_coord).coord_system} coordinate system" 

66 ) 

67 if not isinstance(incube.coord(y_coord).coord_system, supported_grids): 

68 raise NotImplementedError( 

69 f"Does not currently support {incube.coord(y_coord).coord_system} coordinate system" 

70 ) 

71 

72 regrid_method = getattr(iris.analysis, method, None) 

73 if callable(regrid_method): 

74 return incube.regrid(target, regrid_method()) 

75 else: 

76 raise NotImplementedError(f"Does not currently support {method} regrid method") 

77 

78 

79def regrid_onto_xyspacing( 

80 incube: iris.cube.Cube, xspacing: int, yspacing: int, method: str, **kwargs 

81) -> iris.cube.Cube: 

82 """Regrid cube onto a set x,y spacing. 

83 

84 Regrid cube using specified x,y spacing, which is performed linearly. 

85 

86 Parameters 

87 ---------- 

88 incube: Cube 

89 An iris cube of the data to regrid. As a minimum, it needs to be 2D with a latitude, 

90 longitude coordinates. 

91 xspacing: integer 

92 Spacing of points in longitude direction (could be degrees, meters etc.) 

93 yspacing: integer 

94 Spacing of points in latitude direction (could be degrees, meters etc.) 

95 method: str 

96 Method used to regrid onto, etc. Linear will use iris.analysis.Linear() 

97 

98 Returns 

99 ------- 

100 cube_rgd: Cube 

101 An iris cube of the data that has been regridded. 

102 

103 Raises 

104 ------ 

105 ValueError 

106 If a unique x/y coordinate cannot be found 

107 NotImplementedError 

108 If the cubes grid, or the method for regridding, is not yet supported. 

109 

110 Notes 

111 ----- 

112 Currently rectlinear grids (uniform) are supported. 

113 

114 """ 

115 # Get x,y coord names 

116 y_coord, x_coord = get_cube_yxcoordname(incube) 

117 

118 # List of supported grids - check if it is compatible 

119 supported_grids = (iris.coord_systems.GeogCS,) 

120 if not isinstance(incube.coord(x_coord).coord_system, supported_grids): 

121 raise NotImplementedError( 

122 f"Does not currently support {incube.coord(x_coord).coord_system} regrid method" 

123 ) 

124 if not isinstance(incube.coord(y_coord).coord_system, supported_grids): 

125 raise NotImplementedError( 

126 f"Does not currently support {incube.coord(y_coord).coord_system} regrid method" 

127 ) 

128 

129 # Get axis 

130 lat, lon = incube.coord(y_coord), incube.coord(x_coord) 

131 

132 # Get bounds 

133 lat_min, lon_min = lat.points.min(), lon.points.min() 

134 lat_max, lon_max = lat.points.max(), lon.points.max() 

135 

136 # Generate new mesh 

137 latout = np.arange(lat_min, lat_max, yspacing) 

138 lonout = np.arange(lon_min, lon_max, xspacing) 

139 

140 regrid_method = getattr(iris.analysis, method, None) 

141 if callable(regrid_method): 

142 cube_rgd = incube.interpolate( 

143 [(y_coord, latout), (x_coord, lonout)], regrid_method() 

144 ) 

145 else: 

146 raise NotImplementedError(f"Does not currently support {method} regrid method") 

147 

148 return cube_rgd