Skip to content

Loading a VCML file into BiomodelVisitor object #30

@smgroves

Description

@smgroves

the load_vcml_file function seems to only recognize some types of parameters (ModelParameters and Kinetics). My VCML model has an "ApplicationParameter" that isn't recognized. I was able to patch this with the following code, but I'm not sure if this is the best way to do it because it's not clear to me with the ApplicationParameters are; the ones that my file has are output by my patch:
Skipped parameters: [{'name': 'appParm0', 'parent_tag': 'ApplicationParameters', 'text': '1.0'}, {'name': 'appParm1', 'parent_tag': 'ApplicationParameters', 'text': '1.0'}, {'name': 'appParm2', 'parent_tag': 'ApplicationParameters', 'text': '1.0'}, {'name': 'appParm3', 'parent_tag': 'ApplicationParameters', 'text': '1.0'}]

import pyvcell.vcml as vc
from lxml.etree import _Element
import pyvcell.vcml as vc
from lxml import etree
from pathlib import Path


def load_vcml_file_patched(vcml_file: str | Path) -> vc.Biomodel:
    """
    Load a VCML file using PatchedBiomodelVisitor.
    Logs skipped parameters in the visitor.
    """
    vcml_file = Path(vcml_file)
    with open(vcml_file, "r", encoding="utf-8") as f:
        vcml_str = f.read()

    document = vc.VCMLDocument()
    visitor = PatchedBiomodelVisitor(document)

    root = etree.fromstring(vcml_str.encode("utf-8"))
    visitor.visit(root, document)

    if visitor.skipped_parameters:
        print("Skipped parameters:", visitor.skipped_parameters)

    if visitor.document.biomodel is None:
        raise ValueError("No biomodel found in VCML file.")

    return visitor.document.biomodel


class PatchedBiomodelVisitor(vc.vcml_reader.BiomodelVisitor):
    def __init__(self, document):
        super().__init__(document)
        self.skipped_parameters = []  # store skipped parameters

    def visit_Parameter(self, element: _Element, node: vc.Model | vc.Kinetics | vc.Application) -> None:
        parent: _Element | None = element.getparent()
        if parent is None:
            raise ValueError("Parameter element has no parent")
        text: str = element.text or ""
        value: str | float = vc.vcml_reader.float_or_formula(text)
        name: str = element.get("Name", default="unnamed")
        role = element.get("Role", default="user defined")
        unit = element.get("Unit", default="tbd")

        parameter = None

        parent_tag = vc.vcml_reader.strip_namespace(parent.tag)
        if parent_tag == "ModelParameters":
            model: vc.Model = node  # type: ignore
            model_parameter = vc.ModelParameter(
                name=name, value=value, role=role, unit=unit)
            model.model_parameters.append(model_parameter)
            parameter = model_parameter
        elif parent_tag == "Kinetics":
            kinetics: vc.Kinetics = node  # type: ignore
            reaction_node = parent.getparent()
            if reaction_node is None:
                raise ValueError("Kinetics element has no parent")
            reaction_name = reaction_node.get("Name", default="unknown")
            kinetics_parameter = vc.KineticsParameter(
                name=name, value=value, role=role, unit=unit, reaction_name=reaction_name
            )
            kinetics.kinetics_parameters.append(kinetics_parameter)
            parameter = kinetics_parameter
        else:
            # Log skipped parameters
            self.skipped_parameters.append({
                "name": name,
                "parent_tag": parent_tag,
                "text": text
            })
            # Do not raise an error; just skip
            return

        self.generic_visit(element, parameter)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions