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