Skip to content

Commit ce809b4

Browse files
committed
I added multidimensionality functions to the tvrdiff method by calling it recursively. Some changes might need to be made in terms of making the code less verbose, in particular, replacing moveaxis() with apply_along_axis()
1 parent 49631ee commit ce809b4

1 file changed

Lines changed: 43 additions & 0 deletions

File tree

pynumdiff/total_variation_regularization.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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:
5698
def 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

Comments
 (0)