def test_data_MC( mock_asimov, mock_unc, mock_stdev, mock_table_bin, mock_table_channel, mock_dict, mock_bins, mock_draw, example_spec, ): config = {"config": "abc"} figure_folder = "tmp" model, data = model_utils.model_and_data(example_spec) # pre-fit plot visualize.data_MC(model, data, config=config, figure_folder=figure_folder) # Asimov parameter calculation and pre-fit uncertainties assert mock_stdev.call_count == 1 assert mock_asimov.call_args_list[0][0][0] == model assert mock_unc.call_count == 1 assert mock_unc.call_args_list[0][0][0] == model # call to stdev calculation assert mock_stdev.call_count == 1 assert mock_stdev.call_args_list[0][0][0] == model assert np.allclose(mock_stdev.call_args_list[0][0][1], [1.0, 1.0]) assert np.allclose(mock_stdev.call_args_list[0][0][2], [0.04956657, 0.0]) assert np.allclose(mock_stdev.call_args_list[0][0][3], np.asarray([[1.0, 0.0], [0.0, 1.0]])) assert mock_stdev.call_args_list[0][1] == {} # yield table per bin assert mock_table_bin.call_count == 1 assert mock_table_bin.call_args_list[0][0][0] == model assert mock_table_bin.call_args_list[0][0][1] == [[[51.839756]]] assert mock_table_bin.call_args_list[0][0][2] == [[0.3]] assert mock_table_bin.call_args_list[0][0][3] == [[data[0]]] assert mock_table_bin.call_args_list[0][1] == {} # yield table per channel assert mock_table_channel.call_count == 1 assert mock_table_channel.call_args_list[0][0][0] == model assert mock_table_channel.call_args_list[0][0][1] == [[51.839756]] assert mock_table_channel.call_args_list[0][0][2] == [0.3] assert mock_table_channel.call_args_list[0][0][3] == [data[0]] assert mock_table_channel.call_args_list[0][1] == {} assert mock_dict.call_args_list == [[(config, "Signal Region"), {}]] assert mock_bins.call_args_list == [[({ "Name": "region", "Variable": "x" }, ), {}]] expected_histograms = [ { "label": "Signal", "isData": False, "yields": np.asarray([51.839756]), "variable": "x", }, { "label": "Data", "isData": True, "yields": np.asarray(data[:1]), "variable": "x", }, ] assert mock_draw.call_count == 1 assert mock_draw.call_args_list[0][0][0] == expected_histograms assert np.allclose(mock_draw.call_args_list[0][0][1], np.asarray([0.3])) np.testing.assert_equal(mock_draw.call_args_list[0][0][2], np.asarray([1, 2])) assert mock_draw.call_args_list[0][0][3] == pathlib.Path( "tmp/Signal-Region_prefit.pdf") assert mock_draw.call_args_list[0][1] == { "log_scale": None, "log_scale_x": False } # post-fit plot and custom scale fit_results = fit.FitResults( np.asarray([1.01, 1.1]), np.asarray([0.03, 0.1]), [], np.asarray([[1.0, 0.2], [0.2, 1.0]]), 0.0, ) visualize.data_MC( model, data, config=config, figure_folder=figure_folder, fit_results=fit_results, log_scale=False, ) assert mock_asimov.call_count == 1 # no new call # call to stdev calculation assert mock_stdev.call_count == 2 assert mock_stdev.call_args_list[1][0][0] == model assert np.allclose(mock_stdev.call_args_list[1][0][1], [1.01, 1.1]) assert np.allclose(mock_stdev.call_args_list[1][0][2], [0.03, 0.1]) assert np.allclose(mock_stdev.call_args_list[1][0][3], np.asarray([[1.0, 0.2], [0.2, 1.0]])) assert mock_stdev.call_args_list[1][1] == {} assert mock_draw.call_count == 2 # yield at best-fit point is different from pre-fit assert np.allclose(mock_draw.call_args_list[1][0][0][0]["yields"], 57.59396892) assert np.allclose(mock_draw.call_args_list[1][0][1], np.asarray([0.3])) np.testing.assert_equal(mock_draw.call_args_list[1][0][2], np.asarray([1, 2])) assert mock_draw.call_args_list[1][0][3] == pathlib.Path( "tmp/Signal-Region_postfit.pdf") assert mock_draw.call_args_list[1][1] == { "log_scale": False, "log_scale_x": False } # no yield table visualize.data_MC(model, data, config=config, include_table=False) assert mock_table_bin.call_count == 2 # 2 calls from before assert mock_table_channel.call_count == 2 # no config specified, default variable name and bin edges, data without auxdata visualize.data_MC(model, data[:1]) assert mock_draw.call_args[0][0][0]["variable"] == "bin" assert mock_draw.call_args[0][0][1]["variable"] == "bin" assert mock_draw.call_args[0][0][1]["yields"] == np.asarray(data[:1]) np.testing.assert_equal(mock_draw.call_args[0][2], np.asarray([0, 1])) # unknown plotting method with pytest.raises(NotImplementedError, match="unknown backend: unknown"): visualize.data_MC(model, data, config=config, figure_folder=figure_folder, method="unknown")
def test_data_MC(mock_load, mock_draw, tmp_path): """contrib.histogram_drawing is only imported depending on the keyword argument, so the patch works differently from the patch of load_from_config Generally it seems like following the path to the module is preferred, but that does not work for the `data_MC_matplotlib` case. For some information see also https://docs.python.org/3/library/unittest.mock.html#where-to-patch """ config = { "Regions": [{ "Name": "reg_1", "Variable": "x" }], "Samples": [{ "Name": "sample_1" }], } visualize.data_MC(config, tmp_path, tmp_path, prefit=True, method="matplotlib") # the call_args_list contains calls (outer round brackets), first filled with # arguments (inner round brackets) and then keyword arguments assert mock_load.call_args_list == [( ( tmp_path, { "Name": "sample_1" }, { "Name": "reg_1", "Variable": "x" }, { "Name": "nominal" }, ), { "modified": True }, )] assert mock_draw.call_args_list == [(( [{ "label": "sample_1", "isData": False, "hist": {}, "variable": "x" }], tmp_path / "reg_1_prefit.pdf", ), )] # other plotting method with pytest.raises(NotImplementedError, match="unknown backend") as e_info: visualize.data_MC(config, tmp_path, tmp_path, prefit=True, method="unknown") # postfit with pytest.raises(NotImplementedError, match="only prefit implemented so far") as e_info: visualize.data_MC(config, tmp_path, tmp_path, prefit=False, method="matplotlib")
def test_data_MC( mock_asimov, mock_unc, mock_stdev, mock_table, mock_dict, mock_bins, mock_draw, example_spec, ): config = {} figure_folder = "tmp" model_spec = pyhf.Workspace(example_spec).model().spec # pre-fit plot visualize.data_MC(config, example_spec, figure_folder=figure_folder) # Asimov parameter calculation and pre-fit uncertainties assert mock_stdev.call_count == 1 assert mock_asimov.call_args_list[0][0][0].spec == model_spec assert mock_unc.call_count == 1 assert mock_unc.call_args_list[0][0][0].spec == model_spec # call to stdev calculation assert mock_stdev.call_count == 1 assert mock_stdev.call_args_list[0][0][0].spec == model_spec assert np.allclose(mock_stdev.call_args_list[0][0][1], [1.0, 1.0]) assert np.allclose(mock_stdev.call_args_list[0][0][2], [0.04956657, 0.0]) assert np.allclose( mock_stdev.call_args_list[0][0][3], np.asarray([[1.0, 0.0], [0.0, 1.0]]) ) assert mock_stdev.call_args_list[0][1] == {} # yield table assert mock_table.call_count == 1 assert mock_table.call_args_list[0][0][0].spec == model_spec assert mock_table.call_args_list[0][0][1] == [np.asarray([[51.839756]])] assert mock_table.call_args_list[0][0][2] == [[0.3]] assert mock_table.call_args_list[0][0][3] == [np.asarray([475])] assert mock_table.call_args_list[0][1] == {} assert mock_dict.call_args_list == [[(config, "Signal Region"), {}]] assert mock_bins.call_args_list == [[({"Name": "region", "Variable": "x"},), {}]] expected_histograms = [ { "label": "Signal", "isData": False, "yields": np.asarray([51.839756]), "variable": "x", }, { "label": "Data", "isData": True, "yields": np.asarray([475]), "variable": "x", }, ] assert mock_draw.call_count == 1 assert mock_draw.call_args_list[0][0][0] == expected_histograms assert np.allclose(mock_draw.call_args_list[0][0][1], np.asarray([0.3])) assert np.allclose(mock_draw.call_args_list[0][0][2], np.asarray([1, 2])) assert mock_draw.call_args_list[0][0][3] == pathlib.Path( "tmp/Signal-Region_prefit.pdf" ) assert mock_draw.call_args_list[0][1] == {"log_scale": None} # post-fit plot and custom scale fit_results = fit.FitResults( np.asarray([1.01, 1.1]), np.asarray([0.03, 0.1]), [], np.asarray([[1.0, 0.2], [0.2, 1.0]]), 0.0, ) visualize.data_MC( config, example_spec, figure_folder=figure_folder, fit_results=fit_results, log_scale=False, ) assert mock_asimov.call_count == 1 # no new call # call to stdev calculation assert mock_stdev.call_count == 2 assert mock_stdev.call_args_list[1][0][0].spec == model_spec assert np.allclose(mock_stdev.call_args_list[1][0][1], [1.01, 1.1]) assert np.allclose(mock_stdev.call_args_list[1][0][2], [0.03, 0.1]) assert np.allclose( mock_stdev.call_args_list[1][0][3], np.asarray([[1.0, 0.2], [0.2, 1.0]]) ) assert mock_stdev.call_args_list[1][1] == {} assert mock_draw.call_count == 2 # yield at best-fit point is different from pre-fit assert np.allclose(mock_draw.call_args_list[1][0][0][0]["yields"], 57.59396892) assert np.allclose(mock_draw.call_args_list[1][0][1], np.asarray([0.3])) assert np.allclose(mock_draw.call_args_list[1][0][2], np.asarray([1, 2])) assert mock_draw.call_args_list[1][0][3] == pathlib.Path( "tmp/Signal-Region_postfit.pdf" ) assert mock_draw.call_args_list[1][1] == {"log_scale": False} # no yield table visualize.data_MC(config, example_spec, include_table=False) assert mock_table.call_count == 2 # 2 calls from before # unknown plotting method with pytest.raises(NotImplementedError, match="unknown backend: unknown"): visualize.data_MC( config, example_spec, figure_folder=figure_folder, method="unknown" )