Skip to content

Commit 676f8fa

Browse files
authored
Merge pull request #59 from SpeysideHEP/minuit
Minuit integration
2 parents 39bceda + 55b60e0 commit 676f8fa

34 files changed

+2023
-95
lines changed

.github/workflows/tests.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Tests
33
on:
44
pull_request:
55
branches: ["main", "releases/**"]
6-
types: [review_requested, opened]
6+
types: [opened, review_requested, ready_for_review, synchronize]
77
paths: ["src/**.py", "tests/**.py", "tests.yml"]
88
push:
99
branches: ["main", "releases/**"]
@@ -32,8 +32,20 @@ jobs:
3232
python -m pip install --upgrade pip
3333
python -m pip install pytest pytest-cov
3434
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
35-
python -m pip install -e .
35+
python -m pip install -e .[iminuit]
3636
- name: Test with pytest
3737
run: |
3838
python -c 'import spey;spey.about()'
39-
pytest --cov=spey tests/*py #--cov-fail-under 99
39+
pytest --cov --cov-branch --junitxml=junit.xml -o junit_family=legacy --cov-report=xml tests/*py #--cov-fail-under 99
40+
41+
- name: Upload coverage reports to Codecov
42+
uses: codecov/codecov-action@v5
43+
with:
44+
token: ${{ secrets.CODECOV_TOKEN }}
45+
slug: SpeysideHEP/spey
46+
47+
- name: Upload test results to Codecov
48+
if: ${{ !cancelled() }}
49+
uses: codecov/test-results-action@v1
50+
with:
51+
token: ${{ secrets.CODECOV_TOKEN }}

README.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
[![GitHub License](https://img.shields.io/github/license/SpeysideHEP/spey?style=plastic)](https://github.com/SpeysideHEP/spey/blob/main/LICENSE)
1515

1616
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/spey?style=plastic)
17+
[![PyPI Downloads](https://static.pepy.tech/personalized-badge/spey?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/spey)
18+
[![codecov](https://codecov.io/gh/SpeysideHEP/spey/graph/badge.svg?token=78Q76XFPTF)](https://codecov.io/gh/SpeysideHEP/spey)
1719

1820
## Outline
1921

@@ -38,9 +40,19 @@ python -m pip install --upgrade "git+https://github.com/SpeysideHEP/spey"
3840

3941
**Note that `main` branch may not be the stable version.**
4042

43+
To install a specific branch with pip, use the following command:
44+
45+
```bash
46+
python -m pip install git+https://github.com/SpeysideHEP/spey@<BRANCH>
47+
```
48+
49+
**Please be aware that non-released branches are not stable.**
50+
4151
## What is Spey?
4252

43-
Spey is a plug-in-based statistics tool that aims to collect all likelihood prescriptions under one roof. This provides users with the workspace to freely combine different statistical models and study them through a single interface. In order to achieve a module that can be used both with statistical model prescriptions, which has been proposed in the past and will be used in the future, Spey uses a so-called plug-in system where developers can propose their statistical model prescriptions and allow Spey to use them.
53+
Spey is a plug-in-based statistics framework designed to be fully backend-agnostic, providing a unified environment where all likelihood prescriptions can be compiled and accessed in one place. This enables users to flexibly combine diverse statistical models and analyse them through a single, coherent interface. In line with the **FAIR principles, ensuring that models are findable, accessible, interoperable, and reusable**, Spey adopts a modular plug-in system allowing developers to contribute statistical model prescriptions in a transparent and future-proof manner, ensuring compatibility with both current and evolving standards.
54+
55+
Finally, the name "Spey" originally comes from the Spey River, a river in the mid-Highlands of Scotland. The area "Speyside" is famous for its smooth whisky.
4456

4557
### What a plugin provides
4658

@@ -51,8 +63,6 @@ A quick intro on the terminology of spey plugins in this section:
5163
* Depending on the scope of the plugin, you may wish to provide additional (custom) operations and differentiability through various autodif packages such as ``autograd``
5264
or ``jax``. As long as they are implemented through a set of predefined function names spey can automatically detect and use them within the interface.
5365

54-
Finally, the name "Spey" originally comes from the Spey River, a river in the mid-Highlands of Scotland. The area "Speyside" is famous for its smooth whiskey.
55-
5666
### Currently available plug-ins
5767

5868
| Accessor | Description |

docs/api.rst

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Top-Level
2020
ExpectationType
2121
register_backend
2222
AvailableBackends
23+
set_optimiser
2324
get_backend
2425
get_backend_metadata
2526
get_backend_bibtex
@@ -44,18 +45,28 @@ Main Classes
4445
Base Classes
4546
------------
4647

48+
Backend Base
49+
~~~~~~~~~~~~
50+
4751
.. autoclass:: spey.BackendBase
4852
:members:
4953
:undoc-members:
5054

55+
Hypothesis Testing Base
56+
~~~~~~~~~~~~~~~~~~~~~~~
57+
5158
.. autoclass:: spey.base.hypotest_base.HypothesisTestingBase
5259
:members:
5360
:undoc-members:
5461

62+
Model Configuration
63+
~~~~~~~~~~~~~~~~~~~
64+
5565
.. autoclass:: spey.base.model_config.ModelConfig
5666
:members:
5767
:undoc-members:
5868

69+
5970
Statistical Model Combiner
6071
--------------------------
6172

@@ -142,9 +153,11 @@ Simple PDFs
142153
simple_pdf.Gaussian
143154
simple_pdf.MultivariateNormal
144155

156+
Developer Tools
157+
---------------
145158

146159
Exceptions
147-
----------
160+
~~~~~~~~~~
148161

149162
.. currentmodule:: spey.system.exceptions
150163

@@ -162,3 +175,15 @@ Exceptions
162175
CanNotFindRoots
163176
UnknownComputer
164177
CombinerNotAvailable
178+
179+
Logging
180+
~~~~~~~
181+
182+
.. currentmodule:: spey.system.logger
183+
184+
.. autosummary::
185+
:toctree: _generated/
186+
:nosignatures:
187+
188+
disable_logging
189+
capture_logs

docs/exclusion.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ The `allow_negative_signal` keyword controls which test statistic is used and re
7373

7474
For complex statistical models, optimizing the likelihood can be challenging and depends on the choice of optimizer. Spey uses SciPy for optimization and fitting tasks. Any additional keyword arguments not explicitly covered in the {func}`~spey.StatisticalModel.exclusion_confidence_level` function description are passed directly to the optimizer, allowing users to customize its behavior through the interface.
7575

76-
Below we compare the exclusion limits computed with each approach. This comparisson uses normal distribution for the likelihood ([`default.normal`](#normal)) background yields are set to $n_b$, uncertainties are shown with $\sigma$ and observations are given with $n$.
76+
Below we compare the exclusion limits computed with each approach. This comparisson uses normal distribution for the likelihood (`default.normal`) background yields are set to $n_b$, uncertainties are shown with $\sigma$ and observations are given with $n$.
7777

7878
```{figure} ./figs/comparisson_observed.png
7979
---

docs/index.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,24 @@ Welcome to the documentation of Spey
2424
:alt: Zenodo DOI
2525
:target: https://zenodo.org/badge/latestdoi/549515208
2626

27+
.. raw:: html
28+
29+
<a href="https://pepy.tech/projects/spey"><img src="https://static.pepy.tech/personalized-badge/spey?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads" alt="PyPI Downloads"></a>
30+
31+
What is Spey?
32+
-------------
33+
34+
Spey is a plug-in-based statistics framework designed to unify all likelihood models under a single, **backend-agnostic interface**. Its aim is to offer a common workspace where users can freely combine, analyse, and interpret statistical models built on entirely different backends. By standardising how likelihoods are accessed and evaluated, Spey facilitates seamless statistical inference across frameworks that would otherwise remain isolated.
35+
36+
At the core of Spey’s design lies a dedication to the `FAIR principles <https://www.nature.com/articles/sdata201618>`_, **ensuring that statistical models and tools are Findable, Accessible, Interoperable, and Reusable**. Spey only requires one key component from any model: the ability to compute the log-probability. Given this, it can carry out the full range of statistical tasks, including but not limited to fitting, calculating exclusion limits, computing :math:`\chi^2`, and running samplers, without being dependent on any specific backend.
37+
38+
This interoperability is made possible through Spey’s modular plug-in architecture. Developers can contribute their own statistical model prescriptions without modifying the Spey codebase. By publishing an independent Spey plug-in, following the guidelines detailed in the documentation, your model becomes automatically discoverable and usable by any Spey installation. The framework also provides built-in citation tools via metadata, ensuring contributors receive proper credit for their plug-ins.
39+
40+
With its flexible architecture, FAIR-driven approach, and emphasis on long-term sustainability, Spey provides a contemporary ecosystem for statistical inference that connects communities and tools across high-energy physics and beyond.
41+
42+
Finally, the name "Spey" originally comes from the Spey River, a river in the mid-Highlands of Scotland. The area "Speyside" is famous for its smooth whisky.
43+
44+
2745
.. toctree::
2846
:maxdepth: 2
2947
:caption: Contents:

docs/outreach.rst

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,21 @@ Talks
1010
* - Date
1111
- Event
1212
- Location
13-
* - June 18, 2024
13+
* - Nov 25, 2025
14+
- `MC&I XPAG Meeting <https://indico.cern.ch/event/1614906/>`_
15+
- CERN
16+
* - Jun 18, 2024
1417
- `Reinterpretation & OpenMAPP mini-workshop <https://indico.cern.ch/event/1420197/contributions/5988218/>`_
1518
- LPSC Grenoble, FR
16-
* - February 15, 2024
19+
* - Feb 15, 2024
1720
- `Electroweak and Beyond the Standard Model Physics at the EIC <https://www.int.washington.edu/program/schedule/24-87W>`_
1821
- INT, University of Washington, USA
19-
* - December 5, 2023
22+
* - Dec 5, 2023
2023
- `pyhf Users and Developers Workshop 2023 <https://indico.cern.ch/event/1294577/contributions/5685097/>`_
2124
- CERN
22-
* - October 12, 2023
25+
* - Oct 12, 2023
2326
- `PyHEP 2023 - "Python in HEP" Users Workshop <https://indico.cern.ch/event/1252095/contributions/5592415/>`_
2427
- Online
25-
* - August 30, 2023
28+
* - Aug 30, 2023
2629
- `8th workshop on (Re)interpretation of the LHC results for new physics <https://conference.ippp.dur.ac.uk/event/1178/contributions/6436/>`_
2730
- University of Durham, UK

docs/quick_start.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ Python >=3.8 is required. spey heavily relies on `numpy <https://numpy.org/doc/s
2424
which are all packaged during the installation with the necessary versions. Note that some
2525
versions may be restricted due to numeric stability and validation.
2626

27+
To install spey with `iminuit <https://scikit-hep.org/iminuit/>`_, use
28+
29+
.. code-block:: bash
30+
31+
>>> pip install spey[iminuit]
32+
33+
and iminuit functionality can be activated by :func:`~spey.set_optimiser` function.
34+
2735
What is Spey?
2836
-------------
2937

docs/releases/changelog-v0.2.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ Specific upgrades for the latest release can be found [here](https://github.com/
1010
* Add plug-in registry that does not require creating an entire package.
1111
([#60](https://github.com/SpeysideHEP/spey/pull/60))
1212

13+
* Iminuit is available to be used for optimisation as alternative to scipy.
14+
([#59](https://github.com/SpeysideHEP/spey/pull/59))
15+
1316
## Improvements
1417

1518
* Autograd has been upgraded to v1.7 which supports numpy 2.0
@@ -30,6 +33,9 @@ Specific upgrades for the latest release can be found [here](https://github.com/
3033
* Enable compatibility for Python 3.13, and the deprecation of `pkg_resources` has been addressed.
3134
([#56](https://github.com/SpeysideHEP/spey/pull/56))
3235

36+
* Multivariate Normal distribution now supports callable covariance matrix function.
37+
([#59](https://github.com/SpeysideHEP/spey/pull/59))
38+
3339
## Bug Fixes
3440

3541
* Control mechanism added in case of infinite determinant in covariance matrix.

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,6 @@
6565
],
6666
extras_require={
6767
"dev": ["pytest>=7.1.2", "pytest-cov>=3.0.0", "twine>=3.7.1", "wheel>=0.37.1"],
68+
"iminuit": ["iminuit>=2.22.0"],
6869
},
6970
)

src/spey/__init__.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import textwrap
66
from functools import lru_cache
77
from importlib.metadata import EntryPoint, entry_points
8+
from importlib.util import find_spec
89
from typing import Any, Callable, Dict, Iterable, List, Literal, Optional, Union
910

1011
from semantic_version import SimpleSpec, Version
@@ -459,6 +460,43 @@ def log_once(msg: str, log_type: Literal["warning", "error", "info", "debug"]) -
459460
}.get(log_type, log.info)(msg)
460461

461462

463+
def set_optimiser(name: str) -> None:
464+
"""
465+
Set optimiser for fitting interface.
466+
467+
Alternatively, optimiser can be set through terminal via
468+
469+
.. code:: bash
470+
471+
>>> export SPEY_OPTIMISER=<name>
472+
473+
spey will automatically track ``SPEY_OPTIMISER`` settings.
474+
475+
.. versionadded:: 0.2.6
476+
477+
Args:
478+
name (``str``): name of the optimiser, ``scipy`` or ``minuit``.
479+
"""
480+
log.debug(
481+
"Currently optimiser is set to: `%s`", os.environ.get("SPEY_OPTIMISER", "scipy")
482+
)
483+
if name in ["minuit", "iminuit"]:
484+
if find_spec("iminuit") is not None:
485+
os.environ["SPEY_OPTIMISER"] = "minuit"
486+
log.debug("Optimiser set to minuit.")
487+
else:
488+
log.error("iminuit package is not available.")
489+
elif name == "scipy":
490+
os.environ["SPEY_OPTIMISER"] = "scipy"
491+
log.debug("Optimiser set to scipy.")
492+
else:
493+
log.error(
494+
"Unknown optimiser: %s. The optimiser is set to %s",
495+
name,
496+
os.environ.get("SPEY_OPTIMISER", "scipy"),
497+
)
498+
499+
462500
if int(os.environ.get("SPEY_LOGLEVEL", -1)) >= 0:
463501
set_log_level(int(os.environ.get("SPEY_LOGLEVEL")))
464502

0 commit comments

Comments
 (0)