{"id":37084620,"url":"https://github.com/eschanet/simplify","last_synced_at":"2026-01-14T10:23:03.345Z","repository":{"id":46155953,"uuid":"312244035","full_name":"eschanet/simplify","owner":"eschanet","description":"Create and validate simplified likelihoods from full likelihoods.","archived":false,"fork":false,"pushed_at":"2025-09-04T15:42:06.000Z","size":12053,"stargazers_count":6,"open_issues_count":5,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-12-02T04:06:07.931Z","etag":null,"topics":["cern","hep-ex","inference","likelihood","particlephysics","statistics"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eschanet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-11-12T10:35:50.000Z","updated_at":"2023-12-05T15:08:02.000Z","dependencies_parsed_at":"2022-09-03T20:02:55.652Z","dependency_job_id":null,"html_url":"https://github.com/eschanet/simplify","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/eschanet/simplify","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eschanet%2Fsimplify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eschanet%2Fsimplify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eschanet%2Fsimplify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eschanet%2Fsimplify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eschanet","download_url":"https://codeload.github.com/eschanet/simplify/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eschanet%2Fsimplify/sbom","scorecard":{"id":382334,"data":{"date":"2025-08-11","repo":{"name":"github.com/eschanet/simplify","commit":"97dfa8691fc710d8578a4df01960a8fdd5047e4b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.5,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":1,"reason":"Found 3/30 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/CI.yml:1","Warn: no topLevel permission defined: .github/workflows/lint.yml:1","Warn: no topLevel permission defined: .github/workflows/publish.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/CI.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/eschanet/simplify/CI.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/CI.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/eschanet/simplify/CI.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/CI.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/eschanet/simplify/CI.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/eschanet/simplify/lint.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/eschanet/simplify/lint.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/eschanet/simplify/publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/eschanet/simplify/publish.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish.yml:83: update your workflow using https://app.stepsecurity.io/secureworkflow/eschanet/simplify/publish.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish.yml:91: update your workflow using https://app.stepsecurity.io/secureworkflow/eschanet/simplify/publish.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/CI.yml:29","Warn: pipCommand not pinned by hash: .github/workflows/CI.yml:30","Warn: pipCommand not pinned by hash: .github/workflows/lint.yml:23","Warn: pipCommand not pinned by hash: .github/workflows/lint.yml:24","Warn: pipCommand not pinned by hash: .github/workflows/publish.yml:29","Warn: pipCommand not pinned by hash: .github/workflows/publish.yml:30","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned","Info:   0 out of   6 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 6 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T15:45:19.884Z","repository_id":46155953,"created_at":"2025-08-18T15:45:19.884Z","updated_at":"2025-08-18T15:45:19.884Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28417017,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:18:03.274Z","status":"ssl_error","status_checked_at":"2026-01-14T10:16:11.865Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cern","hep-ex","inference","likelihood","particlephysics","statistics"],"created_at":"2026-01-14T10:23:02.703Z","updated_at":"2026-01-14T10:23:03.333Z","avatar_url":"https://github.com/eschanet.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# simplify\n\n[![CI status](https://github.com/eschanet/simplify/workflows/CI/badge.svg)](https://github.com/eschanet/simplify/actions?query=workflow%3ACI)\n[![codecov](https://codecov.io/gh/eschanet/simplify/branch/master/graph/badge.svg)](https://codecov.io/gh/eschanet/simplify)\n[![PyPI version](https://badge.fury.io/py/simplify.svg)](https://badge.fury.io/py/simplify)\n[![python version](https://img.shields.io/pypi/pyversions/simplify.svg)](https://pypi.org/project/simplify/)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n\n\nA python package that creates simplified likelihoods from full likelihoods. The method is documented in the ATLAS PUB note [Implementation of simplified likelihoods in HistFactory for searches for supersymmetry](https://cds.cern.ch/record/2782654) and in [chapter 10 of Eric Schanet's PhD thesis](https://cds.cern.ch/record/2774438/files/CERN-THESIS-2021-077.pdf). Currently, only one format is implemented for simplified likelihoods, but the idea is to support additional forms of (not so) simplified likelihoods.\n\n## Table of contents\n\n1. [Introduction](#introduction)\n2. [Installation](#installation)\n3. [How To Run](#how-to-run)\n4. [Example Likelihood](#example-likelihood)\n\n\n## Introduction\n\nIn high energy physics (HEP), searches for new physics are typically interested in making inferences about a probabilistic model given some observed collision data. This approach can be formalised using a *statistical model* \u003ci\u003ef(\u003cb\u003ex\u003c/b\u003e\u0026VerticalLine;\u003cb\u003e\u0026phi;\u003c/b\u003e)\u003c/i\u003e, i.e. a parametric family of probability density functions (PDFs) describing the probability of observing data \u003ci\u003e\u003cb\u003ex\u003c/b\u003e\u003c/i\u003e given some model parameters \u003ci\u003e\u003cb\u003e\u0026phi;\u003c/b\u003e\u003c/i\u003e. The *likelihood function* \u003ci\u003eL(\u003cb\u003e\u0026phi;\u003c/b\u003e)\u003c/i\u003e then refers to the value of *f* as a function of \u003ci\u003e\u003cb\u003e\u0026phi;\u003c/b\u003e\u003c/i\u003e given fixed \u003ci\u003e\u003cb\u003ex\u003c/b\u003e\u003c/i\u003e.\n\nFor binned data, the [HistFactory](https://cds.cern.ch/record/1456844?ln=de) template for building statistical models and likelihoods finds ample usage in HEP.\n\nAlthough many searches for supersymmetry (SUSY) are sensitive to a variety of beyond the Standard Model (BSM) physics models, for reasons of computational cost and complexity they are often only interpreted in a limited set of *simplified models*. While statistical inference and interpretation of limits on individual SUSY production and decay topologies is straightforward and very convenient, their lack of model complexity leads to poor approximations to the true underlying constraints on the respective model parameters of a more complete SUSY model. In order to investigate realistic SUSY scenarios, large-scale re-interpretation efforts scanning a large number of dimensions is needed, resulting in a significant increase in computational cost for the statistical inference.\n\nThe approximation method put forward in the ATLAS PUB note [Implementation of simplified likelihoods in HistFactory for searches for supersymmetry](https://cds.cern.ch/record/2782654) and implemented in this repository introduces the notion of *simplified likelihoods* that come with low computational cost but high statistical precision, therefore offering a viable solution for large-scale re-interpretation efforts over large model spaces.\n\n\n## Installation\n\nFollow good practice and start by creating a virtual environment, e.g. using `venv`\n\n```console\npython3 -m venv simplify\n```\n\nand then activating it\n```console\nsource simplify/bin/activate\n```\n\n### Default installation from PyPI\n\nYou can install `simplify` directly from PyPI with\n```console\npython3 -m pip install simplify[contrib]\n```\n\nNotice that `simplify` is supported and tested for Python 3.7, Python 3.8, and Python 3.9.\n\n### Development installation\n\nIf you want to contribute to `simplify`, install the development version of the package. Fork the repository, clone your fork, and then install from local resources with\n```console\npython3 -m pip install --ignore-installed -U -e .[complete]\n```\nNote that you might have to wrap `.[complete]` into quotes depending on your shell.\n\nNext, setup the git pre-commit hook for Black\n```console\npre-commit install\n```\n\nNow you should be able to run all the tests with\n```console\npython3 -m pytest\n```\n\n## How to run\n\nYou can use `simplify` either through your command line, or integrate it directly into your scripts.\n\n### CLI\n\nRun with e.g.\n\n```console\nsimplify convert \u003c fullLH.json \u003e simplifiedLH.json\n```\n\nor e.g.\n\n```console\ncurl http://foo/likelihood.json | simplify convert\n```\n\nwhere `fullLH.json` is the full likelihood you want to convert into a simplified likelihood. Simplify is able to read/write from/to stdin/stdout.\n\nHit `simplify --help` for detailed information on the CLI.\n\n### In Python script\n\nYou can also use `simplify` in a Python script, e.g. to create some validation and cross-check plots and tables.\n\n```py\nimport pyhf\nimport json\n\nimport simplify\n\n# set the computational backend to pyhf and load LH\npyhf.set_backend(pyhf.tensorlib, \"minuit\")\nspec = json.load(open(\"likelihood.json\", \"r\"))\n\n# ws from full LH\nws = pyhf.Workspace(spec)\n\n# get model and data for each ws we just created\n# use polynomial interpolation and exponential extrapolation\n# for nuisance params\nmodel = ws.model(\n    modifier_settings = {\n        \"normsys\": {\"interpcode\": \"code4\"},\n        \"histosys\": {\"interpcode\": \"code4p\"},\n    }\n)\ndata = ws.data(model)\n\n# run fit\nfit_result = simplify.fitter.fit(ws)\n\n# plot the pulls\nplt = simplify.plot.pulls(\n    fit_result,\n    \"plots/\"\n)\n\n# plot correlation matrix\nplt = simplify.plot.correlation_matrix(\n    fit_result,\n    \"plots/\",\n    pruning_threshold=0.1\n)\n\n# get a yieldstable in nice LaTeX format\ntables = simplify.plot.yieldsTable(\n    ws,\n    \"plots/\",\n    fit_result,\n)\n```\n\n## Example Likelihood\n\nLet's go through an example likelihood. We'll use the full likelihood of an ATLAS search for direct production of electroweakinos in final states with one lepton and a Higgs boson ([10.1140/epjc/s10052-020-8050-3](https://arxiv.org/abs/1909.09226)). The full likelihood in `JSON` format as specified by [ATL-PHYS-PUB-2019-029](https://cds.cern.ch/record/2684863) is publicly available to download from [doi.org/10.17182](https://www.hepdata.net/record/resource/1408476?view=true). It contains the full statistical model of the original analysis given the full observed dataset from Run-2 of the LHC.\n\nYou can either download the likelihood by hand from [HEPData](https://www.hepdata.net/record/resource/1408476?view=true), or just let `pyhf` do the work for you by using\n```console\npyhf contrib download https://doi.org/10.17182/hepdata.90607.v3/r3 1Lbb-likelihoods \u0026\u0026 cd 1Lbb-likelihoods\n```\n\nFrom there, provided you have already setup `simplify` previously (which also sets up `pyhf`), you can produce a simplified likelihood of this analysis with\n```console\nsimplify convert \u003c BkgOnly.json \u003e simplify_BkgOnly.json\n```\n\nAnd you're done. Well, at least you've got yourself a simplified version of that likelihood, which approximates the total background using a single background sample that is set to the post-fit total background determined from the full likelihood. The uncertainties (the expensive part) are approximated using only the final uncertainty on the background estimate in each bin of the analysis.\n\nIf you think about it, this gives you quite a simple likelihood function. Let's compare them quickly. For the full likelihood, we can inspect the full likelihood with `pyhf` (and only look at the first 17 lines containing summary of what `pyhf` spits out):\n```console\npyhf inspect BkgOnly.json | head -n 17\n```\n\nThis should give you\n```console\n       Summary\n  ------------------\n    channels  8\n     samples  9\n  parameters  115\n   modifiers  115\n\n    channels  nbins\n  ----------  -----\n SRHMEM_mct2    3\n SRLMEM_mct2    3\n SRMMEM_mct2    3\n STCREM_cuts    1\n TRHMEM_cuts    1\n TRLMEM_cuts    1\n TRMMEM_cuts    1\n   WREM_cuts    1\n```\n\nThink about this for a second. You've got 8 channels with a total of 14 bins. Each bin contains information about 9 samples, and each event rate for each sample is subject to a total of 115 additional parameters (the uncertainties of the model). This makes for quite a complicated likelihood function.\n\nOn to the simplified one then.\n```console\npyhf inspect simplify_BkgOnly.json | head -n 17\n```\ngives us\n```console\n       Summary\n  ------------------\n    channels  8\n     samples  1\n  parameters  1\n   modifiers  1\n\n    channels  nbins\n  ----------  -----\n SRHMEM_mct2    3\n SRLMEM_mct2    3\n SRMMEM_mct2    3\n STCREM_cuts    1\n TRHMEM_cuts    1\n TRLMEM_cuts    1\n TRMMEM_cuts    1\n   WREM_cuts    1\n```\ni.e, we still have the original number of bins and samples (this is what drives our sensitivity, so we don't want to compromise here), but we end up with only one sample and one uncertainty per bin.\n\nIt's not surprising to see then, that the computational performance of both is quite different. Let's have a look at a benchmark for this specific analysis:\n\n![Benchmark of ANA-SUSY-2019-08](examples/ANA-SUSY-2019-08/benchmark_1Lbb.png \"Benchmark of ANA-SUSY-2019-08\")\n\nIgnore the green bars for now and focus on the orange and blue ones instead. The orange (blue) ones show the wall times in seconds for the full (simplified) likelihood. In their fastest configurations, the simplified likelihood obviously is two orders of magnitude faster than the full likelihood.\n\nBut this isn't worth anything if the approximation isn't a good one. So let's have a look at how it performs. All the original signal models investigated by the analysis are contained in the `1Lbb-likelihoods` as a `JSON` patch file. Just patch each one onto the full and simplified likelihood, perform statistical inference using `pyhf` and then plot the results:\n\n![Performance of ANA-SUSY-2019-08](examples/ANA-SUSY-2019-08/exclusion_1Lbb_noLabel.png \"PErformance of ANA-SUSY-2019-08\")\n\nGiven the two orders of magnitude we gain in computational speed, this small loss in statistical precision is impressive! Within the one standard deviation uncertainties, there is basically no difference at all in both contours!\n\nP.S. I skipped quite a few steps to get to this figure. All of the necessary tools and scripts are available (and sometimes described) in my [pyhf_inference_tools](https://github.com/eschanet/pyhf_inference_tools).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feschanet%2Fsimplify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feschanet%2Fsimplify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feschanet%2Fsimplify/lists"}