Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

PEtab export ignores the postprocess key, so a job whose fit scores script-transformed simulations exports as a problem that scores the raw ones, without an error

Chiusa Adatta ai principianti
#899 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
76/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
python
Ambito
backend, data

Direzione di ricerca

Leggi i controlli di rifiuto di prediction-transform in pybnf/petab/export.py:188-190 e confrontali con il modo in cui viene caricato conf['postprocess'] in pybnf/config.py:4235. Riproduci il problema con la configurazione dimostrativa edition-2 e conferma che attualmente l'esportazione venga completata senza un avviso. Il lavoro è completato quando l'esportazione rifiuta i job che usano il postprocessing, in modo coerente con il limite documentato di PEtab v2 in docs/petab.rst.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug silent-incorrectness

PEtab export ignores the postprocess key, so a job whose fit scores script-transformed simulations exports as a problem that scores the raw ones, without an error

export_job refuses the PyBNF prediction transforms that PEtab cannot express: _reject_cumulative, _reject_time_error and _reject_normalization (pybnf/petab/export.py:188-190). It never reads conf['postprocess'], and nothing under pybnf/petab/ mentions the key.

The fitter does apply the script:

  • Configuration._load_postprocessing (pybnf/config.py:4235) maps each (model, suffix) to the script. Under edition 2 the experiment name serves as the suffix.
  • Result.postprocess_data (pybnf/algorithms/core.py:84-110) then replaces the simulation with postprocess(data) before it is scored.

A user script is an arbitrary transform of the prediction, and PEtab has no way to represent one. Normalization is refused for the same reason. The export instead writes the bare model column as the observableFormula. The problem it emits has a different objective and a different optimum from the fit, and nothing warns about it. That breaks the contract in docs/petab.rst: anything PEtab v2 cannot express raises NotImplementedError naming the boundary, and nothing is dropped quietly.

Failure scenario

Take the edition-2 demo job (examples/demo/demo_bng_v2.conf) and add postprocess = pp.py par1, where pp.py multiplies the simulated y column by 10.

  • At the model's values (v1, v2, v3) = (0.5, 1, 3), the fitter's chi_sq is 645387.75. The exported problem gives 0 there.
  • At (0.05, 0.1, 0.3), the fitter's exact optimum (1.07e-33), the exported problem gives 6453.88.
  • export_job completes with no exception and no warning. observables.tsv has func_y y ... normal with no transform, and no output file mentions the script.

Reproduction

In an empty directory, with PyBNF installed and BNGPATH set, copy examples/demo/parabola_v2.bngl and examples/demo/par1.exp from the repository and create these files.

pp.py:

def postprocess(data):
    data.data[:, data.cols['y']] *= 10
    return data

check.conf:

edition = 2
model: parabola_v2.bngl
job_type = check
objective = chi_sq
experiment: par1, data: par1.exp
postprocess = pp.py par1
output_dir = out_check

fit.conf (the demo job plus the postprocess line):

edition = 2
model: parabola_v2.bngl
job_type = de
objective = chi_sq
experiment: par1, data: par1.exp
uniform_var = v1 0 10
uniform_var = v2 0 10
uniform_var = v3 0 10
population_size = 20
max_iterations = 30
postprocess = pp.py par1
output_dir = out_fit
  1. pybnf -c check.conf prints Objective value is 645387.75. With the postprocess line deleted, it prints Objective value is 1.0650618739334988e-33. With the postprocess line kept and the model's values changed to v1 0.05, v2 0.1, v3 0.3 in parabola_v2.bngl, it prints Objective value is 1.0650618739334988e-33.
  2. Run this export:
    import warnings
    from pybnf.petab.export import export_job
    with warnings.catch_warnings(record=True) as w:
        warnings.simplefilter('always')
        export_job('fit.conf', 'petab_out')
    print(w)
    
    It prints []. The func_y row of petab_out/observables.tsv is func_y y noiseParameter1_func_y normal noiseParameter1_func_y.
  3. Score the exported tables by hand. For this model, y = v1 x^2 + v2 x + v3 with x = t - 10:
    import csv
    rows = list(csv.DictReader(open('petab_out/measurements.tsv'), delimiter='\t'))
    def chi_sq(v1, v2, v3, y_scale=1):
        tot = 0.0
        for r in rows:
            x = float(r['time']) - 10
            pred = x if r['observableId'] == 'obs_x' else y_scale * (v1*x*x + v2*x + v3)
            tot += (float(r['measurement']) - pred)**2 / (2 * float(r['noiseParameters'])**2)
        return tot
    print(chi_sq(0.5, 1, 3), chi_sq(0.5, 1, 3, y_scale=10), chi_sq(0.05, 0.1, 0.3))
    
    It prints 0.0 645387.75 6453.8775000000005. The middle value puts the script's ×10 back into the formula, and it equals the fitter's 645387.75 exactly. So the exported problem is the job without its postprocess script.
    • Its optimum is (0.5, 1, 3), where the fitter scores 645387.75.
    • The fitter's optimum is (0.05, 0.1, 0.3), where the exported problem scores 6453.88.

The correct behaviour is to refuse the export, the same way a normalization is refused. That is what docs/petab.rst promises for anything PEtab v2 cannot express.

Reachability

This affects any edition-2 job that uses the documented postprocess key (docs/config_keys.rst, docs/advanced.rst) and is exported through pybnf.petab.export_job. The example script in docs/advanced.rst mean-centres an observable. That is the same kind of whole-trajectory reduction as the built-in normalizations, which _reject_normalization refuses.

Nothing upstream stops the export:

  • parse.py:208 accepts postprocess as a multi-string key.
  • config.py:165 whitelists it.
  • The exporter's refusals match only cumulative, time_error and normalization/analytic_scale.

The earlier exporter audit behind #736 and #738 walked the structural tuple keys. postprocess is a plain list key, so the audit did not cover it.

A _reject_postprocess refusal beside _reject_normalization would close this.

Where

  • pybnf/petab/export.py:188-190: the prediction-transform refusals, with no postprocess counterpart
  • pybnf/config.py:4235: _load_postprocessing
  • pybnf/algorithms/core.py:84: Result.postprocess_data, called from pybnf/algorithms/core.py:394, pybnf/algorithms/base.py:934, pybnf/algorithms/base.py:2223 and pybnf/algorithms/model_check.py:84

Related: #851, #912, #842, #898, #900, #901, #896, #894.

Found in a whole-codebase audit for silently wrong results (2026-09-23); the reproduction above was re-run independently of the original finding.

Lingua principale
Python
Stelle
25
Fork
25
Merge medio
2h 38m
PR unite (30g)
98

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di lanl/PyBNF

Tutte le issue di lanl/PyBNF

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.