From 9cf783aeb2c89d52abde5c44b5b345983f549aea Mon Sep 17 00:00:00 2001 From: Wolfgang Kastaun <wolfgang.kastaun@aei.mpg.de> Date: Fri, 20 Dec 2024 19:33:29 +0100 Subject: [PATCH] Changed definition of shift sign to the one used in dsp.timeshift. Now a positive shift generally means a shift to the right, i.e. a delay is a negative shift. --- lisainstrument/dynamic_delay_dask.py | 16 ++++++++-------- lisainstrument/dynamic_delay_dsp.py | 14 +++++++------- lisainstrument/dynamic_delay_numpy.py | 20 ++++++++++---------- lisainstrument/fixed_shift_dask.py | 8 ++++---- lisainstrument/fixed_shift_dsp.py | 8 ++++---- lisainstrument/fixed_shift_numpy.py | 17 ++++++++--------- lisainstrument/regular_interpolators.py | 10 ++++------ 7 files changed, 45 insertions(+), 48 deletions(-) diff --git a/lisainstrument/dynamic_delay_dask.py b/lisainstrument/dynamic_delay_dask.py index 5b8d662..1304b7f 100644 --- a/lisainstrument/dynamic_delay_dask.py +++ b/lisainstrument/dynamic_delay_dask.py @@ -28,8 +28,8 @@ class DynamicShiftDask: This allows to interpolate samples in a dask array to locations specified by a shift given by another dask array of same size. The shift is specified in units of the array index, i.e. there is no separate coordinate array. - A positive shift refers to values left of a given sample, negative shifts - to values on the right. + A positive shift refers to values right of a given sample, negative shifts + to values on the left. The boundary treatment can be specified for each boundary in terms of DynShiftBC enums. @@ -79,8 +79,8 @@ class DynamicShiftDask: The shift and sample arrays need to have the same size, and each shift provides the interpolation location relative to the sample with the same index. - Shifts are floating point values. A shift of +1 refers to the sample on the left, - -1 the sample on the right, etc. All arrays have to be 1D. + Shifts are floating point values. A shift of +1 refers to the sample on the right, + -1 the sample on the left, etc. All arrays have to be 1D. Arguments: samples: 1D dask array with data samples @@ -156,8 +156,8 @@ def make_dynamic_shift_linear_dask( """Set up DynamicShiftDask instance with linear interpolation method. Arguments: - min_delay: Assume that any shift < -min_delay - max_delay: Assume that any shift > -max_delay + min_delay: Assume that any shift > -max_delay + max_delay: Assume that any shift < -min_delay left_bound: Treatment of left boundary right_bound: Treatment of right boundary @@ -180,8 +180,8 @@ def make_dynamic_shift_lagrange_dask( Arguments: length: Number of lagrange polynomials (of order length - 1) - min_delay: Assume that any shift < -min_delay - max_delay: Assume that any shift > -max_delay + min_delay: Assume that any shift > -max_delay + max_delay: Assume that any shift < -min_delay left_bound: Treatment of left boundary right_bound: Treatment of right boundary diff --git a/lisainstrument/dynamic_delay_dsp.py b/lisainstrument/dynamic_delay_dsp.py index bd0ae14..3c394ef 100644 --- a/lisainstrument/dynamic_delay_dsp.py +++ b/lisainstrument/dynamic_delay_dsp.py @@ -67,7 +67,7 @@ class RegularInterpDSP(RegularInterpCore): ) -> np.ndarray: """Interpolate regularly spaced data to location in index-space""" doff = int_offsets - np.arange(locations.shape[0]) - shift = -locations + doff[0] - doff + shift = locations - doff[0] + doff shift_offset = doff[0] return self.apply_shift(samples, shift, shift_offset) @@ -79,7 +79,7 @@ class RegularInterpDSP(RegularInterpCore): shift_offset: int, ) -> np.ndarray: """Iterpolate to location specified in terms of shifts instead absolute locations""" - shift_tot = shift - shift_offset + shift_tot = shift + shift_offset npad_right = 0 @@ -90,7 +90,7 @@ class RegularInterpDSP(RegularInterpCore): msg = "DSPWrapper: insufficient samples for interpolation" raise RuntimeError(msg) - res = dsp.timeshift(samples, -shift_tot, self._order) + res = dsp.timeshift(samples, shift_tot, self._order) if npad_right > 0: res = res[:-npad_right] @@ -121,8 +121,8 @@ def make_dynamic_shift_dsp_dask( Arguments: order: Lagrange interpolation order (must be odd) - min_delay: Assume that any shift < -min_delay - max_delay: Assume that any shift > -max_delay + min_delay: Assume that any shift > -max_delay + max_delay: Assume that any shift < -min_delay left_bound: Treatment of left boundary right_bound: Treatment of right boundary @@ -146,8 +146,8 @@ def make_dynamic_shift_dsp_numpy( Arguments: order: Lagrange interpolation order (must be odd) - min_delay: Assume that any shift < -min_delay - max_delay: Assume that any shift > -max_delay + min_delay: Assume that any shift > -max_delay + max_delay: Assume that any shift < -min_delay left_bound: Treatment of left boundary right_bound: Treatment of right boundary diff --git a/lisainstrument/dynamic_delay_numpy.py b/lisainstrument/dynamic_delay_numpy.py index 639a312..bb5f2f6 100644 --- a/lisainstrument/dynamic_delay_numpy.py +++ b/lisainstrument/dynamic_delay_numpy.py @@ -38,8 +38,8 @@ class DynShiftCfg: """Config class for dynamic shift interpolation Attributes: - min_delay: Assume that any shift < -min_delay - max_delay: Assume that any shift > -max_delay + min_delay: Assume that any shift > -max_delay + max_delay: Assume that any shift < -min_delay left_bound: Treatment of left boundary right_bound: Treatment of right boundary """ @@ -71,8 +71,8 @@ class DynamicShiftNumpy: This allows to interpolate samples in a numpy array to locations specified by a shift given by another numpy array of same size. The shift is specified in units of the array index, i.e. there is no separate coordinate array. - A positive shift refers to values left of a given sample, negative shifts - to values on the right. + A positive shift refers to values right of a given sample, negative shifts + to values on the left. The boundary treatment can be specified for each boundary in terms of DynShiftBC enums. @@ -121,8 +121,8 @@ class DynamicShiftNumpy: The shift and sample arrays need to have the same size, and each shift provides the interpolation location relative to the sample with the same index. - Shifts are floating point values.A shift of +1 refers to the sample on the left, - -1 the sample on the right, etc. All arrays have to be 1D. + Shifts are floating point values. A shift of +1 refers to the sample on the right, + -1 the sample on the left, etc. All arrays have to be 1D. Arguments: @@ -187,8 +187,8 @@ def make_dynamic_shift_lagrange_numpy( Arguments: length: Number of lagrange polynomials (of order length - 1) - min_delay: Assume that any shift < -min_delay - max_delay: Assume that any shift > -max_delay + min_delay: Assume that any shift > -max_delay + max_delay: Assume that any shift < -min_delay left_bound: Treatment of left boundary right_bound: Treatment of right boundary @@ -209,8 +209,8 @@ def make_dynamic_shift_linear_numpy( """Set up DynamicShiftNumpy instance with linear interpolation method. Arguments: - min_delay: Assume that any shift < -min_delay - max_delay: Assume that any shift > -max_delay + min_delay: Assume that any shift > -max_delay + max_delay: Assume that any shift < -min_delay left_bound: Treatment of left boundary right_bound: Treatment of right boundary diff --git a/lisainstrument/fixed_shift_dask.py b/lisainstrument/fixed_shift_dask.py index 471a713..e6e2100 100644 --- a/lisainstrument/fixed_shift_dask.py +++ b/lisainstrument/fixed_shift_dask.py @@ -23,7 +23,7 @@ class FixedShiftDask: # pylint: disable=too-few-public-methods This allows to interpolate samples in a Dask array to locations specified by a fixed shift. The shift is specified in units of the array index, i.e. there is no separate coordinate array. A positive shift refers to values - left of a given sample, negative shifts to values on the right. + right of a given sample, negative shifts to values on the left. The boundary treatment can be specified for each boundary in terms of DynShiftBC enums. @@ -98,7 +98,7 @@ class FixedShiftDask: # pylint: disable=too-few-public-methods Denoting the input data as $y_i$ with $i=0 \ldots N-1$, and the interpolated input data as $y(t)$, such that $y(i)=y_i$, the output $z_k$ is given by - $z_k = y(k-s), k=0 \ ldots N - 1$. + $z_k = y(k + s), k=0 \ ldots N - 1$. Required data outside the provided samples is created if the specified boundary condition allows it, or an exception is raised if the BC disallows it. @@ -113,11 +113,11 @@ class FixedShiftDask: # pylint: disable=too-few-public-methods Dask array with interpolated samples """ - loc = -shift + loc = float(shift) loc_int = int(np.floor(loc)) loc_frac = loc - loc_int - interp = self._interp_fac(-loc_frac) + interp = self._interp_fac(loc_frac) margin_left = interp.margin_left - loc_int margin_right = interp.margin_right + loc_int diff --git a/lisainstrument/fixed_shift_dsp.py b/lisainstrument/fixed_shift_dsp.py index c25597d..39afef8 100644 --- a/lisainstrument/fixed_shift_dsp.py +++ b/lisainstrument/fixed_shift_dsp.py @@ -44,8 +44,8 @@ class FixedShiftWrapDSP(FixedShiftCore): for each interpolation point. The order of the interpolating polynomials is also the order of plynomials that are interpolated with zero error. - The shift is given as a delay, i.e. positive values refer to locations - to the left of the output sample at hand. + The shift sign is defined such that positive values refer to locations + to the right of the output sample at hand. Arguments: length: Size of the interpolation stencil @@ -60,7 +60,7 @@ class FixedShiftWrapDSP(FixedShiftCore): msg = "FixedShiftWrapDSP: even Lagrange polynomial order not supported by dsp.timeshift" raise ValueError(msg) - loc = -float(shift) + loc = float(shift) loc_int = int(np.floor(loc)) # ~ loc_frac = loc - loc_int @@ -97,7 +97,7 @@ class FixedShiftWrapDSP(FixedShiftCore): Shifted input excluding margins """ a = make_numpy_array_1d_float(samples) - res = dsp.timeshift(a, -self.shift, self._order) + res = dsp.timeshift(a, self.shift, self._order) if self.margin_left > 0: res = res[self.margin_left :] diff --git a/lisainstrument/fixed_shift_numpy.py b/lisainstrument/fixed_shift_numpy.py index cf8d47d..77eab13 100644 --- a/lisainstrument/fixed_shift_numpy.py +++ b/lisainstrument/fixed_shift_numpy.py @@ -64,10 +64,9 @@ class FixedShiftCore(Protocol): r"""Apply the fractional shift to a 1D numpy array. The output is the shifted input with left and right margins removed. - The shift $s$ should be bounded $-1 < s < 1$ Denoting the input data as $y_i$ with $i=0 \ldots N-1$, and the interpolated input data as $y(t)$, such that $y(i)=y_i$, the output $z_k$ is given by - $z_k = y(k+M_L-s), k=0 \ ldots N - 1 - M_L - M_R$, where $M_L$ and $M_R$ + $z_k = y(k + M_L + s), k=0 \ ldots N - 1 - M_L - M_R$, where $M_L$ and $M_R$ are the left and right margin sizes. Arguments: @@ -166,15 +165,15 @@ class FixedShiftLagrange(FixedShiftCore): for each interpolation point. The order of the interpolating polynomials is also the order of plynomials that are interpolated with zero error. - The shift is given as a delay, i.e. positive values refer to locations - to the left of the output sample at hand. + The shift sign is defined such that positive values refer to locations + to the right of the output sample at hand. Arguments: length: Size of the interpolation stencil shift: The constant shift """ - loc = -float(shift) + loc = float(shift) if length % 2 == 0: loc_int = int(np.floor(loc)) else: @@ -248,7 +247,7 @@ class FixedShiftNumpy: # pylint: disable=too-few-public-methods This allows to interpolate samples in a numpy array to locations specified by a fixed shift. The shift is specified in units of the array index, i.e. there is no separate coordinate array. A positive shift refers to values - left of a given sample, negative shifts to values on the right. + right of a given sample, negative shifts to values on the left. The boundary treatment can be specified for each boundary in terms of DynShiftBC enums. @@ -323,7 +322,7 @@ class FixedShiftNumpy: # pylint: disable=too-few-public-methods Denoting the input data as $y_i$ with $i=0 \ldots N-1$, and the interpolated input data as $y(t)$, such that $y(i)=y_i$, the output $z_k$ is given by - $z_k = y(k-s), k=0 \ ldots N - 1$. + $z_k = y(k + s), k=0 \ ldots N - 1$. Required data outside the provided samples is created if the specified boundary condition allows it, or an exception is raised if the BC disallows it. @@ -339,12 +338,12 @@ class FixedShiftNumpy: # pylint: disable=too-few-public-methods """ # pylint: disable=duplicate-code - loc = -shift + loc = float(shift) loc_int = int(np.floor(loc)) loc_frac = loc - loc_int # pylint: enable=duplicate-code - interp = self._interp_fac(-loc_frac) + interp = self._interp_fac(loc_frac) margin_left = interp.margin_left - loc_int margin_right = interp.margin_right + loc_int diff --git a/lisainstrument/regular_interpolators.py b/lisainstrument/regular_interpolators.py index 4f4cc69..cc54d10 100644 --- a/lisainstrument/regular_interpolators.py +++ b/lisainstrument/regular_interpolators.py @@ -92,12 +92,12 @@ class RegularInterpCore(Protocol): The locations are specified via an array s of real-valued shifts. For the element s[i] of the shift array with array index i, the absolute location within the index space of the - input samples is given by i - s[i] + ofs, where ofs is a constant integer offset. A zero + input samples is given by i + s[i] + ofs, where ofs is a constant integer offset. A zero shift means the output sample with index i is the input sample with index i+ofs. The offset can be positive or negative. Shift values that would require samples not in the input are not allowed. The output should be the same as for - apply(samples, -shift, shift_offset + np.arange(shift.shape[0])) + apply(samples, shift, shift_offset + np.arange(shift.shape[0])) Arguments: samples: 1D numpy array with sampled data @@ -266,10 +266,9 @@ class RegularInterpLagrange(RegularInterpCore): Returns: Interpolated samples """ - loc = -shift offsets = shift_offset + np.arange(shift.shape[0]) return self.apply( - samples, make_numpy_array_1d(loc), make_numpy_array_1d(offsets) + samples, make_numpy_array_1d(shift), make_numpy_array_1d(offsets) ) @@ -343,10 +342,9 @@ class RegularInterpLinear(RegularInterpCore): Returns: Interpolated samples """ - loc = -shift offsets = shift_offset + np.arange(shift.shape[0]) return self.apply( - samples, make_numpy_array_1d(loc), make_numpy_array_1d(offsets) + samples, make_numpy_array_1d(shift), make_numpy_array_1d(offsets) ) -- GitLab