Add ferx engine support and reduce phase 1 cleaning sensitivity - #4
Conversation
Add ferx as an alternative estimation engine for iterative CWRES-based observation removal, eliminating the NONMEM/PsN dependency when ferx is available. The new `engine` and `ferx_method` parameters in `remove_erroneous_obs()` control engine selection, with NONMEM remaining the default. Internal helpers in `R/utils_ferx.R` normalize ferx output to match the existing parameter/results format used by all downstream plotting and stability functions. Reduce phase 1 gross cleaning defaults to be less aggressive: - IQR multiplier: 3 -> 5 (assess_data_quality, apply_exclusion_criteria) - Concentration increase threshold: 1.5 -> 2.0 - Minimum bin/subject size for IQR computation: 4 -> 8 Also adds a ferx workflow vignette mirroring the NONMEM Part 2 vignette. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Incorporate atomic file writes (tmp + rename) and PsN exit code checking from main into the engine-branched iteration loop. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
pak needs the Remotes field to resolve ferx from GitHub since it is not yet on CRAN. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4 +/- ##
======================================
Coverage 0.00% 0.00%
======================================
Files 10 11 +1
Lines 2416 2584 +168
======================================
- Misses 2416 2584 +168 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Exercises the full ferx code path in remove_erroneous_obs() and utility functions: ferx_run_iteration, ferx_read_pars, param labels, downstream plotting, and stability checks. Tests skip when ferx is not installed (skip_if_not_installed). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| save_temp_dir = FALSE, | ||
| columns = list(ID = "ID", TIME = "TIME", DV = "DV"), | ||
| engine = c("nonmem", "ferx"), | ||
| ferx_method = "focei", |
There was a problem hiding this comment.
ferx_method is unnecessary argument IMO, can also be set in model file. If we do want to be able to set method and other options in function call, then use ... and pass through to ferx_fit( , ...)
| @@ -1,12 +1,13 @@ | |||
| #' Iteratively detect potentially erroneous pharmacokinetic observations | |||
| #' | |||
| #' Performs iterative NONMEM-based detection of potentially erroneous | |||
There was a problem hiding this comment.
this function is becoming very long. Would ask CC to split up in subfunctions, so it's more modular.
Code review — ferx engine (high effort, workflow-backed)Headline: findings 1, 2, 5, 6 share one root cause — the ferx float-equality matcher in 🔴 Critical1. 2. 3. 🟠 High4. 5. 6. 🟡 Medium7. 8. 🔵 Intentional (per PR title — flagged for visibility)9. 10. Verified findings from a multi-agent review (one finder per angle + independent verifier per candidate). 🤖 Generated with Claude Code |
…ularity - Replace float-equality matching with positional .row_idx removal (fixes rounding failures, multi-match bugs, non-numeric ID and custom column issues) - Move engine param to end of signature to avoid positional arg shift - Remove ferx_method param; use ... passthrough to ferx_fit() instead - Fix param label desync: treat unrecognized prefixes as thetas - Use quote=TRUE in ferx_write_data to prevent CSV corruption - Add MDV==0 filter for ferx sdtab when column exists - Extract .reo_run_nonmem_iter() and .reo_prepare_obs() helpers Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The remove-obs chunk used eval=has_ferx, causing the full 20-iteration ferx fitting to run in CI (2+ hours). Changed to eval=FALSE and made the fallback chunk (pre-computed results) always run. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
engine = c("nonmem", "ferx")andferx_methodparameters toremove_erroneous_obs(), enabling iterative CWRES-based observation removal using the ferx R package as an alternative to NONMEM/PsN. NONMEM remains the default. New internal helpers inR/utils_ferx.Rnormalize ferx fit output to the same format used by all downstream plotting, stability, and reporting functions.busulfan_pt2_ferx.Rmdmirroring the NONMEM Part 2 workflow.Test plan
ferx_read_pars(),ferx_parse_param_labels(),ferx_write_data(), engine validationremove_erroneous_obs(engine = "ferx")runs 3 iterations on busulfan_sim (5 subjects), produces correct par/rem/phi/rmse/param_labels/stability outputplot_removal_metrics()(pOFV, thetas, omegas, sigmas, nRMSE) andcheck_model_stability()work with ferx resultsassess_data_quality()with new defaults flags fewer observations than old defaults on busulfan_sim🤖 Generated with Claude Code