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, lonin, latpole, lonpole): 19 """ 20 Rotate a latitude/longitude pair. 21 22 Parameters 23 ---------- 24 **`latin`**: `float` 25 Latitudes in units of degrees. 26 27 **`lonin`**: `float` 28 Longitudes in units of degrees. 29 30 **`latpole`**: `float` 31 Latitude of Pole. 32 33 **`lonpole`**: `float` 34 Longitude of Pole. 35 36 Returns 37 ------- 38 **`tlat, tlons`** 39 Returns two floats of rotated latitude and 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 71 72 73def rot2ll(latin, lonin, latpole, lonpole): 74 """ 75 Unrotate a latitude/longitude pair. 76 77 Parameters 78 ---------- 79 **`latin`**: `float` 80 Latitudes in units of degrees. 81 82 **`lonin`**: `float` 83 Longitudes in units of degrees. 84 85 **`latpole`**: `float` 86 Latitude of Pole. 87 88 **`lonpole`**: `float` 89 Longitude of Pole. 90 91 Returns 92 ------- 93 **`tlat, tlons`** 94 Returns two floats of unrotated latitude and longitude in units of degrees. 95 """ 96 tlon = lonin 97 98 # Convert to xyz coordinates 99 x = math.cos(latin * DEG2RAD) * math.cos(lonin * DEG2RAD) 100 y = math.cos(latin * DEG2RAD) * math.sin(lonin * DEG2RAD) 101 z = math.sin(latin * DEG2RAD) 102 103 # Rotate around y axis 104 rotang = -(latpole + 90) * DEG2RAD 105 sinrot = math.sin(rotang) 106 cosrot = math.cos(rotang) 107 ry = y 108 rx = x * cosrot + z * sinrot 109 rz = -x * sinrot + z * cosrot 110 111 # Convert back to lat/lon 112 tlat = math.asin(rz) / DEG2RAD 113 if math.fabs(rx) > 0.0001: 114 tlon = math.atan2(ry,rx) / DEG2RAD 115 elif ry > 0: 116 tlon = 90.0 117 else: 118 tlon = -90.0 119 120 # Remove the longitude rotation 121 tlon += lonpole 122 if tlon < 0: 123 tlon += 360.0 124 if tlon > 360: 125 tlon -= 360.0 126 127 return tlat, tlon 128 129 130def vector_rotation_angles(tlat, tlon, clat, losp, xlat): 131 """ 132 Generate a rotation angle value that can be applied to a vector quantity to 133 make it Earth-oriented. 134 135 Parameters 136 ---------- 137 **`tlat`**: `float` 138 True latitude in units of degrees. 139 140 **tlon`**: `float` 141 True longitude in units of degrees.. 142 143 **`clat`**: `float` 144 Latitude of center grid point in units of degrees. 145 146 **`losp`**: `float` 147 Longitude of the southern pole in units of degrees. 148 149 **`xlat`**: `float` 150 Latitude of the rotated grid in units of degrees. 151 152 Returns 153 ------- 154 **`rot : float`** 155 Rotation angle in units of radians. 156 """ 157 slon = math.sin((tlon-losp)*DEG2RAD) 158 cgridlat = math.cos(xlat*DEG2RAD) 159 if cgridlat <= 0.0: 160 rot = 0.0 161 else: 162 crot = (math.cos(clat*DEG2RAD)*math.cos(tlat*DEG2RAD)+ 163 math.sin(clat*DEG2RAD)*math.sin(tlat*DEG2RAD)* 164 math.cos(tlon*DEG2RAD))/cgridlat 165 srot = (-1.0*math.sin(clat*DEG2RAD)*slon)/cgridlat 166 rot = math.atan2(srot,crot) 167 return rot
19def ll2rot(latin, lonin, latpole, lonpole): 20 """ 21 Rotate a latitude/longitude pair. 22 23 Parameters 24 ---------- 25 **`latin`**: `float` 26 Latitudes in units of degrees. 27 28 **`lonin`**: `float` 29 Longitudes in units of degrees. 30 31 **`latpole`**: `float` 32 Latitude of Pole. 33 34 **`lonpole`**: `float` 35 Longitude of Pole. 36 37 Returns 38 ------- 39 **`tlat, tlons`** 40 Returns two floats of rotated latitude and longitude in units of degrees. 41 """ 42 tlon = lonin - lonpole 43 44 # Convert to xyz coordinates 45 x = math.cos(latin * DEG2RAD) * math.cos(tlon * DEG2RAD) 46 y = math.cos(latin * DEG2RAD) * math.sin(tlon * DEG2RAD) 47 z = math.sin(latin * DEG2RAD) 48 49 # Rotate around y axis 50 rotang = (latpole + 90) * DEG2RAD 51 sinrot = math.sin(rotang) 52 cosrot = math.cos(rotang) 53 ry = y 54 rx = x * cosrot + z * sinrot 55 rz = -x * sinrot + z * cosrot 56 57 # Convert back to lat/lon 58 tlat = math.asin(rz) / DEG2RAD 59 if math.fabs(rx) > 0.0001: 60 tlon = math.atan2(ry,rx) / DEG2RAD 61 elif ry > 0: 62 tlon = 90.0 63 else: 64 tlon = -90.0 65 66 if tlon < -180: 67 tlon += 360.0 68 if tlon >= 180: 69 tlon -= 360.0 70 71 return tlat, tlon
Rotate a latitude/longitude pair.
Parameters
latin
: float
Latitudes in units of degrees.
lonin
: float
Longitudes in units of degrees.
latpole
: float
Latitude of Pole.
lonpole
: float
Longitude of Pole.
Returns
tlat, tlons
Returns two floats of rotated latitude and longitude in units of degrees.
74def rot2ll(latin, lonin, latpole, lonpole): 75 """ 76 Unrotate a latitude/longitude pair. 77 78 Parameters 79 ---------- 80 **`latin`**: `float` 81 Latitudes in units of degrees. 82 83 **`lonin`**: `float` 84 Longitudes in units of degrees. 85 86 **`latpole`**: `float` 87 Latitude of Pole. 88 89 **`lonpole`**: `float` 90 Longitude of Pole. 91 92 Returns 93 ------- 94 **`tlat, tlons`** 95 Returns two floats of unrotated latitude and longitude in units of degrees. 96 """ 97 tlon = lonin 98 99 # Convert to xyz coordinates 100 x = math.cos(latin * DEG2RAD) * math.cos(lonin * DEG2RAD) 101 y = math.cos(latin * DEG2RAD) * math.sin(lonin * DEG2RAD) 102 z = math.sin(latin * DEG2RAD) 103 104 # Rotate around y axis 105 rotang = -(latpole + 90) * DEG2RAD 106 sinrot = math.sin(rotang) 107 cosrot = math.cos(rotang) 108 ry = y 109 rx = x * cosrot + z * sinrot 110 rz = -x * sinrot + z * cosrot 111 112 # Convert back to lat/lon 113 tlat = math.asin(rz) / DEG2RAD 114 if math.fabs(rx) > 0.0001: 115 tlon = math.atan2(ry,rx) / DEG2RAD 116 elif ry > 0: 117 tlon = 90.0 118 else: 119 tlon = -90.0 120 121 # Remove the longitude rotation 122 tlon += lonpole 123 if tlon < 0: 124 tlon += 360.0 125 if tlon > 360: 126 tlon -= 360.0 127 128 return tlat, tlon
Unrotate a latitude/longitude pair.
Parameters
latin
: float
Latitudes in units of degrees.
lonin
: float
Longitudes in units of degrees.
latpole
: float
Latitude of Pole.
lonpole
: float
Longitude of Pole.
Returns
tlat, tlons
Returns two floats of unrotated latitude and longitude in units of degrees.
131def vector_rotation_angles(tlat, tlon, clat, losp, xlat): 132 """ 133 Generate a rotation angle value that can be applied to a vector quantity to 134 make it Earth-oriented. 135 136 Parameters 137 ---------- 138 **`tlat`**: `float` 139 True latitude in units of degrees. 140 141 **tlon`**: `float` 142 True longitude in units of degrees.. 143 144 **`clat`**: `float` 145 Latitude of center grid point in units of degrees. 146 147 **`losp`**: `float` 148 Longitude of the southern pole in units of degrees. 149 150 **`xlat`**: `float` 151 Latitude of the rotated grid in units of degrees. 152 153 Returns 154 ------- 155 **`rot : float`** 156 Rotation angle in units of radians. 157 """ 158 slon = math.sin((tlon-losp)*DEG2RAD) 159 cgridlat = math.cos(xlat*DEG2RAD) 160 if cgridlat <= 0.0: 161 rot = 0.0 162 else: 163 crot = (math.cos(clat*DEG2RAD)*math.cos(tlat*DEG2RAD)+ 164 math.sin(clat*DEG2RAD)*math.sin(tlat*DEG2RAD)* 165 math.cos(tlon*DEG2RAD))/cgridlat 166 srot = (-1.0*math.sin(clat*DEG2RAD)*slon)/cgridlat 167 rot = math.atan2(srot,crot) 168 return rot
Generate a rotation angle value that can be applied to a vector quantity to make it Earth-oriented.
Parameters
tlat
: float
True latitude in units of degrees.
**tlon**:
float`
True longitude in units of degrees..
clat
: float
Latitude of center grid point in units of degrees.
losp
: float
Longitude of the southern pole in units of degrees.
xlat
: float
Latitude of the rotated grid in units of degrees.
Returns
rot : float
Rotation angle in units of radians.