Source code for pycif.plugins.obsvects.standard.build_full_r
import numpy as np
[docs]
def build_r(obsvect, **kwargs):
r"""Build the full observation error covariance matrix :math:`\mathbf{R}`.
Constructs the square matrix :math:`\mathbf{R} \in \mathbb{R}^{m \times m}`
by filling diagonal blocks for each observation tracer with the squared
per-observation errors:
.. math::
R_{ii} = \sigma_{\varepsilon,i}^2
\quad \forall\, i \in [\text{ypointer},\, \text{ypointer} + \text{dim})
Off-diagonal elements remain zero (diagonal covariance assumption).
.. warning::
This returns a dense :math:`m \times m` matrix. For large observation
vectors (e.g. :math:`m > 10^4`) this will be memory-prohibitive.
Use :func:`~.rinvprod.rinvprod` for the efficient diagonal application.
Args:
obsvect (Plugin): obsvect plugin instance (provides ``yobs_err``,
``dim``, and access to the datavect tracer metadata).
**kwargs: unused; accepted for interface consistency.
Returns:
np.ndarray: diagonal matrix of shape ``(dim, dim)`` containing the
squared observation errors on the main diagonal.
"""
datavect = obsvect.datavect
rfull = np.eye(obsvect.dim)
components = datavect.components
for comp in components.attributes:
component = getattr(components, comp)
# Skip if component does not have parameters
if not hasattr(component, "parameters"):
continue
for trcr in component.parameters.attributes:
tracer = getattr(component.parameters, trcr)
# Skip tracers that are not control variables
if not tracer.isobs:
continue
rfull[tracer.ypointer: tracer.ypointer + tracer.dim,
tracer.ypointer: tracer.ypointer + tracer.dim] *= \
obsvect.yobs_err[tracer.ypointer:
tracer.ypointer + tracer.dim] ** 2
return rfull