From 6a3ab9672e817af3ce136b94c0bc1f6382116b1e Mon Sep 17 00:00:00 2001 From: Andrzej Date: Thu, 9 Jun 2022 12:35:44 +0200 Subject: [PATCH] fix: satisfy precommit --- src/cabinetry/fit/__init__.py | 9 +-- src/cabinetry/fit/results_containers.py | 4 +- src/cabinetry/model_utils.py | 15 ++++- src/cabinetry/visualize/__init__.py | 6 +- src/cabinetry/visualize/plot_result.py | 2 +- tests/cli/test_cli.py | 34 ++++++++-- tests/fit/test_fit.py | 81 ++++++++++++++++++----- tests/fit/test_fit_results_containers.py | 16 ++++- tests/test_model_utils.py | 3 + tests/visualize/reference/pulls.png | Bin 7114 -> 5376 bytes tests/visualize/test_visualize.py | 10 ++- 11 files changed, 139 insertions(+), 41 deletions(-) diff --git a/src/cabinetry/fit/__init__.py b/src/cabinetry/fit/__init__.py index 3283c2b0..d6e0536c 100644 --- a/src/cabinetry/fit/__init__.py +++ b/src/cabinetry/fit/__init__.py @@ -8,7 +8,6 @@ import pyhf import scipy.optimize import scipy.stats -import re from cabinetry import model_utils from cabinetry.fit.results_containers import ( @@ -87,10 +86,7 @@ def _fit_model_pyhf( bestfit = pyhf.tensorlib.to_numpy(result[:, 0]) uncertainty = pyhf.tensorlib.to_numpy(result[:, 1]) - labels = model.config.par_names() - _mod_dict = dict(model.config.modifiers) - _clean_labels = [re.sub(r"\[.*\]", "", label) for label in labels] - types = [_mod_dict[n] if n in _mod_dict else None for n in _clean_labels] + labels, types = model_utils._labels_modifiers(model) corr_mat = pyhf.tensorlib.to_numpy(corr_mat) best_twice_nll = float(best_twice_nll) # convert 0-dim np.ndarray to float @@ -150,7 +146,7 @@ def _fit_model_custom( fix_pars = fix_pars or model.config.suggested_fixed() par_bounds = par_bounds or model.config.suggested_bounds() - labels = model.config.par_names() + labels, types = model_utils._labels_modifiers(model) # set initial step size to 0 for fixed parameters # this will cause the associated parameter uncertainties to be 0 post-fit @@ -195,6 +191,7 @@ def twice_nll_func(pars: np.ndarray) -> Any: bestfit, uncertainty, labels, + types, corr_mat, best_twice_nll, minos_uncertainty=minos_results, diff --git a/src/cabinetry/fit/results_containers.py b/src/cabinetry/fit/results_containers.py index 2c8a3857..8f04af17 100644 --- a/src/cabinetry/fit/results_containers.py +++ b/src/cabinetry/fit/results_containers.py @@ -1,6 +1,6 @@ """Provides containers for inference results.""" -from typing import Dict, List, NamedTuple, Tuple +from typing import Dict, List, NamedTuple, Optional, Tuple import numpy as np @@ -24,7 +24,7 @@ class FitResults(NamedTuple): bestfit: np.ndarray uncertainty: np.ndarray labels: List[str] - types: List[str] + types: List[Optional[str]] corr_mat: np.ndarray best_twice_nll: float goodness_of_fit: float = -1 diff --git a/src/cabinetry/model_utils.py b/src/cabinetry/model_utils.py index 827f4e8a..37ab38b0 100644 --- a/src/cabinetry/model_utils.py +++ b/src/cabinetry/model_utils.py @@ -2,6 +2,7 @@ import json import logging +import re from typing import Any, Dict, List, NamedTuple, Optional, Tuple, Union import awkward as ak @@ -516,6 +517,17 @@ def _filter_channels( return filtered_channels +def _labels_modifiers( + model: pyhf.pdf.Model, +) -> Tuple[List[str], List[Optional[str]]]: + """ """ + labels = model.config.par_names() + _mod_dict = dict(model.config.modifiers) + _clean_labels = [re.sub(r"\[.*\]", "", label) for label in labels] + types = [_mod_dict[n] if n in _mod_dict else None for n in _clean_labels] + return labels, types + + def match_fit_results(model: pyhf.pdf.Model, fit_results: FitResults) -> FitResults: """Matches results from a fit to a model by adding or removing parameters as needed. @@ -543,7 +555,7 @@ def match_fit_results(model: pyhf.pdf.Model, fit_results: FitResults) -> FitResu bestfit = asimov_parameters(model) # Asimov parameter values for target model uncertainty = prefit_uncertainties(model) # pre-fit uncertainties for target model - labels = model.config.par_names() # labels for target model + labels, types = _labels_modifiers(model) # indices of parameters in current fit results, or None if they are missing indices_for_corr: List[Optional[int]] = [None] * len(labels) @@ -577,6 +589,7 @@ def match_fit_results(model: pyhf.pdf.Model, fit_results: FitResults) -> FitResu np.asarray(bestfit), np.asarray(uncertainty), labels, + types, corr_mat, fit_results.best_twice_nll, fit_results.goodness_of_fit, diff --git a/src/cabinetry/visualize/__init__.py b/src/cabinetry/visualize/__init__.py index a339d20f..6387282e 100644 --- a/src/cabinetry/visualize/__init__.py +++ b/src/cabinetry/visualize/__init__.py @@ -1,9 +1,9 @@ """High-level entry point for visualizing fit models and inference results.""" +import fnmatch import glob import logging import pathlib -import fnmatch from typing import Any, Dict, List, Optional, Tuple, Union import matplotlib as mpl @@ -442,7 +442,7 @@ def pulls( *, figure_folder: Union[str, pathlib.Path] = "figures", exclude: Optional[Union[str, List[str], Tuple[str, ...]]] = None, - exclude_by_type: Optional[Union[str, List[str]]] = ["staterror"], + exclude_by_type: Optional[List[str]] = None, close_figure: bool = True, save_figure: bool = True, ) -> mpl.figure.Figure: @@ -489,6 +489,8 @@ def pulls( ) # exclude by type + if exclude_by_type is None: + exclude_by_type = ["staterror"] exclude_set.update( [ label diff --git a/src/cabinetry/visualize/plot_result.py b/src/cabinetry/visualize/plot_result.py index 8f3708a4..755bcfe0 100644 --- a/src/cabinetry/visualize/plot_result.py +++ b/src/cabinetry/visualize/plot_result.py @@ -91,7 +91,7 @@ def pulls( matplotlib.figure.Figure: the pull figure """ num_pars = len(bestfit) - numeric = np.zeros(num_pars, dtype=bool) if numeric is None else numeric + numeric = np.zeros(num_pars, dtype=bool) if numeric is None else np.asarray(numeric) y_positions = np.arange(num_pars)[::-1] fig, ax = plt.subplots(figsize=(6, 1 + num_pars / 4), dpi=100) diff --git a/tests/cli/test_cli.py b/tests/cli/test_cli.py index afb5acd4..74a4c9db 100644 --- a/tests/cli/test_cli.py +++ b/tests/cli/test_cli.py @@ -95,7 +95,12 @@ def test_workspace(mock_validate, mock_build, cli_helpers, tmp_path): @mock.patch( "cabinetry.fit.fit", return_value=fit.FitResults( - np.asarray([1.0]), np.asarray([0.1]), ["label"], np.asarray([[1.0]]), 1.0 + np.asarray([1.0]), + np.asarray([0.1]), + ["label"], + ["type"], + np.asarray([[1.0]]), + 1.0, ), autospec=True, ) @@ -109,8 +114,9 @@ def test_fit(mock_utils, mock_fit, mock_pulls, mock_corrmat, tmp_path): bestfit = np.asarray([1.0]) uncertainty = np.asarray([0.1]) labels = ["label"] + types = ["type"] corr_mat = np.asarray([[1.0]]) - fit_results = fit.FitResults(bestfit, uncertainty, labels, corr_mat, 1.0) + fit_results = fit.FitResults(bestfit, uncertainty, labels, types, corr_mat, 1.0) workspace_path = str(tmp_path / "workspace.json") @@ -204,7 +210,12 @@ def test_fit(mock_utils, mock_fit, mock_pulls, mock_corrmat, tmp_path): @mock.patch( "cabinetry.fit.fit", return_value=fit.FitResults( - np.asarray([1.0]), np.asarray([0.1]), ["label"], np.asarray([[1.0]]), 1.0 + np.asarray([1.0]), + np.asarray([0.1]), + ["label"], + ["type"], + np.asarray([[1.0]]), + 1.0, ), autospec=True, ) @@ -218,8 +229,9 @@ def test_ranking(mock_utils, mock_fit, mock_rank, mock_vis, tmp_path): bestfit = np.asarray([1.0]) uncertainty = np.asarray([0.1]) labels = ["label"] + types = ["type"] corr_mat = np.asarray([[1.0]]) - fit_results = fit.FitResults(bestfit, uncertainty, labels, corr_mat, 1.0) + fit_results = fit.FitResults(bestfit, uncertainty, labels, types, corr_mat, 1.0) workspace_path = str(tmp_path / "workspace.json") @@ -467,7 +479,12 @@ def test_significance(mock_utils, mock_sig, tmp_path): @mock.patch( "cabinetry.fit.fit", return_value=fit.FitResults( - np.asarray([1.0]), np.asarray([0.1]), ["label"], np.asarray([[1.0]]), 1.0 + np.asarray([1.0]), + np.asarray([0.1]), + ["label"], + ["type"], + np.asarray([[1.0]]), + 1.0, ), autospec=True, ) @@ -508,7 +525,12 @@ def test_data_mc( config_path = str(tmp_path / "config.yml") cli_helpers.write_config(config_path, config) fit_results = fit.FitResults( - np.asarray([1.0]), np.asarray([0.1]), ["label"], np.asarray([[1.0]]), 1.0 + np.asarray([1.0]), + np.asarray([0.1]), + ["label"], + ["type"], + np.asarray([[1.0]]), + 1.0, ) result = runner.invoke( diff --git a/tests/fit/test_fit.py b/tests/fit/test_fit.py index d2c901b1..63d15e57 100644 --- a/tests/fit/test_fit.py +++ b/tests/fit/test_fit.py @@ -16,7 +16,8 @@ def test_print_results(caplog): bestfit = np.asarray([1.0, 2.0]) uncertainty = np.asarray([0.1, 0.3]) labels = ["param_A", "param_B"] - fit_results = fit.FitResults(bestfit, uncertainty, labels, np.empty(0), 0.0) + types = ["normsys", "shapesys"] + fit_results = fit.FitResults(bestfit, uncertainty, labels, types, np.empty(0), 0.0) fit.print_results(fit_results) assert "param_A = 1.0000 +/- 0.1000" in [rec.message for rec in caplog.records] @@ -143,13 +144,13 @@ def test__fit_model_custom(mock_minos, example_spec, example_spec_multibin): @mock.patch( "cabinetry.fit._fit_model_custom", return_value=fit.FitResults( - np.asarray([1.2]), np.asarray([0.2]), ["par"], np.empty(0), 2.0 + np.asarray([1.2]), np.asarray([0.2]), ["par"], ["normsys"], np.empty(0), 2.0 ), ) @mock.patch( "cabinetry.fit._fit_model_pyhf", return_value=fit.FitResults( - np.asarray([1.1]), np.asarray([0.2]), ["par"], np.empty(0), 2.0 + np.asarray([1.1]), np.asarray([0.2]), ["par"], ["normsys"], np.empty(0), 2.0 ), ) def test__fit_model(mock_pyhf, mock_custom, example_spec): @@ -295,7 +296,7 @@ def test__goodness_of_fit( @mock.patch( "cabinetry.fit._fit_model", return_value=fit.FitResults( - np.asarray([1.0]), np.asarray([0.1]), ["par"], np.empty(0), 2.0 + np.asarray([1.0]), np.asarray([0.1]), ["par"], ["normsys"], np.empty(0), 2.0 ), ) def test_fit(mock_fit, mock_print, mock_gof): @@ -382,33 +383,78 @@ def test_fit(mock_fit, mock_print, mock_gof): "cabinetry.fit._fit_model", side_effect=[ fit.FitResults( - np.asarray([0.9, 1.3]), np.asarray([0.1, 0.1]), ["a", "b"], np.empty(0), 0.0 + np.asarray([0.9, 1.3]), + np.asarray([0.1, 0.1]), + ["a", "b"], + ["normsys", "normsys"], + np.empty(0), + 0.0, ), fit.FitResults( - np.asarray([0.9, 0.7]), np.asarray([0.1, 0.1]), ["a", "b"], np.empty(0), 0.0 + np.asarray([0.9, 0.7]), + np.asarray([0.1, 0.1]), + ["a", "b"], + ["normsys", "normsys"], + np.empty(0), + 0.0, ), fit.FitResults( - np.asarray([0.9, 1.2]), np.asarray([0.1, 0.1]), ["a", "b"], np.empty(0), 0.0 + np.asarray([0.9, 1.2]), + np.asarray([0.1, 0.1]), + ["a", "b"], + ["normsys", "normsys"], + np.empty(0), + 0.0, ), fit.FitResults( - np.asarray([0.9, 0.8]), np.asarray([0.1, 0.1]), ["a", "b"], np.empty(0), 0.0 + np.asarray([0.9, 0.8]), + np.asarray([0.1, 0.1]), + ["a", "b"], + ["normsys", "normsys"], + np.empty(0), + 0.0, ), # for second ranking call with fixed parameter fit.FitResults( - np.asarray([0.9, 1.2]), np.asarray([0.1, 0.1]), ["a", "b"], np.empty(0), 0.0 + np.asarray([0.9, 1.2]), + np.asarray([0.1, 0.1]), + ["a", "b"], + ["normsys", "normsys"], + np.empty(0), + 0.0, ), fit.FitResults( - np.asarray([0.9, 0.8]), np.asarray([0.1, 0.1]), ["a", "b"], np.empty(0), 0.0 + np.asarray([0.9, 0.8]), + np.asarray([0.1, 0.1]), + ["a", "b"], + ["normsys", "normsys"], + np.empty(0), + 0.0, ), # for third ranking call without reference results fit.FitResults( - np.asarray([0.9, 1.0]), np.asarray([0.3, 0.3]), ["a", "b"], np.empty(0), 0.0 + np.asarray([0.9, 1.0]), + np.asarray([0.3, 0.3]), + ["a", "b"], + ["normsys", "normsys"], + np.empty(0), + 0.0, ), fit.FitResults( - np.asarray([0.9, 1.3]), np.asarray([0.1, 0.1]), ["a", "b"], np.empty(0), 0.0 + np.asarray([0.9, 1.3]), + np.asarray([0.1, 0.1]), + ["a", "b"], + ["normsys", "normsys"], + np.empty(0), + 0.0, ), fit.FitResults( - np.asarray([0.9, 0.7]), np.asarray([0.1, 0.1]), ["a", "b"], np.empty(0), 0.0 + np.asarray([0.9, 0.7]), + np.asarray([0.1, 0.1]), + ["a", "b"], + ["normsys", "normsys"], + np.empty(0), + 0.0, ), ], ) @@ -417,7 +463,8 @@ def test_ranking(mock_fit, example_spec): bestfit = np.asarray([0.9, 1.0]) uncertainty = np.asarray([0.02, 0.1]) labels = ["staterror", "mu"] - fit_results = fit.FitResults(bestfit, uncertainty, labels, np.empty(0), 0.0) + types = ["staterror", "normfactor"] + fit_results = fit.FitResults(bestfit, uncertainty, labels, types, np.empty(0), 0.0) model, data = model_utils.model_and_data(example_spec) ranking_results = fit.ranking(model, data, fit_results=fit_results) @@ -500,16 +547,16 @@ def test_ranking(mock_fit, example_spec): "cabinetry.fit._fit_model", side_effect=[ fit.FitResults( - np.asarray([0.9, 1.3]), np.asarray([0.1, 0.1]), [], np.empty(0), 8.0 + np.asarray([0.9, 1.3]), np.asarray([0.1, 0.1]), [], [], np.empty(0), 8.0 ) ] # nominal fit + [ - fit.FitResults(np.empty(0), np.empty(0), [], np.empty(0), abs(i) + 8) + fit.FitResults(np.empty(0), np.empty(0), [], [], np.empty(0), abs(i) + 8) for i in np.linspace(-5, 5, 11) ] # fits in scan + [ fit.FitResults( - np.asarray([0.9, 1.3]), np.asarray([0.1, 0.1]), [], np.empty(0), 2.0 + np.asarray([0.9, 1.3]), np.asarray([0.1, 0.1]), [], [], np.empty(0), 2.0 ) ] * 6, # fits for custom parameter range diff --git a/tests/fit/test_fit_results_containers.py b/tests/fit/test_fit_results_containers.py index 0739663b..c9746849 100644 --- a/tests/fit/test_fit_results_containers.py +++ b/tests/fit/test_fit_results_containers.py @@ -9,9 +9,12 @@ def test_FitResults(): bestfit = np.asarray([1.0]) uncertainty = np.asarray([0.1]) labels = ["par_a"] + types = [None] corr_mat = np.asarray([[1.0]]) best_twice_nll = 2.0 - fit_results = fit.FitResults(bestfit, uncertainty, labels, corr_mat, best_twice_nll) + fit_results = fit.FitResults( + bestfit, uncertainty, labels, types, corr_mat, best_twice_nll + ) assert np.allclose(fit_results.bestfit, bestfit) assert np.allclose(fit_results.uncertainty, uncertainty) assert fit_results.labels == labels @@ -30,7 +33,13 @@ def test_RankingResults(): postfit_up = np.asarray([0.2]) postfit_down = np.asarray([-0.2]) ranking_results = fit.RankingResults( - bestfit, uncertainty, labels, prefit_up, prefit_down, postfit_up, postfit_down + bestfit, + uncertainty, + labels, + prefit_up, + prefit_down, + postfit_up, + postfit_down, ) assert np.allclose(ranking_results.bestfit, bestfit) assert np.allclose(ranking_results.uncertainty, uncertainty) @@ -100,7 +109,8 @@ def test_print_results(caplog): bestfit = np.asarray([1.0, 2.0]) uncertainty = np.asarray([0.1, 0.3]) labels = ["param_A", "param_B"] - fit_results = fit.FitResults(bestfit, uncertainty, labels, np.empty(0), 0.0) + types = [None, None] + fit_results = fit.FitResults(bestfit, uncertainty, labels, types, np.empty(0), 0.0) fit.print_results(fit_results) assert "param_A = 1.0000 +/- 0.1000" in [rec.message for rec in caplog.records] diff --git a/tests/test_model_utils.py b/tests/test_model_utils.py index ca5e40bb..9624f2f2 100644 --- a/tests/test_model_utils.py +++ b/tests/test_model_utils.py @@ -265,6 +265,7 @@ def test_prediction( np.asarray([1.01, 1.1]), np.asarray([0.03, 0.1]), ["staterror_Signal-Region[0]", "Signal strength"], + ["staterror", "normfactor"], np.asarray([[1.0, 0.2], [0.2, 1.0]]), 0.0, ) @@ -298,6 +299,7 @@ def test_prediction( np.asarray([1.01, 1.1]), np.asarray([0.03, 0.1]), ["a", "b"], + ["staterror", "normfactor"], np.asarray([[1.0, 0.2], [0.2, 1.0]]), 0.0, ) @@ -394,6 +396,7 @@ def test_match_fit_results(mock_pars, mock_uncs): np.asarray([1.0, 2.0, 3.0]), np.asarray([0.1, 0.2, 0.3]), ["par_a", "par_b", "par_c"], + [None, None, None], np.asarray([[1.0, 0.2, 0.5], [0.2, 1.0, 0.1], [0.5, 0.1, 1.0]]), 5.0, 0.1, diff --git a/tests/visualize/reference/pulls.png b/tests/visualize/reference/pulls.png index 8fad063113bf8d15be32dcf14b2f3d32bb73344a..9759e84396d8cb9d86d9f3c1adbe970300a03758 100644 GIT binary patch literal 5376 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 bFCEbtOs2nfEx2nBOg*HmsHRXPXCC-Jqmal@ diff --git a/tests/visualize/test_visualize.py b/tests/visualize/test_visualize.py index 303eb54c..714fef87 100644 --- a/tests/visualize/test_visualize.py +++ b/tests/visualize/test_visualize.py @@ -360,10 +360,11 @@ def test_correlation_matrix(mock_draw): corr_mat = np.asarray([[1.0, 0.2, 0.1], [0.2, 1.0, 0.1], [0.1, 0.1, 1.0]]) corr_mat_pruned = np.asarray([[1.0, 0.2], [0.2, 1.0]]) labels = ["a", "b", "c"] + types = [None, None, None] labels_pruned = ["a", "b"] folder_path = "tmp" figure_path = pathlib.Path(folder_path) / "correlation_matrix.pdf" - fit_results = fit.FitResults(np.empty(0), np.empty(0), labels, corr_mat, 1.0) + fit_results = fit.FitResults(np.empty(0), np.empty(0), labels, types, corr_mat, 1.0) # pruning with threshold fig = visualize.correlation_matrix( @@ -382,7 +383,7 @@ def test_correlation_matrix(mock_draw): # close figure, do not save corr_mat_fixed = np.asarray([[1.0, 0.2, 0.0], [0.2, 1.0, 0.0], [0.0, 0.0, 0.0]]) fit_results_fixed = fit.FitResults( - np.empty(0), np.empty(0), labels, corr_mat_fixed, 1.0 + np.empty(0), np.empty(0), labels, types, corr_mat_fixed, 1.0 ) _ = visualize.correlation_matrix( fit_results_fixed, @@ -407,9 +408,10 @@ def test_pulls(mock_draw): bestfit = np.asarray([0.8, 1.0, 1.05, 1.1]) uncertainty = np.asarray([0.9, 1.0, 0.03, 0.7]) labels = ["a", "b", "staterror_region[0]", "c"] + types = [None, None, "staterror", None] exclude = ["a"] folder_path = "tmp" - fit_results = fit.FitResults(bestfit, uncertainty, labels, np.empty(0), 1.0) + fit_results = fit.FitResults(bestfit, uncertainty, labels, types, np.empty(0), 1.0) filtered_bestfit = np.asarray([1.0, 1.1]) filtered_uncertainty = np.asarray([1.0, 0.7]) @@ -429,6 +431,7 @@ def test_pulls(mock_draw): for i in range(len(filtered_labels)) ] ) + assert np.allclose(mock_draw.call_args[1].pop("numeric"), np.array([False, False])) assert mock_draw.call_args[1] == {"figure_path": figure_path, "close_figure": True} # filtering single parameter instead of list @@ -462,6 +465,7 @@ def test_pulls(mock_draw): for i in range(len(labels_expected)) ] ) + assert np.allclose(mock_draw.call_args[1].pop("numeric"), np.array([False, False])) assert mock_draw.call_args[1] == {"figure_path": None, "close_figure": False}