net_to_sbml refuses a derived parameter that uses _pi() or _e(): BNG2.pl writes "k2 _pi()*k1" in the .net, and converting it raises "function call(s) '__bngsim_const_pi__' that net2sbml cannot translate to MathML"

Open Beginner friendly
#1,741 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@Montana is already working on this.

Since Nov 15, 2026.

  • #1765 by @Montana — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
68/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
python, xml
Domain
data

Research direction

Start in python/bngsim/convert/_sbml_writer.py, at _exprtk_to_ast and _normalize_exprtk, and check how the zero-argument _pi() becomes __bngsim_const_pi__ and why _e() is not rewritten. Reproduce with the script in the issue, which needs BNGPATH set. Done when net_to_sbml and net_to_omex convert a derived parameter using _pi() or _e() into <pi/> and <exponentiale/> in MathML, and the constant no longer appears in sedml_lossy.

Written by the indexing model from the issue text.

Description

bug

net_to_sbml, and so net_to_omex, refuse a network whose derived parameter uses BNGL's _pi() or _e(). With k2 _pi()*k1 declared, BNG2.pl 2.9.3 runs the model and writes k2 _pi()*k1 # ConstantExpression in the .net. Converting that network raises:

ConversionError: derived parameter 'k2': expression uses function call(s) '__bngsim_const_pi__' that net2sbml cannot translate to MathML.

_e() fails the same way, naming '_e'. BNG2.pl 2.9.3 rejects bare _pi and _e in a parameter, so the call form is the only way to write them. MathML has the constants <pi/> and <exponentiale/>.

The same constant in an action (setParameter("kr","_pi()*k1")) is left out of the SED-ML's standard elements, with a warning, and is recorded in sedml_lossy.

Found in the review of the branch for #1733. Reproduced on main at f9d245ff.

Repro (needs BNGPATH)

import os, subprocess, tempfile, warnings, zipfile, re
from pathlib import Path
import numpy as np, bngsim
from bngsim.convert import net_to_omex, read_sedml_protocol, read_omex
print("bngsim", bngsim.__file__)

def bng(model_text):
    d = Path(tempfile.mkdtemp()); (d / "m.bngl").write_text(model_text)
    subprocess.run(["perl", os.path.join(os.environ["BNGPATH"], "BNG2.pl"), "m.bngl"], cwd=d, check=True, capture_output=True)
    return d

def network(d):
    """The network as generate_network writes it."""
    bngsim.Model.from_bngl(d / "m.bngl", net_out=d / "gen.net", cache=False)
    return d / "gen.net"

for fn in ("_pi()", "_e()"):
    MODEL = f"""begin model
begin parameters
  k1 1
  k2 {fn}*k1
end parameters
begin seed species
  A() 100
  B() 0
end seed species
begin observables
  Molecules Atot A()
end observables
begin reaction rules
  A() <-> B() k1, k2
end reaction rules
end model
generate_network({{overwrite=>1}})
simulate({{method=>"ode",t_end=>1,n_steps=>1}})
"""
    d = Path(tempfile.mkdtemp()); (d / "m.bngl").write_text(MODEL)
    net = network(d)
    print(fn, "in the .net:", [l.strip() for l in net.read_text().splitlines() if " k2 " in l])
    try:
        net_to_omex(net, d / "m.omex", bngl=d / "m.bngl", gate="none")
        print("  net_to_omex: ok")
    except Exception as e:
        print("  net_to_omex:", type(e).__name__, str(e)[:200])
    try:
        bngsim.convert.net_to_sbml(net, validate=None); print("  net_to_sbml: ok")
    except Exception as e:
        print("  net_to_sbml:", type(e).__name__, str(e)[:120])

Output (main, f9d245ff)

_pi() in the .net: ['2 k2    _pi()*k1  # ConstantExpression', '2 2 1 k2 #_reverse__R1']
  net_to_omex: ConversionError derived parameter 'k2': expression uses function call(s) '__bngsim_const_pi__' that net2sbml cannot translate to MathML.
  net_to_sbml: ConversionError derived parameter 'k2': expression uses function call(s) '__bngsim_const_pi__' that net2sbml cannot translate to MathML.
_e() in the .net: ['2 k2    _e()*k1  # ConstantExpression', '2 2 1 k2 #_reverse__R1']
  net_to_omex: ConversionError derived parameter 'k2': expression uses function call(s) '_e' that net2sbml cannot translate to MathML.
  net_to_sbml: ConversionError derived parameter 'k2': expression uses function call(s) '_e' that net2sbml cannot translate to MathML.

Where to look

_exprtk_to_ast and _normalize_exprtk in python/bngsim/convert/_sbml_writer.py. The zero-argument call _pi() is apparently rewritten to an internal name, __bngsim_const_pi__, that is never turned into <pi/>; _e() is not rewritten at all. _walk_fix_pi handles a bare pi name only.

Dominant language
Python
Stars
3
Forks
5
Avg merge
1d 1h
Merged PRs (30d)
361

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from lanl/bngsim

All issues in lanl/bngsim

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.