|
7 | 7 | """
|
8 | 8 |
|
9 | 9 | from .data_model import KISAO_ALGORITHMS_MAP, KISAO_PARAMETERS_MAP, Units
|
10 |
| -from biosimulators_utils.config import Config # noqa: F401 |
| 10 | +from biosimulators_utils.combine.data_model import CombineArchiveContentFormat |
| 11 | +from biosimulators_utils.combine.io import CombineArchiveReader, CombineArchiveWriter |
| 12 | +from biosimulators_utils.config import get_config, Config # noqa: F401 |
11 | 13 | from biosimulators_utils.data_model import ValueType
|
12 | 14 | from biosimulators_utils.simulator.utils import get_algorithm_substitution_policy
|
13 | 15 | from biosimulators_utils.utils.core import validate_str_value, parse_value
|
14 | 16 | from kisao.data_model import AlgorithmSubstitutionPolicy, ALGORITHM_SUBSTITUTION_POLICY_LEVELS
|
15 | 17 | from kisao.utils import get_preferred_substitute_algorithm_by_ids
|
16 | 18 | import COPASI
|
17 | 19 | import itertools
|
| 20 | +import libsedml |
| 21 | +import lxml |
| 22 | +import os |
| 23 | +import shutil |
| 24 | +import tempfile |
18 | 25 |
|
19 | 26 | __all__ = [
|
20 | 27 | 'get_algorithm_id',
|
21 | 28 | 'set_algorithm_parameter_value',
|
22 | 29 | 'get_copasi_model_object_by_sbml_id',
|
23 | 30 | 'get_copasi_model_obj_sbml_ids',
|
| 31 | + 'fix_copasi_generated_combine_archive', |
24 | 32 | ]
|
25 | 33 |
|
26 | 34 |
|
@@ -241,3 +249,61 @@ def get_copasi_model_obj_sbml_ids(model):
|
241 | 249 | ids.append(object.getSBMLId())
|
242 | 250 |
|
243 | 251 | return ids
|
| 252 | + |
| 253 | + |
| 254 | +def fix_copasi_generated_combine_archive(in_filename, out_filename, config=None): |
| 255 | + """ Utility function that corrects COMBINE/OMEX archives generated by COPASI so they are compatible |
| 256 | + with other tools. |
| 257 | +
|
| 258 | + All currently released versions of COPASI export COMBINE archive files. However, these archives |
| 259 | + presently diverge from the specifications of the SED-ML format. |
| 260 | +
|
| 261 | + * Format in OMEX manifests is not a valid PURL media type URI |
| 262 | + * SED-ML files lack namespaces for SBML |
| 263 | +
|
| 264 | + Args: |
| 265 | + in_filename (:obj:`str`): path to a COMBINE archive to correct |
| 266 | + out_filename (:obj:`str`): path to save correctd COMBINE archive |
| 267 | + config (:obj:`Config`, optional): BioSimulators-utils configuration |
| 268 | + """ |
| 269 | + config = config or get_config() |
| 270 | + archive_dirname = tempfile.mkdtemp() |
| 271 | + try: |
| 272 | + archive = CombineArchiveReader().run(in_filename, archive_dirname, config=config) |
| 273 | + except Exception: |
| 274 | + shutil.rmtree(archive_dirname) |
| 275 | + raise |
| 276 | + |
| 277 | + # correct URI for COPASI application format |
| 278 | + for content in archive.contents: |
| 279 | + if content.format == 'application/x-copasi': |
| 280 | + content.format = CombineArchiveContentFormat.CopasiML |
| 281 | + # potentially issue warning messages if needed |
| 282 | + break |
| 283 | + |
| 284 | + # add SBML namespace to SED-ML file |
| 285 | + ns = None |
| 286 | + for content in archive.contents: |
| 287 | + if content.format == 'http://identifiers.org/combine.specifications/sbml': |
| 288 | + with open(os.path.join(archive_dirname, content.location), 'rb') as sbml: |
| 289 | + root = lxml.etree.parse(sbml) |
| 290 | + # get default ns |
| 291 | + ns = root.getroot().nsmap[None] |
| 292 | + break |
| 293 | + |
| 294 | + if ns: |
| 295 | + for content in archive.contents: |
| 296 | + if content.format == 'http://identifiers.org/combine.specifications/sed-ml': |
| 297 | + sedml_file = os.path.join(archive_dirname, content.location) |
| 298 | + doc = libsedml.readSedMLFromFile(sedml_file) |
| 299 | + sedml_ns = doc.getSedNamespaces().getNamespaces() |
| 300 | + if not sedml_ns.hasPrefix('sbml'): |
| 301 | + sedml_ns.add(ns, 'sbml') |
| 302 | + libsedml.writeSedMLToFile(doc, sedml_file) |
| 303 | + # potentially issue warning message here, that the sedml file had no SBML prefix and it was added |
| 304 | + break |
| 305 | + |
| 306 | + try: |
| 307 | + CombineArchiveWriter().run(archive, archive_dirname, out_filename) |
| 308 | + finally: |
| 309 | + shutil.rmtree(archive_dirname) |
0 commit comments