@@ -97,7 +97,7 @@ def _total_variation_regularized_derivative(x, dt, order, gamma, solver=None):
9797 dxdt_hat = y / dt # y only holds the dx values; to get deriv scale by dt
9898 x_hat = np .cumsum (y ) + integration_constants .value [order - 1 ] # smoothed data
9999
100- dxdt_hat = (dxdt_hat [0 :- 1 ] + dxdt_hat [1 :])/ 2 # take first order FD to smooth a touch
100+ dxdt_hat = (dxdt_hat [:- 1 ] + dxdt_hat [1 :])/ 2 # take first order FD to smooth a touch
101101 ddxdt_hat_f = dxdt_hat [- 1 ] - dxdt_hat [- 2 ]
102102 dxdt_hat_f = dxdt_hat [- 1 ] + ddxdt_hat_f # What is this doing? Could we use a 2nd order FD above natively?
103103 dxdt_hat = np .hstack ((dxdt_hat , dxdt_hat_f ))
@@ -106,7 +106,7 @@ def _total_variation_regularized_derivative(x, dt, order, gamma, solver=None):
106106 d = dxdt_hat [2 ] - dxdt_hat [1 ]
107107 dxdt_hat [0 ] = dxdt_hat [1 ] - d
108108
109- return x_hat * std + mean , dxdt_hat * std
109+ return x_hat * std + mean , dxdt_hat * std # derivative is linear, so scale derivative by std
110110
111111
112112def velocity (x , dt , params = None , options = None , gamma = None , solver = None ):
@@ -229,7 +229,7 @@ def smooth_acceleration(x, dt, params=None, options=None, gamma=None, window_siz
229229 return x_hat , dxdt_hat
230230
231231
232- def jerk_sliding (x , dt , params = None , options = None , gamma = None , solver = None ):
232+ def jerk_sliding (x , dt , params = None , options = None , gamma = None , solver = None , window_size = 101 ):
233233 """Use convex optimization (cvxpy) to solve for the jerk total variation regularized derivative.
234234
235235 :param np.array[float] x: data to differentiate
@@ -239,6 +239,7 @@ def jerk_sliding(x, dt, params=None, options=None, gamma=None, solver=None):
239239 :param float gamma: the regularization parameter
240240 :param str solver: the solver CVXPY should use, 'MOSEK', 'CVXOPT', 'CLARABEL', 'ECOS', etc.
241241 In testing, 'MOSEK' was the most robust. If not given, fall back to CVXPY's default.
242+ :param int window_size: how wide to make the kernel
242243
243244 :return: tuple[np.array, np.array] of\n
244245 - **x_hat** -- estimated (smoothed) x
@@ -250,68 +251,16 @@ def jerk_sliding(x, dt, params=None, options=None, gamma=None, solver=None):
250251 gamma = params [0 ] if isinstance (params , list ) else params
251252 if options != None :
252253 if 'solver' in options : solver = options ['solver' ]
254+ if 'window_size' in options : window_size = options ['window_size' ]
253255 elif gamma == None :
254256 raise ValueError ("`gamma` must be given." )
255257
256- window_size = 1000
257- stride = 200
258-
259258 if len (x ) < window_size :
259+ warn ("len(x) <= window_size, calling standard jerk() without sliding" )
260260 return _total_variation_regularized_derivative (x , dt , 3 , gamma , solver = solver )
261261
262- # slide the jerk
263- final_xsmooth = []
264- final_xdot_hat = []
265- first_idx = 0
266- final_idx = first_idx + window_size
267- last_loop = False
268-
269- final_weighting = []
270-
271- try :
272- while not last_loop :
273- xsmooth , xdot_hat = _total_variation_regularized_derivative (x [first_idx :final_idx ], dt , 3 ,
274- gamma , solver = solver )
275-
276- xsmooth = np .hstack (([0 ]* first_idx , xsmooth , [0 ]* (len (x )- final_idx )))
277- final_xsmooth .append (xsmooth )
278-
279- xdot_hat = np .hstack (([0 ]* first_idx , xdot_hat , [0 ]* (len (x )- final_idx )))
280- final_xdot_hat .append (xdot_hat )
281-
282- # blending
283- w = np .hstack (([0 ]* first_idx ,
284- np .arange (1 , 201 )/ 200 ,
285- [1 ]* (final_idx - first_idx - 400 ),
286- (np .arange (1 , 201 )/ 200 )[::- 1 ],
287- [0 ]* (len (x )- final_idx )))
288- final_weighting .append (w )
289-
290- if final_idx >= len (x ):
291- last_loop = True
292- else :
293- first_idx += stride
294- final_idx += stride
295- if final_idx > len (x ):
296- final_idx = len (x )
297- if final_idx - first_idx < 200 :
298- first_idx -= (200 - (final_idx - first_idx ))
299-
300- # normalize columns
301- weights = np .vstack (final_weighting )
302- for c in range (weights .shape [1 ]):
303- weights [:, c ] /= np .sum (weights [:, c ])
304-
305- # weighted sums
306- xsmooth = np .vstack (final_xsmooth )
307- xsmooth = np .sum (xsmooth * weights , axis = 0 )
308-
309- xdot_hat = np .vstack (final_xdot_hat )
310- xdot_hat = np .sum (xdot_hat * weights , axis = 0 )
311-
312- return xsmooth , xdot_hat
313-
314- except ValueError :
315- warn ('Solver failed, returning finite difference instead' )
316- from pynumdiff .finite_difference import second_order
317- return second_order (x , dt )
262+ ramp = window_size // 5
263+ kernel = np .hstack ((np .arange (1 , ramp + 1 )/ ramp , np .ones (window_size - 2 * ramp ), (np .arange (1 , ramp + 1 )/ ramp )[::- 1 ]))
264+ return utility .slide_function (_total_variation_regularized_derivative , x , dt , kernel , 3 , gamma , stride = ramp , solver = solver )
265+
266+
0 commit comments