Source code for pycif.plugins.transforms.complex.satellites.vinterp

import numpy as np
import scipy


[docs] def vertical_interp( pres_in, dpres_in, pres_out, dpres_out, cropstrato, vinterp_type="weight", weights_nsubsteps=20 ): """Compute the interpolation coefficients to apply a linear vertical interpolation""" nvertin, lenin = pres_in.shape nvertout, lenout = pres_out.shape if lenin != lenout: raise Exception( "The input mesh has a different length than the target" ) # Initializing index mesh for scipy.griddata meshin = np.array((nvertin + 2) * [list(range(lenin))]) meshout = np.array(nvertout * [list(range(lenout))]) levmeshin = np.array((lenin) * [list(range(-1, nvertin + 1))]).T levin = levmeshin.flatten() # Replacing infinite by max/min +/- eps pin_max = pres_in[(pres_in > -np.inf) & (pres_in < np.inf)].max() pin_min = pres_in[(pres_in > -np.inf) & (pres_in < np.inf)].min() pout_max = pres_out[(pres_out > -np.inf) & (pres_out < np.inf)].max() pout_min = pres_out[(pres_out > -np.inf) & (pres_out < np.inf)].min() eps = max(np.nanmax(np.abs(np.diff(pres_in, axis=0))), np.nanmax(np.abs(np.diff(pres_out, axis=0)))) pmin = min(pin_min, pout_min) - eps pmax = max(pin_max, pout_max) + eps pres_in[pres_in == -np.inf] = pmin pres_in[pres_in == np.inf] = pmax pres_out[pout_min == -np.inf] = pmin pres_out[pout_min == np.inf] = pmax # Assuring press_in is in ascending order. flip_in = False if not np.all(np.diff(pres_in, axis=0) > 0): pres_in = np.flip(pres_in, axis=0) dpres_in = np.flip(dpres_in, axis=0) levmeshin = np.flip(levmeshin, axis=0) flip_in = True # Assuring press_out is in ascending order. flip_out = False if not np.all(np.diff(pres_out, axis=0) > 0): pres_out = np.flip(pres_out, axis=0) dpres_out = np.flip(dpres_out, axis=0) flip_out = True # Initializing pressure mesh for scipy.griddata # For input pressures (those of the model), # extending the roof and floor to detect ak points # outside of the hull of model pressures pres_in = np.concatenate( [ pmin * np.ones((1, lenin)), pres_in, pmax * np.ones((1, lenout)), ], axis=0, ) # Checking assertion made by numpy.interp method. assert np.all((np.diff(pres_in, axis=0) > 0) | (pres_in[:-1] == 0)) # Convert to layer interface if pressure-weighted interpolation if vinterp_type == "weight": # Update input pressures to interfaces pres_in = np.concatenate([ np.log(np.where( np.exp(pres_in[1:-1]) - dpres_in / 2 <= 0, max(1e-10, np.exp(pmin)), np.exp(pres_in[1:-1]) - dpres_in / 2 )), np.log(np.where( np.exp(pres_in[[-2]]) + dpres_in[[-2]] / 2 <= 0, max(1e-10, np.exp(pmin)), np.exp(pres_in[[-2]]) + dpres_in[[-2]] / 2)), pmax * np.ones((1, lenout)) ]) pres_in = np.concatenate([ min(pres_in.min(), pmin) * np.ones((1, lenout)), pres_in ]) levmeshin = np.concatenate([ np.zeros((1, lenin), dtype=int) + nvertin + 1, levmeshin ]) # Update output pressures to interfaces pres_out = np.concatenate([ np.log(np.where( np.exp(pres_out) - dpres_out / 2 <= 0, max(1e-10, np.exp(pmin)), np.exp(pres_out) - dpres_out / 2 )), np.log(np.exp(pres_out[[-1]]) + dpres_out[[-1]] / 2) ]) # Now duplicates output pressures to sub-levels levmeshout = np.arange( 0, nvertout + 1)[:, np.newaxis] * np.ones((1, lenout)) levmeshout_wgt = np.linspace( 0, nvertout, weights_nsubsteps * nvertout, endpoint=False)[:, np.newaxis] * np.ones((1, lenout)) pres_out_wgt = np.empty_like(levmeshout_wgt) for i in range(lenin): pres_out_wgt[:, i] = np.log(np.interp( levmeshout_wgt[:, i], levmeshout[:, i], np.exp(pres_out[:, i]) )) pres_out = pres_out_wgt # For linear interpolation return alpha high/low levout = np.empty_like(pres_out) for i in range(lenin): levout[:, i] = np.interp( pres_out[:, i], pres_in[:, i], levmeshin[:, i] ) # Getting interpolation coefficients xlow = np.floor(levout).astype(int) xhigh = xlow + 1 alphahigh = levout - xlow alphalow = 1 - alphahigh # Cropping ak pressure outside of model pressures toolow = xlow <= 0 toohigh = xhigh > nvertin - 1 xlow[toolow] = 0 xhigh[toolow] = np.maximum(xhigh[toolow], 0) xlow[toohigh] = np.minimum(xlow[toohigh], nvertin - 1) xhigh[toohigh] = nvertin - 1 alphalow[toolow] = 1 alphahigh[toolow] = 0 alphalow[toohigh] = 0 alphahigh[toohigh] = 1 if cropstrato: alphalow[toohigh] = 0 alphahigh[toohigh] = 0 # Scale coefficient by number of sub-step if weight interpolation if vinterp_type == "weight": mask = (alphalow > 0) | (alphahigh > 0) alphahigh[:] = 0 alphalow[mask] = 1 / weights_nsubsteps # Flip back outputs if pressure out has been flipped if flip_out: xlow = xlow[::-1] xhigh = xhigh[::-1] alphalow = alphalow[::-1] alphahigh = alphahigh[::-1] return xlow, xhigh, alphalow, alphahigh