sbmlteam / libsbml

LibSBML is a native library for reading, writing and manipulating files and data streams containing the Systems Biology Markup Language (SBML). It offers language bindings for C, C++, C#, Java, JavaScript, MATLAB, Perl, PHP, Python, R and Ruby.

Home Page:https://sbml.org/software/libsbml

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Explicit Equations in SBML

shoepfl opened this issue · comments

Dear SBML team,

this might be a strange request but is it possible to work with explicit equations using SBML?
I know that the scope of SBML are ODEs, however at the moment I have an explicit equation that I would like to model like a typical ODE (meaning I would like to use the tools for SBML).

Is this possible and what would be the best way to do so?
My aim is to create a PEtab file with this explicit equation.

Thanks for your help.

Best,
Sebastian

Hi Sebastian,

could you provide an actual example of such an equation? I.e. a minimal example of what you are trying to do.

Also I would post the question in addition on SBML discuss https://groups.google.com/g/sbml-discuss/?pli=1
There are more people knowing all the tricks of SBML.

Best Matthias

Hello Sebastian,

if you have an example of what you precisely want to do then that would help. With the libsbml::ASTNode class, you can encode any right hand side of any equation you would want to encode. We have examples showing how to convert between mathml / infix / astnodes ... and example on how to evaluate those expressions.

I'm sure you would find something you'd want to do

again once we know what exactly you would want to have we can give more precise answers.

Hi Matthias and Frank,

thanks for the quick response. My aim is to implement a Retarded Transient function as in the approach of Clemens Kreutz (https://www.frontiersin.org/articles/10.3389/fphy.2020.00070/full). This is very interesting as he states that this could replace many ODEs in biological usecases. The equation looks like this:
grafik

so I have a function for which I want to optimize the parameters, however its not an ODE but an explicit equation.

I found a workaround by now with yaml2sbml:
RTD_yaml2sbml_example.txt

so basically I introduced the equation via an assignment rule. The trick here is that the right hand side that is just 1 (t'=1), which gives me a linear behaviour for t but I wanted to ask if there is a better soultion since this is somehow cheated

I think what you are looking for is either an AssignmentRule or a RateRule. If your equation means 'RTF is always equal to this equation', then you want an AssignmentRule for RTF, and if it means 'dRTF/dt is equal to this equation', then a RateRule for RTF is what you want.

However, I'm not sure what Asus, Atrans, and your t() functions are. If A is a matrix, then SBML cannot encode the equation, unless perhaps you break it down into individual functions for each element of that matrix. If they're 'just' functions, then that's obviously much easier.

I also suspect that your t() equations are delays? Maybe? Delays can indeed be encoded in SBML, though fewer simulators support them. 'delay(S1, Tshift)' means 'the value of S1 as it was Tshift seconds ago', which perhaps will help you; the fact that the function is called 'Retarded Transient' makes me suspect that perhaps this indeed is what's going on.

Basically, if you can break down that function into equations that only contain reals, that mean 'X is always f(y)' or 'the rate of change of X is f(y)', then you should be able to encode it in SBML. And if those functions involve delays, you'll have to ensure that the simulator you're using supports delay equations.

Thanks yes an AssignmentRule should be appropriate in this case - as ist RTF is equal to.

Asus and Atrans are also just the parameters for the sustained and the transient activation so no matrices involved. And as I use amici, which as far as I know does not supprot delay functions yet, I calculate the delay by myself via the function time_trafo=log10(10^(ti*10/Trange)+10^Tshift)-log10(1+10^Tshift) where Trange is the observed time-span and Tshift is the delay I want to estimate.

I will try this now and have a look if it works like expected.

Thanks again, I will write when I have the results

Hi Sebastian,
see attached how to create this with sbmlutils. Let me know if this is what you are looking for.
Script and model attached.
explicit_equations.zip

"""Example model for encoding an equation as AssignmentRule."""
from pkdb_models.models.sorafenib.models import templates
from sbmlutils.factory import *
from sbmlutils.metadata import *

class U(templates.U):
    """UnitDefinitions"""

    pass


version = 1
_m = Model(
    sid="explicit_equations",
    name="Model for explict equations.",
    notes=f"""
    Model for explicit equations.
    
    This model demonstrates the use of assignment rules for encoding explict equations.

    """,
    units=U,
    model_units=ModelUnits(
        time=U.second,
        extent=U.mmole,
        substance=U.mmole,
        length=U.meter,
        area=U.m2,
        volume=U.liter,
    ),
    creators=[
        Creator(
            familyName="König",
            givenName="Matthias",
            email="konigmatt@googlemail.com",
            organization="Humboldt-University Berlin, Institute for Theoretical Biology",
        )
    ]
)

# constant parameters
_m.parameters = [
    Parameter(
        "p0",
        1.0,
        U.dimensionless,
        name="p baseline",
        sboTerm=SBO.KINETIC_CONSTANT,
    ),
    Parameter(
        "A_sus",
        1.0,
        U.dimensionless,
        name="A sus",
        sboTerm=SBO.KINETIC_CONSTANT,
    ),
    Parameter(
        "A_trans",
        1.0,
        U.dimensionless,
        name="A trans",
        sboTerm=SBO.KINETIC_CONSTANT,
    ),
    Parameter(
        "tau1",
        1.0,
        U.second,
        name="tau1",
        sboTerm=SBO.KINETIC_CONSTANT,
    ),
    Parameter(
        "tau2",
        1.0,
        U.second,
        name="tau2",
        sboTerm=SBO.KINETIC_CONSTANT,
    ),
    Parameter(
        "tau1_dash",
        1.0,
        U.second,
        name="tau2",
        sboTerm=SBO.KINETIC_CONSTANT,
    ),
    Parameter(
        "f_RTF",
        1.0,
        U.dimensionless,
        name="f_RTF",
        sboTerm=SBO.KINETIC_CONSTANT,
        constant=False
    )
]

_m.assignments = [
    AssignmentRule(
        "f_RTF",
        "A_sus * (1 dimensionless - exp(-time/tau1)) + A_trans * (1 dimensionless - exp(-time/tau1_dash)) * exp(-time/tau2) + p0",
        unit=U.dimensionless,
        notes="""
        Assignment rule for equation.
        """
    )
]

if __name__ == "__main__":
    from pathlib import Path
    result = create_model(
        filepath=Path(__file__).parent / f"{_m.sid}.xml",
        model=_m, sbml_level=3, sbml_version=2
    )

Visualized in https://sbml4humans.de
Screenshot 2023-05-04 at 11-02-53 SBML4Humans

Best Matthias

Hi Matthias,

thanks a lot for the example. This looks now like the xml I created with yaml2sbml but without the "trick" of using an ode so thats nice. So I will go this way and try to make this possible with yaml2sbml where an ode-specification is mandatory at the moment.

yaml2sbml is thereby the way I want to go as it gives me the complete PEtab problem by just specifying the yaml.

I think I can close this here as also my yaml with the tricked ode is working by now and I also know now that it works without it.

Thanks again for the help - I really like the possibility to use SBML also in this way.