ROC/DET plotter following the ISO/IEC 19795-1:2006(E) standard

Parameters allow users to change the configuration of an plotter when scheduling an experiment

Name Description Type Default
xlabel The label of the X-axis (horizontal) string False Positives (False Match Rate), in %
ylabel The label of the Y-axis (vertical) string True Positives (1 - False Non-Match Rate), in %
xlim-left float64 0.0
xlim-right float64 100.0
ylim-bottom float64 0.0
ylim-top float64 100.0
title The title for this plot string ISO/IEC 19795-1:2006(E) ROC
title-fontsize Controls the title font size uint16 10
xaxis_multiplier The multiplication factor for the X-axis (horizontal) float64 100.0
yaxis_multiplier The multiplication factor for the Y-axis (vertical) float64 100.0
axis-fontsize Controls the axis font size (labels and values) uint16 10
legend Short description of the data, to be added to the plot string
legend-fontsize Controls the font size of the legend uint16 12
legend-loc The location of the legend string best
grid If we should draw grid lines or not for the plot bool True
xaxis_log If X-axis (horizontal) should be in log-scale bool False
yaxis_log If Y-axis (vertical) should be in log-scale bool False
dpi Dots-per-inch in raster image formats uint16 60
width Width of the resulting image in pixels uint16 400
height Height of the resulting image in pixels uint16 300
content_type The type of image returned string image/png
line_attributes Scatter/Line attributes passed directly to Matplotlib string
det If set, plot a DET curve instead of a ROC bool False
xxxxxxxxxx
143
 
1
###############################################################################
2
#                                                                             #
3
# Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/           #
4
# Contact: beat.support@idiap.ch                                              #
5
#                                                                             #
6
# This file is part of the beat.examples module of the BEAT platform.         #
7
#                                                                             #
8
# Commercial License Usage                                                    #
9
# Licensees holding valid commercial BEAT licenses may use this file in       #
10
# accordance with the terms contained in a written agreement between you      #
11
# and Idiap. For further information contact tto@idiap.ch                     #
12
#                                                                             #
13
# Alternatively, this file may be used under the terms of the GNU Affero      #
14
# Public License version 3 as published by the Free Software and appearing    #
15
# in the file LICENSE.AGPL included in the packaging of this file.            #
16
# The BEAT platform is distributed in the hope that it will be useful, but    #
17
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY  #
18
# or FITNESS FOR A PARTICULAR PURPOSE.                                        #
19
#                                                                             #
20
# You should have received a copy of the GNU Affero Public License along      #
21
# with the BEAT platform. If not, see http://www.gnu.org/licenses/.           #
22
#                                                                             #
23
###############################################################################
24
25
# Makes sure we won't require an X11 connection
26
import matplotlib
27
matplotlib.use('Agg')
28
29
import numpy
30
import itertools
31
32
33
class Plotter(baselib.Plotter):
34
35
    def setup(self, parameters):
36
37
        super(Plotter, self).setup(parameters)
38
        self.line_attributes = parameters.get('line_attributes', '').split('&')
39
        self.loc = parameters.get('legend-loc', '')
40
41
        self.title_fontsize    = parameters.get('title-fontsize', '')
42
43
        self.xlim_left   = parameters.get('xlim-left', '')
44
        self.xlim_right  = parameters.get('xlim-right', '')
45
        self.ylim_bottom = parameters.get('ylim-bottom', '')
46
        self.ylim_top    = parameters.get('ylim-top', '')
47
48
        self.axis_fontsize    = parameters.get('axis-fontsize', '')
49
50
51
        self.legend_fontsize = parameters.get('legend-fontsize', '')
52
        self.line_attributes = [k for k in self.line_attributes if k]
53
        self.det = parameters.get('det', False)
54
55
        if self.det:
56
            self.ylabel = "False Negatives (False Non-Match Rate), in %"
57
58
        # These are the "Tableau 20" colors as RGB.
59
        self.tableau20 = [(31,119,180), (152,223,138), (140,86,75), (199,199,199), 
60
                          (174,199,232), (214,39,40), (196,156,148), (188,189,34), 
61
                          (255,127,14), (255,152,150), (227,119,194), (219,219,141), 
62
                          (255,187,120), (148,103,189), (247,182,210), (23,190,207), 
63
                          (44,160,44), (197,176,213), (127,127,127), (158,218,229)]
64
        # Scale the RGB values to the [0, 1] range, which is the format matplotlib accepts.
65
        for i in range(len(self.tableau20)):
66
            r, g, b = self.tableau20[i]
67
            self.tableau20[i] = (r / 255., g / 255., b / 255.)
68
69
70
        return True
71
72
73
    def process(self, inputs):
74
        fig, ax = super(Plotter, self).prepare_canvas()
75
        super(Plotter, self).apply_parameters(ax)
76
77
        ax.set_title(self.title, fontdict={'fontsize':self.title_fontsize})
78
79
        ax.set_xlabel(self.xlabel, fontdict={'fontsize':self.axis_fontsize})
80
        ax.set_ylabel(self.ylabel, fontdict={'fontsize':self.axis_fontsize})
81
82
        ax.set_xlim((self.xlim_left,self.xlim_right))
83
        ax.set_ylim((self.ylim_bottom,self.ylim_top))
84
85
        label = ""
86
        kwargs = {}
87
        single_experiment = len(inputs) == 1
88
89
        number_of_positives = []
90
        number_of_negatives = []
91
        n_lines = 0
92
93
        for xp_label, xp_data in inputs:
94
            for scatter in xp_data.data:
95
                args = []
96
                # the data
97
                x = scatter.false_positives
98
                if self.det:
99
                    y = scatter.false_negatives
100
                else:
101
                    y = 1.0 - scatter.false_negatives
102
103
                # accumulate counts (useful in log plots)
104
                number_of_positives.append(scatter.number_of_positives)
105
                number_of_negatives.append(scatter.number_of_negatives)
106
107
                args.append(x * self.xaxis_multiplier)
108
                args.append(y * self.yaxis_multiplier)
109
110
                # the label
111
                if self.label: #gets the label from user overwritten input
112
                    label = self.label[n_lines%len(self.label)]
113
                else: #make-up label
114
                    if single_experiment:
115
                        label = scatter.label
116
                    else:
117
                        text = [k for k in (xp_label, scatter.label) if k]
118
                        label = '-'.join(text)
119
120
                # the line attributes
121
                if self.line_attributes:
122
                    args.append(self.line_attributes[n_lines%len(self.line_attributes)])
123
                else:
124
                    kwargs['color'] = self.tableau20[n_lines % len(self.tableau20)]
125
                    
126
                kwargs['label'] = label
127
                n_lines += 1
128
                
129
                ax.plot(*args, **kwargs)
130
                
131
        if n_lines > 1:
132
            ax.legend(loc=self.loc, fontsize=self.legend_fontsize, fancybox=True, framealpha=0.5)
133
134
135
        # reset log axis
136
        if self.xaxis_log:
137
            N = min([k for k in number_of_positives if k > 0]) or 100
138
            ax.set_xscale('symlog', linthreshx=1.0/N)
139
        if self.yaxis_log:
140
            N = min([k for k in number_of_negatives if k > 0]) or 100
141
            ax.set_yscale('symlog', linthreshy=1.0/N)
142
143
        return super(Plotter, self).encode_figure(fig)

This is a plotter for ISO/IEC 19795-1:2006(E) standard ROC and DET curves. It is based on the description on the standard, section 10.6 "Graphical presentation of results", pages 35 and 36.

Reports

Created with Raphaël 2.1.2[compare]plot/isoroc/12015May5
Terms of Service | Contact Information | BEAT platform version 2.2.1b0 | © Idiap Research Institute - 2013-2025