Closed artgoldberg closed 4 years ago
More complete trace:
_________________________ TestMultialgorithmSimulationDynamically.test_convert_to_sbml _________________________
self = <tests.test_multialgorithm_simulation.TestMultialgorithmSimulationDynamically testMethod=test_convert_to_sbml>
def test_convert_to_sbml(self):
from wc_lang.sbml import io as sbml_io
from wc_lang.io import Reader, Writer
from wc_sim.testing.utils import read_model_for_test
all_models = ['static', 'one_reaction_linear', 'one_rxn_exponential', 'one_exchange_rxn_compt_growth',
'stop_conditions']
for model_name in all_models:
print(f'converting {model_name}')
dirname = os.path.join(os.path.dirname(__file__), 'fixtures', 'dynamic_tests')
model_filename = os.path.join(dirname, f'{model_name}.xlsx')
integration_framework = 'ordinary_differential_equations'
model = read_model_for_test(model_filename, integration_framework=f'WC:{integration_framework}')
# write wc_lang file
sbml_dirname = os.path.join(dirname, f'{model_name}_sbml')
if not os.path.isdir(sbml_dirname):
os.makedirs(sbml_dirname)
lang_filename = os.path.join(sbml_dirname, f'{model_name}.xlsx')
print(f'writing {lang_filename}')
Writer().run(lang_filename, model)
model_from_file = Reader().run(lang_filename)[Model][0]
assert model_from_file.validate() is None
# write SBML file
try:
> sbml_io.SbmlWriter().run(model_from_file, sbml_dirname)
tests/test_multialgorithm_simulation.py:281:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <wc_lang.sbml.io.SbmlWriter object at 0x7fef69cea6a0>
model = <wc_lang.core.Model object at 0x7fef69ea4358>
dirname = '/root/host/Documents/wc_sim/tests/fixtures/dynamic_tests/static_sbml'
def run(self, model, dirname):
""" Write the submodels of a `wc_lang` model to separate SBML-encoded XML files.
Args:
model (:obj:`wc_lang.core.Model`): `wc_lang` model
dirname (:obj:`str`): path to directory to save SBML-encoded XML files for each submodel
Raises:
:obj:`ValueError`: if the model could not be written to a SBML-encoded file
"""
# validate model
model = PrepForSbmlTransform().run(model.copy())
error = wc_lang.core.Validator().run(model)
if error:
warnings.warn('Model is invalid: ' + str(error), wc_lang.core.WcLangWarning)
# split submodels into separate models
core, submodels = model.submodels.gen_models()
all_models = [core] + submodels
all_models_ids = ['core'] + [m.submodels[0].id for m in submodels]
# create a directory to save SBML-encoded XML documents for model
if not os.path.isdir(dirname):
os.makedirs(dirname)
# encode models in SBML and save to XML file
for model, model_id in zip(all_models, all_models_ids):
# encode models in SBML
> sbml_doc = SbmlExporter.run(model)
/usr/local/lib/python3.6/site-packages/wc_lang/sbml/io.py:108:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cls = <class 'wc_lang.sbml.io.SbmlExporter'>, model = <wc_lang.core.Model object at 0x7fef69ea4358>
@classmethod
def run(cls, model):
""" Encode a `wc_lang` model with at most 1 submodel into SBML
* Validate model
* Create SBML document
* Create SBML model
* Encode model objects in SBML and add to SBML model in dependent order
Args:
model (:obj:`wc_lang.core.Model`): `wc_lang` model with at most 1 submodel
Returns:
:obj:`libsbml.SBMLDocument`: SBML document with SBML-encoded model
Raises:
:obj:`ValueError`: if the model cannot be exported to SBML because it contains multiple submodels
"""
# verify model has at most 1 submodel
if len(model.submodels) > 1:
raise ValueError('Only 1 submodel can be encoded to SBML at a time')
# validate model
error = wc_lang.core.Validator().run(model)
if error:
warnings.warn('Model is invalid: ' + str(error), wc_lang.core.WcLangWarning)
# determine SBML packages needed to export model
packages = {}
for submodel in model.submodels:
if submodel.framework == onto['WC:dynamic_flux_balance_analysis']:
packages['fbc'] = 2
# create an SBML document
sbml_doc = LibSbmlInterface.create_doc(packages=packages)
# create a SBML model
> sbml_model = LibSbmlInterface.init_model(model, sbml_doc, packages=packages)
/usr/local/lib/python3.6/site-packages/wc_lang/sbml/io.py:201:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cls = <class 'wc_lang.sbml.util.LibSbmlInterface'>, model = <wc_lang.core.Model object at 0x7fef69ea4358>
sbml_doc = <SBMLDocument>, packages = {}
@classmethod
def init_model(cls, model, sbml_doc, packages=None):
""" Create and initialize an SMBL model.
Args:
model (:obj:`wc_lang.core.Model`): model
sbml_doc (:obj:`libsbml.SBMLDocument`): a `libsbml` SBMLDocument
packages (:obj:`dict` that maps :obj:`str` to :obj:`int`, optional): dictionary of required packages
that maps package identifiers to package numbers
Returns:
:obj:`libsbml.Model`: the SBML model
"""
# create model
sbml_model = cls.create_model(sbml_doc)
# enable plugins for packages
packages = packages or {}
for package_id in packages.keys():
plugin = cls.call_libsbml(sbml_model.getPlugin, package_id)
cls.call_libsbml(plugin.setStrict, True)
# Set units
> cls.create_units(model, sbml_model)
/usr/local/lib/python3.6/site-packages/wc_lang/sbml/util.py:306:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cls = <class 'wc_lang.sbml.util.LibSbmlInterface'>, model = <wc_lang.core.Model object at 0x7fef69ea4358>
sbml_model = <libsedml.Model; proxy of <Swig Object of type 'Model_t *' at 0x7fef68846ea0> >
@classmethod
def create_units(cls, model, sbml_model):
""" Set time, extent, and substance units of SBML model
Args:
model (:obj:`wc_lang.core.Model`): model
sbml_model (:obj:`libsbml.Model`): SBML model that encodes the model
Returns:
:obj:`dict`: dictionary that maps units to ids of SBML unit definitions
"""
# Define units
units = obj_tables.units.get_obj_units(model)
units_to_sbml = {}
for unit in units:
> sbml_unit = cls.create_unit(unit, sbml_model)
/usr/local/lib/python3.6/site-packages/wc_lang/sbml/util.py:327:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cls = <class 'wc_lang.sbml.util.LibSbmlInterface'>, unit = <Unit('1 / second')>
sbml_model = <libsedml.Model; proxy of <Swig Object of type 'Model_t *' at 0x7fef68846ea0> >
@classmethod
def create_unit(cls, unit, sbml_model):
""" Add a unit definition to a SBML model
Args:
unit (:obj:`unit_registry.Unit`): unit
sbml_model (:obj:`libsbml.Model`): SBML model that encodes the model
Returns:
:obj:`libsbml.UnitDefinition`: unit definition
"""
id = cls.gen_unit_id(unit)
if not id.startswith('unit_'):
return None
> unit_def = cls.call_libsbml(sbml_model.createUnitDefinition)
/usr/local/lib/python3.6/site-packages/wc_lang/sbml/util.py:361:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cls = <class 'wc_lang.sbml.util.LibSbmlInterface'>
method = <bound method Model.createUnitDefinition of <libsedml.Model; proxy of <Swig Object of type 'Model_t *' at 0x7fef68846ea0> >>
returns_int = False, debug = False, args = (), new_args = []
@classmethod
def call_libsbml(cls, method, *args, returns_int=False, debug=False):
""" Call a libSBML method and handle any errors.
Unfortunately, libSBML methods that do not return data usually report errors via return codes,
instead of exceptions, and the generic return codes contain virtually no information.
This function wraps these methods and raises useful exceptions when errors occur.
Set `returns_int` `True` to avoid raising false exceptions or warnings from methods that return
integer values.
Args:
method (:obj:`type`, :obj:`types.FunctionType`, or :obj:`types.MethodType`): `libsbml` method to execute
args (:obj:`list`): a `list` of arguments to the `libsbml` method
returns_int (:obj:`bool`, optional): whether the method returns an integer; if `returns_int`
is `True`, then an exception will not be raised if the method call returns an integer
debug (:obj:`bool`, optional): whether to print debug output
Returns:
:obj:`obj` or `int`: if the call does not return an error, return the `libsbml`
method's return value, either an object that has been created or retrieved, or an integer
value, or the `libsbml` success return code, :obj:`libsbml.LIBSBML_OPERATION_SUCCESS`
Raises:
:obj:`LibSbmlError`: if the `libsbml` call raises an exception, or returns None, or
returns a known integer error code != :obj:`libsbml.LIBSBML_OPERATION_SUCCESS`
"""
new_args = []
for arg in args:
new_args.append(arg)
if new_args:
new_args_str = ', '.join([str(a) for a in new_args])
call_str = "method: {}; args: {}".format(method, new_args_str)
else:
call_str = "method: {}".format(method)
if debug:
print('libSBML call:', call_str)
try:
rc = method(*tuple(new_args))
except BaseException as error:
raise LibSbmlError("Error '{}' in libSBML method call '{}'.".format(error, call_str))
if rc == None:
> raise LibSbmlError("libSBML returned None when executing '{}'.".format(call_str))
E wc_lang.sbml.util.LibSbmlError: libSBML returned None when executing 'method: <bound method Model.createUnitDefinition of <libsedml.Model; proxy of <Swig Object of type 'Model_t *' at 0x7fef68846ea0> >>'.
/usr/local/lib/python3.6/site-packages/wc_lang/sbml/util.py:957: LibSbmlError
What file are you reffering to? The branch wc-sim
-ode
and https://github.com/KarrLab/wc_sim/blob/ode/tests/fixtures/dynamic_tests/static_sbml/static.xlsx
don't exist.
I copied https://github.com/KarrLab/wc_sim/blob/master/tests/fixtures/dynamic_tests/static.xlsx
to a test in wc-lang. tests/sbml/test_sbml_io.py:test_export_another_model
. This illustrates that the model converts to SBML fine.
I cannot reproduce.
This
wc_lang
modelhttps://github.com/KarrLab/wc_sim/blob/ode/tests/fixtures/dynamic_tests/static_sbml/static.xlsx
generates alibSBML returned None
error when attempting to write it as SBML.wc_lang
passes all tests and the model validates:The code:
The error: