Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DimPlot convenience functions infer arguments from the call stack #9436

Open
rharao opened this issue Oct 28, 2024 · 0 comments
Open

DimPlot convenience functions infer arguments from the call stack #9436

rharao opened this issue Oct 28, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@rharao
Copy link

rharao commented Oct 28, 2024

The convenience functions for DimPlot through SpecificDimPlot (namely, PCAPlot, TSNEPlot, and UMAPPlot) rely on false assumptions.

Example: Try running Seurat::UMAPPlot (specifying the namespace rather than just getting UMAPPlot from the search list) on a Seurat object that has a "umap" reduction. One should expect the function to access this with .[["umap"]].

Error in object[[reduction]] : 
  'seurat::umap' not found in this Seurat object

It's trying to find .[["seurat::umap"]] because, instead of UMAPPlot just calling DimPlot with reduction = "umap", SpecificDimPlot is doing string manipulations on the call stack to guess which particular convenience function was called.

Existing code for UMAPPlot, TSNEPlot, and PCAPlot are identical down to the bytecode: they pass their object and dots arguments, unmodified, to the non-exported SpecificDimPlot, and return the result, unmodified. There is no logic on either side and they are bare aliases for the unexposed function; their only purpose is to show up on the call stack.

SpecificDimPlot as it is (comments mine):

function (object, ...) 
{
    funs <- sys.calls()
    # Get the name of the preceding function on the call stack as a string
    name <- as.character(x = funs[[length(x = funs) - 1]])[1]
    # Remove the substring "Plot", if it's there, and convert to lowercase
    # This string is the guessed reduction name for now
    name <- tolower(x = gsub(pattern = "Plot", replacement = "", 
        x = name))
    # Put the input args in a list
    args <- list(object = object)
    args <- c(args, list(...))
    # Tentative better guess (this is undocumented):
    # Search in the names of the object for any string that has _both_
    # the guessed reduction name (case insensitive) _and_
    # the object's default assay name (case sensitive) as substrings
    reduc <- grep(pattern = name, x = names(x = object), value = TRUE, 
        ignore.case = TRUE)
    reduc <- grep(pattern = DefaultAssay(object = object), x = reduc, 
        value = TRUE)
    # If zero or multiple of those strings were found, just use the first guess
    # Update the args list with the guess
    args$reduction <- ifelse(test = length(x = reduc) == 1, yes = reduc, 
        no = name)
    # Now pass the whole thing on to `DimPlot` and hope the guess was right
    tryCatch(expr = return(do.call(what = "DimPlot", args = args)), 
        error = function(e) {
            stop(e)
        })
}

Some situations in which this can mislead or stop the user:

  • User is doing a multiple assay analysis and has the following reductions in the object: "assay1.pca", "assay2.svd", and "pca". The default assay of the object is "assay1".

    • Expected: PCAPlot leads to DimPlot with reduction = "pca".
    • Current: PCAPlot leads to DimPlot with reduction = "assay1.pca" without a warning.
  • User has another package loaded that masks UMAPPlot.

  • User has another package loaded that provides umapplot and wants to clarify to the reader that Seurat::UMAPPlot is to be used.

  • User does not have Seurat loaded but wants to take a quick peek at a Seurat object's UMAP embedding.

    • Expected: Seurat::UMAPPlot leads to Seurat::DimPlot with reduction = "umap".
    • Current: Seurat::UMAPPlot leads to Seurat::DimPlot with reduction = "seurat::umap", causing an error when that doesn't exist.
  • Object has assays "hts" and "htsNew" and reductions "pca" and "tsne". Default assay is "htsNew".

    • Expected: TSNEPlot leads to DimPlot with reduction = "tsne".
    • Current: DimPlot calls .[["htsNew"]], getting the assay instead of the reduction, causing an error; "htsNew" is exposed in names(.) and passes the string logic.
  • A developer is trying to implement their own convenience function, FDGPlot, which has a call to SpecificDimPlot in its body, but within an intermediate function call.

    • Current: The string logic on the call stack will fail because FDGPlot itself will not be at the second-to-top position.

Here is my general idea for how this could be replaced:

# Not exported
SpecificDimPlot <- function(object, ..., .reduction) {
  dots <- list(...)
  if ("reduction" %in% names(dots) && dots$reduction != .reduction) {
    warning(
    "SpecificDimPlot: Ignoring supplied `reduction` argument in favor of '",
    .reduction,
    "'. Use DimPlot to choose any reduction.")
  }
  dots$reduction <- NULL
  reductions <- Reductions(object = object)
  if (! .reduction %in% reductions) {
    reductions <- grep(
      pattern = .reduction,
      x = reductions,
      ignore.case = TRUE,
      value = TRUE)
    if (length(reductions) > 0) {
      # If the requested reduction is not available but others pass grep,
      # use the first one with a warning
      warning(
        "SpecificDimPlot: '",
        .reduction,
        "' not found in this object's reductions. Using '",
        .reduction <- reductions[1],
        "' instead. Use DimPlot to choose any reduction.")
    } else {
      stop(
        "Could not find '",
        .reduction,
        "' in this object's reductions. Use DimPlot to choose any reduction.")
    }
  }
  args <- c(list(object = object, reduction = .reduction), dots)
  tryCatch(
    expr = return(do.call(what = "DimPlot", args = args)),
    error = \(e) stop(e)
  )
}

# Exported
PCAPlot <- \(object, ...) {
  return(SpecificDimPlot(object = object, ..., .reduction = "pca"))
}
TSNEPlot <- \(object, ...) {
  return(SpecificDimPlot(object = object, ..., .reduction = "tsne" ))
}
UMAPPlot <- \(object, ...) {
  return(SpecificDimPlot(object = object, ..., .reduction = "umap"))
}

Would the maintainers be open to a PR regarding this?

Session info ``` - Session info ---------------------------------------------------------------- setting value version R version 4.2.2 Patched (2022-11-10 r83330) os Debian GNU/Linux 12 (bookworm) system x86_64, linux-gnu ui RStudio language (EN) collate en_US.UTF-8 ctype en_US.UTF-8 tz US/Eastern date 2024-10-25 rstudio 2023.12.1+402 Ocean Storm (server) pandoc 3.1.1 @ /usr/lib/rstudio-server/bin/quarto/bin/tools/ (via rmarkdown)
  • Packages --------------------------------------------------------------------
    package * version date (UTC) lib source
    abind 1.4-5 2016-07-21 [1] CRAN (R 4.2.2)
    AnnotationDbi 1.60.2 2023-03-10 [1] Bioconductor
    AnnotationFilter 1.22.0 2022-11-01 [1] Bioconductor
    beachmat 2.14.2 2023-04-07 [1] Bioconductor
    beeswarm 0.4.0 2021-06-01 [1] CRAN (R 4.2.2)
    Biobase 2.58.0 2022-11-01 [1] Bioconductor
    BiocFileCache 2.6.1 2023-02-17 [1] Bioconductor
    BiocGenerics 0.44.0 2022-11-01 [1] Bioconductor
    BiocIO 1.8.0 2022-11-01 [1] Bioconductor
    BiocNeighbors 1.16.0 2022-11-01 [1] Bioconductor
    BiocParallel 1.32.6 2023-03-17 [1] Bioconductor
    BiocSingular 1.14.0 2022-11-01 [1] Bioconductor
    biomaRt 2.54.1 2023-03-20 [1] Bioconductor
    Biostrings 2.66.0 2022-11-01 [1] Bioconductor
    bit 4.0.5 2022-11-15 [1] CRAN (R 4.2.2)
    bit64 4.0.5 2020-08-30 [1] CRAN (R 4.2.2)
    bitops 1.0-8 2024-07-29 [1] CRAN (R 4.2.2)
    blob 1.2.4 2023-03-17 [1] CRAN (R 4.2.2)
    bluster 1.8.0 2022-11-01 [1] Bioconductor
    cachem 1.1.0 2024-05-16 [1] CRAN (R 4.2.2)
    cli 3.6.3 2024-06-21 [1] CRAN (R 4.2.2)
    clipr 0.8.0 2022-02-22 [1] CRAN (R 4.2.2)
    cluster 2.1.4 2022-08-22 [4] CRAN (R 4.2.1)
    codetools 0.2-19 2023-02-01 [4] CRAN (R 4.2.2)
    colorspace 2.1-1 2024-07-26 [1] CRAN (R 4.2.2)
    cowplot 1.1.3 2024-01-22 [1] CRAN (R 4.2.2)
    crayon 1.5.3 2024-06-20 [1] CRAN (R 4.2.2)
    curl 5.2.2 2024-08-26 [1] CRAN (R 4.2.2)
    data.table 1.16.0 2024-08-27 [1] CRAN (R 4.2.2)
    DBI 1.2.3 2024-06-02 [1] CRAN (R 4.2.2)
    dbplyr 2.5.0 2024-03-19 [1] CRAN (R 4.2.2)
    DelayedArray 0.24.0 2022-11-01 [1] Bioconductor
    DelayedMatrixStats 1.20.0 2022-11-01 [1] Bioconductor
    deldir 2.0-4 2024-02-28 [1] CRAN (R 4.2.2)
    digest 0.6.37 2024-08-19 [1] CRAN (R 4.2.2)
    dotCall64 1.1-1 2023-11-28 [1] CRAN (R 4.2.2)
    dplyr 1.1.4 2023-11-17 [1] CRAN (R 4.2.2)
    dqrng 0.4.1 2024-05-28 [1] CRAN (R 4.2.2)
    edgeR 3.40.2 2023-01-19 [1] Bioconductor
    ensembldb 2.22.0 2022-11-01 [1] Bioconductor
    evaluate 0.24.0 2024-06-10 [1] CRAN (R 4.2.2)
    fansi 1.0.6 2023-12-08 [1] CRAN (R 4.2.2)
    farver 2.1.2 2024-05-13 [1] CRAN (R 4.2.2)
    fastDummies 1.7.4 2024-08-16 [1] CRAN (R 4.2.2)
    fastmap 1.2.0 2024-05-15 [1] CRAN (R 4.2.2)
    filelock 1.0.3 2023-12-11 [1] CRAN (R 4.2.2)
    fitdistrplus 1.2-1 2024-07-12 [1] CRAN (R 4.2.2)
    future 1.34.0 2024-07-29 [1] CRAN (R 4.2.2)
    future.apply 1.11.2 2024-03-28 [1] CRAN (R 4.2.2)
    generics 0.1.3 2022-07-05 [1] CRAN (R 4.2.2)
    GenomeInfoDb 1.34.9 2023-02-02 [1] Bioconductor
    GenomeInfoDbData 1.2.9 2024-04-01 [1] Bioconductor
    GenomicAlignments 1.34.1 2023-03-09 [1] Bioconductor
    GenomicFeatures 1.50.4 2023-01-24 [1] Bioconductor
    GenomicRanges 1.50.2 2022-12-16 [1] Bioconductor
    ggbeeswarm 0.7.2 2023-04-29 [1] CRAN (R 4.2.2)
    ggplot2 3.5.1 2024-04-23 [1] CRAN (R 4.2.2)
    ggrastr 1.0.2 2023-06-01 [1] CRAN (R 4.2.2)
    ggrepel 0.9.5 2024-01-10 [1] CRAN (R 4.2.2)
    ggridges 0.5.6 2024-01-23 [1] CRAN (R 4.2.2)
    globals 0.16.3 2024-03-08 [1] CRAN (R 4.2.2)
    glue 1.7.0 2024-01-09 [1] CRAN (R 4.2.2)
    goftest 1.2-3 2021-10-07 [1] CRAN (R 4.2.2)
    gridExtra 2.3 2017-09-09 [1] CRAN (R 4.2.2)
    gtable 0.3.5 2024-04-22 [1] CRAN (R 4.2.2)
    hms 1.1.3 2023-03-21 [1] CRAN (R 4.2.2)
    htmltools 0.5.8.1 2024-04-04 [1] CRAN (R 4.2.2)
    htmlwidgets 1.6.4 2023-12-06 [1] CRAN (R 4.2.2)
    httpuv 1.6.15 2024-03-26 [1] CRAN (R 4.2.2)
    httr 1.4.7 2023-08-15 [1] CRAN (R 4.2.2)
    ica 1.0-3 2022-07-08 [1] CRAN (R 4.2.2)
    igraph 2.0.3 2024-03-13 [1] CRAN (R 4.2.2)
    IRanges 2.32.0 2022-11-01 [1] Bioconductor
    irlba 2.3.5.1 2022-10-03 [1] CRAN (R 4.2.2)
    jsonlite 1.8.8 2023-12-04 [1] CRAN (R 4.2.2)
    KEGGREST 1.38.0 2022-11-01 [1] Bioconductor
    KernSmooth 2.23-20 2021-05-03 [4] CRAN (R 4.0.4)
    knitr 1.48 2024-07-07 [1] CRAN (R 4.2.2)
    labeling 0.4.3 2023-08-29 [1] CRAN (R 4.2.2)
    later 1.3.2 2023-12-06 [1] CRAN (R 4.2.2)
    lattice 0.20-45 2021-09-22 [4] CRAN (R 4.2.0)
    lazyeval 0.2.2 2019-03-15 [1] CRAN (R 4.2.2)
    leiden 0.4.3.1 2023-11-17 [1] CRAN (R 4.2.2)
    lifecycle 1.0.4 2023-11-07 [1] CRAN (R 4.2.2)
    limma 3.54.2 2023-02-28 [1] Bioconductor
    listenv 0.9.1 2024-01-29 [1] CRAN (R 4.2.2)
    lmtest 0.9-40 2022-03-21 [1] CRAN (R 4.2.2)
    locfit 1.5-9.10 2024-06-24 [1] CRAN (R 4.2.2)
    magrittr 2.0.3 2022-03-30 [1] CRAN (R 4.2.2)
    MASS 7.3-58.2 2023-01-23 [4] CRAN (R 4.2.2)
    Matrix 1.6-5 2024-01-11 [1] CRAN (R 4.2.2)
    MatrixGenerics 1.10.0 2022-11-01 [1] Bioconductor
    matrixStats 1.1.0 2023-11-07 [1] CRAN (R 4.2.2)
    memoise 2.0.1 2021-11-26 [1] CRAN (R 4.2.2)
    metapod 1.6.0 2022-11-01 [1] Bioconductor
    mime 0.12 2021-09-28 [1] CRAN (R 4.2.2)
    miniUI 0.1.1.1 2018-05-18 [1] CRAN (R 4.2.2)
    munsell 0.5.1 2024-04-01 [1] CRAN (R 4.2.2)
    nlme 3.1-162 2023-01-31 [4] CRAN (R 4.2.2)
    parallelly 1.38.0 2024-07-27 [1] CRAN (R 4.2.2)
    patchwork 1.2.0 2024-01-08 [1] CRAN (R 4.2.2)
    pbapply 1.7-2 2023-06-27 [1] CRAN (R 4.2.2)
    pillar 1.9.0 2023-03-22 [1] CRAN (R 4.2.2)
    pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.2.2)
    pkgload 1.4.0 2024-06-28 [1] CRAN (R 4.2.2)
    plotly 4.10.4 2024-01-13 [1] CRAN (R 4.2.2)
    plyr 1.8.9 2023-10-02 [1] CRAN (R 4.2.2)
    png 0.1-8 2022-11-29 [1] CRAN (R 4.2.2)
    polyclip 1.10-7 2024-07-23 [1] CRAN (R 4.2.2)
    prettyunits 1.2.0 2023-09-24 [1] CRAN (R 4.2.2)
    progress 1.2.3 2023-12-06 [1] CRAN (R 4.2.2)
    progressr 0.14.0 2023-08-10 [1] CRAN (R 4.2.2)
    promises 1.3.0 2024-04-05 [1] CRAN (R 4.2.2)
    ProtGenerics 1.30.0 2022-11-01 [1] Bioconductor
    purrr 1.0.2 2023-08-10 [1] CRAN (R 4.2.2)
    R6 2.5.1 2021-08-19 [1] CRAN (R 4.2.2)
    RANN 2.6.2 2024-08-25 [1] CRAN (R 4.2.2)
    rappdirs 0.3.3 2021-01-31 [1] CRAN (R 4.2.2)
    RColorBrewer 1.1-3 2022-04-03 [1] CRAN (R 4.2.2)
    Rcpp 1.0.13 2024-07-17 [1] CRAN (R 4.2.2)
    RcppAnnoy 0.0.22 2024-01-23 [1] CRAN (R 4.2.2)
    RcppHNSW 0.6.0 2024-02-04 [1] CRAN (R 4.2.2)
    RCurl 1.98-1.16 2024-07-11 [1] CRAN (R 4.2.2)
    reshape2 1.4.4 2020-04-09 [1] CRAN (R 4.2.2)
    restfulr 0.0.15 2022-06-16 [1] CRAN (R 4.2.2)
    reticulate 1.38.0 2024-06-19 [1] CRAN (R 4.2.2)
    rjson 0.2.21 2022-01-09 [1] CRAN (R 4.2.2)
    rlang 1.1.4 2024-06-04 [1] CRAN (R 4.2.2)
    rmarkdown 2.28 2024-08-17 [1] CRAN (R 4.2.2)
    ROCR 1.0-11 2020-05-02 [1] CRAN (R 4.2.2)
    Rsamtools 2.14.0 2022-11-01 [1] Bioconductor
    RSpectra 0.16-2 2024-07-18 [1] CRAN (R 4.2.2)
    RSQLite 2.3.7 2024-05-27 [1] CRAN (R 4.2.2)
    rstudioapi 0.16.0 2024-03-24 [1] CRAN (R 4.2.2)
    rsvd 1.0.5 2021-04-16 [1] CRAN (R 4.2.2)
    rtracklayer 1.58.0 2022-11-01 [1] Bioconductor
    Rtsne 0.17 2023-12-07 [1] CRAN (R 4.2.2)
    S4Vectors 0.36.2 2023-02-26 [1] Bioconductor
    ScaledMatrix 1.6.0 2022-11-01 [1] Bioconductor
    scales 1.3.0 2023-11-28 [1] CRAN (R 4.2.2)
    scater 1.26.1 2022-11-13 [1] Bioconductor
    scattermore 1.2 2023-06-12 [1] CRAN (R 4.2.2)
    scran 1.26.2 2023-01-19 [1] Bioconductor
    sctransform 0.4.1 2023-10-19 [1] CRAN (R 4.2.2)
    scuttle 1.8.4 2023-01-19 [1] Bioconductor
    sessioninfo 1.2.2 2021-12-06 [1] CRAN (R 4.2.2)
    Seurat 5.1.0 2024-05-10 [1] CRAN (R 4.2.2)
    SeuratObject * 5.0.2 2024-05-08 [1] CRAN (R 4.2.2)
    shiny 1.9.1 2024-08-01 [1] CRAN (R 4.2.2)
    SingleCellExperiment 1.20.1 2023-03-17 [1] Bioconductor
    sp * 2.1-4 2024-04-30 [1] CRAN (R 4.2.2)
    spam 2.10-0 2023-10-23 [1] CRAN (R 4.2.2)
    sparseMatrixStats 1.10.0 2022-11-01 [1] Bioconductor
    spatstat.data 3.1-2 2024-06-21 [1] CRAN (R 4.2.2)
    spatstat.explore 3.3-2 2024-08-21 [1] CRAN (R 4.2.2)
    spatstat.geom 3.3-2 2024-07-15 [1] CRAN (R 4.2.2)
    spatstat.random 3.3-1 2024-07-15 [1] CRAN (R 4.2.2)
    spatstat.sparse 3.1-0 2024-06-21 [1] CRAN (R 4.2.2)
    spatstat.univar 3.0-0 2024-06-28 [1] CRAN (R 4.2.2)
    spatstat.utils 3.1-0 2024-08-17 [1] CRAN (R 4.2.2)
    statmod 1.5.0 2023-01-06 [1] CRAN (R 4.2.2)
    stringi 1.8.4 2024-05-06 [1] CRAN (R 4.2.2)
    stringr 1.5.1 2023-11-14 [1] CRAN (R 4.2.2)
    SummarizedExperiment 1.28.0 2022-11-01 [1] Bioconductor
    survival 3.5-3 2023-02-12 [4] CRAN (R 4.2.2)
    tensor 1.5 2012-05-05 [1] CRAN (R 4.2.2)
    tibble 3.2.1 2023-03-20 [1] CRAN (R 4.2.2)
    tidyr 1.3.1 2024-01-24 [1] CRAN (R 4.2.2)
    tidyselect 1.2.1 2024-03-11 [1] CRAN (R 4.2.2)
    utf8 1.2.4 2023-10-22 [1] CRAN (R 4.2.2)
    uwot 0.2.2 2024-04-21 [1] CRAN (R 4.2.2)
    vctrs 0.6.5 2023-12-01 [1] CRAN (R 4.2.2)
    vipor 0.4.7 2023-12-18 [1] CRAN (R 4.2.2)
    viridis 0.6.5 2024-01-29 [1] CRAN (R 4.2.2)
    viridisLite 0.4.2 2023-05-02 [1] CRAN (R 4.2.2)
    withr 3.0.1 2024-07-31 [1] CRAN (R 4.2.2)
    xfun 0.47 2024-08-17 [1] CRAN (R 4.2.2)
    XML 3.99-0.17 2024-06-25 [1] CRAN (R 4.2.2)
    xml2 1.3.6 2023-12-04 [1] CRAN (R 4.2.2)
    xtable 1.8-4 2019-04-21 [1] CRAN (R 4.2.2)
    XVector 0.38.0 2022-11-01 [1] Bioconductor
    yaml 2.3.10 2024-07-26 [1] CRAN (R 4.2.2)
    zlibbioc 1.44.0 2022-11-01 [1] Bioconductor
    zoo 1.8-12 2023-04-13 [1] CRAN (R 4.2.2)

[1] /home/rao/R/x86_64-pc-linux-gnu-library/4.2
[2] /usr/local/lib/R/site-library
[3] /usr/lib/R/site-library
[4] /usr/lib/R/library


</details>
@rharao rharao added the bug Something isn't working label Oct 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant