Skip to content

Commit e8a57b1

Browse files
authored
Merge branch 'develop' into ant
2 parents a4d554d + 980926f commit e8a57b1

File tree

1 file changed

+52
-21
lines changed

1 file changed

+52
-21
lines changed

tests/v1/test_priors.py

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,15 @@
88
from scipy.stats import norm
99

1010
import petab.v1
11-
from petab.v1 import get_simulation_conditions
11+
from petab.v1 import (
12+
ESTIMATE,
13+
MEASUREMENT,
14+
OBJECTIVE_PRIOR_TYPE,
15+
OBSERVABLE_ID,
16+
SIMULATION,
17+
get_simulation_conditions,
18+
get_simulation_df,
19+
)
1220
from petab.v1.priors import priors_to_measurements
1321

1422

@@ -17,20 +25,31 @@
1725
)
1826
def test_priors_to_measurements(problem_id):
1927
"""Test the conversion of priors to measurements."""
28+
# setup
2029
petab_problem_priors: petab.v1.Problem = (
2130
benchmark_models_petab.get_problem(problem_id)
2231
)
2332
petab_problem_priors.visualization_df = None
2433
assert petab.v1.lint_problem(petab_problem_priors) is False
25-
2634
if problem_id == "Isensee_JCB2018":
2735
# required to match the stored simulation results below
2836
petab.v1.flatten_timepoint_specific_output_overrides(
2937
petab_problem_priors
3038
)
3139
assert petab.v1.lint_problem(petab_problem_priors) is False
40+
3241
original_problem = deepcopy(petab_problem_priors)
42+
# All priors in this test case are defined on parameter scale, hence
43+
# the dummy measurements will take the scaled nominal values.
44+
x_scaled_dict = dict(
45+
zip(
46+
original_problem.x_free_ids,
47+
original_problem.x_nominal_free_scaled,
48+
strict=True,
49+
)
50+
)
3351

52+
# convert priors to measurements
3453
petab_problem_measurements = priors_to_measurements(petab_problem_priors)
3554

3655
# check that the original problem is not modified
@@ -45,6 +64,7 @@ def test_priors_to_measurements(problem_id):
4564
getattr(original_problem, attr)
4665
)
4766
).empty, diff
67+
4868
# check that measurements and observables were added
4969
assert petab.v1.lint_problem(petab_problem_measurements) is False
5070
assert (
@@ -59,6 +79,7 @@ def test_priors_to_measurements(problem_id):
5979
petab_problem_measurements.measurement_df.shape[0]
6080
> petab_problem_priors.measurement_df.shape[0]
6181
)
82+
6283
# ensure we didn't introduce any new conditions
6384
assert len(
6485
get_simulation_conditions(petab_problem_measurements.measurement_df)
@@ -67,26 +88,40 @@ def test_priors_to_measurements(problem_id):
6788
# verify that the objective function value is the same
6889

6990
# load/construct the simulation results
70-
simulation_df_priors = petab.v1.get_simulation_df(
91+
simulation_df_priors = get_simulation_df(
7192
Path(
7293
benchmark_models_petab.MODELS_DIR,
7394
problem_id,
7495
f"simulatedData_{problem_id}.tsv",
7596
)
7697
)
77-
simulation_df_measurements = pd.concat(
78-
[
79-
petab_problem_measurements.measurement_df.rename(
80-
columns={petab.v1.MEASUREMENT: petab.v1.SIMULATION}
81-
)[
82-
petab_problem_measurements.measurement_df[
83-
petab.v1.C.OBSERVABLE_ID
84-
].str.startswith("prior_")
85-
],
86-
simulation_df_priors,
98+
# for the prior observables, we need to "simulate" the model with the
99+
# nominal parameter values
100+
simulated_prior_observables = (
101+
petab_problem_measurements.measurement_df.rename(
102+
columns={MEASUREMENT: SIMULATION}
103+
)[
104+
petab_problem_measurements.measurement_df[
105+
OBSERVABLE_ID
106+
].str.startswith("prior_")
87107
]
88108
)
89109

110+
def apply_parameter_values(row):
111+
# apply the parameter values to the observable formula for the prior
112+
if row[OBSERVABLE_ID].startswith("prior_"):
113+
row[SIMULATION] = x_scaled_dict[
114+
row[OBSERVABLE_ID].removeprefix("prior_")
115+
]
116+
return row
117+
118+
simulated_prior_observables = simulated_prior_observables.apply(
119+
apply_parameter_values, axis=1
120+
)
121+
simulation_df_measurements = pd.concat(
122+
[simulation_df_priors, simulated_prior_observables]
123+
)
124+
90125
llh_priors = petab.v1.calculate_llh_for_table(
91126
petab_problem_priors.measurement_df,
92127
simulation_df_priors,
@@ -102,10 +137,8 @@ def test_priors_to_measurements(problem_id):
102137

103138
# get prior objective function contribution
104139
parameter_ids = petab_problem_priors.parameter_df.index.values[
105-
(petab_problem_priors.parameter_df[petab.v1.ESTIMATE] == 1)
106-
& petab_problem_priors.parameter_df[
107-
petab.v1.OBJECTIVE_PRIOR_TYPE
108-
].notna()
140+
(petab_problem_priors.parameter_df[ESTIMATE] == 1)
141+
& petab_problem_priors.parameter_df[OBJECTIVE_PRIOR_TYPE].notna()
109142
]
110143
priors = petab.v1.get_priors_from_df(
111144
petab_problem_priors.parameter_df,
@@ -117,9 +150,7 @@ def test_priors_to_measurements(problem_id):
117150
prior_type, prior_pars, par_scale, par_bounds = prior
118151
if prior_type == petab.v1.PARAMETER_SCALE_NORMAL:
119152
prior_contrib += norm.logpdf(
120-
petab_problem_priors.x_nominal_free_scaled[
121-
petab_problem_priors.x_free_ids.index(parameter_id)
122-
],
153+
x_scaled_dict[parameter_id],
123154
loc=prior_pars[0],
124155
scale=prior_pars[1],
125156
)
@@ -134,4 +165,4 @@ def test_priors_to_measurements(problem_id):
134165
llh_priors + prior_contrib, llh_measurements, rtol=1e-3, atol=1e-16
135166
), (llh_priors + prior_contrib, llh_measurements)
136167
# check that the tolerance is not too high
137-
assert np.abs(prior_contrib) > 1e-3 * np.abs(llh_priors)
168+
assert np.abs(prior_contrib) > 1e-8 * np.abs(llh_priors)

0 commit comments

Comments
 (0)