Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add toy calculator, empirical distribution, and toy example notebook #790

Merged
merged 60 commits into from
Oct 28, 2020
Merged
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
48a972e
Initial commit
lukasheinrich Mar 4, 2020
f9dc8ed
add toys notebook
kratsg Mar 18, 2020
eda15ed
use tqdm for progress
kratsg Mar 18, 2020
ce2c138
update notebook
kratsg Mar 19, 2020
82358fc
add docstrings
kratsg Mar 27, 2020
2f1106c
add missing to docstring
kratsg Mar 27, 2020
480920e
allow kwargs forwarding through to calculators
kratsg Mar 30, 2020
60f728a
add little doc to hypotest
kratsg Mar 30, 2020
3190599
restructure a little and move into infer.utils
kratsg Mar 30, 2020
44b9f90
Add additional \ for typsetting in Sphinx
matthewfeickert Mar 30, 2020
6e89259
Apply revisions to notebook
matthewfeickert Mar 31, 2020
c7a9331
Add toys notebook to tests
matthewfeickert Mar 31, 2020
2225e07
revert: Set bkg uncert explicitly
matthewfeickert Mar 31, 2020
7718087
Use figure size of (14,6) inches for Figure 5 plots
matthewfeickert Mar 31, 2020
440a750
Clarify calculator action description and correct typo
matthewfeickert Mar 31, 2020
3375c09
Move matplotlib font control to notebook header
matthewfeickert Mar 31, 2020
d584f7a
use sig-like and bkg-like phrasing everywhere
kratsg Mar 31, 2020
84cea15
Add tests for EmpiricalDistribution and ToyCalculator
matthewfeickert Mar 31, 2020
4fdeecf
Use generic term 'test statistic'
matthewfeickert Mar 31, 2020
a3d1057
Update numbers of toys to 20000
matthewfeickert Apr 1, 2020
7da31a7
Use pytest.approx to get CI to pass
matthewfeickert Apr 1, 2020
9d1a6ea
Mark toys notebook as 'slow' test to skip
matthewfeickert Apr 1, 2020
53f9967
Add EmpiricalDistribution, ToyCalculator, and utils.create_calculator…
matthewfeickert Apr 1, 2020
7d12466
Use 10000 toys for faster result
matthewfeickert Apr 1, 2020
babc521
Add examples for EmpericalDist
matthewfeickert Apr 2, 2020
81d8b9a
Correct line spacing for doctest
matthewfeickert Apr 2, 2020
03a4531
Add example for generate_asimov_data
matthewfeickert Apr 2, 2020
70d99f3
Add examples for AsymptoticTestStatDistribution
matthewfeickert Apr 2, 2020
b4c6f0c
Add examples to AsymptoticCalculator
matthewfeickert Apr 2, 2020
00c5b9c
Add ToyCalculator examples
matthewfeickert Apr 2, 2020
552019b
Add examples to infer.utils
matthewfeickert Apr 2, 2020
8ca3348
Use consistent style
matthewfeickert Apr 3, 2020
a5378fa
Specify interpolation method to use
matthewfeickert Apr 5, 2020
8e3113d
fix import
kratsg Oct 26, 2020
1e0d12f
Apply Black
matthewfeickert Oct 27, 2020
9eb8a12
Pop off the hypotest specific kwargs before passing to create_calculator
matthewfeickert Oct 27, 2020
2a98446
Use updated test stats API
matthewfeickert Oct 27, 2020
731ad35
Use correct calculator API
matthewfeickert Oct 27, 2020
ef6aa76
Use model suggested init_pars, par_bounds, fixed_params
matthewfeickert Oct 27, 2020
649d6df
Fix doctest
matthewfeickert Oct 27, 2020
a7ecbe8
Change values for qtilde_mu_bkg.samples in test_infer
matthewfeickert Oct 27, 2020
1558f21
fix up argument passing
kratsg Oct 27, 2020
c16e87f
qtilde False back to existing API
kratsg Oct 27, 2020
5e1d163
move hypotest back
kratsg Oct 27, 2020
e7662e7
fix imports
kratsg Oct 27, 2020
b937fbb
fix up spacing
kratsg Oct 27, 2020
356f82a
actually test toys notebook
kratsg Oct 27, 2020
a522bd0
fix import
kratsg Oct 27, 2020
bbc08ad
fix doctest
kratsg Oct 27, 2020
6e29fbd
add test for coverage in backends
kratsg Oct 27, 2020
6efc1b1
switch to tensorlib backend
kratsg Oct 27, 2020
92ad033
qtilde=True default
kratsg Oct 28, 2020
507d1a8
Use :obj:
matthewfeickert Oct 28, 2020
f5a683e
Keep docstrings to 80 chars when possible
matthewfeickert Oct 28, 2020
61e6c12
Use pyhf.infer.test_statistics.qmu_tilde API
matthewfeickert Oct 28, 2020
6fb6769
Set qtilde for the two toy calculators
matthewfeickert Oct 28, 2020
c5a2bd5
Explicitly give qtilde option in example
matthewfeickert Oct 28, 2020
6e3dca9
Add comment to relevant PR for adding percentile
matthewfeickert Oct 28, 2020
677603b
add :obj:
kratsg Oct 28, 2020
2c9ca25
remove slow
kratsg Oct 28, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,13 @@ Inference
mle.fit
mle.fixed_poi_fit
hypotest
intervals.upperlimit
calculators.generate_asimov_data
calculators.AsymptoticTestStatDistribution
calculators.EmpiricalDistribution
calculators.AsymptoticCalculator
intervals.upperlimit
calculators.ToyCalculator
utils.create_calculator

Exceptions
----------
Expand Down
Binary file added docs/examples/notebooks/img/1007.1727.fig5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6,618 changes: 6,618 additions & 0 deletions docs/examples/notebooks/toys.ipynb

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion src/pyhf/cli/infer.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ def fit(
@click.option('-p', '--patch', multiple=True)
@click.option('--testpoi', default=1.0)
@click.option('--teststat', type=click.Choice(['q', 'qtilde']), default='qtilde')
@click.option(
'--calctype', type=click.Choice(['asymptotics', 'toybased']), default='asymptotics'
)
@click.option(
'--backend',
type=click.Choice(['numpy', 'pytorch', 'tensorflow', 'jax', 'np', 'torch', 'tf']),
Expand All @@ -160,6 +163,7 @@ def cls(
teststat,
backend,
optimizer,
calctype,
optconf,
):
"""
Expand Down Expand Up @@ -219,7 +223,12 @@ def cls(
set_backend(tensorlib, new_optimizer(**optconf))

result = hypotest(
testpoi, ws.data(model), model, qtilde=is_qtilde, return_expected_set=True
testpoi,
ws.data(model),
model,
qtilde=is_qtilde,
calctype=calctype,
return_expected_set=True,
)
result = {
'CLs_obs': tensorlib.tolist(result[0]),
Expand Down
47 changes: 30 additions & 17 deletions src/pyhf/infer/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Inference for Statistical Models."""

from . import utils
from .. import get_backend
from .calculators import AsymptoticCalculator


def hypotest(
Expand All @@ -12,11 +12,17 @@ def hypotest(
par_bounds=None,
fixed_params=None,
qtilde=True,
calctype="asymptotics",
return_tail_probs=False,
return_expected=False,
return_expected_set=False,
**kwargs,
):
r"""
Compute :math:`p`-values and test statistics for a single value of the parameter of interest.

See :py:class:`~pyhf.infer.calculators.AsymptoticCalculator` and :py:class:`~pyhf.infer.calculators.ToyCalculator` on additional keyword arguments to be specified.

Example:
>>> import pyhf
>>> pyhf.set_backend("numpy")
Expand All @@ -25,9 +31,9 @@ def hypotest(
... )
>>> observations = [51, 48]
>>> data = pyhf.tensorlib.astensor(observations + model.config.auxdata)
>>> test_poi = 1.0
>>> mu_test = 1.0
>>> CLs_obs, CLs_exp_band = pyhf.infer.hypotest(
... test_poi, data, model, qtilde=True, return_expected_set=True
... mu_test, data, model, qtilde=True, return_expected_set=True
... )
>>> CLs_obs
array(0.05251497)
Expand All @@ -41,14 +47,13 @@ def hypotest(
init_pars (:obj:`tensor`): The initial parameter values to be used for minimization
par_bounds (:obj:`tensor`): The parameter value bounds to be used for minimization
fixed_params (:obj:`tensor`): Whether to fix the parameter to the init_pars value during minimization
qtilde (:obj:`bool`): When ``True`` use :func:`~pyhf.infer.test_statistics.qmu_tilde`
as the test statistic.
When ``False`` use :func:`~pyhf.infer.test_statistics.qmu`.

Keyword Args:
return_tail_probs (bool): Bool for returning :math:`\mathrm{CL}_{s+b}` and :math:`\mathrm{CL}_{b}`
return_expected (bool): Bool for returning :math:`\mathrm{CL}_{\mathrm{exp}}`
return_expected_set (bool): Bool for returning the :math:`(-2,-1,0,1,2)\sigma` :math:`\mathrm{CL}_{\mathrm{exp}}` --- the "Brazil band"
qtilde (:obj:`bool`): When ``True`` perform the calculation using the alternative
test statistic, :math:`\tilde{q}_{\mu}`, as defined under the Wald
approximation in Equation (62) of :xref:`arXiv:1007.1727`.
calctype (:obj:`str`): The calculator to create. Choose either 'asymptotics' (default) or 'toybased'.
return_tail_probs (:obj:`bool`): Bool for returning :math:`\mathrm{CL}_{s+b}` and :math:`\mathrm{CL}_{b}`
return_expected (:obj:`bool`): Bool for returning :math:`\mathrm{CL}_{\mathrm{exp}}`
return_expected_set (:obj:`bool`): Bool for returning the :math:`(-2,-1,0,1,2)\sigma` :math:`\mathrm{CL}_{\mathrm{exp}}` --- the "Brazil band"

Returns:
Tuple of Floats and lists of Floats:
Expand Down Expand Up @@ -127,9 +132,17 @@ def hypotest(
par_bounds = par_bounds or pdf.config.suggested_bounds()
fixed_params = fixed_params or pdf.config.suggested_fixed()

calc = AsymptoticCalculator(
data, pdf, init_pars, par_bounds, fixed_params, qtilde=qtilde
calc = utils.create_calculator(
calctype,
data,
pdf,
init_pars,
par_bounds,
fixed_params,
qtilde=qtilde,
**kwargs,
)

teststat = calc.teststatistic(poi_test)
sig_plus_bkg_distribution, b_only_distribution = calc.distributions(poi_test)

Expand All @@ -146,9 +159,9 @@ def hypotest(
)

_returns = [CLs]
if kwargs.get('return_tail_probs'):
if return_tail_probs:
_returns.append([CLsb, CLb])
if kwargs.get('return_expected_set'):
if return_expected_set:
CLs_exp = []
for n_sigma in [2, 1, 0, -1, -2]:

Expand All @@ -158,10 +171,10 @@ def hypotest(
expected_bonly_teststat
) / b_only_distribution.pvalue(expected_bonly_teststat)
CLs_exp.append(tensorlib.astensor(CLs))
if kwargs.get('return_expected'):
if return_expected:
_returns.append(CLs_exp[2])
_returns.append(CLs_exp)
elif kwargs.get('return_expected'):
elif return_expected:
n_sigma = 0
expected_bonly_teststat = b_only_distribution.expected_value(n_sigma)

Expand Down
Loading