Skip to content

Commit 31db7ab

Browse files
committed
..
1 parent 365c548 commit 31db7ab

File tree

1 file changed

+35
-35
lines changed

1 file changed

+35
-35
lines changed

python/sdist/amici/petab/petab_importer.py

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,10 @@ def __init__(
706706
self._fixed_pid_to_idx: dict[str, int] = {
707707
id_: i for i, id_ in enumerate(self._fixed_parameter_ids)
708708
}
709+
# maps PEtab observable IDs to petab Observable instances
710+
self._petab_id_to_obs: dict[str, v2.Observable] = {
711+
obs.id: obs for obs in self._petab_problem.observables
712+
}
709713

710714
# create a new model instance from the model module from which
711715
# we can get the default parameters
@@ -926,8 +930,7 @@ def apply_parameters(
926930
927931
Update the parameter-dependent values of the given `ExpData` instance
928932
according to the provided problem parameters (i.e., values of the
929-
parameters in the PEtab
930-
:external+petab:ref:`parameter table <v2_parameter_table>`).
933+
parameters in the PEtab parameter table).
931934
932935
This assumes that:
933936
@@ -941,10 +944,11 @@ def apply_parameters(
941944
In case of errors, the state of `edata` is undefined.
942945
:param problem_parameters: Problem parameters to be applied.
943946
"""
947+
# FIXME: xref
948+
# :external+petab:label:`parameter table <v2_parameter_table>`).
944949
# TODO: support ndarray in addition to dict?
945950
# TODO: use the original or the current parameters
946951
# if only a subset is provided?
947-
# TODO: must handle output overrides here, or add them to the events
948952

949953
# get the original parameter values
950954
# (model parameters set during model creation)
@@ -984,24 +988,43 @@ def apply_parameters(
984988
fixed_par_vals[p_idx] = p_val
985989
edata.fixed_parameters_pre_equilibration = fixed_par_vals
986990

987-
# apply problem parameter values to identical model parameters
988-
# any other parameter mapping is handled by events
991+
# Apply problem parameter values to identical model parameters.
992+
# Any other parameter mapping, except for output parameter
993+
# placeholders, is handled by events.
989994
for k, v in problem_parameters.items():
990995
if (idx := pid_to_idx.get(k)) is not None:
991996
par_vals[idx] = v
992997

998+
# Handle measurement-specific mappings to placeholders
999+
# TODO: must handle output overrides here, or add them to the events
9931000
# TODO handle placeholders
9941001
# check that all periods use the same overrides (except for numeric sigmas)
9951002
# see do_import() for details
996-
# TODO extract function
9971003
measurements = self._petab_problem.get_measurements_for_experiment(
9981004
experiment
9991005
)
1000-
# encountered placeholders and their overrides
1006+
1007+
def apply_override(placeholder: str, override: sp.Basic):
1008+
"""Apply a single placeholder override."""
1009+
if (idx := pid_to_idx.get(placeholder)) is not None:
1010+
if override.is_Number:
1011+
par_vals[idx] = float(override)
1012+
elif override.is_Symbol:
1013+
par_vals[idx] = problem_parameters[str(override)]
1014+
else:
1015+
raise AssertionError(
1016+
f"Unexpected override type: {override} for {placeholder} in experiment {experiment_id}"
1017+
)
1018+
else:
1019+
raise NotImplementedError(
1020+
f"Cannot handle override `{placeholder}' => '{override}'"
1021+
)
1022+
1023+
# tracks encountered placeholders and their overrides
10011024
# (across all observables -- placeholders IDs are globally unique)
10021025
overrides = {}
10031026
for m in measurements:
1004-
obs: Observable = self._petab_problem[m.observable_id]
1027+
obs = self._petab_id_to_obs[m.observable_id]
10051028
if obs.observable_placeholders:
10061029
for placeholder, override in zip(
10071030
obs.observable_placeholders,
@@ -1016,21 +1039,7 @@ def apply_parameters(
10161039
"Timepoint-specific observable placeholder "
10171040
"overrides are not supported"
10181041
)
1019-
1020-
if (idx := pid_to_idx.get(placeholder)) is not None:
1021-
if override.is_Number:
1022-
par_vals[idx] = float(override)
1023-
elif override.is_Symbol:
1024-
par_vals[idx] = problem_parameters[str(override)]
1025-
else:
1026-
raise AssertionError(
1027-
f"Unexpected override type: {override} for {placeholder} in experiment {experiment_id}"
1028-
)
1029-
else:
1030-
raise NotImplementedError(
1031-
f"Cannot handle override `{placeholder}' => '{override}'"
1032-
)
1033-
1042+
apply_override(placeholder, override)
10341043
# TODO: set sigmas via parameters or .sigmay
10351044
if obs.noise_placeholders:
10361045
for placeholder, override in zip(
@@ -1045,22 +1054,13 @@ def apply_parameters(
10451054
"Timepoint-specific observable placeholder "
10461055
"overrides are not supported"
10471056
)
1048-
if (idx := pid_to_idx.get(placeholder)) is not None:
1049-
if override.is_Number:
1050-
par_vals[idx] = float(override)
1051-
else:
1052-
par_vals[idx] = problem_parameters[str(override)]
1053-
else:
1054-
raise NotImplementedError(
1055-
f"Cannot handle override `{placeholder}' => '{override}'"
1056-
)
1057-
# print("ExperimentManager.apply_parameters:")
1058-
# print(m)
1059-
# print(dict(zip(self._parameter_ids, map(float, par_vals))))
1057+
apply_override(placeholder, override)
1058+
10601059
# TODO: set all unused placeholders to NaN to make it easier to spot problems?
10611060
edata.parameters = par_vals
10621061

10631062
# TODO debug, remove
1063+
# print("ExperimentManager.apply_parameters:")
10641064
# print(
10651065
# f"Parameters: {dict(zip(self._parameter_ids, map(float, par_vals)))}"
10661066
# )

0 commit comments

Comments
 (0)