From 367f790ac6a400f07293fb82789dd6d045a500d5 Mon Sep 17 00:00:00 2001 From: Meyers-Im Date: Tue, 26 Sep 2023 14:13:30 -0700 Subject: [PATCH] new utilities for time dilation --- solardatatools/utilities.py | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/solardatatools/utilities.py b/solardatatools/utilities.py index 5fbeb8c7..2f657d7e 100644 --- a/solardatatools/utilities.py +++ b/solardatatools/utilities.py @@ -7,6 +7,7 @@ import sys import numpy as np import cvxpy as cvx +from scipy.interpolate import interp1d def basic_outlier_filter(x, outlier_constant=1.5): @@ -78,3 +79,44 @@ def find_runs(x): run_lengths = np.diff(np.append(run_starts, n)) return run_values, run_starts, run_lengths + + +def time_dilate(data, mask, power=8, scale=None): + """Process an entire PV power matrix at once + :return: + """ + if scale is None: + scale = 1 + N = 2**power + output = np.zeros((N, data.shape[1])) + xs_new = np.linspace(0, 1, N) + for col_ix in range(data.shape[1]): + y = data[:, col_ix] * scale + msk = mask[:, col_ix] + xs = np.linspace(0, 1, int(np.sum(msk))) + interp_f = interp1d(xs, y[msk]) + resampled_signal = interp_f(xs_new) + if np.sum(resampled_signal) > 0: + output[:, col_ix] = resampled_signal + else: + output[:, col_ix] = 0 + return output + + +def undo_time_dilate(data, mask, scale=None): + if scale is None: + scale = 1 + output = np.zeros_like(mask, dtype=float) + xs_old = np.linspace(0, 1, data.shape[0]) + for col_ix in range(data.shape[1]): + # the number of non-zero data points on that day + n_pts = np.sum(mask[:, col_ix]) + # a linear space of n_pts values between 0 and 1 + xs_new = np.linspace(0, 1, n_pts) + # the mapping from the old index to the data + interp_f = interp1d(xs_old, data[:, col_ix] / scale) + # transform the signal to the new length + resampled_signal = interp_f(xs_new) + # insert the data into the daytime index values + output[mask[:, col_ix], col_ix] = resampled_signal + return output