---
title: "scCertify: Explainable Confidence Scoring for Single-Cell Annotations"
author:
    - name: "Jaya Surya Doddetipalli"
package: scCertify
output:
    BiocStyle::html_document:
        toc: true
        number_sections: true
vignette: >
    %\VignetteIndexEntry{scCertify: Explainable Confidence Scoring for Single-Cell Annotations}
    %\VignetteEngine{knitr::rmarkdown}
    %\VignetteEncoding{UTF-8}
---

# Overview

`scCertify` provides an explainable framework for evaluating confidence in
single-cell RNA-sequencing cell-type annotations.

The package combines several complementary sources of evidence:

- marker-gene consistency,
- neighborhood agreement,
- entropy-based uncertainty,
- doublet information,
- calibrated confidence scores, and
- interpretable confidence classes.

`scCertify` supports both `SingleCellExperiment` and Seurat objects.

```{r setup}
library(scCertify)
library(SingleCellExperiment)
library(SummarizedExperiment)
library(Seurat)

set.seed(42)
```

# Input Data

The following example creates a small simulated
`SingleCellExperiment` containing count data and predicted cell-type labels.

```{r simulate-data}
n_genes <- 50
n_cells <- 40

counts <- matrix(
    rpois(n_genes * n_cells, lambda = 5),
    nrow = n_genes,
    ncol = n_cells,
    dimnames = list(
        paste0("Gene", seq_len(n_genes)),
        paste0("Cell", seq_len(n_cells))
    )
)

sce <- SingleCellExperiment(
    assays = list(
        counts = counts
    )
)

colData(sce)$predicted_label <- rep(
    c("T cell", "B cell"),
    each = n_cells / 2
)

sce
```

The predicted cell labels are stored in `colData()`.

```{r sce-metadata}
head(colData(sce))
```

# Marker Gene Definitions

A marker database is represented as a named list, with one element for each
predicted cell type.

```{r marker-list}
markers <- list(
    "T cell" = c("Gene1", "Gene2", "Gene3"),
    "B cell" = c("Gene4", "Gene5", "Gene6")
)

markers
```

# Neighborhood Representation

`neighbor_score()` evaluates agreement among nearby cells. For a
`SingleCellExperiment`, a suitable low-dimensional representation is required.

For this simulated example, a `logcounts` assay is created from a
log-transformed count matrix. `marker_score()` requires this assay to be
present, and the same log-transformed matrix is also used to calculate PCA.

```{r sce-pca}
log_counts <- log1p(
    assay(sce, "counts")
)

assay(sce, "logcounts") <- log_counts

pca <- stats::prcomp(
    t(log_counts),
    center = TRUE,
    scale. = TRUE
)$x[, seq_len(5), drop = FALSE]

reducedDim(sce, "PCA") <- pca

dim(
    reducedDim(sce, "PCA")
)
```

# Marker Consistency

Marker consistency evaluates whether cells express genes expected for their
predicted identity.

`scCertify` uses rank-based enrichment scoring through UCell.

```{r marker-score}
marker_scores <- marker_score(
    sce,
    markers,
    label_column = "predicted_label"
)

head(marker_scores)
```

The resulting scores provide a cell-level measure of marker consistency.

# Neighborhood Agreement

The neighborhood score measures whether nearby cells tend to share the same
predicted annotation.

```{r neighbor-score}
neighbor_scores <- neighbor_score(
    sce,
    label_column = "predicted_label"
)

head(neighbor_scores)
```

# Entropy-Based Uncertainty

`entropy_score()` provides an uncertainty measure based on the distribution of
expression values.

```{r entropy-score}
entropy_values <- entropy_score(
    t(assay(sce, "counts"))
)

head(entropy_values)
```

The values can be normalized and stored in the cell metadata.

```{r entropy-norm}
entropy_norm <- entropy_values / max(
    entropy_values,
    na.rm = TRUE
)

colData(sce)$entropy_norm <- entropy_norm

head(colData(sce)$entropy_norm)
```

# Doublet Information

For this simulated example, doublet scores are generated as demonstration
metadata.

In a real analysis, these values would normally come from a dedicated doublet
detection method.

```{r doublet-score}
colData(sce)$doublet_score <- runif(
    ncol(sce),
    min = 0,
    max = 1
)

head(colData(sce)$doublet_score)
```

# Cell Certification

`cell_certify()` combines marker consistency, neighborhood agreement,
entropy-based uncertainty, and doublet information into a calibrated
confidence score.

```{r cell-certify}
sce <- cell_certify(
    sce,
    markers,
    label_column = "predicted_label"
)

head(
    colData(sce)[,
        c(
            "predicted_label",
            "marker_score",
            "neighbor_score",
            "entropy_norm",
            "doublet_score",
            "confidence_score",
            "confidence_class"
        )
    ]
)
```

# Custom Confidence Thresholds

Confidence classes can be customized using the `moderate_threshold` and
`high_threshold` arguments.

```{r custom-thresholds}
sce_custom <- cell_certify(
    sce,
    markers,
    label_column = "predicted_label",
    moderate_threshold = 0.4,
    high_threshold = 0.75
)

head(
    colData(sce_custom)[,
        c(
            "confidence_score",
            "confidence_class"
        )
    ]
)
```

# Explaining Confidence

`explain_confidence()` identifies factors that contributed to lower confidence
for an individual cell.

```{r explain-confidence}
explain_confidence(
    sce,
    cell_id = "Cell1"
)
```

`explain_cell()` provides a concise summary containing the predicted label,
confidence score, individual evidence components, and interpretation.

```{r explain-cell}
explain_cell(
    sce,
    cell_id = "Cell1"
)
```

# Seurat Interoperability

`scCertify` also supports Seurat objects. The following example demonstrates a
complete evaluated Seurat workflow.

```{r seurat-data}
seurat_counts <- matrix(
    rpois(2000, lambda = 5),
    nrow = 100,
    ncol = 20,
    dimnames = list(
        paste0("Gene", seq_len(100)),
        paste0("Cell", seq_len(20))
    )
)

seurat_object <- Seurat::CreateSeuratObject(
    counts = seurat_counts
)

seurat_object$predicted_label <- rep(
    c("T cell", "B cell"),
    each = 10
)

seurat_object$entropy_norm <- runif(
    ncol(seurat_object)
)

seurat_object$doublet_score <- runif(
    ncol(seurat_object)
)

seurat_object
```

The Seurat object is processed using its standard normalization and PCA
workflow.

```{r seurat-preprocessing}
seurat_object <- Seurat::NormalizeData(
    seurat_object,
    verbose = FALSE
)

seurat_object <- Seurat::FindVariableFeatures(
    seurat_object,
    verbose = FALSE
)

seurat_object <- Seurat::ScaleData(
    seurat_object,
    verbose = FALSE
)

seurat_object <- Seurat::RunPCA(
    seurat_object,
    npcs = 10,
    verbose = FALSE
)

seurat_object
```

The same marker definitions can then be used with `scCertify`.

```{r seurat-certify}
seurat_object <- cell_certify(
    seurat_object,
    markers,
    label_column = "predicted_label"
)

head(
    seurat_object[[
        c(
            "predicted_label",
            "marker_score",
            "neighbor_score",
            "entropy_norm",
            "doublet_score",
            "confidence_score",
            "confidence_class"
        )
    ]]
)
```

The resulting confidence information is stored directly in the Seurat
metadata.

```{r seurat-explain}
explain_confidence(
    seurat_object,
    cell_id = "Cell1"
)

explain_cell(
    seurat_object,
    cell_id = "Cell1"
)
```

# Summary

This vignette demonstrates the complete `scCertify` workflow for both
`SingleCellExperiment` and Seurat objects.

The workflow consists of:

1. creating or loading an annotated single-cell object,
2. supplying marker genes,
3. calculating marker consistency,
4. evaluating neighborhood agreement,
5. estimating entropy-based uncertainty,
6. incorporating doublet information,
7. calculating calibrated confidence scores,
8. assigning confidence classes, and
9. explaining confidence for individual cells.

Because all examples in this vignette are evaluated, the document also provides
a continuously tested demonstration that the documented workflow remains
functional with the package dependencies used by `scCertify`.

# Session Information

```{r session-info}
sessionInfo()
```
