예제 #1
0
def test_sbml_level_version(level: int, version: int, tmp_path: Path) -> None:
    """Test that the various levels and versions of SBML can be generated."""
    md = {
        "mid": "level_version",
        "compartments": [Compartment(sid="C", value=1.0)],
        "species": [
            Species(
                sid="S1",
                initialConcentration=10.0,
                compartment="C",
                hasOnlySubstanceUnits=False,
                boundaryCondition=True,
            )
        ],
        "parameters": [Parameter(sid="k1", value=1.0)],
        "reactions": [
            Reaction(sid="R1", equation="S1 ->", formula=("k1 * S1 * sin(time)", "-"))
        ],
    }

    results = create_model(
        modules=md,
        output_dir=tmp_path,
        tmp=False,
        units_consistency=False,
        sbml_level=level,
        sbml_version=version,
    )
    doc = read_sbml(source=results.sbml_path, validate=False)
    assert level == doc.getLevel()
    assert version == doc.getVersion()
예제 #2
0
def flatten_sbml(sbml_path: Path,
                 filepath=None,
                 leave_ports=True) -> libsbml.SBMLDocument:
    """Flatten given SBML file.

    :param sbml_path: Comp SBML Path
    :param filepath: SBML file to write to
    :param leave_ports: flat to leave ports in flattened model.

    :return: flattened SBMLDocument
    """
    # FIXME: not working with relative paths,
    # necessary to change the working directory to the sbml file directory
    # to resolve relative links to external model definitions.
    if not isinstance(sbml_path, Path):
        sbml_path = Path(sbml_path)

    working_dir = os.getcwd()
    os.chdir(str(sbml_path.parent))

    doc = read_sbml(source=sbml_path)
    flat_doc = flatten_sbml_doc(doc,
                                leave_ports=leave_ports,
                                output_path=filepath)

    # change back the working dir
    os.chdir(working_dir)

    return flat_doc
예제 #3
0
def test_odefac_to_python(sbml_path: Path, tmp_path: Path) -> None:
    """Create python code for given model."""
    doc: libsbml.SBMLDocument = read_sbml(sbml_path)
    sbml2ode = SBML2ODE(doc=doc)
    out_path = tmp_path / "model.py"
    sbml2ode.to_python(out_path)
    assert out_path.exists()
예제 #4
0
def test_compartment_value(
    value: Any, constant: bool, expected: Dict, tmp_path: Path
) -> None:
    m1 = {
        "mid": "compartment_value",
        "compartments": [Compartment(sid="C", value=value, constant=constant)],
    }

    result = create_model(
        modules=m1,
        output_dir=tmp_path,
        units_consistency=False,
    )

    doc = read_sbml(source=result.sbml_path)
    model = doc.getModel()  # type: libsbml.Model
    assert model.getNumCompartments() == expected["compartments"]
    assert model.getNumInitialAssignments() == expected["initial_assignments"]
    assert model.getNumRules() == expected["rules"]
예제 #5
0
 def from_sbml(source: Union[Path, str]) -> "SBMLDocumentInfo":
     """Read model info from SBML."""
     doc: libsbml.SBMLDocument = read_sbml(source)
     return SBMLDocumentInfo(doc=doc)
예제 #6
0
def merge_models(
    model_paths: Dict[str, Path],
    output_dir: Path = None,
    merged_id: str = "merged",
    validate: bool = True,
) -> libsbml.SBMLDocument:
    """Merge models in model path.

    All models must exist in the same subfolder.
    Relative paths are set in the merged models.

    Output directory must exist.

    :param output_dir:
    :param merged_id:
    :param validate:
    :param model_paths: absolute paths to models
    :return:
    """
    # necessary to convert models to SBML L3V1
    cur_dir = os.getcwd()
    os.chdir(str(output_dir))

    base_dir = None
    for model_id, path in model_paths.items():
        if path.exists():
            logging.error(f"Path for SBML file does not exist: {path}")

        # get base dir of all model files from first file
        if base_dir is None:
            base_dir = path.parent
        else:
            new_dir = path.parent
            if not new_dir != base_dir:
                raise IOError(f"All SBML files for merging must be in same "
                              f"directory: {new_dir} != {base_dir}")

        # convert to L3V1
        path_L3: Path = output_dir / f"{model_id}_L3.xml"  # type: ignore
        doc = read_sbml(path_L3)
        if doc.getLevel() < SBML_LEVEL:
            doc.setLevelAndVersion(SBML_LEVEL, SBML_VERSION)
        write_sbml(doc, path_L3)
        model_paths[model_id] = path_L3

    if validate is True:
        for path in model_paths:  # type: ignore
            validate_sbml(source=path, name=str(path))

    # create comp model
    merged_doc = create_merged_doc(
        model_paths, merged_id=merged_id)  # type: libsbml.SBMLDocument
    if validate is True:
        validate_sbml(path, name=str(path))

    # write merged doc
    f_out = os.path.join(output_dir,
                         "{}.xml".format(merged_id))  # type: ignore
    libsbml.writeSBMLToFile(merged_doc, f_out)

    os.chdir(cur_dir)
    return merged_doc
예제 #7
0
def merge_models(
    model_paths: Dict[str, Path],
    output_dir: Path,
    merged_id: str = "merged",
    flatten: bool = True,
    validate: bool = True,
    validate_input: bool = True,
    units_consistency: bool = False,
    modeling_practice: bool = False,
    sbml_level: int = 3,
    sbml_version: int = 1,
) -> libsbml.SBMLDocument:
    """Merge SBML models.

    Merges SBML models given in `model_paths` in the `output_dir`.
    Models are provided as dictionary
    {
        'model1_id': model1_path,
        'model2_id': model2_path,
        ...
    }
    The model ids are used as ids for the ExternalModelDefinitions.
    Relative paths are set in the merged models.

    The created model is either in SBML L3V1 (default) or SBML L3V2.

    :param model_paths: absolute paths to models
    :param output_dir: output directory for merged model
    :param merged_id: model id of the merged model
    :param flatten: flattens the merged model
    :param validate: boolean flag to validate the merged model
    :param validate_input: boolean flag to validate the input models
    :param units_consistency: boolean flag to check units consistency
    :param modeling_practice: boolean flag to check modeling practise
    :param sbml_level: SBML Level of the merged model in [3]
    :param sbml_version: SBML Version of the merged model in [1, 2]
    :return: SBMLDocument of the merged models
    """
    # necessary to convert models to SBML L3V1
    if isinstance(output_dir, str):
        logger.warning(
            f"'output_dir' should be a Path but: '{type(output_dir)}'")
        output_dir = Path(output_dir)
    if not output_dir.exists():
        raise IOError(f"'output_dir' does not exist: {output_dir}")

    validate_kwargs: Dict[str, bool] = {
        "units_consistency": units_consistency,
        "modeling_practice": modeling_practice,
    }

    for model_id, path in model_paths.items():
        if not path.exists():
            raise IOError(f"Path for SBML file does not exist: {path}")
        if isinstance(path, str):
            path = Path(path)

        # convert to L3V1
        path_L3: Path = output_dir / f"{model_id}_L3.xml"
        doc = read_sbml(path)
        doc.setLevelAndVersion(sbml_level, sbml_version)
        write_sbml(doc, path_L3)
        model_paths[model_id] = path_L3

        if validate_input:
            validate_sbml(
                source=path_L3,
                name=str(path),
                **validate_kwargs,
            )

    # create comp model
    cur_dir = os.getcwd()
    os.chdir(str(output_dir))
    merged_doc: libsbml.SBMLDocument = _create_merged_doc(model_paths,
                                                          merged_id=merged_id)
    os.chdir(cur_dir)

    # write merged doc
    merged_path = output_dir / f"{merged_id}.xml"
    write_sbml(merged_doc, filepath=merged_path)
    if validate:
        validate_sbml(merged_path, name=str(merged_path), **validate_kwargs)

    if flatten:
        flat_path = output_dir / f"{merged_id}_flat.xml"
        flatten_sbml(sbml_path=merged_path, sbml_flat_path=flat_path)
        if validate:
            validate_sbml(flat_path, name=str(flat_path), **validate_kwargs)

    return merged_doc