From 190eb6de2323f67043cf258e1b6fe953d7cb0c66 Mon Sep 17 00:00:00 2001 From: Amir MOHAMMADI <amir.mohammadi@idiap.ch> Date: Thu, 3 May 2018 11:59:09 +0200 Subject: [PATCH] lint --- bob/measure/script/commands.py | 40 +++++----- bob/measure/script/common_options.py | 79 ++++++++++++++------ bob/measure/script/figure.py | 105 ++++++++++++++++----------- 3 files changed, 144 insertions(+), 80 deletions(-) diff --git a/bob/measure/script/commands.py b/bob/measure/script/commands.py index d2c6333..2c6423d 100644 --- a/bob/measure/script/commands.py +++ b/bob/measure/script/commands.py @@ -8,6 +8,7 @@ from . import common_options from bob.extension.scripts.click_helper import (verbosity_option, open_file_mode_option) + @click.command() @common_options.scores_argument(nargs=-1) @common_options.eval_option() @@ -24,9 +25,9 @@ def metrics(ctx, scores, evaluation, **kwargs): """Prints a table that contains FtA, FAR, FRR, FMR, FMNR, HTER for a given threshold criterion (eer or min-hter). - You need to provide one or more development score file(s) for each experiment. - You can also provide evaluation files along with dev files. If only dev scores - are provided, you must use flag `--no-evaluation`. + You need to provide one or more development score file(s) for each + experiment. You can also provide evaluation files along with dev files. If + only dev scores are provided, you must use flag `--no-evaluation`. Resulting table format can be changed using the `--tablefmt`. @@ -40,6 +41,7 @@ def metrics(ctx, scores, evaluation, **kwargs): process = figure.Metrics(ctx, scores, evaluation, load.split) process.run() + @click.command() @common_options.scores_argument(nargs=-1) @common_options.title_option() @@ -66,9 +68,9 @@ def roc(ctx, scores, evaluation, **kwargs): false non match rate on the vertical axis. The values for the axis will be computed using :py:func:`bob.measure.roc`. - You need to provide one or more development score file(s) for each experiment. - You can also provide evaluation files along with dev files. If only dev scores - are provided, you must use flag `--no-evaluation`. + You need to provide one or more development score file(s) for each + experiment. You can also provide evaluation files along with dev files. If + only dev scores are provided, you must use flag `--no-evaluation`. Examples: $ bob measure roc dev-scores @@ -81,6 +83,7 @@ def roc(ctx, scores, evaluation, **kwargs): process = figure.Roc(ctx, scores, evaluation, load.split) process.run() + @click.command() @common_options.scores_argument(nargs=-1) @common_options.output_plot_file_option(default_out='det.pdf') @@ -106,9 +109,9 @@ def det(ctx, scores, evaluation, **kwargs): modified ROC curve which plots error rates on both axes (false positives on the x-axis and false negatives on the y-axis) - You need to provide one or more development score file(s) for each experiment. - You can also provide evaluation files along with dev files. If only dev scores - are provided, you must use flag `--no-evaluation`. + You need to provide one or more development score file(s) for each + experiment. You can also provide evaluation files along with dev files. If + only dev scores are provided, you must use flag `--no-evaluation`. Examples: $ bob measure det dev-scores @@ -121,6 +124,7 @@ def det(ctx, scores, evaluation, **kwargs): process = figure.Det(ctx, scores, evaluation, load.split) process.run() + @click.command() @common_options.scores_argument(min_arg=1, force_eval=True, nargs=-1) @common_options.output_plot_file_option(default_out='epc.pdf') @@ -152,6 +156,7 @@ def epc(ctx, scores, **kwargs): process = figure.Epc(ctx, scores, True, load.split) process.run() + @click.command() @common_options.scores_argument(nargs=-1) @common_options.output_plot_file_option(default_out='hist.pdf') @@ -174,9 +179,9 @@ def hist(ctx, scores, evaluation, **kwargs): """ Plots histograms of positive and negatives along with threshold criterion. - You need to provide one or more development score file(s) for each experiment. - You can also provide evaluation files along with dev files. If only dev scores - are provided, you must use flag `--no-evaluation`. + You need to provide one or more development score file(s) for each + experiment. You can also provide evaluation files along with dev files. If + only dev scores are provided, you must use flag `--no-evaluation`. By default, when eval-scores are given, only eval-scores histograms are displayed with threshold line @@ -194,6 +199,7 @@ def hist(ctx, scores, evaluation, **kwargs): process = figure.Hist(ctx, scores, evaluation, load.split) process.run() + @click.command() @common_options.scores_argument(nargs=-1) @common_options.legends_option() @@ -217,8 +223,8 @@ def evaluate(ctx, scores, evaluation, **kwargs): \b 1. Computes the threshold using either EER or min. HTER criteria on development set scores - 2. Applies the above threshold on evaluation set scores to compute the HTER, if a - eval-score set is provided + 2. Applies the above threshold on evaluation set scores to compute the + HTER, if a eval-score set is provided 3. Reports error rates on the console 4. Plots ROC, EPC, DET curves and score distributions to a multi-page PDF file @@ -261,12 +267,12 @@ def evaluate(ctx, scores, evaluation, **kwargs): click.echo("Starting evaluate with dev scores only...") click.echo("Computing ROC...") # set axes limits for ROC - ctx.forward(roc) # use class defaults plot settings + ctx.forward(roc) # use class defaults plot settings click.echo("Computing DET...") - ctx.forward(det) # use class defaults plot settings + ctx.forward(det) # use class defaults plot settings if evaluation: click.echo("Computing EPC...") - ctx.forward(epc) # use class defaults plot settings + ctx.forward(epc) # use class defaults plot settings # the last one closes the file ctx.meta['closef'] = True click.echo("Computing score histograms...") diff --git a/bob/measure/script/common_options.py b/bob/measure/script/common_options.py index ccaa0f7..2f245f5 100644 --- a/bob/measure/script/common_options.py +++ b/bob/measure/script/common_options.py @@ -9,6 +9,7 @@ from bob.extension.scripts.click_helper import (bool_option, list_float_option) LOGGER = logging.getLogger(__name__) + def scores_argument(min_arg=1, force_eval=False, **kwargs): """Get the argument for scores, and add `dev-scores` and `eval-scores` in the context when `--evaluation` flag is on (default) @@ -35,7 +36,7 @@ def scores_argument(min_arg=1, force_eval=False, **kwargs): if 'train' in ctx.meta and ctx.meta['train']: mutli += 1 error += '- %d training file(s) \n' % min_a - #add more test here if other inputs are needed + # add more test here if other inputs are needed min_a *= mutli ctx.meta['min_arg'] = min_a @@ -54,6 +55,7 @@ def scores_argument(min_arg=1, force_eval=False, **kwargs): )(func) return custom_scores_argument + def eval_option(**kwargs): '''Get option flag to say if eval-scores are provided''' return bool_option( @@ -61,34 +63,40 @@ def eval_option(**kwargs): dflt=True ) + def sep_dev_eval_option(dflt=True, **kwargs): '''Get option flag to say if dev and eval plots should be in different plots''' return bool_option( - 'split', 's','If set, evaluation and dev curve in different plots', + 'split', 's', 'If set, evaluation and dev curve in different plots', dflt ) + def linestyles_option(dflt=False, **kwargs): ''' Get option flag to turn on/off linestyles''' return bool_option('line-linestyles', 'S', 'If given, applies a different ' 'linestyles to each line.', dflt, **kwargs) + def cmc_option(**kwargs): '''Get option flag to say if cmc scores''' return bool_option('cmc', 'C', 'If set, CMC score files are provided', **kwargs) + def semilogx_option(dflt=False, **kwargs): '''Option to use semilog X-axis''' return bool_option('semilogx', 'G', 'If set, use semilog on X axis', dflt, **kwargs) + def print_filenames_option(dflt=True, **kwargs): '''Option to tell if filenames should be in the title''' return bool_option('show-fn', 'P', 'If set, show filenames in title', dflt, **kwargs) + def const_layout_option(dflt=True, **kwargs): '''Option to set matplotlib constrained_layout''' def custom_layout_option(func): @@ -102,6 +110,7 @@ def const_layout_option(dflt=True, **kwargs): callback=callback, **kwargs)(func) return custom_layout_option + def axes_val_option(dflt=None, **kwargs): ''' Option for setting min/max values on axes ''' return list_float_option( @@ -111,6 +120,7 @@ def axes_val_option(dflt=None, **kwargs): nitems=4, dflt=dflt, **kwargs ) + def thresholds_option(**kwargs): ''' Option to give a list of thresholds ''' return list_float_option( @@ -120,14 +130,17 @@ def thresholds_option(**kwargs): nitems=None, dflt=None, **kwargs ) + def lines_at_option(**kwargs): '''Get option to draw const far line''' return list_float_option( name='lines-at', short_name='la', - desc='If given, draw vertical lines at the given axis positions', + desc='If given, draw vertical lines at the given axis positions. ' + 'You can provide multiple values separated with a comma (,).', nitems=None, dflt='1e-3', **kwargs ) + def x_rotation_option(dflt=0, **kwargs): '''Get option for rotartion of the x axis lables''' def custom_x_rotation_option(func): @@ -136,11 +149,12 @@ def x_rotation_option(dflt=0, **kwargs): ctx.meta['x_rotation'] = value return value return click.option( - '-r', '--x-rotation', type=click.INT, default=dflt, show_default=True, - help='X axis labels ration', + '-r', '--x-rotation', type=click.INT, default=dflt, + show_default=True, help='X axis labels ration', callback=callback, **kwargs)(func) return custom_x_rotation_option + def legend_ncols_option(dflt=10, **kwargs): '''Get option for number of columns for legends''' def custom_legend_ncols_option(func): @@ -149,11 +163,13 @@ def legend_ncols_option(dflt=10, **kwargs): ctx.meta['legends_ncol'] = value return value return click.option( - '-lc', '--legends-ncol', type=click.INT, default=dflt, show_default=True, + '-lc', '--legends-ncol', type=click.INT, default=dflt, + show_default=True, help='The number of columns of the legend layout.', callback=callback, **kwargs)(func) return custom_legend_ncols_option + def subplot_option(dflt=111, **kwargs): '''Get option to set subplots''' def custom_subplot_option(func): @@ -165,11 +181,12 @@ def subplot_option(dflt=111, **kwargs): ctx.meta['n_row'] = nrows return value return click.option( - '-sp', '--subplot', type=click.INT, default=dflt, show_default=True, - help='The order of subplots.', + '-sp', '--subplot', type=click.INT, default=dflt, + show_default=True, help='The order of subplots.', callback=callback, **kwargs)(func) return custom_subplot_option + def cost_option(**kwargs): '''Get option to get cost for FAR''' def custom_cost_option(func): @@ -184,14 +201,15 @@ def cost_option(**kwargs): callback=callback, **kwargs)(func) return custom_cost_option + def points_curve_option(**kwargs): '''Get the number of points use to draw curves''' def custom_points_curve_option(func): def callback(ctx, param, value): if value < 2: raise click.BadParameter( - 'Number of points to draw curves must be greater than 1' - , ctx=ctx + 'Number of points to draw curves must be greater than 1', + ctx=ctx ) ctx.meta['points'] = value return value @@ -201,6 +219,7 @@ def points_curve_option(**kwargs): callback=callback, **kwargs)(func) return custom_points_curve_option + def n_bins_option(**kwargs): '''Get the number of bins in the histograms''' def custom_n_bins_option(func): @@ -223,6 +242,7 @@ def n_bins_option(**kwargs): callback=callback, **kwargs)(func) return custom_n_bins_option + def table_option(**kwargs): '''Get table option for tabulate package More informnations: https://pypi.python.org/pypi/tabulate @@ -238,9 +258,10 @@ def table_option(**kwargs): '`jira`, `presto`, `psql`, `rst`, `mediawiki`, `moinmoin`, ' '`youtrack`, `html`, `latex`, ' '`latex_raw`, `latex_booktabs`, `textile`', - callback=callback,**kwargs)(func) + callback=callback, **kwargs)(func) return custom_table_option + def output_plot_file_option(default_out='plots.pdf', **kwargs): '''Get options for output file for plots''' def custom_output_plot_file_option(func): @@ -258,6 +279,7 @@ def output_plot_file_option(default_out='plots.pdf', **kwargs): callback=callback, **kwargs)(func) return custom_output_plot_file_option + def output_log_metric_option(**kwargs): '''Get options for output file for metrics''' def custom_output_log_file_option(func): @@ -269,10 +291,11 @@ def output_log_metric_option(**kwargs): return click.option( '-l', '--log', default=None, type=click.STRING, help='If provided, computed numbers are written to ' - 'this file instead of the standard output.', + 'this file instead of the standard output.', callback=callback, **kwargs)(func) return custom_output_log_file_option + def criterion_option(lcriteria=['eer', 'min-hter', 'far'], **kwargs): """Get option flag to tell which criteriom is used (default:eer) @@ -284,7 +307,7 @@ def criterion_option(lcriteria=['eer', 'min-hter', 'far'], **kwargs): def custom_criterion_option(func): def callback(ctx, param, value): list_accepted_crit = lcriteria if lcriteria is not None else \ - ['eer', 'min-hter', 'far'] + ['eer', 'min-hter', 'far'] if value not in list_accepted_crit: raise click.BadParameter('Incorrect value for `--criterion`. ' 'Must be one of [`%s`]' % @@ -295,9 +318,10 @@ def criterion_option(lcriteria=['eer', 'min-hter', 'far'], **kwargs): '-c', '--criterion', default='eer', help='Criterion to compute plots and ' 'metrics: `eer`, `min-hter` or `far`', - callback=callback, is_eager=True ,**kwargs)(func) + callback=callback, is_eager=True, **kwargs)(func) return custom_criterion_option + def far_option(**kwargs): '''Get option to get far value''' def custom_far_option(func): @@ -309,9 +333,10 @@ def far_option(**kwargs): return click.option( '-f', '--far-value', type=click.FLOAT, default=None, help='The FAR value for which to compute metrics', - callback=callback, show_default=True,**kwargs)(func) + callback=callback, show_default=True, **kwargs)(func) return custom_far_option + def min_far_option(dflt=1e-4, **kwargs): '''Get option to get min far value''' def custom_min_far_option(func): @@ -324,9 +349,10 @@ def min_far_option(dflt=1e-4, **kwargs): '-M', '--min-far-value', type=click.FLOAT, default=dflt, help='Select the minimum FAR value used in ROC and DET plots; ' 'should be a power of 10.', - callback=callback, show_default=True,**kwargs)(func) + callback=callback, show_default=True, **kwargs)(func) return custom_min_far_option + def figsize_option(dflt='4,3', **kwargs): """Get option for matplotlib figsize @@ -350,22 +376,25 @@ def figsize_option(dflt='4,3', **kwargs): return value return click.option( '--figsize', default=dflt, help='If given, will run ' - '``plt.rcParams[\'figure.figsize\']=figsize)``. Example: --fig-size 4,6', + '``plt.rcParams[\'figure.figsize\']=figsize)``. ' + 'Example: --fig-size 4,6', callback=callback, **kwargs)(func) return custom_figsize_option + def legend_loc_option(**kwargs): - '''Get tthe legend location of the plot''' + '''Get the legend location of the plot''' def custom_legend_loc_option(func): def callback(ctx, param, value): ctx.meta['legend_loc'] = value return value return click.option( '--legend-location', default=0, show_default=True, - type=INT, help='The lengend location code', + type=INT, help='The legend location code', callback=callback, **kwargs)(func) return custom_legend_loc_option + def line_width_option(**kwargs): '''Get line width option for the plots''' def custom_line_width_option(func): @@ -378,6 +407,7 @@ def line_width_option(**kwargs): callback=callback, **kwargs)(func) return custom_line_width_option + def marker_style_option(**kwargs): '''Get marker style otpion for the plots''' def custom_marker_style_option(func): @@ -390,6 +420,7 @@ def marker_style_option(**kwargs): callback=callback, **kwargs)(func) return custom_marker_style_option + def legends_option(**kwargs): '''Get the legends option for the different systems''' def custom_legends_option(func): @@ -405,6 +436,7 @@ def legends_option(**kwargs): callback=callback, **kwargs)(func) return custom_legends_option + def title_option(**kwargs): '''Get the title option for the different systems''' def custom_title_option(func): @@ -413,10 +445,12 @@ def title_option(**kwargs): return value return click.option( '-t', '--title', type=click.STRING, default=None, - help='The title of the plots', + help="The title of the plots. Provide just a space (-t ' ') to " + "remove the titles from figures.", callback=callback, **kwargs)(func) return custom_title_option + def x_label_option(dflt=None, **kwargs): '''Get the label option for X axis ''' def custom_x_label_option(func): @@ -429,6 +463,7 @@ def x_label_option(dflt=None, **kwargs): callback=callback, **kwargs)(func) return custom_x_label_option + def y_label_option(dflt=None, **kwargs): '''Get the label option for Y axis ''' def custom_y_label_option(func): @@ -441,6 +476,7 @@ def y_label_option(dflt=None, **kwargs): callback=callback, **kwargs)(func) return custom_y_label_option + def style_option(**kwargs): '''Get option for matplotlib style''' def custom_style_option(func): @@ -449,7 +485,8 @@ def style_option(**kwargs): plt.style.use(value) return value return click.option( - '--style', multiple=True, type=click.types.Choice(sorted(plt.style.available)), + '--style', multiple=True, + type=click.types.Choice(sorted(plt.style.available)), help='The matplotlib style to use for plotting. You can provide ' 'multiple styles by repeating this option', callback=callback, **kwargs)(func) diff --git a/bob/measure/script/figure.py b/bob/measure/script/figure.py index fce84e8..910388b 100644 --- a/bob/measure/script/figure.py +++ b/bob/measure/script/figure.py @@ -12,6 +12,7 @@ from matplotlib.backends.backend_pdf import PdfPages from tabulate import tabulate from .. import (far_threshold, plot, utils, ppndf) + class MeasureBase(object): """Base class for metrics and plots. This abstract class define the framework to plot or compute metrics from a @@ -22,7 +23,8 @@ class MeasureBase(object): func_load: Function that is used to load the input files """ - __metaclass__ = ABCMeta #for python 2.7 compatibility + __metaclass__ = ABCMeta # for python 2.7 compatibility + def __init__(self, ctx, scores, evaluation, func_load): """ Parameters @@ -69,7 +71,7 @@ class MeasureBase(object): # Note that more than one dev or eval scores score can be passed to # each system for idx in range(self.n_systems): - # load scores for each system: get the corresponding arrays and + # load scores for each system: get the corresponding arrays and # base-name of files input_scores, input_names = self._load_files( # Scores are given as followed: @@ -137,6 +139,7 @@ class MeasureBase(object): scores.append(self.func_load(filename)) return scores, basenames + class Metrics(MeasureBase): ''' Compute metrics from score files @@ -145,25 +148,26 @@ class Metrics(MeasureBase): log_file: str output stream ''' + def __init__(self, ctx, scores, evaluation, func_load): super(Metrics, self).__init__(ctx, scores, evaluation, func_load) self._tablefmt = None if 'tablefmt' not in ctx.meta else\ - ctx.meta['tablefmt'] + ctx.meta['tablefmt'] self._criterion = None if 'criterion' not in ctx.meta else \ - ctx.meta['criterion'] + ctx.meta['criterion'] self._open_mode = None if 'open_mode' not in ctx.meta else\ - ctx.meta['open_mode'] + ctx.meta['open_mode'] self._thres = None if 'thres' not in ctx.meta else ctx.meta['thres'] - if self._thres is not None : + if self._thres is not None: if len(self._thres) == 1: self._thres = self._thres * self.n_systems elif len(self._thres) != self.n_systems: raise click.BadParameter( - '#thresholds must be the same as #systems (%d)' \ + '#thresholds must be the same as #systems (%d)' % len(self.n_systems) ) self._far = None if 'far_value' not in ctx.meta else \ - ctx.meta['far_value'] + ctx.meta['far_value'] self._log = None if 'log' not in ctx.meta else ctx.meta['log'] self.log_file = sys.stdout if self._log is not None: @@ -180,23 +184,22 @@ class Metrics(MeasureBase): eval_file = input_names[1] threshold = utils.get_thres(self._criterion, dev_neg, dev_pos, self._far) \ - if self._thres is None else self._thres[idx] + if self._thres is None else self._thres[idx] title = self._legends[idx] if self._legends is not None else None if self._thres is None: far_str = '' if self._criterion == 'far' and self._far is not None: far_str = str(self._far) - click.echo("[Min. criterion: %s %s] Threshold on Development set `%s`: %e"\ + click.echo("[Min. criterion: %s %s] Threshold on Development set `%s`: %e" % (self._criterion.upper(), far_str, title or dev_file, threshold), file=self.log_file) else: click.echo("[Min. criterion: user provider] Threshold on " - "Development set `%s`: %e"\ + "Development set `%s`: %e" % (dev_file or title, threshold), file=self.log_file) - from .. import farfrr dev_fmr, dev_fnmr = farfrr(dev_neg, dev_pos, threshold) dev_far = dev_fmr * (1 - dev_fta) @@ -232,11 +235,14 @@ class Metrics(MeasureBase): eval_ni = eval_neg.shape[0] # number of impostors eval_fm = int(round(eval_fmr * eval_ni)) # number of false accepts eval_nc = eval_pos.shape[0] # number of clients - eval_fnm = int(round(eval_fnmr * eval_nc)) # number of false rejects + # number of false rejects + eval_fnm = int(round(eval_fnmr * eval_nc)) eval_fta_str = "%.1f%%" % (100 * eval_fta) - eval_fmr_str = "%.1f%% (%d/%d)" % (100 * eval_fmr, eval_fm, eval_ni) - eval_fnmr_str = "%.1f%% (%d/%d)" % (100 * eval_fnmr, eval_fnm, eval_nc) + eval_fmr_str = "%.1f%% (%d/%d)" % (100 * + eval_fmr, eval_fm, eval_ni) + eval_fnmr_str = "%.1f%% (%d/%d)" % (100 * + eval_fnmr, eval_fnm, eval_nc) eval_far_str = "%.1f%%" % (100 * eval_far) eval_frr_str = "%.1f%%" % (100 * eval_frr) @@ -257,10 +263,12 @@ class Metrics(MeasureBase): if self._log is not None: self.log_file.close() + class PlotBase(MeasureBase): ''' Base class for plots. Regroup several options and code shared by the different plots ''' + def __init__(self, ctx, scores, evaluation, func_load): super(PlotBase, self).__init__(ctx, scores, evaluation, func_load) self._output = None if 'output' not in ctx.meta else ctx.meta['output'] @@ -274,30 +282,31 @@ class PlotBase(MeasureBase): self._min_dig = int(math.log10(self._axlim[0]) if self._axlim[0] != 0 else 0) self._clayout = None if 'clayout' not in ctx.meta else\ - ctx.meta['clayout'] + ctx.meta['clayout'] self._far_at = None if 'lines_at' not in ctx.meta else\ - ctx.meta['lines_at'] + ctx.meta['lines_at'] self._trans_far_val = self._far_at if self._far_at is not None: self._eval_points = {line: [] for line in self._far_at} self._lines_val = [] self._print_fn = True if 'show_fn' not in ctx.meta else\ - ctx.meta['show_fn'] + ctx.meta['show_fn'] self._x_rotation = None if 'x_rotation' not in ctx.meta else \ - ctx.meta['x_rotation'] + ctx.meta['x_rotation'] if 'style' in ctx.meta: mpl.style.use(ctx.meta['style']) self._nb_figs = 2 if self._eval and self._split else 1 self._colors = utils.get_colors(self.n_systems) self._line_linestyles = False if 'line_linestyles' not in ctx.meta else \ - ctx.meta['line_linestyles'] - self._linestyles = utils.get_linestyles(self.n_systems, self._line_linestyles) + ctx.meta['line_linestyles'] + self._linestyles = utils.get_linestyles( + self.n_systems, self._line_linestyles) self._states = ['Development', 'Evaluation'] self._title = None if 'title' not in ctx.meta else ctx.meta['title'] self._x_label = None if 'x_label' not in ctx.meta else\ - ctx.meta['x_label'] + ctx.meta['x_label'] self._y_label = None if 'y_label' not in ctx.meta else\ - ctx.meta['y_label'] + ctx.meta['y_label'] self._grid_color = 'silver' self._pdf_page = None self._end_setup_plot = True @@ -308,11 +317,11 @@ class PlotBase(MeasureBase): matplotlib.use('pdf') self._pdf_page = self._ctx.meta['PdfPages'] if 'PdfPages'in \ - self._ctx.meta else PdfPages(self._output) + self._ctx.meta else PdfPages(self._output) for i in range(self._nb_figs): fs = None if 'figsize' not in self._ctx.meta else\ - self._ctx.meta['figsize'] + self._ctx.meta['figsize'] fig = mpl.figure(i + 1, figsize=fs) fig.set_constrained_layout(self._clayout) fig.clear() @@ -320,7 +329,7 @@ class PlotBase(MeasureBase): def end_process(self): ''' Set title, legend, axis labels, grid colors, save figures, drow lines and close pdf if needed ''' - #draw vertical lines + # draw vertical lines if self._far_at is not None: for (line, line_trans) in zip(self._far_at, self._trans_far_val): mpl.figure(1) @@ -340,7 +349,7 @@ class PlotBase(MeasureBase): mpl.plot(x_values, y_values, '--', color='black') - #only for plots + # only for plots if self._end_setup_plot: for i in range(self._nb_figs): fig = mpl.figure(i + 1) @@ -358,12 +367,12 @@ class PlotBase(MeasureBase): mpl.xticks(rotation=self._x_rotation) self._pdf_page.savefig(fig) - #do not want to close PDF when running evaluate + # 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() - #common protected functions + # common protected functions def _label(self, base, name, idx): if self._legends is not None and len(self._legends) > idx: @@ -376,14 +385,16 @@ class PlotBase(MeasureBase): if self._axlim is not None and None not in self._axlim: mpl.axis(self._axlim) + class Roc(PlotBase): ''' Handles the plotting of ROC''' + def __init__(self, ctx, scores, evaluation, func_load): super(Roc, self).__init__(ctx, scores, evaluation, func_load) self._title = self._title or 'ROC' self._x_label = self._x_label or 'False Positive Rate' self._y_label = self._y_label or "1 - False Negative Rate" - #custom defaults + # custom defaults if self._axlim is None: self._axlim = [1e-4, 1.0, 0, 1.0] @@ -422,7 +433,8 @@ class Roc(PlotBase): from .. import farfrr for line in self._far_at: thres_line = far_threshold(dev_neg, dev_pos, line) - eval_fmr, eval_fnmr = farfrr(eval_neg, eval_pos, thres_line) + eval_fmr, eval_fnmr = farfrr( + eval_neg, eval_pos, thres_line) eval_fnmr = 1 - eval_fnmr mpl.scatter(eval_fmr, eval_fnmr, c=self._colors[idx], s=30) self._eval_points[line].append((eval_fmr, eval_fnmr)) @@ -434,8 +446,10 @@ class Roc(PlotBase): label=self._label('development', dev_file, idx) ) + class Det(PlotBase): ''' Handles the plotting of DET ''' + def __init__(self, ctx, scores, evaluation, func_load): super(Det, self).__init__(ctx, scores, evaluation, func_load) self._title = self._title or 'DET' @@ -443,7 +457,7 @@ class Det(PlotBase): self._y_label = self._y_label or 'False Negative Rate' if self._far_at is not None: self._trans_far_val = [ppndf(float(k)) for k in self._far_at] - #custom defaults here + # custom defaults here if self._x_rotation is None: self._x_rotation = 50 @@ -482,7 +496,8 @@ class Det(PlotBase): from .. import farfrr for line in self._far_at: thres_line = far_threshold(dev_neg, dev_pos, line) - eval_fmr, eval_fnmr = farfrr(eval_neg, eval_pos, thres_line) + eval_fmr, eval_fnmr = farfrr( + eval_neg, eval_pos, thres_line) eval_fmr, eval_fnmr = ppndf(eval_fmr), ppndf(eval_fnmr) mpl.scatter(eval_fmr, eval_fnmr, c=self._colors[idx], s=30) self._eval_points[line].append((eval_fmr, eval_fnmr)) @@ -496,8 +511,10 @@ class Det(PlotBase): def _set_axis(self): plot.det_axis(self._axlim) + class Epc(PlotBase): ''' Handles the plotting of EPC ''' + def __init__(self, ctx, scores, evaluation, func_load): super(Epc, self).__init__(ctx, scores, evaluation, func_load) if self._min_arg != 2: @@ -505,7 +522,7 @@ class Epc(PlotBase): self._title = self._title or 'EPC' self._x_label = self._x_label or r'$\alpha$' self._y_label = self._y_label or 'HTER (%)' - self._eval = True #always eval data with EPC + self._eval = True # always eval data with EPC self._split = False self._nb_figs = 1 self._far_at = None @@ -527,8 +544,10 @@ class Epc(PlotBase): ) ) + class Hist(PlotBase): ''' Functional base class for histograms''' + def __init__(self, ctx, scores, evaluation, func_load): super(Hist, self).__init__(ctx, scores, evaluation, func_load) self._nbins = [] if 'n_bins' not in ctx.meta else ctx.meta['n_bins'] @@ -538,15 +557,15 @@ class Hist(PlotBase): self._thres = self._thres * self.n_systems else: raise click.BadParameter( - '#thresholds must be the same as #systems (%d)' \ + '#thresholds must be the same as #systems (%d)' % self.n_systems ) self._criterion = None if 'criterion' not in ctx.meta else \ - ctx.meta['criterion'] + ctx.meta['criterion'] self._nrows = 1 if 'n_row' not in ctx.meta else ctx.meta['n_row'] self._ncols = 1 if 'n_col' not in ctx.meta else ctx.meta['n_col'] self._nlegends = 10 if 'legends_ncol' not in ctx.meta else \ - ctx.meta['legends_ncol'] + ctx.meta['legends_ncol'] self._step_print = int(self._nrows * self._ncols) self._title_base = 'Scores' self._y_label = 'Probability density' @@ -556,7 +575,7 @@ class Hist(PlotBase): def compute(self, idx, input_scores, input_names): ''' Draw histograms of negative and positive scores.''' dev_neg, dev_pos, eval_neg, eval_pos, threshold = \ - self._get_neg_pos_thres(idx, input_scores, input_names) + self._get_neg_pos_thres(idx, input_scores, input_names) dev_file = input_names[0] eval_file = None if len(input_names) != 2 else input_names[1] n = idx % self._step_print @@ -569,12 +588,13 @@ class Hist(PlotBase): if col == 0: axis.set_ylabel(self._y_label) # rest to be printed - rest_print = self.n_systems - int(idx / self._step_print) * self._step_print + rest_print = self.n_systems - \ + int(idx / self._step_print) * self._step_print if n + self._ncols >= min(self._step_print, rest_print): axis.set_xlabel(self._x_label) axis.set_title(self._get_title(idx, dev_file, eval_file)) label = "%s threshold%s" % ( - '' if self._criterion is None else\ + '' if self._criterion is None else self._criterion.upper(), ' (dev)' if self._eval else '' ) self._lines(threshold, label, neg, pos, idx) @@ -589,7 +609,8 @@ class Hist(PlotBase): def _get_title(self, idx, dev_file, eval_file): title = self._legends[idx] if self._legends is not None else None title = title or self._title or self._title_base - title = '' if self._title is not None and not self._title.replace(' ', '') else title + title = '' if self._title is not None and not self._title.replace( + ' ', '') else title return title or '' def _plot_legends(self): @@ -607,7 +628,7 @@ class Hist(PlotBase): def _get_neg_pos_thres(self, idx, input_scores, input_names): neg_list, pos_list, _ = utils.get_fta_list(input_scores) length = len(neg_list) - #can have several files for one system + # can have several files for one system dev_neg = [neg_list[x] for x in range(0, length, 2)] dev_pos = [pos_list[x] for x in range(0, length, 2)] eval_neg = eval_pos = None -- GitLab