@@ -52,7 +52,49 @@ def iterative_velocity(x, dt, params=None, options=None, num_iterations=None, ga
5252
5353 return x_hat , dxdt_hat
5454
55+ #N-d case:
56+ def tvrdiff (x , dt , order , gamma , huberM = float ('inf' ), solver = None , axis = 0 ):
57+ """
58+ Generalized total variation regularized derivatives (cvxpy). Supports multidimensionality by differentiating along
59+ 'axis', independently for each vector obtained by fixing all other indices.
60+
61+ :param np.array[float] x: data to differentiate
62+ :param float dt: step size
63+ :param int order: 1, 2, or 3, the derivative to regularize
64+ :param float gamma: regularization parameter
65+ :param float huberM: Huber loss parameter, in units of scaled median absolute deviation of input data.
66+ :math:`M = \\ infty` reduces to :math:`\\ ell_2` loss squared on first, fidelity cost term, and
67+ :math:`M = 0` reduces to :math:`\\ ell_1` loss, which seeks sparse residuals.
68+ :param str solver: Solver to use. Solver options include: 'MOSEK', 'CVXOPT', 'CLARABEL', 'ECOS'.
69+ If not given, fall back to CVXPY's default.
5570
71+ :return: - **x_hat** (np.array) -- estimated (smoothed) x
72+ - **dxdt_hat** (np.array) -- estimated derivative of x
73+ """
74+
75+ x0 = np .moveaxis (x , axis , 0 )
76+
77+ # end quick if it's just 1d case
78+ if x0 .ndim == 1 :
79+ x_hat0 , dxdt0 = tvrdiff (x0 , dt , order , gamma , huberM , solver )
80+ return x_hat0 , dxdt0
81+
82+ x_hat0 = np .empty_like (x0 , dtype = float )
83+ dxdt0 = np .empty_like (x0 , dtype = float )
84+ rest = x0 .shape [1 :]
85+ print (rest )
86+
87+ # had to loop in python:(
88+ for i in np .ndindex (rest ):
89+ slice = (slice (None ),) + i
90+ x_hat0 [slice ], dxdt0 [slice ] = tvrdiff (x0 [slice ], dt , order , gamma , huberM , solver )
91+
92+ x_hat = np .moveaxis (x_hat0 , 0 , axis )
93+ dxdt_hat = np .moveaxis (dxdt0 , 0 , axis )
94+
95+ return x_hat , dxdt_hat
96+
97+ # 1-d case:
5698def tvrdiff (x , dt , order , gamma , huberM = float ('inf' ), solver = None ):
5799 """Generalized total variation regularized derivatives. Use convex optimization (cvxpy) to solve for a
58100 total variation regularized derivative. Other convex-solver-based methods in this module call this function.
@@ -70,6 +112,7 @@ def tvrdiff(x, dt, order, gamma, huberM=float('inf'), solver=None):
70112 :return: - **x_hat** (np.array) -- estimated (smoothed) x
71113 - **dxdt_hat** (np.array) -- estimated derivative of x
72114 """
115+
73116 # Normalize for numerical consistency with convex solver
74117 mu = np .mean (x )
75118 sigma = median_abs_deviation (x , scale = 'normal' ) # robust alternative to std()
0 commit comments