Commit 6384d856 authored by Theophile GENTILHOMME's avatar Theophile GENTILHOMME

Modify the display of histograms: now can use subplots to display several...

Modify the display of histograms: now can use subplots to display several histograms on one page, can no longer display both dev and eval histo at the same time, can control the number of columns in the legend
parent b4e207e4
Pipeline #19717 passed with stage
in 74 minutes
...@@ -160,13 +160,14 @@ def epc(ctx, scores, **kwargs): ...@@ -160,13 +160,14 @@ def epc(ctx, scores, **kwargs):
@common_options.criterion_option() @common_options.criterion_option()
@common_options.thresholds_option() @common_options.thresholds_option()
@common_options.const_layout_option() @common_options.const_layout_option()
@common_options.show_dev_option()
@common_options.print_filenames_option() @common_options.print_filenames_option()
@common_options.title_option() @common_options.title_option()
@common_options.legends_option() @common_options.legends_option()
@common_options.figsize_option() @common_options.figsize_option(dflt=None)
@common_options.style_option() @common_options.style_option()
@common_options.linestyles_option() @common_options.linestyles_option()
@common_options.subplot_option()
@common_options.legend_ncols_option()
@verbosity_option() @verbosity_option()
@click.pass_context @click.pass_context
def hist(ctx, scores, evaluation, **kwargs): def hist(ctx, scores, evaluation, **kwargs):
......
...@@ -84,11 +84,6 @@ def semilogx_option(dflt=False, **kwargs): ...@@ -84,11 +84,6 @@ def semilogx_option(dflt=False, **kwargs):
return bool_option('semilogx', 'G', 'If set, use semilog on X axis', dflt, return bool_option('semilogx', 'G', 'If set, use semilog on X axis', dflt,
**kwargs) **kwargs)
def show_dev_option(dflt=False, **kwargs):
'''Option to tell if should show dev histo'''
return bool_option('show-dev', 'D', 'If set, show dev histograms', dflt,
**kwargs)
def print_filenames_option(dflt=True, **kwargs): def print_filenames_option(dflt=True, **kwargs):
'''Option to tell if filenames should be in the title''' '''Option to tell if filenames should be in the title'''
return bool_option('show-fn', 'P', 'If set, show filenames in title', dflt, return bool_option('show-fn', 'P', 'If set, show filenames in title', dflt,
...@@ -129,7 +124,7 @@ def lines_at_option(**kwargs): ...@@ -129,7 +124,7 @@ def lines_at_option(**kwargs):
'''Get option to draw const far line''' '''Get option to draw const far line'''
return list_float_option( return list_float_option(
name='lines-at', short_name='la', name='lines-at', short_name='la',
desc='If given, draw veritcal lines at the given axis positions', desc='If given, draw vertical lines at the given axis positions',
nitems=None, dflt='1e-3', **kwargs nitems=None, dflt='1e-3', **kwargs
) )
...@@ -146,6 +141,35 @@ def x_rotation_option(dflt=0, **kwargs): ...@@ -146,6 +141,35 @@ def x_rotation_option(dflt=0, **kwargs):
callback=callback, **kwargs)(func) callback=callback, **kwargs)(func)
return custom_x_rotation_option 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):
def callback(ctx, param, value):
value = abs(value)
ctx.meta['legends_ncol'] = value
return value
return click.option(
'-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):
def callback(ctx, param, value):
value = abs(value)
nrows = value // 10
nrows, ncols = divmod(nrows, 10)
ctx.meta['n_col'] = ncols
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.',
callback=callback, **kwargs)(func)
return custom_subplot_option
def cost_option(**kwargs): def cost_option(**kwargs):
'''Get option to get cost for FAR''' '''Get option to get cost for FAR'''
def custom_cost_option(func): def custom_cost_option(func):
...@@ -330,18 +354,6 @@ def figsize_option(dflt='4,3', **kwargs): ...@@ -330,18 +354,6 @@ def figsize_option(dflt='4,3', **kwargs):
callback=callback, **kwargs)(func) callback=callback, **kwargs)(func)
return custom_figsize_option return custom_figsize_option
def legend_ncols_option(**kwargs):
'''Get the number of columns to set in the legend of the plot'''
def custom_legend_ncols_option(func):
def callback(ctx, param, value):
ctx.meta['legend_ncol'] = value
return value
return click.option(
'--legend-ncol', default=3, show_default=True,
type=INT, help='The number of columns of the legend layout.',
callback=callback, **kwargs)(func)
return custom_legend_ncols_option
def legend_loc_option(**kwargs): def legend_loc_option(**kwargs):
'''Get tthe legend location of the plot''' '''Get tthe legend location of the plot'''
def custom_legend_loc_option(func): def custom_legend_loc_option(func):
......
...@@ -533,8 +533,6 @@ class Hist(PlotBase): ...@@ -533,8 +533,6 @@ class Hist(PlotBase):
super(Hist, self).__init__(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'] self._nbins = [] if 'n_bins' not in ctx.meta else ctx.meta['n_bins']
self._thres = None if 'thres' not in ctx.meta else ctx.meta['thres'] self._thres = None if 'thres' not in ctx.meta else ctx.meta['thres']
self._show_dev = ((not self._eval) if 'show_dev' not in ctx.meta else\
ctx.meta['show_dev']) or not self._eval
if self._thres is not None and len(self._thres) != self.n_systems: if self._thres is not None and len(self._thres) != self.n_systems:
if len(self._thres) == 1: if len(self._thres) == 1:
self._thres = self._thres * self.n_systems self._thres = self._thres * self.n_systems
...@@ -545,8 +543,13 @@ class Hist(PlotBase): ...@@ -545,8 +543,13 @@ class Hist(PlotBase):
) )
self._criterion = None if 'criterion' not in ctx.meta else \ 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']
self._step_print = int(self._nrows * self._ncols)
self._title_base = 'Scores' self._title_base = 'Scores'
self._y_label = 'Probability Density' self._y_label = 'Probability density'
self._x_label = 'Scores values' self._x_label = 'Scores values'
self._end_setup_plot = False self._end_setup_plot = False
...@@ -556,43 +559,30 @@ class Hist(PlotBase): ...@@ -556,43 +559,30 @@ class Hist(PlotBase):
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] dev_file = input_names[0]
eval_file = None if len(input_names) != 2 else input_names[1] eval_file = None if len(input_names) != 2 else input_names[1]
n = idx % self._step_print
fig = mpl.figure() col = n % self._ncols
if eval_neg is not None and self._show_dev: sub_plot_idx = n + 1
mpl.subplot(2, 1, 1) axis = mpl.subplot(self._nrows, self._ncols, sub_plot_idx)
if self._show_dev: neg = eval_neg if eval_neg is not None else dev_neg
self._setup_hist(dev_neg, dev_pos) pos = eval_pos if eval_pos is not None else dev_pos
mpl.title(self._get_title(idx, dev_file, eval_file)) self._setup_hist(neg, pos)
mpl.ylabel(self._y_label) if col == 0:
if not self._eval: axis.set_ylabel(self._y_label)
mpl.xlabel(self._x_label) if n + self._ncols >= min(self._step_print, self.n_systems):
if eval_neg is not None and self._show_dev: axis.set_xlabel(self._x_label)
ax = mpl.gca() axis.set_title(self._get_title(idx, dev_file, eval_file))
ax.axes.get_xaxis().set_ticklabels([]) label = "%s threshold%s" % (
#Setup lines, corresponding axis and legends '' if self._criterion is None else\
label = "%s threshold" % ('' if self._criterion is None else self._criterion.upper(), ' (dev)' if self._eval else ''
self._criterion.upper()) )
self._lines(threshold, label, dev_neg, dev_pos) self._lines(threshold, label, neg, pos)
if sub_plot_idx == 1:
self._plot_legends() self._plot_legends()
if self._step_print == sub_plot_idx or idx == self.n_systems - 1:
if eval_neg is not None: mpl.tight_layout()
if self._show_dev: self._pdf_page.savefig(mpl.gcf(), bbox_inches="tight")
mpl.subplot(2, 1, 2) mpl.clf()
self._setup_hist( mpl.figure()
eval_neg, eval_pos
)
if not self._show_dev:
mpl.title(self._get_title(idx, dev_file, eval_file))
mpl.ylabel('Probability density')
mpl.xlabel(self._x_label)
#Setup lines, corresponding axis and legends
label = "%s threshold (dev)" % ('' if self._criterion is None else
self._criterion.upper())
self._lines(threshold, label, eval_neg, eval_pos)
if not self._show_dev:
self._plot_legends()
self._pdf_page.savefig(fig)
def _get_title(self, idx, dev_file, eval_file): def _get_title(self, idx, dev_file, eval_file):
title = self._legends[idx] if self._legends is not None else None title = self._legends[idx] if self._legends is not None else None
...@@ -607,14 +597,10 @@ class Hist(PlotBase): ...@@ -607,14 +597,10 @@ class Hist(PlotBase):
li, la = ax.get_legend_handles_labels() li, la = ax.get_legend_handles_labels()
lines += li lines += li
labels += la labels += la
if self._show_dev and self._eval: mpl.gcf().legend(
mpl.legend( lines, labels, fontsize=6, loc='lower center', fancybox=True,
lines, labels, loc='upper center', ncol=6, framealpha=0.5, ncol=self._nlegends,
bbox_to_anchor=(0.5, -0.01), fontsize=6 )
)
else:
mpl.legend(lines, labels,
loc='best', fancybox=True, framealpha=0.5)
def _get_neg_pos_thres(self, idx, input_scores, input_names): def _get_neg_pos_thres(self, idx, input_scores, input_names):
neg_list, pos_list, _ = utils.get_fta_list(input_scores) neg_list, pos_list, _ = utils.get_fta_list(input_scores)
...@@ -658,4 +644,3 @@ class Hist(PlotBase): ...@@ -658,4 +644,3 @@ class Hist(PlotBase):
pos[0], n=1, pos[0], n=1,
label='Positives', alpha=0.5, color='C0' label='Positives', alpha=0.5, color='C0'
) )
...@@ -140,6 +140,7 @@ def test_hist(): ...@@ -140,6 +140,7 @@ def test_hist():
with runner.isolated_filesystem(): with runner.isolated_filesystem():
result = runner.invoke(commands.hist, ['--criterion', 'eer','--output', result = runner.invoke(commands.hist, ['--criterion', 'eer','--output',
'HISTO.pdf', '-b', '30,20', 'HISTO.pdf', '-b', '30,20',
'-sp', 221,
dev1, test1, dev2, test2]) dev1, test1, dev2, test2])
if result.output: if result.output:
click.echo(result.output) click.echo(result.output)
......
...@@ -126,7 +126,6 @@ CLI options ...@@ -126,7 +126,6 @@ CLI options
bob.measure.script.common_options.eval_option bob.measure.script.common_options.eval_option
bob.measure.script.common_options.sep_dev_eval_option bob.measure.script.common_options.sep_dev_eval_option
bob.measure.script.common_options.cmc_option bob.measure.script.common_options.cmc_option
bob.measure.script.common_options.show_dev_option
bob.measure.script.common_options.print_filenames_option bob.measure.script.common_options.print_filenames_option
bob.measure.script.common_options.const_layout_option bob.measure.script.common_options.const_layout_option
bob.measure.script.common_options.axes_val_option bob.measure.script.common_options.axes_val_option
...@@ -151,6 +150,8 @@ CLI options ...@@ -151,6 +150,8 @@ CLI options
bob.measure.script.common_options.x_label_option bob.measure.script.common_options.x_label_option
bob.measure.script.common_options.y_label_option bob.measure.script.common_options.y_label_option
bob.measure.script.common_options.style_option bob.measure.script.common_options.style_option
bob.measure.script.common_options.subplot_option
bob.measure.script.common_options.legend_ncols_option
Details Details
------- -------
......
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