Skip to content

Commit

Permalink
feat: Promote modifications to public API (#2339)
Browse files Browse the repository at this point in the history
* Promote `pyhf.pdf._MainModel._modifications` to `pyhf.pdf._MainModel.modifications`.
* Promote `pyhf.pdf.Model._modifications` to `pyhf.pdf.Model.modifications`.
* Add `pyhf.pdf._MainModel` and `pyhf.pdf._ConstraintModel` to the docs.
* Add documentation for the `modifications()` functions.
  • Loading branch information
kratsg authored Sep 21, 2023
1 parent c096b33 commit ae29d4b
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 9 deletions.
2 changes: 2 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Making Models from PDFs

~pdf.Model
~pdf._ModelConfig
~pdf._MainModel
~pdf._ConstraintModel
~mixins._ChannelSummaryMixin
~workspace.Workspace
~patchset.PatchSet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@
"outputs": [],
"source": [
"def get_mc_counts(pars):\n",
" deltas, factors = pdf._modifications(pars)\n",
" deltas, factors = pdf.modifications(pars)\n",
" allsum = pyhf.tensorlib.concatenate(\n",
" deltas + [pyhf.tensorlib.astensor(pdf.nominal_rates)]\n",
" )\n",
Expand Down
26 changes: 22 additions & 4 deletions src/pyhf/pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,21 @@ def logpdf(self, maindata, pars):
"""
return self.make_pdf(pars).log_prob(maindata)

def _modifications(self, pars):
def modifications(self, pars):
"""
Obtain the additive and multiplicative modifications to the expected
event rates for the model parameters.
Args:
pars (:obj:`tensor`): The model parameters
Returns:
Tuple of additive and multiplicative modifications:
- deltas (:obj:`list`) is the result of an ``apply(pars)`` of combined modifiers
with ``"addition"`` ``op_code``
- factors (:obj:`list`) is the result of ``apply(pars)`` of combined modifiers
with ``"multiplication"`` ``op_code``
"""
deltas = list(
filter(
lambda x: x is not None,
Expand Down Expand Up @@ -695,7 +709,7 @@ def expected_data(self, pars, return_by_sample=False):
"""
tensorlib, _ = get_backend()
pars = tensorlib.astensor(pars)
deltas, factors = self._modifications(pars)
deltas, factors = self.modifications(pars)

allsum = tensorlib.concatenate(deltas + [self.nominal_rates])

Expand Down Expand Up @@ -826,8 +840,12 @@ def expected_auxdata(self, pars):
pars = tensorlib.astensor(pars)
return self.make_pdf(pars)[1].expected_data()

def _modifications(self, pars):
return self.main_model._modifications(pars)
def modifications(self, pars):
"""
The modifications applied to the :class:`~pyhf.pdf._MainModel`. See
:func:`pyhf.pdf._MainModel.modifications` for details.
"""
return self.main_model.modifications(pars)

@property
def nominal_rates(self):
Expand Down
4 changes: 2 additions & 2 deletions tests/test_modifiers.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def test_staterror_holes():

model = pyhf.Model(spec, poi_name="")
assert model.config.npars == 9
_, factors = model._modifications(
_, factors = model.modifications(
pyhf.tensorlib.astensor([2, 2.0, 1.0, 1.0, 3.0, 4.0, 1.0, 5.0, 6.0])
)
assert model.config.param_set("staterror_1").suggested_fixed == [
Expand Down Expand Up @@ -151,7 +151,7 @@ def test_shapesys_holes():
}

model = pyhf.Model(spec, poi_name="mu")
_, factors = model._modifications(
_, factors = model.modifications(
pyhf.tensorlib.astensor([1.0, 2.0, 1.0, 1.0, 3.0, 4.0, 1.0, 1.0, 5.0])
)
assert (factors[1][0, 0, 0, :] == [2.0, 1.0, 1.0, 3.0, 1.0, 1.0, 1.0, 1.0]).all()
Expand Down
4 changes: 2 additions & 2 deletions tests/test_pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,7 @@ def test_lumi_np_scaling():
[[[1.0, 1.0]]],
[[[1.0, 1.0]]],
]
assert pdf._modifications(np.array(pars))[1][0].tolist() == [mods]
assert pdf.modifications(np.array(pars))[1][0].tolist() == [mods]
assert pdf.expected_data(pars).tolist() == [120.0, 110.0, 1.0]

pars[poi_slice], pars[lumi_slice] = [[1.0], [alpha_lumi]]
Expand All @@ -763,7 +763,7 @@ def test_lumi_np_scaling():
[[[1.0, 1.0]]],
[[[alpha_lumi, alpha_lumi]]],
]
assert pdf._modifications(np.array(pars))[1][0].tolist() == [mods]
assert pdf.modifications(np.array(pars))[1][0].tolist() == [mods]
assert pytest.approx(pdf.expected_data(pars).tolist()) == [
100 + 20.0 * alpha_lumi,
110.0 * alpha_lumi,
Expand Down

0 comments on commit ae29d4b

Please sign in to comment.