Repository: scikit-hep/pyhf

Issue:
Model.expected_auxdata and expected_actualdata miss tensorlib conversion
# Description

Both `Model.expected_auxdata` and `Model.expected_actualdata` do not include the same `pars = tensorlib.astensor(pars)` conversion that `Model.expected_data` uses. This results in runtime issues:

```
import pyhf

model = pyhf.simplemodels.hepdata_like(
    signal_data=[12.0, 11.0], bkg_data=[50.0, 52.0], bkg_uncerts=[3.0, 7.0]
)

model.expected_data(model.config.suggested_init())
model.expected_actualdata(model.config.suggested_init())
model.expected_auxdata(model.config.suggested_init())
```
output:
```
Traceback (most recent call last):
  File "ex.py", line 8, in <module>
    model.expected_actualdata(model.config.suggested_init())
  File "[...]/pyhf/src/pyhf/pdf.py", line 631, in expected_actualdata
    return self.make_pdf(pars)[0].expected_data()
  File "[...]/pyhf/src/pyhf/pdf.py", line 692, in make_pdf
    mainpdf = self.main_model.make_pdf(pars)
  File "[...]/pyhf/src/pyhf/pdf.py", line 456, in make_pdf
    lambdas_data = self._expected_data(pars)
  File "[...]/pyhf/src/pyhf/pdf.py", line 517, in _expected_data
    deltas, factors = self._modifications(pars)
  File "[...]/pyhf/src/pyhf/pdf.py", line 483, in _modifications
    [self.modifiers_appliers[k].apply(pars) for k in self._factor_mods],
  File "[...]/pyhf/src/pyhf/pdf.py", line 483, in <listcomp>
    [self.modifiers_appliers[k].apply(pars) for k in self._factor_mods],
  File "[...]/pyhf/src/pyhf/modifiers/shapesys.py", line 169, in apply
    shapefactors = tensorlib.gather(flat_pars, self.access_field)
  File "[...]/pyhf/src/pyhf/tensor/numpy_backend.py", line 136, in gather
    return tensor[indices]
TypeError: only integer scalar arrays can be converted to a scalar index
```
Similar for `expected_auxdata`.

I'm happy to submit a small PR to fix this, unless those functions are going to be deprecated (since at least `expected_actualdata` can alternatively be obtained via `model.expected_data, include_auxdata=False)`).

# Expected Behavior

No crash, but successful return of aux / actual data.

# Actual Behavior

code crashes

# Steps to Reproduce

pyhf 0.5.1, see example code above

# Checklist

- [ ] Run `git fetch` to get the most up to date version of `master`
- [ ] Searched through existing Issues to confirm this is not a duplicate issue
- [ ] Filled out the Description, Expected Behavior, Actual Behavior, and Steps to Reproduce sections above or have edited/removed them in a way that fully describes the issue



Discussion:
@alexander-held The short term mitigation of this (as I assume you need this now) is to give the suggested init values as a tensor

```python
>>> import pyhf
>>> pyhf.set_backend("numpy")
>>> model = pyhf.simplemodels.hepdata_like(
...     signal_data=[12.0, 11.0], bkg_data=[50.0, 52.0], bkg_uncerts=[3.0, 7.0]
... )
>>> model.expected_data(pyhf.tensorlib.astensor(model.config.suggested_init()))
array([ 62.        ,  63.        , 277.77777778,  55.18367347])
>>> model.expected_actualdata(pyhf.tensorlib.astensor(model.config.suggested_init()))
array([62., 63.])
>>> model.expected_auxdata(pyhf.tensorlib.astensor(model.config.suggested_init()))
array([277.77777778,  55.18367347])
```

but I agree that the API should be consistent and that the `Model` object should be able to interact with its own API returns without having to be wrapped as a tensor first.

> I'm happy to submit a small PR to fix this

PRs welcome! Thanks. :)

Resolving patch:
diff --git a/src/pyhf/pdf.py b/src/pyhf/pdf.py
--- a/src/pyhf/pdf.py
+++ b/src/pyhf/pdf.py
@@ -609,6 +609,8 @@ def expected_auxdata(self, pars):
             Tensor: The expected data of the auxiliary pdf
 
         """
+        tensorlib, _ = get_backend()
+        pars = tensorlib.astensor(pars)
         return self.make_pdf(pars)[1].expected_data()
 
     def _modifications(self, pars):
@@ -630,6 +632,8 @@ def expected_actualdata(self, pars):
             Tensor: The expected data of the main model (no auxiliary data)
 
         """
+        tensorlib, _ = get_backend()
+        pars = tensorlib.astensor(pars)
         return self.make_pdf(pars)[0].expected_data()
 
     def expected_data(self, pars, include_auxdata=True):


Test patch:
diff --git a/tests/test_pdf.py b/tests/test_pdf.py
--- a/tests/test_pdf.py
+++ b/tests/test_pdf.py
@@ -133,6 +133,13 @@ def test_pdf_basicapi_tests(backend):
         [60.0, 51.020408630], 1e-08
     )
 
+    assert tensorlib.tolist(pdf.expected_actualdata(pars)) == pytest.approx(
+        [60.0], 1e-08
+    )
+    assert tensorlib.tolist(pdf.expected_auxdata(pars)) == pytest.approx(
+        [51.020408630], 1e-08
+    )
+
     pdf = pyhf.simplemodels.hepdata_like(
         source['bindata']['sig'],
         source['bindata']['bkg'],