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"
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 68/100
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
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
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from lanl/bngsim
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
bug latent bug low priority
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
documentation
Difficulty 1/5 1-3 hours Newbie friendliness 91/100
Maintainers usually reply within 1 day
-
documentation
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
Maintainers usually reply within 1 day
-
benchmarks/README: 'perl BNG2.pl model.bngl' runs the whole protocol, not just generate_networkOpendocumentation
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
Similar issues
-
agents nolte-linux security skills
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
nolte/claude-shared#732 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
Maintainers usually reply within 2 days
-
[Bug] Source archive filter: dry run excludes SystemVerilog (.sv) files with no preflight warningOpen
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
FinanceFlash/unvibecode#906 ·
Maintainers usually reply within 1 day