Performs KNN prediction to annotate cell types based on reference scRNA-seq or bulk RNA-seq data.
Usage
RunKNNPredict(
srt_query,
srt_ref = NULL,
bulk_ref = NULL,
query_group = NULL,
ref_group = NULL,
query_assay = NULL,
ref_assay = NULL,
query_reduction = NULL,
ref_reduction = NULL,
query_dims = 1:30,
ref_dims = 1:30,
query_collapsing = !is.null(query_group),
ref_collapsing = TRUE,
return_full_distance_matrix = FALSE,
features = NULL,
features_type = c("HVF", "DE"),
feature_source = "both",
nfeatures = 2000,
DEtest_param = list(max.cells.per.ident = 200, test.use = "wilcox"),
DE_threshold = "p_val_adj < 0.05",
nn_method = NULL,
distance_metric = "cosine",
k = 30,
filter_lowfreq = 0,
prefix = "KNNPredict",
verbose = TRUE
)Arguments
- srt_query
An object of class Seurat to be annotated with cell types.
- srt_ref
An object of class Seurat storing the reference cells.
- bulk_ref
A cell atlas matrix, where cell types are represented by columns and genes are represented by rows. Either
srt_reforbulk_refmust be provided.- query_group
Column name in the
srt_querymetadata that represents the cell grouping.- ref_group
Column name in the
srt_refmetadata that represents the cell grouping.- query_assay
Assay to be used for the query data. Default is the default assay of the
srt_queryobject.- ref_assay
Assay to be used for the reference data. Default is the default assay of the
srt_refobject.- query_reduction
Dimensionality reduction method used for the query data. If NULL, the function will use the default reduction method specified in the
srt_queryobject.- ref_reduction
Dimensionality reduction method used for the reference data. If NULL, the function will use the default reduction method specified in the
srt_refobject.- query_dims
Dimensions to be used for the query data. Default is the first
30dimensions.- ref_dims
Dimensions to be used for the reference data. Default is the first
30dimensions.- query_collapsing
A boolean value indicating whether the query data should be collapsed to group-level average expression values. If TRUE, the function will calculate the average expression values for each group in the query data and the annotation will be performed separately for each group. Otherwise it will use the raw expression values for each cell.
- ref_collapsing
A boolean value indicating whether the reference data should be collapsed to group-level average expression values. If TRUE, the function will calculate the average expression values for each group in the reference data and the annotation will be performed separately for each group. Otherwise it will use the raw expression values for each cell.
- return_full_distance_matrix
A boolean value indicating whether the full distance matrix should be returned. If TRUE, the function will return the distance matrix used for the KNN prediction, otherwise it will only return the annotated cell types.
- features
Features to be used for the KNN prediction. If
NULL, all the features in the query and reference data will be used.- features_type
Type of features to be used for the KNN prediction. Must be one of "HVF" (highly variable features) or "DE" (differentially expressed features).
- feature_source
The source of the features to be used. Must be one of "both", "query", or "ref".
- nfeatures
Maximum number of features to be used for the KNN prediction.
- DEtest_param
A list of parameters to be passed to the differential expression test function if
features_typeis set to "DE". Default islist(max.cells.per.ident = 200, test.use = "wilcox").- DE_threshold
Threshold used to filter the DE features. If using "roc" test,
DE_thresholdshould be needs to be reassigned. e.g. "power > 0.5".- nn_method
Nearest neighbor search method to use. Options are "raw", "annoy", and "rann". If "raw" is selected, the function will use the brute-force method to find the nearest neighbors. If "annoy" is selected, the function will use the Annoy library for approximate nearest neighbor search. If "rann" is selected, the function will use the RANN library for approximate nearest neighbor search. If not provided, the function will choose the search method based on the size of the query and reference datasets. For finite dense inputs using cosine or Euclidean distance, the raw path uses a bounded-memory compiled top-k kernel unless the full distance matrix is requested. Other metrics and sparse inputs retain the existing proxyC path.
- distance_metric
Distance metric to be used for calculating similarity between cells. Must be one of "cosine", "euclidean", "manhattan", or "hamming".
- k
A number of nearest neighbors to be considered for the KNN prediction.
- filter_lowfreq
Threshold for filtering low-frequency cell types from the predicted results. Cell types with a frequency lower than
filter_lowfreqwill be labelled as "unreliable". Default is0, which means no filtering will be performed.- prefix
Prefix to be added to the resulting annotations.
- verbose
Whether to print the message. Default is
TRUE.
Examples
# Annotate cells using bulk RNA-seq data
data(pancreas_sub)
data(ref_scMCA)
pancreas_sub <- RunStandardWorkflow(pancreas_sub)
#> ℹ [2026-08-30 05:11:05] Start standard processing workflow...
#> ℹ [2026-08-30 05:11:05] Checking a list of <Seurat>...
#> ! [2026-08-30 05:11:05] Data 1/1 of the `srt_list` is "unknown"
#> Warning: Data 1/1 of the `srt_list` is "unknown"
#> ℹ [2026-08-30 05:11:05] Perform `NormalizeData()` with `normalization.method = 'LogNormalize'` on 1/1 of `srt_list`...
#> ℹ [2026-08-30 05:11:05] Perform `FindVariableFeatures()` on 1/1 of `srt_list`...
#> ℹ [2026-08-30 05:11:06] Use the separate HVF from `srt_list`
#> ℹ [2026-08-30 05:11:06] Number of available HVF: 2000
#> ℹ [2026-08-30 05:11:06] Finished check
#> ℹ [2026-08-30 05:11:06] Perform `ScaleData()`
#> ℹ [2026-08-30 05:11:06] Perform pca linear dimension reduction
#> ℹ [2026-08-30 05:11:06] Use stored estimated dimensions 1:23 for Standardpca
#> ℹ [2026-08-30 05:11:07] Perform `Seurat::FindClusters()` with `cluster_algorithm = 'louvain'` and `cluster_resolution = 0.6`
#> ℹ [2026-08-30 05:11:07] Reorder clusters...
#> ℹ [2026-08-30 05:11:07] Skip `log1p()` because `layer = data` is not "counts"
#> ℹ [2026-08-30 05:11:07] Perform umap nonlinear dimension reduction
#> ✔ [2026-08-30 05:11:15] Standard processing workflow completed
pancreas_sub <- RunKNNPredict(
srt_query = pancreas_sub,
bulk_ref = ref_scMCA
)
#> ℹ [2026-08-30 05:11:15] Use [1] 549 features to calculate distance.
#> ℹ [2026-08-30 05:11:15] Detected query data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:11:15] Detected reference data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:11:15] Calculate similarity...
#> ℹ [2026-08-30 05:11:15] Use raw method to find neighbors
#> ℹ [2026-08-30 05:11:16] Predict cell type...
CellDimPlot(
pancreas_sub,
group.by = "KNNPredict_classification",
label = TRUE
)
# Removal of low credible cell types from the predicted results
pancreas_sub <- RunKNNPredict(
srt_query = pancreas_sub,
bulk_ref = ref_scMCA,
filter_lowfreq = 30
)
#> ℹ [2026-08-30 05:11:16] Use [1] 549 features to calculate distance.
#> ℹ [2026-08-30 05:11:16] Detected query data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:11:16] Detected reference data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:11:16] Calculate similarity...
#> ℹ [2026-08-30 05:11:16] Use raw method to find neighbors
#> ℹ [2026-08-30 05:11:16] Predict cell type...
CellDimPlot(
pancreas_sub,
group.by = "KNNPredict_classification",
label = TRUE
)
# Annotate clusters using bulk RNA-seq data
pancreas_sub <- RunKNNPredict(
srt_query = pancreas_sub,
query_group = "SubCellType",
bulk_ref = ref_scMCA
)
#> ℹ [2026-08-30 05:11:16] Use [1] 549 features to calculate distance.
#> ℹ [2026-08-30 05:11:17] Detected query data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:11:17] Detected reference data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:11:17] Calculate similarity...
#> ℹ [2026-08-30 05:11:17] Use raw method to find neighbors
#> ℹ [2026-08-30 05:11:17] Predict cell type...
CellDimPlot(
pancreas_sub,
group.by = "KNNPredict_classification",
label = TRUE
)
# Annotate using single cell RNA-seq data
data(panc8_sub)
# Simply convert genes from human to mouse and preprocess the data
genenames <- make.unique(
thisutils::capitalize(
rownames(panc8_sub),
force_tolower = TRUE
)
)
names(genenames) <- rownames(panc8_sub)
panc8_sub <- RenameFeatures(
panc8_sub,
newnames = genenames
)
#> ℹ [2026-08-30 05:11:17] Rename features for the assay: RNA
panc8_sub <- CheckDataMerge(
panc8_sub,
batch = "tech"
)[["srt_merge"]]
#> ℹ [2026-08-30 05:11:17] Split `srt_merge` into `srt_list` by "tech"
#> ℹ [2026-08-30 05:11:18] Checking a list of <Seurat>...
#> ! [2026-08-30 05:11:18] Data 1/5 of the `srt_list` is "unknown"
#> Warning: Data 1/5 of the `srt_list` is "unknown"
#> ℹ [2026-08-30 05:11:18] Perform `NormalizeData()` with `normalization.method = 'LogNormalize'` on 1/5 of `srt_list`...
#> ℹ [2026-08-30 05:11:18] Perform `FindVariableFeatures()` on 1/5 of `srt_list`...
#> ! [2026-08-30 05:11:18] Data 2/5 of the `srt_list` is "unknown"
#> Warning: Data 2/5 of the `srt_list` is "unknown"
#> ℹ [2026-08-30 05:11:18] Perform `NormalizeData()` with `normalization.method = 'LogNormalize'` on 2/5 of `srt_list`...
#> ℹ [2026-08-30 05:11:18] Perform `FindVariableFeatures()` on 2/5 of `srt_list`...
#> ! [2026-08-30 05:11:18] Data 3/5 of the `srt_list` is "unknown"
#> Warning: Data 3/5 of the `srt_list` is "unknown"
#> ℹ [2026-08-30 05:11:18] Perform `NormalizeData()` with `normalization.method = 'LogNormalize'` on 3/5 of `srt_list`...
#> ℹ [2026-08-30 05:11:18] Perform `FindVariableFeatures()` on 3/5 of `srt_list`...
#> ! [2026-08-30 05:11:19] Data 4/5 of the `srt_list` is "unknown"
#> Warning: Data 4/5 of the `srt_list` is "unknown"
#> ℹ [2026-08-30 05:11:19] Perform `NormalizeData()` with `normalization.method = 'LogNormalize'` on 4/5 of `srt_list`...
#> ℹ [2026-08-30 05:11:19] Perform `FindVariableFeatures()` on 4/5 of `srt_list`...
#> ! [2026-08-30 05:11:19] Data 5/5 of the `srt_list` is "unknown"
#> Warning: Data 5/5 of the `srt_list` is "unknown"
#> ℹ [2026-08-30 05:11:19] Perform `NormalizeData()` with `normalization.method = 'LogNormalize'` on 5/5 of `srt_list`...
#> ℹ [2026-08-30 05:11:19] Perform `FindVariableFeatures()` on 5/5 of `srt_list`...
#> ℹ [2026-08-30 05:11:19] Use the separate HVF from `srt_list`
#> ℹ [2026-08-30 05:11:19] Number of available HVF: 2000
#> ℹ [2026-08-30 05:11:19] Finished check
panc8_sub <- SeuratObject::JoinLayers(panc8_sub)
pancreas_sub <- RunKNNPredict(
srt_query = pancreas_sub,
srt_ref = panc8_sub,
ref_group = "celltype"
)
#> ℹ [2026-08-30 05:11:21] Use the HVF to calculate distance metric
#> ℹ [2026-08-30 05:11:21] Use [1] 637 features to calculate distance.
#> ℹ [2026-08-30 05:11:22] Detected query data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:11:22] Detected reference data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:11:22] Calculate similarity...
#> ℹ [2026-08-30 05:11:22] Use raw method to find neighbors
#> ℹ [2026-08-30 05:11:22] Predict cell type...
CellDimPlot(
pancreas_sub,
group.by = "KNNPredict_classification",
label = TRUE
)
FeatureDimPlot(
pancreas_sub,
features = "KNNPredict_simil"
)
pancreas_sub <- RunKNNPredict(
srt_query = pancreas_sub,
srt_ref = panc8_sub,
ref_group = "celltype",
ref_collapsing = FALSE
)
#> ℹ [2026-08-30 05:11:22] Use the HVF to calculate distance metric
#> ℹ [2026-08-30 05:11:22] Use [1] 637 features to calculate distance.
#> ℹ [2026-08-30 05:11:22] Detected query data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:11:22] Detected reference data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:11:22] Calculate similarity...
#> ℹ [2026-08-30 05:11:22] Use raw method to find neighbors
#> ℹ [2026-08-30 05:11:23] Predict cell type...
CellDimPlot(
pancreas_sub,
group.by = "KNNPredict_classification",
label = TRUE
)
FeatureDimPlot(
pancreas_sub,
features = "KNNPredict_prob"
)
pancreas_sub <- RunKNNPredict(
srt_query = pancreas_sub,
srt_ref = panc8_sub,
query_group = "SubCellType",
ref_group = "celltype"
)
#> ℹ [2026-08-30 05:11:23] Use the HVF to calculate distance metric
#> ℹ [2026-08-30 05:11:23] Use [1] 637 features to calculate distance.
#> ℹ [2026-08-30 05:11:23] Detected query data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:11:23] Detected reference data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:11:23] Calculate similarity...
#> ℹ [2026-08-30 05:11:23] Use raw method to find neighbors
#> ℹ [2026-08-30 05:11:23] Predict cell type...
CellDimPlot(
pancreas_sub,
group.by = "KNNPredict_classification",
label = TRUE
)
FeatureDimPlot(
pancreas_sub,
features = "KNNPredict_simil"
)
# Annotate with DE gene instead of HVF
pancreas_sub <- RunKNNPredict(
srt_query = pancreas_sub,
srt_ref = panc8_sub,
ref_group = "celltype",
features_type = "DE",
feature_source = "ref",
DEtest_param = list(cores = 2)
)
#> ℹ [2026-08-30 05:11:24] Data type is log-normalized
#> ℹ [2026-08-30 05:11:24] Start differential expression test
#> ℹ [2026-08-30 05:11:24] Find all markers(wilcox) among [1] 13 groups...
#> ℹ [2026-08-30 05:11:24] Using 2 cores
#> ⠙ [2026-08-30 05:11:24] Running for acinar [1/13] 8% | ETA: 6m
#> ⠹ [2026-08-30 05:11:24] Running for ductal [3/13] ■■ 23% | ETA: 2m
#> ⠸ [2026-08-30 05:11:24] Running for beta [4/13] ■■■ 31% | ETA: 2m
#> ⠼ [2026-08-30 05:11:24] Running for activated-stellate [6/13] ■■■■ 46% |…
#> ⠴ [2026-08-30 05:11:24] Running for macrophage [8/13] ■■■■■■ 62% | ETA: 38s
#> ⠦ [2026-08-30 05:11:24] Running for mast [10/13] ■■■■■■■ 77% | ETA: 28s
#> ⠧ [2026-08-30 05:11:24] Running for endothelial [12/13] ■■■■■■■■■ 92% | ETA: …
#> ✔ [2026-08-30 05:11:24] Completed 13 tasks in 2m 3.9s
#>
#> ℹ [2026-08-30 05:11:24] Building results
#> ✔ [2026-08-30 05:13:28] Differential expression test completed
#> ℹ [2026-08-30 05:13:28] Use the DE features from AllMarkers_wilcox to calculate distance metric.
#> ℹ [2026-08-30 05:13:28] DE features number of the ref data: [1] 1995
#> ℹ [2026-08-30 05:13:28] Use [1] 1995 features to calculate distance.
#> ℹ [2026-08-30 05:13:29] Detected query data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:13:29] Detected reference data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:13:29] Calculate similarity...
#> ℹ [2026-08-30 05:13:29] Use raw method to find neighbors
#> ℹ [2026-08-30 05:13:29] Predict cell type...
CellDimPlot(
pancreas_sub,
group.by = "KNNPredict_classification",
label = TRUE
)
FeatureDimPlot(
pancreas_sub,
features = "KNNPredict_simil"
)
pancreas_sub <- RunKNNPredict(
srt_query = pancreas_sub,
srt_ref = panc8_sub,
query_group = "SubCellType",
ref_group = "celltype",
features_type = "DE",
feature_source = "both",
DEtest_param = list(cores = 2)
)
#> ℹ [2026-08-30 05:13:30] Data type is log-normalized
#> ℹ [2026-08-30 05:13:30] Start differential expression test
#> ℹ [2026-08-30 05:13:30] Find all markers(wilcox) among [1] 8 groups...
#> ℹ [2026-08-30 05:13:30] Using 2 cores
#> ⠙ [2026-08-30 05:13:30] Running for Ngn3-high-EP [1/8] ■ 12% | ETA: …
#> ⠹ [2026-08-30 05:13:30] Running for Ductal [2/8] ■■ 25% | ETA: 1m
#> ⠸ [2026-08-30 05:13:30] Running for Ngn3-low-EP [4/8] ■■■■■ 50% | ETA: 29s
#> ⠼ [2026-08-30 05:13:30] Running for Alpha [6/8] ■■■■■■■ 75% | ETA: 10s
#> ✔ [2026-08-30 05:13:30] Completed 8 tasks in 35.5s
#>
#> ℹ [2026-08-30 05:13:30] Building results
#> ✔ [2026-08-30 05:14:06] Differential expression test completed
#> ℹ [2026-08-30 05:14:06] Use the DE features from AllMarkers_wilcox to calculate distance metric.
#> ℹ [2026-08-30 05:14:06] DE features number of the query data: [1] 1998
#> ℹ [2026-08-30 05:14:08] Data type is log-normalized
#> ℹ [2026-08-30 05:14:08] Start differential expression test
#> ℹ [2026-08-30 05:14:08] Find all markers(wilcox) among [1] 13 groups...
#> ℹ [2026-08-30 05:14:08] Using 2 cores
#> ⠙ [2026-08-30 05:14:08] Running for acinar [1/13] 8% | ETA: 6m
#> ⠹ [2026-08-30 05:14:08] Running for ductal [3/13] ■■ 23% | ETA: 2m
#> ⠸ [2026-08-30 05:14:08] Running for beta [4/13] ■■■ 31% | ETA: 1m
#> ⠼ [2026-08-30 05:14:08] Running for activated-stellate [6/13] ■■■■ 46% |…
#> ⠴ [2026-08-30 05:14:08] Running for macrophage [8/13] ■■■■■■ 62% | ETA: 35s
#> ⠦ [2026-08-30 05:14:08] Running for mast [10/13] ■■■■■■■ 77% | ETA: 26s
#> ⠧ [2026-08-30 05:14:08] Running for endothelial [12/13] ■■■■■■■■■ 92% | ETA: …
#> ✔ [2026-08-30 05:14:08] Completed 13 tasks in 1m 59s
#>
#> ℹ [2026-08-30 05:14:08] Building results
#> ✔ [2026-08-30 05:16:07] Differential expression test completed
#> ℹ [2026-08-30 05:16:07] Use the DE features from AllMarkers_wilcox to calculate distance metric.
#> ℹ [2026-08-30 05:16:07] DE features number of the ref data: [1] 348
#> ℹ [2026-08-30 05:16:07] Use [1] 99 features to calculate distance.
#> ℹ [2026-08-30 05:16:09] Detected query data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:16:09] Detected reference data type: "log_normalized_counts"
#> ℹ [2026-08-30 05:16:09] Calculate similarity...
#> ℹ [2026-08-30 05:16:09] Use raw method to find neighbors
#> ℹ [2026-08-30 05:16:09] Predict cell type...
CellDimPlot(
pancreas_sub,
group.by = "KNNPredict_classification",
label = TRUE
)
FeatureDimPlot(
pancreas_sub,
features = "KNNPredict_simil"
)