diff --git a/src/zfit_physics/models/pdf_argus.py b/src/zfit_physics/models/pdf_argus.py index d2b00cb..dfdb68b 100644 --- a/src/zfit_physics/models/pdf_argus.py +++ b/src/zfit_physics/models/pdf_argus.py @@ -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 `_ @@ -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"] @@ -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"] diff --git a/src/zfit_physics/models/pdf_kde.py b/src/zfit_physics/models/pdf_kde.py index ebb26eb..63ba105 100644 --- a/src/zfit_physics/models/pdf_kde.py +++ b/src/zfit_physics/models/pdf_kde.py @@ -118,5 +118,5 @@ def dist_kwargs(): ) # @zfit.supports() - # def _analytic_integrate(self, limits, norm_range): + # def _analytic_integrate(self, limits, norm): # raise AnalyticIntegralNotImplementedError diff --git a/tests/test_pdf_argus.py b/tests/test_pdf_argus.py index f07a230..7b31abd 100644 --- a/tests/test_pdf_argus.py +++ b/tests/test_pdf_argus.py @@ -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)) @@ -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 diff --git a/tests/test_pdf_cmsshape.py b/tests/test_pdf_cmsshape.py index 4ae1cf5..b085dac 100644 --- a/tests/test_pdf_cmsshape.py +++ b/tests/test_pdf_cmsshape.py @@ -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 @@ -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 ) diff --git a/tests/test_pdf_relbw.py b/tests/test_pdf_relbw.py index 8007422..fbdf877 100644 --- a/tests/test_pdf_relbw.py +++ b/tests/test_pdf_relbw.py @@ -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)