Пример #1
0
def test_WorkspaceBuilder_get_observations(mock_get_yield):
    # could mock _get_data_sample
    # create observations list from config
    example_config = {
        "General": {"HistogramFolder": "path"},
        "Samples": [{"Name": "data", "Data": True}],
        "Regions": [{"Name": "test_region"}],
    }
    ws_builder = workspace.WorkspaceBuilder(example_config)
    obs = ws_builder.get_observations()
    expected_obs = [{"name": "test_region", "data": [1.0, 2.0]}]
    assert obs == expected_obs
    assert mock_get_yield.call_args_list == [
        ((example_config["Regions"][0], example_config["Samples"][0]), {})
    ]

    mock_get_yield.call_args_list = []  # rest call arguments list

    # multiple channels
    multi_channel_config = {
        "General": {"HistogramFolder": "path"},
        "Samples": [{"Name": "data", "Data": True}],
        "Regions": [{"Name": "test_region"}, {"Name": "other_region"}],
    }
    ws_builder = workspace.WorkspaceBuilder(multi_channel_config)
    obs = ws_builder.get_observations()
    expected_obs = [
        {"name": "test_region", "data": [5.0]},
        {"name": "other_region", "data": [3.0]},
    ]
    assert obs == expected_obs
    assert mock_get_yield.call_args_list == [
        ((multi_channel_config["Regions"][0], multi_channel_config["Samples"][0]), {}),
        ((multi_channel_config["Regions"][1], multi_channel_config["Samples"][0]), {}),
    ]
Пример #2
0
def test_WorkspaceBuilder_get_yield_for_sample(mock_histogram):
    expected_yields = [1.0, 2.0]
    ws_builder = workspace.WorkspaceBuilder({"General": {"HistogramFolder": "path"}})
    yields = ws_builder.get_yield_for_sample({"Name": "region"}, {"Name": "signal"})
    assert yields == expected_yields

    # non-nominal
    yields_non_nominal = ws_builder.get_yield_for_sample(
        {"Name": "region"}, {"Name": "signal"}, systematic={"Name": "variation"}
    )
    assert yields_non_nominal == expected_yields

    assert mock_histogram.call_args_list == [
        (
            (
                pathlib.Path("path"),
                {"Name": "region"},
                {"Name": "signal"},
                {"Name": "Nominal"},
            ),
            {"modified": True},
        ),
        (
            (
                pathlib.Path("path"),
                {"Name": "region"},
                {"Name": "signal"},
                {"Name": "variation"},
            ),
            {"modified": True},
        ),
    ]
Пример #3
0
def test_WorkspaceBuilder_get_unc_for_sample(mock_histogram):
    expected_unc = [0.1, 0.1]
    ws_builder = workspace.WorkspaceBuilder({"General": {"HistogramFolder": "path"}})
    unc = ws_builder.get_unc_for_sample({"Name": "region"}, {"Name": "signal"})
    assert unc == expected_unc

    # non-nominal
    unc_non_nominal = ws_builder.get_unc_for_sample(
        {"Name": "region"}, {"Name": "signal"}, systematic={"Name": "variation"}
    )
    assert unc_non_nominal == expected_unc

    assert mock_histogram.call_args_list == [
        (
            (
                pathlib.Path("path"),
                {"Name": "region"},
                {"Name": "signal"},
                {"Name": "Nominal"},
            ),
            {"modified": True},
        ),
        (
            (
                pathlib.Path("path"),
                {"Name": "region"},
                {"Name": "signal"},
                {"Name": "variation"},
            ),
            {"modified": True},
        ),
    ]
Пример #4
0
def test_WorkspaceBuilder_get_sys_modifiers(mock_norm, mock_norm_shape):
    # could mock region_contains_modifier / sample_contains_modifier
    example_config = {
        "General": {"HistogramFolder": "path"},
        "Systematics": [
            {"Name": "norm", "Type": "Normalization"},
            {"Name": "norm_shape", "Type": "NormPlusShape"},
        ],
    }
    region = {"Name": "SR"}
    sample = {"Name": "Signal"}
    ws_builder = workspace.WorkspaceBuilder(example_config)
    assert ws_builder.get_sys_modifiers(region, sample) == [
        {"mock": "normsys"},
        {"mock": "norm"},
        {"mock": "shape"},
    ]
    assert mock_norm.call_args_list == [[(example_config["Systematics"][0],), {}]]
    assert mock_norm_shape.call_args_list == [
        [(region, sample, example_config["Systematics"][1]), {}]
    ]

    # one systematic not present in region
    example_config_region_mismatch = copy.deepcopy(example_config)
    example_config_region_mismatch["Systematics"][0].update({"Regions": "CR"})
    ws_builder = workspace.WorkspaceBuilder(example_config_region_mismatch)
    assert ws_builder.get_sys_modifiers(region, sample) == [
        {"mock": "norm"},
        {"mock": "shape"},
    ]

    # one systematic not present in sample
    example_config_sample_mismatch = copy.deepcopy(example_config)
    example_config_sample_mismatch["Systematics"][1].update({"Samples": "Background"})
    ws_builder = workspace.WorkspaceBuilder(example_config_sample_mismatch)
    assert ws_builder.get_sys_modifiers(region, sample) == [{"mock": "normsys"}]

    # unsupported systematics type
    example_config_unsupported = {
        "General": {"HistogramFolder": "path"},
        "Systematics": [{"Name": "Normalization", "Type": "unknown"}],
    }
    ws_builder = workspace.WorkspaceBuilder(example_config_unsupported)
    with pytest.raises(
        NotImplementedError, match="not supporting other systematic types yet"
    ):
        ws_builder.get_sys_modifiers(region, sample)
Пример #5
0
def test_WorkspaceBuilder__get_data_sample():
    mc_sample = {"Name": "MC"}
    data_sample = {"Name": "Data", "Data": True}

    example_config = {
        "General": {"HistogramFolder": "path"},
        "Samples": [mc_sample, data_sample],
    }
    ws_builder = workspace.WorkspaceBuilder(example_config)
    assert ws_builder._get_data_sample() == data_sample

    config_two_data_samples = {
        "General": {"HistogramFolder": "path"},
        "Samples": [data_sample, data_sample],
    }
    ws_builder = workspace.WorkspaceBuilder(config_two_data_samples)
    with pytest.raises(ValueError, match="did not find exactly one data sample"):
        ws_builder._get_data_sample()
Пример #6
0
def test_WorkspaceBuilder_get_NormPlusShape_modifiers(mock_histogram):
    # could mock Histogram.normalize_to_yield
    # up: 26, 24 (1.25*nom)
    # nominal: 20, 20
    # down: 8, 12 (0.5*nom)
    example_config = {"General": {"HistogramFolder": "path"}}
    ws_builder = workspace.WorkspaceBuilder(example_config)
    region = {"Name": "SR"}
    sample = {"Name": "Signal"}
    systematic = {"Name": "sys", "Up": {}, "Down": {}}
    # no symmetrization
    modifiers = ws_builder.get_NormPlusShape_modifiers(region, sample, systematic)
    assert modifiers == [
        {"name": "sys", "type": "normsys", "data": {"hi": 1.25, "lo": 0.5}},
        {
            "name": "sys",
            "type": "histosys",
            "data": {"hi_data": [20.8, 19.2], "lo_data": [16.0, 24.0]},
        },
    ]
    assert mock_histogram.call_args_list == [
        (
            (pathlib.Path("path"), region, sample, systematic),
            {"modified": True, "template": "Up"},
        ),
        (
            (pathlib.Path("path"), region, sample, {"Name": "Nominal"}),
            {"modified": True},
        ),
        (
            (pathlib.Path("path"), region, sample, systematic),
            {"modified": True, "template": "Down"},
        ),
    ]

    # down template via symmetrized up template
    systematic = {"Name": "sys", "Up": {}, "Down": {"Symmetrize": True}}
    modifiers = ws_builder.get_NormPlusShape_modifiers(region, sample, systematic)
    assert modifiers == [
        {"name": "sys", "type": "normsys", "data": {"hi": 1.25, "lo": 0.75}},
        {
            "name": "sys",
            "type": "histosys",
            "data": {"hi_data": [20.8, 19.2], "lo_data": [19.2, 20.8]},
        },
    ]
    assert mock_histogram.call_args_list[3:] == [
        (
            (pathlib.Path("path"), region, sample, systematic),
            {"modified": True, "template": "Up"},
        ),
        (
            (pathlib.Path("path"), region, sample, {"Name": "Nominal"}),
            {"modified": True},
        ),
    ]
Пример #7
0
def test_WorkspaceBuilder_build(mock_channels, mock_measuremets, mock_observations):
    ws_builder = workspace.WorkspaceBuilder({"General": {"HistogramFolder": "path"}})
    ws = ws_builder.build()
    ws_expected = {
        "channels": [{"name: channel"}],
        "measurements": [{"name: measurement"}],
        "observations": [{"name: observations"}],
        "version": "1.0.0",
    }
    assert ws == ws_expected
Пример #8
0
def test_WorkspaceBuilder_get_NF_modifiers():
    # could mock region_contains_modifier / sample_contains_modifier
    # one NF affects sample
    example_config = {
        "General": {"HistogramFolder": "path"},
        "NormFactors": [{"Name": "mu", "Samples": ["ABC", "DEF"]}],
    }
    region = {"Name": "SR"}
    sample = {"Name": "DEF"}
    expected_modifier = [{"data": None, "name": "mu", "type": "normfactor"}]
    ws_builder = workspace.WorkspaceBuilder(example_config)
    assert ws_builder.get_NF_modifiers(region, sample) == expected_modifier

    # no NF affects sample
    sample = {"Name": "GHI"}
    assert ws_builder.get_NF_modifiers(region, sample) == []

    # NF enters in region
    example_config = {
        "General": {"HistogramFolder": "path"},
        "NormFactors": [{"Name": "mu", "Regions": "SR"}],
    }
    ws_builder = workspace.WorkspaceBuilder(example_config)
    assert ws_builder.get_NF_modifiers(region, sample) == expected_modifier

    # no NF due to region
    region = {"Name": "CR"}
    assert ws_builder.get_NF_modifiers(region, sample) == []

    # multiple NFs affect sample
    example_config = {
        "General": {"HistogramFolder": "path"},
        "NormFactors": [{"Name": "mu"}, {"Name": "k"}],
    }
    sample = {"Name": "DEF"}
    expected_modifier = [
        {"data": None, "name": "mu", "type": "normfactor"},
        {"data": None, "name": "k", "type": "normfactor"},
    ]
    ws_builder = workspace.WorkspaceBuilder(example_config)
    assert ws_builder.get_NF_modifiers(region, sample) == expected_modifier
Пример #9
0
def test_WorkspaceBuilder_get_channels(mock_contains, mock_get_yield, mock_get_unc):
    # should mock get_NF_modifiers / get_sys_modifiers
    example_config = {
        "General": {"HistogramFolder": "path"},
        "Regions": [{"Name": "region_1"}],
        "Samples": [{"Name": "signal"}, {"Data": True}],
        "NormFactors": [],
    }

    ws_builder = workspace.WorkspaceBuilder(example_config)
    channels = ws_builder.get_channels()
    expected_channels = [
        {
            "name": "region_1",
            "samples": [
                {
                    "name": "signal",
                    "data": [1.0, 2.0],
                    "modifiers": [
                        {
                            "name": "staterror_region_1",
                            "type": "staterror",
                            "data": [0.1, 0.1],
                        }
                    ],
                }
            ],
        }
    ]
    assert channels == expected_channels
    assert mock_contains.call_args_list == [
        ((example_config["Regions"][0], example_config["Samples"][0]), {})
    ]
    assert mock_get_yield.call_args_list == [
        ((example_config["Regions"][0], example_config["Samples"][0]), {})
    ]
    assert mock_get_unc.call_args_list == [
        ((example_config["Regions"][0], example_config["Samples"][0]), {})
    ]

    # run again, this time region will not contain sample due to side_effect
    channels = ws_builder.get_channels()
    expected_channels = [{"name": "region_1", "samples": []}]
    assert channels == expected_channels
    assert mock_contains.call_count == 2
    assert mock_contains.call_args_list[-1] == (
        (example_config["Regions"][0], example_config["Samples"][0]),
        {},
    )
    # no calls to read histogram content
    assert mock_get_yield.call_count == 1
    assert mock_get_unc.call_count == 1
Пример #10
0
def test_WorkspaceBuilder__get_constant_parameter_setting():
    config_no_fixed = {"General": {"HistogramFolder": "path"}}
    ws_builder = workspace.WorkspaceBuilder(config_no_fixed)
    assert ws_builder._get_constant_parameter_setting("par") is None

    config_others_fixed = {
        "General": {
            "HistogramFolder": "path",
            "Fixed": [{"Name": "par_a", "Value": 1.2}],
        }
    }
    ws_builder = workspace.WorkspaceBuilder(config_others_fixed)
    assert ws_builder._get_constant_parameter_setting("par_b") is None

    config_par_fixed = {
        "General": {
            "HistogramFolder": "path",
            "Fixed": [{"Name": "par_a", "Value": 1.2}],
        }
    }
    ws_builder = workspace.WorkspaceBuilder(config_par_fixed)
    assert ws_builder._get_constant_parameter_setting("par_a") == 1.2
Пример #11
0
def test_WorkspaceBuilder_get_Normalization_modifier():
    systematic = {
        "Name": "sys",
        "Up": {"Normalization": 0.1},
        "Down": {"Normalization": -0.05},
    }
    expected_modifier = {
        "name": "sys",
        "type": "normsys",
        "data": {"hi": 1.1, "lo": 0.95},
    }
    ws_builder = workspace.WorkspaceBuilder({"General": {"HistogramFolder": "path"}})
    assert ws_builder.get_Normalization_modifier(systematic) == expected_modifier
Пример #12
0
def test_WorkspaceBuilder_get_measurement():
    example_config = {
        "General": {"Measurement": "fit", "POI": "mu", "HistogramFolder": "path"},
        "NormFactors": [
            {"Name": "NF", "Nominal": 1.0, "Bounds": [0.0, 5.0], "Fixed": False}
        ],
    }
    expected_measurement = [
        {
            "name": "fit",
            "config": {
                "poi": "mu",
                "parameters": [{"name": "NF", "inits": [1.0], "bounds": [[0.0, 5.0]]}],
            },
        }
    ]
    ws_builder = workspace.WorkspaceBuilder(example_config)
    assert ws_builder.get_measurements() == expected_measurement

    # no norm factor settings
    example_config_no_NF_settings = {
        "General": {"Measurement": "fit", "POI": "mu", "HistogramFolder": "path"},
        "NormFactors": [{"Name": "NF"}],
    }
    expected_measurement_no_NF_settings = [
        {"name": "fit", "config": {"poi": "mu", "parameters": [{"name": "NF"}]}}
    ]
    ws_builder = workspace.WorkspaceBuilder(example_config_no_NF_settings)
    assert ws_builder.get_measurements() == expected_measurement_no_NF_settings

    # constant normfactor
    with mock.patch(
        "cabinetry.workspace.WorkspaceBuilder._get_constant_parameter_setting",
        return_value=1.2,
    ) as mock_find_const:
        expected_measurement_const_NF = [
            {
                "name": "fit",
                "config": {
                    "poi": "mu",
                    "parameters": [{"name": "NF", "fixed": True, "inits": [1.2]}],
                },
            }
        ]
        # same config, but patched function to treat NF as fixed
        ws_builder = workspace.WorkspaceBuilder(example_config_no_NF_settings)
        assert ws_builder.get_measurements() == expected_measurement_const_NF
        assert mock_find_const.call_args_list == [(("NF",), {})]

    # constant systematic
    with mock.patch(
        "cabinetry.workspace.WorkspaceBuilder._get_constant_parameter_setting",
        return_value=1.2,
    ) as mock_find_const:
        example_config_const_sys = {
            "General": {
                "Measurement": "fit",
                "POI": "mu",
                "Fixed": [{"Name": "par_A", "Value": 1.2}],
                "HistogramFolder": "path",
            },
            "Systematics": [{"Name": "par_A"}],
        }
        expected_measurement_const_sys = [
            {
                "name": "fit",
                "config": {
                    "poi": "mu",
                    "parameters": [{"name": "par_A", "fixed": True, "inits": [1.2]}],
                },
            }
        ]
        ws_builder = workspace.WorkspaceBuilder(example_config_const_sys)
        assert ws_builder.get_measurements() == expected_measurement_const_sys
        assert mock_find_const.call_args_list == [(("par_A",), {})]

    # no constant systematic
    with mock.patch(
        "cabinetry.workspace.WorkspaceBuilder._get_constant_parameter_setting",
        return_value=None,
    ) as mock_find_const:
        example_config_sys = {
            "General": {"Measurement": "fit", "POI": "mu", "HistogramFolder": "path"},
            "Systematics": [{"Name": "par_A"}],
        }
        expected_measurement_sys = [
            {"name": "fit", "config": {"poi": "mu", "parameters": []}}
        ]
        ws_builder = workspace.WorkspaceBuilder(example_config_sys)
        assert ws_builder.get_measurements() == expected_measurement_sys
        assert mock_find_const.call_args_list == [(("par_A",), {})]
Пример #13
0
def test_WorkspaceBuilder():
    config = {"General": {"HistogramFolder": "path/"}}
    ws_builder = workspace.WorkspaceBuilder(config)
    assert ws_builder.config == config
    assert ws_builder.histogram_folder == pathlib.Path("path/")