Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion petab/v2/petab1to2.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from pandas.io.common import get_handle, is_url

from .. import v1, v2
from ..v1.parameters import scale, unscale
from ..v1.yaml import get_path_prefix, load_yaml
from ..v1.yaml import validate as validate_yaml
from ..versions import get_major_version
Expand Down Expand Up @@ -516,7 +517,36 @@ def update_prior(row) -> tuple[str, str | None]:
pscale = v1.C.LIN

if prior_type not in v1.C.PARAMETER_SCALE_PRIOR_TYPES:
return prior_type, prior_pars
# v1 logNormal / logLaplace are based on the natural logarithm,
# just like v2 log-normal / log-laplace
return {
v1.C.LOG_NORMAL: v2.C.LOG_NORMAL,
v1.C.LOG_LAPLACE: v2.C.LOG_LAPLACE,
}.get(prior_type, prior_type), prior_pars

if prior_type == v1.C.PARAMETER_SCALE_UNIFORM and pscale != v1.C.LIN:
# A uniform distribution of ln(x) (log10(x)) on [a, b] is a
# log-uniform distribution of x on [e^a, e^b] ([10^a, 10^b]).
# v2 log-uniform takes the bounds of x as parameters.
# Missing parameters default to the parameter bounds (see
# `update_prior_pars` below), as in v1.
if not pd.isna(prior_pars):
# Clip [a, b] to the bounds before unscaling, as v1 does
# (see `petab.v1.priors.Prior`). This avoids overflow for
# intervals that exceed the floating-point range when
# unscaled.
low, high = map(
float, str(prior_pars).split(v1.C.PARAMETER_SEPARATOR)
)
lb, ub = row[v1.C.LOWER_BOUND], row[v1.C.UPPER_BOUND]
low = lb if low <= scale(lb, pscale) else unscale(low, pscale)
high = (
ub if high >= scale(ub, pscale) else unscale(high, pscale)
)
prior_pars = (
f"{float(low)}{v2.C.PARAMETER_SEPARATOR}{float(high)}"
)
return v2.C.LOG_UNIFORM, prior_pars

if pscale == v1.C.LOG10 and prior_type in (
v1.C.PARAMETER_SCALE_NORMAL,
Expand Down
39 changes: 28 additions & 11 deletions tests/v2/test_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,24 +197,41 @@ def simulate(measurement_df):
"ignore:.*Parameter scales are not supported in PEtab v2.*:UserWarning"
)
@pytest.mark.parametrize(
"parameter_scale, prior_type",
"parameter_scale, prior_type, prior_parameters",
[
(v1.C.LOG10, v1.C.PARAMETER_SCALE_NORMAL),
(v1.C.LOG10, v1.C.PARAMETER_SCALE_LAPLACE),
(v1.C.LOG, v1.C.PARAMETER_SCALE_NORMAL),
(v1.C.LOG, v1.C.PARAMETER_SCALE_LAPLACE),
(v1.C.LIN, v1.C.PARAMETER_SCALE_NORMAL),
(v1.C.LOG10, v1.C.PARAMETER_SCALE_NORMAL, "-0.5;0.7"),
(v1.C.LOG10, v1.C.PARAMETER_SCALE_LAPLACE, "-0.5;0.7"),
(v1.C.LOG, v1.C.PARAMETER_SCALE_NORMAL, "-0.5;0.7"),
(v1.C.LOG, v1.C.PARAMETER_SCALE_LAPLACE, "-0.5;0.7"),
(v1.C.LIN, v1.C.PARAMETER_SCALE_NORMAL, "-0.5;0.7"),
# parameterScaleUniform within the bounds, exceeding the bounds
# (also beyond the floating-point range when unscaled),
# and defaulting to the bounds
(v1.C.LOG10, v1.C.PARAMETER_SCALE_UNIFORM, "-0.5;0.7"),
(v1.C.LOG10, v1.C.PARAMETER_SCALE_UNIFORM, "-5;0.7"),
(v1.C.LOG10, v1.C.PARAMETER_SCALE_UNIFORM, "-400;400"),
(v1.C.LOG10, v1.C.PARAMETER_SCALE_UNIFORM, np.nan),
(v1.C.LOG, v1.C.PARAMETER_SCALE_UNIFORM, "-0.5;0.7"),
(v1.C.LOG, v1.C.PARAMETER_SCALE_UNIFORM, "-10;0.7"),
(v1.C.LOG, v1.C.PARAMETER_SCALE_UNIFORM, "-1000;1000"),
(v1.C.LOG, v1.C.PARAMETER_SCALE_UNIFORM, np.nan),
(v1.C.LIN, v1.C.PARAMETER_SCALE_UNIFORM, "0.1;0.7"),
# logNormal / logLaplace do not depend on the parameter scale
(v1.C.LOG10, v1.C.LOG_NORMAL, "-0.5;0.7"),
(v1.C.LOG10, v1.C.LOG_LAPLACE, "-0.5;0.7"),
(v1.C.LIN, v1.C.LOG_NORMAL, "-0.5;0.7"),
(v1.C.LIN, v1.C.LOG_LAPLACE, "-0.5;0.7"),
],
)
def test_petab1to2_parameter_scale_priors(
tmp_path, parameter_scale, prior_type
def test_petab1to2_priors(
tmp_path, parameter_scale, prior_type, prior_parameters
):
"""Test that parameterScale{Normal,Laplace} priors are converted to
priors with the same density."""
"""Test that objective priors are converted to priors with the same
density."""
k1 = _K1 | {
v1.C.PARAMETER_SCALE: parameter_scale,
v1.C.OBJECTIVE_PRIOR_TYPE: prior_type,
v1.C.OBJECTIVE_PRIOR_PARAMETERS: "-0.5;0.7",
v1.C.OBJECTIVE_PRIOR_PARAMETERS: prior_parameters,
}
yaml_file = _write_v1_problem(
tmp_path,
Expand Down
Loading