Commit 0781e166 authored by Theophile GENTILHOMME's avatar Theophile GENTILHOMME

Various small changes after Amir review: add/remove command options, use...

Various small changes after Amir review: add/remove command options, use matplotlib 2.2.2 functionalities, fix doc
parent ab9cd9e7
Pipeline #19137 passed with stage
in 25 minutes and 53 seconds
......@@ -260,7 +260,7 @@ def epc(dev_negatives, dev_positives, test_negatives, test_positives,
return pyplot.plot(out[0, :], 100.0 * out[1, :], **kwargs)
def det(negatives, positives, npoints=100, axisfontsize='x-small', **kwargs):
def det(negatives, positives, npoints=100, **kwargs):
"""Plots Detection Error Trade-off (DET) curve as defined in the paper:
Martin, A., Doddington, G., Kamm, T., Ordowski, M., & Przybocki, M. (1997).
......@@ -381,9 +381,9 @@ def det(negatives, positives, npoints=100, axisfontsize='x-small', **kwargs):
pticks = [ppndf(float(v)) for v in desiredTicks]
ax = pyplot.gca() # and finally we set our own tick marks
ax.set_xticks(pticks)
ax.set_xticklabels(desiredLabels, size=axisfontsize)
ax.set_xticklabels(desiredLabels)
ax.set_yticks(pticks)
ax.set_yticklabels(desiredLabels, size=axisfontsize)
ax.set_yticklabels(desiredLabels)
return retval
......
......@@ -21,16 +21,14 @@ from bob.extension.scripts.click_helper import (verbosity_option,
@verbosity_option()
@click.pass_context
def metrics(ctx, scores, evaluation, **kwargs):
"""Prints a single output line that contains all info for a given
criterion (eer or hter).
"""Prints a table that contains FtA, FAR, FRR, FMR, FMNR, HTER for a given
threshold criterion (eer or hter).
You need provide one or more development score file(s) for each experiment.
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 changer using the `--tablefmt`. Default
formats are `fancy_grid` when output in the terminal and `latex` when
written in a log file (see `--log`)
Resulting table format can be changed using the `--tablefmt`.
Examples:
$ bob measure metrics dev-scores
......@@ -42,7 +40,6 @@ def metrics(ctx, scores, evaluation, **kwargs):
process = figure.Metrics(ctx, scores, evaluation, load.split_files)
process.run()
@click.command()
@common_options.scores_argument(nargs=-1)
@common_options.title_option()
......@@ -53,12 +50,14 @@ def metrics(ctx, scores, evaluation, **kwargs):
@common_options.points_curve_option()
@common_options.semilogx_option(True)
@common_options.axes_val_option(dflt=[1e-4, 1, 1e-4, 1])
@common_options.axis_fontsize_option()
@common_options.x_rotation_option()
@common_options.x_label_option()
@common_options.y_label_option()
@common_options.lines_at_option()
@common_options.const_layout_option()
@common_options.figsize_option()
@common_options.style_option()
@common_options.const_layout_option()
@verbosity_option()
@click.pass_context
def roc(ctx, scores, evaluation, **kwargs):
......@@ -67,7 +66,7 @@ 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 provide one or more development score file(s) for each experiment.
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`.
......@@ -82,7 +81,6 @@ def roc(ctx, scores, evaluation, **kwargs):
process = figure.Roc(ctx, scores, evaluation, load.split_files)
process.run()
@click.command()
@common_options.scores_argument(nargs=-1)
@common_options.output_plot_file_option(default_out='det.pdf')
......@@ -91,12 +89,14 @@ def roc(ctx, scores, evaluation, **kwargs):
@common_options.sep_dev_eval_option()
@common_options.eval_option()
@common_options.axes_val_option(dflt=[0.01, 95, 0.01, 95])
@common_options.axis_fontsize_option(dflt=6)
@common_options.x_rotation_option(dflt=45)
@common_options.x_label_option()
@common_options.y_label_option()
@common_options.points_curve_option()
@common_options.const_layout_option()
@common_options.figsize_option()
@common_options.style_option()
@common_options.const_layout_option()
@verbosity_option()
@click.pass_context
def det(ctx, scores, evaluation, **kwargs):
......@@ -104,7 +104,7 @@ 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 provide one or more development score file(s) for each experiment.
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`.
......@@ -119,17 +119,18 @@ def det(ctx, scores, evaluation, **kwargs):
process = figure.Det(ctx, scores, evaluation, load.split_files)
process.run()
@click.command()
@common_options.scores_argument(eval_mandatory=True, nargs=-1)
@common_options.output_plot_file_option(default_out='epc.pdf')
@common_options.title_option()
@common_options.titles_option()
@common_options.points_curve_option()
@common_options.axis_fontsize_option()
@common_options.const_layout_option()
@common_options.x_label_option()
@common_options.y_label_option()
@common_options.figsize_option()
@common_options.style_option()
@common_options.const_layout_option()
@verbosity_option()
@click.pass_context
def epc(ctx, scores, **kwargs):
......@@ -138,7 +139,7 @@ def epc(ctx, scores, **kwargs):
a-priori on the development set and accounts for varying relative cost
in [0; 1] of FPR and FNR when calculating the threshold.
You need provide one or more development score and eval file(s)
You need to provide one or more development score and eval file(s)
for each experiment.
Examples:
......@@ -149,27 +150,28 @@ def epc(ctx, scores, **kwargs):
process = figure.Epc(ctx, scores, True, load.split_files)
process.run()
@click.command()
@common_options.scores_argument(nargs=-1)
@common_options.output_plot_file_option(default_out='hist.pdf')
@common_options.eval_option()
@common_options.n_bins_option()
@common_options.criterion_option()
@common_options.axis_fontsize_option()
@common_options.thresholds_option()
@common_options.const_layout_option()
@common_options.show_dev_option()
@common_options.print_filenames_option()
@common_options.title_option()
@common_options.titles_option()
@common_options.figsize_option()
@common_options.style_option()
@common_options.const_layout_option()
@verbosity_option()
@click.pass_context
def hist(ctx, scores, evaluation, **kwargs):
""" Plots histograms of positive and negatives along with threshold
criterion.
You need provide one or more development score file(s) for each experiment.
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`.
......@@ -189,7 +191,6 @@ def hist(ctx, scores, evaluation, **kwargs):
process = figure.Hist(ctx, scores, evaluation, load.split_files)
process.run()
@click.command()
@common_options.scores_argument(nargs=-1)
@common_options.titles_option()
......@@ -203,6 +204,9 @@ def hist(ctx, scores, evaluation, **kwargs):
@common_options.n_bins_option()
@common_options.lines_at_option()
@common_options.const_layout_option()
@common_options.figsize_option()
@common_options.style_option()
@common_options.const_layout_option()
@verbosity_option()
@click.pass_context
def evaluate(ctx, scores, evaluation, **kwargs):
......@@ -227,6 +231,11 @@ def evaluate(ctx, scores, evaluation, **kwargs):
Examples:
$ bob measure evaluate dev-scores
$ bob measure evaluate scores-dev1 scores-eval1 scores-dev2
scores-eval2
$ bob measure evaluate /path/to/sys-{1,2,3}/scores-{dev,eval}
$ bob measure evaluate -l metrics.txt -o my_plots.pdf dev-scores eval-scores
'''
# first time erase if existing file
......@@ -256,11 +265,10 @@ def evaluate(ctx, scores, evaluation, **kwargs):
if evaluation:
click.echo("Computing EPC...")
ctx.forward(epc) # use class defaults plot settings
ctx.forward(epc)
# the last one closes the file
ctx.meta['closef'] = True
click.echo("Computing score histograms...")
ctx.meta['criter'] = 'hter' # no criterion passed in evaluate
ctx.meta['criter'] = 'eer' # no criterion passed in evaluate
ctx.forward(hist)
click.echo("Evaluate successfully completed!")
click.echo("[plots] => %s" % (ctx.meta['output']))
'''Stores click common options for plots'''
import math
import pkg_resources # to make sure bob gets imported properly
import logging
import click
from click.types import INT, FLOAT, Choice, File
from click.types import INT, FLOAT
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
from bob.extension.scripts.click_helper import (verbosity_option, bool_option,
list_float_option)
from bob.extension.scripts.click_helper import (bool_option, list_float_option)
logger = logging.getLogger(__name__)
LOGGER = logging.getLogger(__name__)
def scores_argument(eval_mandatory=False, min_len=1, **kwargs):
"""Get the argument for scores, and add `dev-scores` and `eval-scores` in
......@@ -18,7 +16,6 @@ def scores_argument(eval_mandatory=False, min_len=1, **kwargs):
Parameters
----------
eval_mandatory :
If evaluation files are mandatory
min_len :
......@@ -27,7 +24,8 @@ def scores_argument(eval_mandatory=False, min_len=1, **kwargs):
Returns
-------
Click option
callable
A decorator to be used for adding score arguments for click commands
"""
def custom_scores_argument(func):
def callback(ctx, param, value):
......@@ -129,23 +127,10 @@ 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 a veritcal lines on ROC plots',
desc='If given, draw veritcal lines on ROC plots',
nitems=None, dflt=None, **kwargs
)
def axis_fontsize_option(dflt=8, **kwargs):
'''Get option for axis font size'''
def custom_axis_fontsize_option(func):
def callback(ctx, param, value):
value = abs(value)
ctx.meta['fontsize'] = value
return value
return click.option(
'-F', '--fontsize', type=click.INT, default=dflt, show_default=True,
help='Axis fontsize',
callback=callback, **kwargs)(func)
return custom_axis_fontsize_option
def x_rotation_option(dflt=0, **kwargs):
'''Get option for rotartion of the x axis lables'''
def custom_x_rotation_option(func):
......@@ -159,7 +144,6 @@ def x_rotation_option(dflt=0, **kwargs):
callback=callback, **kwargs)(func)
return custom_x_rotation_option
def cost_option(**kwargs):
'''Get option to get cost for FAR'''
def custom_cost_option(func):
......@@ -174,18 +158,6 @@ def cost_option(**kwargs):
callback=callback, **kwargs)(func)
return custom_cost_option
def n_sys_option(**kwargs):
'''Get the number of systems to be processed'''
def custom_n_sys_option(func):
def callback(ctx, param, value):
ctx.meta['n_sys'] = value
return value
return click.option(
'--n-sys', type=INT, default=1, show_default=True,
help='The number of systems to be processed',
callback=callback, is_eager=True , **kwargs)(func)
return custom_n_sys_option
def points_curve_option(**kwargs):
'''Get the number of points use to draw curves'''
def custom_points_curve_option(func):
......@@ -248,7 +220,7 @@ def output_plot_file_option(default_out='plots.pdf', **kwargs):
print the path of the file in the log'''
ctx.meta['output'] = value
ctx.meta['PdfPages'] = PdfPages(value)
logger.debug("Plots will be output in %s", value)
LOGGER.debug("Plots will be output in %s", value)
return value
return click.option(
'-o', '--output',
......@@ -264,7 +236,7 @@ def output_plot_metric_option(**kwargs):
''' Save ouput file and associated pdf in context list,
print the path of the file in the log'''
if value is not None:
logger.debug("Metrics will be output in %s", value)
LOGGER.debug("Metrics will be output in %s", value)
ctx.meta['log'] = value
return value
return click.option(
......@@ -279,7 +251,6 @@ def criterion_option(lcriteria=['eer', 'hter', 'far'], **kwargs):
Parameters
----------
lcriteria : :any:`list`
List of possible criteria
"""
......@@ -299,7 +270,6 @@ def criterion_option(lcriteria=['eer', 'hter', 'far'], **kwargs):
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):
......@@ -314,40 +284,6 @@ def far_option(**kwargs):
callback=callback, show_default=True,**kwargs)(func)
return custom_far_option
def rank_option(**kwargs):
'''Get option for rank parameter'''
def custom_rank_option(func):
def callback(ctx, param, value):
value = 1 if value < 0 else value
ctx.meta['rank'] = value
return value
return click.option(
'--rank', type=click.INT, default=1,
help='Given threshold for metrics computations',
callback=callback, show_default=True,**kwargs)(func)
return custom_rank_option
def label_option(name_option='x_label', **kwargs):
'''Get labels options based on the given name.
Parameters:
----------
name_option: str, optional
Name of the label option (e.g. x-lable, y1-label)
'''
def custom_label_option(func):
def callback(ctx, param, value):
''' Get and save labels list in the context list '''
ctx.meta[name_option.replace('-', '_')] = value if value is None else \
[int(i) for i in value.split(',')]
return value
return click.option(
'--' + name_option,
help='The id of figures which should have x_label separated by '
'comma. For example ``--%s 1,2,4``.' % name_option,
callback=callback, **kwargs)(func)
return custom_label_option
def figsize_option(**kwargs):
'''Get option for matplotlib figsize'''
def custom_figsize_option(func):
......
......@@ -4,7 +4,6 @@ from __future__ import division, print_function
from abc import ABCMeta, abstractmethod
import sys
import ntpath
import numpy
import click
import matplotlib
import matplotlib.pyplot as mpl
......@@ -36,29 +35,14 @@ class MeasureBase(object):
Attributes
----------
_scores: :any:`list`:
List of input files (e.g. dev-{1, 2, 3}, {dev,eval}-scores1
_ctx : :py:class:`dict`
Click context dictionary.
_eval : :py:class:`bool`
True if eval data are used
_titles: :any:`list`
List of titles for each system (dev + (eval) scores)
func_load:
Function that is used to load the input files
"""
__metaclass__ = ABCMeta #for python 2.7 compatibility
def __init__(self, ctx, scores, eval, func_load):
"""
Parameters
----------
ctx : :py:class:`dict`
Click context dictionary.
......@@ -137,10 +121,8 @@ class MeasureBase(object):
Parameters
----------
idx : :obj:`int`
index of the system
dev_score:
Development scores. Can be a tuple (neg, pos) of
:py:class:`numpy.ndarray` (e.g.
......@@ -173,7 +155,6 @@ class MeasureBase(object):
Returns
-------
dev_scores: :any:`list`: A list that contains, for each required
dev score file, the output of ``func_load``
eval_scores: :any:`list`: A list that contains, for each required
......@@ -210,8 +191,7 @@ class MeasureBase(object):
'''Process score files and return neg/pos/fta for eval and dev'''
dev_neg = dev_pos = dev_fta = eval_neg = eval_pos = eval_fta = None
if dev_score[0] is not None:
dev_score, dev_fta = utils.get_fta(dev_score)
dev_neg, dev_pos = dev_score
(dev_neg, dev_pos), dev_fta = utils.get_fta(dev_score)
if dev_neg is None:
raise click.UsageError("While loading dev-score file")
......@@ -229,29 +209,8 @@ class Metrics(MeasureBase):
Attributes
----------
_tablefmt: str
Table format
_criter: str
Criterion to compute threshold, see :py:func:`bob.measure.utils.get_thres`
_open_mode: str
Open mode of the output file (e.g. `w`, `a+`)
_thres: :any:`list`
If given, uses those threshold instead of computing them. Lenght of the
list must be the same as the number of systems.
_far: :obj:`float`
If given, uses this FAR to compute threshold
_log: str
Path to output log file
log_file: str
output stream
'''
def __init__(self, ctx, scores, evaluation, func_load):
super(Metrics, self).__init__(ctx, scores, evaluation, func_load)
......@@ -361,33 +320,11 @@ class Metrics(MeasureBase):
class PlotBase(MeasureBase):
''' Base class for plots. Regroup several options and code
shared by the different plots
Attributes
----------
_output: str
Path to the output pdf file
_points: :obj:`int`
Number of points used to draw curves
_split: :obj:`bool`
If False, dev and eval curves will be printed on the some figure
_axlim: :any:`list`
Minimum/Maximum values for the X and Y axes
_x_rotation: :obj:`int`
Rotation of the X axis labels
_axisfontsize: :obj:`int`
Axis font size
'''
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']
self._points = None if 'points' not in ctx.meta else ctx.meta['points']
self._points = 100 if 'points' not in ctx.meta else ctx.meta['points']
self._split = None if 'split' not in ctx.meta else ctx.meta['split']
self._axlim = None if 'axlim' not in ctx.meta else ctx.meta['axlim']
self._clayout = None if 'clayout' not in ctx.meta else\
......@@ -396,9 +333,8 @@ class PlotBase(MeasureBase):
ctx.meta['show_fn']
self._x_rotation = None if 'x_rotation' not in ctx.meta else \
ctx.meta['x_rotation']
self._axisfontsize = 6 if 'fontsize' not in ctx.meta else \
ctx.meta['fontsize']
if 'style' in ctx.meta:
mpl.style.use(ctx.meta['style'])
self._nb_figs = 2 if self._eval and self._split else 1
self._multi_plots = len(self.dev_scores) > 1
self._colors = utils.get_colors(len(self.dev_scores))
......@@ -422,14 +358,11 @@ class PlotBase(MeasureBase):
self._ctx.meta else PdfPages(self._output)
for i in range(self._nb_figs):
fig = mpl.figure(i + 1)
fs = None if 'figsize' not in self._ctx.meta else\
self._ctx.meta['figsize']
fig = mpl.figure(i + 1, figsize=fs)
fig.set_constrained_layout(self._clayout)
fig.clear()
if self._axisfontsize is not None:
mpl.rc('xtick', labelsize=self._axisfontsize)
mpl.rc('ytick', labelsize=self._axisfontsize)
mpl.rc('legend', fontsize=6)
mpl.rc('axes', labelsize=8)
#mpl.rcParams['figure.constrained_layout.use'] = self._clayout
def end_process(self):
''' Set title, legend, axis labels, grid colors, save figures and
......@@ -449,8 +382,6 @@ class PlotBase(MeasureBase):
mpl.grid(True, color=self._grid_color)
mpl.legend(loc='best')
self._set_axis()
#gives warning when applied with mpl
fig.set_tight_layout(True)
mpl.xticks(rotation=self._x_rotation)
self._pdf_page.savefig(fig)
......@@ -472,22 +403,9 @@ class PlotBase(MeasureBase):
def _set_axis(self):
if self._axlim is not None and None not in self._axlim:
mpl.axis(self._axlim)
else:
mpl.axes().autoscale()
class Roc(PlotBase):
''' Handles the plotting of ROC
Attributes
----------
_semilogx: :obj:`bool`
If true, X-axis will be semilog10
_fmr_at: :obj:`float`
If not None, plot a vertical line at this value on the dev plot and
corresponding dots on the eval plot (if any).
'''
''' Handles the plotting of ROC'''
def __init__(self, ctx, scores, evaluation, func_load):
super(Roc, self).__init__(ctx, scores, evaluation, func_load)
self._semilogx = True if 'semilogx' not in ctx.meta else\
......@@ -588,7 +506,7 @@ class Det(PlotBase):
linestyle = '-' if not self._split else LINESTYLES[idx % 14]
plot.det(
dev_neg, dev_pos, self._points, color=self._colors[idx],
linestyle=linestyle, axisfontsize=self._axisfontsize,
linestyle=linestyle,
label=self._label('development', dev_file, idx, **self._kwargs)
)
if self._split:
......@@ -596,13 +514,13 @@ class Det(PlotBase):
linestyle = '--' if not self._split else LINESTYLES[idx % 14]
plot.det(
eval_neg, eval_pos, self._points, color=self._colors[idx],
linestyle=linestyle, axisfontsize=self._axisfontsize,
linestyle=linestyle,
label=self._label('eval', eval_file, idx, **self._kwargs)
)
else:
plot.det(
dev_neg, dev_pos, self._points, color=self._colors[idx],
linestyle=LINESTYLES[idx % 14], axisfontsize=self._axisfontsize,
linestyle=LINESTYLES[idx % 14],
label=self._label('development', dev_file, idx, **self._kwargs)
)
......@@ -619,39 +537,26 @@ class Epc(PlotBase):
if 'eval_scores_0' not in self._ctx.meta:
raise click.UsageError("EPC requires dev and eval score files")
self._title = self._title or 'EPC'
self._x_label = self._x_label or 'Cost'
self._y_label = self._y_label or 'Min. HTER (%)'
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._split = False
self._nb_figs = 1
def compute(self, idx, dev_score, dev_file, eval_score, eval_file=None):
''' Plot EPC using
:py:func:`bob.measure.plot.epc`'''
''' Plot EPC using :py:func:`bob.measure.plot.epc` '''
dev_neg, dev_pos, _, eval_neg, eval_pos, _ =\
self._process_scores(dev_score, eval_score)
plot.epc(
dev_neg, dev_pos, eval_neg, eval_pos, self._points,
color=self._colors[idx], linestyle=LINESTYLES[idx % 14],
label=self._label('curve', dev_file + "_" + eval_file, idx, **self._kwargs)
label=self._label(
'curve', dev_file + "_" + eval_file, idx, **self._kwargs
)
)
class Hist(PlotBase):
''' Functional base class for histograms
Attributes
----------
_nbins: :obj:`int`, str
Number of bins. Default: `auto`
_thres: :any:`list`
If given, uses those threshold instead of computing them. Lenght of the
list must be the same as the number of systems.
_criter: str
Criterion to compute threshold (eer or hter)
'''
''' Functional base class for histograms'''
def __init__(self, ctx, scores, evaluation, func_load):
super(Hist, self).__init__(ctx, scores, evaluation, func_load)
self._nbins = None if 'nbins' not in ctx.meta else ctx.meta['nbins']
......@@ -710,7 +615,6 @@ class Hist(PlotBase):
if not self._show_dev:
self._plot_legends()
fig.set_tight_layout(True)
self._pdf_page.savefig(fig)
def _get_title(self, idx, dev_file, eval_file):
......@@ -739,7 +643,6 @@ class Hist(PlotBase):
mpl.legend(lines, labels,
loc='best', fancybox=True, framealpha=0.5)
def _get_neg_pos_thres(self, idx, dev_score, eval_score):
dev_neg, dev_pos, _, eval_neg, eval_pos, _ = self._process_scores(
dev_score, eval_score
......@@ -752,7 +655,7 @@ class Hist(PlotBase):
def _density_hist(self, scores, **kwargs):
n, bins, patches = mpl.hist(
scores, normed=True, bins=self._nbins, **kwargs
scores, density=True, bins=self._nbins, **kwargs
)
return (n, bins, patches)
......@@ -761,9 +664,8 @@ class Hist(PlotBase):
kwargs.setdefault('color', 'C3')
kwargs.setdefault('linestyle', '--')
kwargs.setdefault('label', label)
_, _, ymax, ymin = mpl.axis()
# plot a vertical threshold line
mpl.axvline(x=threshold, ymin=ymin, ymax=ymax, **kwargs)
mpl.axvline(x=threshold, ymin=0, ymax=1, **kwargs)
def _setup_hist(self, neg, pos):
''' This function can be overwritten in derived classes'''
......
......@@ -16,11 +16,10 @@ NUM_NEG = 5000
NUM_POS = 5000
def gen_score_distr(mean_neg, mean_pos, sigma_neg=1, sigma_pos=1):
"""Generate scores from normal distributions
"""Generate scores from normal distributions
Parameters
----------
mean_neg : float
Mean for negative scores
mean_pos : float
......@@ -32,10 +31,9 @@ def gen_score_distr(mean_neg, mean_pos, sigma_neg=1, sigma_pos=1):
Returns
-------
neg_scores : array_like
neg_scores : :any:`list`
Negatives scores
pos_scores : array_like
pos_scores : :any:`list`
Positive scores
"""
mt = random.mt19937() # initialise the random number generator
......@@ -56,9 +54,9 @@ def write_scores_to_file(pos, neg, filename):
Parameters
----------
pos : array_like
pos : :py:class:`numpy.ndarray`
Scores for positive samples.
neg : array_like
neg : :py:class:`numpy.ndarray`
Scores for negative samples.
filename : str
The path to write the score to.
......
......@@ -7,8 +7,8 @@ from click.types import INT, FLOAT, Choice, File
@with_plugins(pkg_resources.iter_entry_points('bob.measure.cli'))
@click.group(chain=True)
@click.group()
def measure():
"""Entry for bob.measure commands."""
"""Generic performance evaluation commands."""
pass
......@@ -2,7 +2,6 @@
import numpy
import scipy.stats
import click
import bob.core
def remove_nan(scores):
......@@ -12,7 +11,6 @@ def remove_nan(scores):
Parameters