Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 41 additions & 10 deletions bionetgen/modelapi/bngfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
import os, re
import shutil
import tempfile
from typing import NoReturn

from bionetgen.main import BioNetGen
from bionetgen.core.exc import BNGFileError
from bionetgen.core.utils.logging import BNGLogger
from bionetgen.core.utils.utils import find_BNG_path, run_command, ActionList

# This allows access to the CLIs config setup
Expand Down Expand Up @@ -46,6 +48,7 @@ def __init__(
self, path, BNGPATH=def_bng_path, generate_network=False, suppress=True
) -> None:
self.path = path
self.logger = BNGLogger()
self.generate_network = generate_network
self.suppress = suppress
AList = ActionList()
Expand All @@ -60,6 +63,11 @@ def __init__(
# the top-level ActionBlock.
self.parsed_protocol_actions = []

def _raise_file_error(self, message, path=None, loc=None) -> NoReturn:
error_path = self.path if path is None else path
self.logger.error(message, loc=loc)
raise BNGFileError(error_path, message=message)

def generate_xml(self, xml_file, model_file=None) -> bool:
"""
generates an BNG-XML file from a given model file. Defaults
Expand All @@ -85,7 +93,12 @@ def generate_xml(self, xml_file, model_file=None) -> bool:
["perl", self.bngexec, "--xml", stripped_bngl], suppress=self.suppress
)
if rc != 0:
return False
msg = f"BNG-XML generation failed for {model_file}"
self._raise_file_error(
msg,
path=model_file,
loc=f"{__file__} : BNGFile.generate_xml()",
)

# we should now have the XML file
path, model_name = os.path.split(stripped_bngl)
Expand All @@ -102,7 +115,12 @@ def generate_xml(self, xml_file, model_file=None) -> bool:
]
xml_path = preferred[0] if preferred else candidates[0]
if not os.path.exists(xml_path):
return False
msg = f"BNG-XML generation did not produce an XML file for {model_file}"
self._raise_file_error(
msg,
path=model_file,
loc=f"{__file__} : BNGFile.generate_xml()",
)
with open(xml_path, "r", encoding="UTF-8") as f:
content = f.read()
xml_file.write(content)
Expand Down Expand Up @@ -268,14 +286,22 @@ def write_xml(self, open_file, xml_type="bngxml", bngl_str=None) -> bool:
# run with --xml
# TODO: Make output supression an option somewhere
if xml_type == "bngxml":
if self.bngexec is None:
msg = "BNG-XML generation requires BNG2.pl (BioNetGen) to be installed."
self._raise_file_error(msg, loc=f"{__file__} : BNGFile.write_xml()")
rc, _ = run_command(
["perl", self.bngexec, "--xml", "temp.bngl"], suppress=self.suppress
)
if rc != 0:
print("XML generation failed")
return False
msg = f"BNG-XML generation failed for {self.path}"
self._raise_file_error(msg, loc=f"{__file__} : BNGFile.write_xml()")
else:
# we should now have the XML file
if not os.path.exists("temp.xml"):
msg = "BNG-XML generation did not produce temp.xml"
self._raise_file_error(
msg, loc=f"{__file__} : BNGFile.write_xml()"
)
with open("temp.xml", "r", encoding="UTF-8") as f:
content = f.read()
open_file.write(content)
Expand All @@ -284,25 +310,30 @@ def write_xml(self, open_file, xml_type="bngxml", bngl_str=None) -> bool:
return True
elif xml_type == "sbml":
if self.bngexec is None:
print(
msg = (
"SBML generation requires BNG2.pl (BioNetGen) to be installed."
)
return False
self._raise_file_error(msg, loc=f"{__file__} : BNGFile.write_xml()")
command = ["perl", self.bngexec, "temp.bngl"]
rc, _ = run_command(command, suppress=self.suppress)
if rc != 0:
print("SBML generation failed")
return False
msg = f"SBML generation failed for {self.path}"
self._raise_file_error(msg, loc=f"{__file__} : BNGFile.write_xml()")
else:
# we should now have the SBML file
if not os.path.exists("temp_sbml.xml"):
msg = "SBML generation did not produce temp_sbml.xml"
self._raise_file_error(
msg, loc=f"{__file__} : BNGFile.write_xml()"
)
with open("temp_sbml.xml", "r", encoding="UTF-8") as f:
content = f.read()
open_file.write(content)
open_file.seek(0)
return True
else:
print("XML type {} not recognized".format(xml_type))
return False
msg = f"XML type {xml_type} not recognized"
self._raise_file_error(msg, loc=f"{__file__} : BNGFile.write_xml()")
finally:
os.chdir(cur_dir)
try:
Expand Down
24 changes: 13 additions & 11 deletions bionetgen/modelapi/bngparser.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import xmltodict

from bionetgen.main import BioNetGen
from bionetgen.core.exc import BNGParseError, BNGModelError
from bionetgen.core.exc import BNGFileError, BNGParseError, BNGModelError
from tempfile import TemporaryFile

from .bngfile import BNGFile
Expand Down Expand Up @@ -147,17 +147,19 @@ def _parse_model_bngpl(self, model_obj) -> None:
# TODO: Add verbosity option to the library
# print("Attempting to generate XML")
with TemporaryFile("w+") as xml_file:
if self.bngfile.generate_xml(xml_file):
# TODO: Add verbosity option to the library
xmlstr = xml_file.read()
# < is not a valid XML character, we need to replace it
xmlstr = xmlstr.replace('relation="<', 'relation="&lt;')
self.parse_xml(xmlstr, model_obj)
model_obj.reset_compilation_tags()
else:
try:
self.bngfile.generate_xml(xml_file)
except BNGFileError as exc:
raise BNGModelError(
self.bngfile.path, message="XML file couldn't be generated"
)
self.bngfile.path,
message=f"XML file couldn't be generated: {exc.message}",
) from exc
# TODO: Add verbosity option to the library
xmlstr = xml_file.read()
# < is not a valid XML character, we need to replace it
xmlstr = xmlstr.replace('relation="<', 'relation="&lt;')
self.parse_xml(xmlstr, model_obj)
model_obj.reset_compilation_tags()
elif model_file.endswith(".xml"):
with open(model_file, "r") as f:
xml_str = f.read()
Expand Down
19 changes: 12 additions & 7 deletions bionetgen/modelapi/model.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import copy, tempfile, shutil

from bionetgen.main import BioNetGen
from bionetgen.core.exc import BNGModelError
from bionetgen.core.exc import BNGFileError, BNGModelError

from .bngparser import BNGParser
from .blocks import (
Expand Down Expand Up @@ -393,20 +393,24 @@ def setup_simulator(self, sim_type="libRR"):
self.add_action("writeSBML", {})
# temporary folder instead to make it work
# with windows
tmp_folder = None
try:
tmp_folder = tempfile.mkdtemp()
sbml_name = f"{self.model_name}_sbml.xml"
# write the sbml
with open(sbml_name, "w+") as f:
if not (
try:
self.bngparser.bngfile.write_xml(
f, xml_type="sbml", bngl_str=str(self)
)
):
except BNGFileError as exc:
raise BNGModelError(
self.model_path,
message="SBML couldn't be generated for libRR simulator",
)
message=(
"SBML couldn't be generated for libRR simulator: "
f"{exc.message}"
),
) from exc
self.actions.clear_actions()
# get the simulator
import bionetgen as bng
Expand All @@ -416,8 +420,9 @@ def setup_simulator(self, sim_type="libRR"):
selections = ["time"] + [obs for obs in self.observables]
self.simulator.simulator.timeCourseSelections = selections
finally:
shutil.rmtree(tmp_folder)
self.actions = curr_actions
if tmp_folder is not None:
shutil.rmtree(tmp_folder)
self.actions = curr_actions
elif sim_type == "cpy":
# get the simulator
import bionetgen as bng
Expand Down
Loading
Loading