Skip to content

refactor(chemoproteomics): Create a template for chemoproteomics workflows#188

Merged
tonywu1999 merged 13 commits intodevelfrom
feat-chemo
Apr 22, 2026
Merged

refactor(chemoproteomics): Create a template for chemoproteomics workflows#188
tonywu1999 merged 13 commits intodevelfrom
feat-chemo

Conversation

@tonywu1999
Copy link
Copy Markdown
Contributor

@tonywu1999 tonywu1999 commented Apr 21, 2026

Motivation and Context

This PR introduces a new "Chemoproteomics" template to MSstatsShiny, extending the application beyond its original scope of protein differential abundance analysis. The changes implement a template system that allows users to select between two workflows: the existing "Protein Differential Abundance Analysis" (default) and a new "Chemoproteomics" workflow. The chemoproteomics workflow adds specialized support for dose-response analysis with condition metadata tracking, including dose values, units, and drug names. This involves refactoring how response curves are configured and fitted, replacing the previous build_response_curve_matrix function with a more flexible metadata-driven approach.

Detailed Changes

Core Infrastructure

  • Constants (R/constants.R): Added TEMPLATES list defining "default" and "chemoproteomics" template identifiers, and TEMPLATE_LABELS providing user-facing labels for each template.

User Interface

  • Home UI (R/module-home-ui.R): Added a "Select a Template" section with a dropdown selector (selectInput with inputId = "app_template").
  • QC UI (R/module-qc-ui.R): Removed numeric prefixes from section headings (e.g., "1. Peptide level normalization" → "Peptide level normalization").
  • Response Curve UI (R/statmodel-ui-options-modeling.R): Removed the log-x-axis checkbox (create_response_curve_log_xaxis_checkbox); the increasing-trend checkbox now accepts a parameterized value parameter.
  • Visualization UI (R/statmodel-ui-options-visualization.R): Updated plot type label from "Dose Response Curve" to "Response Curve".

Server Logic - Data Loading

  • Loadpage Server (R/module-loadpage-server.R):
    • Added app_template parameter.
    • Introduced condition_metadata reactive state to track per-condition information (dose value, drug name, dose unit).
    • Implemented editable DataTable workflow for condition metadata with cell-edit event handler.
    • On data load (onclick("proceed1", ...)), when the chemoproteomics template is selected and a Condition column exists, automatically derives and populates condition metadata with parsed dose values, drug names, and units; wraps initialization in error handling.
    • Extended module exports to include getConditionMetadata.
    • Added conditional rendering of condition metadata table for chemoproteomics template only.

Server Logic - Experiment Design

  • Expdes Server (R/module-expdes-server.R):
    • Replaced statmodel_input parameter with app_template = reactive(TEMPLATES$default).
    • Removed internal .is_response_curve_mode() helper; response-curve mode is now determined by app_template() == TEMPLATES$chemoproteomics.
    • Added unit scaling for chemoproteomics: multiply user concentrations by 1e9 and scale dose values accordingly.
    • Reduced sample size simulation parameter n_proteins from 1000 to 300.

Server Logic - Statistical Modeling

  • Statmodel Server (R/module-statmodel-server.R):

    • Updated signature to accept app_template, turnover_ratios, and condition_metadata reactive parameters.
    • When app_template() changes, forces comparison mode and visualization settings specific to chemoproteomics (response-curve mode, response-curve plot type, disabled increasing-trend checkbox).
    • Implemented metadata-driven response-curve matrix construction for chemoproteomics: builds contrast matrix from condition_metadata with automatic dose conversion and drug name derivation from control detection or metadata.
    • Added validation that dose values and units contain no placeholder "?" before fitting.
    • Added observer for condition metadata edits to update contrast matrix and re-enable fitting.
    • Suppressed interactive matrix editor UI for chemoproteomics template.
  • Statmodel Comparison Helpers (R/statmodel-server-comparisons.R):

    • Removed build_response_curve_matrix(condition_list) function entirely.
    • Added new helper functions: convert_dose_to_molar(), parse_dose_unit_from_conditions(), parse_drug_name_from_conditions(), and autofill_condition_value().
    • Updated prepare_dose_response_fit documentation to reference new metadata format (GROUP, dose_value, drug columns).
  • Statmodel Visualization (R/statmodel-server-visualization.R):

    • Updated render_group_comparison_plot_inputs() to accept app_template and condition_metadata parameters; for chemoproteomics, derives response-curve input matrix from condition metadata instead of contrast matrix.
    • Updated create_download_plot_handler() similarly to apply metadata-derived matrices for chemoproteomics response-curve plotting.

Server Logic - Code Generation and Utilities

  • Download Code (R/statmodel-server-download-code.R): Hard-coded transform_dose = TRUE for response-curve analysis instead of reading from user input.
  • Response Curve Fitting Options (R/statmodel-server-options-modeling.R): Updated get_response_curve_fitting_options() to accept optional template parameter; for response curves, now returns only the increasing-trend checkbox (no log-x-axis checkbox).
  • Utils (R/utils.R): Updated fitResponseCurves() to accept optional transform_dose parameter (default TRUE).

Main Server

  • Server (R/server.R):
    • Defined app_template reactive that reads input$app_template or defaults to TEMPLATES$default.
    • Threaded app_template into loadpageServer() and statmodelServer().
    • Extracted condition_metadata from loadpage module outputs and passed to statmodelServer().
    • Updated expdesServer() call signature to receive app_template instead of reactive(statmodel_input).

Testing

  • Tests (tests/testthat/test-utils-statmodel-server.R): Removed 42 lines of test cases for the deleted build_response_curve_matrix() function (3 test_that blocks covering generic, time-based, and temperature-based conditions).

Coding Guidelines

  • Reactive Parameters: The PR consistently uses reactive parameters with sensible defaults (reactive(TEMPLATES$default)), but introduces a pattern where some parameters are optional (condition_metadata = reactive(NULL)), which requires defensive checks throughout consuming code.
  • Documentation: New helper functions in statmodel-server-comparisons.R lack roxygen documentation tags (e.g., @param, @return, @noRd), which is inconsistent with the existing codebase documentation standard.
  • Error Handling: Condition metadata initialization wraps logic in tryCatch with user-facing notifications, but some downstream validation (placeholder check in dose values) uses stopExecution(), mixing error handling patterns.
  • UI/UX: Numeric prefixes removed from section headings may impact visual hierarchy and scanning, though this is primarily a cosmetic change.

tonywu1999 and others added 4 commits April 21, 2026 15:29
…e workflow

- Add TEMPLATES/TEMPLATE_LABELS constants for default + chemoproteomics
- Add template selector on home page
- Add condition metadata (DoseVal, DrugName, DoseUnit) editable DT table on loadpage for chemoproteomics
- Parse drug name, dose value, and unit from condition names with user-editable fallbacks
- Convert dose values from measured unit to molar (M) before analysis
- Block analysis when any '?' placeholder values remain in metadata
- Set transform_dose=TRUE for chemoproteomics dose-response fitting
- Remove log-scale checkbox; set transform_dose via template instead
- Add app_template threading through loadpage, qc, statmodel, expdes servers
- Refactor expdesServer to use app_template instead of statmodel_input
- Remove numbered prefixes from QC page section headers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

📝 Walkthrough

Walkthrough

The PR introduces a template-based system with constants TEMPLATES and TEMPLATE_LABELS, threading a reactive app_template throughout the application. It adds condition metadata management for the chemoproteomics template, refactors response-curve mode to be template-driven instead of comparison-mode-driven, replaces build_response_curve_matrix with new dose/drug parsing helpers, and updates UI headings by removing numeric prefixes.

Changes

Cohort / File(s) Summary
Constants & Template System
R/constants.R
Added TEMPLATES and TEMPLATE_LABELS list constants with default and chemoproteomics entries.
Home UI & Template Selection
R/module-home-ui.R
Inserted new "Select a Template" section with selectInput dropdown populated from TEMPLATES and TEMPLATE_LABELS constants.
Load Page Module
R/module-loadpage-server.R
Extended signature to accept app_template parameter; added reactive condition_metadata state with editable DT table UI and chemoproteomics initialization logic via onclick handler; exported getConditionMetadata.
Experimental Design Module
R/module-expdes-server.R
Replaced statmodel_input parameter with app_template reactive; removed .is_response_curve_mode helper; added chemoproteomics unit scaling (1e9 multipliers); reduced n_proteins TPR simulation parameter from 1000 to 300.
QC UI Refinements
R/module-qc-ui.R
Removed numeric prefixes (e.g., "1.", "2.", "3.", "4.") from section heading labels.
Statistical Model Server Core
R/module-statmodel-server.R
Extended signature with app_template, turnover_ratios, condition_metadata reactives; added template-aware UI state management (comparison/plot-type defaults per template); integrated condition metadata into response-curve matrix construction with dose unit conversion; added validation for placeholder dose values; updated analysis code generation.
Response-Curve Comparison Helpers
R/statmodel-server-comparisons.R
Removed build_response_curve_matrix implementation; added four new helper functions: convert_dose_to_molar, parse_dose_unit_from_conditions, parse_drug_name_from_conditions, autofill_condition_value.
Statistical Model Visualization
R/statmodel-server-visualization.R
Extended render_group_comparison_plot_inputs and create_download_plot_handler signatures with app_template and condition_metadata reactives; added chemoproteomics-specific matrix derivation logic using condition metadata in response-curve path.
Response-Curve Download Code
R/statmodel-server-download-code.R
Hard-coded transform_dose = TRUE in response-curve fitting/visualization calls instead of reading from input.
Response-Curve UI Options
R/statmodel-ui-options-modeling.R, R/statmodel-ui-options-visualization.R
Removed create_response_curve_log_xaxis_checkbox function; updated create_response_curve_increasing_trend_checkbox with parameterized value argument; changed plot-type label from "Dose Response Curve" to "Response Curve".
Main Server
R/server.R
Defined app_template reactive from input$app_template with fallback to default; threaded app_template into loadpageServer and statmodelServer; extracted and passed condition_metadata from loadpage into statmodel.
Utilities
R/utils.R
Extended fitResponseCurves signature with optional transform_dose = TRUE parameter; passed to underlying MSstatsResponse::doseResponseFit call.
Test Cleanup
tests/testthat/test-utils-statmodel-server.R
Removed three test cases for build_response_curve_matrix covering generic, time-based, and temperature-based conditions.

Sequence Diagram

sequenceDiagram
    actor User
    participant Home as Home UI
    participant Server as Main Server
    participant LoadPage as LoadPage Module
    participant StatModel as StatModel Module
    participant Helpers as Response Curve Helpers

    User->>Home: Select template (chemoproteomics)
    Home->>Server: input$app_template
    Server->>Server: app_template reactive updated
    Server->>LoadPage: pass app_template reactive
    LoadPage->>LoadPage: initialize condition_metadata (if chemoproteomics)
    LoadPage->>Helpers: parse conditions, units, drug names
    Helpers->>LoadPage: return auto-filled metadata
    LoadPage->>LoadPage: render editable condition_metadata table
    User->>LoadPage: (optional) edit condition metadata
    LoadPage->>LoadPage: update condition_metadata reactive
    Server->>StatModel: pass app_template & condition_metadata
    StatModel->>StatModel: force response-curve mode (chemoproteomics)
    StatModel->>Helpers: convert_dose_to_molar, parse metadata
    Helpers->>StatModel: return derived contrast matrix
    StatModel->>StatModel: render response-curve plot & fitting
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

Review effort 3/5, enhancement

Suggested reviewers

  • sszvetecz

Poem

🐰 A template for every quest,
From default to chemoproteomics blessed,
Condition metadata parsed with care,
Dose curves blooming everywhere,
Turnover tales now template-aware! 🧪✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.
Title check ✅ Passed The title accurately describes the main objective of the pull request: introducing a new template system for chemoproteomics workflows, which is evidenced across multiple files (constants, UI, server logic, and helper functions).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-chemo

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
R/statmodel-server-visualization.R (1)

201-210: ⚠️ Potential issue | 🟠 Major

Honor the response-curve log-scale checkbox in downloaded plots.

transform_dose = TRUE ignores modeling_response_curve_log_xaxis, so downloaded plots can disagree with a user’s linear-scale setting.

Proposed fix
             response_plot <- visualizeResponseProtein(
               data = dia_prepared,
               protein_name = input[[NAMESPACE_STATMODEL$visualization_which_protein]],
               drug_name = input[[NAMESPACE_STATMODEL$visualization_response_curve_which_drug]],
               ratio_response = isTRUE(input[[NAMESPACE_STATMODEL$visualization_response_curve_ratio_scale]]),
               show_ic50 = TRUE,
               add_ci = TRUE,
-              transform_dose = TRUE,
+              transform_dose = isTRUE(input[[NAMESPACE_STATMODEL$modeling_response_curve_log_xaxis]]),
               n_samples = 1000,
               increasing = input[[NAMESPACE_STATMODEL$modeling_response_curve_increasing_trend]]
             )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@R/statmodel-server-visualization.R` around lines 201 - 210, The downloaded
response-curve plot is always using log-dose because transform_dose is hardcoded
TRUE; change the call to visualizeResponseProtein so transform_dose is driven by
the user's checkbox (use
isTRUE(input[[NAMESPACE_STATMODEL$modeling_response_curve_log_xaxis]]) instead
of TRUE). Update the visualizeResponseProtein invocation (the call building
response_plot) to pass transform_dose based on that input so the downloaded plot
honors the modeling_response_curve_log_xaxis setting.
🧹 Nitpick comments (1)
R/module-home-ui.R (1)

45-54: Non-namespaced inputId breaks module encapsulation.

inputId = "app_template" skips ns() so that server.R can read it as input$app_template at the app level. It works today but couples the module to a single mount point — mounting homeUI with a different id, or mounting twice, would either miss this input or produce duplicate IDs. Consider namespacing it and surfacing the selected template via the module's returned reactive instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@R/module-home-ui.R` around lines 45 - 54, The selectInput in module-home-ui.R
uses a non-namespaced inputId ("app_template") which breaks module
encapsulation; change the inputId to use the module namespace (wrap with ns(),
e.g. ns("app_template") inside the selectInput call in the homeUI function) and
update the module server to expose the selected value via a reactive (e.g.
return a reactive that reads input$app_template namespaced inside the
corresponding homeServer). Ensure references to TEMPLATES / TEMPLATE_LABELS
remain the same but consume the namespaced input via the module's returned
reactive so callers can access the chosen template without relying on a global
input id.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@R/constants.R`:
- Around line 1-4: TEMPLATES is missing the protein_turnover key which causes
downstream checks against TEMPLATES$protein_turnover to be NULL; add an explicit
entry to the TEMPLATES list (e.g., protein_turnover = "protein_turnover") and
add the corresponding label in TEMPLATE_LABELS so references like in
statmodel-server-download-code.R, statmodel-server-options-modeling.R,
statmodel-server-visualization.R, module-expdes-server.R and
module-statmodel-server.R work as intended and no longer evaluate to NULL.

In `@R/module-expdes-server.R`:
- Around line 75-77: is_response_curve() currently returns TRUE for both
TEMPLATES$protein_turnover and TEMPLATES$chemoproteomics, but the nM conversion
(scaling by 1e9) in the "chemoproteomics assume nM" path should only apply to
chemoproteomics; change the logic so that either is_response_curve() only
includes TEMPLATES$chemoproteomics (remove TEMPLATES$protein_turnover) or, more
explicitly, guard the scaling with a check app_template() ==
TEMPLATES$chemoproteomics before multiplying by 1e9; update the condition used
in the scaling code (the block that mentions "chemoproteomics assume nM" and
does the 1e9 multiplication) to reference TEMPLATES$chemoproteomics directly to
avoid corrupting protein_turnover data.

In `@R/module-loadpage-server.R`:
- Around line 440-458: The code may leave stale condition metadata if parsing
fails or no Condition column exists; before attempting to rebuild set
condition_metadata(NULL) to clear previous state, and inside the tryCatch ensure
both the "no Condition" branch and the error handler call
condition_metadata(NULL); update the chemoproteomics init block around
get_data(), parse_drug_name_from_conditions(), autofill_condition_value(), and
parse_dose_unit_from_conditions() so any failure or missing Condition explicitly
resets condition_metadata to NULL.

In `@R/module-qc-server.R`:
- Line 19: The qcServer function signature currently declares unused parameters
app_template and get_condition_metadata; remove these two parameters from the
qcServer(...) declaration so the function only accepts (input, output, session,
parent_session, loadpage_input, get_data) and update any callers if present to
match the new signature; if you intended to keep them for future use instead,
add corresponding `@param` entries to the roxygen block and references in the body
(e.g., pass them through or use them) rather than leaving them unused.

In `@R/module-statmodel-server.R`:
- Around line 317-320: The calls to fitResponseCurves explicitly set
transform_dose = TRUE, forcing log-transform even when the UI checkbox is
unchecked; replace the hardcoded TRUE with the reactive checkbox value used by
the UI (the same logical reactive used for plotting) and pass that into
transform_dose (i.e., fitResponseCurves(input, matrix, preprocess_data(),
transform_dose = <ui_checkbox_reactive>)); apply the same change to the other
call site referenced (the block around the second occurrence, lines ~431-440) so
both fitting branches respect the user's checkbox.
- Around line 296-317: The code only checks for "?" but not for non-numeric
DoseVal or invalid DoseUnit, so validate DoseVal and DoseUnit before calling
convert_dose_to_molar: after obtaining meta from condition_metadata() (inside
the chemoproteomics branch) ensure DoseVal parses to a non-NA numeric (no
suppressWarnings(as.numeric(...)) — explicitly coerce and check !is.na) and that
DoseUnit exists and is one of the allowed unit strings (e.g.,
"pM","nM","uM","mM","M") or provide a clear error if missing/invalid; if
validation fails showNotification with a descriptive message and req(FALSE).
Update the block that builds matrix/GROUP/dose_value/drug (used by
convert_dose_to_molar and fitResponseCurves) to rely on the validated values so
convert_dose_to_molar receives guaranteed numeric dose and a known unit.

In `@R/server.R`:
- Line 35: The reactive app_template currently yields NULL before inputs
initialize, which overrides downstream fallbacks; change the app_template
reactive (symbol: app_template) to return a non-NULL default when
input$app_template is NULL (e.g., return TEMPLATES$default) so modules that call
app_template() (e.g., the check using app_template() %in%
c(TEMPLATES$protein_turnover, TEMPLATES$chemoproteomics)) always receive a valid
value and avoid logical(0) behavior during startup.

In `@R/statmodel-server-comparisons.R`:
- Around line 7-13: The function convert_dose_to_molar silently treats unknown
dose_unit lookups as 1 (molar); change it so unknown units are not coerced to 1:
detect NA entries in mult produced by multipliers[dose_unit], leave those mult
values as NA (so callers like build_response_curve_matrix can handle/propagate
them) and emit a warning listing the unique unknown units (use warning() with
context including the unknown unit strings and the function name
convert_dose_to_molar); do not replace NA with 1—only map known keys to their
multipliers and return dose_val * mult (with NA where conversion failed).
- Around line 28-38: The function parse_drug_name_from_conditions currently
computes a single most-frequent prefix and returns a scalar, which gets recycled
and collapses distinct drugs; change it to return a character vector aligned to
the input conditions: for each element of conditions compute the prefix (using
the existing regex/gsub and trimws logic), set "Treatment" for control rows
(is_ctrl) or when the per-element prefix is empty, and return that vector;
ensure the function signature parse_drug_name_from_conditions and its behavior
mirrors parse_dose_unit_from_conditions (vectorized, same length as input) so
callers using ifelse(is_ctrl, conditions, parsed_drug) get per-condition drug
names rather than a recycled scalar.

In `@R/statmodel-server-visualization.R`:
- Around line 49-70: The treatment dropdown still only removes "DMSO" even
though controls were detected earlier via grepl("^(dmso|control|vehicle)$", ...)
in the chemoproteomics branch; update the filtering logic after
prepare_dose_response_fit so that unique_drugs_without_control is derived by
removing any drug values matching that same control regex (case-insensitive)
rather than just the literal "DMSO" — locate where response_curve_setup_matrix
is used, and change the computation of unique_drugs_without_control (and the
value passed to selectInput) to exclude drugs matching the control pattern (use
the same regex or a helper that relies on is_ctrl logic).

---

Outside diff comments:
In `@R/statmodel-server-visualization.R`:
- Around line 201-210: The downloaded response-curve plot is always using
log-dose because transform_dose is hardcoded TRUE; change the call to
visualizeResponseProtein so transform_dose is driven by the user's checkbox (use
isTRUE(input[[NAMESPACE_STATMODEL$modeling_response_curve_log_xaxis]]) instead
of TRUE). Update the visualizeResponseProtein invocation (the call building
response_plot) to pass transform_dose based on that input so the downloaded plot
honors the modeling_response_curve_log_xaxis setting.

---

Nitpick comments:
In `@R/module-home-ui.R`:
- Around line 45-54: The selectInput in module-home-ui.R uses a non-namespaced
inputId ("app_template") which breaks module encapsulation; change the inputId
to use the module namespace (wrap with ns(), e.g. ns("app_template") inside the
selectInput call in the homeUI function) and update the module server to expose
the selected value via a reactive (e.g. return a reactive that reads
input$app_template namespaced inside the corresponding homeServer). Ensure
references to TEMPLATES / TEMPLATE_LABELS remain the same but consume the
namespaced input via the module's returned reactive so callers can access the
chosen template without relying on a global input id.
🪄 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: 2d12f9ec-e75b-4ef6-933b-503c1f0bf363

📥 Commits

Reviewing files that changed from the base of the PR and between 0c12984 and 4f3e01e.

📒 Files selected for processing (15)
  • R/constants.R
  • R/module-expdes-server.R
  • R/module-home-ui.R
  • R/module-loadpage-server.R
  • R/module-qc-server.R
  • R/module-qc-ui.R
  • R/module-statmodel-server.R
  • R/server.R
  • R/statmodel-server-comparisons.R
  • R/statmodel-server-download-code.R
  • R/statmodel-server-options-modeling.R
  • R/statmodel-server-visualization.R
  • R/statmodel-ui-options-modeling.R
  • R/statmodel-ui-options-visualization.R
  • R/utils.R

Comment thread R/constants.R
Comment thread R/module-expdes-server.R
Comment thread R/module-loadpage-server.R
Comment thread R/module-qc-server.R Outdated
Comment on lines +296 to +317
if (isTRUE(app_template() == TEMPLATES$chemoproteomics)) {
meta <- tryCatch(condition_metadata(), error = function(e) NULL)
if (!is.null(meta)) {
check_cols <- intersect(c("DoseVal", "DoseUnit"), colnames(meta))
if (any(sapply(check_cols, function(col) "?" %in% meta[[col]]))) {
showNotification(
"Please fill in all '?' values in the condition metadata table on the data upload page before running the analysis.",
type = "error", duration = 8
)
req(FALSE)
}
}
meta <- condition_metadata()
req(!is.null(meta) && "DoseVal" %in% colnames(meta))
is_ctrl <- grepl("^(dmso|control|vehicle)$", tolower(meta$Condition))
matrix <- data.frame(
GROUP = meta$Condition,
dose_value = convert_dose_to_molar(suppressWarnings(as.numeric(meta$DoseVal)), if ("DoseUnit" %in% colnames(meta)) meta$DoseUnit else "nM"),
drug = ifelse(is_ctrl, meta$Condition, if ("DrugName" %in% colnames(meta)) meta$DrugName else parse_drug_name_from_conditions(meta$Condition)),
stringsAsFactors = FALSE
)
fitResponseCurves(input, matrix, preprocess_data(), transform_dose = TRUE)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Validate edited dose values and units, not just "?".

Users can edit the metadata table to non-numeric values or mistyped units. With suppressWarnings(as.numeric(...)) and unit fallback in conversion, those become NA or incorrect molar values instead of a clear validation error.

Proposed fix
           if (isTRUE(app_template() == TEMPLATES$chemoproteomics)) {
             meta <- tryCatch(condition_metadata(), error = function(e) NULL)
             if (!is.null(meta)) {
-              check_cols <- intersect(c("DoseVal", "DoseUnit"), colnames(meta))
-              if (any(sapply(check_cols, function(col) "?" %in% meta[[col]]))) {
+              dose_values <- suppressWarnings(as.numeric(meta$DoseVal))
+              dose_units <- if ("DoseUnit" %in% colnames(meta)) trimws(meta$DoseUnit) else rep("nM", nrow(meta))
+              valid_units <- c("", "nM", "nm", "uM", "um", "mM", "mm", "M", "m")
+              invalid_metadata <- is.na(dose_values) | !(dose_units %in% valid_units)
+              if (any(invalid_metadata)) {
                 showNotification(
-                  "Please fill in all '?' values in the condition metadata table on the data upload page before running the analysis.",
+                  "Please enter numeric dose values and supported dose units in the condition metadata table before running the analysis.",
                   type = "error", duration = 8
                 )
                 req(FALSE)
               }
             }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@R/module-statmodel-server.R` around lines 296 - 317, The code only checks for
"?" but not for non-numeric DoseVal or invalid DoseUnit, so validate DoseVal and
DoseUnit before calling convert_dose_to_molar: after obtaining meta from
condition_metadata() (inside the chemoproteomics branch) ensure DoseVal parses
to a non-NA numeric (no suppressWarnings(as.numeric(...)) — explicitly coerce
and check !is.na) and that DoseUnit exists and is one of the allowed unit
strings (e.g., "pM","nM","uM","mM","M") or provide a clear error if
missing/invalid; if validation fails showNotification with a descriptive message
and req(FALSE). Update the block that builds matrix/GROUP/dose_value/drug (used
by convert_dose_to_molar and fitResponseCurves) to rely on the validated values
so convert_dose_to_molar receives guaranteed numeric dose and a known unit.

Comment on lines +317 to +320
fitResponseCurves(input, matrix, preprocess_data(), transform_dose = TRUE)
} else {
fitResponseCurves(input, matrix, preprocess_data(), transform_dose = TRUE)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Use the checkbox value for dose transformation.

The UI now lets templates set the log-axis default, but fitting and plotting still force transform_dose = TRUE. If the user unchecks the log-scale option for linear time/dose values, the analysis and plot still transform them.

Proposed fix
-            fitResponseCurves(input, matrix, preprocess_data(), transform_dose = TRUE)
+            transform_dose <- isTRUE(input[[NAMESPACE_STATMODEL$modeling_response_curve_log_xaxis]])
+            fitResponseCurves(input, matrix, preprocess_data(), transform_dose = transform_dose)
           } else {
-            fitResponseCurves(input, matrix, preprocess_data(), transform_dose = TRUE)
+            transform_dose <- isTRUE(input[[NAMESPACE_STATMODEL$modeling_response_curve_log_xaxis]])
+            fitResponseCurves(input, matrix, preprocess_data(), transform_dose = transform_dose)
           }
             visualizeResponseProtein(
               data = dia_prepared,
               protein_name = input[[NAMESPACE_STATMODEL$visualization_which_protein]],
               drug_name = input[[NAMESPACE_STATMODEL$visualization_response_curve_which_drug]],
               ratio_response = isTRUE(input[[NAMESPACE_STATMODEL$visualization_response_curve_ratio_scale]]),
               show_ic50 = TRUE,
               add_ci = TRUE,
-              transform_dose = TRUE,
+              transform_dose = isTRUE(input[[NAMESPACE_STATMODEL$modeling_response_curve_log_xaxis]]),
               n_samples = 1000,
               increasing = input[[NAMESPACE_STATMODEL$modeling_response_curve_increasing_trend]]
             )

Also applies to: 431-440

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@R/module-statmodel-server.R` around lines 317 - 320, The calls to
fitResponseCurves explicitly set transform_dose = TRUE, forcing log-transform
even when the UI checkbox is unchecked; replace the hardcoded TRUE with the
reactive checkbox value used by the UI (the same logical reactive used for
plotting) and pass that into transform_dose (i.e., fitResponseCurves(input,
matrix, preprocess_data(), transform_dose = <ui_checkbox_reactive>)); apply the
same change to the other call site referenced (the block around the second
occurrence, lines ~431-440) so both fitting branches respect the user's
checkbox.

Comment thread R/server.R Outdated
Comment thread R/statmodel-server-comparisons.R
Comment thread R/statmodel-server-comparisons.R
Comment thread R/statmodel-server-visualization.R
Comment thread R/module-statmodel-server.R
Comment thread R/module-loadpage-server.R
Comment thread R/module-statmodel-server.R Outdated
Comment thread R/module-statmodel-server.R
Comment thread R/module-statmodel-server.R Outdated
Comment on lines +265 to +267
} else {
contrast$matrix = build_response_curve_matrix(condition_list())
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this is unnecessary

Comment thread R/module-statmodel-server.R
Comment thread R/module-statmodel-server.R
Comment thread R/module-statmodel-server.R
Comment thread R/module-statmodel-server.R
Comment thread R/statmodel-server-comparisons.R
Comment thread R/statmodel-server-comparisons.R Outdated
Comment thread R/statmodel-server-visualization.R Outdated
Comment thread R/statmodel-server-visualization.R Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
R/module-statmodel-server.R (1)

146-178: ⚠️ Potential issue | 🟠 Major

rc_matrix may be undefined when this reactive fires outside chemoproteomics.

On Line 168 the code does if (is.null(rc_matrix) || nrow(rc_matrix) == 0), but rc_matrix is only assigned inside the if (app_template() == TEMPLATES$chemoproteomics) branch (Lines 149-158), and only when !is.null(meta) && nrow(meta) > 0 && "DoseVal" %in% colnames(meta) (the else returns early on Line 165). For any other template, this observer still fires when the user selects the response-curve comparison mode, and execution reaches Line 168 with rc_matrix unbound, throwing object 'rc_matrix' not found — caught by the outer tryCatch and shown as an error notification to the user.

Even if the UI currently restricts response-curve mode to chemoproteomics, defensively guard with an early return or initialize rc_matrix <- NULL:

🔧 Proposed fix
         if (isTRUE(input[[NAMESPACE_STATMODEL$comparison_mode]] ==
             CONSTANTS_STATMODEL$comparison_mode_response_curve)) {
           tryCatch({
+            rc_matrix <- NULL
             if (app_template() == TEMPLATES$chemoproteomics) {

Related: Line 149 should also use isTRUE(app_template() == TEMPLATES$chemoproteomics) for consistency with Lines 188, 304, and 422 — a NULL return from app_template() here currently yields logical(0) and errors in the if.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@R/module-statmodel-server.R` around lines 146 - 178, The observer can error
because rc_matrix is only set inside the app_template() ==
TEMPLATES$chemoproteomics branch and may be unbound when the reactive runs;
initialize rc_matrix <- NULL at the start of the tryCatch block (before the
app_template() check) and change the template check to isTRUE(app_template() ==
TEMPLATES$chemoproteomics) so a NULL app_template() doesn't produce logical(0);
then keep the existing guard if (is.null(rc_matrix) || nrow(rc_matrix) == 0) to
return/stop and ensure contrast$matrix and enabling/disabling of
NAMESPACE_STATMODEL$modeling_start are handled consistently.
R/statmodel-server-download-code.R (1)

1-1: ⚠️ Potential issue | 🔴 Critical

Critical: function signature is missing app_template argument — call site passes 5 positional args.

R/module-statmodel-server.R line 337 calls:

generate_analysis_code(qc_input(), loadpage_input(), comp_mat, input, app_template())

but the function is defined with only 4 parameters in R/statmodel-server-download-code.R. When this code path executes (e.g., Download analysis code), R will raise unused argument (app_template()) and the reactive will fail.

Either add app_template as a parameter or remove it from the call site.

🔧 Proposed fix
-generate_analysis_code = function(qc_input, loadpage_input, comp_mat, input) {
+generate_analysis_code = function(qc_input, loadpage_input, comp_mat, input, app_template = NULL) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@R/statmodel-server-download-code.R` at line 1, The function
generate_analysis_code is missing the app_template parameter while its caller
passes five positional arguments; update the function signature to include
app_template (e.g., generate_analysis_code = function(qc_input, loadpage_input,
comp_mat, input, app_template)) so the extra argument is accepted, and then use
or forward app_template within the function body as appropriate (or explicitly
ignore it) to prevent the "unused argument" error; reference
generate_analysis_code and the caller in module-statmodel-server.R that invokes
generate_analysis_code(..., app_template()).
♻️ Duplicate comments (2)
R/module-statmodel-server.R (1)

149-166: 🛠️ Refactor suggestion | 🟠 Major

Consolidate the six copies of the chemoproteomics matrix construction.

The is_ctrl <- grepl(...); data.frame(GROUP=..., dose_value=convert_dose_to_molar(...), drug=ifelse(is_ctrl, ...)) pattern now appears at Lines 149-166, 188-199, 212-226, 264-274, 316-324, and 422-431 in this file alone, plus twice in statmodel-server-visualization.R. A per-site bug fix (e.g., the parse_drug_name_from_conditions scalar issue, or validating "?" in DoseUnit) has to be applied eight times.

Extract a single build_chemoproteomics_matrix(meta) helper (suggested in the cross-file comment in statmodel-server-visualization.R) and replace each block with one call. This would shrink this server file by ~50 lines and eliminate the observed drift risk.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@R/module-statmodel-server.R` around lines 149 - 166, The duplicated
chemoproteomics matrix-construction logic across this file (and in
statmodel-server-visualization.R) should be refactored into a single helper
function build_chemoproteomics_matrix(meta); implement
build_chemoproteomics_matrix(meta) to: validate meta (non-null, nrow>0, has
DoseVal), compute is_ctrl with grepl on meta$Condition, compute dose_value using
convert_dose_to_molar(as.numeric(meta$DoseVal), meta$DoseUnit or fallback "nM")
including handling of "?" units, compute drug as ifelse(is_ctrl, meta$Condition,
meta$DrugName or parse_drug_name_from_conditions(meta$Condition)), and return
the data.frame with GROUP, dose_value, drug; then replace each repeated block
(the calls around app_template()==TEMPLATES$chemoproteomics, where
condition_metadata() is used and
showNotification/disable(NAMESPACE_STATMODEL$modeling_start); return() is
triggered) with a single call rc_matrix <- build_chemoproteomics_matrix(meta)
and keep existing error/notification behavior unchanged.
R/statmodel-server-visualization.R (1)

49-64: 🛠️ Refactor suggestion | 🟠 Major

Extract the chemoproteomics matrix construction into a single helper.

The same 8-line data.frame(GROUP, dose_value, drug, ...) block is now repeated in six places across the codebase:

  • statmodel-server-visualization.R Lines 49-64 and 186-197
  • module-statmodel-server.R Lines 149-166, 188-199, 212-226, 264-274, 316-324, and 422-431

Every change (e.g., fixing the "?" unit handling, the scalar drug-name bug, adding a new metadata column) has to be made in six places and will drift. Extract a helper, e.g. in statmodel-server-comparisons.R:

build_chemoproteomics_matrix <- function(meta) {
  if (is.null(meta) || nrow(meta) == 0 || !("DoseVal" %in% colnames(meta))) return(NULL)
  is_ctrl <- grepl("^(dmso|control|vehicle)$", tolower(meta$Condition))
  dose_unit <- if ("DoseUnit" %in% colnames(meta)) meta$DoseUnit else "nM"
  drug_col  <- if ("DrugName" %in% colnames(meta)) meta$DrugName
               else parse_drug_name_from_conditions(meta$Condition)
  data.frame(
    GROUP      = meta$Condition,
    dose_value = convert_dose_to_molar(suppressWarnings(as.numeric(meta$DoseVal)), dose_unit),
    drug       = ifelse(is_ctrl, meta$Condition, drug_col),
    stringsAsFactors = FALSE
  )
}

and call it from every site. This also concentrates the scalar-drug and unknown-unit fixes in one place.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@R/statmodel-server-visualization.R` around lines 49 - 64, Extract the
repeated chemoproteomics data.frame construction into a single helper (e.g.
build_chemoproteomics_matrix) placed in statmodel-server-comparisons.R and have
callers (places building rc_mat: the block guarded by app_template() ==
TEMPLATES$chemoproteomics and other locations in module-statmodel-server.R) call
this helper instead of duplicating logic; the helper should accept meta (from
condition_metadata()), return NULL if meta is NULL/empty or lacks "DoseVal",
compute is_ctrl via grepl on meta$Condition, determine dose_unit (fallback
"nM"), determine drug_col using "DrugName" if present or
parse_drug_name_from_conditions(meta$Condition) otherwise, and return the
data.frame with GROUP, dose_value (via convert_dose_to_molar with
suppressWarnings(as.numeric(meta$DoseVal))), and drug using ifelse(is_ctrl,
meta$Condition, drug_col), so all six duplicated blocks are replaced by rc_mat
<- build_chemoproteomics_matrix(meta) with fallback to contrast$matrix when
helper returns NULL.
🧹 Nitpick comments (3)
R/module-statmodel-server.R (2)

367-371: Null-check targets the reactive wrapper, not its value.

app_template is the reactive function reference and is never NULL in this scope — only app_template() can return NULL. Simplify to:

🔧 Proposed fix
-        if (!is.null(app_template) && !is.null(app_template()) &&
-            app_template() %in% c(TEMPLATES$chemoproteomics)) {
+        if (isTRUE(app_template() == TEMPLATES$chemoproteomics)) {
           return(NULL)
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@R/module-statmodel-server.R` around lines 367 - 371, The null-check is
testing the reactive function reference app_template instead of its returned
value; in the renderUI block for output$matrix you should remove the
is.null(app_template) check and only test app_template() (e.g., if
(!is.null(app_template()) && app_template() %in% c(TEMPLATES$chemoproteomics))
return(NULL)), ensuring you call the reactive to inspect its value; adjust any
conditional logic in the output$matrix renderUI to use app_template()
consistently.

43-71: Duplicated updateRadioButtons / updateSelectInput wiring.

This observeEvent(app_template(), ...) and the observeEvent(input[[comparison_mode]], ...) at Lines 121-137 set overlapping choices for the plot-type selectInput. When the user selects the chemoproteomics template, both observers will fire (the template observer sets comparison_mode, which triggers the mode observer, which sets plot-type choices again). Functionally harmless, but redundant and easy to get out of sync.

Consider extracting shared option lists to helpers (or CONSTANTS_STATMODEL) so both observers reference the same source:

comparison_mode_choices_default <- c(
  "All possible pairwise comparisons"      = CONSTANTS_STATMODEL$comparison_mode_all_pairwise,
  "Compare all against one"                = CONSTANTS_STATMODEL$comparison_mode_all_vs_one,
  "Create custom pairwise comparisons"     = CONSTANTS_STATMODEL$comparison_mode_custom_pairwise,
  "Create custom non-pairwise comparisons" = CONSTANTS_STATMODEL$comparison_mode_custom_nonpairwise
)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@R/module-statmodel-server.R` around lines 43 - 71, The two observers
(observeEvent(app_template()) and the observer watching input[[comparison_mode]]
which call updateRadioButtons and updateSelectInput) duplicate the same choice
lists and can go out of sync; extract the shared choice vectors (e.g.,
comparison_mode_choices_default and visualization_plot_type_choices_default)
into a single source (preferably CONSTANTS_STATMODEL or a small helper function)
and replace the hard-coded choice literals inside updateRadioButtons and
updateSelectInput in both observeEvent blocks to reference those shared symbols;
ensure the chemoproteomics-specific choices (comparison_mode and
visualization_plot_type for TEMPLATES$chemoproteomics) remain set only once (in
observeEvent(app_template())) or by using the shared constants plus a
conditional selection, so both observers use the same choice definitions and no
longer duplicate wiring.
R/module-expdes-server.R (1)

138-142: Dose scaling by 1e9 couples this module to convert_dose_to_molar output.

The 1e9 multiplication assumes .get_concentrations_from_matrix() and prepared_response_data()$dose are always in molar. That invariant now holds because the upstream matrix is built via convert_dose_to_molar() in module-statmodel-server.R/statmodel-server-visualization.R, but it's an implicit cross-module contract. Consider either:

  1. Centralizing the molar↔nM conversion in a single helper (e.g., .to_nM(dose_val)), or
  2. Adding a short comment explicitly stating that upstream dose_value is molar by convention (produced by convert_dose_to_molar).

Also note: .check_replicates_per_dose(sim_data, selected_protein) is invoked after the *1e9 scale; since it only groups by distinct values with table(...), results are unchanged, but readers may find the ordering confusing.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@R/module-expdes-server.R` around lines 138 - 142, The code multiplies doses
by 1e9 (user_concs <- user_concs * 1e9 and sim_data$dose <- sim_data$dose * 1e9)
which implicitly assumes upstream values are in molar from
.get_concentrations_from_matrix()/convert_dose_to_molar(); replace these literal
multiplications with a single helper .to_nM(dose_val) and call
.to_nM(user_concs) and .to_nM(sim_data$dose) (implement .to_nM to multiply by
1e9 and document its contract), and either move the
.check_replicates_per_dose(sim_data, selected_protein) call to before scaling or
add a short comment explaining why the check runs after scaling so readers
understand the ordering.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@R/statmodel-server-comparisons.R`:
- Around line 17-24: The parsed-unit sentinel "?" from
parse_dose_unit_from_conditions is causing silent mis-conversion downstream in
convert_dose_to_molar; update parse_dose_unit_from_conditions to return
NA_character_ for non-control, non-matching units instead of "?" so unknown
units propagate as NA into convert_dose_to_molar (and fail loudly or be handled
consistently in render_group_comparison_plot_inputs and
create_download_plot_handler); ensure any callers expecting "?" are updated to
treat NA_character_ as the missing/unknown-unit case or add a small
normalization wrapper that converts "?" to NA if you prefer centralized
handling.

---

Outside diff comments:
In `@R/module-statmodel-server.R`:
- Around line 146-178: The observer can error because rc_matrix is only set
inside the app_template() == TEMPLATES$chemoproteomics branch and may be unbound
when the reactive runs; initialize rc_matrix <- NULL at the start of the
tryCatch block (before the app_template() check) and change the template check
to isTRUE(app_template() == TEMPLATES$chemoproteomics) so a NULL app_template()
doesn't produce logical(0); then keep the existing guard if (is.null(rc_matrix)
|| nrow(rc_matrix) == 0) to return/stop and ensure contrast$matrix and
enabling/disabling of NAMESPACE_STATMODEL$modeling_start are handled
consistently.

In `@R/statmodel-server-download-code.R`:
- Line 1: The function generate_analysis_code is missing the app_template
parameter while its caller passes five positional arguments; update the function
signature to include app_template (e.g., generate_analysis_code =
function(qc_input, loadpage_input, comp_mat, input, app_template)) so the extra
argument is accepted, and then use or forward app_template within the function
body as appropriate (or explicitly ignore it) to prevent the "unused argument"
error; reference generate_analysis_code and the caller in
module-statmodel-server.R that invokes generate_analysis_code(...,
app_template()).

---

Duplicate comments:
In `@R/module-statmodel-server.R`:
- Around line 149-166: The duplicated chemoproteomics matrix-construction logic
across this file (and in statmodel-server-visualization.R) should be refactored
into a single helper function build_chemoproteomics_matrix(meta); implement
build_chemoproteomics_matrix(meta) to: validate meta (non-null, nrow>0, has
DoseVal), compute is_ctrl with grepl on meta$Condition, compute dose_value using
convert_dose_to_molar(as.numeric(meta$DoseVal), meta$DoseUnit or fallback "nM")
including handling of "?" units, compute drug as ifelse(is_ctrl, meta$Condition,
meta$DrugName or parse_drug_name_from_conditions(meta$Condition)), and return
the data.frame with GROUP, dose_value, drug; then replace each repeated block
(the calls around app_template()==TEMPLATES$chemoproteomics, where
condition_metadata() is used and
showNotification/disable(NAMESPACE_STATMODEL$modeling_start); return() is
triggered) with a single call rc_matrix <- build_chemoproteomics_matrix(meta)
and keep existing error/notification behavior unchanged.

In `@R/statmodel-server-visualization.R`:
- Around line 49-64: Extract the repeated chemoproteomics data.frame
construction into a single helper (e.g. build_chemoproteomics_matrix) placed in
statmodel-server-comparisons.R and have callers (places building rc_mat: the
block guarded by app_template() == TEMPLATES$chemoproteomics and other locations
in module-statmodel-server.R) call this helper instead of duplicating logic; the
helper should accept meta (from condition_metadata()), return NULL if meta is
NULL/empty or lacks "DoseVal", compute is_ctrl via grepl on meta$Condition,
determine dose_unit (fallback "nM"), determine drug_col using "DrugName" if
present or parse_drug_name_from_conditions(meta$Condition) otherwise, and return
the data.frame with GROUP, dose_value (via convert_dose_to_molar with
suppressWarnings(as.numeric(meta$DoseVal))), and drug using ifelse(is_ctrl,
meta$Condition, drug_col), so all six duplicated blocks are replaced by rc_mat
<- build_chemoproteomics_matrix(meta) with fallback to contrast$matrix when
helper returns NULL.

---

Nitpick comments:
In `@R/module-expdes-server.R`:
- Around line 138-142: The code multiplies doses by 1e9 (user_concs <-
user_concs * 1e9 and sim_data$dose <- sim_data$dose * 1e9) which implicitly
assumes upstream values are in molar from
.get_concentrations_from_matrix()/convert_dose_to_molar(); replace these literal
multiplications with a single helper .to_nM(dose_val) and call
.to_nM(user_concs) and .to_nM(sim_data$dose) (implement .to_nM to multiply by
1e9 and document its contract), and either move the
.check_replicates_per_dose(sim_data, selected_protein) call to before scaling or
add a short comment explaining why the check runs after scaling so readers
understand the ordering.

In `@R/module-statmodel-server.R`:
- Around line 367-371: The null-check is testing the reactive function reference
app_template instead of its returned value; in the renderUI block for
output$matrix you should remove the is.null(app_template) check and only test
app_template() (e.g., if (!is.null(app_template()) && app_template() %in%
c(TEMPLATES$chemoproteomics)) return(NULL)), ensuring you call the reactive to
inspect its value; adjust any conditional logic in the output$matrix renderUI to
use app_template() consistently.
- Around line 43-71: The two observers (observeEvent(app_template()) and the
observer watching input[[comparison_mode]] which call updateRadioButtons and
updateSelectInput) duplicate the same choice lists and can go out of sync;
extract the shared choice vectors (e.g., comparison_mode_choices_default and
visualization_plot_type_choices_default) into a single source (preferably
CONSTANTS_STATMODEL or a small helper function) and replace the hard-coded
choice literals inside updateRadioButtons and updateSelectInput in both
observeEvent blocks to reference those shared symbols; ensure the
chemoproteomics-specific choices (comparison_mode and visualization_plot_type
for TEMPLATES$chemoproteomics) remain set only once (in
observeEvent(app_template())) or by using the shared constants plus a
conditional selection, so both observers use the same choice definitions and no
longer duplicate wiring.
🪄 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: be88a8fc-4844-4800-9705-30af2f07788f

📥 Commits

Reviewing files that changed from the base of the PR and between 4f3e01e and c1d3ff1.

📒 Files selected for processing (11)
  • R/module-expdes-server.R
  • R/module-loadpage-server.R
  • R/module-statmodel-server.R
  • R/server.R
  • R/statmodel-server-comparisons.R
  • R/statmodel-server-download-code.R
  • R/statmodel-server-options-modeling.R
  • R/statmodel-server-visualization.R
  • R/statmodel-ui-options-modeling.R
  • R/statmodel-ui-options-visualization.R
  • tests/testthat/test-utils-statmodel-server.R
💤 Files with no reviewable changes (1)
  • tests/testthat/test-utils-statmodel-server.R
🚧 Files skipped from review as they are similar to previous changes (4)
  • R/server.R
  • R/statmodel-server-options-modeling.R
  • R/statmodel-ui-options-visualization.R
  • R/module-loadpage-server.R

Comment thread R/statmodel-server-comparisons.R
@tonywu1999 tonywu1999 changed the title Feat chemo refactor(chemoproteomics): Create a template for chemoproteomics workflows Apr 22, 2026
@tonywu1999 tonywu1999 merged commit b232c54 into devel Apr 22, 2026
1 of 2 checks passed
@tonywu1999 tonywu1999 deleted the feat-chemo branch April 22, 2026 01:59
@coderabbitai coderabbitai Bot mentioned this pull request Apr 22, 2026
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.

1 participant