diff options
| author | J08nY | 2020-07-05 23:42:30 +0200 |
|---|---|---|
| committer | J08nY | 2020-07-05 23:42:30 +0200 |
| commit | fe1b7145e0ce0c5a647216ccf5b749da1de27877 (patch) | |
| tree | b661077ec106206e90dc6ae50c8491926f7e312d | |
| parent | 0e65cac7129365128ea3444bb08390edcce13d9e (diff) | |
| download | pyecsca-fe1b7145e0ce0c5a647216ccf5b749da1de27877.tar.gz pyecsca-fe1b7145e0ce0c5a647216ccf5b749da1de27877.tar.zst pyecsca-fe1b7145e0ce0c5a647216ccf5b749da1de27877.zip | |
Fix trace combination functions.
| -rw-r--r-- | pyecsca/sca/scope/picoscope_sdk.py | 2 | ||||
| -rw-r--r-- | pyecsca/sca/trace/combine.py | 61 |
2 files changed, 53 insertions, 10 deletions
diff --git a/pyecsca/sca/scope/picoscope_sdk.py b/pyecsca/sca/scope/picoscope_sdk.py index 46c1da2..f747388 100644 --- a/pyecsca/sca/scope/picoscope_sdk.py +++ b/pyecsca/sca/scope/picoscope_sdk.py @@ -204,7 +204,7 @@ class PicoScopeSdk(Scope): # pragma: no cover if type == SampleType.Raw: data = arr else: - data = adc2volt(arr, self.ranges[channel], self.MAX_ADC_VALUE) + data = adc2volt(arr, self.ranges[channel], self.MAX_ADC_VALUE, dtype=dtype) return Trace(data, {"sampling_frequency": self.frequency, "channel": channel, "sample_type": type}) def stop(self): diff --git a/pyecsca/sca/trace/combine.py b/pyecsca/sca/trace/combine.py index 04b1a70..496cfcc 100644 --- a/pyecsca/sca/trace/combine.py +++ b/pyecsca/sca/trace/combine.py @@ -18,9 +18,13 @@ def average(*traces: Trace) -> Optional[CombinedTrace]: return None if len(traces) == 1: return CombinedTrace(traces[0].samples.copy()) - dtype = traces[0].samples.dtype - result_samples = np.mean(np.stack([trace.samples for trace in traces]), axis=0).astype(dtype, copy=False) - return CombinedTrace(result_samples) + min_samples = min(map(len, traces)) + s = np.zeros(min_samples, dtype=np.float64) + for t in traces: + s = np.add(s, t.samples[:min_samples]) + avg = ((1/len(traces)) * s) + del s + return CombinedTrace(avg) @public @@ -45,9 +49,46 @@ def standard_deviation(*traces: Trace) -> Optional[CombinedTrace]: """ if not traces: return None - dtype = traces[0].samples.dtype - result_samples = np.std(np.stack([trace.samples for trace in traces]), axis=0).astype(dtype, copy=False) - return CombinedTrace(result_samples) + if len(traces) == 0: + return CombinedTrace(np.zeros(len(traces[0]), dtype=np.float64)) + min_samples = min(map(len, traces)) + s = np.zeros(min_samples, dtype=np.float64) + for t in traces: + s = np.add(s, t.samples[:min_samples]) + ts = np.zeros(min_samples, dtype=np.float64) + for t in traces: + d = np.subtract(t.samples[:min_samples], s) + ts = np.add(ts, np.multiply(d, d, dtype=np.float64)) + std = np.sqrt((1/len(traces)-1) * ts) + del s + del ts + return CombinedTrace(std) + + +@public +def variance(*traces: Trace) -> Optional[CombinedTrace]: + """ + Compute the variance of the `traces`, sample-wise. + + :param traces: + :return: + """ + if not traces: + return None + if len(traces) == 0: + return CombinedTrace(np.zeros(len(traces[0]), dtype=np.float64)) + min_samples = min(map(len, traces)) + s = np.zeros(min_samples, dtype=np.float64) + for t in traces: + s = np.add(s, t.samples[:min_samples]) + ts = np.zeros(min_samples, dtype=np.float64) + for t in traces: + d = np.subtract(t.samples[:min_samples], s) + ts = np.add(ts, np.multiply(d, d, dtype=np.float64)) + var = (1/len(traces)-1) * ts + del s + del ts + return CombinedTrace(var) @public @@ -62,9 +103,11 @@ def add(*traces: Trace) -> Optional[CombinedTrace]: return None if len(traces) == 1: return CombinedTrace(traces[0].samples.copy()) - dtype = traces[0].samples.dtype - result_samples = np.sum(np.stack([trace.samples for trace in traces]), axis=0).astype(dtype, copy=False) - return CombinedTrace(result_samples) + min_samples = min(map(len, traces)) + s = np.zeros(min_samples, dtype=np.float64) + for t in traces: + s = np.add(s, t.samples[:min_samples]) + return CombinedTrace(s) @public |
