Commit 3a000150 authored by Samuel GAIST's avatar Samuel GAIST

[test][prefix][plotters] Add one new version of the scatter plotter

It will be useful for testing beat/beat.editor> v2
parent 18001f8f
{
"dataformat": "plot/scatter/1",
"language": "python",
"parameters": {
"xlabel": {
"default": "X",
"type": "string",
"description": "The label of the X-axis (horizontal)"
},
"ylabel": {
"default": "Y",
"type": "string",
"description": "The label of the Y-axis (vertical)"
},
"title": {
"default": "Scatter plot",
"type": "string",
"description": "The title for this plot"
},
"xaxis_multiplier": {
"default": 1.0,
"type": "float64",
"description": "The multiplication factor for the X-axis (horizontal)"
},
"yaxis_multiplier": {
"default": 1.0,
"type": "float64",
"description": "The multiplication factor for the Y-axis (vertical)"
},
"line_attributes": {
"default": "",
"type": "string",
"description": "Scatter/Line attributes passed directly to Matplotlib"
},
"legend": {
"default": "",
"type": "string",
"description": "Short description of the data, to be added to the plot"
},
"grid": {
"default": false,
"type": "bool",
"description": "If we should draw grid lines or not for the plot"
},
"xaxis_log": {
"default": false,
"type": "bool",
"description": "If X-axis (horizontal) should be in log-scale"
},
"yaxis_log": {
"default": false,
"type": "bool",
"description": "If Y-axis (vertical) should be in log-scale"
},
"mimetype": {
"default": "image/png",
"description": "The type of image returned",
"type": "string",
"choice": [
"image/png",
"image/jpeg",
"application/pdf"
]
}
}
}
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
###################################################################################
# #
# Copyright (c) 2019 Idiap Research Institute, http://www.idiap.ch/ #
# Contact: beat.support@idiap.ch #
# #
# Redistribution and use in source and binary forms, with or without #
# modification, are permitted provided that the following conditions are met: #
# #
# 1. Redistributions of source code must retain the above copyright notice, this #
# list of conditions and the following disclaimer. #
# #
# 2. Redistributions in binary form must reproduce the above copyright notice, #
# this list of conditions and the following disclaimer in the documentation #
# and/or other materials provided with the distribution. #
# #
# 3. Neither the name of the copyright holder nor the names of its contributors #
# may be used to endorse or promote products derived from this software without #
# specific prior written permission. #
# #
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND #
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED #
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE #
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE #
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL #
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR #
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER #
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, #
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE #
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #
# #
###################################################################################
import six
import numpy
import itertools
# Make sure we won't require an X11 connection
import matplotlib
matplotlib.use("Agg") # noqa need to happen before further imports
from matplotlib.figure import Figure
import matplotlib.pyplot as pyplot
class Plotter:
def setup(self, parameters):
self.xlabel = parameters["xlabel"]
self.xaxis_multiplier = parameters["xaxis_multiplier"]
self.xaxis_log = parameters["xaxis_log"]
self.ylabel = parameters["ylabel"]
self.yaxis_multiplier = parameters["yaxis_multiplier"]
self.yaxis_log = parameters["yaxis_log"]
self.title = parameters["title"]
self.line_attributes = parameters["line_attributes"]
self.legend = parameters["legend"]
self.grid = parameters["grid"]
self.mimetype = parameters["mimetype"]
return True
def process(self, inputs):
# Creates the image to return
fig = Figure()
ax = fig.add_subplot(111)
if not isinstance(inputs, (list, tuple)):
inputs = [inputs]
self.legend = self.legend.split("&")
if isinstance(self.legend, str):
self.legend = [self.legend]
self.line_attributes = self.line_attributes.split("&")
if isinstance(self.line_attributes, str):
self.line_attributes = [self.line_attributes]
try:
Z = itertools.izip
except AttributeError:
Z = zip
C = itertools.cycle
for input, attributes, label in Z(
inputs, C(self.line_attributes), C(self.legend)
):
# Massages the input data
final_data = numpy.array([(k.x, k.y) for k in input.data])
x = final_data[:, 0]
y = final_data[:, 1]
x *= self.xaxis_multiplier
y *= self.yaxis_multiplier
args = (x, y)
if attributes:
args = args + (attributes,)
kwargs = {}
if label:
kwargs["label"] = label
# Plots
ax.plot(*args, **kwargs)
# Sets plot attributes
ax.set_xlabel(self.xlabel)
ax.set_ylabel(self.ylabel)
ax.set_title(self.title)
ax.grid(self.grid)
if self.xaxis_log:
ax.set_xscale("log")
if self.yaxis_log:
ax.set_yscale("log")
if any(self.legend):
ax.legend()
# Returns the image
if six.PY2:
sio = six.StringIO()
else:
sio = six.BytesIO()
if self.mimetype == "image/png":
pyplot.savefig(sio, format="png")
elif self.mimetype == "image/jpeg":
pyplot.savefig(sio, format="jpeg")
elif self.mimetype == "application/pdf":
from matplotlib.backends.backend_pdf import FigureCanvasPdf
canvas = FigureCanvasPdf(fig)
canvas.print_figure(sio)
return sio.getvalue()
......@@ -44,20 +44,23 @@ from . import prefix
def test_default():
p = Plotter(prefix, data=None)
nose.tools.assert_false(p.valid)
def test_scatter():
for i in range(1, 3):
yield scatter, f"user/scatter/{i}"
p = Plotter(prefix, "user/scatter/1")
def scatter(plotter_name):
p = Plotter(prefix, plotter_name)
nose.tools.assert_true(p.valid, "\n * %s" % "\n * ".join(p.errors))
def do_plot(mimetype):
def do_plot(mimetype, plotter_name):
p = Plotter(prefix, "user/scatter/1")
p = Plotter(prefix, plotter_name)
nose.tools.assert_true(p.valid)
runnable = p.runner()
......@@ -94,27 +97,34 @@ def do_plot(mimetype):
return runnable.process(data)
def test_plot_png():
fig = do_plot("image/png")
nose.tools.eq_(imghdr.what("test.png", fig), "png")
# with open('test.png', 'wb') as f: f.write(fig)
def test_plot_image():
for i in range(1, 3):
for image_type in ["png", "jpeg"]:
yield plot_image, f"user/scatter/{i}", image_type
def test_plot_jpeg():
fig = do_plot("image/jpeg")
nose.tools.eq_(imghdr.what("test.jpg", fig), "jpeg")
# with open('test.jpg', 'wb') as f: f.write(fig)
def plot_image(plotter_name, image_type):
fig = do_plot(f"image/{image_type}", plotter_name)
nose.tools.eq_(imghdr.what(f"test.{image_type}", fig), image_type)
def test_plot_pdf():
fig = do_plot("application/pdf")
for i in range(1, 3):
yield plot_pdf, f"user/scatter/{i}"
def plot_pdf(plotter_name):
fig = do_plot("application/pdf", plotter_name)
nose.tools.assert_true(fig.startswith(b"%PDF"))
# with open('test.pdf', 'wb') as f: f.write(fig)
def test_plot_many_lines():
for i in range(1, 3):
yield plot_many_lines, f"user/scatter/{i}"
p = Plotter(prefix, "user/scatter/1")
def plot_many_lines(plotter_name):
p = Plotter(prefix, plotter_name)
nose.tools.assert_true(p.valid)
data1 = p.dataformat.type(
......@@ -166,4 +176,3 @@ def test_plot_many_lines():
fig = runnable.process([data1, data2])
nose.tools.eq_(imghdr.what("test.png", fig), "png")
# with open('test2.png', 'wb') as f: f.write(fig)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment