R/cos_similarity.R

Defines functions max_similarity rank_angle cos_sim cos_similarity

Documented in cos_similarity max_similarity rank_angle

#' Gene signature cosine similarity matrix
#'
#' Computes the cosine similarity matrix from the gene signature matrix of a
#' `cellMarkers` object or any matrix. Note that this function computes cosine
#' similarity between matrix columns, unlike [dist()] which computes the
#' distance metric between matrix rows.
#' 
#' @param x Either a matrix or a 'cellMarkers' class or 'deconv' class object.
#' @param use_filter Logical whether to use filtered gene signature.
#' @returns A symmetric similarity matrix.
#' @export
#' 
cos_similarity <- function(x, use_filter = NULL) {
  if (inherits(x, "deconv")) {
    x <- x$mk
    if (is.null(use_filter)) use_filter <- x$opt$use_filter
  }
  if (inherits(x, "cellMarkers")) {
    if (is.null(use_filter)) use_filter <- TRUE
    gs <- x$geneset
    x <- if (use_filter) x$genemeans_filtered[gs, ] else x$genemeans[gs, ]
  }
  cos_sim(x)
}


# cosine similarity of columns of a matrix
cos_sim <- function(x) {
  sx <- scaleSphere(t(x))
  out <- tcrossprod(sx)
  diag(out) <- 1
  out
}

#' Rank distance angles from a cosine similarity matrix
#' 
#' Converts a cosine similarity matrix to angular distance. Then orders the
#' elements in increasing angle. Elements below `angle_cutoff` are returned in a
#' dataframe.
#' 
#' @param x a cosine similarity matrix generated by [cos_similarity()].
#' @param angle_cutoff Cutoff angle in degrees below which to subset the dataframe.
#' @returns a dataframe of rows and columns as factors and the angle between
#'   that row and column extracted from the cosine similarity matrix. Row and
#'   column location are stored as factors so that they can be converted back to
#'   coordinates in the similarity matrix easily using `as.integer()`.
#' @export
rank_angle <- function(x, angle_cutoff = 45) {
  if (!is.matrix(x)) stop("x is not a matrix")
  ang <- acos(x) * 180/pi
  o <- order(ang)
  ind <- arrayInd(o, .dim = dim(x))
  ok <- ind[,1] < ind[,2] & ang[o] <= angle_cutoff
  o2 <- o[ok]
  
  c1 <- factor(ind[ok, 1], levels = seq_len(nrow(x)), labels = rownames(x))
  c2 <- factor(ind[ok, 2], levels = seq_len(ncol(x)), labels = colnames(x))
  data.frame(c1, c2, angle = ang[o2])
}


#' Maximum similarity between cell types
#' 
#' Computes maximum similarity between cell types based on the gene signature
#' matrix.
#' 
#' @param x Either a matrix or a 'cellMarkers' class or 'deconv' class object.
#' @param ... Optional arguments passed to [cos_similarity()].
#' @returns A vector of similarity results.
#' @seealso [diagnose()] which outputs a more comprehensive pairwise comparison
#'   of similarity between cell subclasses.
#' @export
max_similarity <- function(x, ...) {
  cs <- cos_similarity(x, ...)
  diag(cs) <- 0
  rowMaxs(cs)
}

Try the cellGeometry package in your browser

Any scripts or data that you put into this service are public.

cellGeometry documentation built on April 20, 2026, 1:06 a.m.