コード例 #1
0
ファイル: omex.py プロジェクト: fanfanruyun/tellurium
def listContents(omexPath, method="omex"):
    """ Returns list of contents of the combine archive.

    :param omexPath:
    :param method: method to extract content, only 'omex' supported
    :return: list of contents
    """
    if method not in ["omex"]:
        raise ValueError("Method is not supported: {}".format(method))

    contents = []
    omex = libcombine.CombineArchive()
    if omex.initializeFromArchive(omexPath) is None:
        raise IOError("Invalid Combine Archive: {}", omexPath)

    for i in range(omex.getNumEntries()):
        entry = omex.getEntry(i)
        location = entry.getLocation()
        format = entry.getFormat()
        master = entry.getMaster()
        info = None
        try:
            for formatKey in ["sed-ml", "sbml", "sbgn", "cellml"]:
                if libcombine.KnownFormats_isFormat(formatKey, format):
                    info = omex.extractEntryToString(location)
        except:
            pass

        contents.append([i, location, format, master, info])

    omex.cleanUp()

    return contents
コード例 #2
0
ファイル: omex.py プロジェクト: fanfanruyun/tellurium
def extractCombineArchive(omexPath, directory, method="zip"):
    """ Extracts combine archive at given path to directory.

    The zip method extracts all entries in the zip, the omex method
    only extracts the entries listed in the manifest.
    In some archives not all content is listed in the manifest.

    :param omexPath:
    :param directory:
    :param method: method to extract content, either 'zip' or 'omex'
    :return:
    """
    if method not in ["zip", "omex"]:
        raise ValueError("Method is not supported: {}".format(method))

    if method == "zip":
        zip_ref = zipfile.ZipFile(omexPath, 'r')
        zip_ref.extractall(directory)
        zip_ref.close()

    elif method == "omex":
        omex = libcombine.CombineArchive()
        if omex.initializeFromArchive(omexPath) is None:
            raise IOError("Invalid Combine Archive: {}", omexPath)

        for i in range(omex.getNumEntries()):
            entry = omex.getEntry(i)
            location = entry.getLocation()
            filename = os.path.join(directory, location)
            omex.extractEntry(location, filename)

        omex.cleanUp()
コード例 #3
0
ファイル: omex.py プロジェクト: fanfanruyun/tellurium
def getLocationsByFormat(omexPath, formatKey=None, method="omex"):
    """ Returns locations to files with given format in the archive.

    Uses the libcombine KnownFormats for formatKey, e.g., 'sed-ml' or 'sbml'.
    Files which have a master=True have higher priority and are listed first.

    :param omexPath:
    :param formatKey:
    :param method:
    :return:
    """
    if not formatKey:
        raise ValueError("Format must be specified.")

    if method not in ["zip", "omex"]:
        raise ValueError("Method is not supported: {}".format(method))

    locations_master = []
    locations = []

    if method == "omex":
        omex = libcombine.CombineArchive()
        if omex.initializeFromArchive(omexPath) is None:
            raise IOError("Invalid Combine Archive: {}", omexPath)

        for i in range(omex.getNumEntries()):
            entry = omex.getEntry(i)
            format = entry.getFormat()
            master = entry.getMaster()
            if libcombine.KnownFormats.isFormat(formatKey, format):
                loc = entry.getLocation()
                if (master is None) or (master is False):
                    locations.append(loc)
                else:
                    locations_master.append(loc)
        omex.cleanUp()

    elif method == "zip":
        # extract to tmpfile and guess format
        tmp_dir = tempfile.mkdtemp()

        try:
            extractCombineArchive(omexPath, directory=tmp_dir, method="zip")

            # iterate over all locations & guess format
            for root, dirs, files in os.walk(tmp_dir):
                for file in files:
                    file_path = os.path.join(root, file)
                    location = os.path.relpath(file_path, tmp_dir)
                    # guess the format
                    format = libcombine.KnownFormats.guessFormat(file_path)
                    if libcombine.KnownFormats.isFormat(formatKey=formatKey,
                                                        format=format):
                        locations.append(location)
                    # print(format, "\t", location)

        finally:
            shutil.rmtree(tmp_dir)

    return locations_master + locations
コード例 #4
0
ファイル: comex.py プロジェクト: matthiaskoenig/tellurium-web
def print_archive(fileName):
    """ Print the content of the archive.

    :param fileName:
    :return:
    """
    print(fileName)
    archive = libcombine.CombineArchive()
    if not archive.initializeFromArchive(str(fileName)):
        print("Invalid Combine Archive")
        return

    printMetaDataFor(archive, ".")
    print("Num Entries: {0}".format(archive.getNumEntries()))

    for i in range(archive.getNumEntries()):
        print(i)
        entry = archive.getEntry(i)
        print('entry: <{}>'.format(i), entry)

        print(" {0}: location: {1} format: {2}".format(i, entry.getLocation(),
                                                       entry.getFormat()))
        print_metadata(archive, entry.getLocation())

        # the entry could now be extracted via
        # archive.extractEntry(entry.getLocation(), <filename or folder>)

        # or used as string
        # content = archive.extractEntryToString(entry.getLocation());

    archive.cleanUp()
コード例 #5
0
    def from_combine(filename: str) -> 'Problem':
        """Read PEtab COMBINE archive (http://co.mbine.org/documents/archive).

        See also ``create_combine_archive``.

        Arguments:
            filename: Path to the PEtab-COMBINE archive

        Returns:
            A ``petab.Problem`` instance.
        """
        # function-level import, because module-level import interfered with
        # other SWIG interfaces
        try:
            import libcombine
        except ImportError:
            raise ImportError(
                "To use PEtab's COMBINE functionality, libcombine "
                "(python-libcombine) must be installed.")

        archive = libcombine.CombineArchive()
        if archive.initializeFromArchive(filename) is None:
            print(f"Invalid Combine Archive: {filename}")
            return None

        with tempfile.TemporaryDirectory() as tmpdirname:
            archive.extractTo(tmpdirname)
            problem = Problem.from_yaml(
                os.path.join(tmpdirname,
                             archive.getMasterFile().getLocation()))
        archive.cleanUp()

        return problem
コード例 #6
0
def create_omex_from_sedml(sedml_file, omex_file):
    """ Creates a combine archive from folder

    :param folder:
    :param omex_file:
    :return:
    """
    print('*' * 100)
    print('Create OMEX:')
    print('\t', sedml_file)
    print('*' * 100)
    time_now = libcombine.OmexDescription.getCurrentDateAndTime()
    archive = libcombine.CombineArchive()

    # add the sedml file
    location = os.path.relpath(sedml_file)
    format = "http://identifiers.org/combine.specifications/sed-ml"
    master = True
    archive.addFile(path, location, format, master)

    omex_d = libcombine.OmexDescription()
    omex_d.setAbout(location)
    omex_d.setCreated(time_now)

    archive.addMetadata(location, omex_d)

    # delete the old omex file
    if os.path.exists(omex_file):
        os.remove(omex_file)

    archive.writeToFile(omex_file)
    print('Archive created:', omex_file)
コード例 #7
0
def extract_rdf_from_combine_archive(archive_path: str):
    """
    Opens a combine archive and extracts annotation string as a list.
    Args:
        archive_path: full path to combine archive on disk

    Returns:

    """
    if not os.path.isfile(archive_path):
        raise FileNotFoundError(archive_path)

    # read the archive using libcombine
    archive = libcombine.CombineArchive()

    # note the skipOmex flag. This is needed to expose any files with an "rdf" extension.
    archive.initializeFromArchive(archive_path,
                                  skipOmex=True)  # new in libcombine!

    # filter through the entries in the omex archive for rdf extension files
    annotation_entries = [
        i.c_str() for i in archive.getAllLocations() if i[-4:] == ".rdf"
    ]

    # read the rdf into a python string
    return [archive.extractEntryToString(i) for i in annotation_entries]
コード例 #8
0
def create_combine_archive(sbml, name, annotation_string=None):
    """
    Create a combine archive using libcombine. Archive will contain
    a single sbml file with the Manifest that is autocreated by libcombine.
    If annotation_string is not None, an additional annotation file will be
    stored in the combine containing annotation_string.
    Args:
        sbml: the sbml string to be put into a file
        name: Name used for archive and file in archive
        annotation_string: None or string containing the annotation for the combine archive

    Returns:

    """
    current_directory = dir_path = os.path.dirname(os.path.realpath(__file__))
    combine_archive_filename = os.path.join(current_directory, f"{name}.omex")
    archive = libcombine.CombineArchive()
    archive.addFileFromString(
        content=sbml,  # the string contining sbml
        targetName=f"{name}.sbml",  # name the content in archive
        format="sbml",  # format of this content
        isMaster=
        True  # boolean indicating whether the file should be opened first if there are multiple ones.
    )
    if annotation_string:
        archive.addFileFromString(annotation_string, f"{name}.rdf", "turtle",
                                  False)
    archive.writeToFile(combine_archive_filename)
    if not os.path.isfile(combine_archive_filename):
        raise FileNotFoundError(combine_archive_filename)

    print(f"Archive written to \"{combine_archive_filename}\"")
    return combine_archive_filename
コード例 #9
0
ファイル: comex.py プロジェクト: matthiaskoenig/tellurium-web
def tags_info(archive_path):
    """ Reads the tags info from a given archive.

    :param archive_path:
    :return:
    """
    tags_info = []

    # add the file formats from omex
    omex = libcombine.CombineArchive()
    if omex.initializeFromArchive(archive_path) is None:
        print("Invalid Combine Archive: {}", archive_path)
        return None

    sedml_entries = []
    sbml_entries = []
    for i in range(omex.getNumEntries()):
        entry = omex.getEntry(i)
        format = entry.getFormat()
        location = entry.getLocation()
        format_id = base_format(format)

        if format_id in ['sbml', 'cellml', 'sed-ml', 'sedml', 'sbgn', 'sbol']:
            tags_info.append({
                'type': 'format',
                'name': format_id,
            })
        if format_id == 'sbml':
            sbml_entries.append(entry)
        if format_id in ['sedml', 'sed-ml']:
            sedml_entries.append(entry)

    # add the SBML contents
    # add the SED-ML contents
    for entry in sedml_entries:
        content = omex.extractEntryToString(entry.getLocation())
        doc = libsedml.readSedMLFromString(
            content)  # type: libsedml.SedDocument
        print(doc)

        for model in doc.getListOfModels():
            language = model.getLanguage()
            if language:
                name = language.split(':')[-1]
                tags_info.append({
                    'type': 'sedml',
                    'name': 'model:{}'.format(name)
                })

        if len(doc.getListOfDataDescriptions()) > 0:
            tags_info.append({'type': 'sedml', 'name': 'DataDescription'})

    omex.cleanUp()
    return tags_info
コード例 #10
0
    def omex(self):
        """ Open CombineArchive for given archive.

        Don't forget to close the omex after using it.
        :return:
        """
        omex = libcombine.CombineArchive()
        if omex.initializeFromArchive(self.path) is None:
            logger.error("Invalid Combine Archive: {}", self)
            return None
        return omex
コード例 #11
0
    def run(self, archive, in_dir, out_file):
        """ Write an archive to a file

        Args:
            archive (:obj:`CombineArchive`): description of archive
            in_dir (:obj:`str`): directory which contains the files in the archive
            out_file (:obj:`str`): path to save archive

        Raises:
            :obj:`AssertionError`: if files could not be added to the archive or the archive could not be
                saved
        """
        self.errors = []
        self.warnings = []

        # instantiate archive
        archive_comb = libcombine.CombineArchive()

        # add files to archive
        for i_content, content in enumerate(archive.contents):
            if not archive_comb.addFile(
                    os.path.join(in_dir, content.location), content.location,
                    content.format if content.format else '', content.master):
                content_id = '`' + content.location + '`' if content.location else str(
                    i_content + 1)
                msg = 'Content element {} could not be added to the archive.'.format(
                    content_id)
                self.errors.append([msg])
                raise Exception(msg)

        # save archive to a file
        if not archive_comb.writeToFile(out_file):
            msg = 'Archive could not be saved.'
            self.errors.append([msg])
            raise Exception(msg)

        errors, warnings = get_combine_errors_warnings(
            archive_comb.getManifest())
        self.errors.extend(errors)
        self.warnings.extend(warnings)

        if self.warnings:
            warn(
                'COMBINE/OMEX archive may be invalid.\n  ' +
                flatten_nested_list_of_strings(self.warnings).replace(
                    '\n', '\n  '), BioSimulatorsWarning)
        if self.errors:
            raise ValueError('COMBINE/OMEX archive is invalid.\n  ' +
                             flatten_nested_list_of_strings(
                                 self.errors).replace('\n', '\n  '))
コード例 #12
0
def convert(path, meta_data=None):
    user_dir = "/home/jovyan"
    path = os.path.join(user_dir, path)

    # Setup combine archive
    archive = libcombine.CombineArchive()
    archive_dir = tempfile.TemporaryDirectory()
    archive_errors = []

    # Add file(s) to archive
    if path.endswith('.wkfl'):
        if get_status(path) != 'complete':
            raise StochSSExportCombineError("You cannot create a combine achrive \
                                            with a workflow that has not completed")
        archive_name = path.split('/')[:-2].pop().split('.')[0]
        file_type = "workflow"
        dst_parent = '/'.join(path.split('/')[:-3])
        sedml = convert_workflow(path, archive, archive_dir)
        with open(sedml['path'], "w") as sedml_file:
            sedml_file.write(libsedml.SedWriter().writeSedMLToString(sedml['doc']))
        archive.addFile(sedml['path'], "./{0}".format(sedml['name']),
                        libcombine.KnownFormats.lookupFormat('sedml'), True)
    elif path.endswith('.wkgp'):
        archive_name = path.split('/')[:-1].pop().split('.')[0]
        file_type = "Workflow Group"
        dst_parent = '/'.join(path.split('/')[:-2])
        archive_errors = convert_workflow_group(path, archive, archive_dir)
    elif path.endswith('.proj'):
        archive_name = path.split('/').pop().split('.')[0]
        file_type = "Project"
        dst_parent = os.path.dirname(path)
        archive_errors = convert_project(path, archive, archive_dir)
    dst, changed = get_unique_file_name(archive_name + ".omex", dst_parent)
    if changed:
        archive_name = dst.split('/').pop().split('.')[0]

    if meta_data is not None:
        add_meta_data(archive, archive_name, meta_data)

    # write the archive to the parent directory of the project
    archive.writeToFile(dst)

    resp = "The {0} {1} was downloaded as {2}".format(file_type,
                                                      path.split('/').pop(),
                                                      archive_name+".omex")
    return {"message":resp, "errors":archive_errors, "file_type":file_type,
            "file_path":dst.replace("/home/jovyan/", "")}
コード例 #13
0
ファイル: comex.py プロジェクト: matthiaskoenig/tellurium-web
def entries_info(archive_path):
    """ Creates entries information for given archive.

    :param archive_path:
    :return:
    """

    # read combine archive contents & metadata
    omex = libcombine.CombineArchive()
    if omex.initializeFromArchive(archive_path) is None:
        print("Invalid Combine Archive: {}", archive_path)
        return None

    # add entries
    entries = []
    for i in range(omex.getNumEntries()):
        entry = omex.getEntry(i)
        location = entry.getLocation()
        format = entry.getFormat()
        info = {}
        info['location'] = location
        info['format'] = format
        info['short_format'] = short_format(format)
        info['base_format'] = base_format(format)
        info['master'] = entry.getMaster()
        info['metadata'] = metadata_for_location(omex, location=location)

        entries.append(info)

    # add root information
    format = 'http://identifiers.org/combine.specifications/omex'
    info = {
        'location': '.',
        'format': format,
        'short_format': short_format(format),
        'base_format': base_format(format),
        'metadata': metadata_for_location(omex, '.'),
        'master': None
    }
    entries.append(info)

    omex.cleanUp()
    return entries
コード例 #14
0
def printArchive(fileName):
    """ Prints content of combine archive

    :param fileName: path of archive
    :return: None
    """
    archive = libcombine.CombineArchive()
    if archive.initializeFromArchive(fileName) is None:
        print("Invalid Combine Archive")
        return None

    print('*' * 80)
    print('Print archive:', fileName)
    print('*' * 80)
    printMetaDataFor(archive, ".")
    print("Num Entries: {0}".format(archive.getNumEntries()))

    for i in range(archive.getNumEntries()):
        entry = archive.getEntry(i)
        print(" {0}: location: {1} format: {2}".format(i, entry.getLocation(),
                                                       entry.getFormat()))
        printMetaDataFor(archive, entry.getLocation())
    archive.cleanUp()
コード例 #15
0
ファイル: omex.py プロジェクト: fanfanruyun/tellurium
def _addEntriesToArchive(omexPath, entries, workingDir, add_entries):
    """

    :param archive:
    :param entries:
    :param workingDir:
    :return:
    """
    omexPath = os.path.abspath(omexPath)
    print('omexPath:', omexPath)
    print('workingDir:', workingDir)

    if not os.path.exists(workingDir):
        raise IOError(
            "Working directory does not exist: {}".format(workingDir))

    if add_entries is False:
        if os.path.exists(omexPath):
            # delete the old omex file
            warnings.warn(
                "Combine archive is overwritten: {}".format(omexPath))
            os.remove(omexPath)

    archive = libcombine.CombineArchive()

    if add_entries is True:
        # use existing entries
        if os.path.exists(omexPath):
            # init archive from existing content
            if archive.initializeFromArchive(omexPath) is None:
                raise IOError("Combine Archive is invalid: ", omexPath)

    # timestamp
    time_now = libcombine.OmexDescription.getCurrentDateAndTime()

    print('*' * 80)
    for entry in entries:
        print(entry)
        location = entry.location
        path = os.path.join(workingDir, location)
        if not os.path.exists(path):
            raise IOError(
                "File does not exist at given location: {}".format(path))

        archive.addFile(path, location, entry.format, entry.master)

        if entry.description or entry.creators:
            omex_d = libcombine.OmexDescription()
            omex_d.setAbout(location)
            omex_d.setCreated(time_now)

            if entry.description:
                omex_d.setDescription(entry.description)

            if entry.creators:
                for c in entry.creators:
                    creator = libcombine.VCard()
                    creator.setFamilyName(c.familyName)
                    creator.setGivenName(c.givenName)
                    creator.setEmail(c.email)
                    creator.setOrganization(c.organization)
                    omex_d.addCreator(creator)

            archive.addMetadata(location, omex_d)

    archive.writeToFile(omexPath)
    archive.cleanUp()
コード例 #16
0
ファイル: core.py プロジェクト: paulflang/PEtab
def create_combine_archive(
    yaml_file: str,
    filename: str,
    family_name: Optional[str] = None,
    given_name: Optional[str] = None,
    email: Optional[str] = None,
    organization: Optional[str] = None,
) -> None:
    """Create COMBINE archive (http://co.mbine.org/documents/archive) based
    on PEtab YAML file.

    Arguments:
        yaml_file: Path to PEtab YAML file
        family_name: Family name of archive creator
        given_name: Given name of archive creator
        email: E-mail address of archive creator
        organization: Organization of archive creator
    """

    path_prefix = os.path.dirname(yaml_file)
    yaml_config = yaml.load_yaml(yaml_file)

    # function-level import, because module-level import interfered with
    # other SWIG interfaces
    try:
        import libcombine
    except ImportError:
        raise ImportError("To use PEtab's COMBINE functionality, libcombine "
                          "(python-libcombine) must be installed.")

    def _add_file_metadata(location: str, description: str = ""):
        """Add metadata to the added file"""
        omex_description = libcombine.OmexDescription()
        omex_description.setAbout(location)
        omex_description.setDescription(description)
        omex_description.setCreated(
            libcombine.OmexDescription.getCurrentDateAndTime())
        archive.addMetadata(location, omex_description)

    archive = libcombine.CombineArchive()

    # Add PEtab files and metadata
    archive.addFile(yaml_file, os.path.basename(yaml_file),
                    libcombine.KnownFormats.lookupFormat("yaml"), True)
    _add_file_metadata(location=os.path.basename(yaml_file),
                       description="PEtab YAML file")

    # Add parameter file(s) that describe a single parameter table.
    # Works for a single file name, or a list of file names.
    for parameter_subset_file in (list(
            np.array(yaml_config[PARAMETER_FILE]).flat)):
        archive.addFile(os.path.join(path_prefix, parameter_subset_file),
                        parameter_subset_file,
                        libcombine.KnownFormats.lookupFormat("tsv"), False)
        _add_file_metadata(location=parameter_subset_file,
                           description="PEtab parameter file")

    for problem in yaml_config[PROBLEMS]:
        for sbml_file in problem[SBML_FILES]:
            archive.addFile(os.path.join(path_prefix, sbml_file), sbml_file,
                            libcombine.KnownFormats.lookupFormat("sbml"),
                            False)
            _add_file_metadata(location=sbml_file, description="SBML model")

        for field in [
                MEASUREMENT_FILES, OBSERVABLE_FILES, VISUALIZATION_FILES,
                CONDITION_FILES
        ]:
            if field not in problem:
                continue

            for file in problem[field]:
                archive.addFile(os.path.join(path_prefix, file), file,
                                libcombine.KnownFormats.lookupFormat("tsv"),
                                False)
                desc = field.split("_")[0]
                _add_file_metadata(location=file,
                                   description=f"PEtab {desc} file")

    # Add archive metadata
    description = libcombine.OmexDescription()
    description.setAbout(".")
    description.setDescription("PEtab archive")
    description.setCreated(libcombine.OmexDescription.getCurrentDateAndTime())

    # Add creator info
    creator = libcombine.VCard()
    if family_name:
        creator.setFamilyName(family_name)
    if given_name:
        creator.setGivenName(given_name)
    if email:
        creator.setEmail(email)
    if organization:
        creator.setOrganization(organization)
    description.addCreator(creator)

    archive.addMetadata(".", description)
    archive.writeToFile(filename)
コード例 #17
0
def check_archive(archive_file, tempdir='../out'):
    """ Checks the given COMBINE archive

    :param archive_file: combine archive
    :param tempdir: temp folder where to extract files too
    :return: boolean indicating whether issues were found (False), or all is good (True)
    """
    archive = libcombine.CombineArchive()
    archive.initializeFromArchive(archive_file)

    name = os.path.splitext(os.path.basename(archive_file))[0]

    temp_dir = os.path.join(tempdir, name)
    if os.path.exists(temp_dir):
        logging.error('remove existing temp dir {}'.format(temp_dir))

    # print files in manifest
    manifest = archive.getManifest()
    expected_locations = []
    sedml_files = []
    sbml_files = []
    assert (isinstance(manifest, libcombine.CaOmexManifest))

    for i in range(manifest.getNumContents()):
        entry = manifest.getContent(i)
        assert (isinstance(entry, libcombine.CaContent))

        # print(f'location: {entry.getLocation()}, master: {entry.getMaster()}, format: {entry.getFormat()}')

        expected_locations.append(entry.getLocation())
        if 'identifiers.org/combine.specifications/sed-ml' in entry.getFormat(
        ):
            sedml_files.append(entry.getLocation())
        if 'identifiers.org/combine.specifications/sbml' in entry.getFormat():
            sbml_files.append(entry.getLocation())

    # extract archive to see if all files are in the manifest
    archive.extractTo(temp_dir)

    result = True
    # check for files not included in manifest
    for root, dirs, files in os.walk(temp_dir):
        for file in files:
            if file not in expected_locations and file not in [
                    'manifest.xml', 'metadata.rdf'
            ]:
                logging.error(
                    f'Encountered unexpected file in archive "{file}" in archive "{name}"'
                )
                result = False

    # check SED-ML files:
    for sedml_file in sedml_files:
        valid, xpath_expressions, model_file = sedml_tools.check_files_exist(
            os.path.join(temp_dir, sedml_file))
        result = result and valid

        if len(xpath_expressions) > 0 and os.path.exists(model_file):
            sbml_tools.validate_sbml_file(model_file, xpath_expressions)

        # check that SBML files are valid
    for sbml_file in sbml_files:
        sbml_tools.validate_sbml_file(os.path.join(temp_dir, sbml_file))

    # cleanup
    shutil.rmtree(temp_dir)
    return result
コード例 #18
0
    def setUp(self):
        self.archive = libcombine.CombineArchive()
        file_name = test_utils.get_example('BIOMD0000000791-20210325-094855.omex')

        self.assertTrue(os.path.exists(file_name))
        self.archive.initializeFromArchive(file_name)
コード例 #19
0
ファイル: core.py プロジェクト: jpahle/Biosimulations_COPASI
def exec_combine_archive(archive_file, out_dir):
    """Execute the SED tasks defined in a COMBINE archive and save the outputs

    :param archive_file: path to COMBINE archive
    :type archive_file: str
    :param out_dir: directory to store the outputs of the tasks
    :type out_dir: str
    :raises FileNotFoundError: When the combine archive is not found
    :raises IOError: When file is not an OMEX combine archive
    """
    # check that archive exists and is in zip format
    if not os.path.isfile(archive_file):
        raise FileNotFoundError("File does not exist: {}".format(archive_file))

    if not zipfile.is_zipfile(archive_file):
        raise IOError("File is not an OMEX Combine Archive in zip format: {}".format(archive_file))

    try:
        archive_file = os.path.abspath(archive_file)
        out_dir = os.path.abspath(out_dir)
        # Create temp directory
        tmp_dir = tempfile.mkdtemp()

        # Get list of contents from Combine Archive
        archive = libcombine.CombineArchive()
        is_initialised = archive.initializeFromArchive(archive_file)
        is_extracted = archive.extractTo(tmp_dir)
        manifest = archive.getManifest()
        contents = manifest.getListOfContents()

        if not is_initialised or not is_extracted:
            sys.exit("Problem while initialising/extract combine archive")

        # Get location of all SEDML files
        sedml_locations = list()
        for content in contents:
            if content.isFormat('sedml'):
                sedml_locations.append(content.getLocation())

        # run all sedml files
        for sedml_location in sedml_locations:
            sedml_path = os.path.join(tmp_dir, sedml_location)
            sedml_out_dir = os.path.join(out_dir, os.path.splitext(sedml_location)[0])

            sedml_doc = libsedml.readSedMLFromFile(sedml_path)

            tasks = sedml_doc.getListOfTasks()
            task_name_list = [task.getId() for task in tasks]

            for sim in range(0, sedml_doc.getNumSimulations()):
                current_doc = sedml_doc.getSimulation(sim)
                if current_doc.getTypeCode() == libsedml.SEDML_SIMULATION_UNIFORMTIMECOURSE:
                    tc = current_doc
                    if current_doc.isSetAlgorithm():
                        kisao_id = current_doc.getAlgorithm().getKisaoID()
                        print("timeCourseID={}, outputStartTime={}, outputEndTime={}, numberOfPoints={}, kisaoID={} " \
                              .format(tc.getId(), tc.getOutputStartTime(), tc.getOutputEndTime(),
                                      tc.getNumberOfPoints(), kisao_id))
                else:
                    print(f"Encountered unknown simulation {current_doc.getId()}")

            if not os.path.isdir(sedml_out_dir):
                os.makedirs(sedml_out_dir)

            # Create a base Copasi container to hold all the Tasks
            try:
                data_model = copasi.CRootContainer.addDatamodel()
            except BaseException:
                data_model = copasi.CRootContainer.getUndefinedFunction()
            data_model.importSEDML(sedml_path)

            report = create_time_course_report(data_model)
            # Run all Tasks
            task_name_index = 0
            for task_index in range(0, len(data_model.getTaskList())):
                task = data_model.getTaskList().get(task_index)
                # Get Name and Class of task as string
                task_str = str(task)
                try:
                    # Get name of Task
                    task_name = task_str.split('"')[1]
                except IndexError:
                    # Get Class name if Task name is not present
                    task_name = task_str.split("'")[1].split("*")[0]
                    task_name = task_name[:len(task_name) - 1]
                # Set output file for the task
                if task_name == 'Time-Course':
                    task.setScheduled(True)
                    # task.getReport().setReportDefinition(report)
                    report_def = task.getReport().compile('')
                    if not report_def:
                        print('No Report definition found in SEDML, setting to a default definition')
                        task.getReport().setReportDefinition(report)
                    sedml_task_name = task_name_list[task_name_index]
                    report_path = os.path.join(sedml_out_dir, f'{sedml_task_name}.csv')
                    task.getReport().setTarget(report_path)
                    task_name_index = task_name_index + 1
                    print(f'Generated report for Simulation "{sedml_task_name}": {report_path}')
                    # If file exists, don't append in it, overwrite it.
                    task.getReport().setAppend(False)
                    # Initialising the task with default values
                    task.initialize(119)
                    task.process(True)
                    try:
                        pd.read_csv(report_path).drop(" ", axis=1).to_csv(report_path, index=False)
                    except KeyError:
                        print(f"No trailing commas were found in {report_path}\n")
                    df = pd.read_csv(report_path)
                    cols = list(df.columns)
                    new_cols = list()
                    for col in cols:
                        new_cols.append(col.split()[-1])
                    df.columns = new_cols
                    df.to_csv(report_path, index=False)

    finally:
        shutil.rmtree(tmp_dir)
コード例 #20
0
def validate_omex(path):
    """ Simple validation by trying to load. """
    omex = libcombine.CombineArchive()
    print("Init archive:")
    if not omex.initializeFromArchive(path):
        print("Invalid Combine Archive")
コード例 #21
0
    def run(self,
            in_file,
            out_dir,
            include_omex_metadata_files=True,
            config=None):
        """ Read an archive from a file

        Args:
            in_file (:obj:`str`): path to archive
            out_dir (:obj:`str`): directory where the contents of the archive should be unpacked
            include_omex_metadata_files (:obj:`bool`, optional): whether to include the OMEX metadata
                file as part of the contents of the archive
            config (:obj:`Config`, optional): configuration

        Returns:
            :obj:`CombineArchive`: description of archive

        Raises:
            :obj:`ValueError`: archive is invalid
        """
        if config is None:
            config = get_config()

        self.errors = []
        self.warnings = []

        if not os.path.isfile(in_file):
            msg = "`{}` is not a file.".format(in_file)
            self.errors.append([msg])
            raise ValueError(msg)

        archive_comb = libcombine.CombineArchive()
        archive_initialized = archive_comb.initializeFromArchive(in_file)
        if archive_initialized:
            errors, warnings = get_combine_errors_warnings(
                archive_comb.getManifest())
            if config.VALIDATE_OMEX_MANIFESTS:
                self.errors.extend(errors)
                self.warnings.extend(warnings)

        if not archive_initialized or errors:
            if not config.VALIDATE_OMEX_MANIFESTS:
                try:
                    archive = CombineArchiveZipReader().run(in_file, out_dir)
                    msg = '`{}` is a plain zip archive, not a COMBINE/OMEX archive.'.format(
                        in_file)
                    self.warnings.append([msg])
                    warn(msg, BioSimulatorsWarning)
                    return archive
                except ValueError:
                    msg = "`{}` is not a valid COMBINE/OMEX archive.".format(
                        in_file)
                    self.errors.append([msg])
                    raise ValueError(msg)
            elif not self.errors:
                msg = "`{}` is not a valid COMBINE/OMEX archive.".format(
                    in_file)
                self.errors.append([msg])
                raise ValueError(msg)

        # instantiate archive
        archive = CombineArchive()

        # read files
        for location in archive_comb.getAllLocations():
            location = location.c_str()
            file_comb = archive_comb.getEntryByLocation(location)

            if file_comb.isSetFormat():
                format = file_comb.getFormat()
            else:
                format = None

            content = CombineArchiveContent(
                location=location,
                format=format,
                master=file_comb.isSetMaster() and file_comb.getMaster(),
            )
            archive.contents.append(content)

        # extract files
        archive_comb.extractTo(out_dir)

        # read metadata files skipped by libCOMBINE
        content_locations = set(
            os.path.relpath(content.location, '.')
            for content in archive.contents)
        manifest_contents = self.read_manifest(os.path.join(
            out_dir, 'manifest.xml'),
                                               in_file,
                                               config=config)

        if include_omex_metadata_files:
            for manifest_content in manifest_contents:
                if (manifest_content.format and re.match(
                        CombineArchiveContentFormatPattern.OMEX_METADATA.value,
                        manifest_content.format)
                        and os.path.relpath(manifest_content.location,
                                            '.') not in content_locations):
                    archive.contents.append(manifest_content)

        if config.VALIDATE_OMEX_MANIFESTS:
            manifest_includes_archive = False
            for manifest_content in manifest_contents:
                if os.path.relpath(manifest_content.location, '.') == '.':
                    if manifest_content.format:
                        if re.match(CombineArchiveContentFormatPattern.OMEX,
                                    manifest_content.format):
                            manifest_includes_archive = True
                        else:
                            msg = 'The format of the archive must be `{}`, not `{}`.'.format(
                                CombineArchiveContentFormat.OMEX,
                                manifest_content.format)
                            self.errors.append([msg])

            if not manifest_includes_archive:
                msg = (
                    'The manifest does not include its parent COMBINE/OMEX archive. '
                    'Manifests should include their parent COMBINE/OMEX archives.'
                )
                self.warnings.append([msg])

        # raise warnings and errors
        if self.warnings:
            warn(
                'COMBINE/OMEX archive may be invalid.\n  ' +
                flatten_nested_list_of_strings(self.warnings).replace(
                    '\n', '\n  '), BioSimulatorsWarning)
        if self.errors:
            raise ValueError(
                '`{}` is not a valid COMBINE/OMEX archive.\n  {}'.format(
                    in_file,
                    flatten_nested_list_of_strings(self.errors).replace(
                        '\n', '\n  ')))

        # return information about archive
        return archive