Skip to content

ExperimentsToSbmlConverter: keep per-experiment constants in the condition table - #579

Open
FFroehlich wants to merge 2 commits into
mainfrom
claude/experiments-to-sbml-condition-parameters
Open

FFroehlich wants to merge 2 commits into
mainfrom
claude/experiments-to-sbml-condition-parameters

Conversation

@FFroehlich

Copy link
Copy Markdown
Collaborator

ExperimentsToSbmlConverter encodes every change made at the start of an experiment in the model. Each experiment gets an indicator parameter, and each changed target gets one initial assignment of the form Piecewise((v_1, ind_1 > 0.5), ..., (v_n, ind_n > 0.5), (default, True)). Since #546 that piecewise is flat, but it still has one branch per experiment.

Froehlich_CellSystems2018, upgraded to v2, has 9169 experiments. Each has a single period that sets 145 targets: 122 parameters and 23 species, the gene expression levels, mutation status and initial protein amounts of a cell line. That is 1,329,505 changes, which become 9169 indicator parameters and 145 initial assignments of about 9169 branches each. With libpetab 0.10.0, pyPESTO's PetabImporter on this problem was still in _create_initial_assignments after 1 h 43 min and had not reached AMICI. On a reduced model whose targets are all parameters, AMICI's import then took more than 2 h on one core, and the generated code did not compile. Imported as PEtab v1, AMICI imports and generates code for the same model in 917 s.

Change

A change now stays in the condition table if it sets a condition parameter: a per-experiment constant, like a column of a PEtab v1 condition table. A target qualifies if:

  • it is a constant SBML parameter, or a species whose initial value in the model is a number (after substituting compartment sizes that nothing changes);
  • the model does not assign it (no rule, initial assignment or event assignment);
  • it is not in the parameter table or the mapping table, and is not an observable or noise placeholder;
  • it is changed only in the first period of an experiment, and only to numbers.

A parameter's changes are kept as they are. A species gets a parameter _petab_initial_value_<id> that holds its initial value, and the initial assignment <id> = _petab_initial_value_<id>. Its changes become changes of that parameter.

The kept changes go into the experiment's indicator condition (_petab_experiment_condition_<id>), which both kept periods reference. So a value set in pre-equilibration persists into the main period, as it would in the model.

An experiment now gets an indicator parameter only if one of its changes is encoded in the model, as an initial assignment branch or an event. For Froehlich, no indicators and no piecewise assignments remain: 23 initial assignments of the form above, and conversion takes 97 s.

AMICI needs no change. Its v2 importer already makes every remaining condition target a fixed parameter (_do_import_sbml), and ExperimentManager._set_constants sets those per experiment and period.

The converter's output contract changes: a consumer now has to apply all changes of the kept periods, not just the indicators. The class docstring says so. _simulate in tests/v2/test_assignments_to_experiments.py simulated the converted model by setting only the indicator; it now applies the kept conditions, as AMICI does. There is no opt-out flag; one could be added if a consumer needs everything encoded in the model.

Verification

  • New tests in tests/v2/test_converters.py:

    • condition parameters and species stay in the conditions;
    • only experiments with model-encoded changes get an indicator;
    • these targets are still encoded: a parameter that is estimated, changed in a later period, set to an expression, or has an initial assignment; a species with an initial assignment, or whose amount-based initial value depends on a compartment that conditions resize;
    • a species that no condition sets is left alone;
    • a condition parameter set in pre-equilibration is kept for both periods.

    test_initial_assignments_many_experiments now also changes A in a later period, so A still gets the flat piecewise that test is about.

  • pytest tests/v2: 276 passed, 2 skipped (with basico installed). test_petablint_v2 fails in my environment because petablint is not on PATH; it fails the same way on main. ruff check and ruff format are clean.

  • AMICI on the benchmark collection (AMICI 1.2.0, nominal parameters). Each model was imported and simulated as v1, as v2 with libpetab 0.10.0, and as v2 with this branch; AMICI did all the evaluation. Problems with timepoint-specific overrides were flattened the same way for all three when AMICI required it (Fiedler).

    • v2 with 0.10.0 vs this branch:
      • 32 models give the same log-likelihood (largest relative difference 4.1e-9) and the same simulation for all 35,132 measurements (largest relative difference 1.7e-8).
      • Two fail identically with both: Lang_PLOSComputBiol2024 raises an SBMLException, and Armistead_CellDeathDis2024 segfaults during AMICI's v2 code generation.
      • Froehlich was not run with 0.10.0, because of the import time.
    • v1 vs v2: the log-likelihoods agree to within 6.7e-7 relative, except Raimundez_PCB2020 at 3.5e-5. These differences are identical with 0.10.0 and with this branch, so they come from petab1to2 and AMICI's v2 import, not from this change.
  • A small problem through AMICI, with both libpetab versions. It covers condition parameters, a species set per experiment, a species changed alongside to an expression, pre-equilibration, and a parameter changed by an event. Log-likelihood −12299.399748 vs −12299.399747; outputs agree within solver tolerance. The patched model needs 3 indicators instead of 23.

  • Froehlich_CellSystems2018 through pyPESTO and AMICI, with this branch:

🤖 Generated with Claude Code

https://claude.ai/code/session_01JgN92Vr4NPT21RjToXf6GS

FFroehlich and others added 2 commits November 7, 2026 14:47
…n table

A change that sets a constant model parameter to a number at the start of
an experiment, where nothing else assigns that parameter, is constant per
experiment, like a column of a PEtab v1 condition table. Encoding it in the
model added a branch per experiment to the parameter's initial assignment
and an indicator parameter per experiment. Froehlich_CellSystems2018 has
9169 experiments that each set 145 such parameters: 145 piecewise initial
assignments with about 9169 branches each, which AMICI takes hours to
import.

These changes now stay as conditions of the experiment's kept periods
(both of them with pre-equilibration, since the value persists), and an
experiment gets an indicator only if it has a change encoded in the model.
AMICI already sets every remaining condition target as a fixed parameter
per experiment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgN92Vr4NPT21RjToXf6GS
… too

A species set to a number at the start of an experiment, and nowhere else,
is a per-experiment constant as well: Froehlich_CellSystems2018 sets the
initial amounts of 23 species per cell line, which stayed piecewise initial
assignments with ~9169 branches each. Such a species now gets a parameter
`_petab_initial_value_<id>` holding its initial value and the initial
assignment `<id> = _petab_initial_value_<id>`, and its changes are kept as
changes of that parameter. Only species whose initial value is a number
(after substituting compartment sizes that nothing changes) qualify, and
only species that conditions actually set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgN92Vr4NPT21RjToXf6GS
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.52239% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.62%. Comparing base (8c0aa68) to head (08a1390).

Files with missing lines Patch % Lines
petab/v2/converters.py 95.52% 1 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #579      +/-   ##
==========================================
+ Coverage   79.48%   79.62%   +0.14%     
==========================================
  Files          70       70              
  Lines        8278     8340      +62     
  Branches     1498     1515      +17     
==========================================
+ Hits         6580     6641      +61     
  Misses       1207     1207              
- Partials      491      492       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants