aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2020-03-05 14:40:05 +0100
committerJ08nY2020-03-05 14:40:05 +0100
commit79de2bbc6f099b0bd1d79427aabd6113e87c31d3 (patch)
tree8d4cb9f762006eb59fb6e6ca1693f241683cc24f
parent0c3c4a8d6725c01d8c4ba7b4a4e5f43922ec1e65 (diff)
downloadpyecsca-79de2bbc6f099b0bd1d79427aabd6113e87c31d3.tar.gz
pyecsca-79de2bbc6f099b0bd1d79427aabd6113e87c31d3.tar.bz2
pyecsca-79de2bbc6f099b0bd1d79427aabd6113e87c31d3.zip
Add proper plotting.
-rw-r--r--pyecsca/sca/trace/combine.py19
-rw-r--r--pyecsca/sca/trace/plot.py49
-rw-r--r--setup.py7
-rw-r--r--test/sca/test_plot.py33
4 files changed, 71 insertions, 37 deletions
diff --git a/pyecsca/sca/trace/combine.py b/pyecsca/sca/trace/combine.py
index 2ab552a..0e7f325 100644
--- a/pyecsca/sca/trace/combine.py
+++ b/pyecsca/sca/trace/combine.py
@@ -1,6 +1,7 @@
+from typing import Callable, Optional
+
import numpy as np
from public import public
-from typing import Callable, Optional
from .trace import Trace, CombinedTrace
@@ -23,7 +24,8 @@ def average(*traces: Trace) -> Optional[CombinedTrace]:
@public
-def conditional_average(*traces: Trace, condition: Callable[[Trace], bool]) -> Optional[CombinedTrace]:
+def conditional_average(*traces: Trace, condition: Callable[[Trace], bool]) -> Optional[
+ CombinedTrace]:
"""
Average `traces` for which the `condition` is True, sample-wise.
@@ -47,3 +49,16 @@ def standard_deviation(*traces: Trace) -> Optional[CombinedTrace]:
dtype = traces[0].samples.dtype
result_samples = np.std(np.array([trace.samples for trace in traces]), axis=0).astype(dtype)
return CombinedTrace(result_samples, None, None)
+
+
+@public
+def subtract(one: Trace, other: Trace) -> CombinedTrace:
+ """
+ Subtract `other` from `one`, sample-wise.
+
+ :param one:
+ :param other:
+ :return:
+ """
+ result_samples = one.samples - other.samples
+ return CombinedTrace(result_samples, None, None)
diff --git a/pyecsca/sca/trace/plot.py b/pyecsca/sca/trace/plot.py
index 4d5c6db..e784e82 100644
--- a/pyecsca/sca/trace/plot.py
+++ b/pyecsca/sca/trace/plot.py
@@ -1,42 +1,49 @@
"""
This module provides functions for plotting traces.
"""
-from bokeh.io import show, save, export_png, export_svgs
-from bokeh.layouts import column
-from bokeh.plotting import Figure
-from bokeh.resources import CDN
+from functools import reduce
+
+import holoviews as hv
+from holoviews.operation.datashader import datashade
from public import public
from .trace import Trace
@public
-def new_figure():
- return Figure()
-
-
-@public
-def show_figure(figure: Figure):
- show(figure)
+def save_figure(figure, fname: str):
+ hv.save(figure, fname + ".html", fmt="html")
@public
-def save_figure(figure: Figure, fname: str, title: str):
- lay = column(figure, sizing_mode='stretch_both')
- save(lay, fname, resources=CDN, title=title)
+def save_figure_png(figure, fname: str):
+ hv.save(figure, fname + ".png", fmt="png")
@public
-def save_figure_png(figure: Figure, fname: str, width: int, height: int):
- export_png(figure, fname, height, width)
+def save_figure_svg(figure, fname: str):
+ hv.save(figure, fname + ".svg", fmt="svg")
@public
-def save_figure_svg(figure: Figure, fname: str):
- lay = column(figure, sizing_mode='stretch_both')
- export_svgs(lay, fname)
+def plot_trace(trace: Trace, **kwargs):
+ line = hv.Curve((range(len(trace)), trace.samples), kdims="x", vdims="y", **kwargs)
+ return datashade(line, normalization="log")
@public
-def plot_trace(figure: Figure, trace: Trace, **kwargs):
- figure.line(range(len(trace)), trace.samples, **kwargs)
+def plot_traces(*traces: Trace, **kwargs):
+ _cmaps = [
+ ["lightblue", "darkblue"],
+ ["lightcoral", "red"],
+ ["lime", "green"],
+ ["orange", "darkorange"],
+ ["plum", "deeppink"],
+ ["peru", "chocolate"],
+ ["cyan", "darkcyan"]
+ ]
+ dss = []
+ for i, trace in enumerate(traces):
+ line = hv.Curve((range(len(trace)), trace.samples), kdims="x", vdims="y", **kwargs)
+ dss.append(datashade(line, normalization="log", cmap=_cmaps[i % len(_cmaps)]))
+ return reduce(lambda x, y: x * y, dss)
diff --git a/setup.py b/setup.py
index 7ebccae..211e99d 100644
--- a/setup.py
+++ b/setup.py
@@ -29,12 +29,15 @@ setup(
"numpy",
"scipy",
"atpublic",
- "matplotlib",
"cython",
"fastdtw",
"asn1crypto",
"h5py",
- "bokeh"
+ "holoviews",
+ "bokeh",
+ "matplotlib",
+ "datashader",
+ "xarray"
],
extras_require={
"picoscope_sdk": ["picosdk"],
diff --git a/test/sca/test_plot.py b/test/sca/test_plot.py
index d004cf5..9158e5c 100644
--- a/test/sca/test_plot.py
+++ b/test/sca/test_plot.py
@@ -1,29 +1,38 @@
from os import getenv
import numpy as np
-
+import holoviews as hv
from pyecsca.sca.trace import Trace
-from pyecsca.sca.trace.plot import (new_figure, plot_trace, save_figure, save_figure_png,
- save_figure_svg)
-from .utils import Plottable, disabled
+from pyecsca.sca.trace.plot import (plot_trace, save_figure, save_figure_png, save_figure_svg,
+ plot_traces)
+from .utils import Plottable
class PlotTests(Plottable):
def setUp(self) -> None:
- self.trace = Trace(np.array([6, 7, 3, -2, 5, 1], dtype=np.dtype("i1")), None, None)
- self.fig = new_figure()
- plot_trace(self.fig, self.trace)
+ self.trace1 = Trace(np.array([6, 7, 3, -2, 5, 1], dtype=np.dtype("i1")), None, None)
+ self.trace2 = Trace(np.array([2, 3, 7, 0, -1, 0], dtype=np.dtype("i1")), None, None)
def test_html(self):
if getenv("PYECSCA_TEST_PLOTS") is None:
return
- save_figure(self.fig, self.get_fname() + ".html", "Trace plot")
+ hv.extension("bokeh")
+ fig = plot_trace(self.trace1)
+ save_figure(fig, self.get_fname())
+ other = plot_traces(self.trace1, self.trace2)
+ save_figure(other, self.get_fname())
- @disabled
def test_png(self):
- save_figure_png(self.fig, self.get_fname() + ".png", 1000, 400)
+ if getenv("PYECSCA_TEST_PLOTS") is None:
+ return
+ hv.extension("matplotlib")
+ fig = plot_trace(self.trace1)
+ save_figure_png(fig, self.get_fname())
- @disabled
def test_svg(self):
- save_figure_svg(self.fig, self.get_fname() + ".svg")
+ if getenv("PYECSCA_TEST_PLOTS") is None:
+ return
+ hv.extension("matplotlib")
+ fig = plot_trace(self.trace1)
+ save_figure_svg(fig, self.get_fname())