blob: 5540e7aefaeb64167e390127a59f89e1d3dfb8e4 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
"""Provides functions for sample-wise processing of single traces."""
from typing import Any
import numpy as np
from scipy.signal import convolve
from public import public
from pyecsca.sca.trace.trace import Trace
@public
def absolute(trace: Trace) -> Trace:
"""
Apply absolute value to samples of :paramref:`~.absolute.trace`.
:param trace:
:return:
"""
return trace.with_samples(np.absolute(trace.samples))
@public
def invert(trace: Trace) -> Trace:
"""
Invert(negate) the samples of :paramref:`~.invert.trace`.
:param trace:
:return:
"""
return trace.with_samples(np.negative(trace.samples))
@public
def threshold(trace: Trace, value) -> Trace:
"""
Map samples of the :paramref:`~.threshold.trace` to ``1`` if they are above :paramref:`~.threshold.value` or to ``0``.
:param trace:
:param value:
:return:
"""
result_samples = trace.samples.copy()
result_samples[result_samples <= value] = 0
result_samples[np.nonzero(result_samples)] = 1
return trace.with_samples(result_samples)
@public
def rolling_mean(trace: Trace, window: int) -> Trace:
"""
Compute the rolling mean of :paramref:`~.rolling_mean.trace` using :paramref:`~.rolling_mean.window`.
Shortens the trace by ``window - 1``.
:param trace:
:param window:
:return:
"""
return trace.with_samples(
convolve(trace.samples, np.ones(window, dtype=trace.samples.dtype), "valid")
/ window
)
@public
def offset(trace: Trace, offset) -> Trace:
"""
Offset samples of :paramref:`~.offset.trace` by :paramref:`~.offset.offset`, sample-wise.
Adds :paramref:`~.offset.offset` to all samples.
:param trace:
:param offset:
:return:
"""
return trace.with_samples(trace.samples + offset)
def _root_mean_square(trace: Trace):
return np.sqrt(np.mean(np.square(trace.samples)))
@public
def recenter(trace: Trace) -> Trace:
"""
Subtract the root mean square of the :paramref:`~.recenter.trace` from its samples, sample-wise.
:param trace:
:return:
"""
around = _root_mean_square(trace)
return offset(trace, -around)
@public
def normalize(trace: Trace) -> Trace:
"""
Normalize a :paramref:`~.normalize.trace` by subtracting its mean and dividing by its standard deviation.
:param trace:
:return:
"""
return trace.with_samples(
(trace.samples - np.mean(trace.samples)) / np.std(trace.samples)
)
@public
def normalize_wl(trace: Trace) -> Trace:
"""
Normalize a :paramref:`~.normalize_wl.trace` by subtracting its mean and dividing by a multiple (= ``len(trace)``) of its standard deviation.
:param trace:
:return:
"""
return trace.with_samples(
(trace.samples - np.mean(trace.samples))
/ (np.std(trace.samples) * len(trace.samples))
)
@public
def transform(trace: Trace, min_value: Any = 0, max_value: Any = 1) -> Trace:
"""
Scale a :paramref:`~.transform.trace` so that its minimum is at :paramref:`~.transform.min_value` and its maximum is at :paramref:`~.transform.max_value`.
:param trace:
:param min_value:
:param max_value:
:return:
"""
t_min = np.min(trace.samples)
t_max = np.max(trace.samples)
t_range = t_max - t_min
d = max_value - min_value
return trace.with_samples(((trace.samples - t_min) * (d / t_range)) + min_value)
|