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

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