[codex] Add peak properties step for FWHM and prominence#79
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new peak-metrics recipe step to compute derived properties (currently prominence and FWHM) on detected peaks, and then enables downstream filtering/export of those computed properties within the peak workflow.
Changes:
- Introduces
step_measure_peaks_properties()to computeprominenceandfwhmcolumns on the.peakstibble. - Updates
step_measure_peaks_filter(min_prominence=...)to actually filter using the computedprominencecolumn (and error if it’s missing). - Updates tests and documentation/pkgdown/NAMESPACE to cover and expose the new step.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/testthat/test-peak-operations.R | Adds Gaussian-based tests for computed prominence/FWHM, plus coverage for prominence filtering and table export. |
| R/peak-operations.R | Implements step_measure_peaks_properties() and helpers; wires min_prominence filtering to the prominence column. |
| NAMESPACE | Exports the new step and registers S3 methods (prep/bake/print/tidy). |
| man/tidy.recipe.Rd | Adds tidy method alias entry for the new step. |
| man/step_measure_peaks_to_table.Rd | Adds new step to “Other peak-operations” cross-links. |
| man/step_measure_peaks_properties.Rd | New Rd page for step_measure_peaks_properties(). |
| man/step_measure_peaks_integrate.Rd | Adds cross-link to the new properties step. |
| man/step_measure_peaks_filter.Rd | Documents that min_prominence requires a prominence column (from the properties step). |
| man/step_measure_peaks_detect.Rd | Adds documentation pointer to compute additional peak metrics via the new step. |
| man/step_measure_peaks_deconvolve.Rd | Adds cross-link to the new properties step. |
| _pkgdown.yml | Adds the new step to the pkgdown reference index. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| peak_idx <- which.min(abs(region_x - peak_location)) | ||
| peak_height <- corrected_y[peak_idx] | ||
| if (!is.finite(peak_height) || peak_height <= 0) { | ||
| return(NA_real_) | ||
| } | ||
|
|
There was a problem hiding this comment.
In .calculate_peak_fwhm(), peak_idx/peak_height are taken from the detected peak_location. After subtracting the local linear baseline, the true maximum of corrected_y can shift (e.g., with a sloped background), which will bias the half-height target and can yield an incorrect FWHM. Consider locating the peak as which.max(corrected_y) (and using that index for the left/right crossing searches) so FWHM is computed around the baseline-corrected peak maximum rather than the original detected position.
| # Filter by prominence | ||
| if (!is.null(object$min_prominence)) { | ||
| if (!"prominence" %in% names(peaks)) { | ||
| cli::cli_abort( | ||
| c( | ||
| "Cannot filter by {.arg min_prominence} without a {.field prominence} column.", | ||
| "i" = "Use {.fn step_measure_peaks_properties} before prominence-based filtering." | ||
| ) | ||
| ) |
There was a problem hiding this comment.
Now that min_prominence is actually enforced, consider validating it (numeric, length 1, finite, and non-negative) when the step is created or prepped, similar to the validation done in step_measure_peaks_detect(). Without this, non-numeric values can surface later as less-informative comparison errors during bake().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@claude review this PR |
|
Claude finished @JamesHWade's task in 3m 15s —— View job PR Review: Add peak properties step for FWHM and prominence
Overall this is a clean, well-structured addition. The FWHM and prominence calculations are mathematically sound for the common case, and the recipe step pattern is implemented correctly. A few issues worth addressing before merge: Bug: test for
|
After subtracting the local linear baseline, the true maximum of corrected_y can shift on sloped backgrounds. Use which.max(corrected_y) instead of matching the original detected peak location so FWHM is computed around the baseline-corrected peak maximum. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6e9739ee78
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if ( | ||
| !all(is.finite(c(peak_location, left_base, right_base))) || | ||
| left_base >= right_base | ||
| ) { |
There was a problem hiding this comment.
Support descending axes in FWHM calculation
.calculate_peak_fwhm() treats left_base >= right_base as invalid, but for monotonic decreasing axes (common in spectroscopy, e.g. 4000→400 cm⁻¹) detected peaks naturally have left_base numerically greater than right_base. In that case this early return makes FWHM NA for otherwise valid peaks, so step_measure_peaks_properties("fwhm") cannot produce usable widths on descending-axis data. The region extraction should use the boundary range (or index positions) rather than assuming ascending axis values.
Useful? React with 👍 / 👎.
…ilter Address PR review feedback: - .calculate_peak_fwhm() now normalizes base boundaries with min/max so descending x-axes (e.g. IR wavenumber 4000→400 cm⁻¹) produce valid FWHM values instead of NA - step_measure_peaks_filter() validates min_prominence input at construction time, consistent with step_measure_peaks_detect() Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
What changed
Adds a new
step_measure_peaks_properties()recipe step that computes derived peak metrics from detected peaks, currentlyfwhmandprominence, and stores them on the.peakstibble.This change also:
step_measure_peaks_filter(min_prominence = ...)to use the computedprominencecolumn instead of ignoring that argumentstep_measure_peaks_to_table()to export computed properties likepeak_1_fwhmandpeak_1_prominenceWhy it changed
Issue #78 asked for full width at half maximum calculations, and noted that peak prominence would also be useful. The package already had peak detection and integration, but no supported step for deriving and exporting those peak metrics.
User impact
Users can now add a peak-properties step into an existing peak workflow, for example after
step_measure_peaks_detect(), and then filter or export FWHM/prominence values in downstream analysis.Root cause
Peak workflows exposed peak boundaries and areas, but there was no public API to calculate secondary peak descriptors from the observed signal. In addition,
min_prominenceexisted on the filter step without corresponding property computation.Validation
air format .jarl check . --fix --allow-dirtyR -q -e 'devtools::test(filter = "peak-operations")'R -q -e 'devtools::check()'R -q -e 'pkgdown::build_site()'Closes #78