Skip to content
Snippets Groups Projects
Commit e0a0db5e authored by Theophile GENTILHOMME's avatar Theophile GENTILHOMME
Browse files

Add fmr vs IAPMR plot

parent d7eaabda
No related branches found
No related tags found
2 merge requests!42Set of click commands for pad,!41Set of click commands for pad
Pipeline #
......@@ -219,7 +219,6 @@ class Epc(PadPlot):
self._eval = True #always eval data with EPC
self._split = False
self._nb_figs = 1
self._title = ''
if self._min_arg != 4:
raise click.BadParameter("You must provide 4 scores files:{licit,"
......@@ -620,7 +619,6 @@ class Det(PadPlot):
mpl.grid(True, color=self._grid_color)
mpl.legend(loc='best')
self._set_axis()
#gives warning when applied with mpl
fig = mpl.gcf()
mpl.xticks(rotation=self._x_rotation)
mpl.tick_params(axis='both', which='major', labelsize=4)
......@@ -641,3 +639,58 @@ class Det(PadPlot):
det_axis(self._axlim)
else:
det_axis([0.01, 99, 0.01, 99])
class FmrIapmr(PadPlot):
'''FMR vs IAPMR'''
def __init__(self, ctx, scores, evaluation, func_load):
super(FmrIapmr, self).__init__(ctx, scores, evaluation, func_load)
self._eval = True #always eval data with EPC
self._split = False
self._nb_figs = 1
self._semilogx = False if 'semilogx' not in ctx.meta else\
ctx.meta['semilogx']
if self._min_arg != 4:
raise click.BadParameter("You must provide 4 scores files:{licit,"
"spoof}/{dev,eval}")
def compute(self, idx, input_scores, input_names):
''' Implements plots'''
licit_eval_neg = input_scores[1][0]
licit_eval_pos = input_scores[1][1]
spoof_eval_neg = input_scores[3][0]
fmr_list = np.linspace(0, 1, 100)
iapmr_list = []
for i, fmr in enumerate(fmr_list):
thr = far_threshold(licit_eval_neg, licit_eval_pos, fmr, True)
iapmr_list.append(farfrr(spoof_eval_neg, licit_eval_pos, thr)[0])
# re-calculate fmr since threshold might give a different result
# for fmr.
fmr_list[i] = farfrr(licit_eval_neg, licit_eval_pos, thr)[0]
label = self._titles[idx] if self._titles is not None else \
'(%s/%s)' % (input_names[1], input_names[3])
if self._semilogx:
mpl.semilogx(fmr_list, iapmr_list, label=label)
else:
mpl.plot(fmr_list, iapmr_list, label=label)
def end_process(self):
''' Set title, legend, axis labels, grid colors, save figures and
close pdf is needed '''
#only for plots
title = self._title if self._title is not None else "FMR vs IAPMR"
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')
self._set_axis()
fig = mpl.gcf()
mpl.xticks(rotation=self._x_rotation)
mpl.tick_params(axis='both', which='major', labelsize=4)
self._pdf_page.savefig(fig)
#do not want to close PDF when running evaluate
if 'PdfPages' in self._ctx.meta and \
('closef' not in self._ctx.meta or self._ctx.meta['closef']):
self._pdf_page.close()
"""Generates PAD ISO compliant FMR vs IAPMR plots based on the score files
"""
import click
from bob.measure.script import common_options
from bob.extension.scripts.click_helper import verbosity_option
from bob.bio.base.score import load
from . import figure
@click.command()
@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.titles_option()
@common_options.const_layout_option()
@common_options.style_option()
@common_options.figsize_option()
@verbosity_option()
@common_options.axes_val_option()
@common_options.x_rotation_option()
@common_options.x_label_option()
@common_options.y_label_option()
@common_options.semilogx_option()
@click.pass_context
def fmr_iapmr(ctx, scores, **kwargs):
"""Plot FMR vs IAPMR
You need to provide 2 or 4 scores
files for each PAD system in this order:
\b
* licit development scores
* licit evaluation scores
* spoof development scores (when ``--no-spoof`` is False (default))
* spoof evaluation scores (when ``--no-spoof`` is False (default))
Examples:
$ bob pad fmr_iapmr --no-spoof dev-scores eval-scores
$ bob pad fmr_iapmr {licit,spoof}/scores-{dev,eval}
"""
process = figure.FmrIapmr(ctx, scores, True, load.split)
process.run()
......@@ -2,7 +2,7 @@ import sys
import click
from click.testing import CliRunner
import pkg_resources
from ..script import (metrics, histograms, epc, det)
from ..script import (metrics, histograms, epc, det, fmr_iapmr)
def test_det():
......@@ -23,6 +23,30 @@ def test_det():
spoof_dev, spoof_test])
assert result.exit_code == 0, (result.exit_code, result.output)
def test_fmr_iapmr():
licit_dev = pkg_resources.resource_filename('bob.pad.base.test',
'data/licit/scores-dev')
licit_test = pkg_resources.resource_filename('bob.pad.base.test',
'data/licit/scores-eval')
spoof_dev = pkg_resources.resource_filename('bob.pad.base.test',
'data/spoof/scores-dev')
spoof_test = pkg_resources.resource_filename('bob.pad.base.test',
'data/spoof/scores-eval')
runner = CliRunner()
with runner.isolated_filesystem():
result = runner.invoke(fmr_iapmr.fmr_iapmr, [
'--output', 'FMRIAPMR.pdf', licit_dev, licit_test, spoof_dev,
spoof_test
])
assert result.exit_code == 0, (result.exit_code, result.output)
result = runner.invoke(fmr_iapmr.fmr_iapmr, [
'--output', 'FMRIAPMR.pdf', licit_dev, licit_test, spoof_dev,
spoof_test, '-G', '-L', '1e-7,1,0,1'
])
assert result.exit_code == 0, (result.exit_code, result.output)
def test_hist():
licit_dev = pkg_resources.resource_filename('bob.pad.base.test',
'data/licit/scores-dev')
......
......@@ -146,6 +146,7 @@ setup(
'epc = bob.pad.base.script.epc:epc',
'epsc = bob.pad.base.script.epc:epsc',
'gen = bob.pad.base.script.gen:gen',
'fmr_iapmr = bob.pad.base.script.fmr_iapmr:fmr_iapmr',
],
},
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment