Repository: scikit-hep/pyhf

Issue:
Default POI name for model construction
The current default for the POI name in model construction is `"mu"`. The safer choice here would be to go with `""`, i.e. no POI specified. This reduces the assumptions being made and is not going to cause failures for models where no "mu" parameter is defined. I would suggest updating the default accordingly.

https://github.com/scikit-hep/pyhf/blob/f771581ae387493776f2c40170f82b63d0fad317/src/pyhf/pdf.py#L771


Discussion:

Resolving patch:
diff --git a/src/pyhf/pdf.py b/src/pyhf/pdf.py
--- a/src/pyhf/pdf.py
+++ b/src/pyhf/pdf.py
@@ -768,7 +768,9 @@ def __init__(
             log.info(f"Validating spec against schema: {self.schema:s}")
             schema.validate(self.spec, self.schema, version=self.version)
         # build up our representation of the specification
-        poi_name = config_kwargs.pop('poi_name', 'mu')
+        # Default to no POI name
+        # https://github.com/scikit-hep/pyhf/issues/2327
+        poi_name = config_kwargs.pop("poi_name", None)
         self._config = _ModelConfig(self.spec, **config_kwargs)
 
         modifiers, _nominal_rates = _nominal_and_modifiers_from_spec(
diff --git a/src/pyhf/simplemodels.py b/src/pyhf/simplemodels.py
--- a/src/pyhf/simplemodels.py
+++ b/src/pyhf/simplemodels.py
@@ -10,7 +10,7 @@ def __dir__():
 
 
 def correlated_background(
-    signal, bkg, bkg_up, bkg_down, batch_size=None, validate=True
+    signal, bkg, bkg_up, bkg_down, batch_size=None, validate=True, poi_name="mu"
 ):
     r"""
     Construct a simple single channel :class:`~pyhf.pdf.Model` with a
@@ -27,10 +27,14 @@ def correlated_background(
         batch_size (:obj:`None` or :obj:`int`): Number of simultaneous (batched) Models to compute.
         validate (:obj:`bool`): If :obj:`True`, validate the model before returning.
          Only set this to :obj:`False` if you have an experimental use case and know what you're doing.
+        poi_name (:obj:`str`): The :class:`~pyhf.pdf.Model` parameter of interest name.
+          Defaults to ``"mu"``.
 
     Returns:
         ~pyhf.pdf.Model: The statistical model adhering to the :obj:`model.json` schema.
 
+    .. versionchanged:: 0.8.0 Added ``poi_name`` argument.
+
     Example:
         >>> import pyhf
         >>> pyhf.set_backend("numpy")
@@ -79,11 +83,11 @@ def correlated_background(
             }
         ]
     }
-    return Model(spec, batch_size=batch_size, validate=validate)
+    return Model(spec, batch_size=batch_size, validate=validate, poi_name=poi_name)
 
 
 def uncorrelated_background(
-    signal, bkg, bkg_uncertainty, batch_size=None, validate=True
+    signal, bkg, bkg_uncertainty, batch_size=None, validate=True, poi_name="mu"
 ):
     """
     Construct a simple single channel :class:`~pyhf.pdf.Model` with a
@@ -114,10 +118,13 @@ def uncorrelated_background(
         batch_size (:obj:`None` or :obj:`int`): Number of simultaneous (batched) Models to compute
         validate (:obj:`bool`): If :obj:`True`, validate the model before returning.
          Only set this to :obj:`False` if you have an experimental use case and know what you're doing.
+        poi_name (:obj:`str`): The :class:`~pyhf.pdf.Model` parameter of interest name.
+          Defaults to ``"mu"``.
 
     Returns:
         ~pyhf.pdf.Model: The statistical model adhering to the :obj:`model.json` schema
 
+    .. versionchanged:: 0.8.0 Added ``poi_name`` argument.
     """
     spec = {
         'channels': [
@@ -146,7 +153,7 @@ def uncorrelated_background(
             }
         ]
     }
-    return Model(spec, batch_size=batch_size, validate=validate)
+    return Model(spec, batch_size=batch_size, validate=validate, poi_name=poi_name)
 
 
 # Deprecated APIs


Test patch:
diff --git a/tests/test_backend_consistency.py b/tests/test_backend_consistency.py
--- a/tests/test_backend_consistency.py
+++ b/tests/test_backend_consistency.py
@@ -99,7 +99,7 @@ def test_hypotest_qmu_tilde(
         else [signal_sample, background_sample]
     )
     spec = {'channels': [{'name': 'singlechannel', 'samples': samples}]}
-    pdf = pyhf.Model(spec)
+    pdf = pyhf.Model(spec, poi_name="mu")
 
     data = source['bindata']['data'] + pdf.config.auxdata
 
diff --git a/tests/test_optim.py b/tests/test_optim.py
--- a/tests/test_optim.py
+++ b/tests/test_optim.py
@@ -312,7 +312,7 @@ def spec(source):
 
 @pytest.mark.parametrize('mu', [1.0], ids=['mu=1'])
 def test_optim(backend, source, spec, mu):
-    pdf = pyhf.Model(spec)
+    pdf = pyhf.Model(spec, poi_name="mu")
     data = source['bindata']['data'] + pdf.config.auxdata
 
     init_pars = pdf.config.suggested_init()
@@ -336,7 +336,7 @@ def test_optim(backend, source, spec, mu):
 
 @pytest.mark.parametrize('mu', [1.0], ids=['mu=1'])
 def test_optim_with_value(backend, source, spec, mu):
-    pdf = pyhf.Model(spec)
+    pdf = pyhf.Model(spec, poi_name="mu")
     data = source['bindata']['data'] + pdf.config.auxdata
 
     init_pars = pdf.config.suggested_init()
@@ -364,7 +364,7 @@ def test_optim_with_value(backend, source, spec, mu):
 @pytest.mark.parametrize('mu', [1.0], ids=['mu=1'])
 @pytest.mark.only_numpy_minuit
 def test_optim_uncerts(backend, source, spec, mu):
-    pdf = pyhf.Model(spec)
+    pdf = pyhf.Model(spec, poi_name="mu")
     data = source['bindata']['data'] + pdf.config.auxdata
 
     init_pars = pdf.config.suggested_init()
@@ -391,7 +391,7 @@ def test_optim_uncerts(backend, source, spec, mu):
 @pytest.mark.parametrize('mu', [1.0], ids=['mu=1'])
 @pytest.mark.only_numpy_minuit
 def test_optim_correlations(backend, source, spec, mu):
-    pdf = pyhf.Model(spec)
+    pdf = pyhf.Model(spec, poi_name="mu")
     data = source['bindata']['data'] + pdf.config.auxdata
 
     init_pars = pdf.config.suggested_init()
diff --git a/tests/test_validation.py b/tests/test_validation.py
--- a/tests/test_validation.py
+++ b/tests/test_validation.py
@@ -788,7 +788,9 @@ def test_validation(setup):
     source = setup['source']
 
     pdf = pyhf.Model(
-        setup['spec'], modifier_settings={'normsys': {'interpcode': 'code1'}}
+        setup["spec"],
+        modifier_settings={"normsys": {"interpcode": "code1"}},
+        poi_name="mu",
     )
 
     if 'channels' in source: