From 64369427ad943e8a01a479f9c9743d3d5040c79d Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Fri, 24 Jan 2025 01:31:11 -0500 Subject: [PATCH 1/4] add: use ws interp for nyq grid --- news/ws.rst | 23 +++++++++ src/diffpy/pdfgui/control/fitdataset.py | 69 +++++++++++++++++++------ 2 files changed, 75 insertions(+), 17 deletions(-) create mode 100644 news/ws.rst diff --git a/news/ws.rst b/news/ws.rst new file mode 100644 index 00000000..59526e7b --- /dev/null +++ b/news/ws.rst @@ -0,0 +1,23 @@ +**Added:** + +* Added Whittaker-Shannon interpolation option for grid_interpolation. + +**Changed:** + +* Use WS interpolation for Nyquist grid. + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/src/diffpy/pdfgui/control/fitdataset.py b/src/diffpy/pdfgui/control/fitdataset.py index 607b14c4..4bd43416 100644 --- a/src/diffpy/pdfgui/control/fitdataset.py +++ b/src/diffpy/pdfgui/control/fitdataset.py @@ -22,6 +22,7 @@ from diffpy.pdfgui.control.controlerrors import ControlStatusError from diffpy.pdfgui.control.parameter import Parameter from diffpy.pdfgui.control.pdfdataset import PDFDataSet +from diffpy.utils.resampler import wsinterp class FitDataSet(PDFDataSet): @@ -610,13 +611,14 @@ def _updateRcalcSampling(self): if frmax - (rcalcfirst + nrcalc * frstep) > frstep * 1e-8: nrcalc += 1 newrcalc = rcalcfirst + frstep * numpy.arange(nrcalc + 1) + tp = self.getFitSamplingType() # Gcalc: if len(self._Gcalc) > 0: - newGcalc = grid_interpolation(self._rcalc, self._Gcalc, newrcalc) + newGcalc = grid_interpolation(self._rcalc, self._Gcalc, newrcalc, tp) self._Gcalc = list(newGcalc) # dGcalc if len(self._dGcalc) > 0: - newdGcalc = grid_interpolation(self._rcalc, self._dGcalc, newrcalc) + newdGcalc = grid_interpolation(self._rcalc, self._dGcalc, newrcalc, tp) self._dGcalc = list(newdGcalc) # invalidate Gtrunc and dGtrunc self._Gtrunc = [] @@ -709,7 +711,8 @@ def _set_dGcalc(self, value): def _get_Gtrunc(self): self._updateRcalcSampling() if not self._Gtrunc: - newGtrunc = grid_interpolation(self.robs, self.Gobs, self.rcalc) + tp = self.getFitSamplingType() + newGtrunc = grid_interpolation(self.robs, self.Gobs, self.rcalc, tp) self._Gtrunc = list(newGtrunc) return self._Gtrunc @@ -724,13 +727,15 @@ def _set_Gtrunc(self, value): def _get_dGtrunc(self): self._updateRcalcSampling() if not self._dGtrunc: + tp = self.getFitSamplingType() # use sum to avoid index error for empty arrays newdGtrunc = grid_interpolation( self.robs, self.dGobs, self.rcalc, - youtleft=sum(self.dGobs[:1]), - youtright=sum(self.dGobs[-1:]), + tp, + left=sum(self.dGobs[:1]), + right=sum(self.dGobs[-1:]), ) self._dGtrunc = list(newdGtrunc) return self._dGtrunc @@ -775,19 +780,8 @@ def _set_crw(self, value): ############################################################################## # helper functions ############################################################################## +def _linear_interpolation(x0, y0, x1, youtleft, youtright): - -def grid_interpolation(x0, y0, x1, youtleft=0.0, youtright=0.0): - """Linear interpolation of x0, y0 values to a new grid x1. - - x0 -- original x-grid, must be equally spaced - y0 -- original y values - x1 -- new x-grid, it can have any spacing - youtleft -- value for interpolated y1 for x1 below the x0 range - youtright -- value for interpolated y1 for x1 above the x0 range - - Return numpy.array of interpolated y1 values. - """ x0 = numpy.asarray(x0, copy=None, dtype=float) y0 = numpy.asarray(y0, copy=None, dtype=float) n0 = len(x0) @@ -819,6 +813,47 @@ def grid_interpolation(x0, y0, x1, youtleft=0.0, youtright=0.0): y1[m1] = w0lo * y0[ilo0] + w0hi * y0[ihi0] return y1 +def grid_interpolation(x0, y0, x1, tp, left=None, right=None): + """ + Interpolate values from one grid onto another using either linear + or Whittaker–Shannon interpolation. + + Parameters + ---------- + x0 : array_like + Original x-grid, must be equally spaced. + y0 : array_like + Original values defined on x0. + x1 : array_like + New x-grid upon which to interpolate. + tp : {'data', 'Nyquist', 'custom'}, optional + Corresponding fit sampling type. Use Whittaker–Shannon interpolation + for Nyquist resampling and linear interpolation otherwise. + If not provided, linear interpolation is used. + left : float, optional + Value for interpolated y1 for x1 below the x0 range. + Default: if tp='Nyquist' then y1[0] is used. Otherwise 0.0 is used. + right : float, optional + Value for interpolated y1 for x1 above the x0 range. + Default: if tp='Nyquist' then y1[-1] is used. Otherwise 0.0 is used. + + Returns + ------- + numpy.ndarray + Array of interpolated values on the new grid x1. + + Notes + ----- + When tp='Nyquist', the function calls :func:`wsinterp` to perform Whittaker–Shannon interpolation. + Otherwise it uses the internal :func:`_linear_interpolation` routine. + """ + if tp == 'Nyquist': + return wsinterp(x1, x0, y0, left, right) + else: + left = 0.0 if left is None else left + right = 0.0 if right is None else right + return _linear_interpolation(x0, y0, x1, left, right) + # simple test code if __name__ == "__main__": From 9f9e49fc4b245916fe05ba6bf2bfdee74cb32f7e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 06:34:19 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit hooks --- src/diffpy/pdfgui/control/fitdataset.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/diffpy/pdfgui/control/fitdataset.py b/src/diffpy/pdfgui/control/fitdataset.py index 4bd43416..b48e220d 100644 --- a/src/diffpy/pdfgui/control/fitdataset.py +++ b/src/diffpy/pdfgui/control/fitdataset.py @@ -813,10 +813,10 @@ def _linear_interpolation(x0, y0, x1, youtleft, youtright): y1[m1] = w0lo * y0[ilo0] + w0hi * y0[ihi0] return y1 + def grid_interpolation(x0, y0, x1, tp, left=None, right=None): - """ - Interpolate values from one grid onto another using either linear - or Whittaker–Shannon interpolation. + """Interpolate values from one grid onto another using either linear or + Whittaker–Shannon interpolation. Parameters ---------- @@ -827,11 +827,11 @@ def grid_interpolation(x0, y0, x1, tp, left=None, right=None): x1 : array_like New x-grid upon which to interpolate. tp : {'data', 'Nyquist', 'custom'}, optional - Corresponding fit sampling type. Use Whittaker–Shannon interpolation + Corresponding fit sampling type. Use Whittaker–Shannon interpolation for Nyquist resampling and linear interpolation otherwise. If not provided, linear interpolation is used. left : float, optional - Value for interpolated y1 for x1 below the x0 range. + Value for interpolated y1 for x1 below the x0 range. Default: if tp='Nyquist' then y1[0] is used. Otherwise 0.0 is used. right : float, optional Value for interpolated y1 for x1 above the x0 range. @@ -847,7 +847,7 @@ def grid_interpolation(x0, y0, x1, tp, left=None, right=None): When tp='Nyquist', the function calls :func:`wsinterp` to perform Whittaker–Shannon interpolation. Otherwise it uses the internal :func:`_linear_interpolation` routine. """ - if tp == 'Nyquist': + if tp == "Nyquist": return wsinterp(x1, x0, y0, left, right) else: left = 0.0 if left is None else left From 43dcd71cced434b710faaae9e0db4f7cdbcba240 Mon Sep 17 00:00:00 2001 From: Tieqiong Zhang Date: Fri, 24 Jan 2025 01:40:42 -0500 Subject: [PATCH 3/4] update tests and small param order adjustment --- src/diffpy/pdfgui/control/fitdataset.py | 10 +++++----- tests/test_fitdataset.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/diffpy/pdfgui/control/fitdataset.py b/src/diffpy/pdfgui/control/fitdataset.py index b48e220d..97cc14ca 100644 --- a/src/diffpy/pdfgui/control/fitdataset.py +++ b/src/diffpy/pdfgui/control/fitdataset.py @@ -614,11 +614,11 @@ def _updateRcalcSampling(self): tp = self.getFitSamplingType() # Gcalc: if len(self._Gcalc) > 0: - newGcalc = grid_interpolation(self._rcalc, self._Gcalc, newrcalc, tp) + newGcalc = grid_interpolation(self._rcalc, self._Gcalc, newrcalc, tp = tp) self._Gcalc = list(newGcalc) # dGcalc if len(self._dGcalc) > 0: - newdGcalc = grid_interpolation(self._rcalc, self._dGcalc, newrcalc, tp) + newdGcalc = grid_interpolation(self._rcalc, self._dGcalc, newrcalc, tp = tp) self._dGcalc = list(newdGcalc) # invalidate Gtrunc and dGtrunc self._Gtrunc = [] @@ -712,7 +712,7 @@ def _get_Gtrunc(self): self._updateRcalcSampling() if not self._Gtrunc: tp = self.getFitSamplingType() - newGtrunc = grid_interpolation(self.robs, self.Gobs, self.rcalc, tp) + newGtrunc = grid_interpolation(self.robs, self.Gobs, self.rcalc, tp = tp) self._Gtrunc = list(newGtrunc) return self._Gtrunc @@ -733,9 +733,9 @@ def _get_dGtrunc(self): self.robs, self.dGobs, self.rcalc, - tp, left=sum(self.dGobs[:1]), right=sum(self.dGobs[-1:]), + tp = tp, ) self._dGtrunc = list(newdGtrunc) return self._dGtrunc @@ -814,7 +814,7 @@ def _linear_interpolation(x0, y0, x1, youtleft, youtright): return y1 -def grid_interpolation(x0, y0, x1, tp, left=None, right=None): +def grid_interpolation(x0, y0, x1, left=None, right=None, tp=None): """Interpolate values from one grid onto another using either linear or Whittaker–Shannon interpolation. diff --git a/tests/test_fitdataset.py b/tests/test_fitdataset.py index 7ec0d1ff..2e8c0655 100644 --- a/tests/test_fitdataset.py +++ b/tests/test_fitdataset.py @@ -39,7 +39,7 @@ def test_grid_interpolation(self): y0 = numpy.sin(x0) x1 = [-6, x0[0], -0.2, x0[-1], 37] y1a = fds.grid_interpolation(x0, y0, x1) - y1b = fds.grid_interpolation(x0, y0, x1, youtleft=637, youtright=638) + y1b = fds.grid_interpolation(x0, y0, x1, left=637, right=638) # outside values self.assertEqual(0.0, y1a[0]) self.assertEqual(637, y1b[0]) From 2f2cd1e7a75b2a354bddbadf70ba232621cd2564 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 06:41:35 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit hooks --- src/diffpy/pdfgui/control/fitdataset.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/diffpy/pdfgui/control/fitdataset.py b/src/diffpy/pdfgui/control/fitdataset.py index 97cc14ca..559e9dbd 100644 --- a/src/diffpy/pdfgui/control/fitdataset.py +++ b/src/diffpy/pdfgui/control/fitdataset.py @@ -614,11 +614,11 @@ def _updateRcalcSampling(self): tp = self.getFitSamplingType() # Gcalc: if len(self._Gcalc) > 0: - newGcalc = grid_interpolation(self._rcalc, self._Gcalc, newrcalc, tp = tp) + newGcalc = grid_interpolation(self._rcalc, self._Gcalc, newrcalc, tp=tp) self._Gcalc = list(newGcalc) # dGcalc if len(self._dGcalc) > 0: - newdGcalc = grid_interpolation(self._rcalc, self._dGcalc, newrcalc, tp = tp) + newdGcalc = grid_interpolation(self._rcalc, self._dGcalc, newrcalc, tp=tp) self._dGcalc = list(newdGcalc) # invalidate Gtrunc and dGtrunc self._Gtrunc = [] @@ -712,7 +712,7 @@ def _get_Gtrunc(self): self._updateRcalcSampling() if not self._Gtrunc: tp = self.getFitSamplingType() - newGtrunc = grid_interpolation(self.robs, self.Gobs, self.rcalc, tp = tp) + newGtrunc = grid_interpolation(self.robs, self.Gobs, self.rcalc, tp=tp) self._Gtrunc = list(newGtrunc) return self._Gtrunc @@ -735,7 +735,7 @@ def _get_dGtrunc(self): self.rcalc, left=sum(self.dGobs[:1]), right=sum(self.dGobs[-1:]), - tp = tp, + tp=tp, ) self._dGtrunc = list(newdGtrunc) return self._dGtrunc