Skip to content

PEtab v1->v2 converter emits log10 over log-normal under petab 0.9.0, so every converted log10 observable is refused at import #679

Description

@wshlavacek

PyBNF 1.8.1, petab 0.9.0 (released 2026-09-07), Python >= 3.12

Summary

The scale-preserving PEtab v1 -> v2 converter (pybnf.petab.convert.petab1to2_preserve_scale) produces a v2 problem the importer then refuses, for every v1 observable with observableTransformation = log10:

pybnf.printing.PybnfError: Observable 'obs_V': observableTransformation 'log10' contradicts the scale of
noiseDistribution 'log-normal'. Give the residual scale in one place -- a log observableTransformation over
a linear noiseDistribution (normal / laplace).

tests/test_petab_convert.py::TestFullConversion::test_converted_log10_problem_imports_as_lognormal fails on an unmodified main (212b11a) under petab 0.9.0. CI shows it on the py3.12 / 3.13 / 3.14 legs of every PR since 2026-09-07 (first seen on #678). The py3.11 leg stays green only because petab 0.9.0 requires Python >= 3.12, so that leg resolves 0.8.2.

Root cause

This is PyBNF's problem, not petab's.

petab 0.9.0 fixed a missing return in petab1to2's noise-distribution merge (PEtab-dev/libpetab-python#502). Before the fix the converted noiseDistribution column was always blank. After it the converter does what it was designed to do: fold the v1 observableTransformation into the v2 noiseDistribution. For log10 + normal that means log-normal, with a warning that log10-normal does not exist in PEtab v2 and the natural-log family is being substituted.

PyBNF's wrapper then re-injects observableTransformation = log10 as a preserved extra column (issue #499, ADR-0073), precisely to avoid that lossy substitution. The importer's _native_noise_family sees a log10 transformation over a natural-log distribution and refuses the contradiction. Under petab 0.8.2 that never fired because the blank cell defaulted to normal. The converter was silently relying on a petab bug.

The natural-log log case survives because both sides agree on ln. Linear observables are untouched.

Fix

When step 4 of petab1to2_preserve_scale re-injects a log / log10 transformation for an observable, it should also reset that row's noiseDistribution to the v1 base family (normal / laplace). That restores the importer's "give the scale in one place" contract regardless of which petab is installed, and the existing test is the regression pin.

Not a petab bug

Anyone running plain petab1to2 on a log10 problem now gets sigma reinterpreted on the ln scale (off by a factor of ln 10) with only a warning. That is a PEtab v2 specification gap, since v2 has no log10-normal, rather than a library bug, and it is exactly what the PyBNF wrapper exists to work around.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions