from keecas import symbols, u, pc, show_eqn
# Basic parameter substitution
F, A_load = symbols(r"F, A_{load}")
_p = {
F: 100*u.kN,
A_load: 20*u.cm**2,
}
sigma = symbols(r"\sigma")
_e = {
sigma: "F / A_load" | pc.parse_expr,
}
# Substitute parameters into expression
result = _e[sigma] | pc.subs(_p)pipe_command
Pipe commands for functional composition of mathematical operations.
This module provides @Pipe decorated functions that enable chain operations like: expr | pc.subs(vals) | pc.convert_to(units) | pc.N
All functions are designed to work with SymPy expressions and support functional programming patterns for mathematical computation workflows.
Functions
| Name | Description |
|---|---|
| order_subs | Reorder substitutions using topological order for dependency resolution. |
| subs | Substitute variables in symbolic expressions with values or other expressions. |
| N | Numerically evaluate symbolic expressions to floating-point values. |
| convert_to | Convert quantities to different units while preserving values. |
| doit | Evaluate unevaluated operations in symbolic expressions. |
| parse_expr | Parse mathematical expression strings into SymPy symbolic objects. |
| quantity_simplify | Simplify expressions with units by combining and reducing quantities. |
| as_two_terms | Split expression into magnitude and units components. |
| as_Mul | Create unevaluated multiplication from tuple of expressions. |
order_subs
order_subs(subs)Reorder substitutions using topological order for dependency resolution.
Ensures that substitutions are applied in the correct order when variables depend on each other (e.g., y depends on x, so x must be substituted first).
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| subs | dict[Basic, Any] |
Dictionary of substitutions where keys are variables and values are expressions | required |
Returns
| Name | Type | Description |
|---|---|---|
list[tuple[Basic, Any]] |
Ordered list of substitution tuples for exhaustive application |
subs
subs(expression, substitution, sorted=True)Substitute variables in symbolic expressions with values or other expressions.
Applies substitutions to SymPy expressions while handling dependencies between variables. Commonly used in workflows to evaluate symbolic equations with parameters from _p dicts or intermediate expressions from _e dicts. Integrates with pipe operations for functional composition.
NOTE: Returns None if input expression is None, allowing chain operations to gracefully handle missing values.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | Basic |
SymPy expression to apply substitutions to. Can be any symbolic expression containing variables to be replaced. | required |
| substitution | dict[Basic, Any] |
Dictionary mapping variables (symbols) to their replacement values (numeric values, quantities with units, or other expressions). Non-Basic keys and None values are automatically filtered out. | required |
| sorted | bool |
Whether to apply topological sorting for dependency resolution. When True (default), automatically orders substitutions so that dependent variables are substituted in correct order (e.g., if y depends on x, x is substituted first). Defaults to True. | True |
Returns
| Name | Type | Description |
|---|---|---|
Basic |
SymPy expression with substitutions applied, or None if input is None. |
Examples
# Multi-step workflow with merged dicts
_v = {
k: v | pc.subs(_p | _e) | pc.convert_to([u.MPa]) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} F & = 100{\,}\text{kN} & \\[8pt] A_{load} & = 20{\,}\text{cm}^{2} & \\[8pt] \sigma & = \dfrac{F}{A_{load}} & = 50.0{\,}\text{MPa} \end{align}\]
# Dependency resolution with sorted=True
x, y, z = symbols(r"x, y, z")
# y depends on x, z depends on y
_e = {
z: "x + y" | pc.parse_expr,
y: "2 * x" | pc.parse_expr,
x: 5,
}
# Automatic ordering: x first, then y, then z
result = z | pc.subs(_e) # sorted=True by defaultNotes
- Automatically filters out None values and non-Basic keys from substitution dict
- Topological sorting handles complex dependency chains automatically
- Works seamlessly with Pint quantities through SymPy integration
- Common pattern:
_p | _emerges parameters and expressions for substitution
N
N(expression, precision=15)Numerically evaluate symbolic expressions to floating-point values.
Converts symbolic expressions containing irrational numbers, constants, or unevaluated operations into numeric approximations. Commonly used as final step in calculation workflows before display with show_eqn().
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | Basic |
SymPy expression to evaluate numerically. Can contain symbolic math operations, constants (pi, e, etc.), or quantities with units. | required |
| precision | int |
Number of decimal digits for evaluation. Controls internal calculation precision, not display formatting (use float_format in show_eqn for display). Defaults to 15. | 15 |
Returns
| Name | Type | Description |
|---|---|---|
Basic |
Numerically evaluated SymPy expression as floating-point approximation. |
Examples
from keecas import symbols, u, pc, show_eqn
from sympy import pi
# Basic numeric evaluation
r = symbols(r"r")
A_circle = symbols(r"A_{circle}")
_p = {
r: 5*u.cm,
}
_e = {
A_circle: "pi * r**2" | pc.parse_expr,
}
# Evaluate symbolic pi to numeric value
_v = {
k: v | pc.subs(_p | _e) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} r & = 5{\,}\text{cm} & \\[8pt] A_{circle} & = \pi{\,}r^{2} & = 78.5398163397448{\,}\text{cm}^{2} \end{align}\]
# Control precision for high-accuracy calculations
import sympy as sp
expr = sp.sqrt(2)
# Default precision (15 digits)
result_default = expr | pc.N
# High precision (50 digits)
result_high = expr | pc.N(precision=50)# Typical workflow: subs -> convert_to -> N
F, A_load, sigma_Sd = symbols(r"F, A_{load}, \sigma_{Sd}")
_p = {
F: 850*u.kN,
A_load: 120*u.cm**2,
}
_e = {
sigma_Sd: "F / A_load" | pc.parse_expr,
}
_v = {
k: v | pc.subs(_p | _e) | pc.convert_to([u.MPa]) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} F & = 850{\,}\text{kN} & \\[8pt] A_{load} & = 120{\,}\text{cm}^{2} & \\[8pt] \sigma_{Sd} & = \dfrac{F}{A_{load}} & = 70.8333333333333{\,}\text{MPa} \end{align}\]
Notes
- Precision parameter controls internal calculation accuracy, not display
- For display formatting, use float_format parameter in show_eqn()
- Works with Pint quantities, preserving units in output
- Commonly chained after subs() and convert_to() in evaluation workflows
convert_to
convert_to(expression, units=1)Convert quantities to different units while preserving values.
Converts SymPy expressions with units to target units, handling both prefixed units (kN, daN, cm) and compound units (MPa, kN/m). Commonly used in engineering workflows to standardize units before display or comparison. Integrates seamlessly with Pint unit definitions.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | Basic |
SymPy expression with units to convert. Must contain dimensional quantities (e.g., force, pressure, length). | required |
| units | Any |
Target units for conversion. Can be: - Single unit (e.g., u.MPa) - List of units (e.g., [u.kN, u.mm]) - Compound units (e.g., u.kN/u.m) Defaults to 1 (dimensionless). | 1 |
Returns
| Name | Type | Description |
|---|---|---|
Basic |
Expression converted to target units with same magnitude in new units. |
Examples
from keecas import symbols, u, pc, show_eqn
# Basic unit conversion
F, A_load = symbols(r"F, A_{load}")
_p = {
F: 5000*u.N, # Newtons
A_load: 120*u.cm**2,
}
# Convert to kilonewtons
_v = {
F: _p[F] | pc.convert_to(u.kN),
A_load: _p[A_load] | pc.convert_to(u.m),
}
show_eqn([_p, _v])\[\begin{align} F & = 5000{\,}\text{N} & = 5{\,}\text{kN} \\[8pt] A_{load} & = 120{\,}\text{cm}^{2} & = \dfrac{3}{250}{\,}\text{m}^{2} \end{align}\]
# Compound unit conversion
sigma = symbols(r"\sigma")
_p = {
F: 850*u.kN,
A_load: 120*u.cm**2,
}
_e = {
sigma: "F / A_load" | pc.parse_expr,
}
# Convert pressure to MPa
_v = {
k: v | pc.subs(_p | _e) | pc.convert_to(u.MPa) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} F & = 850{\,}\text{kN} & \\[8pt] A_{load} & = 120{\,}\text{cm}^{2} & \\[8pt] \sigma & = \dfrac{F}{A_{load}} & = 70.8333333333333{\,}\text{MPa} \end{align}\]
# List of target units for flexibility
L, delta = symbols(r"L, \delta")
_p = {
L: 8*u.m,
}
_e = {
delta: "L / 400" | pc.parse_expr,
}
# Try converting to mm, fallback to other units if needed
_v = {
k: v | pc.subs(_p | _e) | pc.convert_to([u.mm]) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} L & = 8{\,}\text{m} & \\[8pt] \delta & = \dfrac{L}{400} & = 20.0{\,}\text{mm} \end{align}\]
Notes
- Prefixed units (kN, cm, MPa) handled automatically via SymPy prefix system
- Non-prefixed units (kgf, lbf) use scale factors from Pint definitions
- All Pint units convert correctly through SymPy integration
- Commonly chained between subs() and N() in evaluation workflows
- List of units allows flexible conversion with fallback options
doit
doit(expression)Evaluate unevaluated operations in symbolic expressions.
Forces evaluation of operations that SymPy keeps in symbolic form, such as derivatives, integrals, summations, or limits. Useful when symbolic operations need numeric results or simplified forms.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | Basic |
SymPy expression containing unevaluated operations (derivatives, integrals, summations, limits, etc.) that should be evaluated. | required |
Returns
| Name | Type | Description |
|---|---|---|
Basic |
Expression with all unevaluated operations evaluated to their results. |
Examples
from keecas import symbols, pc
import sympy as sp
# Evaluate derivative
x = symbols(r"x")
expr = sp.Derivative(x**2, x)
# Without doit: shows Derivative(x**2, x)
print(expr)
# With doit: evaluates to 2*x
result = expr | pc.doit
print(result)Derivative(x**2, x)
2*x
# Evaluate integral
integral_expr = sp.Integral(sp.sin(x), x)
# Evaluates to -cos(x)
result = integral_expr | pc.doit# Use in calculation workflow
from keecas import u, show_eqn
F, x_coord = symbols(r"F, x")
_p = {
F: 100*u.kN,
}
# Expression with derivative
_e = {
symbols(r"dF/dx"): sp.Derivative(F * x_coord**2, x_coord),
}
# Evaluate derivative then substitute
_v = {
k: v | pc.doit | pc.subs(_p) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} F & = 100{\,}\text{kN} & \\[8pt] dF/dx & = \dfrac{\partial}{\partial x} F{\,}x^{2} & = 200.0{\,}x{\,}\text{kN} \end{align}\]
Notes
- Works with derivatives, integrals, limits, summations, and products
- May be needed before subs() to properly substitute into evaluated forms
- Not all operations can be evaluated symbolically (may return unchanged)
- Combines well with other pipe commands in calculation workflows
parse_expr
parse_expr(expression, local_dict=None, evaluate=False, **kwargs)Parse mathematical expression strings into SymPy symbolic objects.
Converts string representations of mathematical expressions into SymPy expressions that can be manipulated symbolically. Most commonly used with pipe operator to define expressions in _e dicts using readable string notation instead of verbose SymPy syntax.
NOTE: Automatically captures local variables from caller’s scope when local_dict is None, enabling clean string-based expression definitions.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | str |
String representation of mathematical expression using standard notation (e.g., “F / A”, “pi * r**2”, “sqrt(x2 + y2)”). Supports operators: +, -, *, /, **, parentheses, and common functions. | required |
| local_dict | dict[str, Any] | None |
Dictionary of local variables for parsing context (symbol definitions, parameters, functions). If None, automatically uses caller’s local variables from enclosing scope. Defaults to None. | None |
| evaluate | bool |
Whether to evaluate the expression during parsing (e.g., simplify numeric operations). When False, preserves structure as written. Defaults to False. | False |
| **kwargs | Any |
Additional arguments passed to SymPy’s parse_expr: - transformations: List of parsing transformations (defaults to T[:11]) - global_dict: Global symbol dictionary - rational: Whether to convert floats to rationals | {} |
Returns
| Name | Type | Description |
|---|---|---|
Basic |
Parsed SymPy expression object ready for symbolic manipulation. |
Examples
from keecas import symbols, u, pc, show_eqn
# Most common pattern: define expressions as strings
F, A_load, sigma = symbols(r"F, A_{load}, \sigma")
_p = {
F: 100*u.kN,
A_load: 20*u.cm**2,
}
# Use parse_expr to convert string to SymPy expression
_e = {
sigma: "F / A_load" | pc.parse_expr,
}
_v = {
k: v | pc.subs(_p | _e) | pc.convert_to([u.MPa]) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} F & = 100{\,}\text{kN} & \\[8pt] A_{load} & = 20{\,}\text{cm}^{2} & \\[8pt] \sigma & = \dfrac{F}{A_{load}} & = 50.0{\,}\text{MPa} \end{align}\]
# Complex expressions with functions
from sympy import pi
r, A_circle, V_sphere = symbols(r"r, A_{circle}, V_{sphere}")
_p = {
r: 5*u.cm,
}
_e = {
A_circle: "pi * r**2" | pc.parse_expr,
V_sphere: "(4/3) * pi * r**3" | pc.parse_expr,
}
_v = {
k: v | pc.subs(_p | _e) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} r & = 5{\,}\text{cm} & \\[8pt] A_{circle} & = \pi{\,}r^{2} & = 78.5398163397448{\,}\text{cm}^{2} \\[8pt] V_{sphere} & = \dfrac{4{\,}\pi{\,}r^{3}}{3} & = 523.598775598299{\,}\text{cm}^{3} \end{align}\]
# Custom local_dict for additional functions
from sympy import sqrt
custom_locals = {
'special_func': lambda x: sqrt(x**2 + 1),
}
expr = "special_func(5)" | pc.parse_expr(local_dict=custom_locals)# Multiple dependent expressions
x, y, z, result = symbols(r"x, y, z, result")
_p = {
x: 3,
y: 4,
}
# Expressions can reference each other
_e = {
z: "sqrt(x**2 + y**2)" | pc.parse_expr,
result: "z * 2" | pc.parse_expr,
}
# tip: automatic dependency resolution with pc.subs
_v = {
k: v | pc.subs(_p | _e) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} x & = 3 & \\[8pt] y & = 4 & \\[8pt] z & = \sqrt{x^{2} + y^{2}} & = 5.0 \\[8pt] result & = z{\,}2 & = 10.0 \end{align}\]
Notes
- Uses transformations T[:11] by default for standard mathematical parsing
- Automatically captures caller’s local scope for symbol resolution
- Common functions supported: sin, cos, sqrt, log, exp, abs, etc.
- Operators: +, -, *, /, ** (power), parentheses for grouping
- Cleaner than verbose SymPy syntax: “F/A” vs sp.Div(F, A)
- Idiomatic pattern: define symbols, then use string expressions in _e dict
quantity_simplify
quantity_simplify(
expression,
across_dimensions=True,
unit_system='SI',
**kwargs,
)Simplify expressions with units by combining and reducing quantities.
Applies SymPy’s quantity simplification to combine terms with compatible units and reduce complex unit expressions. Useful for cleaning up expressions with multiple unit terms or dimensional analysis.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | Basic |
SymPy expression to simplify, typically containing multiple terms with units that can be combined or reduced. | required |
| across_dimensions | bool |
Whether to simplify across different dimensions (e.g., combine force and length into energy). When True, allows broader simplifications. Defaults to True. | True |
| unit_system | str |
Unit system for simplification, determines which base units to use. Options include “SI”, “CGS”, “imperial”. Defaults to “SI”. | 'SI' |
| **kwargs | Any |
Additional arguments passed to SymPy’s quantity_simplify: - across_dimensions: Override the across_dimensions parameter - unit_system: Override the unit_system parameter | {} |
Returns
| Name | Type | Description |
|---|---|---|
Basic |
Simplified SymPy expression with combined and reduced unit terms. |
Examples
from keecas import symbols, u, pc, show_eqn
# Simplify expression with multiple force terms
F_1, F_2, F_total = symbols(r"F_1, F_2, F_{total}")
_p = {
F_1: 100*u.kN,
F_2: 50000*u.N,
}
_e = {
F_total: "F_1 + F_2" | pc.parse_expr,
}
# Simplify combines terms with compatible units
_v = {
k: v | pc.subs(_p | _e) | pc.quantity_simplify | pc.convert_to([u.kN]) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} F_{1} & = 100{\,}\text{kN} & \\[8pt] F_{2} & = 50000{\,}\text{N} & \\[8pt] F_{total} & = F_{1} + F_{2} & = 150.0{\,}\text{kN} \end{align}\]
# Dimensional analysis with unit simplification
F, d, E = symbols(r"F, d, E")
_p = {
F: 500*u.N,
d: 2*u.m,
}
# Work (energy) from force and distance
_e = {
E: "F * d" | pc.parse_expr,
}
# Simplify to base energy units
_v = {
k: v | pc.subs(_p | _e) | pc.quantity_simplify | pc.convert_to([u.J]) | pc.N
for k, v in _e.items()
}
show_eqn([_p | _e, _v])\[\begin{align} F & = 500{\,}\text{N} & \\[8pt] d & = 2{\,}\text{m} & \\[8pt] E & = F{\,}d & = 1000.0{\,}\text{J} \end{align}\]
# Different unit systems
from sympy import sympify
from sympy.physics.units import newton, kilonewton
# Create expression with different unit prefixes
expr = 100*kilonewton + 5000*newton
# Simplify combines compatible units
result = expr | pc.quantity_simplify(unit_system="SI")
print(result) # Combines to single unit105000*newton
Notes
- Combines terms with compatible units (e.g., kN + N -> kN)
- Simplifies compound units to base units when appropriate
- across_dimensions=True enables dimensional analysis simplifications
- Works with both SI and other unit systems
- May need convert_to() afterward to get desired output units
as_two_terms
as_two_terms(expression, as_mul=False)Split expression into magnitude and units components.
Separates multiplicative expressions or matrices into two terms, typically magnitude and units for cleaner display.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | Basic |
SymPy expression to split | required |
| as_mul | bool |
If True, return as unevaluated multiplication | False |
Returns
| Name | Type | Description |
|---|---|---|
Basic | tuple[Basic, Basic] |
Two-term tuple or unevaluated multiplication, depending on as_mul. | |
Basic | tuple[Basic, Basic] |
Returns original expression if splitting is not applicable. |
Notes
For matrices, splits only if all elements share the same units.
as_Mul
as_Mul(expression)Create unevaluated multiplication from tuple of expressions.
Multiplies two expressions while keeping them visually separated, ideal for displaying magnitude and units distinctly.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| expression | tuple[Basic, Basic] |
Tuple containing two SymPy expressions to multiply | required |
Returns
| Name | Type | Description |
|---|---|---|
Basic |
Unevaluated multiplication expression for clean display |