Skip to content

Commit cbdadf9

Browse files
committed
Update EnrichedTerms to use var features
1 parent b3d8812 commit cbdadf9

2 files changed

Lines changed: 63 additions & 17 deletions

File tree

R/ontology.R

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@
1111
#' @param group.by Name of grouping variable to use. If `NULL`, use the active
1212
#' cell identities.
1313
#' @param assay Name of assay to use. If `NULL`, use the default assay.
14-
#' @param var.features Subset to only variable features for ontology term
15-
#' enrichment.
14+
#' @param var.features Restrict the analysis to variable features. When `TRUE`
15+
#' (the default), differential testing is performed only on the variable
16+
#' features of the assay, so the ranked list scored by [fgsea::fgsea()] (the
17+
#' enrichment universe) and the term gene sets are evaluated within the same
18+
#' variable-feature space. Requires variable features to be set for the assay
19+
#' (e.g. with [FindTopFeatures()]).
1620
#' @param scoreType `scoreType` parameter for [fgsea::fgseaSimple()].
1721
#' Options are "std", "pos", "neg" (two-tailed or one-tailed tests).
1822
#' @param direction Which direction of enrichment to retain. `"up"` (default)
@@ -55,12 +59,25 @@ EnrichedTerms <- function(
5559

5660
assay <- assay %||% DefaultAssay(object = object)
5761

62+
marker.args <- list(...)
5863
if (var.features) {
64+
var.feat <- VariableFeatures(object = object[[assay]])
65+
if (length(x = var.feat) == 0) {
66+
stop(
67+
"var.features = TRUE but no variable features are set for assay '",
68+
assay, "'. Compute variable features first (for example with ",
69+
"FindTopFeatures()) or set var.features = FALSE."
70+
)
71+
}
72+
# Restrict the analysis to variable features
73+
marker.args$features <- if (is.null(x = marker.args$features)) {
74+
var.feat
75+
} else {
76+
intersect(x = marker.args$features, y = var.feat)
77+
}
5978
terms <- lapply(
6079
X = terms,
61-
FUN = function(x) {
62-
x[x %in% VariableFeatures(object = object[[assay]])]
63-
}
80+
FUN = function(x) x[x %in% var.feat]
6481
)
6582
}
6683

@@ -80,17 +97,19 @@ EnrichedTerms <- function(
8097
)
8198
}
8299
for (i in seq_along(along.with = cellgroups)) {
83-
mk <- Seurat::FindMarkers(
84-
object = object,
85-
assay = assay,
86-
ident.1 = cellgroups[[i]],
87-
group.by = group.by,
88-
...
100+
mk <- do.call(
101+
what = Seurat::FindMarkers,
102+
args = c(
103+
list(
104+
object = object,
105+
assay = assay,
106+
ident.1 = cellgroups[[i]],
107+
group.by = group.by
108+
),
109+
marker.args
110+
)
89111
)
90-
mk$rank_score <- sign(mk$avg_log2FC) * -log10(mk$p_val)
91-
ranked_list <- setNames(object = mk$rank_score, nm = rownames(x = mk))
92-
max_non_infinite <- max(ranked_list[!is.infinite(x = ranked_list)])
93-
ranked_list[is.infinite(x = ranked_list)] <- max_non_infinite
112+
ranked_list <- RankFeatures(markers = mk)
94113

95114
# run fgsea
96115
fgsea_results <- fgsea::fgsea(
@@ -127,3 +146,26 @@ EnrichedTerms <- function(
127146
}
128147
return(pred)
129148
}
149+
150+
# Build a named ranked statistic vector for fgsea from a FindMarkers result.
151+
# The score for each feature is sign(avg_log2FC) * -log10(p_val), so that
152+
# strongly up-regulated features get large positive scores and strongly
153+
# down-regulated features get large negative scores. A p-value of exactly zero
154+
# produces an infinite score (+Inf when up-regulated, -Inf when down-regulated);
155+
# each infinite score is capped at the most extreme finite score of the same
156+
# sign. Capping the two signs separately keeps up-regulated features at the top
157+
# of the ranking and down-regulated features at the bottom
158+
# @param markers A data frame of differential test results with columns
159+
# `avg_log2FC` and `p_val` and feature names as row names (as returned by
160+
# [Seurat::FindMarkers()]).
161+
# @return A named numeric vector of ranking statistics.
162+
RankFeatures <- function(markers) {
163+
rank_score <- sign(x = markers$avg_log2FC) * -log10(x = markers$p_val)
164+
ranked_list <- setNames(object = rank_score, nm = rownames(x = markers))
165+
finite_scores <- ranked_list[is.finite(x = ranked_list)]
166+
pos_cap <- if (length(x = finite_scores) > 0) max(finite_scores) else 1
167+
neg_cap <- if (length(x = finite_scores) > 0) min(finite_scores) else -1
168+
ranked_list[ranked_list == Inf] <- pos_cap
169+
ranked_list[ranked_list == -Inf] <- neg_cap
170+
return(ranked_list)
171+
}

man/EnrichedTerms.Rd

Lines changed: 6 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)