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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: regdiff
3
- Version: 3.6.2
3
+ Version: 3.7
4
4
  Summary: Regularized differentiation of time-series as numpy ndarrays
5
5
  Requires-Dist: numpy>=2.5.4
6
6
  Requires-Dist: scipy>=1.18.1
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "regdiff"
3
- version = "3.6.2"
3
+ version = "3.7"
4
4
  description = "Regularized differentiation of time-series as numpy ndarrays"
5
5
  requires-python = ">=3.14"
6
6
  dependencies = [
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "regdiff"
3
- version = "3.6.2"
3
+ version = "3.7"
4
4
  description = "Regularized differentiation of time-series as numpy ndarrays"
5
5
  requires-python = ">=3.14"
6
6
  dependencies = [
@@ -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 or list of ndarrays
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, list):
115
- if len(u0) == n:
116
- u = np.asarray(u0, copy=True) * dx / data_st_dev
117
- elif len(u0) == 2 * n:
118
- u = np.asarray(u0[:n], copy=True) * dx / data_st_dev
119
- v = np.asarray(u0[n:], copy=True) * (dx**2) / data_st_dev
120
- elif len(u0) == 2 and len(u0[0]) == n and len(u0[1]) == n:
121
- u = np.asarray(u0[0], copy=True) * dx / data_st_dev
122
- v = np.asarray(u0[1], copy=True) * (dx**2) / data_st_dev
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 = np.asarray(u0[:, 0], copy=True) * dx / data_st_dev
129
- v = np.asarray(u0[:, 1], copy=True) * (dx**2) / data_st_dev
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
- data_comp = data[1:] - ofst_1
138
- a_tp_b = np.matvec(a_tp, data_comp)
139
- if diag:
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
- print(
158
- f"u, iteration {iter + 1}: cost: {cost_n}, relative change: {npl.norm(s) / npl.norm(u)}"
159
- )
160
- u_cost.append(cost_n)
161
- if iter >= min_iter and npl.norm(s) / npl.norm(u) < delta_norm_tol:
162
- if diag:
163
- print("u, delta norm tolerance reached")
164
- break
165
- if (
166
- prev_cost
167
- and iter >= min_iter
168
- and (prev_cost - cost_n) / prev_cost < delta_cost_tol
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("u, relative cost tolerance reached")
172
- break
173
- prev_cost = cost_n
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
- u = u * data_st_dev / dx
230
- return u, v
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