Skip to content

Commit ebfd3ed

Browse files
committed
nsinterp
1 parent 891d774 commit ebfd3ed

File tree

4 files changed

+93
-2
lines changed

4 files changed

+93
-2
lines changed

doc/source/examples/resampleexample.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ given enough datapoints.
5858
nickel_resample = wsinterp(grid, nickel_grid, nickel_func)
5959
target_resample = wsinterp(grid, target_grid, target_func)
6060

61-
We can now plot the difference to see that these two functions are quite similar.:
61+
We can now plot the difference to see that these two functions are quite similar.::
6262

6363
plt.plot(grid, target_resample)
6464
plt.plot(grid, nickel_resample)
@@ -78,3 +78,11 @@ given enough datapoints.
7878
In the case of our dataset, our band-limit is ``qmax=25.0`` and our function spans :math:`r \in (0.0, 60.0)`.
7979
Thus, our original grid requires :math:`25.0 * 60.0 / \pi < 478`. Since our grid has :math:`601` datapoints, our
8080
reconstruction was perfect as shown from the comparison between ``Nickel.gr`` and ``NiTarget.gr``.
81+
82+
This computation is implemented in the function ``nsinterp``.::
83+
84+
from diffpy.utils.resampler import nsinterp
85+
qmin = 0
86+
qmax = 25
87+
nickel_resample = (nickel_grid, nickel_func, qmin, qmax)
88+

news/nsinterp.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
**Added:**
2+
3+
* Function nsinterp for automatic interpolation onto the Nyquist-Shannon grid.
4+
5+
**Changed:**
6+
7+
* <news item>
8+
9+
**Deprecated:**
10+
11+
* <news item>
12+
13+
**Removed:**
14+
15+
* <news item>
16+
17+
**Fixed:**
18+
19+
* <news item>
20+
21+
**Security:**
22+
23+
* <news item>

src/diffpy/utils/resampler.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,46 @@ def wsinterp(x, xp, fp, left=None, right=None):
7777
return fp_at_x
7878

7979

80+
def nsinterp(xp, fp, qmin=0, qmax=25, left=None, right=None):
81+
"""One-dimensional Whittaker-Shannon interpolation onto the Nyquist-Shannon grid.
82+
83+
Takes a band-limited function fp and original grid xp and resamples fp on the NS grid.
84+
Uses the minimum number of points N required by the Nyquist sampling theorem.
85+
N = (qmax-qmin)(rmax-rmin)/pi, where rmin and rmax are the ends of the real-space ranges.
86+
fp must be finite, and the user inputs qmin and qmax of the frequency-domain.
87+
88+
Parameters
89+
----------
90+
xp: ndarray
91+
The array of known x values.
92+
fp: ndarray
93+
The array of y values associated with xp.
94+
qmin: float
95+
The lower band limit in the frequency domain.
96+
qmax: float
97+
The upper band limit in the frequency domain.
98+
99+
Returns
100+
-------
101+
x: ndarray
102+
The Nyquist-Shannon grid computed for the given qmin and qmax.
103+
fp_at_x: ndarray
104+
The interpolated values at points x. Returns a single float if x is a scalar,
105+
otherwise returns a numpy.ndarray.
106+
"""
107+
# Ensure numpy array
108+
xp = np.array(xp)
109+
rmin = np.min(xp)
110+
rmax = np.max(xp)
111+
112+
nspoints = int(np.round((qmax-qmin)*(rmax-rmin)/np.pi))
113+
114+
x = np.linspace(rmin, rmax, nspoints)
115+
fp_at_x = wsinterp(x, xp, fp)
116+
117+
return x, fp_at_x
118+
119+
80120
def resample(r, s, dr):
81121
"""Resample a PDF on a new grid.
82122

tests/test_resample.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import numpy as np
44
import pytest
55

6-
from diffpy.utils.resampler import wsinterp
6+
from diffpy.utils.resampler import wsinterp, nsinterp
77

88

99
def test_wsinterp():
@@ -30,3 +30,23 @@ def test_wsinterp():
3030
assert np.allclose(fp_at_x[1:-1], fp)
3131
for i in range(len(x)):
3232
assert fp_at_x[i] == pytest.approx(wsinterp(x[i], xp, fp))
33+
34+
35+
def test_nsinterp():
36+
# Create a cosine function cos(2x) for x \in [0, 3pi]
37+
xp = np.linspace(0, 3*np.pi, 100)
38+
fp = np.cos(2 * xp)
39+
40+
# Want to resample onto the grid {0, pi, 2pi, 3pi}
41+
x = np.array([0, np.pi, 2*np.pi, 3*np.pi])
42+
43+
# Get wsinterp result
44+
ws_f = wsinterp(x, xp, fp)
45+
46+
# Use nsinterp with qmin-qmax=4/3
47+
qmin = np.random.uniform()
48+
qmax = qmin + 4/3
49+
ns_x, ns_f = nsinterp(xp, fp, qmin, qmax)
50+
51+
assert np.allclose(x, ns_x)
52+
assert np.allclose(ws_f, ns_f)

0 commit comments

Comments
 (0)