1515
1616"""Various utilities related to data parsing and manipulation."""
1717
18- import numpy
18+ import numpy as np
1919
2020
21- # NOTE - this should be faster than resample below and conforms more closely to
22- # numpy.interp. I'm keeping resample for legacy reasons.
2321def wsinterp (x , xp , fp , left = None , right = None ):
2422 """One-dimensional Whittaker-Shannon interpolation.
2523
26- This uses the Whittaker-Shannon interpolation formula to interpolate the value of fp (array),
27- which is defined over xp (array), at x (array or float).
24+ Reconstruct a continuous signal from discrete data points by utilizing sinc functions
25+ as interpolation kernels. This function interpolates the values of fp (array),
26+ which are defined over xp (array), at new points x (array or float).
27+ The implementation is based on E. T. Whittaker's 1915 paper
28+ (https://doi.org/10.1017/S0370164600017806).
2829
2930 Parameters
3031 ----------
3132 x: ndarray
32- Desired range for interpolation.
33+ The x values at which interpolation is computed .
3334 xp: ndarray
34- Defined range for fp .
35+ The array of known x values .
3536 fp: ndarray
36- Function to be interpolated .
37+ The array of y values associated with xp .
3738 left: float
3839 If given, set fp for x < xp[0] to left. Otherwise, if left is None (default) or not given,
3940 set fp for x < xp[0] to fp evaluated at xp[-1].
@@ -43,24 +44,23 @@ def wsinterp(x, xp, fp, left=None, right=None):
4344
4445 Returns
4546 -------
46- float:
47- If input x is a scalar (not an array), return the interpolated value at x.
48- ndarray:
49- If input x is an array, return the interpolated array with dimensions of x.
47+ ndarray or float
48+ The interpolated values at points x. Returns a single float if x is a scalar,
49+ otherwise returns a numpy.ndarray.
5050 """
51- scalar = numpy .isscalar (x )
51+ scalar = np .isscalar (x )
5252 if scalar :
53- x = numpy .array (x )
53+ x = np .array (x )
5454 x .resize (1 )
5555 # shape = (nxp, nx), nxp copies of x data span axis 1
56- u = numpy .resize (x , (len (xp ), len (x )))
56+ u = np .resize (x , (len (xp ), len (x )))
5757 # Must take transpose of u for proper broadcasting with xp.
5858 # shape = (nx, nxp), v(xp) data spans axis 1
5959 v = (xp - u .T ) / (xp [1 ] - xp [0 ])
6060 # shape = (nx, nxp), m(v) data spans axis 1
61- m = fp * numpy .sinc (v )
61+ m = fp * np .sinc (v )
6262 # Sum over m(v) (axis 1)
63- fp_at_x = numpy .sum (m , axis = 1 )
63+ fp_at_x = np .sum (m , axis = 1 )
6464
6565 # Enforce left and right
6666 if left is None :
@@ -100,36 +100,33 @@ def resample(r, s, dr):
100100 dr0 = r [1 ] - r [0 ] # Constant timestep
101101
102102 if dr0 < dr :
103- rnew = numpy .arange (r [0 ], r [- 1 ] + 0.5 * dr , dr )
104- snew = numpy .interp (rnew , r , s )
103+ rnew = np .arange (r [0 ], r [- 1 ] + 0.5 * dr , dr )
104+ snew = np .interp (rnew , r , s )
105105 return rnew , snew
106106
107107 elif dr0 > dr :
108108 # Tried to pad the end of s to dampen, but nothing works.
109109 # m = (s[-1] - s[-2]) / dr0
110110 # b = (s[-2] * r[-1] - s[-1] * r[-2]) / dr0
111- # rpad = r[-1] + numpy .arange(1, len(s))*dr0
111+ # rpad = r[-1] + np .arange(1, len(s))*dr0
112112 # spad = rpad * m + b
113- # spad = numpy .concatenate([s,spad])
114- # rnew = numpy .arange(0, rpad[-1], dr)
115- # snew = numpy .zeros_like(rnew)
113+ # spad = np .concatenate([s,spad])
114+ # rnew = np .arange(0, rpad[-1], dr)
115+ # snew = np .zeros_like(rnew)
116116 # Accommodate for the fact that r[0] might not be 0
117117 # u = (rnew-r[0]) / dr0
118118 # for n in range(len(spad)):
119- # snew += spad[n] * numpy .sinc(u - n)
119+ # snew += spad[n] * np .sinc(u - n)
120120
121- # sel = numpy .logical_and(rnew >= r[0], rnew <= r[-1])
121+ # sel = np .logical_and(rnew >= r[0], rnew <= r[-1])
122122
123- rnew = numpy .arange (0 , r [- 1 ], dr )
124- snew = numpy .zeros_like (rnew )
123+ rnew = np .arange (0 , r [- 1 ], dr )
124+ snew = np .zeros_like (rnew )
125125 u = (rnew - r [0 ]) / dr0
126126 for n in range (len (s )):
127- snew += s [n ] * numpy .sinc (u - n )
128- sel = numpy .logical_and (rnew >= r [0 ], rnew <= r [- 1 ])
127+ snew += s [n ] * np .sinc (u - n )
128+ sel = np .logical_and (rnew >= r [0 ], rnew <= r [- 1 ])
129129 return rnew [sel ], snew [sel ]
130130
131131 # If we got here, then no resampling is required
132132 return r .copy (), s .copy ()
133-
134-
135- # End of file
0 commit comments