grib2io.utils.rotated_grid

Tools for working with Rotated Lat/Lon Grids.

  1"""
  2Tools for working with Rotated Lat/Lon Grids.
  3"""
  4
  5import numpy as np
  6
  7RAD2DEG = 57.29577951308232087684
  8DEG2RAD = 0.01745329251994329576
  9
 10def rotate(latin, lonin, aor, splat, splon):
 11    """ 
 12    Perform grid rotation. This function is adapted from ECMWF's ecCodes library
 13    void function, rotate().
 14
 15    https://github.com/ecmwf/eccodes/blob/develop/src/grib_geography.cc
 16
 17    Parameters
 18    ----------
 19
 20    **`latin`**: `float or array_like`
 21
 22    Latitudes in units of degrees.
 23
 24    **`lonin`**: `float or array_like`
 25
 26    Longitudes in units of degrees.
 27
 28    **`aor`**: `float`
 29
 30    Angle of rotation as defined in GRIB2 GDTN 4.1.
 31
 32    **`splat`**: `float`
 33
 34    Latitude of South Pole as defined in GRIB2 GDTN 4.1.
 35
 36    **`splon`**: `float`
 37
 38    Longitude of South Pole as defined in GRIB2 GDTN 4.1.
 39
 40    Returns
 41    -------
 42
 43    **`lats, lons : numpy.ndarray`**
 44
 45    Returns two numpy.ndarrays with dtype=numpy.float32 of grid latitudes and
 46    longitudes in units of degrees.
 47    """ 
 48    zsycen = np.sin(DEG2RAD * (splat + 90.))
 49    zcycen = np.cos(DEG2RAD * (splat + 90.))
 50    zxmxc  = DEG2RAD * (lonin - splon)
 51    zsxmxc = np.sin(zxmxc)
 52    zcxmxc = np.cos(zxmxc)
 53    zsyreg = np.sin(DEG2RAD * latin)
 54    zcyreg = np.cos(DEG2RAD * latin)
 55    zsyrot = zcycen * zsyreg - zsycen * zcyreg * zcxmxc
 56
 57    zsyrot = np.where(zsyrot>1.0,1.0,zsyrot)
 58    zsyrot = np.where(zsyrot<-1.0,-1.0,zsyrot)
 59
 60    pyrot = np.arcsin(zsyrot) * RAD2DEG
 61
 62    zcyrot = np.cos(pyrot * DEG2RAD)
 63    zcxrot = (zcycen * zcyreg * zcxmxc + zsycen * zsyreg) / zcyrot
 64    zcxrot = np.where(zcxrot>1.0,1.0,zcxrot)
 65    zcxrot = np.where(zcxrot<-1.0,-1.0,zcxrot)
 66    zsxrot = zcyreg * zsxmxc / zcyrot
 67
 68    pxrot = np.arccos(zcxrot) * RAD2DEG
 69
 70    pxrot = np.where(zsxrot<0.0,-pxrot,pxrot)
 71
 72    return pyrot, pxrot
 73
 74
 75def unrotate(latin, lonin, aor, splat, splon):
 76    """ 
 77    Perform grid un-rotation. This function is adapted from ECMWF's ecCodes library
 78    void function, unrotate().
 79
 80    https://github.com/ecmwf/eccodes/blob/develop/src/grib_geography.cc
 81
 82    Parameters
 83    ----------
 84
 85    **`latin`**: `float or array_like`
 86
 87    Latitudes in units of degrees.
 88
 89    **`lonin`**: `float or array_like`
 90
 91    Longitudes in units of degrees.
 92
 93    **`aor`**: `float`
 94
 95    Angle of rotation as defined in GRIB2 GDTN 4.1.
 96
 97    **`splat`**: `float`
 98
 99    Latitude of South Pole as defined in GRIB2 GDTN 4.1.
100
101    **`splon`**: `float`
102
103    Longitude of South Pole as defined in GRIB2 GDTN 4.1.
104
105    Returns
106    -------
107
108    **`lats, lons : numpy.ndarray`**
109
110    Returns two numpy.ndarrays with dtype=numpy.float32 of grid latitudes and
111    longitudes in units of degrees.
112    """
113    lon_x = lonin
114    lat_y = latin
115
116    latr = lat_y * DEG2RAD
117    lonr = lon_x * DEG2RAD
118
119    xd = np.cos(lonr) * np.cos(latr)
120    yd = np.sin(lonr) * np.cos(latr)
121    zd = np.sin(latr)
122
123    t = -(90.0 + splat)
124    o = -splon
125
126    sin_t = np.sin(DEG2RAD * t)
127    cos_t = np.cos(DEG2RAD * t)
128    sin_o = np.sin(DEG2RAD * o)
129    cos_o = np.cos(DEG2RAD * o)
130
131    x = cos_t * cos_o * xd + sin_o * yd + sin_t * cos_o * zd
132    y = -cos_t * sin_o * xd + cos_o * yd - sin_t * sin_o * zd
133    z = -sin_t * xd + cos_t * zd
134
135    ret_lat = 0
136    ret_lon = 0
137
138    # Then convert back to 'normal' (lat,lon)
139    # Uses arcsin, to convert back to degrees, put in range -1 to 1 in case of slight rounding error
140    # avoid error on calculating e.g. asin(1.00000001)
141    z = np.where(z>1.0,1.0,z)
142    z = np.where(z<-1.0,-1.0,z)
143
144    ret_lat = np.arcsin(z) * RAD2DEG
145    ret_lon = np.arctan2(y, x) * RAD2DEG
146
147    # Still get a very small rounding error, round to 6 decimal places
148    ret_lat = np.round(ret_lat * 1000000.0) / 1000000.0
149    ret_lon = np.round(ret_lon * 1000000.0) / 1000000.0
150
151    ret_lon -= aor
152
153    return ret_lat, ret_lon
RAD2DEG = 57.29577951308232
DEG2RAD = 0.017453292519943295
def rotate(latin, lonin, aor, splat, splon):
11def rotate(latin, lonin, aor, splat, splon):
12    """ 
13    Perform grid rotation. This function is adapted from ECMWF's ecCodes library
14    void function, rotate().
15
16    https://github.com/ecmwf/eccodes/blob/develop/src/grib_geography.cc
17
18    Parameters
19    ----------
20
21    **`latin`**: `float or array_like`
22
23    Latitudes in units of degrees.
24
25    **`lonin`**: `float or array_like`
26
27    Longitudes in units of degrees.
28
29    **`aor`**: `float`
30
31    Angle of rotation as defined in GRIB2 GDTN 4.1.
32
33    **`splat`**: `float`
34
35    Latitude of South Pole as defined in GRIB2 GDTN 4.1.
36
37    **`splon`**: `float`
38
39    Longitude of South Pole as defined in GRIB2 GDTN 4.1.
40
41    Returns
42    -------
43
44    **`lats, lons : numpy.ndarray`**
45
46    Returns two numpy.ndarrays with dtype=numpy.float32 of grid latitudes and
47    longitudes in units of degrees.
48    """ 
49    zsycen = np.sin(DEG2RAD * (splat + 90.))
50    zcycen = np.cos(DEG2RAD * (splat + 90.))
51    zxmxc  = DEG2RAD * (lonin - splon)
52    zsxmxc = np.sin(zxmxc)
53    zcxmxc = np.cos(zxmxc)
54    zsyreg = np.sin(DEG2RAD * latin)
55    zcyreg = np.cos(DEG2RAD * latin)
56    zsyrot = zcycen * zsyreg - zsycen * zcyreg * zcxmxc
57
58    zsyrot = np.where(zsyrot>1.0,1.0,zsyrot)
59    zsyrot = np.where(zsyrot<-1.0,-1.0,zsyrot)
60
61    pyrot = np.arcsin(zsyrot) * RAD2DEG
62
63    zcyrot = np.cos(pyrot * DEG2RAD)
64    zcxrot = (zcycen * zcyreg * zcxmxc + zsycen * zsyreg) / zcyrot
65    zcxrot = np.where(zcxrot>1.0,1.0,zcxrot)
66    zcxrot = np.where(zcxrot<-1.0,-1.0,zcxrot)
67    zsxrot = zcyreg * zsxmxc / zcyrot
68
69    pxrot = np.arccos(zcxrot) * RAD2DEG
70
71    pxrot = np.where(zsxrot<0.0,-pxrot,pxrot)
72
73    return pyrot, pxrot

Perform grid rotation. This function is adapted from ECMWF's ecCodes library void function, rotate().

https://github.com/ecmwf/eccodes/blob/develop/src/grib_geography.cc

Parameters

latin: float or array_like

Latitudes in units of degrees.

lonin: float or array_like

Longitudes in units of degrees.

aor: float

Angle of rotation as defined in GRIB2 GDTN 4.1.

splat: float

Latitude of South Pole as defined in GRIB2 GDTN 4.1.

splon: float

Longitude of South Pole as defined in GRIB2 GDTN 4.1.

Returns

lats, lons : numpy.ndarray

Returns two numpy.ndarrays with dtype=numpy.float32 of grid latitudes and longitudes in units of degrees.

def unrotate(latin, lonin, aor, splat, splon):
 76def unrotate(latin, lonin, aor, splat, splon):
 77    """ 
 78    Perform grid un-rotation. This function is adapted from ECMWF's ecCodes library
 79    void function, unrotate().
 80
 81    https://github.com/ecmwf/eccodes/blob/develop/src/grib_geography.cc
 82
 83    Parameters
 84    ----------
 85
 86    **`latin`**: `float or array_like`
 87
 88    Latitudes in units of degrees.
 89
 90    **`lonin`**: `float or array_like`
 91
 92    Longitudes in units of degrees.
 93
 94    **`aor`**: `float`
 95
 96    Angle of rotation as defined in GRIB2 GDTN 4.1.
 97
 98    **`splat`**: `float`
 99
100    Latitude of South Pole as defined in GRIB2 GDTN 4.1.
101
102    **`splon`**: `float`
103
104    Longitude of South Pole as defined in GRIB2 GDTN 4.1.
105
106    Returns
107    -------
108
109    **`lats, lons : numpy.ndarray`**
110
111    Returns two numpy.ndarrays with dtype=numpy.float32 of grid latitudes and
112    longitudes in units of degrees.
113    """
114    lon_x = lonin
115    lat_y = latin
116
117    latr = lat_y * DEG2RAD
118    lonr = lon_x * DEG2RAD
119
120    xd = np.cos(lonr) * np.cos(latr)
121    yd = np.sin(lonr) * np.cos(latr)
122    zd = np.sin(latr)
123
124    t = -(90.0 + splat)
125    o = -splon
126
127    sin_t = np.sin(DEG2RAD * t)
128    cos_t = np.cos(DEG2RAD * t)
129    sin_o = np.sin(DEG2RAD * o)
130    cos_o = np.cos(DEG2RAD * o)
131
132    x = cos_t * cos_o * xd + sin_o * yd + sin_t * cos_o * zd
133    y = -cos_t * sin_o * xd + cos_o * yd - sin_t * sin_o * zd
134    z = -sin_t * xd + cos_t * zd
135
136    ret_lat = 0
137    ret_lon = 0
138
139    # Then convert back to 'normal' (lat,lon)
140    # Uses arcsin, to convert back to degrees, put in range -1 to 1 in case of slight rounding error
141    # avoid error on calculating e.g. asin(1.00000001)
142    z = np.where(z>1.0,1.0,z)
143    z = np.where(z<-1.0,-1.0,z)
144
145    ret_lat = np.arcsin(z) * RAD2DEG
146    ret_lon = np.arctan2(y, x) * RAD2DEG
147
148    # Still get a very small rounding error, round to 6 decimal places
149    ret_lat = np.round(ret_lat * 1000000.0) / 1000000.0
150    ret_lon = np.round(ret_lon * 1000000.0) / 1000000.0
151
152    ret_lon -= aor
153
154    return ret_lat, ret_lon

Perform grid un-rotation. This function is adapted from ECMWF's ecCodes library void function, unrotate().

https://github.com/ecmwf/eccodes/blob/develop/src/grib_geography.cc

Parameters

latin: float or array_like

Latitudes in units of degrees.

lonin: float or array_like

Longitudes in units of degrees.

aor: float

Angle of rotation as defined in GRIB2 GDTN 4.1.

splat: float

Latitude of South Pole as defined in GRIB2 GDTN 4.1.

splon: float

Longitude of South Pole as defined in GRIB2 GDTN 4.1.

Returns

lats, lons : numpy.ndarray

Returns two numpy.ndarrays with dtype=numpy.float32 of grid latitudes and longitudes in units of degrees.