Add metabolomics template and MZmine converter (loadpage) - #219
Conversation
📝 WalkthroughWalkthroughThe loadpage now supports metabolomics templates through MZmine file uploads, template-specific controls, validation, MSstats conversion, generated conversion code, and metabolomics summary previews. ChangesMetabolomics MZmine workflow
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Template as app_template
participant Visibility as loadpage visibility observers
participant UI as MZmine upload panel
participant GetData as getData
participant Converter as MSstatsConvert
participant Summary as summary output
Template->>Visibility: select metabolomics
Visibility->>UI: show MZmine controls
UI->>GetData: submit MZmine files
GetData->>Converter: convert inputs to MSstats format
Converter-->>Summary: provide converted data
Summary->>Summary: render metabolomics preview
Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
tests/testthat/test-utils.R (1)
31-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert the preview output type.
The mutation guard checks
input_dt, but never verifies thatviewremains adata.table; an accidental conversion todata.framewould pass this test.Suggested fix
expect_s3_class(input_dt, "data.table") + expect_s3_class(view, "data.table") })🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/testthat/test-utils.R` around lines 31 - 37, Add an assertion in the existing preview-output test to verify that view retains the data.table S3 class, while keeping the current input_dt mutation checks unchanged.R/module-loadpage-ui.R (1)
272-282: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd focused coverage for the MZmine upload contract.
No test asserts the hidden panel or its four namespaced input IDs. A future ID rename would disconnect upload validation/conversion without being caught.
Suggested test
+test_that("create_mzmine_uploads exposes all required MZmine inputs", { + html <- as.character(create_mzmine_uploads(NS("test"))) + + expect_true(grepl('id="test-mzmine_upload_panel"', html, fixed = TRUE)) + for (id in c("mzmine_input", "mzmine_annotation", + "mzmine_annotations", "sirius_annotations")) { + expect_true(grepl(paste0("test-", id), html, fixed = TRUE)) + } +})🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@R/module-loadpage-ui.R` around lines 272 - 282, Add focused test coverage for create_mzmine_uploads that renders the hidden upload panel and verifies all four namespaced file-input IDs: mzmine_input, mzmine_annotation, mzmine_annotations, and sirius_annotations. Ensure the test also confirms the panel uses NAMESPACE_LOADPAGE$mzmine_upload_panel so future ID changes are detected.R/loadpage-server-converter-options-panel.R (2)
307-319: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winPure header builder, correctly documented as unit-testable.
No test was added for
loadpage_filetype_headerdespite the docstring calling out that it's "Pure, so the number/tooltip behavior is unit-testable directly." Consider adding a quick truth-table test alongside the newloadpage_show_mzmine_uploadtest.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@R/loadpage-server-converter-options-panel.R` around lines 307 - 319, Add a focused truth-table unit test for loadpage_filetype_header covering metabolomics and non-metabolomics templates, verifying the resulting header text prefix and tooltip/icon structure. Place it alongside the existing loadpage_show_mzmine_upload tests and keep the test limited to the documented pure header behavior.
338-385: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueNew metabolomics block uses raw literal ids instead of
NAMESPACE_LOADPAGEconstants.Every other observer in this file reads/writes ids via
NAMESPACE_LOADPAGE$...(e.g.NAMESPACE_LOADPAGE$bio,NAMESPACE_LOADPAGE$dda_dia,NAMESPACE_LOADPAGE$filetype), but the new metabolomics block hardcodes"BIO","DDA_DIA","main_selection_divider", and"filetype"directly (lines 348-349, 353, 355-356, 369-373). Functionally equivalent today (tests pin the literal values), but it breaks the established convention and will silently drift if any id constant is ever renamed.♻️ Suggested consistency fix
observe({ metab = !is.null(app_template) && app_template() == TEMPLATES$metabolomics - shinyjs::toggle("BIO", condition = !metab) - shinyjs::toggle("DDA_DIA", condition = !metab) + shinyjs::toggle(NAMESPACE_LOADPAGE$bio, condition = !metab) + shinyjs::toggle(NAMESPACE_LOADPAGE$dda_dia, condition = !metab) shinyjs::toggle("main_selection_divider", condition = !metab) if (metab) { - updateRadioButtons(session, "BIO", selected = "Protein") - updateRadioButtons(session, "DDA_DIA", selected = "LType") + updateRadioButtons(session, NAMESPACE_LOADPAGE$bio, selected = "Protein") + updateRadioButtons(session, NAMESPACE_LOADPAGE$dda_dia, selected = "LType") } }) ... if (!is.null(app_template)) { observeEvent(app_template(), { if (app_template() == TEMPLATES$metabolomics) { - updateRadioButtons(session, "filetype", + updateRadioButtons(session, NAMESPACE_LOADPAGE$filetype, choices = c("MZmine" = "mzmine"), selected = "mzmine") } else { - updateRadioButtons(session, "filetype", + updateRadioButtons(session, NAMESPACE_LOADPAGE$filetype, choices = LOADPAGE_FILETYPE_CHOICES, selected = character(0)) } }) }Separately:
"main_selection_divider"(line 353) is a new id not covered by any existingNAMESPACE_LOADPAGEentry visible in this batch — please confirm it matches the actualdiv/hrid added inmodule-loadpage-ui.R(not included in this review batch), since a mismatched id would makeshinyjs::togglesilently no-op and leave both dividers visible under the metabolomics template.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@R/loadpage-server-converter-options-panel.R` around lines 338 - 385, Update register_loadpage_visibility_observers to use the corresponding NAMESPACE_LOADPAGE constants instead of raw "BIO", "DDA_DIA", and "filetype" identifiers for toggles and radio-button updates. Add or reuse a NAMESPACE_LOADPAGE entry for the divider, ensuring its value exactly matches the UI element id used by module-loadpage-ui.R, then use that constant for the divider toggle.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@R/utils.R`:
- Around line 319-336: Wrap the MZmine processing block in getData(), including
the required fread calls and MZMinetoMSstatsFormat(), with tryCatch. On error,
remove the modal spinner, show the established conversion-error notification,
and return NULL; keep the existing successful conversion path returning mydata
unchanged.
---
Nitpick comments:
In `@R/loadpage-server-converter-options-panel.R`:
- Around line 307-319: Add a focused truth-table unit test for
loadpage_filetype_header covering metabolomics and non-metabolomics templates,
verifying the resulting header text prefix and tooltip/icon structure. Place it
alongside the existing loadpage_show_mzmine_upload tests and keep the test
limited to the documented pure header behavior.
- Around line 338-385: Update register_loadpage_visibility_observers to use the
corresponding NAMESPACE_LOADPAGE constants instead of raw "BIO", "DDA_DIA", and
"filetype" identifiers for toggles and radio-button updates. Add or reuse a
NAMESPACE_LOADPAGE entry for the divider, ensuring its value exactly matches the
UI element id used by module-loadpage-ui.R, then use that constant for the
divider toggle.
In `@R/module-loadpage-ui.R`:
- Around line 272-282: Add focused test coverage for create_mzmine_uploads that
renders the hidden upload panel and verifies all four namespaced file-input IDs:
mzmine_input, mzmine_annotation, mzmine_annotations, and sirius_annotations.
Ensure the test also confirms the panel uses
NAMESPACE_LOADPAGE$mzmine_upload_panel so future ID changes are detected.
In `@tests/testthat/test-utils.R`:
- Around line 31-37: Add an assertion in the existing preview-output test to
verify that view retains the data.table S3 class, while keeping the current
input_dt mutation checks unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5dbc2065-f8ff-46b3-8972-582de1ea679f
📒 Files selected for processing (10)
R/constants.RR/loadpage-server-converter-options-panel.RR/loadpage-server-proceed-validation.RR/loadpage-server-summary.RR/module-loadpage-server.RR/module-loadpage-ui.RR/utils.Rtests/testthat/test-loadpage-server-rendering.Rtests/testthat/test-module-loadpage-ui.Rtests/testthat/test-utils.R
93fe3a7 to
2b0fb04
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@R/loadpage-server-summary.R`:
- Around line 138-142: Add a req(d) guard immediately after get_data() in the
output$summary renderTable block, before calling metabolomics_preview_view(d) or
head(d). Preserve the existing template-specific preview selection once d is
available.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 479e546d-aa48-4a4b-a0ea-90dba351b2d2
📒 Files selected for processing (11)
DESCRIPTIONR/constants.RR/loadpage-server-converter-options-panel.RR/loadpage-server-proceed-validation.RR/loadpage-server-summary.RR/module-loadpage-server.RR/module-loadpage-ui.RR/utils.Rtests/testthat/test-loadpage-server-rendering.Rtests/testthat/test-module-loadpage-ui.Rtests/testthat/test-utils.R
🚧 Files skipped from review as they are similar to previous changes (7)
- R/loadpage-server-proceed-validation.R
- tests/testthat/test-loadpage-server-rendering.R
- R/module-loadpage-server.R
- R/constants.R
- tests/testthat/test-utils.R
- R/utils.R
- R/module-loadpage-ui.R
| output$summary = renderTable( | ||
| { | ||
| head(get_data()) | ||
| d = get_data() | ||
| if (!is.null(app_template) && app_template() == TEMPLATES$metabolomics) | ||
| head(metabolomics_preview_view(d)) else head(d) |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Require d before processing the summary preview.
If get_data() returns NULL (e.g., when validation fails and data isn't loaded yet), passing NULL to metabolomics_preview_view(d) might cause a runtime error if the function does not explicitly handle it. Adding a req(d) guard, similar to output$summary1 and output$summary2, ensures execution gracefully halts when data is absent.
🛡️ Proposed fix to add validation
output$summary = renderTable(
{
d = get_data()
+ req(d)
if (!is.null(app_template) && app_template() == TEMPLATES$metabolomics)
head(metabolomics_preview_view(d)) else head(d)
}, bordered = TRUE
)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| output$summary = renderTable( | |
| { | |
| head(get_data()) | |
| d = get_data() | |
| if (!is.null(app_template) && app_template() == TEMPLATES$metabolomics) | |
| head(metabolomics_preview_view(d)) else head(d) | |
| output$summary = renderTable( | |
| { | |
| d = get_data() | |
| req(d) | |
| if (!is.null(app_template) && app_template() == TEMPLATES$metabolomics) | |
| head(metabolomics_preview_view(d)) else head(d) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@R/loadpage-server-summary.R` around lines 138 - 142, Add a req(d) guard
immediately after get_data() in the output$summary renderTable block, before
calling metabolomics_preview_view(d) or head(d). Preserve the existing
template-specific preview selection once d is available.
4646270 to
e3f07c2
Compare
Motivation and Context
This PR adds a metabolomics-specific loadpage workflow to support data converted from MZmine. It introduces a
metabolomicsanalysis template that reconfigures the loadpage UI (showing only metabolomics-relevant inputs), restricts filetype options to MZmine, validates required MZmine uploads, converts uploaded MZmine tables into MSstats format, and renders metabolomics-specific previews/summaries with metabolite/feature terminology.Changes
New templates/constants (core wiring)
TEMPLATESandTEMPLATE_LABELSwith:metabolomicsprotein_turnoverlabels)NAMESPACE_LOADPAGE:tmt_options_uimzmine_upload_panelmain_selection_dividerLOADPAGE_FILETYPE_CHOICESLOADPAGE_METABOLOMICS_FILETYPE_CHOICESMetabolomics/MZmine-specific loadpage UI and visibility
loadpage_show_mzmine_upload(filetype)to control visibility of the MZmine upload panel (enabled only forfiletype == "mzmine").loadpage_show_label_free_options(...)to suppress label-free options under the metabolomics template.register_loadpage_visibility_observers(input, output, session, app_template = NULL)with template-aware behavior:app_templateis metabolomics:main_selection_divider"Protein"/"LType")output$upload_descriptionto metabolomics-specific contentfiletypeto show/hidemzmine_upload_panel.app_template.proceed1summary panels, shifting that behavior to summary rendering.Loadpage proceed validation (MZmine gating)
register_loadpage_proceed_validation()soproceed1is enabled forfiletype == "mzmine"only when these are all non-NULL:input$mzmine_inputinput$mzmine_annotationinput$mzmine_annotationsMetabolomics preview and summary rendering
metabolomics_summary2_view(summary2)to drop metabolomics-redundant rows and relabel remaining ones to metabolomics terminology.register_loadpage_summary():output$summaryuseshead(metabolomics_preview_view(d))for metabolomics templateoutput$summary2usesmetabolomics_summary2_view()for metabolomics templaterenderUI(instead of wrapping in always-present hidden containers).MZmine conversion logic
getData()with an earlyinput$filetype == "mzmine"branch:MSstatsConvert::MZMinetoMSstatsFormat()"Peptide"post-processing).getDataCode()to generate a matchingfiletype == 'mzmine'code path (including optional SIRIUS).Module wiring and UI refactor
loadpageServer()to forwardapp_templateintoregister_loadpage_visibility_observers(..., app_template = app_template).loadpageUI():uiOutput(ns("upload_description"))for upload guidanceid’d, namespacedhrformain_selection_divideruiOutput(ns("filetype_header"))backed byLOADPAGE_FILETYPE_CHOICEScreate_metabolomics_header_content()andcreate_mzmine_uploads(ns)(namespaced inputs for MZmine quant table, annotations, compound annotations, optional SIRIUS).DESCRIPTION
Remotes: r-lib/log4r.Unit Tests
tests/testthat/test-loadpage-server-rendering.Rloadpage_show_mzmine_upload()(onlyconverter/filetype == "mzmine"yieldsTRUE).LOADPAGE_METABOLOMICS_FILETYPE_CHOICES.tests/testthat/test-module-loadpage-ui.Rmetabolomicsis registered inTEMPLATESwith expectedTEMPLATE_LABELS, and is present in home picker mapping.upload_description(uiOutput) placeholder.create_metabolomics_header_content().create_mzmine_uploads(ns)(hidden panel rendering, expected namespaced file-input IDs, and key tooltip/label markup).tests/testthat/test-utils.Rmetabolomics_preview_view():ProteinName→Metabolite,PeptideSequence→Featuredata.frameand does not mutate the inputdata.table.metabolomics_summary2_view():Coding Guidelines Violated
R/utils.Rcontains a# TODO: This code stops processing if a file is not uploaded correctly.comment (TODO marker present at/around line 579).