Bioconductor / Contributions

Contribute Packages to Bioconductor
131 stars 33 forks source link

CRISPRball #3163

Closed j-andrews7 closed 7 months ago

j-andrews7 commented 9 months ago

Update the following URL to point to the GitHub repository of the package you wish to submit to Bioconductor

Confirm the following by editing each check box to '[x]'

I am familiar with the essential aspects of Bioconductor software management, including:

For questions/help about the submission process, including questions about the output of the automatic reports generated by the SPB (Single Package Builder), please use the #package-submission channel of our Community Slack. Follow the link on the home page of the Bioconductor website to sign up.

bioc-issue-bot commented 9 months ago

Hi @j-andrews7

Thanks for submitting your package. We are taking a quick look at it and you will hear back from us soon.

The DESCRIPTION file for this package is:

Package: CRISPRball
Title: Shiny Application for Interactive CRISPR Screen Visualization, Exploration, Comparison, and Filtering
Version: 0.99.0
Authors@R: 
    c(person(given = "Jared",
 family = "Andrews",
 role = c("aut", "cre"),
 email = "jared.andrews07@gmail.com",
 comment = c(ORCID = "0000-0002-0780-6248")),
        person(given = "Jacob",
  family = "Steele",
  role = "ctb",
  comment = c(ORCID = "0000-0001-9924-2226")))
Description: A Shiny application for visualization, exploration, comparison, 
    and filtering of CRISPR screens analyzed with MAGeCK RRA or MLE. Features
    include interactive plots with on-click labeling, full customization of plot aesthetics,
    data upload and/or download, and much more. Quickly and easily explore your CRISPR screen
    results and generate publication-quality figures in seconds.
License: MIT + file LICENSE
URL: https://github.com/j-andrews7/CRISPRball
BugReports: https://support.bioconductor.org/
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.3
biocViews: 
    Software,
    ShinyApps, 
    CRISPR,
    QualityControl,
    Visualization,
    GUI
Imports: 
    DT,
    shiny,
    grid,
    ComplexHeatmap,
    InteractiveComplexHeatmap,
    graphics,
    stats,
    ggplot2,
    plotly,
    shinyWidgets,
    shinycssloaders,
    shinyjqui,
    dittoSeq,
    matrixStats,
    colourpicker,
    shinyjs,
    MAGeCKFlute,
    circlize,
    PCAtools,
    utils,
    grDevices,
    htmlwidgets
Suggests:
    BiocStyle,
    msigdbr,
    depmap,
    pool,
    RSQLite,
    mygene,
    testthat (>= 3.0.0),
    knitr,
    rmarkdown
Depends:
    R (>= 4.3.0),
    shinyBS
LazyData: false
Config/testthat/edition: 3
VignetteBuilder: knitr
bioc-issue-bot commented 9 months ago

Your package has been added to git.bioconductor.org to continue the pre-review process. A build report will be posted shortly. Please fix any ERROR and WARNING in the build report before a reviewer is assigned or provide a justification on why you feel the ERROR or WARNING should be granted an exception.

IMPORTANT: Please read this documentation for setting up remotes to push to git.bioconductor.org. All changes should be pushed to git.bioconductor.org moving forward. It is required to push a version bump to git.bioconductor.org to trigger a new build report.

Bioconductor utilized your github ssh-keys for git.bioconductor.org access. To manage keys and future access you may want to active your Bioconductor Git Credentials Account

bioc-issue-bot commented 9 months ago

Dear Package contributor,

This is the automated single package builder at bioconductor.org.

Your package has been built on the Bioconductor Build System.

Congratulations! The package built without errors or warnings on all platforms.

Please see the build report for more details.

The following are build products from R CMD build on the Bioconductor Build System: Linux (Ubuntu 22.04.2 LTS): CRISPRball_0.99.0.tar.gz macOS 12.6.5 Monterey: CRISPRball_0.99.0.tar.gz

Links above active for 21 days.

Remember: if you submitted your package after July 7th, 2020, when making changes to your repository push to git@git.bioconductor.org:packages/CRISPRball to trigger a new build. A quick tutorial for setting up remotes and pushing to upstream can be found here.

bioc-issue-bot commented 9 months ago

A reviewer has been assigned to your package for an indepth review. Please respond accordingly to any further comments from the reviewer.

j-andrews7 commented 8 months ago

Any shot we think this gets reviewed by the 18th? I know the review burden at this point is definitely a crunch.

jianhong commented 8 months ago

Package 'CRISPRball' Review

Thank you for submitting your package to Bioconductor. The package passed check and build. However there are several things need to be fixed. Please try to answer the comments line by line when you are ready for a second review. Code: Note: please consider; Important: must be addressed.

The NAMESPACE file

bioc-issue-bot commented 8 months ago

Received a valid push on git.bioconductor.org; starting a build for commit id: 393d11ba53ee79d3e96c12122b886f7f0fbc46e6

bioc-issue-bot commented 8 months ago

Dear Package contributor,

This is the automated single package builder at bioconductor.org.

Your package has been built on the Bioconductor Build System.

Congratulations! The package built without errors or warnings on all platforms.

Please see the build report for more details.

The following are build products from R CMD build on the Bioconductor Build System: Linux (Ubuntu 22.04.2 LTS): CRISPRball_0.99.1.tar.gz macOS 12.6.5 Monterey: CRISPRball_0.99.1.tar.gz

Links above active for 21 days.

Remember: if you submitted your package after July 7th, 2020, when making changes to your repository push to git@git.bioconductor.org:packages/CRISPRball to trigger a new build. A quick tutorial for setting up remotes and pushing to upstream can be found here.

j-andrews7 commented 8 months ago

Many thanks for the review @jianhong. I have tried to address most of the points:

The NAMESPACE file

Remove the duplicated import. in line 20 import(DT) in line 21 import(ggplot2) in line 22 import(shiny, except = c(dataTableOutput, renderDataTable)) in line 23 import(shiny, except = c(dataTableOutput, renderDataTable))

These have been removed.

R code

Important:is() or inherits() instead of class().

This has been fixed.

NOTE: :: is not suggested in source code unless you can make sure all the packages are imported. Some people think it is better to keep ::. However please note that you need to manully double check the import items when you make any change in the DESCRIPTION file during development. My recommendation is to remove one or two repeats to force the dependency check.

These were removed where appropriate. A few are still retained for dealing with the DepMap SQL database, but they are preceded by a dependency check.

NOTE: Vectorize: for loops present, try to replace them by *apply funcitons. In file R/CRISPRball.R: at line 255 found ' for (tabname in defaultDisabledTabs) {' In file R/plotting_gene_sgrna.R: at line 181 found ' for (featset in highlight.featsets) {' at line 289 found ' for (n in hover.info) {' at line 534 found ' for (featset in highlight.featsets) {' at line 651 found ' for (n in hover.info) {' at line 890 found ' for (featset in highlight.featsets) {' at line 993 found ' for (n in hover.info) {' In file R/plotting_qc.R: at line 132 found ' for (i in 2:ncol(mat)) {' at line 354 found ' for (n in hover.info) {' In file R/utils_data_upload.R: at line 129 found ' for (sample in samples) {'

All but one of these has been replaced by lapply.

Important: Functional programming: code repetition. repetition in .create_gene_outputs and .create_sgrna_outputs in .create_gene_outputs line 1: output, robjects) line 2:{ line 3: output$gene.term.options <- renderUI({ line 4: req(robjects$set1.genes) line 5: df <- robjects$set1.genes line 36: } line 37: DT::datatable(df, rownames = FALSE, filter = "top", extensions = c("Buttons"), line 38: caption = paste0(input$gene.sel1, " Gene Summary"), line 39: options = list(search = list(regex = TRUE), pageLength = 10, line 40: dom = "Blfrtip", buttons = c("copy", "csv", "excel", line 41: "pdf", "print"), columnDefs = list(list(visible = FALSE, line 42: targets = target)))) %>% DT::formatStyle(0, line 43: target = "row", lineHeight = "50%") line 44: }) line 114: fig line 115: }) line 116: output$gene1.rank <- renderPlotly({ line 117: req(robjects$set1.genes, input$gene.esterm) line 118: input$rank.update line 119: df <- robjects$set1.genes line 256: }) line 257: output$gene2.summary <- renderDT(server = FALSE, { line 258: req(robjects$set2.genes) line 259: df <- robjects$set2.genes line 268: DT::datatable(df, rownames = FALSE, filter = "top", extensions = c("Buttons"), line 269: caption = paste0(input$gene.sel2, " Gene Summary"), line 270: options = list(search = list(regex = TRUE), dom = "Blfrtip", line 271: buttons = c("copy", "csv", "excel", "pdf", "print"), line 272: pageLength = 10, columnDefs = list(list(visible = FALSE, line 273: targets = target)))) %>% DT::formatStyle(0, line 274: target = "row", lineHeight = "50%") line 275: }) line 345: fig line 346: }) line 347: output$gene2.rank <- renderPlotly({ line 348: req(robjects$set2.genes, input$gene.esterm) line 349: input$rank.update in .create_sgrna_outputs line 1: output, robjects) line 2:{ line 3: output$sgrna.rank.options <- renderUI({ line 4: req(robjects$set1.sgrnas) line 5: df <- robjects$set1.sgrnas line 8: }) line 9: output$sgrna1.summary <- renderDT(server = FALSE, { line 10: req(robjects$set1.sgrnas) line 11: df <- robjects$set1.sgrnas line 12: DT::datatable(df, rownames = FALSE, filter = "top", extensions = c("Buttons"), line 13: caption = paste0(input$sgrna.sel1, " sgRNA Summary"), line 14: options = list(search = list(regex = TRUE), pageLength = 10, line 15: dom = "Blfrtip", buttons = c("copy", "csv", "excel", line 25: fig line 26: }) line 27: output$sgrna1.rank <- renderPlotly({ line 28: req(robjects$set1.sgrnas, input$sgrna.rankby) line 29: input$rank.update line 30: df <- robjects$set1.sgrnas line 63: " sgRNA Details"), options = list(pageLength = 10, line 64: dom = "Blfrtip", buttons = c("copy", "csv", "excel", line 65: "pdf", "print"), columnDefs = list(list(visible = FALSE, line 66: targets = target)))) %>% DT::formatStyle(0, line 67: target = "row", lineHeight = "50%") line 68: }) line 69: output$sgrna2.summary <- renderDT(server = FALSE, { line 70: req(robjects$set2.sgrnas) line 71: df <- robjects$set2.sgrnas line 72: DT::datatable(df, rownames = FALSE, filter = "top", extensions = c("Buttons"), line 73: caption = paste0(input$sgrna.sel2, " sgRNA Summary"), line 74: options = list(search = list(regex = TRUE), pageLength = 10, line 75: dom = "Blfrtip", buttons = c("copy", "csv", "excel", line 85: fig line 86: }) line 87: output$sgrna2.rank <- renderPlotly({ line 88: req(robjects$set2.sgrnas, input$sgrna.rankby) line 89: input$rank.update line 90: df <- robjects$set2.sgrnas line 123: " sgRNA Details"), options = list(pageLength = 10, line 124: dom = "Blfrtip", buttons = c("copy", "csv", "excel", line 125: "pdf", "print"), columnDefs = list(list(visible = FALSE, line 126: targets = target)))) %>% DT::formatStyle(0, line 127: target = "row", lineHeight = "50%") line 128: }) repetition in .create_tab_comparison and .create_tab_gene in .create_tab_comparison line 16: step = 0.05, value = 0.5))), fluidRow(column(12, line 17: tipify(prettyCheckbox("comp.rem.ess", label = "Remove essential genes", line 18: value = FALSE, animation = "smooth", status = "success", line 19: bigger = TRUE, icon = icon("check")), "Remove essential genes if any provided to function.", line 20: "right", options = list(container = "body")), line 21: tipify(prettyCheckbox("comp.dep.crispr.ess", label = "Remove DepMap CRISPR essential genes", line 22: value = FALSE, animation = "smooth", status = "success", line 23: bigger = TRUE, icon = icon("check")), "Remove DepMap Chronos Combined, Score, and Achilles common essential genes from latest release.", line 24: "right", options = list(container = "body")), line 25: tipify(prettyCheckbox("comp.dep.rnai.ess", label = "Remove DepMap RNAi essential genes", line 26: value = FALSE, animation = "smooth", status = "success", line 27: bigger = TRUE, icon = icon("check")), "Remove RNAi common essential genes from latest DepMap release.", line 28: "right", options = list(container = "body")), line 29: tipify(prettyCheckbox("comp.dep.crispr.sel", label = "Remove DepMap CRISPR selective genes", line 30: value = FALSE, animation = "smooth", status = "success", line 31: bigger = TRUE, icon = icon("check")), "Remove DepMap Chronos Combined, Score, and Achilles strongly selective genes from latest release.", line 32: "right", options = list(container = "body")), line 33: tipify(prettyCheckbox("comp.dep.rnai.sel", label = "Remove DepMap RNAi selective genes", line 34: value = FALSE, animation = "smooth", status = "success", line 35: bigger = TRUE, icon = icon("check")), "Remove DepMap RNAi strongly selective genes from latest release.", line 36: "right", options = list(container = "body")), line 37: tipify(prettyCheckbox("comp.rem.pos", label = "Remove positive control genes", line 38: value = FALSE, animation = "smooth", status = "success", line 39: bigger = TRUE, icon = icon("check")), "Remove positive control genes if provided.", line 40: "right", options = list(container = "body")))), in .create_tab_gene line 15: fluidRow(column(12, tipify(prettyCheckbox("rem.ess", line 16: label = "Remove essential genes", value = FALSE, line 17: animation = "smooth", status = "success", bigger = TRUE, line 18: icon = icon("check")), "Remove essential genes if any provided to function.", line 19: "right", options = list(container = "body")), line 20: tipify(prettyCheckbox("dep.crispr.ess", label = "Remove DepMap CRISPR essential genes", line 21: value = FALSE, animation = "smooth", status = "success", line 22: bigger = TRUE, icon = icon("check")), "Remove DepMap Chronos Combined, Score, and Achilles common essential genes from latest release.", line 23: "right", options = list(container = "body")), line 24: tipify(prettyCheckbox("dep.rnai.ess", label = "Remove DepMap RNAi essential genes", line 25: value = FALSE, animation = "smooth", status = "success", line 26: bigger = TRUE, icon = icon("check")), "Remove RNAi common essential genes from latest DepMap release.", line 27: "right", options = list(container = "body")), line 28: tipify(prettyCheckbox("dep.crispr.sel", label = "Remove DepMap CRISPR selective genes", line 29: value = FALSE, animation = "smooth", status = "success", line 30: bigger = TRUE, icon = icon("check")), "Remove DepMap Chronos Combined, Score, and Achilles strongly selective genes from latest release.", line 31: "right", options = list(container = "body")), line 32: tipify(prettyCheckbox("dep.rnai.sel", label = "Remove DepMap RNAi selective genes", line 33: value = FALSE, animation = "smooth", status = "success", line 34: bigger = TRUE, icon = icon("check")), "Remove DepMap RNAi strongly selective genes from latest release.", line 35: "right", options = list(container = "body")), line 36: tipify(prettyCheckbox("rem.pos", label = "Remove positive control genes", line 37: value = FALSE, animation = "smooth", status = "success", line 38: bigger = TRUE, icon = icon("check")), "Remove positive control genes if provided to function.", line 39: "right", options = list(container = "body")), repetition in .create_tab_gene and .create_tab_sgrna in .create_tab_gene line 3: tabPanel(title = "Gene (Overview)", id = "gene-overview", line 4: sidebarLayout(sidebarPanel(width = 2, h4("Plot Controls"), line 5: hr(), div(fluidRow(column(6, tipify(selectizeInput("gene.sel1", line 6: "Dataset 1:", choices = dataset.choices), "Dataset shown in top row.", line 191: placement = "bottom", trigger = "hover", options = list(container = "body")), line 192: div(downloadButton("dl_plot.gene1.vol", "Download Volcano Plot", line 193: class = "btn-dl"), style = "display:inline-block; float:right"), line 194: withSpinner(jqui_resizable(plotlyOutput("gene1.vol"))))), line 200: "Click and drag to zoom in. Hover over a point for additional info."), line 201: placement = "bottom", trigger = "hover", options = list(container = "body")), line 202: div(downloadButton("dl_plot.gene1.rank", "Download Rank Plot", line 203: class = "btn-dl"), style = "display:inline-block; float:right"), line 204: withSpinner(jqui_resizable(plotlyOutput("gene1.rank"))))), line 210: "Click and drag to zoom in. Hover over a point for additional info."), line 211: placement = "bottom", trigger = "hover", options = list(container = "body")), line 212: div(downloadButton("dl_plot.gene1.lawn", "Download Lawn Plot", line 213: class = "btn-dl"), style = "display:inline-block; float:right"), line 214: withSpinner(jqui_resizable(plotlyOutput("gene1.lawn")))))), line 216: div(downloadButton("dl_plot.gene2.vol", "Download Volcano Plot", line 217: class = "btn-dl"), style = "display:inline-block; float:right")), line 218: column(width = 4, withSpinner(jqui_resizable(plotlyOutput("gene2.rank"))), line 219: div(downloadButton("dl_plot.gene2.rank", "Download Rank Plot", line 220: class = "btn-dl"), style = "display:inline-block; float:right")), line 221: column(width = 4, withSpinner(jqui_resizable(plotlyOutput("gene2.lawn"))), line 222: div(downloadButton("dl_plot.gene2.lawn", "Download Lawn Plot", line 223: class = "btn-dl"), style = "display:inline-block; float:right")))))) in .create_tab_sgrna line 2:{ line 3: tabPanel(title = "sgRNA", id = "sgrna", sidebarLayout(sidebarPanel(width = 2, line 4: h4("Plot Controls"), hr(), div(fluidRow(column(6, tipify(selectizeInput("sgrna.sel1", line 5: "Dataset 1:", choices = sgrna.choices), "Dataset shown in top row.", line 19: "Hover over a point for additional info."), placement = "bottom", line 20: trigger = "hover", options = list(container = "body")), line 21: div(downloadButton("dl_plot.sgrna1.counts", "Download Counts Plot", line 22: class = "btn-dl"), style = "display:inline-block; float:right"), line 23: withSpinner(jqui_resizable(plotlyOutput("sgrna1.counts"))))), line 27: "Click and drag to zoom in. Hover over a point for additional info."), line 28: placement = "bottom", trigger = "hover", options = list(container = "body")), line 29: div(downloadButton("dl_plot.sgrna1.rank", "Download Rank Plot", line 30: class = "btn-dl"), style = "display:inline-block; float:right"), line 31: withSpinner(jqui_resizable(plotlyOutput("sgrna1.rank"))))), line 35: div(downloadButton("dl_plot.sgrna2.counts", "Download Counts Plot", line 36: class = "btn-dl"), style = "display:inline-block; float:right; height:18px"), line 37: ), column(width = 4, withSpinner(jqui_resizable(plotlyOutput("sgrna2.rank"))), line 38: div(downloadButton("dl_plot.sgrna2.rank", "Download Rank Plot", line 39: class = "btn-dl"), style = "display:inline-block; float:right"), line 40: ), column(width = 6, jqui_resizable(div(DT::dataTableOutput("sgrna2.detail"), repetition in .create_tab_gene_summary and .create_tab_sgrna_summary in .create_tab_gene_summary line 1: function () line 2: { line 3: tabPanel(title = "Gene Summary Tables", id = "gene-summ", line 4: br(), div(withSpinner(DT::dataTableOutput("gene1.summary")), line 5: style = "font-size:80%;"), br(), div(withSpinner(DT::dataTableOutput("gene2.summary")), line 6: style = "font-size:80%;")) in .create_tab_sgrna_summary line 1: function () line 2: { line 3: tabPanel(title = "sgRNA Summary Tables", id = "sgrna-tables", line 4: br(), div(withSpinner(DT::dataTableOutput("sgrna1.summary")), line 5: style = "font-size:80%;"), br(), div(withSpinner(DT::dataTableOutput("sgrna2.summary")), line 6: style = "font-size:80%;")) repetition in .create_tab_qc and .create_tab_sgrna in .create_tab_qc line 74: trigger = "hover", options = list(container = "body")), line 75: div(downloadButton("dl_plot.qc.gini", "Download Gini Plot", line 76: class = "btn-dl"), style = "display:inline-block; float:right"), line 77: withSpinner(jqui_resizable(plotlyOutput("qc.gini")))), line 78: span(popify(icon("circle-info", style = "font-size: 20px"), line 92: placement = "bottom", trigger = "hover", options = list(container = "body")), line 93: div(downloadButton("dl_plot.qc.missed", "Download sgRNA Count Plot", line 94: class = "btn-dl"), style = "display:inline-block; float:right"), line 95: withSpinner(jqui_resizable(plotlyOutput("qc.missed")))), line 96: span(popify(icon("circle-info", style = "font-size: 20px"), in .create_tab_sgrna line 20: trigger = "hover", options = list(container = "body")), line 21: div(downloadButton("dl_plot.sgrna1.counts", "Download Counts Plot", line 22: class = "btn-dl"), style = "display:inline-block; float:right"), line 23: withSpinner(jqui_resizable(plotlyOutput("sgrna1.counts"))))), line 24: column(width = 4, span(popify(icon("circle-info", style = "font-size: 20px"), line 28: placement = "bottom", trigger = "hover", options = list(container = "body")), line 29: div(downloadButton("dl_plot.sgrna1.rank", "Download Rank Plot", line 30: class = "btn-dl"), style = "display:inline-block; float:right"), line 31: withSpinner(jqui_resizable(plotlyOutput("sgrna1.rank"))))), repetition in .mle_ingress and .rra_ingress in .mle_ingress line 2:{ line 3: if (!sig.col %in% colnames(df)) { line 4: mess <- paste0("Column '", sig.col, "' not found in data. Using 'fdr' instead.") line 5: message(mess) line 6: sig.col <- "fdr" line 7: } line 8: if (!es.col %in% colnames(df)) { line 9: mess <- paste0("Column '", es.col, "' not found in data. Using 'beta' instead.") line 10: message(mess) line 11: es.col <- "beta" line 12: } line 13: df$id <- df$Gene line 14: df$hit_type <- apply(df, 1, function(x) { line 15: x <- split(unname(x), names(x)) line 16: ifelse(as.numeric(x[[sig.col]]) < sig.thresh & as.numeric(x[[es.col]]) < line 17: -as.numeric(es.thresh), "neg", ifelse(as.numeric(x[[sig.col]]) < line 18: sig.thresh & as.numeric(x[[es.col]]) > as.numeric(es.thresh), line 19: "pos", NA)) line 20: }) line 21: df$Rank <- rank(df[[es.col]]) line 22: df$RandomIndex <- sample(seq_len(nrow(df)), nrow(df)) line 23: return(df) in .rra_ingress line 23: }) line 24: if (!sig.col %in% colnames(df)) { line 25: mess <- paste0("Column '", sig.col, "' not found in data. Using 'fdr' instead.") line 26: message(mess) line 27: sig.col <- "fdr" line 28: } line 29: if (!es.col %in% colnames(df)) { line 30: mess <- paste0("Column '", es.col, "' not found in data. Using 'LFC' instead.") line 31: message(mess) line 32: es.col <- "LFC" line 33: } line 34: df$hit_type <- apply(df, 1, function(x) { line 35: x <- split(unname(x), names(x)) line 36: ifelse(as.numeric(x[[sig.col]]) < sig.thresh & as.numeric(x[[es.col]]) < line 37: -as.numeric(es.thresh), "neg", ifelse(as.numeric(x[[sig.col]]) < line 38: sig.thresh & as.numeric(x[[es.col]]) > as.numeric(es.thresh), line 39: "pos", NA)) line 40: }) line 45: }) line 46: df$Rank <- rank(df[[es.col]]) line 47: df$RandomIndex <- sample(seq_len(nrow(df)), nrow(df)) line 48: return(df) repetition in plot_depmap_cn and plot_depmap_dependency in plot_depmap_cn line 13: breaks = c(df$color)) + theme(legend.position = "none") line 14: if (!plot.grid) { line 15: gg <- gg + theme(panel.grid.major = element_blank(), line 16: panel.grid.minor = element_blank()) line 17: } line 18: gg <- ggplotly(gg, tooltip = "text") line 19: gg %>% config(edits = list(annotationPosition = TRUE, line 20: annotationTail = TRUE), toImageButtonOptions = list(format = "svg"), line 21: displaylogo = FALSE, plotGlPixelRatio = 7) line 22: } line 23: else { line 24: .empty_plot("Gene not found in DepMap.", plotly = TRUE) line 25: } in plot_depmap_dependency line 16: theme(legend.position = "none") line 17: if (!plot.grid) { line 18: gg <- gg + theme(panel.grid.major = element_blank(), line 19: panel.grid.minor = element_blank()) line 20: } line 26: yaxis = list(title = "Density")) line 27: gg %>% config(edits = list(annotationPosition = TRUE, line 28: annotationTail = TRUE), toImageButtonOptions = list(format = "svg"), line 29: displaylogo = FALSE, plotGlPixelRatio = 7) line 30: } line 31: else { line 32: .empty_plot("Gene not found in DepMap.", plotly = TRUE) line 33: } repetition in plot_depmap_cn, plot_depmap_dependency, plot_depmap_lineages and plot_depmap_expression in plot_depmap_cn line 1: color = "#CEA3CB", plot.grid = FALSE) line 2:{ line 3: if (!is.null(df) && nrow(df) > 0) { line 4: df$color <- color line 5: gg <- ggplot(show.legend = FALSE) + geom_density(data = df, line 6: aes(x = .data[["log_copy_number"]], color = .data[["color"]], line 7: fill = .data[["color"]])) + geom_rug(data = df, line 8: aes(x = .data[["log_copy_number"]], color = .data[["color"]], line 9: text = .data[["hover.string"]], fill = .data[["color"]]), line 10: outside = FALSE) + ylab("Density") + xlab("log2(Copy Number)") + line 11: theme_bw() + scale_color_manual(values = c(df$color), line 12: breaks = c(df$color)) + scale_fill_manual(values = c(df$color), line 13: breaks = c(df$color)) + theme(legend.position = "none") line 14: if (!plot.grid) { line 15: gg <- gg + theme(panel.grid.major = element_blank(), line 16: panel.grid.minor = element_blank()) line 17: } line 18: gg <- ggplotly(gg, tooltip = "text") line 19: gg %>% config(edits = list(annotationPosition = TRUE, line 20: annotationTail = TRUE), toImageButtonOptions = list(format = "svg"), line 21: displaylogo = FALSE, plotGlPixelRatio = 7) line 22: } line 23: else { line 24: .empty_plot("Gene not found in DepMap.", plotly = TRUE) line 25: } in plot_depmap_expression line 1: color = "#7B8CB2", plot.grid = FALSE) line 2:{ line 3: if (!is.null(df) && nrow(df) > 0) { line 4: df$color <- color line 5: gg <- ggplot(show.legend = FALSE) + geom_density(data = df, line 6: aes(x = .data[["rna_expression"]], color = .data[["color"]], line 7: fill = .data[["color"]])) + geom_rug(data = df, line 8: aes(x = .data[["rna_expression"]], color = .data[["color"]], line 9: text = .data[["hover.string"]], fill = .data[["color"]]), line 10: outside = FALSE) + ylab("Density") + xlab("log2(TPM+1)") + line 11: theme_bw() + scale_color_manual(values = c(df$color), line 12: breaks = c(df$color)) + scale_fill_manual(values = c(df$color), line 13: breaks = c(df$color)) + theme(legend.position = "none") line 14: if (!plot.grid) { line 15: gg <- gg + theme(panel.grid.major = element_blank(), line 16: panel.grid.minor = element_blank()) line 17: } line 18: gg <- ggplotly(gg, tooltip = "text") line 19: gg %>% config(edits = list(annotationPosition = TRUE, line 20: annotationTail = TRUE), toImageButtonOptions = list(format = "svg"), line 21: displaylogo = FALSE, plotGlPixelRatio = 7) line 22: } line 23: else { line 24: .empty_plot("Gene not found in DepMap.", plotly = TRUE) line 25: } in plot_depmap_dependency line 16: theme(legend.position = "none") line 17: if (!plot.grid) { line 18: gg <- gg + theme(panel.grid.major = element_blank(), line 19: panel.grid.minor = element_blank()) line 20: } line 26: yaxis = list(title = "Density")) line 27: gg %>% config(edits = list(annotationPosition = TRUE, line 28: annotationTail = TRUE), toImageButtonOptions = list(format = "svg"), line 29: displaylogo = FALSE, plotGlPixelRatio = 7) line 30: } line 31: else { line 32: .empty_plot("Gene not found in DepMap.", plotly = TRUE) line 33: } in plot_depmap_lineages line 35: xaxis = ax, yaxis = ay) line 36: fig %>% config(edits = list(annotationPosition = TRUE, line 37: annotationTail = TRUE), toImageButtonOptions = list(format = "svg"), line 38: displaylogo = FALSE, plotGlPixelRatio = 7) line 39: } line 40: else { line 41: .empty_plot("Gene not found in DepMap.", plotly = TRUE) line 42: } repetition in plot_lawn, plot_volcano and plot_rank in plot_lawn line 6: insig.opacity = 0.5, label.size = 10, webgl = TRUE, webgl.ratio = 7, line 7: show.counts = TRUE, show.hl.counts = TRUE, counts.size = TRUE, line 8: highlight.featsets = NULL, highlight.feats = NULL, featsets = NULL, line 9: highlight.feats.color = "#E69F00", highlight.feats.size = 7, line 10: highlight.feats.opac = 1, highlight.feats.linecolor = "#000000", line 11: highlight.feats.linewidth = 1, highlight.feats.label = TRUE, line 12: highlight.featsets.color = "#009E73", highlight.featsets.size = 7, line 13: highlight.featsets.opac = 1, highlight.featsets.linecolor = "#000000", line 14: highlight.featsets.linewidth = 1, highlight.featsets.label = FALSE, line 15: h.id.suffix = "_lawn") line 16:{ line 17: if (!x.term %in% colnames(res)) { line 18: fig <- .empty_plot(paste0("Column '", x.term, "' not found in dataframe."), line 19: plotly = TRUE) line 20: } line 21: else if (!lfc.term %in% colnames(res)) { line 22: fig <- .empty_plot(paste0("Column '", lfc.term, "' not found in dataframe."), line 23: plotly = TRUE) line 24: } line 25: else if (!is.null(sig.term) & !sig.term %in% colnames(res)) { line 26: fig <- .empty_plot(paste0("Column '", sig.term, "' not found in dataframe."), line 27: plotly = TRUE) line 28: } line 29: else if (!feat.term %in% colnames(res) & feat.term != "rows") { line 30: fig <- .empty_plot(paste0("Column '", feat.term, "' not found in dataframe."), line 31: plotly = TRUE) line 32: } line 33: else { line 34: res$col <- rep(insig.color, nrow(res)) line 35: res$cex <- rep(insig.size, nrow(res)) line 36: res$order <- rep(0, nrow(res)) line 37: res$lcol <- res$col line 38: res$lw <- 0 line 39: res$opacity <- insig.opacity line 41: highlight <- highlight.feats line 42: highlight.fs <- NULL line 43: if (!is.null(highlight.featsets)) { line 44: for (featset in highlight.featsets) { line 45: highlight.fs <- c(highlight.fs, featsets[[featset]]) line 46: } line 47: } line 49: fc.thresh line 50: res$col[up.feats] <- up.color line 51: res$cex[up.feats] <- sig.size line 52: res$order[up.feats] <- 1 line 53: res$opacity[up.feats] <- sig.opacity line 56: res$col[dn.feats] <- down.color line 57: res$cex[dn.feats] <- sig.size line 58: res$order[dn.feats] <- 1 line 59: res$opacity[dn.feats] <- sig.opacity line 60: res$x <- res[[x.term]] line 66: if (feat.term == "rows") { line 67: res$feat <- rownames(res) line 68: } line 69: else { line 70: res$feat <- res[[feat.term]] line 71: } line 72: n.fs.hl <- 0 line 73: n.hl <- 0 line 74: if (!is.null(highlight.fs)) { line 75: highlight.fs <- highlight.fs[highlight.fs %in% res$feat] line 76: n.fs.hl <- length(res$col[res$feat %in% highlight.fs]) line 77: res$col[res$feat %in% highlight.fs] <- highlight.featsets.color line 78: res$cex[res$feat %in% highlight.fs] <- highlight.featsets.size line 79: res$opacity[res$feat %in% highlight.fs] <- highlight.featsets.opac line 80: res$lcol[res$feat %in% highlight.fs] <- highlight.featsets.linecolor line 81: res$lw[res$feat %in% highlight.fs] <- highlight.featsets.linewidth line 82: res$order[res$feat %in% highlight.fs] <- 2 line 83: if (highlight.featsets.label) { line 84: add.fs <- data.frame(x = res$x[res$feat %in% line 85: highlight.fs], y = res$y[res$feat %in% highlight.fs], line 86: customdata = res$feat[res$feat %in% highlight.fs]) line 87: if (!is.null(fs)) { line 88: fs <- fs[, c("x", "y", "customdata")] line 89: fs <- rbind(fs, add.fs) line 90: } line 91: else { line 92: fs <- add.fs line 93: } line 94: } line 95: } line 96: if (!is.null(highlight)) { line 97: highlight <- highlight[highlight %in% res$feat] line 98: if (length(highlight) > 0) { line 99: n.hl <- length(res$col[res$feat %in% highlight]) line 100: res$col[res$feat %in% highlight] <- highlight.feats.color line 101: res$cex[res$feat %in% highlight] <- highlight.feats.size line 102: res$opacity[res$feat %in% highlight] <- highlight.feats.opac line 103: res$lcol[res$feat %in% highlight] <- highlight.feats.linecolor line 104: res$lw[res$feat %in% highlight] <- highlight.feats.linewidth line 105: res$order[res$feat %in% highlight] <- 3 line 106: if (highlight.feats.label) { line 107: add.fs <- data.frame(x = res$x[res$feat %in% line 108: highlight], y = res$y[res$feat %in% highlight], line 109: customdata = res$feat[res$feat %in% highlight]) line 110: if (!is.null(fs)) { line 111: fs <- fs[, c("x", "y", "customdata")] line 112: fs <- rbind(fs, add.fs) line 113: } line 114: else { line 115: fs <- add.fs line 116: } line 117: } line 118: } line 119: } line 120: res$hover.string <- paste0(" ", feat.term, ": ", line 121: res$feat, " ", lfc.term, ": ", format(round(res[[lfc.term]], line 122: 4), nsmall = 4), " ", sig.term, ": ", line 123: format(round(res[[sig.term]], 6), nsmall = 6)) line 124: if (!is.null(hover.info)) { line 125: for (n in hover.info) { line 126: res$hover.string <- paste0(res$hover.string, line 127: " ", n, ": ", res[[n]]) line 128: } line 129: } line 130: res <- as.data.frame(res) line 131: res <- res[order(res$order), ] line 132: n.up.feats <- length(up.feats[up.feats == TRUE]) line 133: n.dn.feats <- length(dn.feats[dn.feats == TRUE]) line 134: n.feats <- nrow(res) line 135: ay <- list(showline = TRUE, mirror = TRUE, linecolor = toRGB("black"), line 136: linewidth = 0.5, title = paste0("-log10(", sig.term, line 146: sig.hline <- .hline(y = -log10(sig.thresh), color = "#000000", line 147: width = 1, dash = "longdash") line 148: } line 149: fig <- plot_ly(res, x = ~x, y = ~y, customdata = ~feat, line 150: type = "scatter", mode = "markers", marker = list(color = ~col, line 151: size = ~cex, symbol = ~sh, line = list(color = ~lcol, line 152: width = ~lw), opacity = ~opacity), text = ~hover.string, line 153: hoverinfo = "text", source = paste0(h.id, h.id.suffix)) %>% line 154: config(edits = list(annotationPosition = TRUE, annotationTail = TRUE), line 155: toImageButtonOptions = list(format = "svg"), line 156: displaylogo = FALSE, plotGlPixelRatio = webgl.ratio) line 157: if (!is.null(fs)) { line 158: fig <- fig %>% layout(xaxis = ax, yaxis = ay, showlegend = FALSE, line 159: shapes = list(sig.hline)) %>% add_annotations(x = fs$x, line 160: y = fs$y, text = fs$customdata, font = list(size = label.size, line 161: family = "Arial"), arrowside = "none") line 162: } line 163: else { line 164: fig <- fig %>% layout(xaxis = ax, yaxis = ay, showlegend = FALSE, line 165: shapes = list(sig.hline)) line 166: } line 167: if (show.counts) { line 168: fig <- fig %>% add_annotations(x = 1, y = 1, xref = "paper", line 169: yref = "paper", text = paste0("Up features: ", line 170: n.up.feats, "\nDown features: ", n.dn.feats, line 171: "\nTotal features: ", n.feats), showarrow = FALSE, line 172: font = list(size = counts.size)) line 173: } line 174: if (show.hl.counts) { line 175: fig <- fig %>% add_annotations(x = 0, y = 1, xref = "paper", line 176: yref = "paper", text = paste0("Set features: ", line 177: n.fs.hl, "\nHighlighted features: ", n.hl), line 178: showarrow = FALSE, font = list(size = counts.size)) line 179: } line 180: if (webgl) { line 181: fig <- fig %>% toWebGL() line 182: } line 183: } line 184: fig in plot_rank line 5: insig.size = 5, sig.opacity = 1, insig.opacity = 0.5, label.size = 10, line 6: webgl = TRUE, webgl.ratio = 7, show.counts = TRUE, show.hl.counts = TRUE, line 7: counts.size = TRUE, highlight.featsets = NULL, highlight.feats = NULL, line 8: featsets = NULL, highlight.feats.color = "#E69F00", highlight.feats.size = 7, line 9: highlight.feats.opac = 1, highlight.feats.linecolor = "#000000", line 10: highlight.feats.linewidth = 1, highlight.feats.label = TRUE, line 11: highlight.featsets.color = "#009E73", highlight.featsets.size = 7, line 12: highlight.featsets.opac = 1, highlight.featsets.linecolor = "#000000", line 13: highlight.featsets.linewidth = 1, highlight.featsets.label = FALSE, line 14: h.id.suffix = "_volc") line 15:{ line 16: if (!rank.term %in% colnames(res)) { line 17: fig <- .empty_plot(paste0("Column '", rank.term, "' not found in dataframe."), line 18: plotly = TRUE) line 19: } line 20: else if (!is.null(sig.term) & !sig.term %in% colnames(res)) { line 21: fig <- .empty_plot(paste0("Column '", sig.term, "' not found in dataframe."), line 22: plotly = TRUE) line 23: } line 24: else if (!feat.term %in% colnames(res) & feat.term != "rows") { line 25: fig <- .empty_plot(paste0("Column '", feat.term, "' not found in dataframe."), line 26: plotly = TRUE) line 27: } line 28: else { line 29: res$col <- rep(insig.color, nrow(res)) line 30: res$cex <- rep(insig.size, nrow(res)) line 31: res$order <- rep(0, nrow(res)) line 32: res$lcol <- res$col line 33: res$lw <- 0 line 34: res$opacity <- insig.opacity line 38: highlight <- highlight.feats line 39: highlight.fs <- NULL line 40: if (!is.null(highlight.featsets)) { line 41: for (featset in highlight.featsets) { line 42: highlight.fs <- c(highlight.fs, featsets[[featset]]) line 43: } line 44: } line 54: } line 55: res$col[up.feats] <- up.color line 56: res$cex[up.feats] <- sig.size line 57: res$order[up.feats] <- 1 line 58: res$opacity[up.feats] <- sig.opacity line 59: res$col[dn.feats] <- down.color line 60: res$cex[dn.feats] <- sig.size line 61: res$order[dn.feats] <- 1 line 62: res$opacity[dn.feats] <- sig.opacity line 63: if (rank.ascending) { line 74: if (feat.term == "rows") { line 75: res$feat <- rownames(res) line 76: } line 77: else { line 78: res$feat <- res[[feat.term]] line 79: } line 80: n.fs.hl <- 0 line 81: n.hl <- 0 line 82: if (!is.null(highlight.fs)) { line 83: highlight.fs <- highlight.fs[highlight.fs %in% res$feat] line 84: n.fs.hl <- length(res$col[res$feat %in% highlight.fs]) line 85: res$col[res$feat %in% highlight.fs] <- highlight.featsets.color line 86: res$cex[res$feat %in% highlight.fs] <- highlight.featsets.size line 87: res$opacity[res$feat %in% highlight.fs] <- highlight.featsets.opac line 88: res$lcol[res$feat %in% highlight.fs] <- highlight.featsets.linecolor line 89: res$lw[res$feat %in% highlight.fs] <- highlight.featsets.linewidth line 90: res$order[res$feat %in% highlight.fs] <- 2 line 91: if (highlight.featsets.label) { line 92: add.fs <- data.frame(x = res$x[res$feat %in% line 93: highlight.fs], y = res$y[res$feat %in% highlight.fs], line 94: customdata = res$feat[res$feat %in% highlight.fs]) line 95: if (!is.null(fs)) { line 96: fs <- fs[, c("x", "y", "customdata")] line 97: fs <- rbind(fs, add.fs) line 98: } line 99: else { line 100: fs <- add.fs line 101: } line 102: } line 103: } line 104: if (!is.null(highlight)) { line 105: highlight <- highlight[highlight %in% res$feat] line 106: if (length(highlight) > 0) { line 107: n.hl <- length(res$col[res$feat %in% highlight]) line 108: res$col[res$feat %in% highlight] <- highlight.feats.color line 109: res$cex[res$feat %in% highlight] <- highlight.feats.size line 110: res$opacity[res$feat %in% highlight] <- highlight.feats.opac line 111: res$lcol[res$feat %in% highlight] <- highlight.feats.linecolor line 112: res$lw[res$feat %in% highlight] <- highlight.feats.linewidth line 113: res$order[res$feat %in% highlight] <- 3 line 114: if (highlight.feats.label) { line 115: add.fs <- data.frame(x = res$x[res$feat %in% line 116: highlight], y = res$y[res$feat %in% highlight], line 117: customdata = res$feat[res$feat %in% highlight]) line 118: if (!is.null(fs)) { line 119: fs <- fs[, c("x", "y", "customdata")] line 120: fs <- rbind(fs, add.fs) line 121: } line 122: else { line 123: fs <- add.fs line 124: } line 125: } line 126: } line 127: } line 128: res$hover.string <- paste(" ", feat.term, ": ", line 130: rank.term, ": ", format(round(res[[rank.term]], line 131: 4), nsmall = 4), " ", sig.term, ": ", line 132: format(round(res[[sig.term]], 6), nsmall = 6)) line 133: if (!is.null(hover.info)) { line 134: for (n in hover.info) { line 135: res$hover.string <- paste0(res$hover.string, line 136: " ", n, ": ", res[[n]]) line 137: } line 138: } line 139: res <- as.data.frame(res) line 140: res <- res[order(res$order), ] line 141: n.up.feats <- length(up.feats[up.feats == TRUE]) line 142: n.dn.feats <- length(dn.feats[dn.feats == TRUE]) line 143: n.feats <- nrow(res) line 144: ay <- list(showline = TRUE, mirror = TRUE, linecolor = toRGB("black"), line 145: linewidth = 0.5, title = rank.term, range = ylim, line 158: y.line2 <- .hline(y = -y.thresh, color = "#000000", line 159: width = 1, dash = "longdash") line 160: } line 161: fig <- plot_ly(res, x = ~x, y = ~y, customdata = ~feat, line 162: type = "scatter", mode = "markers", marker = list(color = ~col, line 163: size = ~cex, symbol = ~sh, line = list(color = ~lcol, line 164: width = ~lw), opacity = ~opacity), text = ~hover.string, line 165: hoverinfo = "text", source = paste0(h.id, h.id.suffix)) %>% line 166: config(edits = list(annotationPosition = TRUE, annotationTail = TRUE), line 167: toImageButtonOptions = list(format = "svg"), line 168: displaylogo = FALSE, plotGlPixelRatio = webgl.ratio) line 169: if (!is.null(fs)) { line 170: fig <- fig %>% layout(xaxis = ax, yaxis = ay, showlegend = FALSE, line 171: shapes = list(y.line1, y.line2)) %>% add_annotations(x = fs$x, line 172: y = fs$y, text = fs$customdata, font = list(size = label.size, line 173: family = "Arial"), arrowside = "none") line 174: } line 175: else { line 176: fig <- fig %>% layout(xaxis = ax, yaxis = ay, showlegend = FALSE, line 177: shapes = list(y.line1, y.line2)) line 178: } line 179: if (show.counts) { line 180: fig <- fig %>% add_annotations(x = 1, y = 0, xref = "paper", line 181: yref = "paper", text = paste0("Up features: ", line 182: n.up.feats, "\nDown features: ", n.dn.feats, line 183: "\nTotal features: ", n.feats), showarrow = FALSE, line 184: font = list(size = counts.size)) line 185: } line 186: if (show.hl.counts) { line 187: fig <- fig %>% add_annotations(x = 0, y = 1, xref = "paper", line 188: yref = "paper", text = paste0("Set features: ", line 189: n.fs.hl, "\nHighlighted features: ", n.hl), line 190: showarrow = FALSE, font = list(size = counts.size)) line 191: } line 192: if (webgl) { line 193: fig <- fig %>% toWebGL() line 194: } line 195: } line 196: fig in plot_volcano line 5: insig.size = 5, sig.opacity = 1, insig.opacity = 0.5, label.size = 10, line 6: webgl = TRUE, webgl.ratio = 7, show.counts = TRUE, show.hl.counts = TRUE, line 7: counts.size = 8, highlight.featsets = NULL, highlight.feats = NULL, line 8: featsets = NULL, highlight.feats.color = "#E69F00", highlight.feats.size = 7, line 9: highlight.feats.opac = 1, highlight.feats.linecolor = "#000000", line 10: highlight.feats.linewidth = 1, highlight.feats.label = TRUE, line 11: highlight.featsets.color = "#009E73", highlight.featsets.size = 7, line 12: highlight.featsets.opac = 1, highlight.featsets.linecolor = "#000000", line 13: highlight.featsets.linewidth = 1, highlight.featsets.label = FALSE, line 14: h.id.suffix = "_volc") line 15:{ line 16: if (!feat.term %in% colnames(res) & feat.term != "rows") { line 17: fig <- .empty_plot(paste0("Column '", feat.term, "' not found in dataframe."), line 18: plotly = TRUE) line 19: } line 20: else if (!sig.term %in% colnames(res)) { line 21: fig <- .empty_plot(paste0("Column '", sig.term, "' not found in dataframe."), line 22: plotly = TRUE) line 23: } line 24: else if (!lfc.term %in% colnames(res)) { line 25: fig <- .empty_plot(paste0("Column '", lfc.term, "' not found in dataframe."), line 26: plotly = TRUE) line 27: } line 28: else { line 29: res$col <- rep(insig.color, nrow(res)) line 30: res$cex <- rep(insig.size, nrow(res)) line 31: res$order <- rep(0, nrow(res)) line 32: res$lcol <- res$col line 33: res$lw <- 0 line 34: res$opacity <- insig.opacity line 35: res <- res[!is.na(res[[sig.term]]), ] line 36: highlight <- highlight.feats line 37: highlight.fs <- highlight.featsets line 38: if (!is.null(highlight.featsets)) { line 39: for (featset in highlight.featsets) { line 40: highlight.fs <- c(highlight.fs, featsets[[featset]]) line 41: } line 42: } line 43: up.feats <- res[[sig.term]] < sig.thresh & res[[lfc.term]] > line 44: fc.thresh line 45: res$col[up.feats] <- up.color line 46: res$cex[up.feats] <- sig.size line 47: res$order[up.feats] <- 1 line 48: res$opacity[up.feats] <- sig.opacity line 49: dn.feats <- res[[sig.term]] < sig.thresh & res[[lfc.term]] < line 50: -fc.thresh line 51: res$col[dn.feats] <- down.color line 52: res$cex[dn.feats] <- sig.size line 53: res$order[dn.feats] <- 1 line 54: res$opacity[dn.feats] <- sig.opacity line 55: res$x <- res[[lfc.term]] line 56: res$y <- -log10(res[[sig.term]]) line 57: res$col[res$y < -log10(sig.thresh)] <- insig.color line 58: res$sh <- ifelse(res$y > ylim, "triangle-up-open", ifelse(res$x < line 64: res$x[res$x < -xlim] <- -xlim + 0.05 line 65: if (feat.term == "rows") { line 66: res$feat <- rownames(res) line 67: } line 68: else { line 69: res$feat <- res[[feat.term]] line 70: } line 71: n.fs.hl <- 0 line 72: n.hl <- 0 line 73: if (!is.null(highlight.fs)) { line 74: highlight.fs <- highlight.fs[highlight.fs %in% res$feat] line 75: n.fs.hl <- length(res$col[res$feat %in% highlight.fs]) line 76: res$col[res$feat %in% highlight.fs] <- highlight.featsets.color line 77: res$cex[res$feat %in% highlight.fs] <- highlight.featsets.size line 78: res$opacity[res$feat %in% highlight.fs] <- highlight.featsets.opac line 79: res$lcol[res$feat %in% highlight.fs] <- highlight.featsets.linecolor line 80: res$lw[res$feat %in% highlight.fs] <- highlight.featsets.linewidth line 81: res$order[res$feat %in% highlight.fs] <- 2 line 82: if (highlight.featsets.label) { line 83: add.fs <- data.frame(x = res$x[res$feat %in% line 84: highlight.fs], y = res$y[res$feat %in% highlight.fs], line 85: customdata = res$feat[res$feat %in% highlight.fs]) line 86: if (!is.null(fs)) { line 87: fs <- fs[, c("x", "y", "customdata")] line 88: fs <- rbind(fs, add.fs) line 89: } line 90: else { line 91: fs <- add.fs line 92: } line 93: } line 94: } line 95: if (!is.null(highlight)) { line 96: highlight <- highlight[highlight %in% res$feat] line 97: if (length(highlight) > 0) { line 98: n.hl <- length(res$col[res$feat %in% highlight]) line 99: res$col[res$feat %in% highlight] <- highlight.feats.color line 100: res$cex[res$feat %in% highlight] <- highlight.feats.size line 101: res$opacity[res$feat %in% highlight] <- highlight.feats.opac line 102: res$lcol[res$feat %in% highlight] <- highlight.feats.linecolor line 103: res$lw[res$feat %in% highlight] <- highlight.feats.linewidth line 104: res$order[res$feat %in% highlight] <- 3 line 105: if (highlight.feats.label) { line 106: add.fs <- data.frame(x = res$x[res$feat %in% line 107: highlight], y = res$y[res$feat %in% highlight], line 108: customdata = res$feat[res$feat %in% highlight]) line 109: if (!is.null(fs)) { line 110: fs <- fs[, c("x", "y", "customdata")] line 111: fs <- rbind(fs, add.fs) line 112: } line 113: else { line 114: fs <- add.fs line 115: } line 116: } line 117: } line 118: } line 119: res$hover.string <- paste0(" ", feat.term, ": ", line 120: res$feat, " ", lfc.term, ": ", format(round(res[[lfc.term]], line 121: 4), nsmall = 4), " ", sig.term, ": ", line 122: format(round(res[[sig.term]], 6), nsmall = 6)) line 123: if (!is.null(hover.info)) { line 124: for (n in hover.info) { line 125: res$hover.string <- paste0(res$hover.string, line 126: " ", n, ":", res[[n]]) line 127: } line 128: } line 129: res <- as.data.frame(res) line 130: res <- res[order(res$order), ] line 131: n.up.feats <- length(up.feats[up.feats == TRUE]) line 132: n.dn.feats <- length(dn.feats[dn.feats == TRUE]) line 133: n.feats <- nrow(res) line 134: ay <- list(showline = TRUE, mirror = TRUE, linecolor = toRGB("black"), line 135: linewidth = 0.5, title = paste0("-log10(", sig.term, line 136: ")"), range = list(0, ylim), showgrid = FALSE, line 137: layer = "below traces", zeroline = FALSE, ticks = "outside", line 138: zerolinewidth = 0.5) line 139: ax <- list(showline = TRUE, mirror = TRUE, linecolor = toRGB("black"), line 140: linewidth = 0.5, title = lfc.term, range = list(-xlim, line 145: sig.hline <- NULL line 146: if (sig.line) { line 147: sig.hline <- .hline(y = -log10(sig.thresh), color = "#000000", line 148: width = 1, dash = "longdash") line 149: } line 153: fc.line2 <- .vline(x = -fc.thresh, color = "#000000", line 154: width = 1, dash = "longdash") line 155: } line 156: fig <- plot_ly(res, x = ~x, y = ~y, customdata = ~feat, line 157: type = "scatter", mode = "markers", marker = list(color = ~col, line 158: size = ~cex, symbol = ~sh, line = list(color = ~lcol, line 159: width = ~lw), opacity = ~opacity), text = ~hover.string, line 160: hoverinfo = "text", source = paste0(h.id, h.id.suffix)) %>% line 161: config(edits = list(annotationPosition = TRUE, annotationTail = TRUE), line 162: toImageButtonOptions = list(format = "svg"), line 163: displaylogo = FALSE, plotGlPixelRatio = webgl.ratio) line 164: if (!is.null(fs)) { line 165: fig <- fig %>% layout(xaxis = ax, yaxis = ay, showlegend = FALSE, line 166: shapes = list(sig.hline, fc.line1, fc.line2), line 167: hoverlabel = list(font = list(size = 10))) %>% line 168: add_annotations(x = fs$x, y = fs$y, text = fs$customdata, line 169: font = list(size = label.size, family = "Arial"), line 170: arrowside = "none") line 176: } line 177: if (show.counts) { line 178: fig <- fig %>% add_annotations(x = 1, y = 1, xref = "paper", line 179: yref = "paper", text = paste0("Up features: ", line 180: n.up.feats, "\nDown features: ", n.dn.feats, line 181: "\nTotal features: ", n.feats), showarrow = FALSE, line 182: font = list(size = counts.size)) line 183: } line 184: if (show.hl.counts) { line 185: fig <- fig %>% add_annotations(x = 0, y = 1, xref = "paper", line 186: yref = "paper", text = paste0("Set features: ", line 187: n.fs.hl, "\nHighlighted features: ", n.hl), line 188: showarrow = FALSE, font = list(size = counts.size)) line 189: } line 190: if (webgl) { line 191: fig <- fig %>% toWebGL() line 192: } line 193: } line 194: fig

I do not know how these lines/functions were flagged, but I feel this is mostly a reflection of the package being largely composed of a Shiny app. There is some amount of unavoidable code repetition, particularly when defining the UI. If there are more specific guidelines as to how to avoid this in Shiny packages, I am happy to follow it.

Documentation

Important: Vignette should have an Installation section. rmd file vignettes/CRISPRball.Rmd Important: Please include Bioconductor installation instructions using BiocManager. rmd file vignettes/CRISPRball.Rmd Note: Vignette includes motivation for submitting to Bioconductor as part of the abstract/intro of the main vignette. rmd file vignettes/CRISPRball.Rmd

Added an installation section and a few lines for motivation referencing other Bioconductor packages that this one complements.

Important: Vignette should have real runable code. Remove most of the eval=FALSE. All Pseudocode are not acceptable. rmd file vignettes/CRISPRball.Rmd

Since this package is a Shiny app, this is challenging. I based my vignette off of other packages that are largely Shiny applications that make use of eval=FALSE similarly, e.g. GeneTonic. I am not sure of a good way around this but am open to suggestions. I included the screenshots so that an idea of what to expect is present, and I will have a live example that folks can test out soon.

Important: To avoid the '* NOTE: Consider adding runnable examples to man pages that document exported objects.' in BiocCheck, could you please add runnable examples to

  • build_depmap_db.Rd
  • get_depmap_essentiality.Rd
  • get_depmap_plot_data.Rd

    Important: Usage of dontrun{} / donttest{} tags found in man page examples. 9% of man pages use at least one of these tags.

  • build_depmap_db.Rd
  • get_depmap_plot_data.Rd

build_depmap_db creates a relatively large (4.1 GB) database and takes a while to download the data. I feel dontrun is appropriate here. get_depmap_plot_data utilizes said database, hence the use of dontrun in its example.

Important: Empty or missing \value sections found in man pages. Found in files: man/depmap_22q1_cn.Rd man/depmap_22q1_crispr_rnai.Rd man/depmap_22q1_crispr.Rd man/depmap_22q1_rnai.Rd man/depmap_22q1_TPM.Rd

These have been added.

Important: NEWS.md is not consistant with the DESCRIPTION

Is this just the version not matching? I have changed NEWS.md to 0.99.0 for now, but I thought it'd get bumped to 1.0.0 on release.

jianhong commented 8 months ago

Check https://mastering-shiny.org/scaling-modules.html to try to reduce the code repetition.

NEWS file should be the file talking about the basic information about the changes and additions to the package. The file will be used to address the important point which will affect the usage.

In the documentation, a full runnable example will inform you the broken of the key function by the auto building system.

Hope this will help.

bioc-issue-bot commented 8 months ago

Received a valid push on git.bioconductor.org; starting a build for commit id: 86323977c72f2e1e8bff0cba620587e560075824

bioc-issue-bot commented 8 months ago

Dear Package contributor,

This is the automated single package builder at bioconductor.org.

Your package has been built on the Bioconductor Build System.

On one or more platforms, the build results were: "WARNINGS, skipped, ERROR". This may mean there is a problem with the package that you need to fix. Or it may mean that there is a problem with the build system itself.

Please see the build report for more details.

The following are build products from R CMD build on the Bioconductor Build System: macOS 12.6.5 Monterey: CRISPRball_0.99.2.tar.gz

Links above active for 21 days.

Remember: if you submitted your package after July 7th, 2020, when making changes to your repository push to git@git.bioconductor.org:packages/CRISPRball to trigger a new build. A quick tutorial for setting up remotes and pushing to upstream can be found here.

bioc-issue-bot commented 8 months ago

Received a valid push on git.bioconductor.org; starting a build for commit id: 9cd7edc14fce135b88690ec32890945019343fc7

bioc-issue-bot commented 8 months ago

Dear Package contributor,

This is the automated single package builder at bioconductor.org.

Your package has been built on the Bioconductor Build System.

Congratulations! The package built without errors or warnings on all platforms.

Please see the build report for more details.

The following are build products from R CMD build on the Bioconductor Build System: macOS 12.6.5 Monterey: CRISPRball_0.99.3.tar.gz Linux (Ubuntu 22.04.2 LTS): CRISPRball_0.99.3.tar.gz

Links above active for 21 days.

Remember: if you submitted your package after July 7th, 2020, when making changes to your repository push to git@git.bioconductor.org:packages/CRISPRball to trigger a new build. A quick tutorial for setting up remotes and pushing to upstream can be found here.

j-andrews7 commented 8 months ago

Thanks for the comments. I have a few questions.

Check https://mastering-shiny.org/scaling-modules.html to try to reduce the code repetition.

Introducing Shiny modules at this stage will substantially increase complexity. I do have plans to integrate them in time, but it is not a simple change. Is this necessary for acceptance?

NEWS file should be the file talking about the basic information about the changes and additions to the package. The file will be used to address the important point which will affect the usage.

I understand how the NEWS file is meant to be used for package updates. I do not understand what I need to add to this for initial submission. Every other package I look at seems to just have some variant of "Submitted to Bioconductor X.YY" for version 1.0, e.g. dittoSeq and SingleR. Can you provide an example of what you expect this file to contain for an initial package submission?

In the documentation, a full runnable example will inform you the broken of the key function by the auto building system.

For these specific functions, they generate or require a large (> 4GB) database file that takes several minutes to run, far in excess of the <5s per example runtime recommended. R CMD check complained about long running examples, and these cause warnings in the Bioconductor build system due to running >10 minutes total. I think dontrun is appropriate for these examples.

I have added a series of long tests to test the database construction and basic retrieval functionality that I feel allays potential concerns with broken functionality. Does that work?

jianhong commented 8 months ago
  1. While the module is not mandatory, it is strongly recommended. I appreciate knowing that it's on your TODO list.
  2. Do you anticipate significant challenges in creating an accurate NEWS file?
  3. It's necessary to provide a functional example. Please make an effort to create a simplified sample.

If you find my review process too rigorous, feel free to request a different reviewer. Best wishes for the swift acceptance of your package.

bioc-issue-bot commented 8 months ago

Received a valid push on git.bioconductor.org; starting a build for commit id: 1e9ef7f8f203ae48a63decf2f87f4c453fa0e3a4

bioc-issue-bot commented 8 months ago

Dear Package contributor,

This is the automated single package builder at bioconductor.org.

Your package has been built on the Bioconductor Build System.

Congratulations! The package built without errors or warnings on all platforms.

Please see the build report for more details.

The following are build products from R CMD build on the Bioconductor Build System: Linux (Ubuntu 22.04.2 LTS): CRISPRball_0.99.4.tar.gz macOS 12.6.5 Monterey: CRISPRball_0.99.4.tar.gz

Links above active for 21 days.

Remember: if you submitted your package after July 7th, 2020, when making changes to your repository push to git@git.bioconductor.org:packages/CRISPRball to trigger a new build. A quick tutorial for setting up remotes and pushing to upstream can be found here.

j-andrews7 commented 8 months ago

Thanks for the comments.

While the module is not mandatory, it is strongly recommended. I appreciate knowing that it's on your TODO list.

If this is the case, it would be good to add it to the guidelines for Bioconductor Shiny apps, which currently makes no mention of them (tagging @kevinrue since I think he made that page).

My hope is to make a package of generic Shiny modules (e.g. scatterplot, barchart, etc) that can be built upon and easily incorporated into existing applications, but this will take some time. Given that this package/app is functional, I'd prefer not to wait to get it included into Bioconductor, but I recognize this is ultimately up to the reviewers/Bioc staff.

Do you anticipate significant challenges in creating an accurate NEWS file?

I have tweaked this again. It matches those of other accepted packages and the Bioconductor guidelines specified here. It looks fine by my eye via utils::news("CRISPRball"). If it is still incorrect, can you please provide an example or more specific indications of what needs to be changed?

I am happy to make any changes requested.

It's necessary to provide a functional example. Please make an effort to create a simplified sample.

I have altered said functions such that they have runnable examples that do not throw warnings during the build process.

If you find my review process too rigorous, feel free to request a different reviewer. Best wishes for the swift acceptance of your package.

I do appreciate the review, and I'd prefer not to duplicate effort for the reviewers. I know the review load can be heavy and take significant time, particularly near releases. I actually appreciate your rigor, and I hope I am not coming across otherwise.

kevinrue commented 8 months ago

Disclaimer:

Like Andrews, I appreciate the time and effort that goes into Bioconductor package reviews, having gone through the process a dozen time and always receiving helpful feedback and insights.

With that in mind:

@jianhong : While the module is not mandatory, it is strongly recommended. I appreciate knowing that it's on your TODO list.

I suppose that you mean "it is strongly recommended [by Hadley Wickham in the book 'Mastering Shiny']". I haven't seen any such recommendation in any Bioconductor guidelines anywhere, to date; I believe that the choice is still largely left to developers in Bioconductor at the moment. Even in https://mastering-shiny.org/scaling-modules.html, Hadley does a great job of detailing the motivations and advantages of modules for complex apps, but all I can read is gentle encouragement to try and use them, not a veto on Shiny apps that use only regular functions, e.g.

It takes a while to get your head around modules, but once you do you’ll have an unlocked a powerful technique for simplifying complex apps. (quote from the book)

Given the current Bioconductor guidelines - specifically, lack of specific guidelines on Shiny modules - my personal experience is that the use of Shiny modules (or not) is not currently a criteria for acceptance into Bioconductor (if that were the case, three of my packages accepted in the last six months should have been rejected too).

@j-andrews7 : If this is the case, it would be good to add it to the guidelines for Bioconductor Shiny apps, which currently makes no mention of them (tagging @kevinrue since I think he made that page).

Again, I welcome contributions to the Shiny guidelines, whether related to Shiny modules or other aspects. I still prefer to write my own Shiny apps without modules, and I don't plan to re-write my own Shiny apps like Andrew is so openly considering, so it would certainly be more useful that someone with experience of Shiny modules proposes guidelines based on their own experience.

In summary, I appreciate the reviewer's reminder that Shiny modules are documented as a "powerful technique for simplifying complex apps", but in the context of this new package review, I believe that Shiny modules have never been a requirement for acceptance of Shiny apps into Bioconductor.

vjcitn commented 7 months ago

Sorry for delay in commenting here. I'd agree that modules cannot be required at this time. @j-andrews7 if you have any comments on how you plan to introduce them, these would be welcome. Otherwise, in light of the rigorous review already conducted by @jianhong I'd say we should consider accepting the package. Could we have a version bump to ensure SPB processes again?

bioc-issue-bot commented 7 months ago

Received a valid push on git.bioconductor.org; starting a build for commit id: 9e2fbe8410cb416cf10efa9c41dd85cb322c981c

j-andrews7 commented 7 months ago

HI @vjcitn, thanks for taking a look. For the modules, I plan to make a package composed of Shiny modules for generic plots, then have them used as building blocks for more complicated modules/plots. As an example, here's a module/example app for a scatter plot:

library(shiny)
library(plotly)
library(colourpicker)
library(shinydashboard)

#' Function to organize inputs into a grid layout
#' @param tag_list A tagList containing UI inputs or a named list 
#'   containing multiple tagLists containing UI inputs.
#' @param tack An optional UI input to tack onto the end of the grid.
#' @param columns Number of columns.
#' @param rows Number of rows.
#'
#' @return A Shiny tagList with inputs organized into a grid, optionally
#'   nested inside a tabsetPanel.
#'
#' @importFrom shiny fluidRow column tagList tabsetPanel tabPanel
#' @export
#' @author Jared Andrews
organize_inputs <- function(tag_list, tack = NULL, columns = NULL, rows = NULL) {
  # Check if tag_list is a list of named lists
  if (!is(tag_list, "shiny.tag.list")) {

    # Create a tabsetPanel with a tabPanel for each list element
    out <- do.call(tabsetPanel, c(
      lapply(names(tag_list), function(tab_name) {
        tabPanel(
          tab_name,
          do.call(tagList, organize_inputs(tag_list[[tab_name]], columns = columns, rows = rows))
        )
      }))
    )

  } else {
    n_tags <- length(tag_list)

    # Calculate missing dimension based on the provided one and total tags
    if (is.null(columns) & !is.null(rows)) {
      columns <- ceiling(n_tags / rows)
    } else if (is.null(rows) & !is.null(columns)) {
      rows <- ceiling(n_tags / columns)
    } else if (is.null(rows) & is.null(columns)) {
      stop("Either rows or columns must be provided.")
    }

    out <- lapply(seq_len(rows), function(r) {
      do.call(fluidRow, lapply(seq_len(columns), function(c) {
        idx <- (r - 1) * columns + c
        if (idx <= n_tags) {
          column(width = 12 / columns, tag_list[[idx]])
        }
      }))
    })
  }

  if (!is.null(tack)) {
    out <- tagList(out, tack)
  }

  out
}

###### Plot Generation ######

#' Generate a single scatterplot using Plotly
#'
#' @param data Data frame containing the data to plot.
#' @param x.var Name of the variable for the x-axis.
#' @param y.var Name of the variable for the y-axis.
#' @param color.by (Optional) Name of the variable for point color.
#' @param shape.by (Optional) Name of the variable for point shape.
#' @param point.size Size of the points in the plot (default is 6).
#' 
#' @return A Plotly scatterplot object
#'
#' @importFrom plotly plot_ly add_trace %>% layout
#' @author Jared Andrews
#' @examples
#' data <- data.frame(x = rnorm(100), y = rnorm(100), color = rnorm(100), shape = factor(rep(1:2, 50)))
#' .scatterplot(data, "x", "y", "color", "shape")
.scatterplot <- function(data, 
                         x.var, 
                         y.var, 
                         color.by = NULL, 
                         shape.by = NULL, 
                         gridlines = TRUE, 
                         point.size = 4, 
                         size.by = NULL,
                         hlines = NULL, 
                         vlines = NULL, 
                         line.width = 1, 
                         line.color = "black",
                         xlim = NULL, 
                         ylim = NULL, 
                         opacity = 1, 
                         label.by = NULL) {

  if (!is.null(xlim) && xlim != "") {
    xlim <- as.numeric(unlist(strsplit(xlim, ",")))
  } else {
    xlim <- NULL
  }

  if (!is.null(ylim) && ylim != "") {
    ylim <- as.numeric(unlist(strsplit(ylim, ",")))
  } else {
    ylim <- NULL
  }

  # Create a list to hold marker properties
  marker.list <- list()

  # Add optional styling
  if (!is.null(color.by) && color.by != "") {
    marker.list$color <- ~.data[[color.by]]
  }

  if (!is.null(shape.by) && shape.by != "") {
    marker.list$symbol <- ~.data[[shape.by]]
  }

  if (!is.null(size.by) && size.by != "") {
    marker.list$size <- ~.data[[size.by]]
  } else {
    marker.list$size <- point.size
  }

  marker.list$opacity <- opacity

  p <- plot_ly(data, x = ~.data[[x.var]], y = ~.data[[y.var]], type = 'scatter', mode = 'markers', marker = marker.list)

  lines <- NULL

  if (!is.null(vlines) && vlines != "") {
    vlines <- as.numeric(unlist(strsplit(vlines, ",")))
    vlines <- lapply(vlines, function(v) {
      list(type = "line", x0 = v, x1 = v, y0 = 0, y1 = 1, xref = "x", yref = "paper",
          line = list(color = line.color, width = line.width))
    })

    lines <- c(lines, vlines)
  }

  if (!is.null(hlines) && hlines != "") {
    hlines <- as.numeric(unlist(strsplit(hlines, ",")))
    hlines <- lapply(hlines, function(h) {
      list(type = "line", x0 = 0, x1 = 1, y0 = h, y1 = h, xref = "paper", yref = "y",
          line = list(color = line.color, width = line.width))
    })

    lines <- c(lines, hlines)
  }

  p <- p %>% layout(
    xaxis = list(range = xlim, showgrid = gridlines),
    yaxis = list(range = ylim, showgrid = gridlines),
    shapes = lines
  )

  if (!is.null(label.by) && label.by != "") {
    p <- p %>% add_text(text = ~.data[[label.by]])
  }

  p
}

#' Generate scatterplot(s) via Plotly
#'
#' Determines if subplots are needed based on the `split.by` parameter.
#'
#' @param data Data frame containing the data to plot
#' @param x.var Name of the variable for the x-axis
#' @param y.var Name of the variable for the y-axis
#' @param color.by (Optional) Name of the variable for point color
#' @param shape.by (Optional) Name of the variable for point shape
#' @param point.size Size of the points in the plot (default is 6)
#' @param split.by (Optional) Name of the variable to facet the plot
#' 
#' @importFrom plotly subplot
#' 
#' @return A Plotly plot object (either a single plot or a subplot)
#' @examples
#' data <- data.frame(x = rnorm(100), y = rnorm(100), color = rnorm(100), shape = factor(rep(1:2, 50)), split = factor(rep(1:2, each = 50)))
#' make_scatterplot(data, x.var = "x", y.var = "y", color.by = "color", shape.by = "shape", split.by = "split")
make_scatterplot <- function(data, 
                             x.var, 
                             y.var, 
                             color.by = NULL, 
                             shape.by = NULL, 
                             split.by = NULL,
                             gridlines = TRUE, 
                             nrows = NULL, 
                             point.size = 6,
                             size.by = NULL,
                             hlines = NULL, 
                             vlines = NULL, 
                             line.width = 1, 
                             line.color = "black",
                             xlim = NULL, 
                             ylim = NULL, 
                             opacity = 1, 
                             label.by = NULL) {

  if (is.null(split.by) || split.by == "") {
    p <- .scatterplot(data = data, 
                      x.var = x.var, 
                      y.var = y.var, 
                      color.by = color.by, 
                      shape.by = shape.by, 
                      gridlines = gridlines, 
                      point.size = point.size, 
                      size.by = size.by,
                      hlines = hlines, 
                      vlines = vlines, 
                      line.width = line.width, 
                      line.color = line.color,
                      xlim = xlim, 
                      ylim = ylim, 
                      opacity = opacity,  
                      label.by = label.by)
  } else {
    if (is.null(nrows) || nrows == 0) {
      nrows = 1
    }

    plots_list <- lapply(unique(data[[split.by]]), function(val) {
      sub_data <- data[data[[split.by]] == val,]
      .scatterplot(data = sub_data, 
                      x.var = x.var, 
                      y.var = y.var, 
                      color.by = color.by, 
                      shape.by = shape.by, 
                      gridlines = gridlines, 
                      point.size = point.size, 
                      size.by = size.by,
                      hlines = hlines, 
                      vlines = vlines, 
                      line.width = line.width, 
                      line.color = line.color,
                      xlim = xlim, 
                      ylim = ylim, 
                      opacity = opacity, 
                      label.by = label.by)
    })

    p <- subplot(plots_list, nrows = nrows, shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE)
  }

  p
}

###### Module UI ######

#' Input UI components for the scatterplot module
#' @param id The ID for the Shiny module.
#' @param data The data frame used for plot generation.
#' @param columns Number of columns for the UI grid.
#' @param rows Number of rows for the UI grid.
#' @return A Shiny tagList containing the UI elements
#'
#' @importFrom shiny tagList NS selectInput numericInput actionButton
#' @export
#' @author Jared Andrews
scatterplotInputsUI <- function(id, data, columns = 2, rows = NULL) {
  ns <- NS(id)
  choices <- c("", names(data))
  inputs <- list(
    "Point Styling" = tagList(
      selectInput(ns("x.var"), "X Variable:", choices, selected = names(data)[1]),
      selectInput(ns("y.var"), "Y Variable:", choices, selected = names(data)[2]),
      selectInput(ns("color.by"), "Color By:", choices, selected = NULL),
      selectInput(ns("shape.by"), "Shape By:", choices, selected = NULL),
      selectInput(ns("size.by"), "Size By:", choices, selected = NULL),
      numericInput(ns("point.size"), "Point Size:", 6),
      sliderInput(ns("opacity"), "Point Opacity:", min = 0, max = 1, value = 1, step = 0.1),
      selectInput(ns("label.by"), "Label By:", choices, selected = NULL)
    ),
    "Axis & Lines" = tagList(
      textInput(ns("hlines"), "Horizontal Lines (comma-separated):", ""),
      textInput(ns("vlines"), "Vertical Lines (comma-separated):", ""),
      numericInput(ns("line.width"), "Line Width:", 1),
      colourInput(ns("line.color"), "Line Color:", "black"),
      textInput(ns("xlim"), "X-axis Limits (comma-separated):", ""),
      textInput(ns("ylim"), "Y-axis Limits (comma-separated):", ""),
      checkboxInput(ns("gridlines"), "Show Gridlines", TRUE)
    ),
    "Subplots" = tagList(
      selectInput(ns("split.by"), "Split By:", choices, selected = NULL),
      numericInput(ns("nrows"), "Subplot Rows:", 0),
    )
  )

  organize_inputs(inputs, tack = actionButton(ns("update"), "Update Plot"), columns = columns)
}

#' Output UI components for the scatterplot module
#' @param id The ID for the Shiny module
#' @return A Shiny plotlyOutput for the scatterplot
#' @importFrom shiny NS
#' @importFrom plotly plotlyOutput
#' @export
#' @author Jared Andrews
scatterplotOutputUI <- function(id) {
  ns <- NS(id)
  plotlyOutput(ns("scatterplot"))
}

###### Module Server ######

# Server logic for scatterplot module
# @param input Shiny input
# @param output Shiny output
# @param session Shiny session
# @param data The data frame to plot
scatterplotServer <- function(id, data) {
  moduleServer(id, function(input, output, session) {

    output$scatterplot <- renderPlotly({
      input$update

      make_scatterplot(
        data = data,
        x.var = isolate(input$x.var),
        y.var = isolate(input$y.var),
        color.by = isolate(input$color.by),
        shape.by = isolate(input$shape.by),
        split.by = isolate(input$split.by),
        gridlines = isolate(input$gridlines),
        nrows = isolate(input$nrows),
        point.size = isolate(input$point.size),
        size.by = isolate(input$size.by),
        hlines = isolate(input$hlines),
        vlines = isolate(input$vlines),
        line.width = isolate(input$line.width),
        line.color = isolate(input$line.color),
        xlim = isolate(input$xlim),
        ylim = isolate(input$ylim),
        opacity = isolate(input$opacity),
        label.by = isolate(input$label.by)
      )
    })
  })
}

###### Example App ######

ui <- fluidPage(
  titlePanel("Modular Scatterplots"),
  sidebarLayout(
    sidebarPanel(
      scatterplotInputsUI("scatter1", mtcars),
      hr(),
      scatterplotInputsUI("scatter2", iris)
    ),
    mainPanel(
      scatterplotOutputUI("scatter1"),
      hr(),
      scatterplotOutputUI("scatter2")
    )
  )
)

server <- function(input, output, session) {
  scatterplotServer("scatter1", data = mtcars)
  scatterplotServer("scatter2", data = iris)
}

shinyApp(ui, server)

The hope would be to provide a very flexible base module that folks could utilize in their own modules, e.g. volcano/MAplot modules. I don't necessarily have all the details worked out for how they could be built upon, but I think the idea has legs. The basic modules package will probably find its way to CRAN, but one built upon it with more specific modules for bioinformatics might make it to Bioconductor at a later date. That's the hope, though carving out time to do so is always a challenge.

bioc-issue-bot commented 7 months ago

Dear Package contributor,

This is the automated single package builder at bioconductor.org.

Your package has been built on the Bioconductor Single Package Builder.

On one or more platforms, the build results were: "WARNINGS". This may mean there is a problem with the package that you need to fix. Or it may mean that there is a problem with the build system itself.

Please see the build report for more details.

The following are build products from R CMD build on the Single Package Builder: Linux (Ubuntu 22.04.2 LTS): CRISPRball_0.99.5.tar.gz macOS 12.7.1 Monterey: CRISPRball_0.99.5.tar.gz

Links above active for 21 days.

Remember: if you submitted your package after July 7th, 2020, when making changes to your repository push to git@git.bioconductor.org:packages/CRISPRball to trigger a new build. A quick tutorial for setting up remotes and pushing to upstream can be found here.

bioc-issue-bot commented 7 months ago

Received a valid push on git.bioconductor.org; starting a build for commit id: 7ffb2cacea0c290d841d3fc421aa622e4ef6fad3

j-andrews7 commented 7 months ago

Naturally, check is hitting the 10 minute limit now. I will work to shorten it, though it may require use of dontrun on an example or two as noted above.

bioc-issue-bot commented 7 months ago

Dear Package contributor,

This is the automated single package builder at bioconductor.org.

Your package has been built on the Bioconductor Single Package Builder.

On one or more platforms, the build results were: "WARNINGS". This may mean there is a problem with the package that you need to fix. Or it may mean that there is a problem with the build system itself.

Please see the build report for more details.

The following are build products from R CMD build on the Single Package Builder: Linux (Ubuntu 22.04.2 LTS): CRISPRball_0.99.6.tar.gz macOS 12.7.1 Monterey: CRISPRball_0.99.6.tar.gz

Links above active for 21 days.

Remember: if you submitted your package after July 7th, 2020, when making changes to your repository push to git@git.bioconductor.org:packages/CRISPRball to trigger a new build. A quick tutorial for setting up remotes and pushing to upstream can be found here.

vjcitn commented 7 months ago

The modules sketch is very helpful, thanks!

bioc-issue-bot commented 7 months ago

Received a valid push on git.bioconductor.org; starting a build for commit id: 5327b228c2c68e5fe14192a05b6826a9d1570666

bioc-issue-bot commented 7 months ago

Dear Package contributor,

This is the automated single package builder at bioconductor.org.

Your package has been built on the Bioconductor Single Package Builder.

On one or more platforms, the build results were: "WARNINGS". This may mean there is a problem with the package that you need to fix. Or it may mean that there is a problem with the build system itself.

Please see the build report for more details.

The following are build products from R CMD build on the Single Package Builder: Linux (Ubuntu 22.04.2 LTS): CRISPRball_0.99.7.tar.gz macOS 12.7.1 Monterey: CRISPRball_0.99.7.tar.gz

Links above active for 21 days.

Remember: if you submitted your package after July 7th, 2020, when making changes to your repository push to git@git.bioconductor.org:packages/CRISPRball to trigger a new build. A quick tutorial for setting up remotes and pushing to upstream can be found here.

bioc-issue-bot commented 7 months ago

Received a valid push on git.bioconductor.org; starting a build for commit id: 2a4d9e7ef1f34f99e4d9cba8d08d080654f62895

bioc-issue-bot commented 7 months ago

Dear Package contributor,

This is the automated single package builder at bioconductor.org.

Your package has been built on the Bioconductor Single Package Builder.

Congratulations! The package built without errors or warnings on all platforms.

Please see the build report for more details.

The following are build products from R CMD build on the Single Package Builder: macOS 12.7.1 Monterey: CRISPRball_0.99.8.tar.gz Linux (Ubuntu 22.04.2 LTS): CRISPRball_0.99.8.tar.gz

Links above active for 21 days.

Remember: if you submitted your package after July 7th, 2020, when making changes to your repository push to git@git.bioconductor.org:packages/CRISPRball to trigger a new build. A quick tutorial for setting up remotes and pushing to upstream can be found here.

j-andrews7 commented 7 months ago

Swapped out one example to not run, as the data download just takes too long.

vjcitn commented 7 months ago

A data download should not be part of standard SPB checking, or part of mature package behavior on check. Are you using BiocFileCache or a Hub contribution? If you are and the event is a one-off, then once it succeeds, bump the version and the next check should not do any downloading but just restore from cache/hub.

j-andrews7 commented 7 months ago

It's through ExperimentHub via the depmap package. It gets stored as a SQLite database that is used by the app. There are longtests that check the database construction functionality, it's just the example for one function that ends up taking over a minute to run and pushing total check time over 10.

Will give it a check and bump the version again.

On Sun, Nov 26, 2023, 5:43 AM Vince Carey @.***> wrote:

A data download should not be part of standard SPB checking, or part of mature package behavior on check. Are you using BiocFileCache or a Hub contribution? If you are and the event is a one-off, then once it succeeds, bump the version and the next check should not do any downloading but just restore from cache/hub.

— Reply to this email directly, view it on GitHub https://github.com/Bioconductor/Contributions/issues/3163#issuecomment-1826760922, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACOAQNA5DEOV5ZHFB32VC6TYGMTNNAVCNFSM6AAAAAA5FHEMA6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQMRWG43DAOJSGI . You are receiving this because you were mentioned.Message ID: @.***>

bioc-issue-bot commented 7 months ago

Received a valid push on git.bioconductor.org; starting a build for commit id: 8316cd0fc65c3f7d067421d23a1b2d826277d69b

bioc-issue-bot commented 7 months ago

Dear Package contributor,

This is the automated single package builder at bioconductor.org.

Your package has been built on the Bioconductor Single Package Builder.

On one or more platforms, the build results were: "WARNINGS, ERROR". This may mean there is a problem with the package that you need to fix. Or it may mean that there is a problem with the build system itself.

Please see the build report for more details.

The following are build products from R CMD build on the Single Package Builder: Linux (Ubuntu 22.04.2 LTS): CRISPRball_0.99.9.tar.gz macOS 12.7.1 Monterey: CRISPRball_0.99.9.tar.gz

Links above active for 21 days.

Remember: if you submitted your package after July 7th, 2020, when making changes to your repository push to git@git.bioconductor.org:packages/CRISPRball to trigger a new build. A quick tutorial for setting up remotes and pushing to upstream can be found here.

bioc-issue-bot commented 7 months ago

Received a valid push on git.bioconductor.org; starting a build for commit id: bfd09589a6029a7f07eee96c1dfbccdd939d3080

bioc-issue-bot commented 7 months ago

Dear Package contributor,

This is the automated single package builder at bioconductor.org.

Your package has been built on the Bioconductor Single Package Builder.

On one or more platforms, the build results were: "WARNINGS". This may mean there is a problem with the package that you need to fix. Or it may mean that there is a problem with the build system itself.

Please see the build report for more details.

The following are build products from R CMD build on the Single Package Builder: Linux (Ubuntu 22.04.2 LTS): CRISPRball_0.99.10.tar.gz macOS 12.7.1 Monterey: CRISPRball_0.99.10.tar.gz

Links above active for 21 days.

Remember: if you submitted your package after July 7th, 2020, when making changes to your repository push to git@git.bioconductor.org:packages/CRISPRball to trigger a new build. A quick tutorial for setting up remotes and pushing to upstream can be found here.

j-andrews7 commented 7 months ago

I am not sure what's throwing a warning here, though the build report only has the linux build shown. I've checked that the longtests run fine, so I am not sure what else needs be done here.

kevinrue commented 7 months ago

Do I see lik you and the report says all OK or skipped? Sounds like it's an issue in the single package builder not your package. I think you've done what you could: notify the reviewer and wait. In any case that's what I would have done :)

j-andrews7 commented 7 months ago

@vjcitn any other feedback here? As Kevin mentioned, the build report has all OK or skipped, so I don't know where the "WARNINGS" tag is coming from.

Should I bump the version to trigger another build?

lshep commented 7 months ago

there was a bug that prevented the mac build from showing; likely came from there. But I'm okay with moving forward. I'll take one last look today

bioc-issue-bot commented 7 months ago

Your package has been accepted. It will be added to the Bioconductor nightly builds.

Thank you for contributing to Bioconductor!

Reviewers for Bioconductor packages are volunteers from the Bioconductor community. If you are interested in becoming a Bioconductor package reviewer, please see Reviewers Expectations.

lshep commented 7 months ago

The default branch of your GitHub repository has been added to Bioconductor's git repository as branch devel.

To use the git.bioconductor.org repository, we need an 'ssh' key to associate with your github user name. If your GitHub account already has ssh public keys (https://github.com/j-andrews7.keys is not empty), then no further steps are required. Otherwise, do the following:

  1. Add an SSH key to your github account
  2. Submit your SSH key to Bioconductor

See further instructions at

https://bioconductor.org/developers/how-to/git/

for working with this repository. See especially

https://bioconductor.org/developers/how-to/git/new-package-workflow/ https://bioconductor.org/developers/how-to/git/sync-existing-repositories/

to keep your GitHub and Bioconductor repositories in sync.

Your package will be included in the next nigthly 'devel' build (check-out from git at about 6 pm Eastern; build completion around 2pm Eastern the next day) at

https://bioconductor.org/checkResults/

(Builds sometimes fail, so ensure that the date stamps on the main landing page are consistent with the addition of your package). Once the package builds successfully, you package will be available for download in the 'Devel' version of Bioconductor using BiocManager::install("CRISPRball"). The package 'landing page' will be created at

https://bioconductor.org/packages/CRISPRball

If you have any questions, please contact the bioc-devel mailing list (https://stat.ethz.ch/mailman/listinfo/bioc-devel); this issue will not be monitored further.

j-andrews7 commented 7 months ago

Thanks to all for the reviews and comments, they were very much appreciated!