Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Specification of Timecourses #581

Draft
wants to merge 31 commits into
base: main
Choose a base branch
from
Draft

WIP: Specification of Timecourses #581

wants to merge 31 commits into from

Conversation

fbergmann
Copy link
Contributor

@fbergmann fbergmann commented May 22, 2024

This draft PR adds the descriptions from the Time course specification to the release/2.0.0 branch.

preview site is: https://petab--581.org.readthedocs.build/en/581/documentation_data_format.html#timecourses-table

FFroehlich and others added 17 commits March 10, 2023 07:32
* extract all changes from previous

* fixup

* allow hyphens in extension names

* fixup hyphens

* only require one toolbox that implements extension

* specify how to work with multiple PEtab problems

* specify we do not require a quorum number of votes

* allow test cases to be provided by the extension library

* Apply suggestions from code review

Co-authored-by: Daniel Weindl <[email protected]>

Co-authored-by: Daniel Weindl <[email protected]>
PEtab extensions were introduced in #537. We should be able to distinguish there between optional extensions and required extensions, i.e. those that modify the parameter estimation problem as such, and those that just add additional/optional information (e.g. annotations, info for visualization, ...). If some tool does not know about a certain optional extension, it can safely be ignored during import, if it does not know about a required extension, it should fail.

This PR adds a `required` attribute to extensions in the yaml file to indicate whether they are required for the mathematical interpretation of the PEtab problem.

Resolves #544
- remove preequilibrationConditionId
- remove simulationConditionId
- add timecourseID
@dweindl
Copy link
Member

dweindl commented May 23, 2024

Thx Frank.

Maybe #541 and #542 can also be addressed here.

@dweindl dweindl linked an issue May 30, 2024 that may be closed by this pull request
dweindl and others added 2 commits June 26, 2024 16:00
Previously, the math expression syntax wasn't specified. This was very problematic, because different libraries and programming languages have different names for the same functions, and more importantly, differ in operator precedence.


Co-authored-by: Dilan Pathirana <[email protected]>
Co-authored-by: dilpath <[email protected]>
@dweindl
Copy link
Member

dweindl commented Dec 5, 2024

Resolved merge conflicts.

This needs to be updated to match the new mostly-agreed-upon format in #586

  • changed conditions table
  • changed experiments table
  • add examples from google doc - to be updated to the new format
  • update v2/gfx/petab_scope_and_files.svg: changed names, changed columns, match color of conditions+experiments table
  • v2/gfx/petab_scope_and_files.svg / v2/gfx/petab_files.svg : smaller SBML logo / indicate alternatives

@dweindl dweindl force-pushed the v2_timecourses branch 2 times, most recently from b79293f to 56be96d Compare December 10, 2024 20:14
dweindl added a commit to PEtab-dev/libpetab-python that referenced this pull request Dec 18, 2024
Add basic support for PEtab version 2 experiments (see also PEtab-dev/PEtab#586, and  PEtab-dev/PEtab#581). Follow-up to #334.

Partially supersedes #263, which was started before petab.v1/petab.v2 were introduced and before PEtab-dev/PEtab#586.

* updates the required fields in the measurement table
* updates some validation functions to not expect the old `simulationConditionId`s (but does not do full validation yet)
* extends PEtab v1 up-conversion to create a new experiment table.

---------

Co-authored-by: Dilan Pathirana <[email protected]>
values as defined in the model).
The target must be a constant target or a differential target.

- ``setRate``: The time-derivative of the target is set to ``targetValue``
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems natural to have an addToCurrentValue as well

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine to have it for coherence. For simplicity, we could leave it out, since in this case, the target value for setCurrentValue and X could easily be written as X + 10 instead of addToCurrentValue, X, 10.

Another question is what other operations we would need. multiply{CurrentValue,Rate,...}? exp? log?

It would be nice if we could always just refer to the old value in targetValue, but that would require introducing additional functions there (rateOf, rateExpressionOf, ...). That would reduce the list of operations, and one could also use the old values of other entities, not just that of the current target.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that sounds like it would be helpful to introduce targetValue in favour of having addTo, multiply, etc.

Why would we need operators like rateOf, rateExpressionOf? I don't see why one would ever transfer information from rate to value and everything else should be achievable one way or another.

Also, what about using setValue in favor of setCurrentValue?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One use case where one might want to use both the current value and the rate expression could be some piecewise definition of a rate expression where the condition depends on the current state. I'd don't consider super important.

This is specified as a tab-separated value file in the following way:

+---------------------+-------------------+-----------------+
| experimentId | time | conditionId |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I agree that we can drop the name in the conditions table, I think it would be nice to have an optional name column here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine to add experimentName here if we drop the condition names. However, if we want to keep condition names, which then would have to be specified in some other place (yaml, annotations table, ...?), I would collect all of that in the same place.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case I would propose to move all names (including observables etc) to such a table. Would anyways be nice as it would introduce the possibility of, e.g. naming states.

Copy link
Member

@dilpath dilpath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'm happy to review this again after the current feedback round


- A model

- A measurement file to fit the model to [TSV]

- A condition file specifying model inputs and condition-specific parameters
- (optional) A condition file specifying model inputs and condition-specific parameters
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we usually refer to this as the "conditions table"

Suggested change
- (optional) A condition file specifying model inputs and condition-specific parameters
- (optional) A conditions file specifying model inputs and condition-specific parameters

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Makes sense to use coherent terminology. Also for all other tables/files...

* Clarification and specification of various previously underspecified aspects
(math expressions, overriding values in the condition table, etc.)
(:ref:`math_expressions`, overriding values in the condition table, etc.)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should list everything (explicitly or by some grouping)

Suggested change
(:ref:`math_expressions`, overriding values in the condition table, etc.)
(:ref:`math_expressions`, overriding values in the condition table)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be updated once all changes here have been finalized.

| ... | ... | ... | | ... |
+--------------+------------------+------------------+-----------------+--------------------+

Each line specifies a change of one specific property of a specific entity.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Each line specifies a change of one specific property of a specific entity.
Each line specifies the change in the numeric value of one specific non-estimated entity.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This hides the fact that a single entity has different types of associated values (e.g., current value vs. rate) and excludes "symbolic assignment" like setAssignment, doesn't it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right, make sense. Then to avoid the word property, which isn't defined yet:

Suggested change
Each line specifies a change of one specific property of a specific entity.
Each line specifies one change in one target entity.

+---------------------+-------------------+-----------------+
| experimentId | time | conditionId |
+=====================+===================+=================+
| PETAB_ID | NUMERIC or '-inf' | CONDITION_ID |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, in the measurements table it is NUMERIC\|inf instead

@dweindl
Copy link
Member

dweindl commented Feb 11, 2025

Thanks for the feedback.

Co-authored-by: Dilan Pathirana <[email protected]>
Co-authored-by: Fabian Fröhlich <[email protected]>
dweindl and others added 2 commits February 11, 2025 10:45

This is specified as a tab-separated value file in the following way:

**TODO: keep conditionName or not?**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

conditionName I think can be kept as optional as it can help with nicer plotting.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that now there may be several rows per condition, which makes it not so ideal to specify any condition names there. Would you still keep it that table? Would all rows for that condition have to have the same value, or should there only be one non-empty entry per condition?

Comment on lines +238 to +239
- ``setAssignment``: The target is set to the value of ``targetValue``
(symbolically).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I have missed this discussion, but, is setRate, setAssignment and other operationType that alter in a sense the dynamic model (e.g. if setRate = 0.0 for one condition and setRate = 1.0 for another, the structural model differs between conditions, so I imagine that tools need to basically build multiple model structures during import), something that is going to be supported and encouraged to be supported by most PEtab tools?

Instead if this is a feature that is reserved to mean this, maybe it should be stated somewhere (so that users and potential developers of importers does not think this is a key important feature to support)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this is discussed after Differential/Algebraic/Constant targets are introduced. To my understanding, structural alterations are not allowed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might have different understandings of "structural alterations". Changing some algebraic expression e := x to e := y would be allowed, but changing some differential state to some algebraic expression would not be allowed. In how much that requires building different models is probably very much implementation dependent.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might have different understandings of "structural alterations". Changing some algebraic expression e := x to e := y would be allowed, but changing some differential state to some algebraic expression would not be allowed. In how much that requires building different models is probably very much implementation dependent.

Thanks for clarification, just a last question to fully understand. So if we have a parameter given via an assignment rule; k = k1 * k2 would it then be allowed to change k via setAssignment?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that was to my understanding the (only) use case for setAssignment.

graph between model components:

- When a condition changes quantity ``A`` and ``B``, and ``B`` is dependent on
``A``, the change in quantity A should be applied first such that the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not how SBML work right?

If I remember correctly if both A and B are assigned something in an event, basically the pre-event A and B values are used unless priority is specified.

But regardless, I agree compartment should have priority.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not how SBML work right?

If I remember correctly if both A and B are assigned something in an event, basically the pre-event A and B values are used unless priority is specified.

I'm not sure, all I see in the SBML spec is (regarding simultaneously-occurring events)

A given simulator may use any algorithm to choose an order as long as every event is executed exactly once.

This choice of compartment priority (and more generally to respect the dependency graph) is partly based on discussions with @matthiaskoenig last year -- perhaps @matthiaskoenig can say more here?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a difference between simultaneously occuring events and simultaneous assignments during the same event. I would treat assignments via conditions the same as a single event, i.e. not subject to priority or useValuesFromTriggerTime attributes. I would propose to not follow the dependency graph (and rather simply use pre-assignment values) with the exception of compartments. As done with SBML Event Assignments (even though this isn't crystal clear in the sbml spec).

For example it might make sense to average two species A = B = (A + B)/2. Due to circularity, this assignment is not possible when following the dependency graph, but straightforward with pre-change values. Following of dependencies can always be reproduces through substitution.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want 2 different behaviors. These are managed in SBML events via the useValuesFromTriggerTime flag. So we need probably this flag on the timecourse to ensure both scenarios are possible (see also comment below)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd vote for @FFroehlich's suggestion here.

@matthiaskoenig
Copy link

In the timecourses, what we essentially have are event assignments triggered at t=t_trigger​. All event assignments must be executed simultaneously—this is not a step-by-step process. Instead, the model state must transition to the new state all at once. Any mathematical expressions that depend on updated parameters, compartments, or species must be re-evaluated accordingly. In other words, all changes are applied in a single step, and the AST (Abstract Syntax Tree) affected by these changes is fully re-evaluated. There is no predefined execution order—it is a single transformation of the model state.

Therefore, the claim that "compartment has priority" is incorrect and does not make sense. The underlying issue is that PETab changes are not clearly defined and have been incorrectly implemented by simulators. As seen in cases where changes affect both compartment volumes and concentrations, many simulators apply these changes sequentially, which is incorrect. Instead, all triggered changes must be applied in a single step. This clarification should also be explicitly stated for changes applied outside of timecourses.

Additionally, in SBML, there is a flag called useValuesFromTriggerTime, which allows the use of values before the assignments. This is likely what you are referring to:

The time of assignment is not affected by the Event attribute useValuesFromTriggerTime—that attribute affects the time at which the EventAssignment’s math expression is evaluated. In other words, SBML allows decoupling the time at which the variable is assigned from the time at which its value expression is calculated.

@matthiaskoenig
Copy link

In SBML, all ListOf constructs are unordered lists. This means an SBML model can be modified by shuffling any ListOf elements, such as ListOfEventAssignments, without affecting the numerical results of a simulation. In other words, there is no inherent order in these lists, nor are there execution priorities—except in cases where ordering is necessary, in which attributes like priority have been introduced to dictate the execution of multiple Events.

The same principle should apply when multiple changes are made in PETab: all changes should be applied simultaneously. If ordering is required, an explicit order or priority attribute must be introduced. If mathematical expressions need to reference values from the end of the previous time span, a useValuesFromTriggerTime mechanism is necessary. For cases where a mix of behaviors is needed, an Event-like construct could be introduced, allowing assignments to be grouped and prioritized.

There is a reason SBML Events are complex. Either we adopt a full event-based approach where changes can be triggered after each time span, or we adhere to a simpler default approach where all changes are applied simultaneously.

One concern is that specifications often end up reflecting existing implementations rather than defining a general, correct solution. This appears to be happening here, as most PETab implementations currently apply changes sequentially. This approach is likely incorrect, but since the specification does not clearly define the intended behavior, there is uncertainty. Moreover, it does not align with what users of SBML models would expect.

@dweindl
Copy link
Member

dweindl commented Feb 26, 2025

since the specification does not clearly define the intended behavior, there is uncertainty

Right. That definitely needs to be addressed.

what users of SBML models would expect

To be honest, I am not sure for how many SBML users the users' expectations match the SBML standard when it comes to event assignments. I am still regularly confused when it comes to simultaneous changes in compartment sizes and concentrations.
That was one reason why we considered different options, such as the compartment-change-first approach.
I'd find some explicit priority the most intuitive and least error-prone. This would in my opinion also cause the least issues with non-SBML models, where the interpretation as dependent/independent quantity is maybe less clear.

@matthiaskoenig
Copy link

The main issue with establishing a fixed order for updating multiple variables (such as compartments, species, or parameters) is that mathematical calculations dependent on these variables could produce unexpected results depending on the update sequence.

For example, consider a compartment V and a concentration C. Any calculation that relies on both V and C may yield different outcomes depending on the update order. Suppose we start with V=1 and C=1, then update both to V=10 and C=10. If there is a calculation dependent on the relationship between V and C, the result will vary based on the order in which they are updated. For instance, an event triggered when V>C will only occur if V is updated before C. If C is updated first or both are updated simultaneously, the event may not trigger, leading to inconsistencies.

In other words, updating variables sequentially in a fixed order can lead to intermediate steps that place the model in an undefined state. This issue persists regardless of the specific order. Therefore, it is essential to either update all variables synchronously or clearly define and follow a predetermined update sequence for each variable to maintain a consistent model state (simply updating compartments before species does not resolve the issue).

The issue with the concentrations is just one of such a problem because species concentrations depend on their compartment volumes, so there is a math dependency linking C and V which depends on the order. But there can be many such dependencies in the math of the model.

@dweindl
Copy link
Member

dweindl commented Feb 27, 2025

Okay, fair point. The intermediate model states would be a problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
6 participants