Skip to main content

latex2code 🧮 ➡️ 🐍

Python Version License: MIT Code Style: Black

A lightweight Python library and CLI tool that transpiles a supported subset of LaTeX mathematical expressions into Python functions.

Designed for scientific computing, machine learning researchers, and engineers who want to bridge the gap between academic papers and executable code.


Features

  • 📐 Common Math: Translates arithmetic, fractions, powers, roots, limits, binomial coefficients, and common functions such as \sin, \cos, \tan, \exp, \log, \operatorname{erf}, \max, and hyperbolic functions.
  • 🔢 Greek Symbols & Constants: Common Greek-letter commands become variables; \pi and e are numeric constants.
  • 🔁 Matrix & Array Support: Converts LaTeX matrix environments (\begin{pmatrix}, \begin{bmatrix}, \begin{matrix}) and tabular/array layouts like \begin{array}{cc} ... \end{array} into numpy.ndarray objects.
  • 🧩 Piecewise Expressions: Recognizes \begin{cases} ... \end{cases} and emits Python conditional expressions.
  • 🔒 Absolute Values & Floor/Ceiling: Handles common wrappers like \left|x\right|, \left\lfloor x \right\rfloor, and \left\lceil x \right\rceil.
  • 🧮 Symbolic Operations: Uses SymPy to evaluate supported derivatives, limits, integrals, finite products, and nth roots; finite sums are emitted as executable Python.
  • 📐 Extended Trig & Inverse Functions: Supports reciprocal and inverse trig functions such as \csc, \arccot, \arcsec, and \arccsc.
  • 🤖 Machine-Learning Functions: Supports \operatorname{sigmoid}(x), \operatorname{relu}(x), \operatorname{softplus}(x), \operatorname{logit}(x), \operatorname{softsign}(x), and \operatorname{swish}(x) in scalar, NumPy, PyTorch, and JAX modes.
  • 🏷️ Type Annotations: Automatically generates functions with PEP 484 type hints.
  • 🔍 Inspection Reports: Shows the parsed symbolic expression, variables, warnings, and generated Python source.
  • 💻 Command Line Interface: Transpiles formulas directly from your terminal and accepts input from stdin.

This is a focused expression transpiler, not a complete LaTeX implementation or a computer algebra system.


Installation

Clone the repository and install in editable mode:

git clone https://github.com/ThulioASB/latex2code.git
cd latex2code
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
pip install -e .

Install an optional differentiable backend with one of the extras:

pip install -e ".[torch]"
pip install -e ".[jax]"

Usage

As a Python Library

from latex2code import transpile_latex

# Transpile a fraction with trigonometric functions
code = transpile_latex(r"\frac{\sin(x) + \cos(y)}{\sqrt{z}}", function_name="calculate_wave")
print(code)

Output:

import math

def calculate_wave(x: float, y: float, z: float) -> float:
    return (math.sin(x) + math.cos(y))/math.sqrt(z)

For direct evaluation in a notebook or application, use compile_latex. The returned object is callable and retains the generated source and inspection details:

import numpy as np
from latex2code import compile_latex

formula = compile_latex(
    r"\frac{\sin(x)}{\sqrt{x^2 + 1}}",
    backend="numpy",
)

x = np.linspace(0, 10, 100)
result = formula(x)

The convenience helper latex_to_code accepts the same keyword-only generation options as the main transpiler. Use variable_map to rename parsed symbols:

from latex2code import latex_to_code

code = latex_to_code(
    r"\theta + \lambda",
    function_name="signal_model",
    type_hints=False,
    variable_map={"lambda": "lambda_value"},
)
print(code)

The legacy custom_symbol_map and use_numpy Python arguments are deprecated. Use variable_map and backend="numpy" instead.

Choose a backend just as with transpile_latex; optional frameworks must be installed when compiling a formula for that backend. The callable uses only the arguments supplied by the caller and does not automatically move or cast array/tensor inputs.

Constants and Greek Variables

from latex2code import transpile_latex

code = transpile_latex(r"\sin(\pi x) + e + \theta", function_name="signal_response")
print(code)

Standard constants \pi and e are emitted as numeric constants by default. Other Greek-letter symbols such as \theta remain variables and appear in the generated function signature. Pass a constants mapping to customize substitutions; for example, constants={"pi": math.pi} leaves e as a function argument. Use args=["x", "w", "b"] to explicitly set argument order; the default follows each variable's first appearance in the input.

Text wrappers preserve their contents: \mathrm{e}^x retains the e, and \text{...} is not removed as if it were whitespace.

Inspecting a Transpilation

Use the inspection API to check how an expression was interpreted before using its generated source:

from latex2code import inspect_latex

details = inspect_latex(r"\sin(\pi x) + \theta")
print(details.input_expression)
print(details.backend)
print(details.parsed_expression)
print(details.expression_tree)
print(details.variables)
print(details.generated_code)
print(details.warnings)

The CLI's --inspect option prints the same information as JSON. Parse and unsupported-feature errors include a line and column with a short source excerpt when the location can be identified:

latex2code "\sin(\pi x) + \theta" --inspect

Use variable_map to give parsed symbols clearer Python argument names without changing the mathematics. Keys are parsed symbol names, and values must be unique Python identifiers:

from latex2code import compile_latex

model = compile_latex(
    r"\theta + \lambda",
    variable_map={"theta": "angle", "lambda": "wavelength"},
)
print(model(angle=0.5, wavelength=2.0))

Inspection reports include expression_tree, a JSON-compatible tree of SymPy operations and arguments, as well as the readable parsed_expression string.

Matrix Transpilation

from latex2code import transpile_latex

latex_matrix = r"\begin{pmatrix} x^2 & 1 \\ 0 & y \end{pmatrix}"
code = transpile_latex(latex_matrix, function_name="create_matrix", type_hints=False)
print(code)

Output:

import numpy as np

def create_matrix(x, y):
    return np.array([[x**2, 1], [0, y]])

Piecewise Expressions

from latex2code import transpile_latex

code = transpile_latex(
    r"\begin{cases} x & x > 0 \\ -x & x \le 0 \end{cases}",
    function_name="abs_value",
    type_hints=False,
)
print(code)

Output:

def abs_value(x):
    return (x) if (x > 0) else (-x)

Machine-Learning Activations

Common activation and link functions can be generated for scalar, NumPy, PyTorch, or JAX inputs:

from latex2code import transpile_latex

code = transpile_latex(
    r"\operatorname{sigmoid}(x)",
    function_name="logistic_probability",
    backend="numpy",
)
print(code)

The default python backend emits ordinary Python math. backend="numpy" supports NumPy arrays. The optional torch and jax backends generate operations using framework primitives so tensor autodiff can trace expressions; pass tensors/arrays of the chosen framework as inputs. These backends do not imply that every supported LaTeX construct has equivalent batching or gradient semantics. Named sigmoid, softplus, and swish operators use stable scalar or framework-native implementations. Writing equivalent expanded formulas manually (such as log(1 + exp(x))) is not guaranteed to receive this stabilization. Check input domains for logit, logarithms, and roots; the transpiler does not silently clip inputs.

torch_code = transpile_latex(r"\sin(x)^2 + x", backend="torch")
jax_code = transpile_latex(r"\sin(x)^2 + x", backend="jax")

Using Generated Code in Training or Analysis

Choose tensor dtype/device and array shape in your application; generated functions preserve framework operations and do not move or silently cast tensor inputs:

import torch

source = transpile_latex(r"\operatorname{softplus}(x) + x^2", backend="torch")
namespace = {}
exec(source, namespace)
formula = namespace["formula"]

x = torch.tensor([0.25, 1.0], dtype=torch.float64, device="cpu", requires_grad=True)
loss = formula(x).mean()
loss.backward()

For JAX, generated functions can be passed to jax.jit, jax.vmap, and jax.grad when the expression uses supported JAX primitives. Test the actual shapes and dtypes used by your workload.

Piecewise functions use eager elementwise selection (where) for array/tensor inputs: both branch expressions may be evaluated before selection. Avoid invalid operations in inactive branches (such as taking log(x) in a branch where x <= 0); use a formula with valid branch expressions or write a framework-specific implementation when true lazy control flow is required. Transpiling piecewise expressions for NumPy, PyTorch, or JAX emits a PiecewiseEvaluationWarning. Automatic domain clipping is intentionally not performed because it changes the formula and its gradients.

Reproducible Scientific Example: Gaussian Density

This normal probability density uses x, mu, and sigma in the same units; its output has inverse units. Require sigma > 0. At the mean, with sigma = 2, the density is 1 / (2 sqrt(2 pi)), approximately 0.19947114020071635:

from latex2code import compile_latex

density = compile_latex(
    r"\frac{1}{\sigma \sqrt{2 \pi}}"
    r"\exp(-\frac{(x-\mu)^2}{2 \sigma^2})"
)
value = density(x=0.0, mu=0.0, sigma=2.0)
print(value)  # 0.19947114020071635

The expression does not enforce sigma > 0; validate model parameters in the calling application. To evaluate arrays/tensors, select backend="numpy", "torch", or "jax" and choose the input dtype to suit the calculation's precision requirements.

Limits and Binomial Coefficients

from latex2code import transpile_latex

limit_code = transpile_latex(r"\lim_{x \to 0} \frac{\sin(x)}{x}", function_name="sinc_limit", type_hints=False)
print(limit_code)

binomial_code = transpile_latex(r"\binom{n}{k}", function_name="choose", type_hints=False)
print(binomial_code)

product_code = transpile_latex(r"\prod_{i=1}^{n} i", function_name="factorial_product", type_hints=False)
print(product_code)

Output:

def sinc_limit():
    return 1

import math

def choose(n, k):
    return (math.gamma(n + 1)/(math.gamma(k + 1)*math.gamma(-k + n + 1)))

import math

def factorial_product(n):
    return math.factorial(n)

CLI Usage

You can run latex2code directly from your command line:

latex2code "\frac{a}{b}" --name divide

You can also pipe input from standard input:

echo '\sin(x) + \cos(y)' | latex2code - --name signal

Write the generated source directly to a Python file with --output:

latex2code "\frac{a}{b}" --name divide --output divide.py

Select an output backend with --backend:

latex2code "\sin(x)^2 + x" --backend torch --output differentiable.py
latex2code "\sin(x)^2 + x" --backend jax --output differentiable.py

Generated source for PyTorch/JAX imports the selected framework, so install that framework in the environment where the generated file will run. Use --inspect to print a JSON report with the parsed expression, function variables, warnings, and source. Rename parsed symbols with repeatable --map-variable SYMBOL=NAME options:

latex2code "\theta + x" --map-variable theta=angle

Start an interactive session to paste and transpile expressions. Use --inspect to show the structured JSON report for each expression; quit or exit ends the session. For multiline expressions, enter :begin, paste the expression, then enter :end:

latex2code --interactive
latex2code --interactive --inspect --backend numpy

Options

Flag Long Option Description
-n --name Name of the generated Python function (default: formula).
--no-types Disable type hints in the generated signature.
--backend Select python, numpy, torch, or jax output (default: python).
-o --output Write generated Python source to a file instead of stdout.
--inspect Print JSON containing the parsed expression, variables, warnings, and generated source.
--map-variable SYMBOL=NAME Rename a parsed variable; may be repeated.
-i --interactive Read and transpile expressions until quit, exit, or end-of-file.

Running Tests

Run the test suite using pytest:

pytest

Supported Scope and Limitations

  • The table describes the supported shapes of input; it does not claim full TeX macro or document parsing.
Area Supported examples Notes
Arithmetic +, -, products, fractions, powers, roots, nth roots Parsed expressions follow SymPy's supported LaTeX grammar.
Functions Trigonometric, inverse/reciprocal trig, hyperbolic, exponential/logarithmic, erf, gamma, beta, max, min Function support can depend on backend printer support; beta is generated using log-gamma arithmetic.
ML operators sigmoid, relu, softplus, logit, softsign, swish Use \operatorname{...}(x); sigmoid, softplus, and swish use stable scalar/framework-native implementations.
Symbolic calculus Derivatives, limits, integrals, finite sums and reducible finite products SymPy evaluates operations when possible; unresolved products fail rather than emitting incomplete code.
Arrays and cases Matrix/array layouts, cases, selected aligned equation layouts Aligned equations are represented as rows of values, not solved as systems.
Inspection and names Parsed expression tree and variable-to-identifier mapping Mappings rename arguments only; they do not substitute values or change expression semantics.

Backend behavior below describes tested pathways, not a guarantee that every parser-supported function has equivalent semantics across targets:

Capability Python NumPy PyTorch JAX
Scalar arithmetic and common functions Yes Yes Yes, for generated native operations Yes, for generated native operations
Elementwise arrays/tensors No array contract NumPy broadcasting Pass tensors with desired dtype/device Pass arrays with desired dtype
Matrix/array constructors NumPy output for compatibility NumPy arrays Tensor output; gradients through dynamic entries JAX arrays
Piecewise array evaluation Python conditional expression where, eager branches where, eager branches where, eager branches
Automatic differentiation No No Yes, for differentiable native operations Yes, for differentiable native operations
JIT compilation No library guarantee No library guarantee No library guarantee jax.jit tested for supported primitives

PyTorch and JAX are optional runtime dependencies. Operations without a native differentiable implementation are rejected rather than silently replaced with Python math. JAX commonly defaults to 32-bit floating point; enable and verify 64-bit mode in the application when needed. Python and NumPy error/gamma functions can use Python math implementations wrapped for arrays, which may be slower than native array kernels.

  • Input is parsed strictly by SymPy's ANTLR-based LaTeX parser plus a restricted safe fallback, so malformed trailing tokens are rejected rather than silently discarded. Document markup, arbitrary TeX macros, and arbitrary custom functions are outside scope.
  • Presentation-only spacing commands such as \quad, \qquad, \,, \hspace{...}, and \vspace{...} are ignored. \displaystyle and related math-style commands are also ignored. Text wrappers and unknown macros are not stripped because they can carry mathematical meaning; remove or rewrite them explicitly if unsupported.
  • Function application and implicit multiplication follow the parser's documented grammar; no assumptions are made about custom function names or subscript semantics. Inspect the parsed expression/tree and explicitly rename variables instead of relying on guessed intent.
  • Unsupported commands and functions raise UnsupportedLaTeXFeatureError; close command/function spellings are suggested when possible. Malformed input raises InvalidLaTeXSyntaxError, which includes a source location and excerpt when identifiable, plus delimiter or environment hints when detected.
  • For example, a misspelled \sinn(x) reports the likely \sin command, while a fraction with an unmatched brace points out the unbalanced delimiters.
  • Piecewise cases without an explicit default remain undefined outside their listed conditions; generated Python returns None there, while NumPy mode represents those values as numpy.nan.
  • \pi and e are numeric constants; other Greek symbols may become function parameters. Use inspect_latex or CLI --inspect to review parsed variables and generated code.
  • Derivatives and integrals are evaluated symbolically when SymPy can do so. An indefinite integral returns one antiderivative and does not add the arbitrary constant of integration.
  • Finite sums are emitted as executable Python sum expressions. Matrices use the selected array backend (Python's matrix output remains a NumPy array for compatibility).
  • Finite products are symbolically evaluated when SymPy can reduce them; unresolved symbolic products raise CodeGenerationError rather than returning incomplete Python.
  • NumPy, PyTorch, and JAX operate elementwise where the framework supports the operation. Finite sums still use scalar iteration bounds.
  • Piecewise outputs use elementwise selection in array backends. Validate branch domains when an unselected branch could itself produce invalid values.
  • SymPy's current LaTeX grammar requires the antlr4-python3-runtime package (declared with a compatible version range); SymPy's Lark backend was evaluated but does not cover the expression grammar and constructs supported here.
  • Generated tensor code does not promise a particular device, dtype, or shape policy. Gamma has poles at non-positive integers; behavior at singularities and outside mathematical domains follows the selected backend.
  • Generated Python is not a mathematical proof or a guarantee of numerical stability. Review and test output before relying on it in research or production calculations.

License

Distributed under the MIT License. See LICENSE for more information.

Metadata

Release files for latex2code 0.2.1

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

Source distribution (sdist)

Source distribution for latex2code 0.2.1
File Size Uploaded
latex2code-0.2.1.tar.gz 43.3 kB Details

Built distribution (wheel)

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

Total release size: 72.5 kB

Release files / latex2code-0.2.1.tar.gz

Download URL latex2code-0.2.1.tar.gz
Size 43.3 kB
Tags Source
SHA-256 checksum
How to use checksums
70c7e07f17716cace020fc2adb2f5f5465dab2a06ffd0e1c92965d69026472d5
BLAKE2b-256 checksum
How to use checksums
6a533a2d15d32fb2c13b4298c057741e53f6a14f9c869823ead0aab91b115ac0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / latex2code-0.2.1-py3-none-any.whl

Download URL latex2code-0.2.1-py3-none-any.whl
Size 29.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0485401a2bbc61866efc4544fc58281cd981d35f0e4c4d78f7ebdcb380865a29
BLAKE2b-256 checksum
How to use checksums
b52617cd3275955f7980f481a9b519962dfcf960b904c8b20b3177c5edd1ad0f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.0

2 release files

This release

0.2.1 This release

2 release files

0.2.0

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