Source code for pycif.plugins.controlvects.standard.init_bprod

import numpy as np
from logging import debug

try:
    import cPickle as pickle
except ImportError:
    import pickle

from .utils.rescale_std import rescale_std
from .utils.get_correlations import get_vcorr, get_tcorr, get_hcorr


[docs] def init_bprod(cntrlv, options={}, **kwargs): """Initilializes the product of chi by sqrt-B. It allows translating information from the minimization space to the control space. This first needs to initialize correlation matrices Args: cntrlv (dict): definition of the control vector Returns: updated control vector: """ datavect = cntrlv.datavect # Initializing sqrt-B cntrlv.hcorrelations = {} cntrlv.tcorrelations = {} cntrlv.vcorrelations = {} cntrlv.chi_dim = 0 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 hasattr(tracer, "hresol"): continue # Deals with horizontal correlations if any hresol = tracer.hresol if hasattr(tracer, "hcorrelations") \ and hresol != "global": debug(f"Fetching horizontal correlation for {comp}/{trcr}") sqrt_evalues, evectors = get_hcorr(cntrlv, tracer) tracer.chi_hresoldim = sqrt_evalues.size else: tracer.chi_hresoldim = tracer.hresoldim # Initializes temporal correlations if any if hasattr(tracer, "tcorrelations"): corr = tracer.tcorrelations if getattr(corr, "multi_sigmas", False): sigmas = corr.sigmas.attributes tresols = [] ndates = getattr(tracer, "dates").size B = np.ones((ndates, ndates)) for sigma in sigmas: tmp_corr = getattr(corr.sigmas, sigma) sqrt_evalues, evectors = get_tcorr( cntrlv, tracer, tmp_corr) tresols.append(sqrt_evalues.size) # Aggregate to full B B *= evectors.dot( np.diag(sqrt_evalues ** 2)).dot(evectors.T) # Check that all temporal resolution from sub-sigmas are # consistent tresols = list(set(tresols)) if len(tresols) != 1: raise Exception("Error with multiple temporal " "correlations, the length of all " "sub-correlation matrices is not " "consistent.") chi_tresoldim = tresols[0] # Aggregate multiple B evalues, evectors = np.linalg.eigh(B) corr.evectors = evectors corr.sqrt_evalues = np.sqrt(evalues) else: corr.type = getattr(corr, "type", "isotrope") sqrt_evalues, evectors = get_tcorr(cntrlv, tracer, corr) chi_tresoldim = sqrt_evalues.size tracer.chi_tresoldim = chi_tresoldim else: tracer.chi_tresoldim = tracer.ndates # Deal with vertical correlations if hasattr(tracer, "vcorrelations") \ and tracer.vresol != "column": sqrt_evalues, evectors = get_vcorr(cntrlv, tracer) tracer.chi_vresoldim = sqrt_evalues.size else: tracer.chi_vresoldim = tracer.vresoldim # Update the dimension of the full control vector tracer.chi_pointer = cntrlv.chi_dim tracer.chi_dim = \ tracer.chi_hresoldim \ * tracer.chi_tresoldim \ * tracer.chi_vresoldim cntrlv.chi_dim += tracer.chi_dim # Rescale std depending on the global error if specified glob_err = getattr(tracer, "glob_err", None) if glob_err is None: continue if glob_err.total < 0: raise Exception("glob_err must be > 0") rescale_std(cntrlv, tracer, comp, trcr, glob_err) # Defining chi from the total dimension cntrlv.chi = np.zeros((cntrlv.chi_dim,)) # Save the full B matrix if required # Be careful with the size of your set-up if cntrlv.save_full_B: bfull = cntrlv.build_b(cntrlv) bfile = "{}/controlvect/bfull.pickle".format(cntrlv.workdir) with open(bfile, "wb") as f: pickle.dump(bfull, f) # Random perturbation of the control vector if cntrlv.perturb_xb: np.random.seed() x = np.random.normal(size=(1, cntrlv.dim)) x_sample = cntrlv.sqrtbprod(x) cntrlv.xb = x_sample return cntrlv