Skip to content

ode2sbml.converters.mathml_utils

mathml_utils

MathML utilities: SymPy ↔ SBML-MathML conversion via sbmlmath.

formula_to_astnode(formula)

Convert a SymPy-parseable formula string to a libsbml ASTNode.

Conversion pipeline: 1. Validate the string (no np./math. prefixes) 2. sympify → SymPy expression (with Symbol locals to avoid name clashes) 3. Print to SBML MathML via sbmlmath 4. Strip sbml:units annotations and parse with libsbml.readMathMLFromString 5. Return the libsbml ASTNode

Falls back to libsbml.parseL3Formula for simple expressions if sbmlmath conversion fails.

Source code in ode2sbml/converters/mathml_utils.py
def formula_to_astnode(formula: str) -> libsbml.ASTNode:
    """
    Convert a SymPy-parseable formula string to a libsbml ASTNode.

    Conversion pipeline:
      1. Validate the string (no np./math. prefixes)
      2. sympify → SymPy expression (with Symbol locals to avoid name clashes)
      3. Print to SBML MathML via sbmlmath
      4. Strip sbml:units annotations and parse with libsbml.readMathMLFromString
      5. Return the libsbml ASTNode

    Falls back to ``libsbml.parseL3Formula`` for simple expressions if
    sbmlmath conversion fails.
    """
    _check_for_invalid_symbols(formula)

    try:
        expr = _sympify_formula(formula)
    except Exception as exc:
        raise ValueError(f"Cannot parse formula '{formula}': {exc}") from exc

    return sympy_to_astnode(expr)

sympy_to_astnode(expr)

Convert a SymPy expression to a libsbml ASTNode.

Source code in ode2sbml/converters/mathml_utils.py
def sympy_to_astnode(expr: sp.Expr) -> libsbml.ASTNode:
    """Convert a SymPy expression to a libsbml ASTNode."""
    expr = _preprocess_sympy(expr)

    try:
        mathml_str = SBMLMathMLPrinter().doprint(expr)
        mathml_str = _clean_mathml(mathml_str)
        node = libsbml.readMathMLFromString(mathml_str)
        if node is not None:
            return node
    except Exception:
        pass

    # Fallback: use libsbml's own L3 formula parser on the string representation
    formula_str = str(expr)
    node = libsbml.parseL3Formula(formula_str)
    if node is None:
        raise ValueError(f"Cannot convert expression '{expr}' to libsbml ASTNode.")
    return node

astnode_to_sympy(node)

Convert a libsbml ASTNode to a SymPy expression.

Source code in ode2sbml/converters/mathml_utils.py
def astnode_to_sympy(node: libsbml.ASTNode) -> sp.Expr:
    """Convert a libsbml ASTNode to a SymPy expression."""
    mathml = libsbml.writeMathMLToString(node)
    return SBMLMathMLParser().parse_str(mathml)

formula_to_mathml_str(formula)

Return the SBML MathML string for a formula.

Useful for debugging and testing.

Source code in ode2sbml/converters/mathml_utils.py
def formula_to_mathml_str(formula: str) -> str:
    """
    Return the SBML MathML string for a formula.

    Useful for debugging and testing.
    """
    _check_for_invalid_symbols(formula)
    expr = _sympify_formula(formula)
    expr = _preprocess_sympy(expr)
    return SBMLMathMLPrinter().doprint(expr)