Skip to main content

symeval

Write a sympy expression, fill in pint quantities, and get the full derivation, that is (1) formula, (2) substituted values with units, and (3) the result with unit — rendered as LaTeX in your marimo or Jupyter notebook.

  • ✨ Crystal-clear — shows the full derivation: formula, values with units, and result
  • 🐍 Pure Python — drop into your interactive notebooks and other Python code, no special syntax, no cell magic, no Domain-Specific Language (DSL)
  • 📏 Unit-aware — pint quantities carry units through every step and convert to your chosen output unit
  • 🧮 Sympy-native — rearrange or simplify your formula symbolically first, then evaluate
  • 📊 DataFrame-ready — use quantity_evalf() to compute a new unit-aware column on a DataFrame
pip install symeval

Axial stress under a compressive force

from pint import Quantity
from sympy import Symbol
from symeval import sym_evalf

sigma = sym_evalf(
    expr=Symbol("F") / Symbol("A"),
    subs={Symbol("F"): Quantity(-680, "kN"), Symbol("A"): Quantity(10_580, "mm^2")},
    output_symbol=r"\sigma",
    output_unit="MPa",
    decimals=2,
)

$$\begin{align*} \sigma &= \frac{F}{A} \ &= \frac{,-680\ \mathrm{kN}}{,10580\ \mathrm{mm}^{2}} \ \sigma &= -6.43\times 10^{7}\ \mathrm{Pa} = -64.27\ \mathrm{MPa} \end{align*}$$

You can also build the sympy expression first and call .sym_evalf() as a method — useful when you want to do symbolic math before filling in numbers. Pass mode= to choose the rendering style; mode="verbose" adds an extra line showing all values converted to SI base units:

f_sym, a_sym = Symbol("F"), Symbol("A")
sigma_expr = f_sym / a_sym

sigma_expr.sym_evalf(
    subs={f_sym: Quantity(-680, "kN"), a_sym: Quantity(10_580, "mm^2")},
    output_symbol=r"\sigma",
    output_unit="MPa",
    decimals=2,
    mode="verbose",
)

$$\begin{align*} \sigma &= \frac{F}{A} \ &= \frac{,-680\ \mathrm{kN}}{,10580\ \mathrm{mm}^{2}} \ &= \frac{,-6.800\times 10^{5}\ \mathrm{N}}{,1.058\times 10^{-2}\ \mathrm{m}^{2}} \ \sigma &= -6.43\times 10^{7}\ \mathrm{Pa} = -64.27\ \mathrm{MPa} \end{align*}$$

mode="one_line" collapses the derivation onto a single line:

sigma_expr.sym_evalf(
    subs={f_sym: Quantity(-680, "kN"), a_sym: Quantity(10_580, "mm^2")},
    output_symbol=r"\sigma",
    output_unit="MPa",
    decimals=1,
    mode="one_line",
)

$$\sigma = \frac{F}{A} = \frac{,-680\ \mathrm{kN}}{,10580\ \mathrm{mm}^{2}} = -64.3\ \mathrm{MPa}$$

quantity_evalf() on a DataFrame

quantity_evalf is the numeric-only sibling of sym_evalf — same unit-aware evaluation, no LaTeX overhead. It's useful for applying a formula across every row of a DataFrame:

import polars as pl
from pint import Quantity
from sympy import Symbol
from symeval import quantity_evalf

f_sym, a_sym = Symbol("F"), Symbol("A")
sigma_expr = f_sym / a_sym

members = pl.DataFrame({
    "member_type": ["column", "column", "brace", "strut", "tie"],
    "section":     ["W14x90", "HSS8x8x5/8", "HSS6x6x3/8", "L4x4", "C8x11.5"],
    "F_kN":        [-720.0, -680.0, 340.0, -110.0, 250.0],
    "A_mm2":       [17_100.0, 10_580.0, 4_890.0, 1_870.0, 2_168.0],
})

def stress_MPa(row):
    return quantity_evalf(
        sigma_expr,
        subs={f_sym: Quantity(row["F_kN"], "kN"), a_sym: Quantity(row["A_mm2"], "mm^2")},
        output_unit="MPa",
    ).magnitude

members_with_stress = members.with_columns(
    pl.struct(["F_kN", "A_mm2"])
    .map_elements(stress_MPa, return_dtype=pl.Float64)
    .alias("sigma_MPa")
)
member_type section F_kN A_mm2 sigma_MPa
column W14x90 -720.00 17100.00 -42.11
column HSS8x8x5/8 -680.00 10580.00 -64.27
brace HSS6x6x3/8 340.00 4890.00 69.53
strut L4x4 -110.00 1870.00 -58.82
tie C8x11.5 250.00 2168.00 115.31

Then use sym_evalf to show the full derivation for any row you want to inspect:

sigma_expr.sym_evalf(
    subs={f_sym: Quantity(-680, "kN"), a_sym: Quantity(10_580, "mm^2")},
    output_symbol=r"\sigma",
    output_unit="MPa",
    decimals=1,
)

$$\begin{align*} \sigma &= \frac{F}{A} \ &= \frac{,-680\ \mathrm{kN}}{,10580\ \mathrm{mm}^{2}} \ \sigma &= -6.4\times 10^{7}\ \mathrm{Pa} = -64.3\ \mathrm{MPa} \end{align*}$$

Axial resistance of a steel HSS member

A worked example from CSA S16-17. Each sym_evalf result feeds into the next — F_e into $\lambda$, $\lambda$ into $C_r$, $C_r$ into $DCR$ — so the LaTeX rendering captures the full audit trail of a multi-step engineering check:

$$F_{e} = \frac{\pi^{2} E r_{y}^{2}}{L^{2} k^{2}} = \frac{\pi^{2} ,200\ \mathrm{GPa} ,\left(76.1\ \mathrm{mm}\right)^{2}}{,\left(6.5\ \mathrm{m}\right)^{2} ,1^{2}} = 0.271\ \mathrm{GPa}$$

$$\lambda = \left(\frac{F_{y}}{F_{e}}\right)^{n} = \left(\frac{,400\ \mathrm{MPa}}{,0.2706\ \mathrm{GPa}}\right)^{,1.34} = 1.689$$

$$C_{r} = A F_{y} \phi_{s} \left(\lambda + 1\right)^{- \frac{1}{n}} = ,10580\ \mathrm{mm}^{2} ,400\ \mathrm{MPa} ,0.85 \left(,1.6886 + 1\right)^{- \frac{1}{,1.34}} = 1.720\ \mathrm{MN}$$

$$DCR = \frac{C_{f}}{C_{r}} = \frac{,680\ \mathrm{kN}}{,1.7196\ \mathrm{MN}} = 0.395$$

See symeval_mo.py for the full reactive marimo notebook with input UIs.

Ideal Gas Law: symbolic rearrangement

Starting from $PV = nRT$, sympy.solve rearranges the equation symbolically for any variable, then the resulting expression feeds straight into sym_evalf:

$$\begin{align*} P &= \frac{R T n}{V} \ &= \frac{,8.314\ \frac{\mathrm{J}}{\left(\mathrm{K} \cdot \mathrm{mol}\right)} ,273.15\ \mathrm{K} ,1\ \mathrm{mol}}{,22.4\ \mathrm{l}} \ P &= 1.01\times 10^{5}\ \mathrm{Pa} = 101.39\ \mathrm{kPa} \end{align*}$$

See symeval_mo.py for the full reactive marimo notebook with input UIs.

Author

Built and maintained by Joost Gevaert at Bedrock.

Feedback & contributing

Found a bug or have a feature request? Open an issue — pull requests are welcome too. The package is a single marimo notebook (symeval_mo.py) with ## EXPORT-marked cells extracted into src/symeval/ via mobuild; see CLAUDE.md for the project layout and RELEASING.md for the release workflow.

Inspiration

License

Apache License 2.0 — see LICENSE.

Release files for symeval 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for symeval 0.4.0
File Size Uploaded
symeval-0.4.0.tar.gz 17.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for symeval 0.4.0
File Interpreter ABI Platform
symeval-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 32.5 kB

Release files / symeval-0.4.0.tar.gz

Download URL symeval-0.4.0.tar.gz
Size 17.6 kB
Tags Source
SHA-256 checksum
How to use checksums
8e0395782f61140f68a87b2622df9c61f5c2e9ecfdcc31ab9a5ca03450977951
BLAKE2b-256 checksum
How to use checksums
d47fe1c92d976db792f2be1d34af6b0bfa85e0ebc3dc86de232f60bbf140213a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / symeval-0.4.0-py3-none-any.whl

Download URL symeval-0.4.0-py3-none-any.whl
Size 14.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
088f8f09f217feaddc9d4beb43ef19b77c9b1f004049eb2c7e4643d98658ab73
BLAKE2b-256 checksum
How to use checksums
f8574e7a5b58075e95233aaf53f357140d3e07c5e7cf4b42404938f59c4ba5a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

0.5.2

2 release files

0.5.1

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

This release

0.4.0 This release

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page