regdiff 3.6.2__tar.gz → 3.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -70,6 +70,7 @@ def reg_diff(
|
|
|
70
70
|
delta_cost_tol=1e-6,
|
|
71
71
|
delta_norm_tol=1e-6,
|
|
72
72
|
ep=1e-8,
|
|
73
|
+
skip_first_deriv=False,
|
|
73
74
|
diag=False,
|
|
74
75
|
):
|
|
75
76
|
"""differentation function that takes a vector of position data and returns the first and second derivatives, evaluated using TV-regularized differentiation.
|
|
@@ -77,12 +78,13 @@ def reg_diff(
|
|
|
77
78
|
:param alpha: the regularization coefficient for the first derivative
|
|
78
79
|
:param alpha2: the regularization coeffiient for the second derivative. If left blank only the first derivative will be calculated.
|
|
79
80
|
:param dx: the time step for the data
|
|
80
|
-
:param u0: an initial guess for the derivative(s) as an ndarray
|
|
81
|
+
:param u0: an initial guess for the derivative(s) as an ndarray
|
|
81
82
|
:param min_iter: minimal number of iterations to calculate before returning. Default value 5.
|
|
82
83
|
:param max_iter: maximum number of iterations to calculate before returning. Default value is 1000000.
|
|
83
84
|
:param delta_cost_tol: relative delta cost to reach iteratively before returning (applies to both derivatives). Default value is 1e-6.
|
|
84
85
|
:param delta_norm_tol: relative delta norm of step to reach iteratively before returning (applies to both derivatives). Default value is 1e-6.
|
|
85
86
|
:param ep: epsilon to use to smooth the absolute value function. Devault value is 1e-8
|
|
87
|
+
:param skip_first_deriv: if True, use the value of u0 for the first derivative and do not calculate it
|
|
86
88
|
:param diag: if True, prints diagnostic information during execution. Default False.
|
|
87
89
|
|
|
88
90
|
:return: u -- the first derivative
|
|
@@ -110,23 +112,25 @@ def reg_diff(
|
|
|
110
112
|
# bunch of code for handling an input u0
|
|
111
113
|
u = None
|
|
112
114
|
v = None
|
|
115
|
+
if u0 is None and skip_first_deriv:
|
|
116
|
+
raise RuntimeError("If first derivative should be skipped, one should be provided")
|
|
113
117
|
if u0 is not None:
|
|
114
|
-
if isinstance(u0,
|
|
115
|
-
if
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
elif
|
|
121
|
-
u =
|
|
122
|
-
v =
|
|
123
|
-
elif isinstance(u0, np.ndarray):
|
|
124
|
-
if u0.shape[0] == 2 and u0.shape[1] == n:
|
|
125
|
-
u = np.asarray(u0[0, :], copy=True) * dx / data_st_dev
|
|
126
|
-
v = np.asarray(u0[1, :], copy=True) * (dx**2) / data_st_dev
|
|
118
|
+
if isinstance(u0, np.ndarray):
|
|
119
|
+
if u0.ndim == 1:
|
|
120
|
+
if len(u0) == n:
|
|
121
|
+
u = u0 * dx / data_st_dev
|
|
122
|
+
else:
|
|
123
|
+
raise ValueError("Expected a first-derivative u0 tensor that is the same size as the data tensor")
|
|
124
|
+
elif u0.shape[0] == 2 and u0.shape[1] == n:
|
|
125
|
+
u = u0[0] * dx / data_st_dev
|
|
126
|
+
v = u0[1] * (dx**2) / data_st_dev
|
|
127
127
|
elif u0.shape[1] == 2 and u0.shape[0] == n:
|
|
128
|
-
u =
|
|
129
|
-
v =
|
|
128
|
+
u = u0[:, 0] * dx / data_st_dev
|
|
129
|
+
v = u0[:, 1] * (dx**2) / data_st_dev
|
|
130
|
+
else:
|
|
131
|
+
raise ValueError("Bad u0 tensor size")
|
|
132
|
+
else:
|
|
133
|
+
raise ValueError("u0 should be an ndarray")
|
|
130
134
|
if not isinstance(u, np.ndarray):
|
|
131
135
|
u = np.matvec(diff, data)
|
|
132
136
|
if not isinstance(v, np.ndarray) and second_deriv:
|
|
@@ -134,43 +138,44 @@ def reg_diff(
|
|
|
134
138
|
|
|
135
139
|
# start calculating u
|
|
136
140
|
ofst_1 = data[0]
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
u_cost = [
|
|
141
|
-
npl.norm(np.subtract(sp.integrate.cumulative_trapezoid(u), data_comp))
|
|
142
|
-
+ alpha * npl.norm(np.diff(u), ord=1)
|
|
143
|
-
]
|
|
144
|
-
prev_cost = None
|
|
145
|
-
for iter in range(max_iter):
|
|
146
|
-
c = np.reciprocal(np.sqrt(np.power(np.diff(u), 2) + ep))
|
|
147
|
-
En = np.diag(c)
|
|
148
|
-
Ln = np.matmul(np.matmul(d_tp, En), d)
|
|
149
|
-
gn = np.add(np.subtract(np.matvec(a_tp_a, u), a_tp_b), alpha * np.matvec(Ln, u))
|
|
150
|
-
Hn = np.add(a_tp_a, alpha * Ln)
|
|
151
|
-
s = npl.solve(Hn, gn)
|
|
152
|
-
u = np.subtract(u, s)
|
|
153
|
-
cost_n = npl.norm(
|
|
154
|
-
np.subtract(sp.integrate.cumulative_trapezoid(u), data_comp)
|
|
155
|
-
) + alpha * npl.norm(np.diff(u), ord=1)
|
|
141
|
+
if not skip_first_deriv:
|
|
142
|
+
data_comp = data[1:] - ofst_1
|
|
143
|
+
a_tp_b = np.matvec(a_tp, data_comp)
|
|
156
144
|
if diag:
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
145
|
+
u_cost = [
|
|
146
|
+
npl.norm(np.subtract(sp.integrate.cumulative_trapezoid(u), data_comp))
|
|
147
|
+
+ alpha * npl.norm(np.diff(u), ord=1)
|
|
148
|
+
]
|
|
149
|
+
prev_cost = None
|
|
150
|
+
for iter in range(max_iter):
|
|
151
|
+
c = np.reciprocal(np.sqrt(np.power(np.diff(u), 2) + ep))
|
|
152
|
+
En = np.diag(c)
|
|
153
|
+
Ln = np.matmul(np.matmul(d_tp, En), d)
|
|
154
|
+
gn = np.add(np.subtract(np.matvec(a_tp_a, u), a_tp_b), alpha * np.matvec(Ln, u))
|
|
155
|
+
Hn = np.add(a_tp_a, alpha * Ln)
|
|
156
|
+
s = npl.solve(Hn, gn)
|
|
157
|
+
u = np.subtract(u, s)
|
|
158
|
+
cost_n = npl.norm(
|
|
159
|
+
np.subtract(sp.integrate.cumulative_trapezoid(u), data_comp)
|
|
160
|
+
) + alpha * npl.norm(np.diff(u), ord=1)
|
|
170
161
|
if diag:
|
|
171
|
-
print(
|
|
172
|
-
|
|
173
|
-
|
|
162
|
+
print(
|
|
163
|
+
f"u, iteration {iter + 1}: cost: {cost_n}, relative change: {npl.norm(s) / npl.norm(u)}"
|
|
164
|
+
)
|
|
165
|
+
u_cost.append(cost_n)
|
|
166
|
+
if iter >= min_iter and npl.norm(s) / npl.norm(u) < delta_norm_tol:
|
|
167
|
+
if diag:
|
|
168
|
+
print("u, delta norm tolerance reached")
|
|
169
|
+
break
|
|
170
|
+
if (
|
|
171
|
+
prev_cost
|
|
172
|
+
and iter >= min_iter
|
|
173
|
+
and (prev_cost - cost_n) / prev_cost < delta_cost_tol
|
|
174
|
+
):
|
|
175
|
+
if diag:
|
|
176
|
+
print("u, relative cost tolerance reached")
|
|
177
|
+
break
|
|
178
|
+
prev_cost = cost_n
|
|
174
179
|
|
|
175
180
|
if second_deriv:
|
|
176
181
|
ofst_2 = u[0]
|
|
@@ -226,5 +231,10 @@ def reg_diff(
|
|
|
226
231
|
break
|
|
227
232
|
prev_cost = cost_n
|
|
228
233
|
v = v * data_st_dev / (dx**2)
|
|
229
|
-
|
|
230
|
-
|
|
234
|
+
returns = []
|
|
235
|
+
if not skip_first_deriv:
|
|
236
|
+
u = u * data_st_dev / dx
|
|
237
|
+
returns.append(u)
|
|
238
|
+
if second_deriv:
|
|
239
|
+
returns.append(v)
|
|
240
|
+
return (*returns,)
|
|
File without changes
|