Skip to content

Commit 5815158

Browse files
committed
finished #68 for smooth_finite_difference module
1 parent ab43990 commit 5815158

1 file changed

Lines changed: 69 additions & 118 deletions

File tree

pynumdiff/smooth_finite_difference/_smooth_finite_difference.py

Lines changed: 69 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ def mediandiff(x, dt, params=None, options={}, window_size=5, num_iterations=1):
2626
- **dxdt_hat** -- estimated derivative of x
2727
"""
2828
if params != None: # Warning to support old interface for a while. Remove these lines along with params in a future release.
29-
warn("""`params` and `options` parameters will be removed in a future version. Use `window_size`
30-
and `num_iterations` instead.""", DeprecationWarning)
29+
warn("`params` and `options` parameters will be removed in a future version. Use `window_size` " +
30+
"and `num_iterations` instead.", DeprecationWarning)
3131
window_size = params[0] if isinstance(params, list) else params
3232
if 'iterate' in options and options['iterate']:
3333
num_iterations = params[1]
@@ -60,8 +60,8 @@ def meandiff(x, dt, params=None, options={}, window_size=5, num_iterations=1):
6060
- **dxdt_hat** -- estimated derivative of x
6161
"""
6262
if params != None: # Warning to support old interface for a while. Remove these lines along with params in a future release.
63-
warn("""`params` and `options` parameters will be removed in a future version. Use `window_size`
64-
and `num_iterations` instead.""", DeprecationWarning)
63+
warn("`params` and `options` parameters will be removed in a future version. Use `window_size` " +
64+
"and `num_iterations` instead.", DeprecationWarning)
6565
window_size = params[0] if isinstance(params, list) else params
6666
if 'iterate' in options and options['iterate']:
6767
num_iterations = params[1]
@@ -89,8 +89,8 @@ def gaussiandiff(x, dt, params=None, options={}, window_size=5, num_iterations=1
8989
- **dxdt_hat** -- estimated derivative of x
9090
"""
9191
if params != None: # Warning to support old interface for a while. Remove these lines along with params in a future release.
92-
warn("""`params` and `options` parameters will be removed in a future version. Use `window_size`
93-
and `num_iterations` instead.""", DeprecationWarning)
92+
warn("`params` and `options` parameters will be removed in a future version. Use `window_size` " +
93+
"and `num_iterations` instead.", DeprecationWarning)
9494
window_size = params[0] if isinstance(params, list) else params
9595
if 'iterate' in options and options['iterate']:
9696
num_iterations = params[1]
@@ -102,99 +102,65 @@ def gaussiandiff(x, dt, params=None, options={}, window_size=5, num_iterations=1
102102
return x_hat, dxdt_hat
103103

104104

105-
def friedrichsdiff(x, dt, params, options={}):
106-
"""
107-
Perform friedrichs smoothing by convolving friedrichs kernel with x
108-
followed by first order finite difference
109-
110-
:param x: array of time series to differentiate
111-
:type x: np.array (float)
112-
113-
:param dt: time step size
114-
:type dt: float
115-
116-
:param params: [filter_window_size] or if 'iterate' in options:
117-
[filter_window_size, num_iterations]
118-
119-
:type params: list (int)
120-
121-
:param options: an empty dictionary or a dictionary with 1 key value pair
122-
123-
- 'iterate': whether to run multiple iterations of the smoother. Note: iterate does nothing for median smoother.
124-
125-
:type options: dict {'iterate': (boolean)}
126-
127-
:return: a tuple consisting of:
128-
129-
- x_hat: estimated (smoothed) x
130-
- dxdt_hat: estimated derivative of x
105+
def friedrichsdiff(x, dt, params=None, options={}, window_size=5, num_iterations=1):
106+
"""Perform friedrichs smoothing by convolving friedrichs kernel with x followed by first order finite difference
131107
108+
:param np.array[float] x: array of time series to differentiate
109+
:param float dt: time step size
110+
:param list[int] params: (**deprecated**, prefer :code:`window_size` and :code:`num_iterations`)
111+
:code:`[window_size]` or, :code:`if 'iterate' in options`, :code:`[window_size, num_iterations]`
112+
:param dict options: (**deprecated**, prefer :code:`num_iterations`) an empty dictionary or {'iterate': (bool)}
113+
:param int window_size: filter window size
114+
:param int num_iterations: how many times to apply smoothing
132115
133-
:rtype: tuple -> (np.array, np.array)
116+
:return: tuple[np.array, np.array] of\n
117+
- **x_hat** -- estimated (smoothed) x
118+
- **dxdt_hat** -- estimated derivative of x
134119
"""
135-
136-
if 'iterate' in options.keys() and options['iterate'] is True:
137-
window_size, iterations = params
138-
else:
139-
iterations = 1
140-
if isinstance(params, list):
141-
window_size = params[0]
142-
else:
143-
window_size = params
120+
if params != None: # Warning to support old interface for a while. Remove these lines along with params in a future release.
121+
warn("`params` and `options` parameters will be removed in a future version. Use `window_size` " +
122+
"and `num_iterations` instead.", DeprecationWarning)
123+
window_size = params[0] if isinstance(params, list) else params
124+
if 'iterate' in options and options['iterate']:
125+
num_iterations = params[1]
144126

145127
kernel = utility._friedrichs_kernel(window_size)
146-
x_hat = utility.convolutional_smoother(x, kernel, iterations)
128+
x_hat = utility.convolutional_smoother(x, kernel, num_iterations)
147129
x_hat, dxdt_hat = finite_difference(x_hat, dt)
148130

149131
return x_hat, dxdt_hat
150132

151133

152-
def butterdiff(x, dt, params, options={}):
153-
"""
154-
Perform butterworth smoothing on x with scipy.signal.filtfilt
155-
followed by first order finite difference
156-
157-
:param x: array of time series to differentiate
158-
:type x: np.array (float)
159-
160-
:param dt: time step size
161-
:type dt: float
162-
163-
:param params: [n, wn], n = order of the filter; wn = Cutoff frequency.
164-
For a discrete timeseries, the value is normalized to the range 0-1,
165-
where 1 is the Nyquist frequency.
166-
167-
:type params: list (int)
168-
169-
:param options: an empty dictionary or a dictionary with 2 key value pair
170-
171-
- 'iterate': whether to run multiple iterations of the smoother. Note: iterate does nothing for median smoother.
172-
- 'padmethod': "pad" or "gust", see scipy.signal.filtfilt
173-
174-
:type options: dict {'iterate': (boolean), 'padmethod': string}
175-
176-
:return: a tuple consisting of:
177-
178-
- x_hat: estimated (smoothed) x
179-
- dxdt_hat: estimated derivative of x
134+
def butterdiff(x, dt, params=None, options={}, filter_order=2, cutoff_freq=0.5, num_iterations=1):
135+
"""Perform butterworth smoothing on x with scipy.signal.filtfilt followed by first order finite difference
180136
137+
:param np.array[float] x: array of time series to differentiate
138+
:param float dt: time step size
139+
:param list[int] params: (**deprecated**, prefer :code:`filter_order`, :code:`cutoff_freq`,
140+
and :code:`num_iterations`)
141+
:param dict options: (**deprecated**, prefer :code:`num_iterations`) an empty dictionary or {'iterate': (bool)}
142+
:param int filter_order: order of the filter
143+
:param float cutoff_freq: cutoff frequency :math:`\\in [0, 1]`. For a discrete timeseries,
144+
the value is normalized to the range 0-1, where 1 is the Nyquist frequency.
145+
:param int num_iterations: how many times to apply smoothing
181146
182-
:rtype: tuple -> (np.array, np.array)
147+
:return: tuple[np.array, np.array] of\n
148+
- **x_hat** -- estimated (smoothed) x
149+
- **dxdt_hat** -- estimated derivative of x
183150
"""
184-
if 'iterate' in options.keys() and options['iterate'] is True:
185-
n, wn, iterations = params
186-
else:
187-
iterations = 1
188-
n, wn = params
151+
if params != None: # Warning to support old interface for a while. Remove these lines along with params in a future release.
152+
warn("`params` and `options` parameters will be removed in a future version. Use `filter_order`, " +
153+
"`cutoff_freq`, and `num_iterations` instead.", DeprecationWarning)
154+
filter_order, cutoff_freq = params[0:2]
155+
if 'iterate' in options and options['iterate']:
156+
num_iterations = params[2]
189157

190-
b, a = scipy.signal.butter(n, wn)
158+
b, a = scipy.signal.butter(filter_order, cutoff_freq)
191159

192160
x_hat = x
193-
for _ in range(iterations):
194-
if len(x) < 9:
195-
x_hat = scipy.signal.filtfilt(b, a, x_hat, method="pad", padlen=len(x)-1)
196-
else:
197-
x_hat = scipy.signal.filtfilt(b, a, x_hat, method="pad")
161+
padlen = len(x)-1 if len(x) < 9 else None
162+
for _ in range(num_iterations):
163+
x_hat = scipy.signal.filtfilt(b, a, x_hat, method="pad", padlen=padlen)
198164

199165
x_hat, dxdt_hat = finite_difference(x_hat, dt)
200166

@@ -204,48 +170,33 @@ def butterdiff(x, dt, params, options={}):
204170
return x_hat, dxdt_hat
205171

206172

207-
def splinediff(x, dt, params, options={}):
208-
"""
209-
Perform spline smoothing on x with scipy.interpolate.UnivariateSpline
210-
followed by first order finite difference
211-
212-
:param x: array of time series to differentiate
213-
:type x: np.array (float)
214-
215-
:param dt: time step size
216-
:type dt: float
217-
218-
:param params: [k, s], k: Order of the spline. A kth order spline can be differentiated k times.
219-
s: Positive smoothing factor used to choose the number of knots.
220-
Number of knots will be increased until the smoothing condition is satisfied:
221-
sum((w[i] * (y[i]-spl(x[i])))**2, axis=0) <= s
222-
223-
:type params: list (int)
224-
225-
:param options: an empty dictionary or a dictionary with 1 key value pair
226-
227-
- 'iterate': whether to run multiple iterations of the smoother. Note: iterate does nothing for median smoother.
228-
229-
:type options: dict {'iterate': (boolean)}
230-
231-
:return: a tuple consisting of:
232-
233-
- x_hat: estimated (smoothed) x
234-
- dxdt_hat: estimated derivative of x
173+
def splinediff(x, dt, params=None, options={}, k=3, s=None, num_iterations=1):
174+
"""Perform spline smoothing on x with scipy.interpolate.UnivariateSpline followed by first order finite difference
235175
176+
:param np.array[float] x: array of time series to differentiate
177+
:param float dt: time step size
178+
:param list params: (**deprecated**, prefer :code:`order`, :code:`cutoff_freq`, and :code:`num_iterations`)
179+
:param dict options: (**deprecated**, prefer :code:`num_iterations`) an empty dictionary or {'iterate': (bool)}
180+
:param int k: polynomial order of the spline. A kth order spline can be differentiated k times.
181+
:param float s: positive smoothing factor used to choose the number of knots. Number of knots will be increased
182+
until the smoothing condition is satisfied: :math:`\\sum_t (x[t] - \\text{spline}[t])^2 \\leq s`
183+
:param int num_iterations: how many times to apply smoothing
236184
237-
:rtype: tuple -> (np.array, np.array)
185+
:return: tuple[np.array, np.array] of\n
186+
- **x_hat** -- estimated (smoothed) x
187+
- **dxdt_hat** -- estimated derivative of x
238188
"""
239-
if 'iterate' in options.keys() and options['iterate'] is True:
240-
k, s, iterations = params
241-
else:
242-
iterations = 1
243-
k, s = params
189+
if params != None: # Warning to support old interface for a while. Remove these lines along with params in a future release.
190+
warn("`params` and `options` parameters will be removed in a future version. Use `k`, `s`, and " +
191+
"`num_iterations` instead.", DeprecationWarning)
192+
k, s = params[0:2]
193+
if 'iterate' in options and options['iterate']:
194+
num_iterations = params[2]
244195

245196
t = np.arange(0, len(x)*dt, dt)
246197

247198
x_hat = x
248-
for _ in range(iterations):
199+
for _ in range(num_iterations):
249200
spline = scipy.interpolate.UnivariateSpline(t, x_hat, k=k, s=s)
250201
x_hat = spline(t)
251202

0 commit comments

Comments
 (0)