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