grib2io.utils.arakawa_rotated_grid
Functions for handling an Arakawa Rotated Lat/Lon Grids.
This grid is not often used, but is currently used for the NCEP/RAP using GRIB2 Grid Definition Template 32769
These functions are adapted from the NCAR Command Language (ncl), from NcGRIB2.c
1""" 2Functions for handling an Arakawa Rotated Lat/Lon Grids. 3 4This grid is not often used, but is currently used for the NCEP/RAP using 5[GRIB2 Grid Definition Template 32769](https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_temp3-32769.shtml) 6 7These functions are adapted from the NCAR Command Language (ncl), 8from [NcGRIB2.c](https://github.com/NCAR/ncl/blob/develop/ni/src/ncl/NclGRIB2.c) 9""" 10import math 11import numpy as np 12 13from . import rotated_grid 14 15DEG2RAD = rotated_grid.DEG2RAD 16RAD2DEG = rotated_grid.RAD2DEG 17 18def ll2rot(latin: float, lonin: float, latpole: float, lonpole: float) -> tuple[float, float]: 19 """ 20 Rotate a latitude/longitude pair. 21 22 Parameters 23 ---------- 24 latin 25 Unrotated latitude in units of degrees. 26 lonin 27 Unrotated longitude in units of degrees. 28 latpole 29 Latitude of Pole. 30 lonpole 31 Longitude of Pole. 32 33 Returns 34 ------- 35 tlat 36 Rotated latitude in units of degrees. 37 tlons 38 Rotated longitude in units of degrees. 39 """ 40 tlon = lonin - lonpole 41 42 # Convert to xyz coordinates 43 x = math.cos(latin * DEG2RAD) * math.cos(tlon * DEG2RAD) 44 y = math.cos(latin * DEG2RAD) * math.sin(tlon * DEG2RAD) 45 z = math.sin(latin * DEG2RAD) 46 47 # Rotate around y axis 48 rotang = (latpole + 90) * DEG2RAD 49 sinrot = math.sin(rotang) 50 cosrot = math.cos(rotang) 51 ry = y 52 rx = x * cosrot + z * sinrot 53 rz = -x * sinrot + z * cosrot 54 55 # Convert back to lat/lon 56 tlat = math.asin(rz) / DEG2RAD 57 if math.fabs(rx) > 0.0001: 58 tlon = math.atan2(ry,rx) / DEG2RAD 59 elif ry > 0: 60 tlon = 90.0 61 else: 62 tlon = -90.0 63 64 if tlon < -180: 65 tlon += 360.0 66 if tlon >= 180: 67 tlon -= 360.0 68 69 return tlat, tlon 70 71 72def rot2ll(latin: float, lonin: float, latpole: float, lonpole: float) -> tuple[float, float]: 73 """ 74 Unrotate a latitude/longitude pair. 75 76 Parameters 77 ---------- 78 latin 79 Rotated latitude in units of degrees. 80 lonin 81 Rotated longitude in units of degrees. 82 latpole 83 Latitude of Pole. 84 lonpole 85 Longitude of Pole. 86 87 Returns 88 ------- 89 tlat 90 Unrotated latitude in units of degrees. 91 tlons 92 Unrotated longitude in units of degrees. 93 """ 94 tlon = lonin 95 96 # Convert to xyz coordinates 97 x = math.cos(latin * DEG2RAD) * math.cos(lonin * DEG2RAD) 98 y = math.cos(latin * DEG2RAD) * math.sin(lonin * DEG2RAD) 99 z = math.sin(latin * DEG2RAD) 100 101 # Rotate around y axis 102 rotang = -(latpole + 90) * DEG2RAD 103 sinrot = math.sin(rotang) 104 cosrot = math.cos(rotang) 105 ry = y 106 rx = x * cosrot + z * sinrot 107 rz = -x * sinrot + z * cosrot 108 109 # Convert back to lat/lon 110 tlat = math.asin(rz) / DEG2RAD 111 if math.fabs(rx) > 0.0001: 112 tlon = math.atan2(ry,rx) / DEG2RAD 113 elif ry > 0: 114 tlon = 90.0 115 else: 116 tlon = -90.0 117 118 # Remove the longitude rotation 119 tlon += lonpole 120 if tlon < 0: 121 tlon += 360.0 122 if tlon > 360: 123 tlon -= 360.0 124 125 return tlat, tlon 126 127 128def vector_rotation_angles( 129 tlat: float, 130 tlon: float, 131 clat: float, 132 losp: float, 133 xlat: float, 134) -> float: 135 """ 136 Generate a rotation angle value. 137 138 The rotation angle value can be applied to a vector quantity to make it 139 Earth-oriented. 140 141 Parameters 142 ---------- 143 tlat 144 True latitude in units of degrees. 145 tlon 146 True longitude in units of degrees.. 147 clat 148 Latitude of center grid point in units of degrees. 149 losp 150 Longitude of the southern pole in units of degrees. 151 xlat 152 Latitude of the rotated grid in units of degrees. 153 154 Returns 155 ------- 156 rot 157 Rotation angle in units of radians. 158 """ 159 slon = math.sin((tlon-losp)*DEG2RAD) 160 cgridlat = math.cos(xlat*DEG2RAD) 161 if cgridlat <= 0.0: 162 rot = 0.0 163 else: 164 crot = (math.cos(clat*DEG2RAD)*math.cos(tlat*DEG2RAD)+ 165 math.sin(clat*DEG2RAD)*math.sin(tlat*DEG2RAD)* 166 math.cos(tlon*DEG2RAD))/cgridlat 167 srot = (-1.0*math.sin(clat*DEG2RAD)*slon)/cgridlat 168 rot = math.atan2(srot,crot) 169 return rot
DEG2RAD =
0.017453292519943295
RAD2DEG =
57.29577951308232
def
ll2rot( latin: float, lonin: float, latpole: float, lonpole: float) -> tuple[float, float]:
19def ll2rot(latin: float, lonin: float, latpole: float, lonpole: float) -> tuple[float, float]: 20 """ 21 Rotate a latitude/longitude pair. 22 23 Parameters 24 ---------- 25 latin 26 Unrotated latitude in units of degrees. 27 lonin 28 Unrotated longitude in units of degrees. 29 latpole 30 Latitude of Pole. 31 lonpole 32 Longitude of Pole. 33 34 Returns 35 ------- 36 tlat 37 Rotated latitude in units of degrees. 38 tlons 39 Rotated longitude in units of degrees. 40 """ 41 tlon = lonin - lonpole 42 43 # Convert to xyz coordinates 44 x = math.cos(latin * DEG2RAD) * math.cos(tlon * DEG2RAD) 45 y = math.cos(latin * DEG2RAD) * math.sin(tlon * DEG2RAD) 46 z = math.sin(latin * DEG2RAD) 47 48 # Rotate around y axis 49 rotang = (latpole + 90) * DEG2RAD 50 sinrot = math.sin(rotang) 51 cosrot = math.cos(rotang) 52 ry = y 53 rx = x * cosrot + z * sinrot 54 rz = -x * sinrot + z * cosrot 55 56 # Convert back to lat/lon 57 tlat = math.asin(rz) / DEG2RAD 58 if math.fabs(rx) > 0.0001: 59 tlon = math.atan2(ry,rx) / DEG2RAD 60 elif ry > 0: 61 tlon = 90.0 62 else: 63 tlon = -90.0 64 65 if tlon < -180: 66 tlon += 360.0 67 if tlon >= 180: 68 tlon -= 360.0 69 70 return tlat, tlon
Rotate a latitude/longitude pair.
Parameters
- latin: Unrotated latitude in units of degrees.
- lonin: Unrotated longitude in units of degrees.
- latpole: Latitude of Pole.
- lonpole: Longitude of Pole.
Returns
- tlat: Rotated latitude in units of degrees.
- tlons: Rotated longitude in units of degrees.
def
rot2ll( latin: float, lonin: float, latpole: float, lonpole: float) -> tuple[float, float]:
73def rot2ll(latin: float, lonin: float, latpole: float, lonpole: float) -> tuple[float, float]: 74 """ 75 Unrotate a latitude/longitude pair. 76 77 Parameters 78 ---------- 79 latin 80 Rotated latitude in units of degrees. 81 lonin 82 Rotated longitude in units of degrees. 83 latpole 84 Latitude of Pole. 85 lonpole 86 Longitude of Pole. 87 88 Returns 89 ------- 90 tlat 91 Unrotated latitude in units of degrees. 92 tlons 93 Unrotated longitude in units of degrees. 94 """ 95 tlon = lonin 96 97 # Convert to xyz coordinates 98 x = math.cos(latin * DEG2RAD) * math.cos(lonin * DEG2RAD) 99 y = math.cos(latin * DEG2RAD) * math.sin(lonin * DEG2RAD) 100 z = math.sin(latin * DEG2RAD) 101 102 # Rotate around y axis 103 rotang = -(latpole + 90) * DEG2RAD 104 sinrot = math.sin(rotang) 105 cosrot = math.cos(rotang) 106 ry = y 107 rx = x * cosrot + z * sinrot 108 rz = -x * sinrot + z * cosrot 109 110 # Convert back to lat/lon 111 tlat = math.asin(rz) / DEG2RAD 112 if math.fabs(rx) > 0.0001: 113 tlon = math.atan2(ry,rx) / DEG2RAD 114 elif ry > 0: 115 tlon = 90.0 116 else: 117 tlon = -90.0 118 119 # Remove the longitude rotation 120 tlon += lonpole 121 if tlon < 0: 122 tlon += 360.0 123 if tlon > 360: 124 tlon -= 360.0 125 126 return tlat, tlon
Unrotate a latitude/longitude pair.
Parameters
- latin: Rotated latitude in units of degrees.
- lonin: Rotated longitude in units of degrees.
- latpole: Latitude of Pole.
- lonpole: Longitude of Pole.
Returns
- tlat: Unrotated latitude in units of degrees.
- tlons: Unrotated longitude in units of degrees.
def
vector_rotation_angles(tlat: float, tlon: float, clat: float, losp: float, xlat: float) -> float:
129def vector_rotation_angles( 130 tlat: float, 131 tlon: float, 132 clat: float, 133 losp: float, 134 xlat: float, 135) -> float: 136 """ 137 Generate a rotation angle value. 138 139 The rotation angle value can be applied to a vector quantity to make it 140 Earth-oriented. 141 142 Parameters 143 ---------- 144 tlat 145 True latitude in units of degrees. 146 tlon 147 True longitude in units of degrees.. 148 clat 149 Latitude of center grid point in units of degrees. 150 losp 151 Longitude of the southern pole in units of degrees. 152 xlat 153 Latitude of the rotated grid in units of degrees. 154 155 Returns 156 ------- 157 rot 158 Rotation angle in units of radians. 159 """ 160 slon = math.sin((tlon-losp)*DEG2RAD) 161 cgridlat = math.cos(xlat*DEG2RAD) 162 if cgridlat <= 0.0: 163 rot = 0.0 164 else: 165 crot = (math.cos(clat*DEG2RAD)*math.cos(tlat*DEG2RAD)+ 166 math.sin(clat*DEG2RAD)*math.sin(tlat*DEG2RAD)* 167 math.cos(tlon*DEG2RAD))/cgridlat 168 srot = (-1.0*math.sin(clat*DEG2RAD)*slon)/cgridlat 169 rot = math.atan2(srot,crot) 170 return rot
Generate a rotation angle value.
The rotation angle value can be applied to a vector quantity to make it Earth-oriented.
Parameters
- tlat: True latitude in units of degrees.
- tlon: True longitude in units of degrees..
- clat: Latitude of center grid point in units of degrees.
- losp: Longitude of the southern pole in units of degrees.
- xlat: Latitude of the rotated grid in units of degrees.
Returns
- rot: Rotation angle in units of radians.