1+ import logging
12import tempfile
3+ from os import PathLike
24from pathlib import Path
35
46import sympy # type: ignore[import-untyped]
5- from libvcell import sbml_to_vcml , vcml_to_sbml , vcml_to_vcml
7+ from libvcell import sbml_to_vcml , vcml_to_sbml
68from sympy .parsing .sympy_parser import parse_expr # type: ignore[import-untyped]
79
810from pyvcell ._internal .simdata .simdata_models import VariableType
911from pyvcell .sbml .sbml_spatial_model import SbmlSpatialModel
10- from pyvcell .vcml import Application , VCMLDocument , VcmlReader , VcmlWriter
11- from pyvcell .vcml .models import Biomodel
12+ from pyvcell .vcml .models import Application , Biomodel , VCMLDocument
13+ from pyvcell .vcml .vcml_reader import VcmlReader
14+ from pyvcell .vcml .vcml_writer import VcmlWriter
1215
1316
1417def update_biomodel (bio_model : Biomodel ) -> Biomodel :
@@ -21,21 +24,10 @@ def update_biomodel(bio_model: Biomodel) -> Biomodel:
2124 Returns:
2225 BioModel: The updated BioModel object.
2326 """
24- vcml_writer = VcmlWriter ()
25- vcml_content : str = vcml_writer .write_vcml (document = VCMLDocument (biomodel = bio_model ))
26-
27- with tempfile .TemporaryDirectory () as tmp_dir_name :
28- tmp_dir_path = Path (tmp_dir_name )
29- tmp_dir_path .mkdir (parents = True , exist_ok = True )
30- vcml_file_path = tmp_dir_path / "model.vcml"
31- success , error_message = vcml_to_vcml (vcml_content = vcml_content , vcml_file_path = vcml_file_path )
32- if not success :
33- raise ValueError (f"Failed to regenerate VCML: { error_message } " )
34- new_bio_model = VcmlReader .biomodel_from_file (vcml_file_path )
35- return new_bio_model
27+ return load_vcml_str (to_vcml_str (bio_model = bio_model ))
3628
3729
38- def from_sbml (sbml_spatial_model : SbmlSpatialModel ) -> Biomodel :
30+ def _from_sbml_object (sbml_spatial_model : SbmlSpatialModel ) -> Biomodel :
3931 """
4032 Import an SBML Spatial model and return a VCell Biomodel.
4133
@@ -63,7 +55,7 @@ def from_sbml(sbml_spatial_model: SbmlSpatialModel) -> Biomodel:
6355 return new_bio_model
6456
6557
66- def to_sbml (bio_model : Biomodel , application_name : str , round_trip_validation : bool ) -> SbmlSpatialModel :
58+ def _to_sbml_object (bio_model : Biomodel , application_name : str , round_trip_validation : bool ) -> SbmlSpatialModel :
6759 """
6860 Export an SBML Spatial model from an application within a VCell Biomodel.
6961
@@ -146,3 +138,153 @@ def field_data_refs(bio_model: Biomodel, simulation_name: str) -> set[tuple[str,
146138 field_data_refs .add ((data_name .name , varname .name , VariableType .VOLUME , float (time )))
147139
148140 return field_data_refs
141+
142+
143+ def load_antimony_str (antimony_str : str ) -> Biomodel :
144+ import antimony # type: ignore[import-untyped]
145+
146+ antimony_success = antimony .loadAntimonyString (antimony_str )
147+ if antimony_success != - 1 :
148+ sbml_str = antimony .getSBMLString ()
149+ sbml_str = sbml_str .replace ("sboTerm" , "metaid" )
150+ logging .info (f"Hack - introduced a metaid in place of sboTerm to SBML string:\n { sbml_str } " )
151+ return load_sbml_str (sbml_str )
152+ else :
153+ raise ValueError ("Error loading model:" , antimony .getLastError ())
154+
155+
156+ def load_antimony_file (antimony_file : PathLike [str ] | str ) -> Biomodel :
157+ import antimony # ignore
158+
159+ antimony_success = antimony .loadAntimonyFile (antimony_file )
160+ if antimony_success != - 1 :
161+ sbml_str = antimony .getSBMLString ()
162+ return load_sbml_str (sbml_str )
163+ else :
164+ raise ValueError ("Error loading model:" , antimony .getLastError ())
165+
166+
167+ def to_antimony_str (
168+ bio_model : Biomodel , application_name : str | None = None , round_trip_validation : bool = True
169+ ) -> str :
170+ sbml_str = to_sbml_str (bio_model , application_name , round_trip_validation = round_trip_validation )
171+ import antimony
172+
173+ antimony_success = antimony .loadSBMLString (sbml_str )
174+ if antimony_success != - 1 :
175+ antimony_str = str (antimony .getAntimonyString ())
176+ return antimony_str
177+ else :
178+ raise ValueError ("Error converting SBML to Antimony:" , antimony .getLastError ())
179+
180+
181+ def write_antimony_file (bio_model : Biomodel , antimony_file : PathLike [str ] | str ) -> None :
182+ antimony_str = to_antimony_str (bio_model )
183+ with open (antimony_file , "w" ) as f :
184+ f .write (antimony_str )
185+
186+
187+ def load_vcml_str (vcml_str : str ) -> Biomodel :
188+ return VcmlReader .biomodel_from_str (vcml_str )
189+
190+
191+ def load_vcml_file (vcml_file : PathLike [str ] | str ) -> Biomodel :
192+ return VcmlReader .biomodel_from_file (vcml_file )
193+
194+
195+ def to_vcml_str (bio_model : Biomodel , regenerate : bool = True ) -> str :
196+ """
197+ Convert a Biomodel object to a VCML string, after refreshing its content with a round trip to libvcell
198+ """
199+ vcml_document = VCMLDocument (biomodel = bio_model )
200+ vcml_str : str = VcmlWriter ().write_vcml (document = vcml_document )
201+ if not regenerate :
202+ return vcml_str
203+
204+ import libvcell
205+
206+ with tempfile .TemporaryDirectory () as tempdir :
207+ vcml_path = Path (tempdir ) / "model.vcml"
208+ vc_success , vc_errmsg = libvcell .vcml_to_vcml (vcml_content = vcml_str , vcml_file_path = vcml_path )
209+ if not vc_success :
210+ raise ValueError ("Error converting VCML to VCML:" , vc_errmsg )
211+ with open (vcml_path ) as f :
212+ vcml_str = f .read ()
213+ return vcml_str
214+
215+
216+ def write_vcml_file (bio_model : Biomodel , vcml_file : PathLike [str ] | str , regenerate : bool = True ) -> None :
217+ with open (vcml_file , "w" ) as f :
218+ f .write (to_vcml_str (bio_model = bio_model , regenerate = regenerate ))
219+
220+
221+ def load_sbml_str (sbml_str : str ) -> Biomodel :
222+ import libvcell
223+
224+ with tempfile .TemporaryDirectory () as tempdir :
225+ vcml_path = Path (tempdir ) / "model.vcml"
226+ vc_success , vc_errmsg = libvcell .sbml_to_vcml (sbml_content = sbml_str , vcml_file_path = vcml_path )
227+ if vc_success :
228+ return VcmlReader .biomodel_from_file (vcml_path = vcml_path )
229+ else :
230+ raise ValueError ("Error loading model:" , vc_errmsg )
231+
232+
233+ def load_sbml_file (sbml_file : PathLike [str ] | str ) -> Biomodel :
234+ import libvcell
235+
236+ with tempfile .TemporaryDirectory () as tempdir :
237+ with open (sbml_file ) as f :
238+ sbml_str = f .read ()
239+ vcml_path = Path (tempdir ) / "model.vcml"
240+ vc_success , vc_errmsg = libvcell .sbml_to_vcml (sbml_content = sbml_str , vcml_file_path = vcml_path )
241+ if vc_success :
242+ return VcmlReader .biomodel_from_file (vcml_path = vcml_path )
243+ else :
244+ raise ValueError ("Error loading model:" , vc_errmsg )
245+
246+
247+ def to_sbml_str (bio_model : Biomodel , application_name : str | None = None , round_trip_validation : bool = True ) -> str :
248+ import libvcell
249+
250+ if application_name is None :
251+ if len (bio_model .applications ) == 0 :
252+ raise ValueError ("sbml export from biomodel needs a biomodel application" )
253+ if len (bio_model .applications ) > 1 :
254+ raise ValueError ("Application must have exactly one application" )
255+ application_name = bio_model .applications [0 ].name
256+ elif application_name not in [app .name for app in bio_model .applications ]:
257+ raise ValueError (f"Application '{ application_name } ' not found in biomodel" )
258+ vcml_document = VCMLDocument (biomodel = bio_model )
259+ vcml_str : str = VcmlWriter ().write_vcml (document = vcml_document )
260+ with tempfile .TemporaryDirectory () as tempdir :
261+ sbml_path = Path (tempdir ) / "model.sbml"
262+ success , msg = libvcell .vcml_to_sbml (
263+ vcml_content = vcml_str ,
264+ application_name = application_name ,
265+ sbml_file_path = sbml_path ,
266+ round_trip_validation = round_trip_validation ,
267+ )
268+ if not success :
269+ raise ValueError ("Error converting VCML to SBML:" , msg )
270+ with open (sbml_path ) as f :
271+ sbml_str = f .read ()
272+ return sbml_str
273+
274+
275+ def write_sbml_file (
276+ bio_model : Biomodel ,
277+ sbml_file : PathLike [str ] | str ,
278+ application_name : str | None = None ,
279+ round_trip_validation : bool = True ,
280+ ) -> None :
281+ sbml_str = to_sbml_str (bio_model , application_name , round_trip_validation )
282+ with open (sbml_file , "w" ) as f :
283+ f .write (sbml_str )
284+
285+
286+ def refresh_biomodel (bio_model : Biomodel ) -> Biomodel :
287+ with tempfile .TemporaryDirectory () as tempdir :
288+ vcml_path = Path (tempdir ) / "model.vcml"
289+ write_vcml_file (bio_model = bio_model , vcml_file = vcml_path )
290+ return VcmlReader .biomodel_from_file (vcml_path = vcml_path )
0 commit comments