3Contains class definitions for filtering algorithms.
4Those can be leveraged to deal with noise, e.g.\ by smoothing neighboring data points.
10from abc
import abstractmethod
15from fosanalysis
import utils
20 Abstract base class for filter classes.
21 These filters will modify the values, but not the shape of the arrays.
23 To reduce/avoid boundary effects, generally crop the data after smoothing.
28 A filter to limit the entries.
29 The result \f$y\f$ will only contain all entries for which \f$y_i \in [x_{\mathrm{min}},\: x_{\mathrm{max}}]\f$ holds.
30 Values, that exceed the limits, will be truncated at the according limit using the equation
31 \f[y_i = \min\left(\max\left(x_i,\: x_{\mathrm{min}}\right),\: x_{\mathrm{max}}\right)\f].
34 minimum: float =
None,
35 maximum: float =
None,
38 Construct an instance of the class.
39 \param minimum \copydoc minimum
40 \param maximum \copydoc maximum
41 \param *args Additional positional arguments, will be passed to the superconstructor.
42 \param **kwargs Additional keyword arguments, will be passed to the superconstructor.
57 make_copy: bool =
True,
58 timespace: str =
"2d",
59 minimum: float =
None,
60 maximum: float =
None,
61 *args, **kwargs) -> tuple:
63 Limit the entries in the given list to the specified range.
64 Returns a list, which conforms to \f$\mathrm{minimum} \leq x \leq \mathrm{maximum} \forall x \in X\f$.
65 Entries, which exceed the given range are cropped to it.
66 \copydetails preprocessing.base.Task.run()
67 \param minimum \copydoc minimum
68 \param maximum \copydoc maximum
70 return super().
run(x, y, z,
79 *args, **kwargs) -> tuple:
80 return x, self.
_limit(z, *args, **kwargs)
85 *args, **kwargs) -> tuple:
86 return x, y, self.
_limit(z, *args, **kwargs)
89 minimum: float =
None,
90 maximum: float =
None,
91 *args, **kwargs) -> np.array:
93 Limit the values of the array.
94 \param z Array with data to be limited.
95 \param minimum \copydoc minimum
96 \param maximum \copydoc maximum
97 \param *args Additional positional arguments, ignored.
98 \param **kwargs Additional keyword arguments, ignored.
100 minimum = minimum
if minimum
is not None else self.
minimum
101 maximum = maximum
if maximum
is not None else self.
maximum
102 if minimum
is not None:
103 z = np.maximum(z, minimum)
104 if maximum
is not None:
105 z = np.minimum(z, maximum)
110 Abstract base class for filter classes, based on sliding windows.
111 The sliding windows are generated by \ref utils.windows.sliding().
112 To each of those sliding windows, \ref method is applied.
113 The result is written to the central pixel of the window.
114 To reduce/avoid boundary effects, genrally crop the data after smoothing.
119 pad_mode: str =
None,
122 Construct an instance of the class.
123 As this is an abstract class, it may not be instantiated directly itself.
124 \param radius \copydoc radius
125 \param method \copydoc method
126 \param pad_mode \copydoc pad_mode
127 \param *args Additional positional arguments, will be passed to the superconstructor.
128 \param **kwargs Additional keyword arguments, will be passed to the superconstructor.
162 timespace: str =
None,
163 make_copy: bool =
True,
166 *args, **kwargs) -> tuple:
168 The given data is filtered with a sliding window.
169 \copydetails SlidingFilter
170 \copydetails preprocessing.base.Task.run()
171 \param radius \copydoc radius Defaults to \ref radius.
172 \param method \copydoc method
174 return super().
run(x, y, z,
183 *args, **kwargs) -> tuple:
184 return x, self.
_slide(z, *args, **kwargs)
189 *args, **kwargs) -> tuple:
190 return x, y, self.
_slide(z, *args, **kwargs)
195 *args, **kwargs) -> np.array:
197 Move the window over the input array and apply \ref method on it.
198 The central pixel of the window \f$x_{i}\f$ is assigned the value
200 x_{i} \gets \mathrm{op}(x_{j,\:\ldots,\:k}) \text{ with } j = i -r \text{ and } k = i + r.
202 \param z Array of strain data.
203 \param radius \copydoc radius Defaults to \ref radius.
204 \param method \copydoc method
205 \param *args Additional positional arguments, will be ignored.
206 \param **kwargs Additional keyword arguments, will be ignored.
207 \return Returns an array with the same shape as `z`.
209 radius = radius
if radius
is not None else self.
radius
210 method = method
if method
is not None else self.
method
211 method_function = method
if callable(method)
else getattr(np, method)
214 return utils.windows.sliding_window_function(z, radius, method_function)
218 The Cluster filter is an iterative smoothing algorithm guaranteed to converge \cite Lou_2020_ApplicationofClustering.
219 The one-dimensional signal to filter consists of abscissa data \f$\mathbf{x}\f$ and according ordinate data (measured values) \f$\mathbf{z}\f$.
220 For the \f$k\f$th entry (pixel), consisting of its location \f$x_{k}\f$ and its original value \f$z_{k}\f$, a value is estimated iteratively.
221 The pixel value estimate \f$z^{(t+1)}_{k}\f$ for the next iteration step \f$t+1\f$ is determined by (see \ref _new_z_t()):
223 z^{(t+1)}_{k} = \frac{
224 \sum_{i} z_{i} w_{i} \exp\left(- \beta^{(t)} \left(z_{i} - z^{(t)}_{k}\right)^{2}\right)
226 \sum_{i} w_{i} \exp\left(- \beta^{(t)} \left(z_{i} - z^{(t)}_{k}\right)^{2}\right)
229 Here, the \f$i\f$th pixels position is \f$x_{i}\f$, its value is \f$z_{i}\f$ and \f$w_{i}\f$ is its weight.
230 The weight indicates the influence on the currently optimized pixel at position \f$x_{k}\f$
231 and drops exponentially with the distance for the current pixel (see \ref _get_weights())
233 w_{i} = \exp\left(-\alpha ||x_{i} - x_{k}||^{2}\right)
235 with \f$|| x_{i} - x_{k} ||^{2}\f$ being the squared Euclidian norm.
236 The main parameter for the filter is \f$\alpha\f$, which controls the weight falloff and hence, the filter's scale.
237 It can be calculated from ttarget weight and distance with \ref estimate_alpha().
238 The locality parameter \f$\beta\f$ based on the local variance is estimated to (see \ref _get_beta()):
243 2 \sum_{i} \left(z_{i}-z^{(t)_{k}}\right)^{2} w_{i}
246 The initial guess \f$z^{(0)}\f$ is estimated by (see \ref _initial_z):
254 After each iteration, the estimate change is
256 \Delta z^{(t)}_{k} = |z^{(t-1)} - z^{(t)}_{k}|
258 calculated and the iteration is stopped if this change falls below the predefined threshold \f$\Delta z_{\mathrm{tol}}\f$:
260 \Delta z^{(t)}_{k} \leq \Delta z_{\mathrm{tol}}.
262 This process is repeated for all pixels.
266 tolerance: float = 0.1,
270 Construct a Cluster object.
271 \param alpha \copybrief alpha \copydetails alpha For more, see \ref alpha.
272 \param tolerance \copybrief tolerance \copydetails tolerance.
273 \param fill \copybrief fill \copydetails fill.
274 \param *args Additional positional arguments, will be passed to the superconstructor.
275 \param **kwargs Additional keyword arguments, will be passed to the superconstructor.
300 assert alpha >= 0,
"The scaling value alpha needs to be non-negative!"
305 *args, **kwargs) -> tuple:
307 Carry out the filtering on one-dimensional data.
309 \copydetails fosanalysis.preprocessing.base.Task._run_1d()
311 z_filtered = copy.deepcopy(z)
312 z_zero = copy.deepcopy(z)
313 nan_array = np.logical_not(np.isfinite(z_zero))
314 z_zero[nan_array] = 0
315 iterator = np.nditer(z_zero, flags=[
"multi_index"])
316 for z_orig
in iterator:
317 pixel = iterator.multi_index
318 if self.
fill or not nan_array[pixel]:
320 weights_array[nan_array] = 0
324 z_t_new = self.
_new_z_t(z_zero, weights_array, z_t)
325 improvement = z_t_new - z_t
327 z_filtered[pixel] = z_t
333 *args, **kwargs) -> tuple:
335 Cluster has no true 2D operation mode.
336 Set \ref timespace to `"1d_space"`!
338 raise NotImplementedError(
"Cluster does not support true 2D operation. Try `timepace='1d_space'` instead.")
344 Calculate the array of weights for the current position.
345 The weight \f$w_i\f$ of the \f$i\f$th element on the current
346 element is calculated as
348 w_{i} = \exp\left(-\alpha || x_{i} - x ||^{2}\right).
350 \param pixel Position (index) of the current datapoint to estimate.
351 \param x_array Array of abscissa data.
353 position = x_array[pixel]
354 dist = np.square(x_array - position)
355 return np.exp(-self.
alpha * dist)
357 z_dist_array: np.array,
358 weights_array: np.array,
361 Calculate the locality parameter \f$\beta\f$.
362 The locality parameter \f$\beta\f$ is affected on the local variance.
368 2 \sum_{i} \left(z_{i}-z^{(t)_{k}}\right)^{2} w_{i}
371 \param z_dist_array 1D-array distance matrix for the current pixel.
372 \param weights_array 1D-array containing the weights.
374 return 0.5 * np.sum(weights_array)/np.sum(weights_array * z_dist_array)
377 weights_array:np.array,
380 Guess the the initial estimate.
381 The initial estimate \f$z^{(0)}\f$ is calculated by
383 z^{(0)} = \frac{\sum_{i} z_{i} w_{i}}{\sum_{i} w_{i}}.
385 \param z_array 1D-array of the original ordniate data.
386 \param weights_array 1D-array containing the weights.
388 return np.sum(weights_array * z_array)/np.sum(weights_array)
391 weights_array: np.array,
395 Calculate the next iteration estimate.
396 The next estimate \f$z^{(t+1)}_{k}\f$ is calculated as
398 z^{(t+1)}_{k} = \frac{
399 \sum_{i} z_{i} w_{i} \exp\left(- \beta^{(t)} \left(z_{i} - z^{(t)}_{k}\right)^{2}\right)
401 \sum_{i} w_{i} \exp\left(- \beta^{(t)} \left(z_{i} - z^{(t)}_{k}\right)^{2}\right)
404 Here, the \f$i\f$th pixels position is \f$x_{i}\f$, its value is \f$z_{i}\f$ and \f$w_{i}\f$ is its weight.
405 The weight indicates the influence on the currently optimized pixel at position \f$x_{k}\f$
406 and drops exponentially with the distance for the current pixel.
407 \param z_array 1D-array of the original ordniate data.
408 \param weights_array 1D-array containing the weights.
409 \param z_t Estimate of the previous iteration step for the current pixel.
411 z_dist_array = np.square(z_array - z_t)
412 beta = self.
_get_beta(z_dist_array, weights_array)
413 weighted = weights_array * np.exp(-beta * z_dist_array)
414 numerator = np.sum(z_array * weighted)
415 denominator = np.sum(weighted)
416 return numerator/denominator
422 Calculate the weight falloff parameter \f$\alpha\f$, see \ref alpha.
425 \alpha = -\frac{\ln w}{l^2}
427 \param weight Target weight \f$w\f$.
428 \param length Target distance \f$l\f$.
430 assert weight > 0,
"weight and length must be greater than 0!"
431 assert length > 0,
"weight and length must be greater than 0!"
432 return -np.log(weight)/(np.square(length))
Abstract base class for preprocessing task classes.
The Cluster filter is an iterative smoothing algorithm guaranteed to converge lou_2020_applicationofc...
float _initial_z(self, np.array z_array, np.array weights_array)
Guess the the initial estimate.
tuple _run_2d(self, np.array x, np.array y, np.array z, *args, **kwargs)
Cluster has no true 2D operation mode.
float _new_z_t(self, np.array z_array, np.array weights_array, float z_t)
fill
Switch, whether missing data should be interpolated.
tuple _run_1d(self, np.array x, np.array z, *args, **kwargs)
Carry out the filtering on one-dimensional data.
tolerance
Stopping criterion for the iterative process.
alpha
Falloff parameter for the weight function.
__init__(self, float alpha, float tolerance=0.1, bool fill=False, *args, **kwargs)
Construct a Cluster object.
float _get_beta(self, np.array z_dist_array, np.array weights_array)
np.array _get_weights(self, int pixel, np.array x_array)
Calculate the array of weights for the current position.
estimate_alpha(self, float weight, float length)
Calculate the weight falloff parameter , see alpha.
Abstract base class for filter classes.
A filter to limit the entries.
tuple _run_2d(self, np.array x, np.array y, np.array z, *args, **kwargs)
Native two-dimensional operation implementation.
maximum
Maximal value, which will be included in the result.
np.array _limit(self, np.array z, float minimum=None, float maximum=None, *args, **kwargs)
Limit the values of the array.
__init__(self, float minimum=None, float maximum=None, *args, **kwargs)
Construct an instance of the class.
tuple run(self, np.array x, np.array y, np.array z, bool make_copy=True, str timespace="2d", float minimum=None, float maximum=None, *args, **kwargs)
Limit the entries in the given list to the specified range.
minimum
Minimal value, which will be included in the result.
tuple _run_1d(self, np.array x, np.array z, *args, **kwargs)
Reimplementations describe a one-dimensional operation.
Abstract base class for filter classes, based on sliding windows.
tuple run(self, np.array x, np.array y, np.array z, str timespace=None, bool make_copy=True, int radius=None, str method=None, *args, **kwargs)
The given data is filtered with a sliding window.
__init__(self, int radius, str method, str pad_mode=None, *args, **kwargs)
Construct an instance of the class.
tuple _run_1d(self, np.array x, np.array z, *args, **kwargs)
Reimplementations describe a one-dimensional operation.
np.array _slide(self, np.array z, radius=None, str method=None, *args, **kwargs)
Move the window over the input array and apply method on it.
tuple _run_2d(self, np.array x, np.array y, np.array z, *args, **kwargs)
Native two-dimensional operation implementation.
pad_mode
Mode for padding the edges of the result array.
radius
Smoothing radius for the data, number of entries of data to each side to be taken into account.
method
Specify, how the data is smoothed.