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

Rename 'norm_range' to 'norm' and fix argus integration #95

Merged
merged 1 commit into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
39 changes: 27 additions & 12 deletions src/zfit_physics/models/pdf_argus.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def __init__(
\mathrm{Argus}(m, m_0, c, p) = m \cdot \left[ 1 - \left( \frac{m}{m_0} \right)^2 \right]^p
\cdot \exp\left[ c \cdot \left(1 - \left(\frac{m}{m_0}\right)^2 \right) \right]

and normalized to one over the `norm_range` (which defaults to `obs`).
and normalized to one over the `norm` (which defaults to `obs`).

The implementation follows the `RooFit version <https://root.cern.ch/doc/master/classRooArgusBG.html>`_

Expand Down Expand Up @@ -114,19 +114,36 @@ def __init__(
Returns:
`tf.Tensor`: the values matching the (broadcasted) shapes of the input
"""

params = {"m0": m0, "c": c, "p": p}
super().__init__(obs=obs, name=name, params=params, extended=extended, norm=norm, label=label)

_N_OBS = 1

@zfit.supports()
def _unnormalized_pdf(self, x, params):
if isinstance(p, zfit.param.ConstantParameter):
p_is_half = np.isclose(p.static_value, 0.5)
else:
try:
p_is_half = np.isclose(p, 0.5)
except NotImplementedError:
p_is_half = False # we cannot know, unfortunately

if isinstance(c, zfit.param.ConstantParameter):
c_is_negative = c.static_value < 0
else:
try:
c_is_negative = c < 0
except NotImplementedError:
c_is_negative = False

self._argus_p_is_half = p_is_half
self._argus_c_is_positive = c_is_negative

@zfit.supports(norm=False)
def _pdf(self, x, norm, params):
"""
Calculation of ARGUS PDF value
(Docs: https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.argus.html)
"""
m = x[0]

del norm
m0 = params["m0"]
c = params["c"]
p = params["p"]
Expand Down Expand Up @@ -191,12 +208,10 @@ def argus_integral_p_half_func(lower, upper, c, m0):


def argus_integral_p_half(limits, params, model):
del model
p = params["p"]
if not isinstance(p, zfit.param.ConstantParameter) or not np.isclose(p.static_value, 0.5):
raise zfit.exception.AnalyticIntegralNotImplementedError()
c = params["c"]
if not isinstance(c, zfit.param.ConstantParameter) or c.static_value > 0:
if not model._argus_p_is_half:
raise zfit.exception.AnalyticIntegralNotImplementedError()
if not model._argus_c_is_positive:
raise zfit.exception.AnalyticIntegralNotImplementedError()

m0 = params["m0"]
Expand Down
2 changes: 1 addition & 1 deletion src/zfit_physics/models/pdf_kde.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,5 @@ def dist_kwargs():
)

# @zfit.supports()
# def _analytic_integrate(self, limits, norm_range):
# def _analytic_integrate(self, limits, norm):
# raise AnalyticIntegralNotImplementedError
6 changes: 3 additions & 3 deletions tests/test_pdf_argus.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
param2_true = 1.2


def test_standard():
def test_standard_argus():
# test special properties here
obs = zfit.Space("obs1", (-2, 6))

Expand All @@ -24,8 +24,8 @@ def test_standard():
upper = 5.0
argus_pdf = argus.pdf(tf.linspace(lower, upper, 1000001))
assert pytest.approx(zfit.run(tf.reduce_mean(argus_pdf) * (upper - lower)), 4e-2) == 1.0
analytic_integral = zfit.run(argus.analytic_integrate(obs, norm_range=False))
numeric_integral = zfit.run(argus.numeric_integrate(obs, norm_range=False))
analytic_integral = zfit.run(argus.analytic_integrate(obs, norm=False))
numeric_integral = zfit.run(argus.numeric_integrate(obs, norm=False))
assert pytest.approx(analytic_integral, 4e-2) == numeric_integral


Expand Down
8 changes: 4 additions & 4 deletions tests/test_pdf_cmsshape.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ def test_cmsshape_pdf():
def test_cmsshape_integral():
# Test CDF and integral here
cmsshape, obs = create_cmsshape(m=m_true, beta=beta_true, gamma=gamma_true, limits=(50, 130))
full_interval_analytic = zfit.run(cmsshape.analytic_integrate(obs, norm_range=False))
full_interval_numeric = zfit.run(cmsshape.numeric_integrate(obs, norm_range=False))
full_interval_analytic = zfit.run(cmsshape.analytic_integrate(obs, norm=False))
full_interval_numeric = zfit.run(cmsshape.numeric_integrate(obs, norm=False))
true_integral = 0.99999
numba_stats_full_integral = cmsshape_numba.cdf(
130, beta=beta_true, gamma=gamma_true, loc=m_true
Expand All @@ -55,8 +55,8 @@ def test_cmsshape_integral():
assert full_interval_analytic == pytest.approx(numba_stats_full_integral, 1e-8)
assert full_interval_numeric == pytest.approx(numba_stats_full_integral, 1e-8)

analytic_integral = zfit.run(cmsshape.analytic_integrate(limits=(80, 100), norm_range=False))
numeric_integral = zfit.run(cmsshape.numeric_integrate(limits=(80, 100), norm_range=False))
analytic_integral = zfit.run(cmsshape.analytic_integrate(limits=(80, 100), norm=False))
numeric_integral = zfit.run(cmsshape.numeric_integrate(limits=(80, 100), norm=False))
numba_stats_integral = cmsshape_numba.cdf(100, beta=beta_true, gamma=gamma_true, loc=m_true) - cmsshape_numba.cdf(
80, beta=beta_true, gamma=gamma_true, loc=m_true
)
Expand Down
8 changes: 4 additions & 4 deletions tests/test_pdf_relbw.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ def test_relbw_pdf():
def test_relbw_integral():
# Test CDF and integral here
relbw, obs = create_relbw(m_true, gamma_true, limits=(0, 200))
full_interval_analytic = zfit.run(relbw.analytic_integrate(obs, norm_range=False))
full_interval_numeric = zfit.run(relbw.numeric_integrate(obs, norm_range=False))
full_interval_analytic = zfit.run(relbw.analytic_integrate(obs, norm=False))
full_interval_numeric = zfit.run(relbw.numeric_integrate(obs, norm=False))
true_integral = 0.99888
assert full_interval_analytic == pytest.approx(true_integral, 1e-4)
assert full_interval_numeric == pytest.approx(true_integral, 1e-2)

analytic_integral = zfit.run(relbw.analytic_integrate(limits=(50, 100), norm_range=False))
numeric_integral = zfit.run(relbw.numeric_integrate(limits=(50, 100), norm_range=False))
analytic_integral = zfit.run(relbw.analytic_integrate(limits=(50, 100), norm=False))
numeric_integral = zfit.run(relbw.numeric_integrate(limits=(50, 100), norm=False))
assert analytic_integral == pytest.approx(numeric_integral, 0.01)


Expand Down
Loading