Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ importFrom(DT,datatable)
importFrom(DT,renderDT)
importFrom(DT,renderDataTable)
importFrom(Hmisc,describe)
importFrom(MSstatsBig,bigDIANNtoMSstatsFormat)
importFrom(MSstatsBig,bigSpectronauttoMSstatsFormat)
importFrom(MSstatsBioNet,annotateProteinInfoFromIndra)
importFrom(MSstatsBioNet,generateCytoscapeConfig)
importFrom(MSstatsBioNet,getSubnetworkFromIndra)
Expand Down
1 change: 1 addition & 0 deletions R/MSstatsShiny.R
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#' @importFrom dplyr `%>%` filter summarise n_distinct group_by ungroup select n mutate
#' @importFrom tidyr unite
#' @importFrom MSstatsConvert MSstatsLogsSettings
#' @importFrom MSstatsBig bigDIANNtoMSstatsFormat bigSpectronauttoMSstatsFormat
#' @importFrom MSstatsPTM dataProcessPlotsPTM groupComparisonPlotsPTM MaxQtoMSstatsPTMFormat PDtoMSstatsPTMFormat FragPipetoMSstatsPTMFormat SkylinetoMSstatsPTMFormat SpectronauttoMSstatsPTMFormat
#' @importFrom utils capture.output head packageVersion read.csv read.delim write.csv
#' @importFrom stats aggregate
Expand Down
52 changes: 50 additions & 2 deletions R/module-loadpage-server.R
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ loadpageServer <- function(id, parent_session, is_web_server = FALSE) {
})

# Render just the filename for user feedback in the UI.
output$specdata_big_path <- renderPrint({
output$big_file_path <- renderPrint({
req(nrow(local_file_info()) > 0)
cat(local_file_info()$name)
})
Expand Down Expand Up @@ -72,6 +72,52 @@ loadpageServer <- function(id, parent_session, is_web_server = FALSE) {
tagList(ui_elements, create_separator_buttons(session$ns, "sep_specdata"))
})

output$diann_header_ui <- renderUI({
req(input$filetype == 'diann', input$BIO != 'PTM')
create_diann_header()
})

output$diann_file_selection_ui <- renderUI({
req(input$filetype == 'diann', input$BIO != 'PTM')

ui_elements <- tagList()

if (!is_web_server) {
ui_elements <- tagList(ui_elements, create_diann_mode_selector(session$ns, isTRUE(input$big_file_diann)))

if (isTRUE(input$big_file_diann)) {
ui_elements <- tagList(ui_elements, create_diann_large_file_ui(session$ns))
} else {
ui_elements <- tagList(ui_elements, create_diann_standard_ui(session$ns))
}
} else {
ui_elements <- tagList(ui_elements, create_diann_standard_ui(session$ns))
}

tagList(ui_elements, create_separator_buttons(session$ns, "sep_dianndata"))
})

output$diann_options_ui <- renderUI({
req(input$filetype == 'diann', input$BIO != 'PTM')

if (!is_web_server && isTRUE(input$big_file_diann)) {
mbr_def <- if (is.null(input$diann_MBR)) TRUE else input$diann_MBR
quant_col_def <- if (is.null(input$diann_quantificationColumn)) "Fragment.Quant.Corrected" else input$diann_quantificationColumn

max_feature_def <- if (is.null(input$max_feature_count)) 100 else input$max_feature_count
unique_peps_def <- if (is.null(input$filter_unique_peptides)) FALSE else input$filter_unique_peptides
agg_psms_def <- if (is.null(input$aggregate_psms)) FALSE else input$aggregate_psms
few_obs_def <- if (is.null(input$filter_few_obs)) FALSE else input$filter_few_obs

tagList(
create_diann_large_filter_options(session$ns, mbr_def, quant_col_def),
create_diann_large_bottom_ui(session$ns, max_feature_def, unique_peps_def, agg_psms_def, few_obs_def)
)
} else {
NULL
}
})

output$spectronaut_options_ui <- renderUI({
req(input$filetype == 'spec', input$BIO != 'PTM')

Expand Down Expand Up @@ -195,7 +241,9 @@ loadpageServer <- function(id, parent_session, is_web_server = FALSE) {
enable("proceed1")
}
} else if (input$filetype == "diann") {
if(!is.null(input$dianndata) && !is.null(input$sep_dianndata)) { # && !is.null(input$annot)
diann_regular_file_ok <- !isTRUE(input$big_file_diann) && !is.null(input$dianndata)
diann_big_file_ok <- isTRUE(input$big_file_diann) && length(local_big_file_path()) > 0
if((diann_regular_file_ok || diann_big_file_ok) && !is.null(input$sep_dianndata)) {
enable("proceed1")
}
}
Expand Down
60 changes: 54 additions & 6 deletions R/module-loadpage-ui.R
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,10 @@ create_skyline_uploads <- function(ns) {
#' Create DIANN file uploads
#' @noRd
create_diann_uploads <- function(ns) {
conditionalPanel(
condition = "input['loadpage-filetype'] == 'diann' && input['loadpage-BIO'] != 'PTM'",
h4("4. Upload MSstats report from DIANN"),
fileInput(ns('dianndata'), "", multiple = FALSE, accept = NULL),
create_separator_buttons(ns, "sep_dianndata")
tagList(
uiOutput(ns("diann_header_ui")),
uiOutput(ns("diann_file_selection_ui")),
uiOutput(ns("diann_options_ui"))
)
}

Expand All @@ -295,24 +294,51 @@ create_spectronaut_header <- function() {
h4("4. Upload MSstats scheme output from Spectronaut")
}

#' Create DIANN header
#' @noRd
create_diann_header <- function() {
h4("4. Upload MSstats report from DIANN")
}

#' Create Spectronaut mode selector (Local only)
#' @noRd
create_spectronaut_mode_selector <- function(ns, selected = FALSE) {
checkboxInput(ns("big_file_spec"), "Large file mode", value = selected)
}

#' Create DIANN mode selector (Local only)
#' @noRd
create_diann_mode_selector <- function(ns, selected = FALSE) {
checkboxInput(ns("big_file_diann"), "Large file mode", value = selected)
}

#' Create Spectronaut standard file input
#' @noRd
create_spectronaut_standard_ui <- function(ns) {
fileInput(ns('specdata'), "", multiple = FALSE, accept = NULL)
}

#' Create DIANN standard file input
#' @noRd
create_diann_standard_ui <- function(ns) {
fileInput(ns('dianndata'), "", multiple = FALSE, accept = NULL)
}

#' Create Spectronaut large file selection UI
#' @noRd
create_spectronaut_large_file_ui <- function(ns) {
tagList(
shinyFiles::shinyFilesButton(ns("big_file_browse"), "Browse for local file...", "Please select a file", multiple = FALSE),
verbatimTextOutput(ns("specdata_big_path"))
verbatimTextOutput(ns("big_file_path"))
)
}

#' Create DIANN large file selection UI
#' @noRd
create_diann_large_file_ui <- function(ns) {
tagList(
shinyFiles::shinyFilesButton(ns("big_file_browse"), "Browse for local file...", "Please select a file", multiple = FALSE),
verbatimTextOutput(ns("big_file_path"))
)
}

Expand All @@ -328,6 +354,17 @@ create_spectronaut_large_filter_options <- function(ns, excluded_def = FALSE, id
)
}

#' Create DIANN large file filter options
#' @noRd
create_diann_large_filter_options <- function(ns, mbr_def = TRUE, quant_col_def = "Fragment.Quant.Corrected") {
tagList(
tags$hr(),
h4("Options for large file processing"),
checkboxInput(ns("diann_MBR"), "MBR Enabled", value = mbr_def),
textInput(ns("diann_quantificationColumn"), "Quantification Column", value = quant_col_def)
)
}

#' Create Spectronaut Q-value cutoff input
#' @noRd
create_spectronaut_qvalue_cutoff_ui <- function(ns, cutoff_def = 0.01) {
Expand All @@ -345,6 +382,17 @@ create_spectronaut_large_bottom_ui <- function(ns, max_feature_def = 20, unique_
)
}

#' Create DIANN large file options (Bottom part)
#' @noRd
create_diann_large_bottom_ui <- function(ns, max_feature_def = 100, unique_peps_def = FALSE, agg_psms_def = FALSE, few_obs_def = FALSE) {
tagList(
numericInput(ns("max_feature_count"), "Max feature count", value = max_feature_def, min = 1),
checkboxInput(ns("filter_unique_peptides"), "Use unique peptides", value = unique_peps_def),
checkboxInput(ns("aggregate_psms"), "Aggregate PSMs to peptides", value = agg_psms_def),
checkboxInput(ns("filter_few_obs"), "Filter features with few observations", value = few_obs_def)
)
}

#' Create PTM FragPipe uploads
#' @noRd
create_ptm_fragpipe_uploads <- function(ns) {
Expand Down
145 changes: 124 additions & 21 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ getData <- function(input) {
shinybusy::update_modal_spinner(text = "Processing large Spectronaut file...")

# Call the big file conversion function from MSstatsConvert
converted_data <- MSstatsBig::bigSpectronauttoMSstatsFormat(
converted_data <- bigSpectronauttoMSstatsFormat(
input_file = local_big_file_path,
output_file_name = "output_file.csv",
backend = "arrow",
Expand Down Expand Up @@ -592,10 +592,70 @@ getData <- function(input) {
}
}
else if(input$filetype == 'diann') {
if (isTRUE(input$big_file_diann)) {
# Logic for big DIANN files
# Parse the file path from shinyFiles input
volumes <- shinyFiles::getVolumes()()
path_info <- shinyFiles::parseFilePaths(volumes, input$big_file_browse)
local_big_file_path <- if (nrow(path_info) > 0) path_info$datapath else NULL

if (!is.numeric(input$max_feature_count) || is.na(input$max_feature_count) || input$max_feature_count <= 0) {
showNotification("Error: max_feature_count must be a positive number.", type = "error")
shinybusy::remove_modal_spinner()
return(NULL)
}

if (is.null(local_big_file_path) || !file.exists(local_big_file_path)) {
showNotification("Error: The selected file does not exist or is not readable.", type = "error")
shinybusy::remove_modal_spinner()
return(NULL)
}

shinybusy::update_modal_spinner(text = "Processing large DIANN file...")

# Call the big file conversion function from MSstatsConvert
converted_data <- bigDIANNtoMSstatsFormat(
input_file = local_big_file_path,
Copy link
Contributor

Choose a reason for hiding this comment

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

Two things:

  1. The annotation file will need to be incorporated into this function
  2. Add bigDIANNtoMSstatsFormat and bigSpectronauttoMSstatsFormat as dependencies in this file. And then you won't need to do MSstatsBig:: when calling the function.

annotation = getAnnot(input),
output_file_name = "output_file.csv",
backend = "arrow",
MBR = isTRUE(input$diann_MBR),
quantificationColumn = input$diann_quantificationColumn,
max_feature_count = input$max_feature_count,
filter_unique_peptides = input$filter_unique_peptides,
aggregate_psms = input$aggregate_psms,
filter_few_obs = input$filter_few_obs
)

# Attempt to load the data into memory.
mydata <- tryCatch({
dplyr::collect(converted_data)
}, error = function(e) {
showNotification(
paste("Memory Error: The dataset is too large to process in-memory.", e$message),
type = "error",
duration = NULL
)
return(NULL)
})

if (is.null(mydata)) {
shinybusy::remove_modal_spinner()
return(NULL)
}
Comment on lines +595 to +645
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

rg -n 'big_file_browse' --type=r -C2

Repository: Vitek-Lab/MSstatsShiny

Length of output: 2953


🏁 Script executed:

rg -n 'bigDIANNtoMSstatsFormat' --type=r -C5

Repository: Vitek-Lab/MSstatsShiny

Length of output: 4398


🏁 Script executed:

sed -n '938,955p' R/utils.R

Repository: Vitek-Lab/MSstatsShiny

Length of output: 1306


🏁 Script executed:

# Check if both Spectronaut and DIANN big file UIs are conditionally rendered or always active
rg -n 'create_spectronaut_large_file_ui|create_diann_large_file_ui' -C3

Repository: Vitek-Lab/MSstatsShiny

Length of output: 2795


Generated code for DIANN big-file conversion is missing the annotation parameter.

The runtime code at line 619 correctly includes annotation = getAnnot(input) in the bigDIANNtoMSstatsFormat() call. However, the generated code (lines 938–955 in the getDataCode function) omits this parameter. The generated code should include:

codes = paste(codes, "  annotation = \"insert your annotation file path\",\n", sep = "")

The shared input$big_file_browse input ID is appropriate—both Spectronaut and DIANN large-file UIs are conditionally rendered (only one active at a time based on input$big_file_spec or input$big_file_diann), so the single shinyFileChoose binding works correctly.

🤖 Prompt for AI Agents
In `@R/utils.R` around lines 595 - 645, The generated code in getDataCode omits
the annotation argument when emitting the bigDIANNtoMSstatsFormat() call; update
getDataCode to include a line that appends the annotation parameter (e.g., codes
= paste(codes, "  annotation = \"insert your annotation file path\",\\n", sep =
"")) so the generated call matches the runtime call (bigDIANNtoMSstatsFormat
with annotation = getAnnot(input)); ensure the string is properly escaped and
includes the trailing comma/newline and references input$big_file_browse/shared
UI as before.

} else {
if (getFileExtension(input$dianndata$name) %in% c("parquet", "pq")) {
data = read_parquet(input$dianndata$datapath)
} else {
data = read.csv(input$dianndata$datapath, sep=input$sep_dianndata)
sep = input$sep_dianndata
if(is.null(sep)) {
sep = "\t"
}
if (sep == "\t") {
data = read.delim(input$dianndata$datapath)
} else {
data = read.csv(input$dianndata$datapath, sep = sep)
}
}

qvalue_cutoff = 0.01
Expand All @@ -620,6 +680,7 @@ getData <- function(input) {
use_log_file = FALSE,
quantificationColumn = quantificationColumn
)
}
print("Mydata from mstats")
print(mydata)
}
Expand Down Expand Up @@ -721,7 +782,8 @@ library(MSstatsTMT)
library(MSstatsPTM)\n", sep = "")
codes = paste(codes, "\n# Package versions\n# MSstats version ", packageVersion("MSstats"),
"\n# MSstatsTMT version ", packageVersion("MSstatsTMT"),
"\n# MSstatsPTM version ", packageVersion("MSstatsPTM"), sep = "")
"\n# MSstatsPTM version ", packageVersion("MSstatsPTM"),
"\n# MSstatsBig version ", tryCatch(packageVersion("MSstatsBig"), error = function(e) "Not Installed"), sep = "")
codes = paste(codes, "\n\n# Read data\n", sep = "")
if(input$filetype == 'sample') {
if(input$BIO != "PTM" && input$DDA_DIA =='LType' && input$LabelFreeType == "SRM_PRM") {
Expand Down Expand Up @@ -843,27 +905,68 @@ library(MSstatsPTM)\n", sep = "")
}
else if(input$filetype == 'spec') {

codes = paste(codes, "data = read.csv(\"insert your MSstats scheme output from Spectronaut filepath\", header = TRUE, sep = ",input$sep_specdata,")\nannot_file = read.csv(\"insert your annotation filepath\", sep='\t')#Optional\n"
, sep = "")

codes = paste(codes, "data = SpectronauttoMSstatsFormat(data,
annotation = annot_file #Optional,
filter_with_Qvalue = TRUE, ## same as default
qvalue_cutoff = 0.01, ## same as default
fewMeasurements=\"remove\",
removeProtein_with1Feature = TRUE,
use_log_file = FALSE)\n", sep = "")
if (isTRUE(input$big_file_spec)) {
codes = paste(codes, "library(MSstatsBig)\n", sep = "")
codes = paste(codes, "data = MSstatsBig::bigSpectronauttoMSstatsFormat(\n", sep = "")
codes = paste(codes, " input_file = \"insert your large Spectronaut file path\",\n", sep = "")
codes = paste(codes, " output_file_name = \"output_file.csv\",\n", sep = "")
codes = paste(codes, " backend = \"arrow\",\n", sep = "")
codes = paste(codes, " filter_by_excluded = ", input$filter_by_excluded, ",\n", sep = "")
codes = paste(codes, " filter_by_identified = ", input$filter_by_identified, ",\n", sep = "")
codes = paste(codes, " filter_by_qvalue = ", input$filter_by_qvalue, ",\n", sep = "")
codes = paste(codes, " qvalue_cutoff = ", input$qvalue_cutoff, ",\n", sep = "")
codes = paste(codes, " max_feature_count = ", input$max_feature_count, ",\n", sep = "")
codes = paste(codes, " filter_unique_peptides = ", input$filter_unique_peptides, ",\n", sep = "")
codes = paste(codes, " aggregate_psms = ", input$aggregate_psms, ",\n", sep = "")
codes = paste(codes, " filter_few_obs = ", input$filter_few_obs, "\n", sep = "")
codes = paste(codes, ")\n", sep = "")
codes = paste(codes, "data = dplyr::collect(data)\n", sep = "")
} else {
codes = paste(codes, "data = read.csv(\"insert your MSstats scheme output from Spectronaut filepath\", header = TRUE, sep = ",input$sep_specdata,")\nannot_file = read.csv(\"insert your annotation filepath\", sep='\t')#Optional\n"
, sep = "")
codes = paste(codes, "data = SpectronauttoMSstatsFormat(data,
annotation = annot_file #Optional,
filter_with_Qvalue = TRUE, ## same as default
qvalue_cutoff = 0.01, ## same as default
fewMeasurements=\"remove\",
removeProtein_with1Feature = TRUE,
use_log_file = FALSE)\n", sep = "")
}
}
else if(input$filetype == 'diann') {

codes = paste(codes, "data = read.csv(\"insert your MSstats scheme output from DIANN filepath\", header = TRUE, sep = '\\t')\nannot_file = read.csv(\"insert your annotation filepath\")#Optional\n"
, sep = "")

codes = paste(codes, "data = DIANNtoMSstatsFormat(data,
annotation = annot_file, #Optional
qvalue_cutoff = 0.01, ## same as default
removeProtein_with1Feature = TRUE,
use_log_file = FALSE)\n", sep = "")
if (isTRUE(input$big_file_diann)) {
codes = paste(codes, "library(MSstatsBig)\n", sep = "")
codes = paste(codes, "data = MSstatsBig::bigDIANNtoMSstatsFormat(\n", sep = "")
codes = paste(codes, " input_file = \"insert your large DIANN file path\",\n", sep = "")
codes = paste(codes, " output_file_name = \"output_file.csv\",\n", sep = "")
codes = paste(codes, " backend = \"arrow\",\n", sep = "")
codes = paste(codes, " MBR = ", isTRUE(input$diann_MBR), ",\n", sep = "")
codes = paste(codes, " quantificationColumn = \"", input$diann_quantificationColumn, "\",\n", sep = "")
codes = paste(codes, " max_feature_count = ", input$max_feature_count, ",\n", sep = "")
codes = paste(codes, " filter_unique_peptides = ", input$filter_unique_peptides, ",\n", sep = "")
codes = paste(codes, " aggregate_psms = ", input$aggregate_psms, ",\n", sep = "")
codes = paste(codes, " filter_few_obs = ", input$filter_few_obs, "\n", sep = "")
codes = paste(codes, ")\n", sep = "")
codes = paste(codes, "data = dplyr::collect(data)\n", sep = "")
Comment on lines +938 to +951
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Generated code for big DIANN is missing the annotation parameter.

The runtime call at line 619 passes annotation = getAnnot(input), but the code snippet emitted here omits it. Users attempting to reproduce the analysis with the generated code will get incorrect results or an error if annotation is required.

Proposed fix
         codes = paste(codes, "data = MSstatsBig::bigDIANNtoMSstatsFormat(\n", sep = "")
         codes = paste(codes, "  input_file = \"insert your large DIANN file path\",\n", sep = "")
+        codes = paste(codes, "  annotation = read.csv(\"insert your annotation filepath\"),\n", sep = "")
         codes = paste(codes, "  output_file_name = \"output_file.csv\",\n", sep = "")
🤖 Prompt for AI Agents
In `@R/utils.R` around lines 938 - 951, The generated big DIANN code omits the
annotation argument for MSstatsBig::bigDIANNtoMSstatsFormat; update the code
building block that constructs the bigDIANN call (where codes is appended with
"data = MSstatsBig::bigDIANNtoMSstatsFormat(") to include annotation =
getAnnot(input) as a parameter (matching how the runtime uses annotation =
getAnnot(input)), ensuring proper comma placement and quoting/concatenation
consistent with the surrounding parameters (e.g., alongside input_file, backend,
MBR, quantificationColumn, etc.) so the emitted call contains annotation =
getAnnot(input).

} else {
sep = input$sep_dianndata
if(is.null(sep)) {
sep = "\t"
}

if (sep == "\t") {
codes = paste(codes, "data = read.delim(\"insert your MSstats scheme output from DIANN filepath\")\nannot_file = read.csv(\"insert your annotation filepath\")#Optional\n", sep = "")
} else {
codes = paste(codes, "data = read.csv(\"insert your MSstats scheme output from DIANN filepath\", header = TRUE, sep = '", sep, "')\nannot_file = read.csv(\"insert your annotation filepath\")#Optional\n", sep = "")
}

codes = paste(codes, "data = DIANNtoMSstatsFormat(data,
annotation = annot_file, #Optional
qvalue_cutoff = 0.01, ## same as default
removeProtein_with1Feature = TRUE,
use_log_file = FALSE)\n", sep = "")
}
}
else if(input$filetype == 'open') {

Expand Down
Loading
Loading