diff --git a/DESCRIPTION b/DESCRIPTION index 4d26cbe00..b23f1f21c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: Seurat -Version: 4.1.0 -Date: 2022-01-14 +Version: 4.1.1 +Date: 2022-05-01 Title: Tools for Single Cell Genomics Description: A toolkit for quality control, analysis, and exploration of single cell RNA sequencing data. 'Seurat' aims to enable users to identify and interpret sources of heterogeneity from single cell transcriptomic measurements, and to integrate diverse types of single cell data. See Satija R, Farrell J, Gennert D, et al (2015) , Macosko E, Basu A, Satija R, et al (2015) , Stuart T, Butler A, et al (2019) , and Hao, Hao, et al (2020) for more details. Authors@R: c( @@ -66,7 +66,7 @@ Imports: scales, scattermore (>= 0.7), sctransform (>= 0.3.3), - SeuratObject (>= 4.0.4), + SeuratObject (>= 4.1.0), shiny, spatstat.core, spatstat.geom, diff --git a/NEWS.md b/NEWS.md index a83239ffa..27201ac2e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,7 +1,19 @@ +# Seurat 4.1.1 (2022-05-01) + +## Changes +- Fix `giveCsparse` related warnings in `Read10X_h5` +- Fix ident labeling for `SpatialPlot` ([#5774](https://github.com/satijalab/seurat/issues/5774)) +- Fix `ReadMtx` on Windows ([#5687](https://github.com/satijalab/seurat/issues/5687)) +- Fix `VlnPlot` to switch on rasterization only when required ([#5846](https://github.com/satijalab/seurat/pull/5846)) +- Fix `ncol` behavior in `SpatialPlot` ([#5774](https://github.com/satijalab/seurat/issues/5774)) +- Set `jitter` to FALSE in `FeatureScatter` ([#5876](https://github.com/satijalab/seurat/pull/5876)) +- Update `Cells` methods to new signature (`x, ...`) +- Replace use of `default.stringsAsFactors()` with `getOption("stringsAsFactors")` + # Seurat 4.1.0 (2022-01-14) ## Added - Add `raster.dpi` parameter to `DimPlot/FeaturePlot` to optionally rasterize individual points ([#5392](https://github.com/satijalab/seurat/pull/5392)) -- Add support for sctransform v2, differential expression on with SCT +- Add support for sctransform v2, differential expression with SCT assay ## Changes - Update `ReadParseBio` to support split-pipe 0.9.6p ([#5446](https://github.com/satijalab/seurat/pull/5446)) diff --git a/R/generics.R b/R/generics.R index f1a10e795..0b6120813 100644 --- a/R/generics.R +++ b/R/generics.R @@ -444,7 +444,7 @@ RunPCA <- function(object, ...) { #' Run Supervised Latent Semantic Indexing #' #' Run a supervised LSI (SLSI) dimensionality reduction supervised by a -#' cell-cell kernel. SLSI is used to capture a linear transformation of peaks +#' cell-cell kernel. SLSI is used to capture a linear transformation of peaks #' that maximizes its dependency to the given cell-cell kernel. #' #' @param object An object @@ -452,7 +452,7 @@ RunPCA <- function(object, ...) { #' #' @return Returns Seurat object with the SLSI calculation stored in the #' reductions slot -#' +#' #' @export #' #' @rdname RunSLSI @@ -506,8 +506,9 @@ RunTSNE <- function(object, ...) { #' Run UMAP #' #' Runs the Uniform Manifold Approximation and Projection (UMAP) dimensional -#' reduction technique. To run, you must first install the umap-learn python -#' package (e.g. via \code{pip install umap-learn}). Details on this package can be +#' reduction technique. To run using \code{umap.method="umap-learn"}, you must +#' first install the umap-learn python package (e.g. via +#' \code{pip install umap-learn}). Details on this package can be #' found here: \url{https://github.com/lmcinnes/umap}. For a more in depth #' discussion of the mathematics underlying UMAP, see the ArXiv paper here: #' \url{https://arxiv.org/abs/1802.03426}. diff --git a/R/objects.R b/R/objects.R index db9f67983..d84d74226 100644 --- a/R/objects.R +++ b/R/objects.R @@ -454,6 +454,7 @@ CreateSCTAssayObject <- function( #' remove all DimReducs) #' @param graphs Only keep a subset of Graphs specified here (if NULL, remove #' all Graphs) +#' @param misc Preserve the \code{misc} slot; default is \code{TRUE} #' #' @export #' @concept objects @@ -466,7 +467,8 @@ DietSeurat <- function( features = NULL, assays = NULL, dimreducs = NULL, - graphs = NULL + graphs = NULL, + misc = TRUE ) { object <- UpdateSlots(object = object) assays <- assays %||% FilterObjects(object = object, classes.keep = "Assay") @@ -508,6 +510,11 @@ DietSeurat <- function( } } } + # remove misc when desired + if (!isTRUE(x = misc)) { + slot(object = object, name = "misc") <- list() + } + # remove unspecified DimReducs and Graphs all.objects <- FilterObjects(object = object, classes.keep = c('DimReduc', 'Graph')) objects.to.remove <- all.objects[!all.objects %in% c(dimreducs, graphs)] @@ -1301,7 +1308,7 @@ as.sparse.H5Group <- function(x, ...) { #' @method Cells SCTModel #' @export #' -Cells.SCTModel <- function(x) { +Cells.SCTModel <- function(x, ...) { return(rownames(x = slot(object = x, name = "cell.attributes"))) } @@ -1313,7 +1320,7 @@ Cells.SCTModel <- function(x) { #' #' @seealso \code{\link[SeuratObject:Cells]{SeuratObject::Cells}} #' -Cells.SlideSeq <- function(x) { +Cells.SlideSeq <- function(x, ...) { return(rownames(x = GetTissueCoordinates(object = x))) } @@ -1323,7 +1330,7 @@ Cells.SlideSeq <- function(x) { #' @method Cells STARmap #' @export #' -Cells.STARmap <- function(x) { +Cells.STARmap <- function(x, ...) { return(rownames(x = GetTissueCoordinates(object = x))) } @@ -1332,7 +1339,7 @@ Cells.STARmap <- function(x) { #' @method Cells VisiumV1 #' @export #' -Cells.VisiumV1 <- function(x) { +Cells.VisiumV1 <- function(x, ...) { return(rownames(x = GetTissueCoordinates(object = x, scale = NULL))) } @@ -2274,7 +2281,7 @@ setMethod( definition = function(object) { cat('An AnchorSet object containing', nrow(x = slot(object = object, name = "anchors")), "anchors between the reference and query Seurat objects. \n", - "This can be used as input to TransferData.") + "This can be used as input to TransferData.\n") } ) @@ -2284,7 +2291,7 @@ setMethod( definition = function(object) { cat('An AnchorSet object containing', nrow(x = slot(object = object, name = "anchors")), "anchors between", length(x = slot(object = object, name = "object.list")), "Seurat objects \n", - "This can be used as input to IntegrateData.") + "This can be used as input to IntegrateData.\n") } ) @@ -2295,7 +2302,7 @@ setMethod( cat( 'A ModalityWeights object containing modality weights between', paste(slot(object = object, name = "modality.assay"), collapse = " and "), - "assays \n", "This can be used as input to FindMultiModelNeighbors.") + "assays \n", "This can be used as input to FindMultiModelNeighbors.\n") } ) @@ -2307,7 +2314,7 @@ setMethod( "An sctransform model.\n", " Model formula: ", slot(object = object, name = "model"), "\n Parameters stored for", nrow(x = SCTResults(object = object, slot = "feature.attributes")), "features,", - nrow(x = SCTResults(object = object, slot = "cell.attributes")), "cells") + nrow(x = SCTResults(object = object, slot = "cell.attributes")), "cells.\n") } ) diff --git a/R/preprocessing.R b/R/preprocessing.R index 1c54fc605..4f6765faa 100644 --- a/R/preprocessing.R +++ b/R/preprocessing.R @@ -954,7 +954,7 @@ Read10X_h5 <- function(filename, use.names = TRUE, unique.features = TRUE) { p = indptr[], x = as.numeric(x = counts[]), dims = shp[], - giveCsparse = FALSE + repr = "T" ) if (unique.features) { features <- make.unique(names = features) @@ -967,7 +967,11 @@ Read10X_h5 <- function(filename, use.names = TRUE, unique.features = TRUE) { types <- infile[[paste0(genome, '/features/feature_type')]][] types.unique <- unique(x = types) if (length(x = types.unique) > 1) { - message("Genome ", genome, " has multiple modalities, returning a list of matrices for this genome") + message( + "Genome ", + genome, + " has multiple modalities, returning a list of matrices for this genome" + ) sparse.mat <- sapply( X = types.unique, FUN = function(x) { @@ -1103,10 +1107,19 @@ ReadMtx <- function( "feature list" = features ) for (i in seq_along(along.with = all.files)) { - uri <- normalizePath(all.files[[i]], mustWork = FALSE) + uri <- tryCatch( + expr = { + con <- url(description = all.files[[i]]) + close(con = con) + all.files[[i]] + }, + error = function(...) { + return(normalizePath(path = all.files[[i]], winslash = '/')) + } + ) err <- paste("Cannot find", names(x = all.files)[i], "at", uri) uri <- build_url(url = parse_url(url = uri)) - if (grepl(pattern = '^:///', x = uri)) { + if (grepl(pattern = '^[A-Z]?:///', x = uri)) { uri <- gsub(pattern = '^://', replacement = '', x = uri) if (!file.exists(uri)) { stop(err, call. = FALSE) diff --git a/R/utilities.R b/R/utilities.R index 65741c2a2..d0d76dfba 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -1610,7 +1610,7 @@ as.data.frame.Matrix <- function( row.names = NULL, optional = FALSE, ..., - stringsAsFactors = default.stringsAsFactors() + stringsAsFactors = getOption(x = "stringsAsFactors", default = FALSE) ) { return(as.data.frame( x = as.matrix(x = x), diff --git a/R/visualization.R b/R/visualization.R index 0f8f0383c..9e65d7a92 100644 --- a/R/visualization.R +++ b/R/visualization.R @@ -1890,7 +1890,7 @@ CellScatter <- function( #' 100,000 #' @param raster.dpi Pixel resolution for rasterized plots, passed to geom_scattermore(). #' Default is c(512, 512). -#' @param jitter Jitter for easier visualization of crowded points +#' @param jitter Jitter for easier visualization of crowded points (default is FALSE) #' #' @return A ggplot object #' @@ -1924,7 +1924,7 @@ FeatureScatter <- function( plot.cor = TRUE, raster = NULL, raster.dpi = c(512, 512), - jitter = TRUE + jitter = FALSE ) { cells <- cells %||% colnames(x = object) if (isTRUE(x = shuffle)) { @@ -2418,7 +2418,7 @@ LinkedDimPlot <- function( dims = dims, col.by = group.by, alpha.by = plot.env$alpha.by - ) + scale_alpha_ordinal(range = alpha) + guides(alpha = FALSE) + ) + scale_alpha_ordinal(range = alpha) + guides(alpha = "none") plot.env$dimplot } ) @@ -2555,7 +2555,7 @@ LinkedFeaturePlot <- function( scale_fill_gradientn(name = feature, colours = cols) + theme(legend.position = 'top') + scale_alpha(range = alpha) + - guides(alpha = FALSE) + guides(alpha = "none") plot.env$spatialplot } ) @@ -2914,7 +2914,7 @@ ISpatialFeaturePlot <- function( scale_fill_gradientn(name = plot.env$feature, colours = FeaturePalettes[[plot.env$palette]]) + theme(legend.position = 'top') + scale_alpha(range = c(input$alpha, 1)) + - guides(alpha = FALSE) + guides(alpha = "none") plot.env$plot }) } @@ -3232,7 +3232,7 @@ SpatialPlot <- function( ) + theme(legend.position = 'top') + scale_alpha(range = alpha) + - guides(alpha = FALSE) + guides(alpha = "none") } else if (label) { plot <- LabelClusters( plot = plot, @@ -3286,10 +3286,14 @@ SpatialPlot <- function( # images = GetImage(object = object, mode = 'plotly', image = images) # )) # } - if (length(x = images) > 1 && combine) { - plots <- wrap_plots(plots = plots, ncol = length(x = images)) - } else if (length(x = images == 1) && combine) { - plots <- wrap_plots(plots = plots, ncol = ncol) + if (combine) { + if (!is.null(x = ncol)) { + return(wrap_plots(plots = plots, ncol = ncol)) + } + if (length(x = images) > 1) { + return(wrap_plots(plots = plots, ncol = length(x = images))) + } + return(wrap_plots(plots = plots)) } return(plots) } @@ -3542,13 +3546,20 @@ DotPlot <- function( if (!is.null(x = id.levels)) { data.plot$id <- factor(x = data.plot$id, levels = id.levels) } - if (length(x = levels(x = data.plot$id)) == 1) { + ngroup <- length(x = levels(x = data.plot$id)) + if (ngroup == 1) { scale <- FALSE warning( "Only one identity present, the expression values will be not scaled", call. = FALSE, immediate. = TRUE ) + } else if (ngroup < 5 & scale) { + warning( + "Scaling data with a low number of groups may produce misleading results", + call. = FALSE, + immediate. = TRUE + ) } avg.exp.scaled <- sapply( X = unique(x = data.plot$features.plot), @@ -7240,8 +7251,9 @@ SingleExIPlot <- function( if ((nrow(x = data) > 1e5) & !isFALSE(raster)){ message("Rasterizing points since number of points exceeds 100,000.", "\nTo disable this behavior set `raster=FALSE`") + # change raster to TRUE + raster <- TRUE } - raster <- TRUE } if (!is.null(x = seed.use)) { set.seed(seed = seed.use) @@ -7666,6 +7678,7 @@ SingleSpatialPlot <- function( colors <- DiscretePalette(length(unique(data[[col.by]])), palette = cols) scale <- scale_fill_manual(values = colors, na.value = na.value) } else { + cols <- cols[names(x = cols) %in% data$ident] scale <- scale_fill_manual(values = cols, na.value = na.value) } plot <- plot + scale diff --git a/cran-comments.md b/cran-comments.md index ee8f02d38..2e206a8e3 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,19 +1,33 @@ -# Seurat v4.1.0 +# Seurat v4.1.1 ## Test environments -* local Ubuntu 20.04 install, R 4.1.2 +* local Ubuntu 20.04 install, R 4.1.3 * Ubuntu 16.04.6 (on travis-ci), R 4.0.0, R devel * macOS 10.13.6 (on travis-ci), R 4.0.2 * Windows Server 2012 R2 (on AppVeyor), R 4.1.0 Patched * win-builder (release, devel) ## R CMD check results -There were no ERRORs, WARNINGs, or NOTEs +There were no ERRORs or WARNINGs + +There was one NOTE: + +* checking CRAN incoming feasibility ... NOTE +Maintainer: 'Paul Hoffman ' + +Found the following (possibly) invalid URLs: + URL: https://www.science.org/doi/abs/10.1126/science.aad0501 + From: man/cc.genes.Rd + man/cc.genes.updated.2019.Rd + Status: 503 + Message: Service Unavailable + +This URL is valid and the service still exists. When navigating to the URL either via the documentation or directly, you are taken to the correct article ## Downstream dependencies There no packages that depend on Seurat -There are sixteen packages that import Seurat: CAMML, CDSeq, CIDER, DR.SC, DUBStepR, PhitestR, Platypus, rPanglaoDB, scDiffCom, scMappR, SCRIP, scRNAstat, Signac, SignacX, SoupX, and tidyseurat; this update does not impact their functionality +There are sixteen packages that import Seurat: CAMML, CIDER, DR.SC, DUBStepR, maple, Platypus, rPanglaoDB, scDiffCom, scMappR, SCRIP, scRNAstat, Signac, SignacX, SoupX, spruce, and tidyseurat; this update does not impact their functionality -There are ten packages that suggest Seurat: BisqueRNA, ClustAssess, clustree, conos, DIscBIO, dyngen, harmony, rliger, Rmagic, and VAM; this update does not impact their functionality. +There are twelve packages that suggest Seurat: BisqueRNA, CIARA, ClustAssess, clustree, conos, DIscBIO, dyngen, harmony, rliger, Rmagic, treefit, and VAM; this update does not impact their functionality. diff --git a/man/Cells.Rd b/man/Cells.Rd index 8da74d202..4191764b5 100644 --- a/man/Cells.Rd +++ b/man/Cells.Rd @@ -7,16 +7,18 @@ \alias{Cells.VisiumV1} \title{Get Cell Names} \usage{ -\method{Cells}{SCTModel}(x) +\method{Cells}{SCTModel}(x, ...) -\method{Cells}{SlideSeq}(x) +\method{Cells}{SlideSeq}(x, ...) -\method{Cells}{STARmap}(x) +\method{Cells}{STARmap}(x, ...) -\method{Cells}{VisiumV1}(x) +\method{Cells}{VisiumV1}(x, ...) } \arguments{ \item{x}{An object} + +\item{...}{Arguments passed to other methods} } \description{ Get Cell Names diff --git a/man/DietSeurat.Rd b/man/DietSeurat.Rd index 8d6a4e4c3..35b66560e 100644 --- a/man/DietSeurat.Rd +++ b/man/DietSeurat.Rd @@ -12,7 +12,8 @@ DietSeurat( features = NULL, assays = NULL, dimreducs = NULL, - graphs = NULL + graphs = NULL, + misc = TRUE ) } \arguments{ @@ -33,6 +34,8 @@ remove all DimReducs)} \item{graphs}{Only keep a subset of Graphs specified here (if NULL, remove all Graphs)} + +\item{misc}{Preserve the \code{misc} slot; default is \code{TRUE}} } \description{ Keep only certain aspects of the Seurat object. Can be useful in functions that utilize merge as diff --git a/man/FeatureScatter.Rd b/man/FeatureScatter.Rd index ab20ab9ae..a6634d840 100644 --- a/man/FeatureScatter.Rd +++ b/man/FeatureScatter.Rd @@ -23,7 +23,7 @@ FeatureScatter( plot.cor = TRUE, raster = NULL, raster.dpi = c(512, 512), - jitter = TRUE + jitter = FALSE ) } \arguments{ @@ -67,7 +67,7 @@ which will automatically use raster if the number of points plotted is greater t \item{raster.dpi}{Pixel resolution for rasterized plots, passed to geom_scattermore(). Default is c(512, 512).} -\item{jitter}{Jitter for easier visualization of crowded points} +\item{jitter}{Jitter for easier visualization of crowded points (default is FALSE)} } \value{ A ggplot object diff --git a/man/RunSLSI.Rd b/man/RunSLSI.Rd index c89ed6886..5b7a05ad6 100644 --- a/man/RunSLSI.Rd +++ b/man/RunSLSI.Rd @@ -74,7 +74,7 @@ reductions slot } \description{ Run a supervised LSI (SLSI) dimensionality reduction supervised by a -cell-cell kernel. SLSI is used to capture a linear transformation of peaks +cell-cell kernel. SLSI is used to capture a linear transformation of peaks that maximizes its dependency to the given cell-cell kernel. } \concept{dimensional_reduction} diff --git a/man/RunUMAP.Rd b/man/RunUMAP.Rd index bbf838065..54b2319ae 100644 --- a/man/RunUMAP.Rd +++ b/man/RunUMAP.Rd @@ -243,8 +243,9 @@ Returns a Seurat object containing a UMAP representation } \description{ Runs the Uniform Manifold Approximation and Projection (UMAP) dimensional -reduction technique. To run, you must first install the umap-learn python -package (e.g. via \code{pip install umap-learn}). Details on this package can be +reduction technique. To run using \code{umap.method="umap-learn"}, you must +first install the umap-learn python package (e.g. via +\code{pip install umap-learn}). Details on this package can be found here: \url{https://github.com/lmcinnes/umap}. For a more in depth discussion of the mathematics underlying UMAP, see the ArXiv paper here: \url{https://arxiv.org/abs/1802.03426}. diff --git a/man/as.sparse.Rd b/man/as.sparse.Rd index 1872e4fe8..481122512 100644 --- a/man/as.sparse.Rd +++ b/man/as.sparse.Rd @@ -12,7 +12,7 @@ row.names = NULL, optional = FALSE, ..., - stringsAsFactors = default.stringsAsFactors() + stringsAsFactors = getOption(x = "stringsAsFactors", default = FALSE) ) } \arguments{ diff --git a/tests/testthat/test_load_10X.R b/tests/testthat/test_load_10X.R index 0a4dc5d1c..02b23e6dd 100644 --- a/tests/testthat/test_load_10X.R +++ b/tests/testthat/test_load_10X.R @@ -31,7 +31,6 @@ test_that("Read10X handles missing files properly", { if (requireNamespace("hdf5r", quietly = TRUE)) { context("Load10X_Spatial") dname <- "../testdata/visium" - # txsp <- Read10X_Spatial(outs_path = "../testdata/visium/") txsp <- Load10X_Spatial(data.dir = '../testdata/visium') test_that("10x Spatial Data Parsing", { expect_is(txsp, "Seurat")