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

import copy
import pandas as pd
import numpy as np
from .......utils.datastores.empty import init_empty
from .......utils.parallel import thread
from .......utils.check.errclass import CifError


[docs] def forward( transf, ddi, inputs, inout_datastore, onlyinit, mapper, sampled_out, sparse_out, save_debug, nthreads=1 ): if onlyinit or ddi not in mapper["interpol_indexes"]: return interpol_indexes = mapper["interpol_indexes"][ddi] # Load input and output dates from transform trid_ref = list(mapper["inputs"].keys())[0] in_dates = mapper["inputs"][trid_ref]["input_dates"] out_dates = mapper["outputs"][trid_ref]["input_dates"] if np.size(out_dates[ddi]) == 1: raise CifError("Output dates should not be single for adjoint interpolation") else: out_dates_start = out_dates[ddi]["start_date"] out_dates_end = out_dates[ddi]["end_date"] # Output dates from output datastore ds_out_dates_start = out_dates_start ds_out_dates_end = out_dates_end # Threading adjoint propogation nthreads_tmp = min(nthreads, len(mapper["inputs"])) thread_intervals = np.linspace( 0, len(mapper["inputs"]), nthreads_tmp + 1 ).astype(int) list_trids = copy.deepcopy(list(mapper["inputs"].keys())) @thread def thread_function(ithread): for itrid in range(thread_intervals[ithread], thread_intervals[ithread + 1]): trid = list_trids[itrid] # Initialize empty output datastore outputs = None # Loop over target dates for ddtarget in interpol_indexes: # Fetch adjoint metadata wgt = transf.metadata[ddi][ddtarget]["weights"] ds_tmp_mask = transf.metadata[ddi][ddtarget]["target_mask"] data_in = copy.deepcopy(inputs[trid][ddtarget]) if not isinstance(data_in, pd.DataFrame): continue # Initiate outputs if still None if outputs is None: outputs = init_empty(nlines=len(ds_tmp_mask)) # Put new data into respective outputs if sparse_out or sampled_out: # input_weights = outputs_tmp['interpol_indexes'] # Fill empty columns columns = [c for c in ["spec", "incr"] if c in data_in["maindata"]] for c in columns: if c not in outputs["maindata"]: outputs[("maindata", c)] = 0. # Group once for all data_out = \ (data_in["maindata"].loc[:, columns] * wgt[("interpol_indexes", "weights")].values[:, np.newaxis]) \ .groupby(wgt[("target_index", "")].values).sum() output_index = wgt.groupby(wgt[("target_index", "")].values).first()[ ("target_index", "")].values for c in columns: outputs.loc[output_index, ("maindata", c)] = \ outputs.loc[output_index, ("maindata", c)].values \ + data_out[c].values # # Propagate info from previous transforms # # if saving debug info # if save_debug: # outputs_tmp = copy.deepcopy(outputs.loc[ds_tmp_mask]) # data_out = \ # data_in["metadata"].groupby( # outputs_tmp.loc[:, "ref_index"]).first() # for c in data_in.columns: # if c[0] == "maindata": # continue # if c[1] not in data_out: # outputs.loc[:, c] = np.nan # outputs.loc[ds_tmp_mask, c] = data_out[c[1]].values # debug_cols = pd.MultiIndex.from_product( # [[transf.transform_id], out_index.columns] # ) # group_index = out_index.groupby("out_index") # df_debug = pd.DataFrame( # {c: group_index[c[1]].apply( # list) for c in debug_cols}, # index=outputs.index, # columns=debug_cols) # for c in df_debug.columns: # outputs.loc[:, c] = df_debug[c].values else: mask = data_in["metadata"]["tstep"].isin( out_index["indexes"]) data_out = copy.deepcopy(data_in.loc[mask]) data_out.loc[:, ("metadata", "tstep")] = \ out_index.set_index("indexes").loc[ data_out["metadata"]["tstep"], "out_index"].values outputs = pd.concat([outputs, data_out]) # Putting in outputs for sparse_out if (not sparse_out or sampled_out) and outputs is not None: inout_datastore["outputs"][trid][ddi] = outputs # Apply threaded function thread_function(range(nthreads_tmp))