Skip to content

Commit 4ae2024

Browse files
FFroehlichclaude
andcommitted
petab1to2: fix conversion of logNormal, logLaplace and parameterScaleUniform priors
* v1 `logNormal` / `logLaplace` were passed through verbatim, but v2 only knows `log-normal` / `log-laplace`. Both are based on the natural logarithm, so the parameters are kept. * `parameterScaleUniform` on `log` scale became `log-uniform` with the ln-space parameters, but v2 `log-uniform` takes the bounds of the parameter itself, so the prior density was NaN. Use exp(a); exp(b). * `parameterScaleUniform` on `log10` scale raised NotImplementedError. Convert to `log-uniform` with 10^a; 10^b. Missing parameterScaleUniform parameters still default to the parameter bounds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent d3cb3a1 commit 4ae2024

2 files changed

Lines changed: 45 additions & 12 deletions

File tree

‎petab/v2/petab1to2.py‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
from .. import v1, v2
1919
from ..v1.math import sympify_petab
20+
from ..v1.parameters import unscale
2021
from ..v1.yaml import get_path_prefix, load_yaml, validate
2122
from ..versions import get_major_version
2223
from .models import MODEL_TYPE_SBML
@@ -496,7 +497,25 @@ def update_prior(row) -> tuple[str, str | None]:
496497
pscale = v1.C.LIN
497498

498499
if prior_type not in v1.C.PARAMETER_SCALE_PRIOR_TYPES:
499-
return prior_type, prior_pars
500+
# v1 logNormal / logLaplace are based on the natural logarithm,
501+
# just like v2 log-normal / log-laplace
502+
return {
503+
v1.C.LOG_NORMAL: v2.C.LOG_NORMAL,
504+
v1.C.LOG_LAPLACE: v2.C.LOG_LAPLACE,
505+
}.get(prior_type, prior_type), prior_pars
506+
507+
if prior_type == v1.C.PARAMETER_SCALE_UNIFORM and pscale != v1.C.LIN:
508+
# A uniform distribution of ln(x) (log10(x)) on [a, b] is a
509+
# log-uniform distribution of x on [e^a, e^b] ([10^a, 10^b]).
510+
# v2 log-uniform takes the bounds of x as parameters.
511+
# Missing parameters default to the parameter bounds (see
512+
# `update_prior_pars` below), as in v1.
513+
if not pd.isna(prior_pars):
514+
prior_pars = v2.C.PARAMETER_SEPARATOR.join(
515+
str(float(unscale(float(p), pscale)))
516+
for p in str(prior_pars).split(v1.C.PARAMETER_SEPARATOR)
517+
)
518+
return v2.C.LOG_UNIFORM, prior_pars
500519

501520
if pscale == v1.C.LOG10 and prior_type in (
502521
v1.C.PARAMETER_SCALE_NORMAL,

‎tests/v2/test_conversion.py‎

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -195,24 +195,38 @@ def simulate(measurement_df):
195195
"ignore:.*Parameter scales are not supported in PEtab v2.*:UserWarning"
196196
)
197197
@pytest.mark.parametrize(
198-
"parameter_scale, prior_type",
198+
"parameter_scale, prior_type, prior_parameters",
199199
[
200-
(v1.C.LOG10, v1.C.PARAMETER_SCALE_NORMAL),
201-
(v1.C.LOG10, v1.C.PARAMETER_SCALE_LAPLACE),
202-
(v1.C.LOG, v1.C.PARAMETER_SCALE_NORMAL),
203-
(v1.C.LOG, v1.C.PARAMETER_SCALE_LAPLACE),
204-
(v1.C.LIN, v1.C.PARAMETER_SCALE_NORMAL),
200+
(v1.C.LOG10, v1.C.PARAMETER_SCALE_NORMAL, "-0.5;0.7"),
201+
(v1.C.LOG10, v1.C.PARAMETER_SCALE_LAPLACE, "-0.5;0.7"),
202+
(v1.C.LOG, v1.C.PARAMETER_SCALE_NORMAL, "-0.5;0.7"),
203+
(v1.C.LOG, v1.C.PARAMETER_SCALE_LAPLACE, "-0.5;0.7"),
204+
(v1.C.LIN, v1.C.PARAMETER_SCALE_NORMAL, "-0.5;0.7"),
205+
# parameterScaleUniform within the bounds, exceeding the bounds,
206+
# and defaulting to the bounds
207+
(v1.C.LOG10, v1.C.PARAMETER_SCALE_UNIFORM, "-0.5;0.7"),
208+
(v1.C.LOG10, v1.C.PARAMETER_SCALE_UNIFORM, "-5;0.7"),
209+
(v1.C.LOG10, v1.C.PARAMETER_SCALE_UNIFORM, np.nan),
210+
(v1.C.LOG, v1.C.PARAMETER_SCALE_UNIFORM, "-0.5;0.7"),
211+
(v1.C.LOG, v1.C.PARAMETER_SCALE_UNIFORM, "-10;0.7"),
212+
(v1.C.LOG, v1.C.PARAMETER_SCALE_UNIFORM, np.nan),
213+
(v1.C.LIN, v1.C.PARAMETER_SCALE_UNIFORM, "0.1;0.7"),
214+
# logNormal / logLaplace do not depend on the parameter scale
215+
(v1.C.LOG10, v1.C.LOG_NORMAL, "-0.5;0.7"),
216+
(v1.C.LOG10, v1.C.LOG_LAPLACE, "-0.5;0.7"),
217+
(v1.C.LIN, v1.C.LOG_NORMAL, "-0.5;0.7"),
218+
(v1.C.LIN, v1.C.LOG_LAPLACE, "-0.5;0.7"),
205219
],
206220
)
207-
def test_petab1to2_parameter_scale_priors(
208-
tmp_path, parameter_scale, prior_type
221+
def test_petab1to2_priors(
222+
tmp_path, parameter_scale, prior_type, prior_parameters
209223
):
210-
"""Test that parameterScale{Normal,Laplace} priors are converted to
211-
priors with the same density."""
224+
"""Test that objective priors are converted to priors with the same
225+
density."""
212226
k1 = _K1 | {
213227
v1.C.PARAMETER_SCALE: parameter_scale,
214228
v1.C.OBJECTIVE_PRIOR_TYPE: prior_type,
215-
v1.C.OBJECTIVE_PRIOR_PARAMETERS: "-0.5;0.7",
229+
v1.C.OBJECTIVE_PRIOR_PARAMETERS: prior_parameters,
216230
}
217231
yaml_file = _write_v1_problem(
218232
tmp_path,

0 commit comments

Comments
 (0)