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

import os
from logging import debug, info

import numpy as np

from .....utils.geometry.dist_matrix import dist_matrix
from .....utils.netcdf import readnc
from .....utils.path import init_dir
from ....transforms.system.fromcontrol.utils.scalemaps import map2scale
from .....utils.check.errclass import CifError, CifIOError


[docs] def build_vcorrelations( vresol, nlev, sigma_lev, method, corr_plg=None, tracer=None, dump=False, dir_dump="", evalmin=0, crop_chi=False, **kwargs ): """Build vertical correlation matrix based on distance between levels Return: tuple with: - square roots of eigenvalues - eigenvectors """ # Try reading existing file try: evalues, evectors = read_vcorr( vresol, nlev, sigma_lev, method, dir_dump ) # Else build correlations except IOError: info(f"Computing vcorr for {nlev} levels and {method} method") if method == "level": dx = np.abs( np.arange(nlev)[:, np.newaxis] - np.arange(nlev)[np.newaxis] ).astype(float) else: raise CifError("Not implemented yet") # Compute the correlation matrix itself corr = np.exp( - np.divide(dx, sigma_lev, out=np.full_like(dx, np.inf)) ).astype(np.float64) # Component analysis evalues, evectors = np.linalg.eigh(corr) # Re-ordering values # (not necessary in principle in recent numpy versions) index = np.argsort(evalues)[::-1] evalues = evalues[index] evectors = evectors[:, index] # Dumping to a binary file if dump: dump_vcorr( vresol, nlev, sigma_lev, method, evalues, evectors, f"{tracer.workdir}/controlvect/correlations/" ) except Exception as e: raise e # Truncating values < evalmin mask = evalues >= evalmin if crop_chi: return evalues[mask] ** 0.5, evectors[:, mask] else: evalues[~mask] = 0 return evalues ** 0.5, evectors
[docs] def dump_vcorr(vresol, nlev, sigma_lev, method, evalues, evectors, dir_dump, overwrite=False): """Dumps eigenvalues and vectors to a binary file. The default file format is: f"{dir_dump}/vertcor_{vresol}_{nlev}_{method}.bin" ) """ file_dump = f"{dir_dump}/vertcor_{vresol}_{nlev}_{method}.bin" if os.path.isfile(file_dump) and overwrite: raise CifIOError( f"Warning: {file_dump} already exists. I don't want to overwrite it" ) datasave = np.concatenate((evalues[np.newaxis, :], evectors), axis=0) # Creating path if does not exist if not os.path.isdir(os.path.dirname(file_dump)): init_dir(os.path.dirname(file_dump)) # Saving data np.array(datasave).tofile(file_dump)
[docs] def read_vcorr(vresol, nlev, sigma_lev, method, dir_dump): """Reads vertical correlations from existing text file """ file_dump = f"{dir_dump}/vertcor_{vresol}_{nlev}_{method}.bin" if not os.path.isfile(file_dump): raise CifIOError( f"{file_dump} does not exist. Please compute correlations from scratch" ) debug(f"Reading vertical correlations from {file_dump}") data = np.fromfile(file_dump).reshape((-1, nlev)) evalues = data[0] evectors = data[1:] evalues[evalues < 0] = 0.0 return evalues, evectors