1"""
2PySCeS - Python Simulator for Cellular Systems (http://pysces.sourceforge.net)
3
4Copyright (C) 2004-2022 B.G. Olivier, J.M. Rohwer, J.-H.S Hofmeyr all rights reserved,
5
6Brett G. Olivier (bgoli@users.sourceforge.net)
7Triple-J Group for Molecular Cell Physiology
8Stellenbosch University, South Africa.
9
10Permission to use, modify, and distribute this software is given under the
11terms of the PySceS (BSD style) license. See LICENSE.txt that came with
12this distribution for specifics.
13
14NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
15Brett G. Olivier
16"""
17from __future__ import division, print_function
18from __future__ import absolute_import
19from __future__ import unicode_literals
20
21from pysces.version import __version__
22
23__doc__ = """
24          PyscesInterfaces
25          ----------------
26
27          Interfaces converting to and from PySCeS models - makes use of Brett's Core2
28          """
29
30import os
31from pysces import model_dir, output_dir
32from pysces.core2.PyscesCore2 import NewCore
33from pysces.core2.PyscesCore2Interfaces import (
34    PscToCore,
35    SbmlToCore,
36    CoreToPsc,
37    CoreToSBML,
38)
39
40
41class Core2interfaces(object):
42    """
43    Defines interfaces for translating PySCeS model objects into and from other formats.
44    """
45
46    core = None
47    sbml = None
48    core2sbml = None
49    core2psc = None
50    sbml2core = None
51    sbml_level = 2
52    sbml_version = 1
53
54    def __buildPscComponents__(self):
55        """
56        Builds the PSC file
57        """
58        self.core2psc.setHeader()
59        self.core2psc.setFixed()
60        self.core2psc.setCompartments()
61        self.core2psc.setFunctions()
62        self.core2psc.setReactions()
63        self.core2psc.setAssignmentRules()
64        self.core2psc.setRateRules()
65        self.core2psc.setEvents()
66        self.core2psc.setSpecies()
67        self.core2psc.setParameters()
68        self.core2psc.setNotes()
69
70    def __buildSbmlComponents__(self):
71        """
72        The SBML file build commands
73        """
74        self.core2sbml.createModel()
75        self.core2sbml.setDescription()
76        self.core2sbml.setUnits()
77        self.core2sbml.setCompartments()
78        self.core2sbml.setSpecies()
79        self.core2sbml.setParameters()
80        self.core2sbml.setFunctions()
81        self.core2sbml.setReactions()
82        self.core2sbml.setEvents()
83        self.core2sbml.setRules()
84
85    def writeMod2PSC(
86        self, mod, filename=None, directory=None, iValues=True, getstrbuf=False
87    ):
88        """
89        Writes a PySCeS model object to a PSC file.
90
91        - *filename*: writes <filename>.psc or <model_name>.psc if None
92        - *directory*: (optional) an output directory
93        - *iValues*: if True then the models initial values are used (or the current values if False).
94        - *getstrbuf*: if True a StringIO buffer is returned instead of writing to disk
95        """
96        self.core = NewCore(mod, iValues=iValues)
97        assert self.core != None, "\nPlease set a PySCeS model or Core2 object"
98        self.core2psc = CoreToPsc(self.core)
99        if not iValues:
100            self.core2psc.SPECIES_CURRENT_VALUE = True
101            self.core2psc.FIXED_SPECIES_CURRENT_VALUE = True
102            self.core2psc.PARAMETER_CURRENT_VALUE = True
103
104        self.__buildPscComponents__()
105        if filename == None:
106            filename = self.core.name
107        if filename[-4:] != '.psc':
108            filename += '.psc'
109        if not getstrbuf:
110            self.core2psc.write(filename, directory, getstrbuf)
111        else:
112            return self.core2psc.write(filename, directory, getstrbuf)
113
114    def writeMod2SBML(
115        self,
116        mod,
117        filename=None,
118        directory=None,
119        iValues=True,
120        getdocument=False,
121        getstrbuf=False,
122    ):
123        """
124        Writes a PySCeS model object to an SBML file.
125
126        - *filename*: writes <filename>.xml or <model_name>.xml if None
127        - *directory*: (optional) an output directory
128        - *iValues*: if True then the models initial values are used (or the current values if False).
129        - *getdocument*: if True an SBML document object is returned instead of writing to disk or
130        - *getstrbuf*: if True a StringIO buffer is returned instead of writing to disk
131        """
132        self.core = NewCore(mod, iValues=iValues)
133        ##  assert os.sys.platform != 'win32', '\nSBML translation currently only supported on Linux (Mac?)'
134        assert self.core != None, "\nPlease set a PySCeS model or Core2 object"
135        self.core2sbml = CoreToSBML(self.core)
136        self.core2sbml.level = self.sbml_level
137        self.core2sbml.version = self.sbml_version
138        assert self.core2sbml.SBML != None, "\nProblems loading SBML/Python interface"
139        self.__buildSbmlComponents__()
140        if filename == None:
141            filename = self.core.name
142        if filename[-4:] != '.xml':
143            filename += '.xml'
144        if getdocument:
145            return self.core2sbml.getSBMLdocument()
146        elif getstrbuf:
147            return self.core2sbml.getSBMLFileAsStrBuf()
148        else:
149            self.core2sbml.writeSBML2file(filename, directory)
150
151    def readSBMLToCore(self, filename, directory=None):
152        """
153        Reads the SBML file specified with filename and converts it into
154        a core2 object pysces.interface.core
155
156        - *filename*: the SBML file
157        - *directory*: (optional) the SBML file directory None means try the current working directory
158        """
159        if directory != None:
160            fpath = os.path.join(directory, filename)
161            assert os.path.exists(fpath), "\nFile \"%s\" does not exist!" % fpath
162
163        self.sbml2core = SbmlToCore()
164        self.sbml2core.getSbmlStringFromDisk(filename, Dir=directory)
165        self.sbml2core.getSbmlModel()
166        self.sbml2core.checkSbmlSupport()
167        self.sbml2core.getParsedModel()
168        self.sbml2core.getUnits()
169        self.core = NewCore(self.sbml2core)
170
171    def readMod2Core(self, mod, iValues=True):
172        """
173        Convert a PySCeS model object to core2
174
175        - *iValues*: if True then the models initial values are used (or the current values if False).
176        """
177        self.core = NewCore(mod, iValues=iValues)
178
179    def writeCore2PSC(self, filename=None, directory=None, getstrbuf=False):
180        """
181        Writes a Core2 object to a PSC file.
182
183        - *filename*: writes <filename>.xml or <model_name>.xml if None
184        - *directory*: (optional) an output directory
185        - *getstrbuf*: if True a StringIO buffer is returned instead of writing to disk
186        """
187        assert self.core != None, "\nPlease set a PySCeS model or Core2 object"
188        ##  print 'Using existing self.core'
189        self.core2psc = CoreToPsc(self.core)
190        self.__buildPscComponents__()
191        if filename == None:
192            filename = self.core.name
193        if filename[-4:] != '.psc':
194            filename += '.psc'
195        if not getstrbuf:
196            self.core2psc.write(filename, directory, getstrbuf)
197        else:
198            return self.core2psc.write(filename, directory, getstrbuf)
199
200    def writeCore2SBML(self, filename=None, directory=None, getdocument=False):
201        """
202        Writes Core2 object to an SBML file.
203
204        - *filename*: writes <filename>.xml or <model_name>.xml if None
205        - *directory*: (optional) an output directory
206        - *getdocument*: if True an SBML document object is returned instead of writing to disk or
207        """
208        assert self.core != None, "\nPlease set a PySCeS model or Core2 object"
209        ##  print 'Using existing self.core'
210        self.core2sbml = CoreToSBML(self.core)
211        self.core2sbml.level = self.sbml_level
212        self.core2sbml.version = self.sbml_version
213        assert self.core2sbml.SBML != None, "\nProblems loading SBML/Python interface"
214        self.__buildSbmlComponents__()
215        if filename == None:
216            filename = self.core.name
217        if filename[-4:] != '.xml':
218            filename += '.xml'
219        if not getdocument:
220            self.core2sbml.writeSBML2file(filename, directory)
221        else:
222            return self.core2sbml.getSBMLdocument()
223
224    def convertSBML2PSC(self, sbmlfile, sbmldir=None, pscfile=None, pscdir=None):
225        """
226        Convert an SBML file to a PySCeS MDL input file.
227
228        - *sbmlfile*: the SBML file name
229        - *sbmldir*: the directory of SBML files (if None current working directory is assumed)
230        - *pscfile*: the output PSC file name (if None *sbmlfile*.psc is used)
231        - *pscdir*: the PSC output directory (if None the pysces.model_dir is used)
232        """
233        if sbmldir == None or not os.path.exists(sbmldir):
234            sbmldir = os.getcwd()
235        if not os.path.exists(os.path.join(sbmldir, sbmlfile)):
236            raise RuntimeError(
237                '\nSBML file \"%s\" does not exist!' % os.path.join(sbmldir, sbmlfile)
238            )
239        if pscdir == None or not os.path.exists(pscdir):
240            pscdir = model_dir
241        if pscfile == None:
242            pscfile = '%s.psc' % sbmlfile
243        self.readSBMLToCore(filename=sbmlfile, directory=sbmldir)
244        self.writeCore2PSC(filename=pscfile, directory=pscdir, getstrbuf=False)
245        print(
246            '\nSBML2PSC\nin : %s\nout: %s'
247            % (os.path.join(sbmldir, sbmlfile), os.path.join(pscdir, pscfile))
248        )
249