Skip to content

Commit d8b0bbf

Browse files
Fabian Fröhlichclaude
andauthored
assignments_to_experiments: model change only makes a ramp's target differential
The slope parameter is a placeholder at 0; every ramp's start value and slope, including at time 0, are set through the condition table. Constant model parameters in changes at an experiment's start take their model values, since those changes may only refer to parameter table symbols. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MNJePorYs9zmPYMam6g4EP
1 parent 08da490 commit d8b0bbf

2 files changed

Lines changed: 26 additions & 10 deletions

File tree

‎petab/v2/converters.py‎

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -779,8 +779,9 @@ def assignments_to_experiments(problem: Problem) -> Problem:
779779
target = sbml_model.getParameter(target_id)
780780
# A value that changes with time within a period (a ramp) cannot be a
781781
# condition change on a constant target, which is applied once at
782-
# the start of its period. The target becomes a differential entity
783-
# instead, `d target/dt = <target>_slope`, and each period sets both.
782+
# the start of its period. The model only makes the target a
783+
# differential entity, `d target/dt = <target>_slope`; the slope's
784+
# value, like the target's, is set by every period that starts one.
784785
ramps = expr.xreplace({c: sp.Dummy() for c in switches}).has(time)
785786
slope_id = None
786787
if ramps:
@@ -790,7 +791,7 @@ def assignments_to_experiments(problem: Problem) -> Problem:
790791
slope = sbml_model.createParameter()
791792
slope.setId(slope_id)
792793
slope.setConstant(False)
793-
slope.setValue(float(sp.diff(default, time).subs(model_values)))
794+
slope.setValue(0.0)
794795
rate_rule = sbml_model.createRateRule()
795796
rate_rule.setVariable(target_id)
796797
rate_rule.setMath(libsbml.parseL3Formula(slope_id))
@@ -852,9 +853,11 @@ def assignments_to_experiments(problem: Problem) -> Problem:
852853
previous = value
853854
# The model already has the pre-switch value at the start of
854855
# the first period, and the switches can become the first
855-
# periods if they only refer to parameter table symbols.
856+
# periods if they only refer to parameter table symbols. A
857+
# ramp's start and slope are always set by the tables.
856858
redundant = (
857-
i == 0
859+
not ramps
860+
and i == 0
858861
and (start_value - default).is_zero
859862
and all(
860863
{str(s) for s in value.free_symbols} <= parameter_ids
@@ -870,6 +873,17 @@ def assignments_to_experiments(problem: Problem) -> Problem:
870873
# preequilibration held the slope at zero
871874
or (ramps and after_preequilibration)
872875
):
876+
if i == 0:
877+
# at the start of an experiment, a change may only
878+
# refer to parameter table symbols; other symbols
879+
# are constant model parameters, at their values
880+
start_value = start_value.subs(
881+
{
882+
s: sbml_model.getParameter(str(s)).getValue()
883+
for s in start_value.free_symbols - {time}
884+
if str(s) not in parameter_ids
885+
}
886+
)
873887
additions += _changes(
874888
experiment,
875889
period.time,

‎tests/v2/test_conversion.py‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,13 +1082,15 @@ def test_assignments_to_experiments_ramp():
10821082
converted = assignments_to_experiments(problem)
10831083

10841084
sbml = converted.model.sbml_model
1085-
# the ramp's start and slope are the model's own initial values
1085+
# the model only makes the target differential; the slope is a
1086+
# placeholder until the tables set it
10861087
assert _rate_rule(converted, "k1") == "k1_slope"
1087-
assert sbml.getParameter("k1").getValue() == 1.0
1088-
assert sbml.getParameter("k1_slope").getValue() == 0.5
1089-
# at the switch, the target and its slope drop to zero
1088+
assert sbml.getParameter("k1_slope").getValue() == 0.0
1089+
# the ramp starts at time 0, and at the switch, the target and its slope
1090+
# drop to zero
10901091
assert _changes_by_period(converted) == {
1091-
(DEFAULT_EXPERIMENT_ID, 10.0): {"k1": 0.0, "k1_slope": 0.0}
1092+
(DEFAULT_EXPERIMENT_ID, 0.0): {"k1": 1.0, "k1_slope": 0.5},
1093+
(DEFAULT_EXPERIMENT_ID, 10.0): {"k1": 0.0, "k1_slope": 0.0},
10921094
}
10931095

10941096

0 commit comments

Comments
 (0)