Skip to content

feat(advanced-options): Set up advanced options panel for subnetwork search#178

Open
tonywu1999 wants to merge 6 commits intodevelfrom
feature-advanced-options
Open

feat(advanced-options): Set up advanced options panel for subnetwork search#178
tonywu1999 wants to merge 6 commits intodevelfrom
feature-advanced-options

Conversation

@tonywu1999
Copy link
Contributor

@tonywu1999 tonywu1999 commented Mar 5, 2026

Motivation and Context

This PR implements an "Advanced Options" panel for the network visualization module to let users fine-tune subnetwork extraction. The UI adds a collapsible advanced panel (toggleable via an action link) exposing three new filters — PTM-site matching, inclusion of infinite fold-changes, and regulation direction — and threads these inputs through server logic to the subnetwork extraction and generated reproducible code. The goal is to enable more precise, PTM-aware network extraction and reproducible code emission for downstream analyses.

Detailed Changes

  • NAMESPACE / package imports

    • Added importFrom(shiny, actionLink) (NAMESPACE).
    • Added importFrom(shinyjs, toggle) (NAMESPACE) and updated R/MSstatsShiny.R roxygen import list to include shinyjs::toggle.
  • UI module (R/module-visualize-network-ui.R)

    • Added createAdvancedOptionsCollapsible(ns):
      • Action link ns("toggle_adv") with icon to show/hide advanced options.
      • Hidden panel (shinyjs::hidden) containing:
        • checkboxInput ns("filterByCuration") (existing, relocated inside panel)
        • checkboxInput ns("filter_by_ptm_site") — new: filter relationships by PTM site match
        • checkboxInput ns("include_infinite_fc") — new: include infinite logFC entries
        • selectInput ns("direction") — new: "both"/"up"/"down" options for regulation direction
      • useShinyjs() called inside the helper.
    • Replaced call to createCurationFilterCheckbox(...) with createAdvancedOptionsCollapsible(ns) in createDataUploadBox().
    • networkUI continues to call shinyjs::useShinyjs() at module level.
    • UI changes: +62 / -12 (lines reported).
  • Server module (R/module-visualize-network-server.R and helpers in R/MSstatsShiny.R)

    • getInputParameters(input, selectedProteins):
      • Now returns filter_by_ptm_site = input$filter_by_ptm_site, include_infinite_fc = input$include_infinite_fc, direction = input$direction in the returned list.
      • Preserves previous handling for statementTypes/sources/filterByCuration; filterByCuration has explicit NULL->FALSE coercion, new parameters are passed through directly.
    • extractSubnetwork(...) signature extended to accept three new parameters:
      • New signature includes filter_by_ptm_site, include_infinite_fc, direction.
      • Calls MSstatsBioNet::getSubnetworkFromIndra(...) with the new named arguments: filter_by_ptm_site, include_infinite_fc, direction.
      • Wrapped in tryCatch with notification on error.
    • visualizeNetworkServer:
      • Observes input$toggle_adv and uses shinyjs::toggle() to show/hide advanced panel (wiring for the UI action link).
      • Threads the new parameters from getInputParameters to extractSubnetwork and to code-generation logic so generated reproducible code includes them.
    • Data processing and UI glue otherwise preserved; updates ensure propagation from UI inputs to MSstatsBioNet call.
    • Server changes: +21/-4 (reported across files).
  • Tests (tests/testthat/test_network_visualization.R)

    • Updated mocked extractSubnetwork signature and test call to accept/pass the three new parameters (filter_by_ptm_site, include_infinite_fc, direction).
    • The test updates pass default values for the new parameters (FALSE, FALSE, "both") and keep existing expected subnetwork return unchanged.
    • Changes to tests: +6/-2 (reported).

Unit tests added/modified

  • tests/testthat/test_network_visualization.R updated:
    • The test mock for extractSubnetwork was extended to accept the new parameters and the test invocation was updated to supply defaults for filter_by_ptm_site, include_infinite_fc, and direction.
    • No new tests were added that exercise:
      • UI toggle behavior for the advanced panel (input$toggle_adv and shinyjs toggle).
      • Downstream effects of filter_by_ptm_site / include_infinite_fc / direction on getSubnetworkFromIndra output beyond the existing mock.
      • Explicit null/default handling for the new inputs in getInputParameters beyond direct passthrough.

Coding guidelines / potential issues

  1. Test coverage gap:

    • Although tests were updated to match the expanded function signature, there are no new unit tests validating the behavioral effects of the new parameters (e.g., that filter_by_ptm_site actually filters, that direction excludes the appropriate proteins, or that include_infinite_fc includes expected infinite-FC cases). There are also no tests for the UI toggle show/hide behavior.
  2. Input default/null handling consistency:

    • getInputParameters coerces filterByCuration to a logical default (explicit NULL -> FALSE) but passes filter_by_ptm_site, include_infinite_fc, and direction through directly (no explicit NULL/default coercion). If input values are NULL (e.g., missing in some contexts), downstream code or MSstatsBioNet::getSubnetworkFromIndra may receive NULLs; consider explicit coercion/defaulting to FALSE for booleans and "both" for direction.
  3. Documentation missing for new parameters:

    • extractSubnetwork() lacks updated roxygen/documentation to describe the new parameters (filter_by_ptm_site, include_infinite_fc, direction). Public-facing docs or internal comments should be updated.
  4. Duplicate useShinyjs() calls:

    • useShinyjs() is invoked at module-level in networkUI() and again inside createAdvancedOptionsCollapsible(). This is redundant; having useShinyjs() once at the module root is sufficient.
  5. Imports surface expansion:

    • NAMESPACE now imports shiny::actionLink and shinyjs::toggle; this increases the import surface. Confirm that exported namespace changes are intentional and documented.
  6. Test mock signatures:

    • While tests were modified to match the new signature, ensure any other mocked functions or downstream callers (including external integration tests or examples) are updated to avoid signature mismatches.

@coderabbitai
Copy link

coderabbitai bot commented Mar 5, 2026

Warning

Rate limit exceeded

@tonywu1999 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 22 minutes and 4 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2a00c321-45a2-4d80-9c20-fb03c4a6ae69

📥 Commits

Reviewing files that changed from the base of the PR and between 4122b7c and 7ebf7f7.

📒 Files selected for processing (1)
  • tests/testthat/test_network_visualization.R
📝 Walkthrough

Walkthrough

The PR adds two imports (shiny::actionLink, shinyjs::toggle) and introduces a collapsible "Advanced Options" UI with three new filters (filter_by_ptm_site, include_infinite_fc, direction), threads those inputs through getInputParameters and visualizeNetworkServer, extends extractSubnetwork signature, updates generated network code, and adjusts tests.

Changes

Cohort / File(s) Summary
Package Imports
NAMESPACE, R/MSstatsShiny.R
Added importFrom(shiny, actionLink) and importFrom(shinyjs, toggle) to support the new UI toggle and shinyjs usage.
Advanced Options UI
R/module-visualize-network-ui.R
Replaced the static curation checkbox with a collapsible "Advanced Options" panel (uses useShinyjs() and an action link); added filter_by_ptm_site, include_infinite_fc, and direction inputs and tooltips; added createAdvancedOptionsCollapsible(ns) and updated createDataUploadBox(...) to use it.
Server Parameter Threading
R/module-visualize-network-server.R
Added reading of new inputs to getInputParameters(), wired input$toggle_adv to show/hide panel, propagated filter_by_ptm_site, include_infinite_fc, and direction through visualizeNetworkServer, and updated generate_network_code() to emit these parameters.
Core function signature & tests
R/.../extractSubnetwork*, tests/testthat/test_network_visualization.R
Extended extractSubnetwork(...) signature to include filter_by_ptm_site, include_infinite_fc, and direction; updated unit test mocks/calls to pass the new parameters with defaults.

Sequence Diagram

sequenceDiagram
    participant User as User
    participant UI as Advanced Options Panel
    participant Server as visualizeNetworkServer
    participant Input as getInputParameters
    participant Extract as extractSubnetwork
    participant INDRA as getSubnetworkFromIndra

    User->>UI: Click actionLink (toggle)
    UI->>UI: (shinyjs::toggle) show/hide advanced options
    User->>UI: Set filter_by_ptm_site / include_infinite_fc / direction
    Server->>Input: getInputParameters() reads inputs
    Input-->>Server: return parameters (including new filters)
    Server->>Extract: extractSubnetwork(..., filter_by_ptm_site, include_infinite_fc, direction)
    Extract->>INDRA: getSubnetworkFromIndra(..., filter_by_ptm_site, include_infinite_fc, direction)
    INDRA-->>Extract: filtered subnetwork
    Extract-->>Server: network result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰 A tiny toggle, a secret door,
Advanced options tucked in store.
Three filters hop into the flow,
Through server paths they softly go.
Subnetworks bloom where rabbits sow!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately reflects the main change: setting up a new advanced options panel for subnetwork search filtering, which is evident across the UI, server, and test modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature-advanced-options

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.

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Namespacing Bug

The advanced options toggle calls shinyjs::toggle(id = "adv_panel") from within a module, but the UI element id is namespaced via ns("adv_panel"). This will likely prevent the panel from toggling unless the server uses the namespaced id (e.g., session$ns("adv_panel")).

observeEvent(input$toggle_adv, {
  toggle(id = "adv_panel", anim = TRUE)
})
Code Generation

The generated code appends direction = using the raw value from params$direction, which is a character string (both/up/down). Without quoting/escaping, the produced R code will be invalid (it will emit direction = both instead of direction = "both").

codes <- paste(codes, ",\n  filter_by_curation = ", params$filterByCuration, "\n", sep = "")
codes <- paste(codes, ",\n  filter_by_ptm_site = ", params$filter_by_ptm_site, "\n", sep = "")
codes <- paste(codes, ",\n  include_infinite_fc = ", params$include_infinite_fc, "\n", sep = "")
codes <- paste(codes, ",\n  direction = ", params$direction, "\n", sep = "")
Input Defaults

New parameters are passed through (filter_by_ptm_site, include_infinite_fc, direction) without req()/defaults/coercion. If any of these are temporarily NULL during initialization/reactivity, or if getSubnetworkFromIndra() doesn’t accept NULL, subnetwork extraction may fail; consider explicit defaults/coercion (e.g., isTRUE() for checkboxes).

  proteinIdType = req(input$proteinIdType),
  pValue = as.numeric(req(input$pValue)),
  evidence = as.numeric(req(input$evidence)),
  absLogFC = as.numeric(req(input$absLogFC)),
  statementTypes = statementTypes,
  sources = sources,
  selectedLabel = req(input$selectedLabel),
  selectedProteins = selectedProteins,
  filterByCuration = filterByCuration,
  filter_by_ptm_site = input$filter_by_ptm_site,
  include_infinite_fc = input$include_infinite_fc,
  direction = input$direction
)

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Toggle the namespaced panel id

In a Shiny module, DOM ids are namespaced, so toggling "adv_panel" directly may not
find the element. Toggle the namespaced id (e.g., via NS(id, ...) or
session$ns(...)) so the advanced panel reliably opens/closes.

R/module-visualize-network-server.R [395-397]

 observeEvent(input$toggle_adv, {
-  toggle(id = "adv_panel", anim = TRUE)
+  toggle(id = NS(id, "adv_panel"), anim = TRUE)
 })
Suggestion importance[1-10]: 8

__

Why: In a Shiny module, the UI element id is created via ns("adv_panel"), so calling toggle(id = "adv_panel") likely won’t match the DOM node and the advanced panel won’t open/close. Using a namespaced id (e.g., NS(id, "adv_panel") or session$ns("adv_panel")) fixes the module behavior.

Medium
Quote string values in generated code

params$direction is a character value, but the generated R code omits quotes,
producing invalid code like direction = both. Quote the value when pasting so the
output is executable.

R/module-visualize-network-server.R [565]

-codes <- paste(codes, ",\n  direction = ", params$direction, "\n", sep = "")
+codes <- paste0(codes, ",\n  direction = ", shQuote(params$direction), "\n")
Suggestion importance[1-10]: 6

__

Why: params$direction is a character (e.g., both/up/down), and emitting it without quotes makes the generated R code invalid (direction = both). Using shQuote(params$direction) produces executable code without changing runtime logic.

Low
Enforce stable input types

These inputs can be NULL before initialization or if the UI conditionally hides
them, which can break downstream filtering. Coerce checkboxes to strict logicals and
require direction to be present before use.

R/module-visualize-network-server.R [184-187]

 filterByCuration = filterByCuration,
-filter_by_ptm_site = input$filter_by_ptm_site,
-include_infinite_fc = input$include_infinite_fc,
-direction = input$direction
+filter_by_ptm_site = isTRUE(input$filter_by_ptm_site),
+include_infinite_fc = isTRUE(input$include_infinite_fc),
+direction = req(input$direction)
Suggestion importance[1-10]: 4

__

Why: Coercing checkbox inputs with isTRUE() can make downstream code more robust if these values ever come through as NULL. However, these inputs are always present in the UI (just hidden), so the practical impact is limited and req(input$direction) is likely unnecessary given the default selection.

Low

Copy link

@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: 3

Caution

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

⚠️ Outside diff range comments (1)
R/module-visualize-network-server.R (1)

214-229: ⚠️ Potential issue | 🔴 Critical

The MSstatsBioNet API does not document support for the three new parameters.

According to the official MSstatsBioNet package documentation, getSubnetworkFromIndra() does not include filter_by_ptm_site, include_infinite_fc, or direction parameters. Passing these undocumented arguments will cause a runtime error ("unused argument") unless your project depends on an unreleased or modified version of MSstatsBioNet. Confirm that the MSstatsBioNet version constraint in your DESCRIPTION file or package dependencies explicitly requires a version that supports these parameters, or remove them from the function call.

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

In `@R/module-visualize-network-server.R` around lines 214 - 229, The call to
getSubnetworkFromIndra inside extractSubnetwork passes three parameters that
MSstatsBioNet does not document (filter_by_ptm_site, include_infinite_fc,
direction); remove these three arguments from the getSubnetworkFromIndra(...)
invocation in extractSubnetwork or alternatively update the package
dependency/version in DESCRIPTION to a specific MSstatsBioNet release that
explicitly supports those parameters—search for the extractSubnetwork function
and the getSubnetworkFromIndra call to apply the change and keep the remaining
named arguments unchanged.
🧹 Nitpick comments (1)
R/module-visualize-network-ui.R (1)

260-260: Remove redundant useShinyjs() call.

useShinyjs() is already called in the main networkUI function at line 468. Calling it again inside createAdvancedOptionsCollapsible is redundant and can cause initialization issues or warnings. It should only be included once in the UI hierarchy.

♻️ Proposed fix
 createAdvancedOptionsCollapsible <- function(ns) {
   div(
     style = "margin-bottom: 15px;", 
     tagList(
-      useShinyjs(),
       actionLink(
         ns("toggle_adv"),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@R/module-visualize-network-ui.R` at line 260, Remove the redundant
useShinyjs() call inside createAdvancedOptionsCollapsible: locate the function
createAdvancedOptionsCollapsible and delete the useShinyjs() invocation so that
useShinyjs() is only called once in the top-level networkUI function; ensure no
other duplicate initializations remain in helper UI functions.
🤖 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/module-visualize-network-server.R`:
- Around line 563-565: The generated code writes params$direction without quotes
causing R to treat it as a symbol; update the string concatenation that builds
codes (the line referencing params$direction) to wrap the value in quotes (e.g.,
emit "direction = \"<value>\"" or use shQuote(params$direction)) so the produced
R code contains a quoted string ("both"/"up"/"down"); keep the other
concatenations unchanged.
- Around line 395-397: The toggle call inside observeEvent(input$toggle_adv)
uses the un-namespaced id "adv_panel" and must use the module namespace: change
the toggle invocation in the observeEvent (where input$toggle_adv is handled) to
call toggle(id = session$ns("adv_panel"), anim = TRUE) so it targets the
ns("adv_panel") element created in the UI within this module.
- Around line 214-216: Update the test calls to match the new extractSubnetwork
signature: in the tests that call extractSubnetwork (from
tests/testthat/test_network_visualization.R around the earlier failing calls),
pass the three new arguments filter_by_ptm_site, include_infinite_fc, and
direction (e.g., FALSE, FALSE, "both") as the 9th–11th parameters so the call
becomes extractSubnetwork(annotated_df, pValue, evidence, statementTypes,
sources, absLogFC, selectedProteins, filterByCuration, FALSE, FALSE, "both");
ensure all test invocations of extractSubnetwork use these three additional
arguments.

---

Outside diff comments:
In `@R/module-visualize-network-server.R`:
- Around line 214-229: The call to getSubnetworkFromIndra inside
extractSubnetwork passes three parameters that MSstatsBioNet does not document
(filter_by_ptm_site, include_infinite_fc, direction); remove these three
arguments from the getSubnetworkFromIndra(...) invocation in extractSubnetwork
or alternatively update the package dependency/version in DESCRIPTION to a
specific MSstatsBioNet release that explicitly supports those parameters—search
for the extractSubnetwork function and the getSubnetworkFromIndra call to apply
the change and keep the remaining named arguments unchanged.

---

Nitpick comments:
In `@R/module-visualize-network-ui.R`:
- Line 260: Remove the redundant useShinyjs() call inside
createAdvancedOptionsCollapsible: locate the function
createAdvancedOptionsCollapsible and delete the useShinyjs() invocation so that
useShinyjs() is only called once in the top-level networkUI function; ensure no
other duplicate initializations remain in helper UI functions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 813e9dc4-43e2-4e66-8f6f-bbd9d2b1157c

📥 Commits

Reviewing files that changed from the base of the PR and between 520b3e4 and a514f14.

📒 Files selected for processing (4)
  • NAMESPACE
  • R/MSstatsShiny.R
  • R/module-visualize-network-server.R
  • R/module-visualize-network-ui.R

Copy link

@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

🧹 Nitpick comments (1)
R/module-visualize-network-server.R (1)

184-187: Consider adding defensive NULL handling for new parameters.

The existing filterByCuration parameter has explicit NULL handling (Lines 169-173), but the new parameters are read directly from input without defaults. If the UI inputs haven't been initialized or are conditionally hidden, these could be NULL.

♻️ Suggested defensive handling
     filterByCuration = filterByCuration,
-    filter_by_ptm_site = input$filter_by_ptm_site,
-    include_infinite_fc = input$include_infinite_fc,
-    direction = input$direction
+    filter_by_ptm_site = if (is.null(input$filter_by_ptm_site)) FALSE else input$filter_by_ptm_site,
+    include_infinite_fc = if (is.null(input$include_infinite_fc)) FALSE else input$include_infinite_fc,
+    direction = if (is.null(input$direction)) "both" else input$direction
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@R/module-visualize-network-server.R` around lines 184 - 187, The new
parameters (filter_by_ptm_site, include_infinite_fc, direction) should get the
same defensive NULL handling as filterByCuration: when building the list passed
into the module, replace direct input reads with guarded expressions (e.g., for
filter_by_ptm_site and include_infinite_fc coerce NULL to FALSE, and for
direction coerce NULL to a sensible default such as "both" or the module's
expected default) so the code using filterByCuration, filter_by_ptm_site,
include_infinite_fc, and direction never receives NULL; implement these guards
using if (is.null(input$...)) <default> else input$... or a coalescing helper
before passing them through.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/testthat/test_network_visualization.R`:
- Around line 182-186: The error test still calls extractSubnetwork with the old
8-argument signature (see the failing call using create_mock_annotated_data()) —
update that test to call extractSubnetwork with the new 11 parameters (add the
three new params: filterByCuration, filter_by_ptm_site, include_infinite_fc) in
the same order used elsewhere (e.g., direction = "both"); ensure the error
handling invocation matches the updated signature of extractSubnetwork so the
test exercises the intended error path.

---

Nitpick comments:
In `@R/module-visualize-network-server.R`:
- Around line 184-187: The new parameters (filter_by_ptm_site,
include_infinite_fc, direction) should get the same defensive NULL handling as
filterByCuration: when building the list passed into the module, replace direct
input reads with guarded expressions (e.g., for filter_by_ptm_site and
include_infinite_fc coerce NULL to FALSE, and for direction coerce NULL to a
sensible default such as "both" or the module's expected default) so the code
using filterByCuration, filter_by_ptm_site, include_infinite_fc, and direction
never receives NULL; implement these guards using if (is.null(input$...))
<default> else input$... or a coalescing helper before passing them through.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 42d9ab12-1543-4dd5-b461-a430dee35889

📥 Commits

Reviewing files that changed from the base of the PR and between a514f14 and 4122b7c.

📒 Files selected for processing (2)
  • R/module-visualize-network-server.R
  • tests/testthat/test_network_visualization.R

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant