Skip to content

Commit

Permalink
Merge branch 'main' into binomial-dist
Browse files Browse the repository at this point in the history
  • Loading branch information
HDembinski committed Aug 6, 2024
2 parents c8d11cf + 7da0422 commit e655e9f
Show file tree
Hide file tree
Showing 17 changed files with 254 additions and 99 deletions.
40 changes: 40 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Deploy

on:
push:
tags:
- '**'
workflow_dispatch:
pull_request:
paths:
- .github/workflows/deploy.yml

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref }}
cancel-in-progress: true

jobs:
deploy:
runs-on: ubuntu-latest

environment:
name: pypi
url: https://pypi.org/p/numba-stats
permissions:
id-token: write

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # needed by setuptools_scm
- uses: actions/setup-python@v5
with:
python-version: '3.12'

- run: python -m pip install --upgrade pip build
- run: python -m build
- run: python -m pip install --prefer-binary $(echo dist/*.whl)'[test]'
- run: python -m pytest

- uses: pypa/gh-action-pypi-publish@release/v1
if: github.event_name == 'push' && contains(github.event.ref, '/tags/')
28 changes: 0 additions & 28 deletions .github/workflows/release.yml

This file was deleted.

18 changes: 12 additions & 6 deletions .github/workflows/ci.yml → .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: CI
name: Test

on:
push:
Expand All @@ -8,19 +8,25 @@ on:
paths-ignore:
- '*.md'

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref }}
cancel-in-progress: true

env:
PIP_ONLY_BINARY: ":all:"

jobs:
build:
test:

runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.12"]
python-version: ["3.9", "3.12"]

steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- run: python -m pip install --upgrade pip
- run: python -m pip install --prefer-binary -e .[test]
- run: python -m pytest
- run: python -m pip install --upgrade pip nox
- run: nox -s test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ venv
*.egg-info
.vscode
bench/*.svg
.nox
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
repos:
# Standard hooks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
rev: v4.6.0
hooks:
- id: check-case-conflict
- id: check-docstring-first
Expand All @@ -33,13 +33,13 @@ repos:

# Ruff linter, replacement for flake8, pydocstyle, isort
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.2.2'
rev: 'v0.5.6'
hooks:
- id: ruff
args: [--fix, --show-fixes]

# Python formatting
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 24.2.0
rev: 24.8.0
hooks:
- id: black
1 change: 0 additions & 1 deletion MANIFEST.in

This file was deleted.

22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# numba-stats

![](https://img.shields.io/pypi/v/numba-stats.svg)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.13236518.svg)](https://doi.org/10.5281/zenodo.13236518)

We provide `numba`-accelerated implementations of statistical distributions for common probability distributions

We provide `numba`-accelerated implementations of common probability distributions.

* Uniform
* (Truncated) Normal
Expand Down Expand Up @@ -83,6 +85,16 @@ You won't get these errors when you call the numba-stats PDFs outside of a compi
but
`norm_pdf(1, 2, 3)` (as implemented above) will fail.

## Documentation

To get documentation, please use `help()` in the Python interpreter.

Functions with equivalents in `scipy.stats` follow the `scipy` calling conventions exactly, except for distributions starting with `trunc...`, which follow a different convention, since the `scipy` behavior is very impractical. Even so, note that the `scipy` conventions are sometimes a bit unusual, particular in case of the exponential, the log-normal, and the uniform distribution. See the `scipy` docs for details.

## Citation

If you use this package in a scientific work, please cite us. You can generate citations in your preferred format on the [Zenodo website](https://doi.org/10.5281/zenodo.13236518).

## Benchmarks

The following benchmarks were produced on an Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz against SciPy-1.10.1. The dotted line on the right-hand figure shows the expected speedup (4x) from parallelization on a CPU with four physical cores.
Expand Down Expand Up @@ -113,15 +125,9 @@ The `bernstein.density` does not profit from auto-parallelization, on the contra
![](docs/_static/bernstein.density.svg)
![](docs/_static/truncexpon.pdf.plus.norm.pdf.svg)

## Documentation

To get documentation, please use `help()` in the Python interpreter.

Functions with equivalents in `scipy.stats` follow the `scipy` calling conventions exactly, except for distributions starting with `trunc...`, which follow a different convention, since the `scipy` behavior is very impractical. Even so, note that the `scipy` conventions are sometimes a bit unusual, particular in case of the exponential, the log-normal, and the uniform distribution. See the `scipy` docs for details.

## Contributions

**You can help with adding more distributions, patches are very welcome.** Implementing a probability distribution is easy. You need to write it in simple Python that `numba` can understand. Special functions from `scipy.special` can be used after some wrapping, see submodule `numba_stats._special.py` how it is done.
**You can help with adding more distributions, patches are welcome.** Implementing a probability distribution is easy. You need to write it in simple Python that `numba` can understand. Special functions from `scipy.special` can be used after some wrapping, see submodule `numba_stats._special.py` how it is done.

## numba-stats and numba-scipy

Expand Down
2 changes: 0 additions & 2 deletions coverage.sh

This file was deleted.

50 changes: 50 additions & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""
Noxfile to orchestrate tests and computing coverage.
Pass extra arguments to pytest after --
"""

import nox
import sys

sys.path.append(".")
import python_releases

nox.needs_version = ">=2024.3.2"
nox.options.default_venv_backend = "uv|virtualenv"

ENV = {
"COVERAGE_CORE": "sysmon", # faster coverage on Python 3.12
}

PYPROJECT = nox.project.load_toml("pyproject.toml")
MINIMUM_PYTHON = PYPROJECT["project"]["requires-python"].strip(">=")
LATEST_PYTHON = str(python_releases.latest())

nox.options.sessions = ["test", "maxtest"]

# running in parallel with pytest-xdist does not make the tests faster


@nox.session(reuse_venv=True)
def test(session: nox.Session) -> None:
"""Run all tests."""
session.install("-e.[test]")
session.run("pytest", *session.posargs)


@nox.session(python=LATEST_PYTHON, reuse_venv=True)
def maxtest(session: nox.Session) -> None:
"""Run the unit and regular tests."""
session.install("-e.[test]")
session.run("pytest", *session.posargs, env=ENV)


# Python-3.12 provides coverage info faster
@nox.session(python="3.12", reuse_venv=True)
def cov(session: nox.Session) -> None:
"""Run covage and place in 'htmlcov' directory."""
session.install("-e.[test]")
session.run("coverage", "run", "-m", "pytest", env=ENV)
session.run("coverage", "html", "-d", "htmlcov")
session.run("coverage", "report", "-m")
41 changes: 40 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,47 @@
requires = ["setuptools>=42", "setuptools_scm[toml]>=3.4"]
build-backend = "setuptools.build_meta"

[project]
name = "numba-stats"
dynamic = ["version"]
requires-python = ">=3.9"
dependencies = ["numba>=0.53", "numpy>=1.20", "scipy>=1.5"]
authors = [{ name = "Hans Dembinski", email = "[email protected]" }]
readme = "README.md"
description = "Numba-accelerated implementations of scipy probability distributions and others used in particle physics"
license = { text = "MIT" }
classifiers = [
# complete classifier list: http://pypi.python.org/pypi?%3Aaction=list_classifiers
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Science/Research',
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3 :: Only',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: Implementation :: CPython',
]

[project.urls]
repository = "https://github.com/hdembinski/numba-stats"

[project.optional-dependencies]
test = [
"pytest>=6",
"pytest-cov>=5",
"pytest-benchmark>=4",
"pydocstyle>=6",
"coverage>=6",
]

[tool.setuptools.packages.find]
where = ["src"]

[tool.setuptools_scm]
write_to = "src/numba_stats/_version.py"

[tool.pytest.ini_options]
minversion = "6.0"
Expand Down
64 changes: 64 additions & 0 deletions python_releases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""Get the latest Python release which is online."""

import urllib.request
import re
from html.parser import HTMLParser
import gzip
from packaging.version import Version


class PythonVersionParser(HTMLParser):
"""Specialized HTMLParser to get Python version number."""

def __init__(self):
"""Initialize parser state."""
super().__init__()
self.versions = set()
self.found_version = False

def handle_starttag(self, tag, attrs):
"""Look for the right tag and store result in an attribute."""
if tag == "a":
for attr in attrs:
if attr[0] == "href" and "/downloads/release/python-" in attr[1]:
self.found_version = True
return

def handle_data(self, data):
"""Extract Python version from entry."""
if self.found_version:
self.found_version = False
match = re.search(r"Python (\d+\.\d+)", data)
if match:
self.versions.add(Version(match.group(1)))


def versions():
"""Get all Python release versions."""
req = urllib.request.Request("https://www.python.org/downloads/")
req.add_header("Accept-Encoding", "gzip")

with urllib.request.urlopen(req) as response:
raw = response.read()
if response.info().get("Content-Encoding") == "gzip":
raw = gzip.decompress(raw)
html = raw.decode("utf-8")

parser = PythonVersionParser()
parser.feed(html)

return parser.versions


def latest():
"""Return version of latest Python release."""
return max(versions())


def main():
"""Print all discovered release versions."""
print(" ".join(str(x) for x in sorted(versions())))


if __name__ == "__main__":
main()
37 changes: 0 additions & 37 deletions setup.cfg

This file was deleted.

8 changes: 0 additions & 8 deletions setup.py

This file was deleted.

Loading

0 comments on commit e655e9f

Please sign in to comment.