Maintainer triage (June 29, 2026)
- Status: Verified bug against the current
master source in this fork.
- Severity: High.
- Area labels: area:param-estimation, area:calibration.
- Tackle batch: P3 - documented-mode crashes and tooling breakages.
The source review confirmed that the cited code path and failure mode are still present. The original audit details are preserved below for reproduction notes and suggested fixes.
Original audit details
Severity: High · Category: API misuse (crash) + logic · Part of #67
Two defects in the model-fitting tooling. Grouped as the "fit/predict produces no usable result" cluster (parameter estimation + calibration); the two fixes are small and live in adjacent fitting modules.
1. (High) ParameterEstimation IPOPT branch crashes: get_objective called with non-existent update_self keyword
Location: PharmaPy/ParamEstim.py:641-642
After IPOPT converges, resid_multidim = self.get_objective(opt_par, out_array=True, update_self=False). The base signature is get_objective(self, params, out_array=False, set_self=True) (460) — there is no update_self parameter (only the MultipleCurveResolution subclass override at 1297 has it). For a plain ParameterEstimation, this raises TypeError immediately after the solve.
- Trigger:
paramest.optimize_fn(method='IPOPT') (with cyipopt installed) — the documented alternative solver.
- Wrong result:
TypeError: get_objective() got an unexpected keyword argument 'update_self'; the converged parameters, covariance, and confidence intervals are lost even though optimization succeeded.
- Fix: use the base keyword —
self.get_objective(opt_par, out_array=True, set_self=False).
2. (High) PCR_calibration.predict re-centers new inputs with their own mean/std instead of training statistics
Location: PharmaPy/Calibration.py:190-220
predict() centers via self.__center_data(inputs) in both branches (194-197) without passing mean/std, so __center_data recomputes mean/std from the new prediction inputs (49-57). The model was fit with the training stats (self.data_mean/self.data_std), so projection onto the stored PCs (self.svd_dict['V'], 207) and the regression np.dot(new_projections, coeff) + self.y_means (220) are inconsistent. standardize defaults True, so 1/std executes.
- Trigger: fit a
PCR_calibration, then predict(new_spectra) on new measurements — the model's primary use.
- Wrong result: for a single new sample,
std=0 over that row → divide-by-zero → NaN/inf predictions; for multi-row batches, scores and predicted y are systematically offset/scaled wrong. The in-fit self-prediction predict(self.data) happens to match, masking the bug.
- Fix: pass the training stats —
self.__center_data(inputs, self.data_mean, self.data_std) in the non-snv branch.
Related (not duplicates): No existing issue references Calibration.py/PCR_calibration or the ParamEstim IPOPT signature.
Maintainer triage (June 29, 2026)
mastersource in this fork.The source review confirmed that the cited code path and failure mode are still present. The original audit details are preserved below for reproduction notes and suggested fixes.
Original audit details
Severity: High · Category: API misuse (crash) + logic · Part of #67
Two defects in the model-fitting tooling. Grouped as the "fit/predict produces no usable result" cluster (parameter estimation + calibration); the two fixes are small and live in adjacent fitting modules.
1. (High)
ParameterEstimationIPOPT branch crashes:get_objectivecalled with non-existentupdate_selfkeywordLocation:
PharmaPy/ParamEstim.py:641-642After IPOPT converges,
resid_multidim = self.get_objective(opt_par, out_array=True, update_self=False). The base signature isget_objective(self, params, out_array=False, set_self=True)(460) — there is noupdate_selfparameter (only theMultipleCurveResolutionsubclass override at 1297 has it). For a plainParameterEstimation, this raisesTypeErrorimmediately after the solve.paramest.optimize_fn(method='IPOPT')(with cyipopt installed) — the documented alternative solver.TypeError: get_objective() got an unexpected keyword argument 'update_self'; the converged parameters, covariance, and confidence intervals are lost even though optimization succeeded.self.get_objective(opt_par, out_array=True, set_self=False).2. (High)
PCR_calibration.predictre-centers new inputs with their own mean/std instead of training statisticsLocation:
PharmaPy/Calibration.py:190-220predict()centers viaself.__center_data(inputs)in both branches (194-197) without passing mean/std, so__center_datarecomputes mean/std from the new prediction inputs (49-57). The model was fit with the training stats (self.data_mean/self.data_std), so projection onto the stored PCs (self.svd_dict['V'], 207) and the regressionnp.dot(new_projections, coeff) + self.y_means(220) are inconsistent.standardizedefaults True, so1/stdexecutes.PCR_calibration, thenpredict(new_spectra)on new measurements — the model's primary use.std=0over that row → divide-by-zero → NaN/inf predictions; for multi-row batches, scores and predicted y are systematically offset/scaled wrong. The in-fit self-predictionpredict(self.data)happens to match, masking the bug.self.__center_data(inputs, self.data_mean, self.data_std)in the non-snv branch.Related (not duplicates): No existing issue references
Calibration.py/PCR_calibrationor theParamEstimIPOPT signature.