# grib2io.utils.rotated_grid

Tools for working with Rotated Lat/Lon Grids.

View Source

      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): View Source

    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): View Source

     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.