From 1358cfabc9a4542ab978250eff5183e214c99ca8 Mon Sep 17 00:00:00 2001 From: Theophile GENTILHOMME <tgentilhomme@jurasix08.idiap.ch> Date: Mon, 23 Apr 2018 09:27:42 +0200 Subject: [PATCH] Modify code according to the changes in bob.measure --- bob/pad/base/script/det.py | 6 +- bob/pad/base/script/epc.py | 12 +-- bob/pad/base/script/figure.py | 150 ++++++++++++------------------ bob/pad/base/script/histograms.py | 8 +- bob/pad/base/script/metrics.py | 4 +- 5 files changed, 71 insertions(+), 109 deletions(-) diff --git a/bob/pad/base/script/det.py b/bob/pad/base/script/det.py index 0992ba9..35e626f 100644 --- a/bob/pad/base/script/det.py +++ b/bob/pad/base/script/det.py @@ -6,10 +6,8 @@ from bob.extension.scripts.click_helper import verbosity_option from bob.bio.base.score import load from . import figure -FUNC_SPLIT = lambda x: load.load_files(x, load.split) - @click.command() -@common_options.scores_argument(eval_mandatory=True, min_len=2, nargs=-1) +@common_options.scores_argument(min_arg=2, force_eval=True, nargs=-1) @common_options.output_plot_file_option(default_out='det.pdf') @common_options.titles_option() @common_options.const_layout_option() @@ -48,5 +46,5 @@ def det(ctx, scores, criteria, real_data, **kwargs): $ bob pad det {licit,spoof}/scores-{dev,eval} """ - process = figure.Det(ctx, scores, True, FUNC_SPLIT, criteria, real_data) + process = figure.Det(ctx, scores, True, load.split, criteria, real_data) process.run() diff --git a/bob/pad/base/script/epc.py b/bob/pad/base/script/epc.py index 1f341dd..10b89f1 100644 --- a/bob/pad/base/script/epc.py +++ b/bob/pad/base/script/epc.py @@ -6,10 +6,8 @@ from bob.extension.scripts.click_helper import verbosity_option from bob.bio.base.score import load from . import figure -FUNC_SPLIT = lambda x: load.load_files(x, load.split) - @click.command() -@common_options.scores_argument(eval_mandatory=True, min_len=2, nargs=-1) +@common_options.scores_argument(min_arg=2, force_eval=True, nargs=-1) @common_options.output_plot_file_option(default_out='epc.pdf') @common_options.titles_option() @common_options.const_layout_option() @@ -43,11 +41,11 @@ def epc(ctx, scores, **kwargs): $ bob pad epc {licit,spoof}/scores-{dev,eval} """ - process = figure.Epc(ctx, scores, True, FUNC_SPLIT) + process = figure.Epc(ctx, scores, True, load.split) process.run() @click.command() -@common_options.scores_argument(eval_mandatory=True, min_len=2, nargs=-1) +@common_options.scores_argument(min_arg=2, force_eval=True, nargs=-1) @common_options.output_plot_file_option(default_out='epsc.pdf') @common_options.titles_option() @common_options.const_layout_option() @@ -102,12 +100,12 @@ def epsc(ctx, scores, criteria, var_param, fixed_param, three_d, **kwargs): if (ctx.meta['wer'] and ctx.meta['iapmr']): raise click.BadParameter('Cannot plot both WER and IAPMR in 3D') process = figure.Epsc3D( - ctx, scores, True, FUNC_SPLIT, + ctx, scores, True, load.split, criteria, var_param, fixed_param ) else: process = figure.Epsc( - ctx, scores, True, FUNC_SPLIT, + ctx, scores, True, load.split, criteria, var_param, fixed_param ) process.run() diff --git a/bob/pad/base/script/figure.py b/bob/pad/base/script/figure.py index 078a6d6..9de35c8 100644 --- a/bob/pad/base/script/figure.py +++ b/bob/pad/base/script/figure.py @@ -8,7 +8,7 @@ import matplotlib.pyplot as mpl import bob.measure.script.figure as measure_figure from tabulate import tabulate from bob.extension.scripts.click_helper import verbosity_option -from bob.measure.utils import (get_fta, get_thres) +from bob.measure.utils import (get_fta, get_fta_list, get_thres) from bob.measure import ( far_threshold, eer_threshold, min_hter_threshold, farfrr, epc, ppndf ) @@ -57,15 +57,18 @@ class Metrics(measure_figure.Metrics): super(Metrics, self).__init__(ctx, scores, evaluation, func_load) ''' Compute metrics from score files''' - def compute(self, idx, dev_score, dev_file=None, - eval_score=None, eval_file=None): + def compute(self, idx, input_scores, input_names): ''' Compute metrics for the given criteria''' - dev_neg, dev_pos, _, eval_neg, eval_pos, _ =\ - self._process_scores(dev_score, eval_score) + neg_list, pos_list, _ = get_fta_list(input_scores) + dev_neg, dev_pos = neg_list[0], pos_list[0] + dev_file = input_names[0] + if self._eval: + eval_neg, eval_pos = neg_list[1], pos_list[1] + eval_file = input_names[1] title = self._titles[idx] if self._titles is not None else None headers = ['' or title, 'Development %s' % dev_file] - if self._eval and eval_score is not None: + if self._eval: headers.append('Eval. % s' % eval_file) for m in ALL_CRITERIA: raws = [] @@ -93,11 +96,11 @@ class HistPad(measure_figure.Hist): def _setup_hist(self, neg, pos): self._title_base = 'PAD' self._density_hist( - pos, label='Bona Fide', color='C1', **self._kwargs + pos[0], label='Bona Fide', color='C1' ) self._density_hist( - neg, label='Presentation attack', alpha=0.4, color='C7', - hatch='\\\\', **self._kwargs + neg[0], label='Presentation attack', alpha=0.4, color='C7', + hatch='\\\\' ) def _calc_pass_rate(threshold, scores): @@ -134,48 +137,24 @@ def _iapmr_line_plot(scores, n_points=100, **kwargs): 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 ''' - def _get_neg_pos_thres(self, idx, dev_score, eval_score): - assert len(dev_score) == self._min_arg - dev_neg_list = [] - eval_neg_list = [] - dev_pos_list = [] - eval_pos_list = [] - for i in range(self._min_arg): - dev_neg, dev_pos, _, eval_neg, eval_pos, _ = self._process_scores( - dev_score[i], eval_score[i] - ) - dev_neg_list.append(dev_neg) - dev_pos_list.append(dev_pos) - eval_neg_list.append(eval_neg) - eval_pos_list.append(eval_pos) - - threshold = get_thres( - self._criter, dev_neg_list[0], dev_pos_list[0] - ) if self._thres is None else self._thres[idx] - return (dev_neg_list, dev_pos_list, - eval_neg_list, eval_pos_list, threshold) def _setup_hist(self, neg, pos): self._title_base = 'Vulnerability' - assert len(neg) == len(pos) == self._min_arg self._density_hist( - pos[0], label='Bona Fide', color='C1', **self._kwargs + pos[0], label='Bona Fide', color='C1' ) self._density_hist( - neg[0], label='Zero-effort impostors', alpha=0.8, color='C0', - **self._kwargs + neg[0], label='Zero-effort impostors', alpha=0.8, color='C0' ) self._density_hist( neg[1], label='Presentation attack', alpha=0.4, color='C7', - hatch='\\\\', **self._kwargs + hatch='\\\\' ) def _lines(self, threshold, neg, pos, **kwargs): @@ -210,24 +189,6 @@ class PadPlot(measure_figure.PlotBase): super(PadPlot, self).__init__(ctx, scores, evaluation, func_load) mpl.rcParams['figure.constrained_layout.use'] = self._clayout - def _process_scores(self, dev_score, eval_score): - '''Process score files and return neg/pos/fta for eval and dev''' - assert len(dev_score) == self._min_arg - dev_neg_list = [] - eval_neg_list = [] - dev_pos_list = [] - eval_pos_list = [] - for i in range(self._min_arg): - dev_neg, dev_pos, _, eval_neg, eval_pos, _ = \ - super(PadPlot, self)._process_scores( - dev_score[i], eval_score[i] - ) - dev_neg_list.append(dev_neg) - dev_pos_list.append(dev_pos) - eval_neg_list.append(eval_neg) - eval_pos_list.append(eval_pos) - return (dev_neg_list, dev_pos_list, None, - eval_neg_list, eval_pos_list, None) def end_process(self): '''Close pdf ''' @@ -260,14 +221,19 @@ class Epc(PadPlot): self._eval = True #always eval data with EPC self._split = False self._nb_figs = 1 + self._title = '' - def compute(self, idx, dev_score, dev_file, eval_score, eval_file=None): + 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): ''' Plot EPC for PAD''' - licit_dev_neg = dev_score[0][0] - licit_dev_pos = dev_score[0][1] - licit_eval_neg = eval_score[0][0] - licit_eval_pos = eval_score[0][1] - spoof_eval_neg = eval_score[1][0] + licit_dev_neg = input_scores[0][0] + licit_dev_pos = input_scores[0][1] + licit_eval_neg = input_scores[1][0] + licit_eval_pos = input_scores[1][1] + spoof_eval_neg = input_scores[3][0] mpl.gcf().clear() epc_baseline = epc( licit_dev_neg, licit_dev_pos, licit_eval_neg, @@ -277,7 +243,7 @@ class Epc(PadPlot): epc_baseline[:, 0], [100. * k for k in epc_baseline[:, 1]], color='C0', label=self._label( - 'WER', '%s-%s' % (dev_file[0], eval_file[0]), idx + 'WER', '%s-%s' % (input_names[0], input_names[1]), idx ), linestyle='-' ) @@ -299,7 +265,7 @@ class Epc(PadPlot): color='C3', linestyle='-', label=self._label( - 'IAPMR', '%s-%s' % (dev_file[0], eval_file[0]), idx + 'IAPMR', '%s-%s' % (input_names[0], input_names[1]), idx ) ) prob_ax.set_yticklabels(prob_ax.get_yticks()) @@ -330,21 +296,25 @@ class Epsc(PadPlot): self._criteria = 'eer' if criteria is None else criteria self._var_param = "omega" if var_param is None else var_param self._fixed_param = 0.5 if fixed_param is None else fixed_param - self._title = '' 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," + "spoof}/{dev,eval}") - def compute(self, idx, dev_score, dev_file, eval_score, eval_file=None): + def compute(self, idx, input_scores, input_names): ''' Plot EPSC for PAD''' - licit_dev_neg = dev_score[0][0] - licit_dev_pos = dev_score[0][1] - licit_eval_neg = eval_score[0][0] - licit_eval_pos = eval_score[0][1] - spoof_dev_neg = dev_score[1][0] - spoof_dev_pos = dev_score[1][1] - spoof_eval_neg = eval_score[1][0] - spoof_eval_pos = eval_score[1][1] + licit_dev_neg = input_scores[0][0] + licit_dev_pos = input_scores[0][1] + licit_eval_neg = input_scores[1][0] + licit_eval_pos = input_scores[1][1] + spoof_dev_neg = input_scores[2][0] + spoof_dev_pos = input_scores[2][1] + spoof_eval_neg = input_scores[3][0] + spoof_eval_pos = input_scores[3][1] title = self._titles[idx] if self._titles is not None else None mpl.gcf().clear() @@ -443,16 +413,16 @@ class Epsc(PadPlot): class Epsc3D(Epsc): ''' 3D EPSC plots for PAD''' - def compute(self, idx, dev_score, dev_file, eval_score, eval_file=None): + def compute(self, idx, input_scores, input_names): ''' Implements plots''' - licit_dev_neg = dev_score[0][0] - licit_dev_pos = dev_score[0][1] - licit_eval_neg = eval_score[0][0] - licit_eval_pos = eval_score[0][1] - spoof_dev_neg = dev_score[1][0] - spoof_dev_pos = dev_score[1][1] - spoof_eval_neg = eval_score[1][0] - spoof_eval_pos = eval_score[1][1] + licit_dev_neg = input_scores[0][0] + licit_dev_pos = input_scores[0][1] + licit_eval_neg = input_scores[1][0] + licit_eval_pos = input_scores[1][1] + spoof_dev_neg = input_scores[2][0] + spoof_dev_pos = input_scores[2][1] + spoof_eval_neg = input_scores[3][0] + spoof_eval_pos = input_scores[3][1] title = self._titles[idx] if self._titles is not None else None @@ -516,14 +486,14 @@ class Det(PadPlot): self._criteria = criteria self._real_data = True if real_data is None else real_data - def compute(self, idx, dev_score, dev_file, eval_score, eval_file=None): + def compute(self, idx, input_scores, input_names): ''' Implements plots''' - licit_dev_neg = dev_score[0][0] - licit_dev_pos = dev_score[0][1] - licit_eval_neg = eval_score[0][0] - licit_eval_pos = eval_score[0][1] - spoof_eval_neg = eval_score[1][0] if len(dev_score) > 1 else None - spoof_eval_pos = eval_score[1][1] if len(dev_score) > 1 else None + licit_dev_neg = input_scores[0][0] + licit_dev_pos = input_scores[0][1] + licit_eval_neg = input_scores[1][0] + licit_eval_pos = input_scores[1][1] + spoof_eval_neg = input_scores[3][0] if len(input_scores) > 2 else None + spoof_eval_pos = input_scores[3][1] if len(input_scores) > 2 else None det( licit_eval_neg, @@ -531,7 +501,7 @@ class Det(PadPlot): self._points, color=self._colors[idx], linestyle='-', - label=self._label("licit", dev_file[0], idx) + label=self._label("licit", input_names[0], idx) ) if not self._no_spoof and spoof_eval_neg is not None: det( @@ -540,7 +510,7 @@ class Det(PadPlot): self._points, color=self._colors[idx], linestyle='--', - label=self._label("spoof", eval_file[0], idx) + label=self._label("spoof", input_names[3], idx) ) if self._criteria is None: diff --git a/bob/pad/base/script/histograms.py b/bob/pad/base/script/histograms.py index e342718..4e83d6a 100644 --- a/bob/pad/base/script/histograms.py +++ b/bob/pad/base/script/histograms.py @@ -6,8 +6,6 @@ from bob.extension.scripts.click_helper import (verbosity_option, bool_option) from bob.bio.base.score import load from . import figure -FUNC_SPLIT = lambda x: load.load_files(x, load.split) - @click.command() @common_options.scores_argument(nargs=-1) @common_options.output_plot_file_option(default_out='hist.pdf') @@ -44,11 +42,11 @@ def hist(ctx, scores, evaluation, **kwargs): $ bob pad hist --criter hter dev-scores1 eval-scores1 """ - process = figure.HistPad(ctx, scores, evaluation, FUNC_SPLIT) + process = figure.HistPad(ctx, scores, evaluation, load.split) process.run() @click.command() -@common_options.scores_argument(nargs=-1, eval_mandatory=True, min_len=2) +@common_options.scores_argument(nargs=-1, min_arg=2) @common_options.output_plot_file_option(default_out='vuln.pdf') @common_options.eval_option() @common_options.n_bins_option() @@ -102,5 +100,5 @@ def vuln(ctx, scores, evaluation, **kwargs): $ bob pad vuln {licit,spoof}/scores-{dev,eval} ''' - process = figure.HistVuln(ctx, scores, evaluation, FUNC_SPLIT) + process = figure.HistVuln(ctx, scores, evaluation, load.split) process.run() diff --git a/bob/pad/base/script/metrics.py b/bob/pad/base/script/metrics.py index 151468f..60db789 100644 --- a/bob/pad/base/script/metrics.py +++ b/bob/pad/base/script/metrics.py @@ -7,8 +7,6 @@ from bob.extension.scripts.click_helper import (verbosity_option, from bob.bio.base.score import load from . import figure -FUNC_SPLIT = lambda x: load.load_files(x, load.split) - @click.command(context_settings=dict(token_normalize_func=lambda x: x.lower())) @common_options.scores_argument(nargs=-1) @common_options.eval_option() @@ -51,5 +49,5 @@ def metrics(ctx, scores, evaluation, **kwargs): $ bob pad metrics /path/to/system{1,2,3}/score-{dev,eval} """ - process = figure.Metrics(ctx, scores, evaluation, FUNC_SPLIT) + process = figure.Metrics(ctx, scores, evaluation, load.split) process.run() -- GitLab