Source code for atmos_flux_inversion.covariances

"""Support classes for covariances.

See Also
--------
atmos_flux_inversion.correlations
"""
from __future__ import absolute_import

import numpy as np
from numpy import newaxis, sqrt

from .linalg import (
    ProductLinearOperator, SelfAdjointLinearOperator,
    DiagonalOperator, matrix_sqrt)

OBSERVATION_INTERVAL = np.array(1, dtype="m8[h]")
"""The time between individual observations at one site.

More precisely, these are the units used with the correlation function
used in :func:`observation_covariance_matrix`.
"""


[docs]class CorrelationStandardDeviation(ProductLinearOperator, SelfAdjointLinearOperator): """Represent correlation-std product.""" def __init__(self, correlation, std): """Set up instance to use given parameters. Parameters ---------- correlation: LinearOperator[N, N] Correlations std: array_like[N] Standard deviations """ std_matrix = DiagonalOperator(std) super(CorrelationStandardDeviation, self).__init__( std_matrix, correlation, std_matrix) def _transpose(self): """Return transpose of self.""" return self # pragma: no cover def _adjoint(self): """Return adjoint of self.""" return self
[docs] def sqrt(self): """Find S such that S.T @ S == self.""" std_matrix, correlation, _ = self._operators return ProductLinearOperator( matrix_sqrt(correlation), std_matrix)
_sqrt = sqrt
[docs]def observation_covariance_matrix(variance_series, correlation_function): """Create the observation covariance matrix given parammeters. Assumes the observations are far enough apart to be uncorrelated. Parameters ---------- variance_series : pandas.Series[n_observations] correlation_function : DistanceCorrelationFunction Returns ------- np.ndarray """ obs_time_name = [name for name in variance_series.index.names if "time" in name][0] obs_site_name = [name for name in variance_series.index.names if "site" in name or "name" in name][0] obs_times = variance_series.index.get_level_values(obs_time_name) obs_sites = variance_series.index.get_level_values(obs_site_name) # Only correlations for now observation_covariance = correlation_function( abs(obs_times[:, newaxis] - obs_times[newaxis, :]) / OBSERVATION_INTERVAL ) observation_covariance[ obs_sites.values[:, newaxis] != obs_sites.values[newaxis, :] ] = 0 # now turn it into covariance obs_stds = sqrt(variance_series.values) observation_covariance *= obs_stds[:, newaxis] observation_covariance *= obs_stds[newaxis, :] return observation_covariance