Commit f276f395 authored by Theophile GENTILHOMME's avatar Theophile GENTILHOMME
Browse files

Add legend options, small changes utils function and doc

parent a2640f7d
......@@ -10,6 +10,8 @@ from . import figure
@common_options.scores_argument(min_arg=2, force_eval=True, nargs=-1)
@common_options.output_plot_file_option(default_out='det.pdf')
@common_options.legends_option()
@common_options.no_legend_option()
@common_options.legend_loc_option(dflt='upper-right')
@common_options.title_option()
@common_options.const_layout_option()
@common_options.style_option()
......@@ -18,7 +20,7 @@ from . import figure
'no-spoof', 'ns', '', False
)
@verbosity_option()
@common_options.axes_val_option(dflt=[0.01, 95, 0.01, 95])
@common_options.axes_val_option(dflt='0.01,95,0.01,95')
@common_options.x_rotation_option(dflt=45)
@common_options.x_label_option()
@common_options.y_label_option()
......
......@@ -10,6 +10,8 @@ from . import figure
@common_options.scores_argument(min_arg=2, force_eval=True, nargs=-1)
@common_options.output_plot_file_option(default_out='epc.pdf')
@common_options.legends_option()
@common_options.no_legend_option()
@common_options.legend_loc_option()
@common_options.title_option()
@common_options.const_layout_option()
@common_options.x_label_option()
......@@ -51,6 +53,8 @@ def epc(ctx, scores, **kwargs):
@common_options.scores_argument(min_arg=2, force_eval=True, nargs=-1)
@common_options.output_plot_file_option(default_out='epsc.pdf')
@common_options.legends_option()
@common_options.no_legend_option()
@common_options.legend_loc_option()
@common_options.const_layout_option()
@common_options.x_label_option()
@common_options.y_label_option()
......
......@@ -13,12 +13,20 @@ import argparse
def calc_pass_rate(threshold, attacks):
"""Calculates the rate of successful spoofing attacks
Keyword parameters:
Parameters
----------
threshold :
the threshold used for classification
scores :
numpy with the scores of the spoofing attacks
Returns
-------
float
rate of successful spoofing attacks
"""
return (attacks >= threshold).mean()
- threshold - the threshold used for classification
- attack: numpy with the scores of the spoofing attacks
"""
return sum(1 for i in attacks if i >= threshold) / float(attacks.size)
def weighted_neg_error_rate_criteria(data,
weight,
......@@ -298,30 +306,32 @@ def epsc_error_rates(licit_neg, licit_pos, spoof_neg, spoof_pos, thresholds,
(omega and beta) and thresholds (the thresholds need to be computed first
using the method: epsc_thresholds() before passing to this method)
Keyword arguments:
- licit_neg - numpy.array of scores for the negatives (licit scenario)
- licit_pos - numpy.array of scores for the positives (licit scenario)
- spoof_neg - numpy.array of scores for the negatives (spoof scenario)
- spoof_pos - numpy.array of scores for the positives (spoof scenario)
- thresholds - numpy.ndarray with threshold values
- omega - numpy.array of the omega parameter balancing between impostors
and spoofing attacks
- beta - numpy.array of the beta parameter balancing between real accesses
and all negatives (impostors and spoofing attacks)
"""
if not isinstance(omega, list) and not isinstance(
omega, tuple) and not isinstance(omega, numpy.ndarray):
omega = numpy.array([omega])
else:
omega = numpy.array(omega)
if not isinstance(beta, list) and not isinstance(
beta, tuple) and not isinstance(beta, numpy.ndarray):
beta = numpy.array([beta])
else:
beta = numpy.array(beta)
Parameters
----------
licit_neg : array_like
array of scores for the negatives (licit scenario)
licit_pos : array_like
array of scores for the positives (licit scenario)
spoof_neg : array_like
array of scores for the negatives (spoof scenario)
spoof_pos : array_like
array of scores for the positives (spoof scenario)
thresholds : array_like
ndarray with threshold values
omega : array_like
array of the omega parameter balancing between impostors
and spoofing attacks
beta : array_like
array of the beta parameter balancing between real accesses
and all negatives (impostors and spoofing attacks)
Returns
-------
far_w_errors: array_like
FAR_w
wer_wb_errors: array_like
WER_wb
"""
far_w_errors = numpy.ndarray((beta.size, omega.size), 'float64')
wer_wb_errors = numpy.ndarray((beta.size, omega.size), 'float64')
......@@ -340,34 +350,36 @@ def epsc_error_rates(licit_neg, licit_pos, spoof_neg, spoof_pos, thresholds,
def all_error_rates(licit_neg, licit_pos, spoof_neg, spoof_pos, thresholds,
omega, beta):
"""Calculates several error rates: FAR_w and HTER_w for the given weights
(omega and beta) and thresholds (the thresholds need to be computed first
"""Calculates several error rates: FAR_w and WER_wb for the given weights
(omega and beta) and thresholds (the thresholds need to be computed first
using the method: epsc_thresholds() before passing to this method)
Keyword arguments:
- licit_neg - numpy.array of scores for the negatives (licit scenario)
- licit_pos - numpy.array of scores for the positives (licit scenario)
- spoof_neg - numpy.array of scores for the negatives (spoof scenario)
- spoof_pos - numpy.array of scores for the positives (spoof scenario)
- thresholds - numpy.array with threshold values
- omega - numpy.array of the omega parameter balancing between impostors
and spoofing attacks
- beta - numpy.array of the beta parameter balancing between real accesses
and all negatives (impostors and spoofing attacks)
"""
if not isinstance(omega, list) and not isinstance(
omega, tuple) and not isinstance(omega, numpy.ndarray):
omega = numpy.array([omega])
else:
omega = numpy.array(omega)
if not isinstance(beta, list) and not isinstance(
beta, tuple) and not isinstance(beta, numpy.ndarray):
beta = numpy.array([beta])
else:
beta = numpy.array(beta)
Parameters
----------
licit_neg : array_like
array of scores for the negatives (licit scenario)
licit_pos : array_like
array of scores for the positives (licit scenario)
spoof_neg : array_like
array of scores for the negatives (spoof scenario)
spoof_pos : array_like
array of scores for the positives (spoof scenario)
thresholds : array_like
ndarray with threshold values
omega : array_like
array of the omega parameter balancing between impostors
and spoofing attacks
beta : array_like
array of the beta parameter balancing between real accesses
and all negatives (impostors and spoofing attacks)
Returns
-------
far_w_errors: array_like
FAR_w
wer_wb_errors: array_like
WER_wb
"""
frr_errors = numpy.ndarray((beta.size, omega.size), 'float64')
far_errors = numpy.ndarray((beta.size, omega.size), 'float64')
......
......@@ -17,6 +17,7 @@ from . import error_utils
ALL_CRITERIA = ('bpcer20', 'eer', 'min-hter')
def calc_threshold(method, neg, pos):
"""Calculates the threshold based on the given method.
The scores should be sorted!
......@@ -52,6 +53,7 @@ def calc_threshold(method, neg, pos):
return threshold
class Metrics(measure_figure.Metrics):
def __init__(self, ctx, scores, evaluation, func_load):
super(Metrics, self).__init__(ctx, scores, evaluation, func_load)
......@@ -90,6 +92,7 @@ class Metrics(measure_figure.Metrics):
file=self.log_file
)
class HistPad(measure_figure.Hist):
''' Histograms for PAD '''
......@@ -103,8 +106,6 @@ class HistPad(measure_figure.Hist):
hatch='\\\\'
)
def _calc_pass_rate(threshold, scores):
return (scores >= threshold).mean()
def _iapmr_dot(threshold, iapmr, real_data, **kwargs):
# plot a dot on threshold versus IAPMR line and show IAPMR as a number
......@@ -127,20 +128,23 @@ def _iapmr_dot(threshold, iapmr, real_data, **kwargs):
mpl.text(threshold + (threshold - axlim[0]) / 12, 100. * iapmr,
'%.1f%%' % (100. * iapmr,), color='C3')
def _iapmr_line_plot(scores, n_points=100, **kwargs):
axlim = mpl.axis()
step = (axlim[1] - axlim[0]) / float(n_points)
thres = [(k * step) + axlim[0] for k in range(2, n_points - 1)]
mix_prob_y = []
for k in thres:
mix_prob_y.append(100. * _calc_pass_rate(k, scores))
mix_prob_y.append(100. * error_utils.calc_pass_rate(k, scores))
mpl.plot(thres, mix_prob_y, label='IAPMR', color='C3', **kwargs)
def _iapmr_plot(scores, threshold, iapmr, real_data, **kwargs):
_iapmr_dot(threshold, iapmr, real_data, **kwargs)
_iapmr_line_plot(scores, n_points=100, **kwargs)
class HistVuln(measure_figure.Hist):
''' Histograms for vulnerability '''
......@@ -169,15 +173,7 @@ class HistVuln(measure_figure.Hist):
ax2.grid(False)
real_data = True if 'real_data' not in self._ctx.meta else \
self._ctx.meta['real_data']
far, frr = farfrr(neg[0], pos[0], threshold)
_iapmr_plot(neg[1], threshold, iapmr, real_data=real_data)
click.echo(
'%s (t=%.2g) = %.2f%%; IAPMR = %.2f%%' % (
self._criterion.upper(),
threshold,
50*(far+frr), 100*iapmr
)
)
n = idx % self._step_print
col = n % self._ncols
rest_print = self.n_systems - int(idx / self._step_print) * self._step_print
......@@ -187,6 +183,7 @@ class HistVuln(measure_figure.Hist):
ax2.yaxis.label.set_color('red')
ax2.spines['right'].set_color('red')
class PadPlot(measure_figure.PlotBase):
'''Base class for PAD plots'''
def __init__(self, ctx, scores, evaluation, func_load):
......@@ -208,7 +205,10 @@ class PadPlot(measure_figure.PlotBase):
li, la = ax.get_legend_handles_labels()
lines += li
labels += la
mpl.gca().legend(lines, labels, loc=0, fancybox=True, framealpha=0.5)
if self._disp_legend:
mpl.gca().legend(lines, labels, loc=self._legend_loc,
fancybox=True, framealpha=0.5)
class Epc(PadPlot):
''' Handles the plotting of EPC '''
......@@ -277,12 +277,14 @@ class Epc(PadPlot):
prob_ax.yaxis.set_ticklabels(["%.0f" % val for val in ylabels])
prob_ax.set_axisbelow(True)
title = self._legends[idx] if self._legends is not None else self._title
mpl.title(title)
if title.replace(' ', ''):
mpl.title(title)
#legends for all axes
self._plot_legends()
mpl.xticks(rotation=self._x_rotation)
self._pdf_page.savefig(mpl.gcf())
class Epsc(PadPlot):
''' Handles the plotting of EPSC '''
def __init__(self, ctx, scores, evaluation, func_load,
......@@ -397,11 +399,13 @@ class Epsc(PadPlot):
axis.spines['right'].set_color('red')
if self._var_param == 'omega':
mpl.title(title or (r"EPSC with $\beta$ = %.2f" %\
self._fixed_param))
if title.replace(' ', ''):
mpl.title(title or (r"EPSC with $\beta$ = %.2f" %\
self._fixed_param))
else:
mpl.title(title or (r"EPSC with $\omega$ = %.2f" %\
self._fixed_param))
if title.replace(' ', ''):
mpl.title(title or (r"EPSC with $\omega$ = %.2f" %\
self._fixed_param))
mpl.grid()
self._plot_legends()
......@@ -410,6 +414,7 @@ class Epsc(PadPlot):
mpl.xticks(rotation=self._x_rotation)
self._pdf_page.savefig()
class Epsc3D(Epsc):
''' 3D EPSC plots for PAD'''
def compute(self, idx, input_scores, input_names):
......@@ -469,7 +474,8 @@ class Epsc3D(Epsc):
r"WER$_{\omega,\beta}$ (%)" if self._wer else "IAPMR (%)"
)
mpl.title(title or "3D EPSC")
if title.replace(' ', ''):
mpl.title(title or "3D EPSC")
ax1.set_xticklabels(ax1.get_xticks())
ax1.set_yticklabels(ax1.get_yticks())
......@@ -477,6 +483,7 @@ class Epsc3D(Epsc):
self._pdf_page.savefig()
class Det(PadPlot):
'''DET for PAD'''
def __init__(self, ctx, scores, evaluation, func_load, criteria, real_data):
......@@ -617,11 +624,13 @@ class Det(PadPlot):
add = " and overlaid SPOOF scenario"
title = self._title if self._title is not None else \
('DET: LICIT' + add)
mpl.title(title)
if title.replace(' ', ''):
mpl.title(title)
mpl.xlabel(self._x_label or "False Acceptance Rate (%)")
mpl.ylabel(self._y_label or "False Rejection Rate (%)")
mpl.grid(True, color=self._grid_color)
mpl.legend(loc='best')
if self._disp_legend:
mpl.legend(loc=self._legend_loc)
self._set_axis()
fig = mpl.gcf()
mpl.xticks(rotation=self._x_rotation)
......@@ -644,6 +653,7 @@ class Det(PadPlot):
else:
det_axis([0.01, 99, 0.01, 99])
class FmrIapmr(PadPlot):
'''FMR vs IAPMR'''
def __init__(self, ctx, scores, evaluation, func_load):
......@@ -682,11 +692,13 @@ class FmrIapmr(PadPlot):
close pdf is needed '''
#only for plots
title = self._title if self._title is not None else "FMR vs IAPMR"
mpl.title(title)
if title.replace(' ', ''):
mpl.title(title)
mpl.xlabel(self._x_label or "False Match Rate (%)")
mpl.ylabel(self._y_label or "IAPMR (%)")
mpl.grid(True, color=self._grid_color)
mpl.legend(loc='best')
if self._disp_legend:
mpl.legend(loc=self._legend_loc)
self._set_axis()
fig = mpl.gcf()
mpl.xticks(rotation=self._x_rotation)
......
......@@ -10,6 +10,8 @@ from . import figure
@common_options.scores_argument(min_arg=2, force_eval=True, nargs=-1)
@common_options.output_plot_file_option(default_out='fmr_iapmr.pdf')
@common_options.legends_option()
@common_options.no_legend_option()
@common_options.legend_loc_option()
@common_options.title_option()
@common_options.const_layout_option()
@common_options.style_option()
......
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