diff --git a/petab/v1/models/sbml_model.py b/petab/v1/models/sbml_model.py index 8e8cf498..c6957ca6 100644 --- a/petab/v1/models/sbml_model.py +++ b/petab/v1/models/sbml_model.py @@ -65,9 +65,7 @@ def __getstate__(self): # libsbml stuff cannot be serialized directly if self.sbml_model: - sbml_document = self.sbml_model.getSBMLDocument() - sbml_writer = libsbml.SBMLWriter() - state["sbml_string"] = sbml_writer.writeSBMLToString(sbml_document) + state["sbml_string"] = self.to_sbml_str() exclude = ["sbml_reader", "sbml_document", "sbml_model"] for key in exclude: @@ -133,6 +131,26 @@ def from_antimony(ant_model: str | Path) -> SbmlModel: sbml_str = antimony2sbml(ant_model) return SbmlModel.from_string(sbml_str) + def to_antimony(self) -> str: + """Convert the SBML model to an Antimony string.""" + import antimony as ant + + sbml_str = self.to_sbml_str() + + ant.clearPreviousLoads() + ant.freeAll() + + if ant.loadSBMLString(sbml_str) < 0: + raise RuntimeError(ant.getLastError()) + + return ant.getAntimonyString() + + def to_sbml_str(self) -> str: + """Convert the SBML model to an SBML/XML string.""" + sbml_document = self.sbml_model.getSBMLDocument() + sbml_writer = libsbml.SBMLWriter() + return sbml_writer.writeSBMLToString(sbml_document) + @property def model_id(self): return self._model_id diff --git a/tests/v1/test_sbml.py b/tests/v1/test_sbml.py index b29f1ea7..c38f5ab5 100644 --- a/tests/v1/test_sbml.py +++ b/tests/v1/test_sbml.py @@ -134,7 +134,7 @@ def test_sbml_model_repr(): assert repr(petab_model) == "" -def test_sbml_from_ant(): +def test_sbml_from_to_ant(): ant_model = """ model test R1: S1 -> S2; k1*S1 @@ -147,3 +147,6 @@ def test_sbml_from_ant(): assert set(petab_model.get_valid_parameters_for_parameter_table()) == { "k1" } + + # convert back to antimony + assert "R1: S1 -> S2; k1*S1" in petab_model.to_antimony()