Repository: scikit-hep/pyhf

Issue:
Correlated background simplemodel
something like

```python
def simplemodel2(s,b_up,b_nom,b_dn):
    spec = {
        'channels': [
            {
                'name': 'singlechannel',
                'samples': [
                    {
                    'name': 'signal',
                    'data': s,
                    'modifiers': [{'name': 'mu', 'type': 'normfactor', 'data': None}]
                    },
                    {'name': 'background',
                    'data': b_nom,
                    'modifiers': [
                        {
                            'name': 'uncorr_bkguncrt',
                            'type': 'histosys',
                            'data': {
                                'hi_data': b_up,
                                'lo_data': b_dn
                            }
                        }
                        ]
                    }
                ]
            }
        ]
    }
    return pyhf.Model(spec)

```

with an API like `pyhf.simplemodels.correlated_bkg`


Discussion:
In a separate Issue and PR we should also revise the current `simplemodels` API and deprecate `hepdata_like` (for the next release and then remove it in 2 releases).

Resolving patch:
diff --git a/src/pyhf/simplemodels.py b/src/pyhf/simplemodels.py
--- a/src/pyhf/simplemodels.py
+++ b/src/pyhf/simplemodels.py
@@ -1,12 +1,81 @@
 from . import Model
 
-__all__ = ["hepdata_like"]
+__all__ = ["correlated_background", "hepdata_like"]
 
 
 def __dir__():
     return __all__
 
 
+def correlated_background(signal, bkg, bkg_up, bkg_down, batch_size=None):
+    r"""
+    Construct a simple single channel :class:`~pyhf.pdf.Model` with a
+    :class:`~pyhf.modifiers.histosys` modifier representing a background
+    with a fully correlated bin-by-bin uncertainty.
+
+    Args:
+        signal (:obj:`list`): The data in the signal sample.
+        bkg (:obj:`list`): The data in the background sample.
+        bkg_up (:obj:`list`): The background sample under an upward variation
+         corresponding to :math:`\alpha=+1`.
+        bkg_down (:obj:`list`): The background sample under a downward variation
+         corresponding to :math:`\alpha=-1`.
+        batch_size (:obj:`None` or :obj:`int`): Number of simultaneous (batched) Models to compute.
+
+    Returns:
+        ~pyhf.pdf.Model: The statistical model adhering to the :obj:`model.json` schema.
+
+    Example:
+        >>> import pyhf
+        >>> pyhf.set_backend("numpy")
+        >>> model = pyhf.simplemodels.correlated_background(
+        ...     signal=[12.0, 11.0],
+        ...     bkg=[50.0, 52.0],
+        ...     bkg_up=[45.0, 57.0],
+        ...     bkg_down=[55.0, 47.0],
+        ... )
+        >>> model.schema
+        'model.json'
+        >>> model.config.channels
+        ['single_channel']
+        >>> model.config.samples
+        ['background', 'signal']
+        >>> model.config.parameters
+        ['correlated_bkg_uncertainty', 'mu']
+        >>> model.expected_data(model.config.suggested_init())
+        array([62., 63.,  0.])
+
+    """
+    spec = {
+        "channels": [
+            {
+                "name": "single_channel",
+                "samples": [
+                    {
+                        "name": "signal",
+                        "data": signal,
+                        "modifiers": [
+                            {"name": "mu", "type": "normfactor", "data": None}
+                        ],
+                    },
+                    {
+                        "name": "background",
+                        "data": bkg,
+                        "modifiers": [
+                            {
+                                "name": "correlated_bkg_uncertainty",
+                                "type": "histosys",
+                                "data": {"hi_data": bkg_up, "lo_data": bkg_down},
+                            }
+                        ],
+                    },
+                ],
+            }
+        ]
+    }
+    return Model(spec, batch_size=batch_size)
+
+
 def hepdata_like(signal_data, bkg_data, bkg_uncerts, batch_size=None):
     """
     Construct a simple single channel :class:`~pyhf.pdf.Model` with a


Test patch:
diff --git a/tests/test_public_api_repr.py b/tests/test_public_api_repr.py
--- a/tests/test_public_api_repr.py
+++ b/tests/test_public_api_repr.py
@@ -220,7 +220,7 @@ def test_readxml_public_api():
 
 
 def test_simplemodels_public_api():
-    assert dir(pyhf.simplemodels) == ["hepdata_like"]
+    assert dir(pyhf.simplemodels) == ["correlated_background", "hepdata_like"]
 
 
 def test_utils_public_api():
diff --git a/tests/test_simplemodels.py b/tests/test_simplemodels.py
new file mode 100644
--- /dev/null
+++ b/tests/test_simplemodels.py
@@ -0,0 +1,24 @@
+import pyhf
+
+
+def test_correlated_background():
+    model = pyhf.simplemodels.correlated_background(
+        signal=[12.0, 11.0],
+        bkg=[50.0, 52.0],
+        bkg_up=[45.0, 57.0],
+        bkg_down=[55.0, 47.0],
+    )
+    assert model.config.channels == ["single_channel"]
+    assert model.config.samples == ["background", "signal"]
+    assert model.config.par_order == ["mu", "correlated_bkg_uncertainty"]
+    assert model.config.suggested_init() == [1.0, 0.0]
+
+
+def test_uncorrelated_background():
+    model = pyhf.simplemodels.hepdata_like(
+        signal_data=[12.0, 11.0], bkg_data=[50.0, 52.0], bkg_uncerts=[3.0, 7.0]
+    )
+    assert model.config.channels == ["singlechannel"]
+    assert model.config.samples == ["background", "signal"]
+    assert model.config.par_order == ["mu", "uncorr_bkguncrt"]
+    assert model.config.suggested_init() == [1.0, 1.0, 1.0]