Source code for pycif.plugins.controlvects.standard.utils.get_correlations

from logging import warning

import pandas as pd

from .build_hcorr import build_hcorrelations
from .build_tcorr import build_tcorrelations
from .build_vcorr import build_vcorrelations
from .build_lsm import build_lsm
from .....utils.check.errclass import CifAttributeError, CifError


[docs] def get_hcorr(cntrlv, tracer): hresol = tracer.hresol hresoldim = tracer.hresoldim # Get the grid for horizontal correlations grid = getattr(tracer, "domain", cntrlv.domain) corr = tracer.hcorrelations dump_hcorr = getattr(corr, "dump_hcorr", False) dircorrel = getattr(corr, "dircorrel", f"{cntrlv.workdir}/controlvect/correlations/") evalmin = getattr(corr, "evalmin", 0.) projection = getattr(grid, "projection", "gps") is_lbc = getattr(tracer, "is_lbc", False) crop_chi = getattr(corr, "crop_chi", False) use_sparse = getattr(corr, "use_sparse", False) sparse_crop_threshold = getattr(corr, "sparse_crop_threshold", 0.1) # Two possible options: - uniform correlation length, # or separated land and sea, along a land-sea mask # Default is no separation lsm = getattr(corr, "landsea", False) landseamask = None if lsm: landseamask, sigma_land, sigma_sea = build_lsm(corr, hresol, tracer) else: if not hasattr(corr, "sigma"): raise CifAttributeError( "The attribute `sigma` is missing to define horizontal correlations with no landsea mask.\n" "Please include it in the relevant paragraph in `datavect` of your yaml" ) sigma = getattr(corr, "sigma", -1) sigma_land = sigma sigma_sea = -999 # Load or compute the horizontal correlations # Checks before whether they were already loaded # Use pre-computed correlations for hpixels only, # otherwise, re-compute correlations if (sigma_land, sigma_sea, is_lbc, hresol, hresoldim) in \ cntrlv.hcorrelations and hresol in ["hpixels", "regions"]: sqrt_evalues = cntrlv.hcorrelations[ (sigma_land, sigma_sea, is_lbc, hresol, hresoldim) ]["sqrt_evalues"] evectors = cntrlv.hcorrelations[ (sigma_land, sigma_sea, is_lbc, hresol, hresoldim)]["evectors"] else: # Take sides if LBC parameter zlat = grid.zlat zlon = grid.zlon if is_lbc: zlat = grid.zlat_side zlon = grid.zlon_side # Take centroids if not hpixels if hresol != "hpixels": zlon = tracer.centroids_lons zlat = tracer.centroids_lats sqrt_evalues, evectors = build_hcorrelations( hresol, hresoldim, zlat, zlon, lsm, landseamask, sigma_land, sigma_sea, evalmin=evalmin, dump=dump_hcorr, dir_dump=dircorrel, projection=projection, is_lbc=is_lbc, crop_chi=crop_chi, tracer=tracer, use_sparse=use_sparse, sparse_crop_threshold=sparse_crop_threshold ) # Storing computed correlations for use by other components cntrlv.hcorrelations[ (sigma_land, sigma_sea, is_lbc, hresol, hresoldim)] = { "evectors": evectors, "sqrt_evalues": sqrt_evalues, } corr.sqrt_evalues = sqrt_evalues corr.evectors = evectors return sqrt_evalues, evectors
[docs] def get_tcorr(cntrlv, tracer, corr): tresol = getattr(tracer, "tresol") tsubresol = getattr(tracer, "tsubresol", "0") dates = getattr(tracer, "dates") # Check that sigma_t is really a frequency sigma_t = getattr(corr, "sigma_t", -1) if isinstance(sigma_t, str): if sigma_t[:-2] == "MS" or sigma_t[:-1] == "M": warning(f"sigma_t={sigma_t} can be ambiguous, 'MS' is " "interpreted as 'milliseconds' and 'M' as 'minutes', " "and NEVER as 'months'") if pd.to_timedelta(sigma_t).total_seconds() == 0: raise CifError(f"The specified sigma_t ({sigma_t}) is not a correct pandas frequency.\nPlease check your Yaml file!") # Load other parameters sigma_type = getattr(corr, "type") dump_tcorr = getattr(corr, "dump_tcorr", False) dircorrel = getattr(corr, "dircorrel", f"{cntrlv.workdir}/controlvect/correlations/") evalmin = getattr(corr, "evalmin", 0.) crop_chi = getattr(corr, "crop_chi", False) # Load or compute the temporal correlations # Checks before whether they were already loaded if (sigma_t, tresol, tsubresol) in cntrlv.tcorrelations: sqrt_evalues = cntrlv.tcorrelations[ (sigma_t, tresol, tsubresol, sigma_type)]["sqrt_evalues"] evectors = cntrlv.tcorrelations[ (sigma_t, tresol, tsubresol, sigma_type)]["evectors"] else: # Computes correlations for dates[:-1] # as the last dates indicates the end of the period sqrt_evalues, evectors = build_tcorrelations( tresol, tsubresol, dates, sigma_t, sigma_type, evalmin=evalmin, dump=dump_tcorr, dir_dump=dircorrel, crop_chi=crop_chi, corr_plg=corr, tracer=tracer ) # Storing computed correlations for use by other components cntrlv.tcorrelations[(sigma_t, tresol, tsubresol, sigma_type)] = { "evectors": evectors, "sqrt_evalues": sqrt_evalues, } corr.sqrt_evalues = sqrt_evalues corr.evectors = evectors return sqrt_evalues, evectors
[docs] def get_vcorr(cntrlv, tracer): vresol = getattr(tracer, "vresol") nlev = tracer.nlev grid = getattr(tracer, "domain", cntrlv.domain) corr = tracer.vcorrelations dump_vcorr = getattr(corr, "dump_vcorr", False) dircorrel = getattr(corr, "dircorrel", f"{cntrlv.workdir}/controlvect/correlations/") evalmin = getattr(corr, "evalmin", 0.) crop_chi = getattr(corr, "crop_chi", False) # Check method method = corr.method if method not in ["level", "pressure"]: raise CifError( f"Unrecognized method {method} for vertical correlations" ) sigma_lev = corr.sigma # Load or compute the temporal correlations # Checks before whether they were already loaded if (sigma_lev, vresol) in cntrlv.vcorrelations: sqrt_evalues = cntrlv.vcorrelations[ (sigma_lev, vresol, method)]["sqrt_evalues"] evectors = cntrlv.vcorrelations[ (sigma_lev, vresol, method)]["evectors"] else: # Computes correlations for dates[:-1] # as the last dates indicates the end of the period sqrt_evalues, evectors = build_vcorrelations( vresol, nlev, sigma_lev, method, corr_plg=corr, tracer=tracer, dump=dump_vcorr, dir_dump=dircorrel, evalmin=evalmin, crop_chi=crop_chi ) # Storing computed correlations for use by other components cntrlv.tcorrelations[(sigma_lev, vresol, method)] = { "evectors": evectors, "sqrt_evalues": sqrt_evalues, } corr.sqrt_evalues = sqrt_evalues corr.evectors = evectors return sqrt_evalues, evectors