Fast, Numba-compatible Akima/makima spline interpolation for regular and irregular grids
Project description
pyakima
pyakima is a fast, JIT-compatible Akima spline implementation written in
pure Python.
Akima splines are a type of cubic spline that can guarantee continuous differentiability and local behavior while minimizing overshoot on both regular and irregular interpolation grids.
pyakima ships a small object-oriented Python API for ordinary use and
Numba-friendly helper functions for building and evaluating splines inside
fully jitted code.
The implementation is fully typed (py.typed) and keeps the public surface
small:
AkimaSpline is an object-oriented interface which simplifies calls for non-jitted Python callers; it has only a constructor and a __call__ method.
For jitted workloads,
- The spline interpolation itself is represented as a set of coefficients stored in a
SplineCoeffsobject, computed once viamake_akima_coeffs. - The spline is called from
cubic_call, which selects the appropriate coefficients and evaluates the polynomial withspline_single_knot_eval.
The top panel slides one control point up and down: the pyakima makima fit
stays local and flat on either side of the spike, while a natural cubic spline
rings above and below it. The bottom panel zooms into a sharp kink to show the
three corner models pyakima exports:
non-rounded: Algorithm based on [1], comparable numerical behavior to GSL; note the unstable behavior is because the algorithm is non-differentiable at corners, not a peculiar limitation of this implementation [2].akima(SciPy parity) [3]. Discontinuous behavior is less severe thannon-rounded; slightly more prone to overshoot, and still has special edge-case handling.makimaModified Akima Algorithm [4]; recommended default Less overshoot thanakima, while mathematically guaranteed to preserve differentiability/continuous behavior at corners without special edge-case handling. Similar performance toakimain most cases.
The control points oscillate smoothly between regular uniform-grid spacing and an inverse-CDF-based spacing.
Such a spacing is similar to what might be used when using Akima splines for a PSD estimation task, or in approximating a function
with sharp features with as few control points as possible. Such uses with irregular grids are a key modern application of Akima splines,
and are of central importance to their utility in gravitational-wave detection applications, such as using trans-dimensional MCMC
to adaptively fit Akima splines to un-modeled gravitational-wave sources [5], [6], [7].
Cubic splines, such as scipy's default CubicSpline plotted above, oscillate wildly on the same irregularly-spaced grid, which typically makes them unsuitable for such analysis tasks.
Table of Contents
- Installation
- Quick Start
- Jitted Use
- Spline Options
- Regenerating the Demo
- Performance Snapshot
- Quality Gates
- Contributing
- License
- References
Installation
pip install pyakima
pyakima requires Python 3.10 or newer, NumPy, and Numba. The optional demo
dependencies are available with:
pip install "pyakima[demos]"
Note that pygsl_lite from the demos dependencies may not always succeed on a pip install; any demo that uses it recovers gracefully if it cannot be imported.
pyakima.demos.speed_demo can recover if none of the demos dependencies are present.
pyakima.demos.step_demo runs if only matplotlib is present.
Quick Start
import numpy as np
from pyakima import AkimaSpline
x = np.linspace(0.0, 10.0, 16)
y = np.sin(x)
spline = AkimaSpline(x, y, corner_model="makima", ext=3)
print(spline(2.5))
print(spline(np.linspace(-1.0, 11.0, 1000)))
AkimaSpline is the ergonomic Python interface. The class stores a compiled
coefficient bundle and dispatches scalar or vector evaluations to the fast
helper functions.
Jitted Use
Use make_akima_coeffs and cubic_call when the spline should be created or
evaluated from inside an njit function.
import numpy as np
from numba import njit
from pyakima import make_akima_coeffs, cubic_call
@njit
def build_and_evaluate(x: np.ndarray, y: np.ndarray, x_eval: np.ndarray) -> np.ndarray:
coeffs = make_akima_coeffs(x, y, corner_model=2)
return cubic_call(x_eval, coeffs, 0)
For lower-level control, call cubic_call_scalar,
cubic_call_vector, or cubic_call_vector_linear directly.
Spline Options
pyakima supports several Akima corner models:
AkimaSpline option |
helper option | Behavior |
|---|---|---|
"non-rounded" |
0 |
Wodicka/GSL-style non-rounded sharp corners. |
"akima" |
1 |
Classic Akima behavior, close to scipy method="akima". |
"makima" |
2 |
Modified Akima weights, close to scipy method="makima". |
Boundary handling uses SciPy-like ext values:
ext |
Out-of-bounds behavior |
|---|---|
0 |
Extrapolate. |
1 |
Return zero. |
3 |
Return the nearest boundary value. |
4 |
Return nan. |
ext=2 (raise on out-of-bounds) is not implemented. ext=4 is added for
NaN boundary handling. AkimaSpline defaults to ext=3.
Regenerating the Demo
pyakima.demos ships as an example subpackage; run it from a source checkout so
it can write the README assets:
pip install -e '.[demos]' # scipy, matplotlib, pygsl_lite
python -m pyakima.demos.animate_demo # writes assets/akima_demo_{light,dark}.gif
python -m pyakima.demos.animate_grid_demo # writes assets/akima_grid_{light,dark}.gif
python -m pyakima.demos.step_demo # writes assets/akima_step_{light,dark}.png
Performance Snapshot
Run python -m pyakima.demos.speed_demo to compare pyakima with the optional
SciPy and pygsl_lite backends available in your environment.
The current 0.1.0 snapshot was measured on a single Apple Silicon M3 core with
Python 3.14.6, Numba 0.66.0, NumPy 2.4.6, SciPy 1.17.1, and pygsl_lite
0.1.8. The demo used 50 repeats, with each repeat adaptively looped to at least
0.100 s, and a representative range of spline and caller sizes.
The full benchmark is available in
docs/benchmarks/m3_0_1_0_speeds.txt.
Highlights from that run:
pyakimawas minimum 1.7x faster than SciPyAkima1DInterpolatoracross all benchmarks.- Spline creation was about 5.7-32.6x faster than SciPy.
- With Python-call overhead, scalar evaluation was about 2.3x faster than SciPy but 0.3-0.4x slower than
pygsl_lite. When called fully jitted (no Python-call overhead), scalar evaluation was about 109-361x faster than SciPy and 18-52x faster thanpygsl_lite. - Python-call vector evaluation was faster than SciPy in every tested case (about 1.7-4.8x in the SciPy-style rows).
- Against
pygsl_lite, Python-call vector evaluation was faster once the call did enough work (for example, 1,000 or more evaluation points in the sampled cases), while scalar and tiny-vector cases can be dominated by dispatch overhead. - Fully jitted vector evaluation was faster than SciPy in every tested case
(about 1.7-29.0x). It was also faster than
pygsl_litefor most non-tiny vector workloads in the sample (about 2.3-11.2x for 1,000 or more evaluation points).
Benchmark results depend on hardware, Python/NumPy/Numba versions, and whether the call is made through Python or entirely inside jitted code.
Quality Gates
The CI suite checks the package with:
pytestunit test suite; pull requests todevonly test modern versions, while pull requests targetingmainrun for all supported versions.coverage.pybranch coverage; pull requests targetingmainare gated at 100% total coverage, while other targets use the development threshold in the coverage workflow.- strict
mypy, plus Pyrefly and Pyright type checking. - Ruff with
select = ["ALL"]andruff format, run throughprekpre-commit hooks. - Skylos dead-code detection.
- Pylint and pydoclint docstring/signature checks.
- source distribution and wheel builds, including install/import checks across the supported dependency range.
Useful local checks:
python -m pytest
NUMBA_DISABLE_JIT=1 python -m coverage run --branch --source=pyakima --omit='*/demos/*' -m pytest
python -m coverage report -m --fail-under=100
uvx prek run --all-files --show-diff-on-failure --color=always
uvx skylos pyakima tests
Contributing
Thank you for your interest in helping improve the repository!
Feature requests and bug reports can be made through GitHub Issues. Bug reports should be accompanied by a minimal reproducing example and description of the desired behavior.
Suggested contributions or fixes should be made through pull requests to dev.
All new code must be fully type annotated, and pass the static type-checking and linting rules; to reduce churn, ensure, at minimum, prek run --all-files passes before attempting to commit.
New core/utility functions should have full numpy-style docstrings (verify with pydoclint --style=numpy), and full unit test coverage, verified with:
NUMBA_DISABLE_JIT=1 python -m coverage run --branch --source=pyakima --omit='*/demos/*' -m pytest
python -m coverage report -m --fail-under=100
License
pyakima is distributed under the Apache License 2.0. See
LICENSE for the
full license text.
References
- G. Engeln-Müllges & F. Uhlig, Numerical Algorithms with C, Springer, 1996, ch. 13 "Akima and Renner Subsplines," Algorithm 13.1. ISBN 978-3-642-64682-9.
- Note: the internals of the GSL implementation have never been viewed by the repository author. However, calls to GSL exhibit near-identical behavior, supporting that the issue is algorithmic rather than due to implementation error.
- Akima, Hiroshi. "A new method of interpolation and smooth curve fitting based on local procedures." Journal of the ACM (JACM) , 17.4, 1970, pp. 589–602.
- C. Moler, Makima Piecewise Cubic Interpolation, Cleve's Corner (MathWorks blog), 2019.
- Detecting gravitational wave signals using a flexible model for the amplitude and frequency evolution. T Gupta, NJ Cornish. Physical Review D, 2024•APS arXiv:2404.11719.
- Model-agnostic gravitational-wave background characterization algorithm. T Knapp, PM Meyers, AI Renzini.Physical Review D, 2025•APS. arXiv:2507.08095
- “Precise analysis of gravitational waves from binary neutron star coalescence using Hilbert–Huang transform based on Akima spline interpolation.” Yoda, Itsuki et al. Progress of Theoretical and Experimental Physics (2023). DOI:10.1093/ptep/ptad101
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyakima-0.1.0.tar.gz.
File metadata
- Download URL: pyakima-0.1.0.tar.gz
- Upload date:
- Size: 46.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ce5b1b79b888f45fc1b51cd1b1bf92e0cf7880e8be6c235061f7815ec94acaa
|
|
| MD5 |
4ea0ed34b4be9976732672b94dd92d4c
|
|
| BLAKE2b-256 |
d0492579937f2654329fb406ac8fc57502a6313b79cea70c888ef3d97a13a1bd
|
Provenance
The following attestation bundles were made for pyakima-0.1.0.tar.gz:
Publisher:
publish.yml on mcdigman/pyakima
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyakima-0.1.0.tar.gz -
Subject digest:
5ce5b1b79b888f45fc1b51cd1b1bf92e0cf7880e8be6c235061f7815ec94acaa - Sigstore transparency entry: 2139150034
- Sigstore integration time:
-
Permalink:
mcdigman/pyakima@36a27b9616bef8172b768f0ec1f29d53dc178c83 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/mcdigman
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@36a27b9616bef8172b768f0ec1f29d53dc178c83 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyakima-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pyakima-0.1.0-py3-none-any.whl
- Upload date:
- Size: 32.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a455b6b46554618cac8f17e735c80e8558bf9927da41a85f000bcb53d6029e27
|
|
| MD5 |
ca18f0d901f228881b1d949975493b10
|
|
| BLAKE2b-256 |
2481e1ccccad57c8b1eac835bc8c65bce781ddb0336acdd81622847c0fa2589d
|
Provenance
The following attestation bundles were made for pyakima-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on mcdigman/pyakima
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyakima-0.1.0-py3-none-any.whl -
Subject digest:
a455b6b46554618cac8f17e735c80e8558bf9927da41a85f000bcb53d6029e27 - Sigstore transparency entry: 2139150085
- Sigstore integration time:
-
Permalink:
mcdigman/pyakima@36a27b9616bef8172b768f0ec1f29d53dc178c83 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/mcdigman
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@36a27b9616bef8172b768f0ec1f29d53dc178c83 -
Trigger Event:
release
-
Statement type: