Skip to content

mocquin/physipy

Repository files navigation

physipy

PyPI version Python versions Read the Docs Benchmarked by asv Ruff Checked with mypy pre-commit Downloads License: MIT Try it on Binder

physipy lets you manipulate physical quantities in Python — the association of a value (a scalar, a numpy.ndarray, and more) with a physical unit (such as meter or joule). Dimensional consistency is enforced automatically, so adding a length to a time raises an error instead of producing nonsense.

>>> from physipy import units, constants
>>> nm = units["nm"]      # nanometer
>>> hp = constants["h"]   # Planck's constant
>>> c  = constants["c"]   # speed of light
>>> E_ph = hp * c / (500 * nm)   # energy of a 500 nm photon
>>> print(E_ph)
3.9728917142978567e-19 kg*m**2/s**2
>>> E_ph.favunit = units["J"]    # choose a display ("favourite") unit
>>> print(E_ph)
3.9728917142978567e-19 J

Installation

physipy is published on PyPI. The core only needs numpy:

pip install physipy

Heavier dependencies are optional extras — install only what you use:

Extra Enables Pulls in
calculus physipy.calculus (integration / ODE / root finding) scipy
constants physical-constant values in physipy.constants scipy
plotting unit-aware matplotlib integration (setup_matplotlib) matplotlib
symbolic compound dimension parsing (Dimension("L**2/T")) and LaTeX sympy
all everything above all of them
pip install "physipy[plotting]"   # core + matplotlib integration
pip install "physipy[all]"        # everything

If you use an optional feature without its dependency installed, physipy raises a clear, actionable ImportError telling you which extra to install.

To work from source:

git clone https://github.com/mocquin/physipy
cd physipy
pip install -e ".[all]"

Why physipy?

  • Light-weight — two core classes (Dimension and Quantity) plus a few helpers; the rest is convenience.
  • Great numpy support — 150+ functions and ufuncs work transparently on quantities (see below).
  • pandas support via the companion package physipandas.
  • matplotlib support — unit-aware axes with a single setup_matplotlib() call.
  • Fast — on par with or faster than the main alternative packages, for both scalars and arrays.
  • Extensively unit-tested, performance tracked with airspeed velocity, and shipped with inline type hints (PEP 561).

Project goals

  • Few lines of code.
  • A simple architecture, built around only two classes (Dimension and Quantity).
  • High numpy compatibility.
  • Human-readable, fast-to-write syntax.

How it works

  • A Dimension represents a physical dimension, based on the SI system. It is essentially a dict mapping each base dimension to its exponent.
  • A Quantity is the association of a value (scalar, array, …) with a Dimension. It does not subclass numpy.ndarray, yet stays compatible with numpy ufuncs. Most of the work lives in this class.
  • By default a Quantity is displayed in SI units. Set its favunit (favourite unit) to display it differently — my_toe_length.favunit = mm.
  • Plenty of units (e.g. watt) and constants (e.g. the speed of light) ship with physipy. Your quantities, units, and constants are all Quantity objects.

numpy support

import numpy as np
from physipy import m, units

mm = units["mm"]

lengths = np.linspace(-3 * m, 4.5 * m, num=12)
print(lengths[4])
print(lengths.mean())

numpy is handled almost fully and transparently: basic operations, indexing, numpy functions and universal functions all work. Over 150 functions are implemented. A few limitations remain, but they can be worked around — see the numpy support page.

pandas support

pandas integrates with physipy through its extension API, provided by the companion package physipandas:

import numpy as np
import pandas as pd
from physipy import m
from physipandas import QuantityDtype, QuantityArray

c = pd.Series(QuantityArray(np.arange(10) * m), dtype=QuantityDtype(m))

print(type(c))                  # <class 'pandas.core.series.Series'>
print(c.physipy.dimension)      # L
print(c.physipy.values.mean())  # 4.5 m

See the physipandas repository for more.

matplotlib support

Call setup_matplotlib() once and matplotlib will label axes with units automatically:

import numpy as np
import matplotlib.pyplot as plt
from physipy import s, m, units, setup_matplotlib

setup_matplotlib()        # make matplotlib physipy-aware
mm = units["mm"]
ms = units["ms"]

x = np.linspace(0, 5) * s
x.favunit = ms
y = np.linspace(0, 30) * mm
y.favunit = mm

fig, ax = plt.subplots()
ax.plot(x, y)

See the matplotlib support page.

Widgets

A set of ipywidgets and PyQt widgets that understand units is available in a separate package, to make interactive exploration of results easier.

Performance

physipy's performance is tracked with airspeed velocity; results are published at https://mocquin.github.io/physipy/. A quick benchmark shows physipy is as fast as (or faster than) other well-known packages, for both scalars and arrays.

For an in-depth comparison see the quantities-comparison repository.

Alternative packages

For a detailed comparison of physipy with pint, astropy.units, unyt and others — design choices, pros/cons and implementation differences — see the Comparison with other packages page in the documentation.

There are many Python packages handling physical quantities. A non-exhaustive list (roughly by popularity):

astropy · sympy · pint · forallpeople · unyt · python-measurement · Unum · scipp · magnitude · numericalunits · buckingham · quantities · brian · quantiphy · pynbody · pyansys-units · natu · misu · openscm-units · and pysics, from which physipy was originally inspired.

Know another one? Contributions are welcome. For broader context, see this quantities-comparison repo, this talk, and this comparison table.

Development

git clone https://github.com/mocquin/physipy
cd physipy
uv sync --all-extras            # or: pip install -e ".[all]" --group dev
pre-commit install              # enable lint/format/type hooks on commit

pytest                          # run the test suite
ruff check . && ruff format .   # lint + format
mypy                            # type-check
mkdocs serve                    # preview the docs locally

Building distributions:

python -m build       # or: uv build

License

physipy is released under the MIT License — see LICENSE.

Acknowledgment

Hat tip to phicem and the pysics package, which inspired physipy. Check it out!

About

A python package that transparently handles physical quantities like 2 meters or `np.array([1, 2, 3]) Joule`

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages