Skip to content

Commit 63d61be

Browse files
committed
Merge branch 'develop'
2 parents 10d950e + 2bf638b commit 63d61be

27 files changed

+263
-86
lines changed

.github/workflows/cmd-check.yml

+9-7
Original file line numberDiff line numberDiff line change
@@ -90,24 +90,24 @@ jobs:
9090
- name: Query dependencies
9191
run: |
9292
install.packages('remotes')
93-
saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2)
93+
saveRDS(remotes::dev_package_deps(), ".github/depends.Rds", version = 2)
9494
shell: Rscript {0}
9595

9696
- name: Cache R packages
9797
if: "!contains(github.event.head_commit.message, '/nocache') && runner.os != 'Linux'"
9898
uses: actions/cache@v2
9999
with:
100100
path: ${{ env.R_LIBS_USER }}
101-
key: ${{ env.cache-version }}-${{ runner.os }}-biocversion-RELEASE_3_12-r-4.0-${{ hashFiles('.github/depends.Rds') }}
102-
restore-keys: ${{ env.cache-version }}-${{ runner.os }}-biocversion-RELEASE_3_12-r-4.0-
101+
key: ${{ env.cache-version }}-${{ runner.os }}-biocversion-RELEASE_3_12-r-4.0-2${{ hashFiles('.github/depends.Rds') }}
102+
restore-keys: ${{ env.cache-version }}-${{ runner.os }}-biocversion-RELEASE_3_12-r-4.0-2
103103

104104
- name: Cache R packages on Linux
105105
if: "!contains(github.event.head_commit.message, '/nocache') && runner.os == 'Linux' "
106106
uses: actions/cache@v2
107107
with:
108108
path: /home/runner/work/_temp/Library
109-
key: ${{ env.cache-version }}-${{ runner.os }}-biocversion-RELEASE_3_12-r-4.0-${{ hashFiles('.github/depends.Rds') }}
110-
restore-keys: ${{ env.cache-version }}-${{ runner.os }}-biocversion-RELEASE_3_12-r-4.0-
109+
key: ${{ env.cache-version }}-${{ runner.os }}-biocversion-RELEASE_3_12-r-4.0-2${{ hashFiles('.github/depends.Rds') }}
110+
restore-keys: ${{ env.cache-version }}-${{ runner.os }}-biocversion-RELEASE_3_12-r-4.0-2
111111

112112
- name: Install Linux system dependencies
113113
if: runner.os == 'Linux'
@@ -161,15 +161,15 @@ jobs:
161161
162162
## Pass #1 at installing dependencies
163163
message(paste('****', Sys.time(), 'pass number 1 at installing dependencies: local dependencies ****'))
164-
remotes::install_local(dependencies = TRUE, repos = BiocManager::repositories(), build_vignettes = TRUE, upgrade = TRUE)
164+
remotes::install_local(repos = BiocManager::repositories(), build_vignettes = TRUE, upgrade = TRUE)
165165
continue-on-error: true
166166
shell: Rscript {0}
167167

168168
- name: Install dependencies pass 2
169169
run: |
170170
## Pass #2 at installing dependencies
171171
message(paste('****', Sys.time(), 'pass number 2 at installing dependencies: any remaining dependencies ****'))
172-
remotes::install_local(dependencies = TRUE, repos = BiocManager::repositories(), build_vignettes = TRUE, upgrade = TRUE)
172+
remotes::install_local(repos = BiocManager::repositories(), build_vignettes = TRUE, upgrade = TRUE)
173173
174174
## For running the checks
175175
message(paste('****', Sys.time(), 'installing rcmdcheck and BiocCheck ****'))
@@ -194,6 +194,8 @@ jobs:
194194
- name: Run CMD check
195195
env:
196196
_R_CHECK_CRAN_INCOMING_: false
197+
_R_CHECK_DEPENDS_ONLY_: true
198+
_R_CHECK_FORCE_SUGGESTS_: false
197199
run: |
198200
rcmdcheck::rcmdcheck(
199201
args = c("--no-build-vignettes", "--no-manual", "--timings"),

DESCRIPTION

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: Signac
22
Title: Analysis of Single-Cell Chromatin Data
3-
Version: 1.4.0
4-
Date: 2021-09-20
3+
Version: 1.5.0
4+
Date: 2021-12-07
55
Authors@R: c(
66
person(given = 'Tim', family = 'Stuart', email = '[email protected]', role = c('aut', 'cre'), comment = c(ORCID = '0000-0002-3044-0897')),
77
person(given = 'Avi', family = 'Srivastava', email = '[email protected]', role = 'aut', comment = c(ORCID = '0000-0001-9798-2079')),
@@ -12,14 +12,14 @@ Description: A framework for the analysis and exploration of single-cell chromat
1212
The 'Signac' package contains functions for quantifying single-cell chromatin data,
1313
computing per-cell quality control metrics, dimension reduction
1414
and normalization, visualization, and DNA sequence motif analysis.
15-
Reference: Stuart et al. (2020) <doi:10.1101/2020.11.09.373613>.
15+
Reference: Stuart et al. (2021) <doi:10.1038/s41592-021-01282-5>.
1616
Depends:
1717
R (>= 4.0.0),
1818
methods
1919
License: MIT + file LICENSE
2020
Encoding: UTF-8
2121
LazyData: true
22-
RoxygenNote: 7.1.1
22+
RoxygenNote: 7.1.2
2323
URL: https://github.com/timoast/signac, https://satijalab.org/signac
2424
BugReports: https://github.com/timoast/signac/issues
2525
LinkingTo: Rcpp
@@ -75,6 +75,7 @@ Collate:
7575
'quantification.R'
7676
'utilities.R'
7777
'visualization.R'
78+
'zzz.R'
7879
Suggests:
7980
testthat (>= 2.1.0),
8081
chromVAR,

NEWS.md

+17
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
# Signac 1.5.0
2+
3+
Bug fixes:
4+
5+
* Fixed bug in `FeatureMatrix()` when cells information not present in Fragment object ([#803](https://github.com/timoast/signac/issues/803))
6+
* Fixed bug in object merging ([#804](https://github.com/timoast/signac/issues/804))
7+
* Add ability to run `LinkPeaks()` using Ensembl IDs ([#858](https://github.com/timoast/signac/issues/858))
8+
* Fix issue in `GeneActivity()` when gene names are `NA` ([#865](https://github.com/timoast/signac/issues/865))
9+
* Fix bug in `FeatureMatrix()` when only one region supplied
10+
* Allow negative values in `ExpressionPlot()` when using scaled data ([#893](https://github.com/timoast/signac/issues/893))
11+
12+
Other changes:
13+
14+
* Added `idf` parameter to `RunTFIDF()` to use precomputed IDF vector
15+
* Added `gene.id` parameter to `GeneActivity()` to allow output genes named using gene ID ([#837](https://github.com/timoast/signac/issues/837))
16+
* Added `sep` parameter to `ConnectionsToLinks()` ([#841](https://github.com/timoast/signac/issues/841))
17+
118
# Signac 1.4.0
219

320
Bug fixes:

R/links.R

+38-11
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ GetLinkedGenes <- function(
8686
#' CCAN that it belongs to in the second column.
8787
#' @param threshold Threshold for retaining a coaccessible site. Links with
8888
#' a value less than or equal to this threshold will be discarded.
89+
#' @param sep Separators to use for strings encoding genomic coordinates.
90+
#' First element is used to separate the chromosome from the coordinates, second
91+
#' element is used to separate the start from end coordinate.
8992
#'
9093
#' @export
9194
#' @importFrom GenomicRanges start end makeGRangesFromDataFrame
@@ -94,11 +97,16 @@ GetLinkedGenes <- function(
9497
#'
9598
#' @concept links
9699
#' @return Returns a \code{\link[GenomicRanges]{GRanges}} object
97-
ConnectionsToLinks <- function(conns, ccans = NULL, threshold = 0) {
100+
ConnectionsToLinks <- function(
101+
conns,
102+
ccans = NULL,
103+
threshold = 0,
104+
sep = c("-", "-")
105+
) {
98106
# add chromosome information
99-
chr1 <- stri_split_fixed(str = conns$Peak1, pattern = "-")
107+
chr1 <- stri_split_fixed(str = conns$Peak1, pattern = sep[[1]])
100108
conns$chr1 <- unlist(x = chr1)[3 * (seq_along(along.with = chr1)) - 2]
101-
chr2 <- stri_split_fixed(str = conns$Peak2, pattern = "-")
109+
chr2 <- stri_split_fixed(str = conns$Peak2, pattern = sep[[1]])
102110
conns$chr2 <- unlist(x = chr2)[3 * (seq_along(along.with = chr2)) - 2]
103111

104112
# filter out trans-chr links
@@ -124,8 +132,8 @@ ConnectionsToLinks <- function(conns, ccans = NULL, threshold = 0) {
124132
}
125133

126134
# extract genomic regions
127-
coords.1 <- StringToGRanges(regions = conns$Peak1, sep = c("-", "-"))
128-
coords.2 <- StringToGRanges(regions = conns$Peak2, sep = c("-", "-"))
135+
coords.1 <- StringToGRanges(regions = conns$Peak1, sep = sep)
136+
coords.2 <- StringToGRanges(regions = conns$Peak2, sep = sep)
129137
chr <- seqnames(x = coords.1)
130138

131139
# find midpoints
@@ -187,6 +195,8 @@ ConnectionsToLinks <- function(conns, ccans = NULL, threshold = 0) {
187195
#' p-value equal or greater than this value will be removed from the output.
188196
#' @param score_cutoff Minimum absolute value correlation coefficient for a link
189197
#' to be retained
198+
#' @param gene.id Set to TRUE if genes in the expression assay are named
199+
#' using gene IDs rather than gene names.
190200
#' @param verbose Display messages
191201
#'
192202
#' @importFrom Seurat GetAssayData
@@ -227,6 +237,7 @@ LinkPeaks <- function(
227237
n_sample = 200,
228238
pvalue_cutoff = 0.05,
229239
score_cutoff = 0.05,
240+
gene.id = FALSE,
230241
verbose = TRUE
231242
) {
232243
if (!inherits(x = object[[peak.assay]], what = "ChromatinAssay")) {
@@ -274,14 +285,12 @@ LinkPeaks <- function(
274285
peaks.keep <- peakcounts > min.cells
275286
genes.keep <- genecounts > min.cells
276287
peak.data <- peak.data[peaks.keep, ]
277-
if (is.null(x = genes.use)) {
278-
expression.data <- expression.data[genes.keep, ]
279-
} else {
288+
if (!is.null(x = genes.use)) {
280289
genes.keep <- intersect(
281290
x = names(x = genes.keep[genes.keep]), y = genes.use
282291
)
283-
expression.data <- expression.data[genes.keep, , drop = FALSE]
284292
}
293+
expression.data <- expression.data[genes.keep, , drop = FALSE]
285294
if (verbose) {
286295
message(
287296
"Testing ",
@@ -292,7 +301,20 @@ LinkPeaks <- function(
292301
)
293302
}
294303
genes <- rownames(x = expression.data)
295-
gene.coords.use <- gene.coords[gene.coords$gene_name %in% genes,]
304+
if (gene.id) {
305+
gene.coords.use <- gene.coords[gene.coords$gene_id %in% genes,]
306+
gene.coords.use$gene_name <- gene.coords.use$gene_id
307+
} else {
308+
gene.coords.use <- gene.coords[gene.coords$gene_name %in% genes,]
309+
}
310+
if (length(x = gene.coords.use) == 0) {
311+
stop("Could not find gene coordinates for requested genes")
312+
}
313+
if (length(x = gene.coords.use) < nrow(x = expression.data)) {
314+
message("Found gene coordinates for ",
315+
length(x = gene.coords.use),
316+
" genes")
317+
}
296318
peaks <- granges(x = object[[peak.assay]])
297319
peaks <- peaks[peaks.keep]
298320
peak_distance_matrix <- DistanceToTSS(
@@ -518,7 +540,12 @@ LinksToGRanges <- function(linkmat, gene.coords, sep = c("-", "-")) {
518540
#' @importFrom GenomicRanges resize
519541
#
520542
# @return Returns a sparse matrix
521-
DistanceToTSS <- function(peaks, genes, distance = 200000, sep = c("-", "-")) {
543+
DistanceToTSS <- function(
544+
peaks,
545+
genes,
546+
distance = 200000,
547+
sep = c("-", "-")
548+
) {
522549
tss <- resize(x = genes, width = 1, fix = 'start')
523550
genes.extended <- suppressWarnings(
524551
expr = Extend(

R/objects.R

+2-2
Original file line numberDiff line numberDiff line change
@@ -1157,7 +1157,7 @@ merge.ChromatinAssay <- function(
11571157
if (all(count_nonzero > 0)) {
11581158
merged.counts <- RowMergeSparseMatrices(
11591159
mat1 = all.counts[[1]],
1160-
mat2 = all.counts[[2:length(x = all.counts)]]
1160+
mat2 = all.counts[2:length(x = all.counts)]
11611161
)
11621162
reduced.ranges <- StringToGRanges(regions = rownames(x = merged.counts))
11631163
} else {
@@ -1167,7 +1167,7 @@ merge.ChromatinAssay <- function(
11671167
if (all(data_nonzero > 0)) {
11681168
merged.data <- RowMergeSparseMatrices(
11691169
mat1 = all.data[[1]],
1170-
mat2 = all.data[[2:length(x = all.data)]]
1170+
mat2 = all.data[2:length(x = all.data)]
11711171
)
11721172
reduced.ranges <- SetIfNull(
11731173
x = reduced.ranges,

R/preprocessing.R

+36-6
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,8 @@ RegionStats.Seurat <- function(
552552
#' \eqn{IDF}.
553553
#' }
554554
#' @param scale.factor Which scale factor to use. Default is 10000.
555+
#' @param idf A precomputed IDF vector to use. If NULL, compute based on the
556+
#' input data matrix.
555557
#' @param verbose Print progress
556558
#' @rdname RunTFIDF
557559
#' @importFrom Matrix colSums rowSums Diagonal tcrossprod
@@ -566,6 +568,7 @@ RunTFIDF.default <- function(
566568
assay = NULL,
567569
method = 1,
568570
scale.factor = 1e4,
571+
idf = NULL,
569572
verbose = TRUE,
570573
...
571574
) {
@@ -587,18 +590,41 @@ RunTFIDF.default <- function(
587590
} else {
588591
tf <- tcrossprod(x = object, y = Diagonal(x = 1 / npeaks))
589592
}
590-
rsums <- rowSums(x = object)
591-
if (any(rsums == 0)) {
592-
warning("Some features contain 0 total counts")
593+
if (!is.null(x = idf)) {
594+
precomputed_idf <- TRUE
595+
if (!inherits(x = idf, what = "numeric")) {
596+
stop("idf parameter must be a numeric vector")
597+
}
598+
if (length(x = idf) != nrow(x = object)) {
599+
stop("Length of supplied IDF vector does not match",
600+
" number of rows in input matrix")
601+
}
602+
if (any(idf == 0)) {
603+
stop("Supplied IDF values cannot be zero")
604+
}
605+
if (verbose) {
606+
message("Using precomputed IDF vector")
607+
}
608+
} else {
609+
precomputed_idf <- FALSE
610+
rsums <- rowSums(x = object)
611+
if (any(rsums == 0)) {
612+
warning("Some features contain 0 total counts")
613+
}
614+
idf <- ncol(x = object) / rsums
593615
}
594-
idf <- ncol(x = object) / rsums
616+
595617
if (method == 2) {
596-
idf <- log(1 + idf)
618+
if (!precomputed_idf) {
619+
idf <- log(1 + idf)
620+
}
597621
} else if (method == 3) {
598622
slot(object = tf, name = "x") <- log1p(
599623
x = slot(object = tf, name = "x") * scale.factor
600624
)
601-
idf <- log(1 + idf)
625+
if (!precomputed_idf) {
626+
idf <- log(1 + idf)
627+
}
602628
}
603629
norm.data <- Diagonal(n = length(x = idf), x = idf) %*% tf
604630
if (method == 1) {
@@ -626,6 +652,7 @@ RunTFIDF.Assay <- function(
626652
assay = NULL,
627653
method = 1,
628654
scale.factor = 1e4,
655+
idf = NULL,
629656
verbose = TRUE,
630657
...
631658
) {
@@ -634,6 +661,7 @@ RunTFIDF.Assay <- function(
634661
method = method,
635662
assay = assay,
636663
scale.factor = scale.factor,
664+
idf = idf,
637665
verbose = verbose,
638666
...
639667
)
@@ -658,6 +686,7 @@ RunTFIDF.Seurat <- function(
658686
assay = NULL,
659687
method = 1,
660688
scale.factor = 1e4,
689+
idf = NULL,
661690
verbose = TRUE,
662691
...
663692
) {
@@ -668,6 +697,7 @@ RunTFIDF.Seurat <- function(
668697
assay = assay,
669698
method = method,
670699
scale.factor = scale.factor,
700+
idf = idf,
671701
verbose = verbose,
672702
...
673703
)

0 commit comments

Comments
 (0)