diff --git a/src/cabinetry/workspace.py b/src/cabinetry/workspace.py index e6729ec4..8521c5e8 100644 --- a/src/cabinetry/workspace.py +++ b/src/cabinetry/workspace.py @@ -126,7 +126,9 @@ def normplusshape_modifiers( provides the `histosys` and `normsys` modifiers for ``pyhf`` (in `HistFactory` language, this corresponds to a `HistoSys` and an `OverallSys`). Symmetrization could happen either at this stage (this is the case currently), or somewhere - earlier, such as during template postprocessing. + earlier, such as during template postprocessing. A `histosys` modifier is not + created for single-bin channels, as it has no effect in this case (everything is + handled by the `normsys` modifier already). Args: region (Dict[str, Any]): region the systematic variation acts in @@ -200,13 +202,15 @@ def normplusshape_modifiers( modifiers.append(norm_modifier) # add the shape part in a histosys - shape_modifier = {} - shape_modifier.update({"name": modifier_name}) - shape_modifier.update({"type": "histosys"}) - shape_modifier.update( - {"data": {"hi_data": histo_yield_up, "lo_data": histo_yield_down}} - ) - modifiers.append(shape_modifier) + if len(histogram_nominal.yields) > 1: + # only relevant if there is more than one bin, otherwise there is no "shape" + shape_modifier = {} + shape_modifier.update({"name": modifier_name}) + shape_modifier.update({"type": "histosys"}) + shape_modifier.update( + {"data": {"hi_data": histo_yield_up, "lo_data": histo_yield_down}} + ) + modifiers.append(shape_modifier) return modifiers def sys_modifiers( diff --git a/tests/test_workspace.py b/tests/test_workspace.py index 8cfa0af1..f4902d5e 100644 --- a/tests/test_workspace.py +++ b/tests/test_workspace.py @@ -136,6 +136,9 @@ def test_WorkspaceBuilder_normalization_modifier(): # for test of symmetrization: up and nominal histo.Histogram.from_arrays([0, 1, 2], [26.0, 24.0], [0.1, 0.1]), histo.Histogram.from_arrays([0, 1, 2], [20.0, 20.0], [0.1, 0.1]), + # single bin for test of histosys being skipped (up and nominal) + histo.Histogram.from_arrays([0, 1], [26.0], [0.1]), + histo.Histogram.from_arrays([0, 1], [20.0], [0.1]), ], ) def test_WorkspaceBuilder_normplusshape_modifiers(mock_histogram): @@ -194,6 +197,12 @@ def test_WorkspaceBuilder_normplusshape_modifiers(mock_histogram): ((pathlib.Path("path"), region, sample, {}), {"modified": True}), ] + # single bin, causing histosys being skipped + modifiers = ws_builder.normplusshape_modifiers(region, sample, systematic) + assert modifiers == [ + {"name": "mod_name", "type": "normsys", "data": {"hi": 1.3, "lo": 0.7}}, + ] + @mock.patch( "cabinetry.workspace.WorkspaceBuilder.normplusshape_modifiers",