Repository: scikit-hep/pyhf

Issue:
API: change CLs to be scalar
# Description

right now it's returning (1,) vectors



Discussion:

Resolving patch:
diff --git a/src/pyhf/cli/infer.py b/src/pyhf/cli/infer.py
--- a/src/pyhf/cli/infer.py
+++ b/src/pyhf/cli/infer.py
@@ -107,8 +107,8 @@ def cls(
         testpoi, ws.data(model), model, qtilde=is_qtilde, return_expected_set=True
     )
     result = {
-        'CLs_obs': tensorlib.tolist(result[0])[0],
-        'CLs_exp': tensorlib.tolist(tensorlib.reshape(result[-1], [-1])),
+        'CLs_obs': tensorlib.tolist(result[0]),
+        'CLs_exp': [tensorlib.tolist(tensor) for tensor in result[-1]],
     }
 
     if output_file is None:
diff --git a/src/pyhf/infer/__init__.py b/src/pyhf/infer/__init__.py
--- a/src/pyhf/infer/__init__.py
+++ b/src/pyhf/infer/__init__.py
@@ -23,14 +23,10 @@ def hypotest(
         >>> CLs_obs, CLs_exp_band = pyhf.infer.hypotest(
         ...     test_poi, data, model, qtilde=True, return_expected_set=True
         ... )
-        >>> print(CLs_obs)
-        [0.05251554]
-        >>> print(CLs_exp_band)
-        [[0.00260641]
-         [0.01382066]
-         [0.06445521]
-         [0.23526104]
-         [0.57304182]]
+        >>> CLs_obs
+        array(0.05251554)
+        >>> CLs_exp_band
+        [array(0.00260641), array(0.01382066), array(0.06445521), array(0.23526104), array(0.57304182)]
 
     Args:
         poi_test (Number or Tensor): The value of the parameter of interest (POI)
@@ -102,10 +98,11 @@ def hypotest(
     CLsb = sig_plus_bkg_distribution.pvalue(teststat)
     CLb = b_only_distribution.pvalue(teststat)
     CLs = CLsb / CLb
+    # Ensure that all CL values are 0-d tensors
     CLsb, CLb, CLs = (
-        tensorlib.reshape(CLsb, (1,)),
-        tensorlib.reshape(CLb, (1,)),
-        tensorlib.reshape(CLs, (1,)),
+        tensorlib.astensor(CLsb),
+        tensorlib.astensor(CLb),
+        tensorlib.astensor(CLs),
     )
 
     _returns = [CLs]
@@ -120,8 +117,7 @@ def hypotest(
             CLs = sig_plus_bkg_distribution.pvalue(
                 expected_bonly_teststat
             ) / b_only_distribution.pvalue(expected_bonly_teststat)
-            CLs_exp.append(tensorlib.reshape(CLs, (1,)))
-        CLs_exp = tensorlib.astensor(CLs_exp)
+            CLs_exp.append(tensorlib.astensor(CLs))
         if kwargs.get('return_expected'):
             _returns.append(CLs_exp[2])
         _returns.append(CLs_exp)
@@ -132,7 +128,7 @@ def hypotest(
         CLs = sig_plus_bkg_distribution.pvalue(
             expected_bonly_teststat
         ) / b_only_distribution.pvalue(expected_bonly_teststat)
-        _returns.append(tensorlib.reshape(CLs, (1,)))
+        _returns.append(tensorlib.astensor(CLs))
     # Enforce a consistent return type of the observed CLs
     return tuple(_returns) if len(_returns) > 1 else _returns[0]
 


Test patch:
diff --git a/tests/test_infer.py b/tests/test_infer.py
--- a/tests/test_infer.py
+++ b/tests/test_infer.py
@@ -59,7 +59,7 @@ def test_hypotest_default(tmpdir, hypotest_args):
     kwargs = {}
     result = pyhf.infer.hypotest(*hypotest_args, **kwargs)
     # CLs_obs
-    assert len(list(result)) == 1
+    assert pyhf.tensorlib.shape(result) == ()
     assert isinstance(result, type(tb.astensor(result)))
 
 
@@ -178,7 +178,7 @@ def logpdf(self, pars, data):
         1.0, model.expected_data(model.config.suggested_init()), model
     )
 
-    assert np.isclose(cls[0], 0.7267836451638846)
+    assert np.isclose(cls, 0.7267836451638846)
 
 
 @pytest.mark.parametrize("qtilde", [True, False])
diff --git a/tests/test_regression.py b/tests/test_regression.py
--- a/tests/test_regression.py
+++ b/tests/test_regression.py
@@ -28,7 +28,7 @@ def calculate_CLs(bkgonly_json, signal_patch_json):
     result = pyhf.infer.hypotest(
         1.0, workspace.data(model), model, qtilde=True, return_expected_set=True
     )
-    return result[0].tolist()[0], result[-1].ravel().tolist()
+    return result[0].tolist(), result[-1]
 
 
 def test_sbottom_regionA_1300_205_60(
diff --git a/tests/test_validation.py b/tests/test_validation.py
--- a/tests/test_validation.py
+++ b/tests/test_validation.py
@@ -906,16 +906,16 @@ def test_shapesys_nuisparfilter_validation():
         "observations": [{"data": [100, 10], "name": "channel1"}],
         "version": "1.0.0",
     }
-    w = pyhf.Workspace(spec)
-    m = w.model(
+    ws = pyhf.Workspace(spec)
+    model = ws.model(
         modifier_settings={
             'normsys': {'interpcode': 'code4'},
             'histosys': {'interpcode': 'code4p'},
         },
     )
-    d = w.data(m)
-    obs, exp = pyhf.infer.hypotest(1.0, d, m, return_expected_set=True)
-    pyhf_results = {'CLs_obs': obs[0], 'CLs_exp': [e[0] for e in exp]}
+    data = ws.data(model)
+    obs, exp = pyhf.infer.hypotest(1.0, data, model, return_expected_set=True)
+    pyhf_results = {'CLs_obs': obs, 'CLs_exp': [e for e in exp]}
 
     assert np.allclose(
         reference_root_results['CLs_obs'], pyhf_results['CLs_obs'], atol=1e-4, rtol=1e-5