Summary
bionetgen.run() raises ValueError while building its BNGResult whenever BNG2.pl writes a ragged .cdat. run_network does this for SSA on networks where some species are unpopulated at t=0 and become populated during the run: the per-row species-column count grows over the trajectory while the header line stays fixed at the initial count. result.py:_load_dat builds a fixed NumPy dtype from the header and calls np.loadtxt(path, dtype={...}), which requires every row to have the same width and aborts on the first wider row.
The simulation itself succeeds and the output files are written correctly — only the post-run load-back into BNGResult fails, which makes the whole run() call fatal even though a perfectly good .gdat is on disk.
Error
File ".../bionetgen/core/tools/result.py", line 176, in _load_dat
return np.rec.array(np.loadtxt(path, dtype={"names": names, "formats": formats}))
...
ValueError: the dtype passed requires 26 columns but 27 were found at row 2; use `usecols` to select a subset and avoid this error
Reproduction
Any SSA run on a network with species unpopulated at t=0 triggers it. For example, agentCellSystem with a capped network:
generate_network({overwrite=>1,max_iter=>3,max_agg=>4})
simulate({method=>"ssa",seed=>1,t_start=>0,t_end=>1,n_steps=>20,print_CDAT=>1})
import bionetgen
bionetgen.run("model.bngl", out="out")
The produced .cdat has a fixed-width header but data rows whose width grows as species first appear, e.g.:
header (incl. # and time): 27 tokens
data row widths: 26, 27, 28, 34, 36, 38, 40, 42
The .gdat (a fixed observable set) loads fine. The same model under method=>"ode" writes a dense .cdat that loads fine. The ragged .cdat is itself reproducible byte-for-byte across runs (fixed seed) — it is well-defined output, just not rectangular.
Root cause
result.py:_load_dat assumes a rectangular table (a fixed dtype derived from the header width). run_network's SSA .cdat output is not guaranteed rectangular.
Possible directions
- Tolerate ragged rows (read max width / pad missing trailing species with 0 /
usecols), since species absent from a row have population 0.
- Or make a failed
.cdat load non-fatal so a valid .gdat still yields a usable BNGResult.
Environment
BNG2.pl 2.9.3; Python 3.12; current numpy.
Summary
bionetgen.run()raisesValueErrorwhile building itsBNGResultwhenever BNG2.pl writes a ragged.cdat.run_networkdoes this for SSA on networks where some species are unpopulated att=0and become populated during the run: the per-row species-column count grows over the trajectory while the header line stays fixed at the initial count.result.py:_load_datbuilds a fixed NumPy dtype from the header and callsnp.loadtxt(path, dtype={...}), which requires every row to have the same width and aborts on the first wider row.The simulation itself succeeds and the output files are written correctly — only the post-run load-back into
BNGResultfails, which makes the wholerun()call fatal even though a perfectly good.gdatis on disk.Error
Reproduction
Any SSA run on a network with species unpopulated at
t=0triggers it. For example,agentCellSystemwith a capped network:The produced
.cdathas a fixed-width header but data rows whose width grows as species first appear, e.g.:The
.gdat(a fixed observable set) loads fine. The same model undermethod=>"ode"writes a dense.cdatthat loads fine. The ragged.cdatis itself reproducible byte-for-byte across runs (fixed seed) — it is well-defined output, just not rectangular.Root cause
result.py:_load_datassumes a rectangular table (a fixed dtype derived from the header width).run_network's SSA.cdatoutput is not guaranteed rectangular.Possible directions
usecols), since species absent from a row have population 0..cdatload non-fatal so a valid.gdatstill yields a usableBNGResult.Environment
BNG2.pl 2.9.3; Python 3.12; current numpy.