Skip to content

Add metabolomics template and MZmine converter (loadpage) - #219

Merged
tonywu1999 merged 4 commits into
develfrom
MSstatsShiny/work/20260710_metabolomics_loadpage
Jul 16, 2026
Merged

Add metabolomics template and MZmine converter (loadpage)#219
tonywu1999 merged 4 commits into
develfrom
MSstatsShiny/work/20260710_metabolomics_loadpage

Conversation

@swaraj-neu

@swaraj-neu swaraj-neu commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Motivation and Context

This PR adds a metabolomics-specific loadpage workflow to support data converted from MZmine. It introduces a metabolomics analysis 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)

    • Extended TEMPLATES and TEMPLATE_LABELS with:
      • metabolomics
      • (and updated protein_turnover labels)
    • Added loadpage UI constants to NAMESPACE_LOADPAGE:
      • tmt_options_ui
      • mzmine_upload_panel
      • main_selection_divider
    • Added exported filetype choice constants:
      • LOADPAGE_FILETYPE_CHOICES
      • LOADPAGE_METABOLOMICS_FILETYPE_CHOICES
  • Metabolomics/MZmine-specific loadpage UI and visibility

    • Added loadpage_show_mzmine_upload(filetype) to control visibility of the MZmine upload panel (enabled only for filetype == "mzmine").
    • Updated loadpage_show_label_free_options(...) to suppress label-free options under the metabolomics template.
    • Extended register_loadpage_visibility_observers(input, output, session, app_template = NULL) with template-aware behavior:
      • When app_template is metabolomics:
        • hides BIO and DDA_DIA radios
        • hides main_selection_divider
        • resets BIO/DDA_DIA to defaults ("Protein" / "LType")
        • updates output$upload_description to metabolomics-specific content
        • restricts filetype radio choices to MZmine-only
      • Observes filetype to show/hide mzmine_upload_panel.
    • Tightened the label-free options panel observer to pass app_template.
    • Removed BIO-driven show/hide observers for post-proceed1 summary panels, shifting that behavior to summary rendering.
  • Loadpage proceed validation (MZmine gating)

    • Updated register_loadpage_proceed_validation() so proceed1 is enabled for filetype == "mzmine" only when these are all non-NULL:
      • input$mzmine_input
      • input$mzmine_annotation
      • input$mzmine_annotations
    • This MZmine branch is prioritized ahead of existing BIO/DDA_DIA gating.
  • Metabolomics preview and summary rendering

    • Added metabolomics_summary2_view(summary2) to drop metabolomics-redundant rows and relabel remaining ones to metabolomics terminology.
    • Updated register_loadpage_summary():
      • output$summary uses head(metabolomics_preview_view(d)) for metabolomics template
      • output$summary2 uses metabolomics_summary2_view() for metabolomics template
      • refactored “Top 6 rows” preview rendering to conditionally include panels directly in renderUI (instead of wrapping in always-present hidden containers).
  • MZmine conversion logic

    • Updated getData() with an early input$filetype == "mzmine" branch:
      • reads MZmine feature quant table + annotation(s) + compound annotations (+ optional SIRIUS)
      • converts via MSstatsConvert::MZMinetoMSstatsFormat()
      • returns immediately (skipping BIO/DDA_DIA routing and BIO=="Peptide" post-processing).
    • Updated getDataCode() to generate a matching filetype == 'mzmine' code path (including optional SIRIUS).
  • Module wiring and UI refactor

    • Updated loadpageServer() to forward app_template into register_loadpage_visibility_observers(..., app_template = app_template).
    • Updated loadpageUI():
      • switched to uiOutput(ns("upload_description")) for upload guidance
      • added an explicitly id’d, namespaced hr for main_selection_divider
      • changed “File Type” header rendering to uiOutput(ns("filetype_header")) backed by LOADPAGE_FILETYPE_CHOICES
      • inserted a hidden metabolomics MZmine upload panel before other annotation uploads
      • added create_metabolomics_header_content() and create_mzmine_uploads(ns) (namespaced inputs for MZmine quant table, annotations, compound annotations, optional SIRIUS).
  • DESCRIPTION

    • Added Remotes: r-lib/log4r.

Unit Tests

  • tests/testthat/test-loadpage-server-rendering.R

    • Added truth-table test for loadpage_show_mzmine_upload() (only converter/filetype == "mzmine" yields TRUE).
    • Added exact-expected-value test for LOADPAGE_METABOLOMICS_FILETYPE_CHOICES.
    • Updated label-free options visibility expectations for metabolomics template suppression.
  • tests/testthat/test-module-loadpage-ui.R

    • Added checks that metabolomics is registered in TEMPLATES with expected TEMPLATE_LABELS, and is present in home picker mapping.
    • Updated UI test expectations to use server-rendered upload_description (uiOutput) placeholder.
    • Added tests for create_metabolomics_header_content().
    • Added dedicated tests for create_mzmine_uploads(ns) (hidden panel rendering, expected namespaced file-input IDs, and key tooltip/label markup).
  • tests/testthat/test-utils.R

    • Added tests for metabolomics_preview_view():
      • renames ProteinNameMetabolite, PeptideSequenceFeature
      • drops charge/label-related columns
      • returns a data.frame and does not mutate the input data.table.
    • Added tests for metabolomics_summary2_view():
      • verifies relabeling and removal of redundant rows/records.

Coding Guidelines Violated

  • R/utils.R contains a # TODO: This code stops processing if a file is not uploaded correctly. comment (TODO marker present at/around line 579).

@swaraj-neu swaraj-neu self-assigned this Jul 11, 2026
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The loadpage now supports metabolomics templates through MZmine file uploads, template-specific controls, validation, MSstats conversion, generated conversion code, and metabolomics summary previews.

Changes

Metabolomics MZmine workflow

Layer / File(s) Summary
Template and MZmine upload UI
DESCRIPTION, R/constants.R, R/module-loadpage-ui.R, tests/testthat/test-module-loadpage-ui.R
Adds metabolomics template constants, filetype choices, server-rendered headers, and namespaced MZmine upload inputs.
MZmine visibility and proceed gating
R/loadpage-server-converter-options-panel.R, R/loadpage-server-proceed-validation.R, R/module-loadpage-server.R, tests/testthat/test-loadpage-server-rendering.R
Adds template-aware visibility observers and enables proceeding when required MZmine inputs are provided.
MZmine conversion and metabolomics preview
R/utils.R, R/loadpage-server-summary.R, tests/testthat/test-utils.R
Converts MZmine inputs to MSstats format, generates equivalent code, and renders renamed metabolomics previews and summaries.

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
Loading

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: tonywu1999

Poem

A rabbit hops where MZmine files flow,
Through tidy tables row by row.
New labels bloom, panels appear,
Metabolite previews sparkle clear.
“Proceed!” I thump—the path is bright!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding a metabolomics template and MZmine converter support in the loadpage.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch MSstatsShiny/work/20260710_metabolomics_loadpage

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
tests/testthat/test-utils.R (1)

31-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the preview output type.

The mutation guard checks input_dt, but never verifies that view remains a data.table; an accidental conversion to data.frame would 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 win

Add 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 win

Pure header builder, correctly documented as unit-testable.

No test was added for loadpage_filetype_header despite 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 new loadpage_show_mzmine_upload test.

🤖 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 value

New metabolomics block uses raw literal ids instead of NAMESPACE_LOADPAGE constants.

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 existing NAMESPACE_LOADPAGE entry visible in this batch — please confirm it matches the actual div/hr id added in module-loadpage-ui.R (not included in this review batch), since a mismatched id would make shinyjs::toggle silently 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

📥 Commits

Reviewing files that changed from the base of the PR and between f8f426b and dbf9876.

📒 Files selected for processing (10)
  • R/constants.R
  • R/loadpage-server-converter-options-panel.R
  • R/loadpage-server-proceed-validation.R
  • R/loadpage-server-summary.R
  • R/module-loadpage-server.R
  • R/module-loadpage-ui.R
  • R/utils.R
  • tests/testthat/test-loadpage-server-rendering.R
  • tests/testthat/test-module-loadpage-ui.R
  • tests/testthat/test-utils.R

Comment thread R/utils.R
Comment thread R/module-loadpage-ui.R
Comment thread R/loadpage-server-converter-options-panel.R
Comment thread R/module-loadpage-ui.R Outdated
Comment thread tests/testthat/test-module-loadpage-ui.R
Comment thread R/loadpage-server-summary.R
Comment thread R/loadpage-server-summary.R
Comment thread R/loadpage-server-summary.R
Comment thread R/loadpage-server-converter-options-panel.R Outdated
Comment thread R/loadpage-server-converter-options-panel.R Outdated
Comment thread R/loadpage-server-converter-options-panel.R
Comment thread R/loadpage-server-converter-options-panel.R Outdated
Comment thread R/loadpage-server-summary.R Outdated
Comment thread R/loadpage-server-converter-options-panel.R Outdated
@swaraj-neu
swaraj-neu force-pushed the MSstatsShiny/work/20260710_metabolomics_loadpage branch from 93fe3a7 to 2b0fb04 Compare July 16, 2026 05:04

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 93fe3a7 and 4646270.

📒 Files selected for processing (11)
  • DESCRIPTION
  • R/constants.R
  • R/loadpage-server-converter-options-panel.R
  • R/loadpage-server-proceed-validation.R
  • R/loadpage-server-summary.R
  • R/module-loadpage-server.R
  • R/module-loadpage-ui.R
  • R/utils.R
  • tests/testthat/test-loadpage-server-rendering.R
  • tests/testthat/test-module-loadpage-ui.R
  • tests/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

Comment on lines +138 to +142
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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 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.

Suggested change
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.

@tonywu1999
tonywu1999 force-pushed the MSstatsShiny/work/20260710_metabolomics_loadpage branch from 4646270 to e3f07c2 Compare July 16, 2026 13:53
@tonywu1999
tonywu1999 merged commit 9f08e0c into devel Jul 16, 2026
2 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants