Callable class for sample weights that can be pickled.
This class wraps the weights_series and provides a callable interface compatible with ForecasterRecursive’s weight_func parameter. Unlike local functions with closures, instances of this class can be pickled using standard pickle/joblib.
When all weights for the requested index sum to zero (e.g. the entire training window falls inside gap-penalty zones after outlier detection), __call__ returns None instead of an all-zero array. ForecasterRecursive.create_sample_weights treats a None return as “no weighting”, avoiding a ValueError while still applying the weighted imputation for windows that do contain positive weights.
import pickleimport numpy as npimport pandas as pdfrom spotforecast2_safe.preprocessing.imputation import WeightFunctionweights = pd.Series([1.0, 0.9, 0.8], index=[0, 1, 2])weight_func = WeightFunction(weights)# Callable interface: returns weights for a pd.Indexresult = weight_func(pd.Index([0, 1]))print(result)assert np.allclose(result, [1.0, 0.9])# Returns None when all weights in the window are zerozero_weights = pd.Series([0.0, 0.0, 0.0], index=[0, 1, 2])wf_zero = WeightFunction(zero_weights)assert wf_zero(pd.Index([0, 1])) isNone# Can be pickled and unpickled (no closure, fully serialisable)unpickled = pickle.loads(pickle.dumps(weight_func))result2 = unpickled(pd.Index([0, 1]))print(result2)assert np.allclose(result2, [1.0, 0.9])
WeightFunction: all sample weights for the requested index are zero (the window falls entirely within gap-penalty zones). Returning None so ForecasterRecursive uses uniform weighting.