Source code for pycif.plugins.transforms.basic.time_interpolation.utils.array.forward

import numpy as np
import xarray as xr
import pandas as pd
import copy
from .......utils.parallel import thread
from .......utils.check.errclass import CifError


[docs] def forward( ddi, mapper, inout_datastore, inputs, nthreads=1 ): list_trids = copy.deepcopy(list(mapper["inputs"].keys())) # If the period has no interpolation indexes, just pass if ddi not in mapper["interpol_indexes"]: return if not mapper["do_interpolation"][ddi]: # Re-order periods if necessary if np.any(mapper["reorder_periods"][ddi]): interpol_indexes = mapper["interpol_indexes"][ddi] target_period = list(interpol_indexes.keys())[0] for trid in list_trids: inout_datastore["outputs"][trid][ddi] = \ inputs[trid][target_period] # Otherwise, just forward the inputs else: for trid in list_trids: inout_datastore["outputs"][trid][ddi] = \ inputs[trid].get(ddi, {}) return # Handling output dates trid_ref = list(mapper["inputs"].keys())[0] out_dates = mapper["outputs"][trid_ref]["input_dates"][ddi] if np.size(out_dates) == 0: raise CifError("This should not happen") elif np.size(out_dates) == 1: raise CifError("Output dates should not be single for forward interpolation") else: out_dates_start = out_dates["start_date"] out_dates_end = out_dates["end_date"] # Threading filling of outputs thread_intervals = np.linspace( 0, len(mapper["inputs"]), nthreads + 1 ).astype(int) list_trids = copy.deepcopy(list(mapper["inputs"].keys())) all_interpol_indexes = mapper["interpol_indexes"][ddi] @thread def thread_function(ithread): for itrid in range(thread_intervals[ithread], thread_intervals[ithread + 1]): trid = list_trids[itrid] # Loop on sub-periods outputs = {} for ddtarget in all_interpol_indexes: interpol_indexes = all_interpol_indexes[ddtarget] interpol_indexes.loc[ interpol_indexes["weights"] == 0, "weights"] = 1 data_in = inputs[trid][ddtarget] for did in data_in: # Skip adj_out if did == "adj_out": continue if did not in outputs: outputs[did] = xr.DataArray( np.zeros( (len(out_dates_start), *data_in[did].shape[1:])), coords={"time": out_dates_start}, dims=("time", "lev", "lat", "lon"), ) data_out = xr.DataArray( data_in[did].values[ interpol_indexes["indexes"].astype(int).values ] * interpol_indexes["weights"].values[ :, np.newaxis, np.newaxis, np.newaxis ], coords={"time": out_dates_start[interpol_indexes.index]}, dims=("time", "lev", "lat", "lon"), ) # Account for filter on crop dates in_dates = mapper["inputs"][trid]["input_dates"][ddtarget] in_dates_all = pd.DatetimeIndex( in_dates.stack().drop_duplicates().sort_values()) ddi_mask = ( (out_dates_start <= in_dates_all.max()) & (out_dates_end >= in_dates_all.min()) ) target_indexes = np.where(ddi_mask)[0] np.add.at( outputs[did].values, target_indexes[interpol_indexes.index.values], data_out.values ) inout_datastore["outputs"][trid][ddi] = outputs # Apply threaded function thread_function(range(nthreads))