# grib2io.utils.gauss_grid

Tools for working with Gaussian grids.

View Source

     1"""
     2Tools for working with Gaussian grids.
     3"""
     4
     5# Adopted from: https://gist.github.com/ajdawson/b64d24dfac618b91974f
     6from __future__ import (absolute_import, division, print_function)
     7
     8import functools
     9
    10import numpy as np
    11import numpy.linalg as la
    12from numpy.polynomial.legendre import legcompanion, legder, legval
    13
    14
    15def __single_arg_fast_cache(func):
    16    """Caching decorator for functions of one argument."""
    17    class CachingDict(dict):
    18
    19        def __missing__(self, key):
    20            result = self[key] = func(key)
    21            return result
    22
    23        @functools.wraps(func)
    24        def __getitem__(self, *args, **kwargs):
    25            return super(CachingDict, self).__getitem__(*args, **kwargs)
    26
    27    return CachingDict().__getitem__
    28
    29
    30@__single_arg_fast_cache
    31def gaussian_latitudes(nlat):
    32    """
    33    Construct latitudes for a Gaussian grid.
    34
    35    Parameters
    36    ----------
    37
    38    **`nlat`**: The number of latitudes in the Gaussian grid.
    39
    40    Returns
    41    -------
    42
    43    Numpy array of latitudes (in degrees) with a length of `nlat`.
    44    """
    45    if abs(int(nlat)) != nlat:
    46        raise ValueError('nlat must be a non-negative integer')
    47    # Create the coefficients of the Legendre polynomial and construct the
    48    # companion matrix:
    49    cs = np.array([0] * nlat + [1], dtype=int)
    50    cm = legcompanion(cs)
    51    # Compute the eigenvalues of the companion matrix (the roots of the
    52    # Legendre polynomial) taking advantage of the fact that the matrix is
    53    # symmetric:
    54    roots = la.eigvalsh(cm)
    55    roots.sort()
    56    # Improve the roots by one application of Newton's method, using the
    57    # solved root as the initial guess:
    58    fx = legval(roots, cs)
    59    fpx = legval(roots, legder(cs))
    60    roots -= fx / fpx
    61    # The roots should exhibit symmetry, but with a sign change, so make sure
    62    # this is the case:
    63    roots = (roots - roots[::-1]) / 2.
    64    # Convert the roots from the interval [-1, 1] to latitude values on the
    65    # interval [-90, 90] degrees:
    66    latitudes = np.rad2deg(np.arcsin(roots))
    67    # Flip latitudes such that it is oriented from North to South [90, -90]
    68    latitudes = np.flip(latitudes)
    69    return latitudes

def gaussian_latitudes(): View Source

    31@__single_arg_fast_cache
    32def gaussian_latitudes(nlat):
    33    """
    34    Construct latitudes for a Gaussian grid.
    35
    36    Parameters
    37    ----------
    38
    39    **`nlat`**: The number of latitudes in the Gaussian grid.
    40
    41    Returns
    42    -------
    43
    44    Numpy array of latitudes (in degrees) with a length of `nlat`.
    45    """
    46    if abs(int(nlat)) != nlat:
    47        raise ValueError('nlat must be a non-negative integer')
    48    # Create the coefficients of the Legendre polynomial and construct the
    49    # companion matrix:
    50    cs = np.array([0] * nlat + [1], dtype=int)
    51    cm = legcompanion(cs)
    52    # Compute the eigenvalues of the companion matrix (the roots of the
    53    # Legendre polynomial) taking advantage of the fact that the matrix is
    54    # symmetric:
    55    roots = la.eigvalsh(cm)
    56    roots.sort()
    57    # Improve the roots by one application of Newton's method, using the
    58    # solved root as the initial guess:
    59    fx = legval(roots, cs)
    60    fpx = legval(roots, legder(cs))
    61    roots -= fx / fpx
    62    # The roots should exhibit symmetry, but with a sign change, so make sure
    63    # this is the case:
    64    roots = (roots - roots[::-1]) / 2.
    65    # Convert the roots from the interval [-1, 1] to latitude values on the
    66    # interval [-90, 90] degrees:
    67    latitudes = np.rad2deg(np.arcsin(roots))
    68    # Flip latitudes such that it is oriented from North to South [90, -90]
    69    latitudes = np.flip(latitudes)
    70    return latitudes

Construct latitudes for a Gaussian grid.

## Parameters

`nlat`: The number of latitudes in the Gaussian grid.

## Returns

Numpy array of latitudes (in degrees) with a length of `nlat`.