BDNF regulates pituitary stem cell engagement toward precursor state.
The 6 matches
- [1] § STAR★Methods › Method details › Ligand-receptor inference ↔ R/modeling.R, lines 2–63 · score 0.76 · ligand receptor interacting, cell cluster, Seurat, CellChat, inference, inversely
- [2] § STAR★Methods › Method details › Pseudotime trajectory analysis ↔ R/modeling.R, lines 2–63 · score 0.71 · nearest neighbor, Single cell transcriptomic, Dimensionality, gene expression, inferred, imported
- [3] § STAR★Methods › Method details › Ligand-receptor inference ↔ R/CellChat_class.R, lines 2–76 · score 0.68 · ligand receptor interacting, Seurat, CellChat, inference, v3, probability
- [4] § STAR★Methods › Method details › Pseudotime trajectory analysis ↔ R/CellChat_class.R, lines 2–76 · score 0.68 · single cell RNA, Single cell transcriptomic, UMAP, Preprocessed, Dimensionality, imported
- [5] § Results › BDNF, a candidate trophic factor for pre-corticotrope expansion ↔ R/utilities.R, lines 712–814 · score 0.62 · ligand receptor pair, expressed ligand, expressed genes, CellChat, interactions, cells
- [6] § STAR★Methods › Method details › Immunofluorescence (IHF) staining › Pomc−/− scRNA-seq ↔ R/utilities.R, lines 1014–1042 · score 0.55 · UMAP, embedding, algorithm, dimensionality, manifold, component
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
R · 1,297 lines · 65 KB · GPL-3.0 · 2 matches
- #' Compute the communication probability/strength between any interacting cell groups
- #'
- #' To further speed up on large-scale datasets, USER can downsample the data using the function 'subset' from Seurat package (e.g., pbmc.small <- subset(pbmc, downsample = 500)), or using the function `sketchData` from CellChat, in particular for the large cell clusters;
- #'
- #'
- #' @param object CellChat object
- #' @param type Methods for computing the average gene expression per cell group. By default = "triMean", producing fewer but stronger interactions;
- #' When setting `type = "truncatedMean"`, a value should be assigned to 'trim', producing more interactions.
- #' @param trim the fraction (0 to 0.25) of observations to be trimmed from each end of x before the mean is computed
- #' @param LR.use A subset of ligand-receptor interactions used in inferring communication network
- #' @param raw.use Whether use the raw data (i.e., `[email hidden]`) or the smoothed data (i.e., `[email hidden]`).
- #' Set raw.use = FALSE to use the projected data when analyzing single-cell data with shallow sequencing depth because the projected data could help to reduce the dropout effects of signaling genes, in particular for possible zero expression of subunits of ligands/receptors.
- #' @param population.size Whether consider the proportion of cells in each group across all sequenced cells.
- #' Set population.size = FALSE if analyzing sorting-enriched single cells, to remove the potential artifact of population size.
- #' Set population.size = TRUE if analyzing unsorted single-cell transcriptomes, with the reason that abundant cell populations tend to send collectively stronger signals than the rare cell populations.
- #'
- #' Parameters for spatial data analysis:
- #' @param distance.use Whether to use distance constraints to compute communication probability. Setting `distance.use = TRUE` indicates that the cell-cell communication probability is inversely proportional to the computed distance.
- #' Setting `distance.use = FALSE` will only filter out interactions between spatially distant regions, but not add distance constraints.
- #' @param interaction.range The maximum interaction/diffusion length of ligands (Unit: microns). This hard threshold is used to filter out the connections between spatially distant regions
- #' @param scale.distance A scale or normalization factor for the spatial distances when setting `distance.use = TRUE`. For example, scale.distance equals 1, 0.1, 0.01, 0.001, 0.11, or 0.011. We choose this values such that the minimum value of the scaled distances is in [1,2]. This value is not necessary when setting `distance.use = FALSE`.
- #'
- #' When comparing communication across different CellChat objects, the same scale factor should be used. For a single CellChat analysis, different scale factors will not affect the ranking of the signaling based on their interaction strength.
- #'
- #' @param k.min The minimum number of interacting cell pairs required for defining spatially proximal cell groups.
- #' @param contact.dependent Whether using the `contact-dependent` manner for inference signaling, that is determining interacting cell pairs by requiring cells to be in direct membrane-membrane contact. By default `contact.dependent = TRUE` when inferring contact-dependent and juxtacrine signaling (that is "Cell-Cell Contact" signaling classified in CellChatDB$interaction$annotation).
- #' If only focusing on `Secreted Signaling`, the `contact-dependent` manner will be not used except for setting `contact.dependent.forced = TRUE`.
- #' @param contact.range The interaction range (Unit: microns) to restrict the contact-dependent signaling when `contact.dependent = TRUE`.
- #' For spatial transcriptomics in a single-cell resolution, `contact.range` is approximately equal to the estimated cell diameter (i.e., the cell center-to-center distance), which means that contact-dependent and juxtacrine signaling can only happens when the two cells are contact to each other.
- #'
- #' Typically, `contact.range = 10`, which is a typical human cell size. However, for low-resolution spatial data such as 10X visium, it should be the cell center-to-center distance (i.e., `contact.range = 100` for visium data). The function `computeCellDistance` can compute the center-to-center distance.
- #'
- #' @param contact.knn.k Number of neighbors to restrict the contact-dependent signaling within the neatest neighbors when `contact.dependent = TRUE`. By default, CellChat uses `contact.range` to restrict the contact-dependent signaling; however, users can also provide a value of `contact.knn.k`, in order to determine interacting cell pairs based on the k-nearest neighbors (knn).
- #' For 10X visium, contact.knn.k = 6. For other spatial technologies, this value may be hard to determine because the sequenced cells/spots are usually not regularly arranged.
- #' @param do.symmetric Whether converting the adjacent matrix into symmetric one when determining spatially proximal cell groups. Default is TRUE, indicating that if adj(i,j) or adj(j,i) is zero, then both are zeros.
- #'
- #' @param contact.dependent.forced Whether forcing to use the `contact-dependent` manner for inference signaling for all L-R pairs including secreted signaling. Users can set `contact.dependent.forced = TRUE` if also preferring interactions within a contact manner for `Secreted Signaling`.
- #'
- #' @param nboot Threshold of p-values
- #' @param seed.use Set a random seed. By default, set the seed to 1.
- #' @param Kh Parameter in Hill function
- #' @param n Parameter in Hill function
- #'
- #'
- #' @importFrom future nbrOfWorkers
- #' @importFrom future.apply future_sapply
- #' @importFrom pbapply pbsapply
- #' @importFrom stats aggregate
- #' @importFrom Matrix crossprod
- #' @importFrom utils txtProgressBar setTxtProgressBar
- #'
- #' @return A CellChat object with updated slot 'net':
- #'
- #' object@net$prob is the inferred communication probability (strength) array, where the first, second and third dimensions represent a source, target and ligand-receptor pair, respectively.
- #'
- #' USER can access all the inferred cell-cell communications using the function 'subsetCommunication(object)', which returns a data frame.
- #'
- #' object@net$pval is the corresponding p-values of each interaction
- #'
- #' @export
- #'
- computeCommunProb <- function(object, type = c("triMean", "truncatedMean","thresholdedMean", "median"), trim = 0.1, LR.use = NULL, raw.use = TRUE, population.size = FALSE,
- distance.use = TRUE, interaction.range = 250, scale.distance = 0.01, k.min = 10, contact.dependent = TRUE, contact.range = NULL, contact.knn.k = NULL, contact.dependent.forced = FALSE, do.symmetric = TRUE,
- nboot = 100, seed.use = 1L, Kh = 0.5, n = 1) {
- type <- match.arg(type)
- cat(type, "is used for calculating the average gene expression per cell group.", "\n")
- FunMean <- switch(type,
- triMean = triMean,
- truncatedMean = function(x) mean(x, trim = trim, na.rm = TRUE),
- thresholdedMean = function(x) thresholdedMean(x, trim = trim, na.rm = TRUE),
- median = function(x) median(x, na.rm = TRUE))
- if (raw.use) {
- data <- as.matrix([email hidden])
- } else {
- data <- as.matrix([email hidden])
- }
- if (is.null(LR.use)) {
- pairLR.use <- object@LR$LRsig
- } else {
- if (length(unique(LR.use$annotation)) > 1) {
- LR.use$annotation <- factor(LR.use$annotation, levels = c("Secreted Signaling","ECM-Receptor", "Non-protein Signaling", "Cell-Cell Contact"))
- LR.use <- LR.use[order(LR.use$annotation), , drop = FALSE]
- LR.use$annotation <- as.character(LR.use$annotation)
- }
- pairLR.use <- LR.use
- }
- complex_input <- object@DB$complex
- cofactor_input <- object@DB$cofactor
- my.sapply <- ifelse(
- test = future::nbrOfWorkers() == 1,
- yes = sapply,
- no = future.apply::future_sapply
- )
- ptm = Sys.time()
- pairLRsig <- pairLR.use
- group <- object@idents
- geneL <- as.character(pairLRsig$ligand)
- geneR <- as.character(pairLRsig$receptor)
- nLR <- nrow(pairLRsig)
- numCluster <- nlevels(group)
- if (numCluster != length(unique(group))) {
- stop("Please check `unique(object@idents)` and ensure that the factor levels are correct!
- You may need to drop unused levels using 'droplevels' function. e.g.,
- `meta$labels = droplevels(meta$labels, exclude = setdiff(levels(meta$labels),unique(meta$labels)))`")
- }
- data.use <- data/max(data)
- nC <- ncol(data.use)
- # compute the average expression per group
- data.use.avg <- aggregate(t(data.use), list(group), FUN = FunMean)
- data.use.avg <- t(data.use.avg[,-1])
- colnames(data.use.avg) <- levels(group)
- # compute the expression of ligand or receptor
- dataLavg <- computeExpr_LR(geneL, data.use.avg, complex_input)
- dataRavg <- computeExpr_LR(geneR, data.use.avg, complex_input)
- # take account into the effect of co-activation and co-inhibition receptors
- dataRavg.co.A.receptor <- computeExpr_coreceptor(cofactor_input, data.use.avg, pairLRsig, type = "A")
- dataRavg.co.I.receptor <- computeExpr_coreceptor(cofactor_input, data.use.avg, pairLRsig, type = "I")
- dataRavg <- dataRavg * dataRavg.co.A.receptor/dataRavg.co.I.receptor
- dataLavg2 <- t(replicate(nrow(dataLavg), as.numeric(table(group))/nC))
- dataRavg2 <- dataLavg2
- # compute the expression of agonist and antagonist
- index.agonist <- which(!is.na(pairLRsig$agonist) & pairLRsig$agonist != "")
- index.antagonist <- which(!is.na(pairLRsig$antagonist) & pairLRsig$antagonist != "")
- # quantify the communication probability
- # compute the spatial constraint
- if (object@options$datatype != "RNA") {
- data.spatial <- object@images$coordinates
- if ("spatial.factors" %in% names(object@images)) {
- ratio <- object@images$spatial.factors$ratio
- tol <- object@images$spatial.factors$tol
- } else {
- stop("`object@images$spatial.factors` is missing. Please update the object via `updateCellChat`! \n")
- }
- meta.t = data.frame(group = group, samples = object@meta$samples, row.names = rownames(object@meta))
- res <- computeRegionDistance(coordinates = data.spatial, meta = meta.t, interaction.range = interaction.range, ratio = ratio, tol = tol, k.min = k.min, contact.dependent = contact.dependent, contact.range = contact.range, contact.knn.k = contact.knn.k)
- d.spatial <- res$d.spatial # NaN if no nearby cell pairs
- adj.contact <- res$adj.contact # zeros if no nearby cell pairs
- if (distance.use) {
- print(paste0('>>> Run CellChat on spatial transcriptomics data using distances as constraints of the computed communication probability <<< [', Sys.time(),']'))
- d.spatial <- d.spatial * scale.distance
- diag(d.spatial) <- NaN
- d.min <- min(d.spatial, na.rm = TRUE)
- if (d.min < 1) {
- cat("The suggested minimum value of scaled distances is in [1,2], and the calculated value here is ", d.min,"\n")
- stop("Please increase the value of `scale.distance` and use a value that is slighly smaller than ", format(1/d.min, digits = 2) ,"\n")
- }
- P.spatial <- 1/d.spatial
- P.spatial[is.na(d.spatial)] <- 0
- diag(P.spatial) <- max(P.spatial) # if this value is 1, the self-connections will have more larger weight.
- d.spatial <- d.spatial/scale.distance # This is only for saving the data
- } else {
- print(paste0('>>> Run CellChat on spatial transcriptomics data without distance values as constraints of the computed communication probability <<< [', Sys.time(),']'))
- P.spatial <- matrix(1, nrow = numCluster, ncol = numCluster)
- P.spatial[is.na(d.spatial)] <- 0 # diagonal is 1
- }
- } else {
- print(paste0('>>> Run CellChat on sc/snRNA-seq data <<< [', Sys.time(),']'))
- d.spatial <- matrix(NaN, nrow = numCluster, ncol = numCluster)
- P.spatial <- matrix(1, nrow = numCluster, ncol = numCluster)
- adj.contact <- matrix(1, nrow = numCluster, ncol = numCluster)
- contact.dependent = FALSE; contact.dependent.forced = FALSE; contact.range = NULL; contact.knn.k = NULL;
- distance.use = NULL; interaction.range = NULL; ratio = NULL; tol = NULL; k.min = NULL;
- }
- if (object@options$datatype == "RNA") {
- nLR1 <- nLR
- } else {
- if (contact.dependent.forced == TRUE) {
- cat("Force to run CellChat in a `contact-dependent` manner for all L-R pairs including secreted signaling.\n")
- P.spatial <- P.spatial * adj.contact
- nLR1 <- nLR
- } else { # contact.dependent.forced == F
- if (contact.dependent == TRUE && length(unique(pairLRsig$annotation)) > 0) {
- if (all(unique(pairLRsig$annotation) %in% c("Cell-Cell Contact"))) {
- cat("All the input L-R pairs are `Cell-Cell Contact` signaling. Run CellChat in a contact-dependent manner. \n")
- P.spatial <- P.spatial * adj.contact
- nLR1 <- nLR
- } else if (all(unique(pairLRsig$annotation) %in% c("Secreted Signaling", "ECM-Receptor", "Non-protein Signaling"))) {
- cat("Molecules of the input L-R pairs are diffusible. Run CellChat in a diffusion manner based on the `interaction.range`.\n")
- nLR1 <- nLR
- } else {
- cat("The input L-R pairs have both secreted signaling and contact-dependent signaling. Run CellChat in a contact-dependent manner for `Cell-Cell Contact` signaling, and in a diffusion manner based on the `interaction.range` for other L-R pairs. \n")
- nLR1 <- max(which(pairLRsig$annotation %in% c("Secreted Signaling", "ECM-Receptor", "Non-protein Signaling")))
- }
- } else { # contact.dependent == F or there is no `annotation` column in the database
- cat("Run CellChat in a diffusion manner based on the `interaction.range` for all L-R pairs. Setting `contact.dependent = TRUE` if preferring a contact-dependent manner for `Cell-Cell Contact` signaling. \n")
- nLR1 <- nLR
- }
- }
- }
- Prob <- array(0, dim = c(numCluster,numCluster,nLR))
- Pval <- array(0, dim = c(numCluster,numCluster,nLR))
- set.seed(seed.use)
- permutation <- replicate(nboot, sample.int(nC, size = nC))
- data.use.avg.boot <- my.sapply(
- X = 1:nboot,
- FUN = function(nE) {
- groupboot <- group[permutation[, nE]]
- data.use.avgB <- aggregate(t(data.use), list(groupboot), FUN = FunMean)
- data.use.avgB <- t(data.use.avgB[,-1])
- return(data.use.avgB)
- },
- simplify = FALSE
- )
- pb <- txtProgressBar(min = 0, max = nLR, style = 3, file = stderr())
- for (i in 1:nLR) {
- # ligand/receptor
- dataLR <- Matrix::crossprod(matrix(dataLavg[i,], nrow = 1), matrix(dataRavg[i,], nrow = 1))
- P1 <- dataLR^n/(Kh^n + dataLR^n)
- P1_Pspatial <- P1*P.spatial
- if (sum(P1_Pspatial) == 0) {
- Pnull = P1_Pspatial
- Prob[ , , i] <- Pnull
- p = 1
- Pval[, , i] <- matrix(p, nrow = numCluster, ncol = numCluster, byrow = FALSE)
- } else {
- if (i > nLR1) {
- P.spatial <- P.spatial * adj.contact
- }
- # agonist and antagonist
- if (is.element(i, index.agonist)) {
- data.agonist <- computeExpr_agonist(data.use = data.use.avg, pairLRsig, cofactor_input, index.agonist = i, Kh = Kh, n = n)
- P2 <- Matrix::crossprod(matrix(data.agonist, nrow = 1))
- } else {
- P2 <- matrix(1, nrow = numCluster, ncol = numCluster)
- }
- if (is.element(i, index.antagonist)) {
- data.antagonist <- computeExpr_antagonist(data.use = data.use.avg, pairLRsig, cofactor_input, index.antagonist = i, Kh = Kh, n = n)
- P3 <- Matrix::crossprod(matrix(data.antagonist, nrow = 1))
- } else {
- P3 <- matrix(1, nrow = numCluster, ncol = numCluster)
- }
- # number of cells
- if (population.size) {
- P4 <- Matrix::crossprod(matrix(dataLavg2[i,], nrow = 1), matrix(dataRavg2[i,], nrow = 1))
- } else {
- P4 <- matrix(1, nrow = numCluster, ncol = numCluster)
- }
- # Pnull = P1*P2*P3*P4
- Pnull = P1*P2*P3*P4*P.spatial
- Prob[ , , i] <- Pnull
- Pnull <- as.vector(Pnull)
- #Pboot <- foreach(nE = 1:nboot) %dopar% {
- Pboot <- my.sapply(
- X = 1:nboot,
- FUN = function(nE) {
- data.use.avgB <- data.use.avg.boot[[nE]]
- dataLavgB <- computeExpr_LR(geneL[i], data.use.avgB, complex_input)
- dataRavgB <- computeExpr_LR(geneR[i], data.use.avgB, complex_input)
- # take account into the effect of co-activation and co-inhibition receptors
- dataRavgB.co.A.receptor <- computeExpr_coreceptor(cofactor_input, data.use.avgB, pairLRsig[i, , drop = FALSE], type = "A")
- dataRavgB.co.I.receptor <- computeExpr_coreceptor(cofactor_input, data.use.avgB, pairLRsig[i, , drop = FALSE], type = "I")
- dataRavgB <- dataRavgB * dataRavgB.co.A.receptor/dataRavgB.co.I.receptor
- dataLRB = Matrix::crossprod(dataLavgB, dataRavgB)
- P1.boot <- dataLRB^n/(Kh^n + dataLRB^n)
- # agonist and antagonist
- if (is.element(i, index.agonist)) {
- data.agonist <- computeExpr_agonist(data.use = data.use.avgB, pairLRsig, cofactor_input, index.agonist = i, Kh = Kh, n = n)
- P2.boot <- Matrix::crossprod(matrix(data.agonist, nrow = 1))
- } else {
- P2.boot <- matrix(1, nrow = numCluster, ncol = numCluster)
- }
- if (is.element(i, index.antagonist)) {
- data.antagonist <- computeExpr_antagonist(data.use = data.use.avgB, pairLRsig, cofactor_input, index.antagonist = i, Kh = Kh, n= n)
- P3.boot <- Matrix::crossprod(matrix(data.antagonist, nrow = 1))
- } else {
- P3.boot <- matrix(1, nrow = numCluster, ncol = numCluster)
- }
- if (population.size) {
- groupboot <- group[permutation[, nE]]
- dataLavg2B <- as.numeric(table(groupboot))/nC
- dataLavg2B <- matrix(dataLavg2B, nrow = 1)
- dataRavg2B <- dataLavg2B
- P4.boot = Matrix::crossprod(dataLavg2B, dataRavg2B)
- } else {
- P4.boot = matrix(1, nrow = numCluster, ncol = numCluster)
- }
- # Pboot = P1.boot*P2.boot*P3.boot*P4.boot
- Pboot = P1.boot*P2.boot*P3.boot*P4.boot*P.spatial
- return(as.vector(Pboot))
- }
- )
- Pboot <- matrix(unlist(Pboot), nrow=length(Pnull), ncol = nboot, byrow = FALSE)
- nReject <- rowSums(Pboot - Pnull > 0)
- p = nReject/nboot
- Pval[, , i] <- matrix(p, nrow = numCluster, ncol = numCluster, byrow = FALSE)
- }
- setTxtProgressBar(pb = pb, value = i)
- }
- close(con = pb)
- Pval[Prob == 0] <- 1
- dimnames(Prob) <- list(levels(group), levels(group), rownames(pairLRsig))
- dimnames(Pval) <- dimnames(Prob)
- net <- list("prob" = Prob, "pval" = Pval)
- execution.time = Sys.time() - ptm
- object@options$run.time <- as.numeric(execution.time, units = "secs")
- object@options$parameter <- list(type.mean = type, trim = trim, raw.use = raw.use, population.size = population.size, nboot = nboot, seed.use = seed.use, Kh = Kh, n = n,
- distance.use = distance.use, interaction.range = interaction.range, ratio = ratio, tol = tol, k.min = k.min,
- contact.dependent = contact.dependent, contact.range = contact.range, contact.knn.k = contact.knn.k, contact.dependent.forced = contact.dependent.forced
- )
- if (object@options$datatype != "RNA") {
- object@images$distance <- d.spatial
- }
- object@net <- net
- print(paste0('>>> CellChat inference is done. Parameter values are stored in `object@options$parameter` <<< [', Sys.time(),']'))
- return(object)
- }
- #' Compute the communication probability on signaling pathway level by summarizing all related ligands/receptors
- #'
- #' @param object CellChat object
- #' @param net A list from object@net; If net = NULL, net = object@net
- #' @param pairLR.use A dataframe giving the ligand-receptor interactions; If pairLR.use = NULL, pairLR.use = object@LR$LRsig
- #' @param thresh threshold of the p-value for determining significant interaction
- #'
- #' @return A CellChat object with updated slot 'netP':
- #'
- #' object@netP$prob is the communication probability array on signaling pathway level; USER can convert this array to a data frame using the function 'reshape2::melt()',
- #'
- #' e.g., `df.netP <- reshape2::melt(object@netP$prob, value.name = "prob"); colnames(df.netP)[1:3] <- c("source","target","pathway_name")` or access all significant interactions using the function \code{\link{subsetCommunication}}
- #'
- #' object@netP$pathways list all the signaling pathways with significant communications.
- #'
- #' From version >= 1.1.0, pathways are ordered based on the total communication probabilities. NB: pathways with small total communication probabilities might be also very important since they might be specifically activated between only few cell types.
- #'
- #' @export
- #'
- computeCommunProbPathway <- function(object = NULL, net = NULL, pairLR.use = NULL, thresh = 0.05) {
- if (is.null(net)) {
- net <- object@net
- }
- if (is.null(pairLR.use)) {
- pairLR.use <- object@LR$LRsig
- }
- prob <- net$prob
- prob[net$pval > thresh] <- 0
- LR <- dimnames(prob)[[3]]
- LR.sig <- LR[apply(prob, 3, sum) != 0]
- pathways <- unique(pairLR.use$pathway_name)
- group <- factor(pairLR.use$pathway_name, levels = pathways)
- prob.pathways <- aperm(apply(prob, c(1, 2), by, group, sum), c(2, 3, 1))
- pathways.sig <- pathways[apply(prob.pathways, 3, sum) != 0]
- prob.pathways.sig <- prob.pathways[,,pathways.sig, drop = FALSE]
- idx <- sort(apply(prob.pathways.sig, 3, sum), decreasing=TRUE, index.return = TRUE)$ix
- pathways.sig <- pathways.sig[idx]
- prob.pathways.sig <- prob.pathways.sig[, , idx]
- if (is.null(object)) {
- netP = list(pathways = pathways.sig, prob = prob.pathways.sig)
- return(netP)
- } else {
- object@net$LRs <- LR.sig
- object@netP$pathways <- pathways.sig
- object@netP$prob <- prob.pathways.sig
- return(object)
- }
- }
- #' Calculate the aggregated network by counting the number of links or summarizing the communication probability
- #'
- #' @param object CellChat object
- #' @param sources.use,targets.use,signaling,pairLR.use Please check the description in function \code{\link{subsetCommunication}}
- #' @param remove.isolate whether removing the isolate cell groups without any interactions when applying \code{\link{subsetCommunication}}
- #' @param thresh threshold of the p-value for determining significant interaction
- #' @param return.object whether return an updated CellChat object
- #' @importFrom dplyr group_by summarize groups
- #' @importFrom stringr str_split
- #'
- #' @return Return an updated CellChat object:
- #'
- #' `object@net$count` is a matrix: rows and columns are sources and targets respectively, and elements are the number of interactions between any two cell groups. USER can convert a matrix to a data frame using the function `reshape2::melt()`
- #'
- #' `object@net$weight` is also a matrix containing the interaction weights between any two cell groups
- #'
- #' `object@net$sum` is deprecated. Use `object@net$weight`
- #'
- #' @export
- #'
- aggregateNet <- function(object, sources.use = NULL, targets.use = NULL, signaling = NULL, pairLR.use = NULL, remove.isolate = TRUE, thresh = 0.05, return.object = TRUE) {
- net <- object@net
- if (is.null(sources.use) & is.null(targets.use) & is.null(signaling) & is.null(pairLR.use)) {
- prob <- net$prob
- pval <- net$pval
- pval[prob == 0] <- 1
- prob[pval >= thresh] <- 0
- net$count <- apply(prob > 0, c(1,2), sum)
- net$weight <- apply(prob, c(1,2), sum)
- net$weight[is.na(net$weight)] <- 0
- net$count[is.na(net$count)] <- 0
- } else {
- df.net <- subsetCommunication(object, slot.name = "net",
- sources.use = sources.use, targets.use = targets.use,
- signaling = signaling,
- pairLR.use = pairLR.use,
- thresh = thresh)
- df.net$source_target <- paste(df.net$source, df.net$target, sep = "|")
- df.net2 <- df.net %>% group_by(source_target) %>% summarize(count = n(), .groups = 'drop')
- df.net3 <- df.net %>% group_by(source_target) %>% summarize(prob = sum(prob), .groups = 'drop')
- df.net2$prob <- df.net3$prob
- a <- stringr::str_split(df.net2$source_target, "|", simplify = T)
- df.net2$source <- as.character(a[, 1])
- df.net2$target <- as.character(a[, 2])
- cells.level <- levels(object@idents)
- if (remove.isolate) {
- message("Isolate cell groups without any interactions are removed. To block it, set `remove.isolate = FALSE`")
- df.net2$source <- factor(df.net2$source, levels = cells.level[cells.level %in% unique(df.net2$source)])
- df.net2$target <- factor(df.net2$target, levels = cells.level[cells.level %in% unique(df.net2$target)])
- } else {
- df.net2$source <- factor(df.net2$source, levels = cells.level)
- df.net2$target <- factor(df.net2$target, levels = cells.level)
- }
- count <- tapply(df.net2[["count"]], list(df.net2[["source"]], df.net2[["target"]]), sum)
- prob <- tapply(df.net2[["prob"]], list(df.net2[["source"]], df.net2[["target"]]), sum)
- net$count <- count
- net$weight <- prob
- net$weight[is.na(net$weight)] <- 0
- net$count[is.na(net$count)] <- 0
- }
- if (return.object) {
- object@net <- net
- return(object)
- } else {
- return(net)
- }
- }
- #' Compute averaged expression values for each cell group
- #'
- #' @param object CellChat object
- #' @param features a char vector giving the used features. default use all features
- #' @param group.by cell group information; default is `object@idents` when input is a single object and `object@idents$joint` when input is a merged object; otherwise it should be one of the column names of the meta slot
- #' @param type methods for computing the average gene expression per cell group.
- #'
- #' By default = "triMean", defined as a weighted average of the distribution's median and its two quartiles (https://en.wikipedia.org/wiki/Trimean);
- #'
- #' When setting `type = "truncatedMean"`, a value should be assigned to 'trim'. See the function `base::mean`.
- #'
- #' @param trim the fraction (0 to 0.25) of observations to be trimmed from each end of x before the mean is computed.
- #' @param slot.name the data in the slot.name to use
- #' @param data.use a customed data matrix. Default: data.use = NULL and the expression matrix in the 'slot.name' is used
- #'
- #' @return Returns a matrix with genes as rows, cell groups as columns.
- #' @export
- #'
- computeAveExpr <- function(object, features = NULL, group.by = NULL, type = c("triMean", "truncatedMean", "median"), trim = NULL,
- slot.name = c("data.signaling", "data"), data.use = NULL) {
- type <- match.arg(type)
- slot.name <- match.arg(slot.name)
- FunMean <- switch(type,
- triMean = triMean,
- truncatedMean = function(x) mean(x, trim = trim, na.rm = TRUE),
- median = function(x) median(x, na.rm = TRUE))
- if (is.null(data.use)) {
- data.use <- slot(object, slot.name)
- }
- if (is.null(features)) {
- features.use <- row.names(data.use)
- } else {
- features.use <- intersect(features, row.names(data.use))
- }
- data.use <- data.use[features.use, , drop = FALSE]
- data.use <- as.matrix(data.use)
- if (is.null(group.by)) {
- labels <- object@idents
- if (!is.factor(labels)) {
- message("Use the joint cell labels from the merged CellChat object")
- labels <- object@idents$joint
- }
- } else {
- labels <- object@meta[[group.by]]
- }
- if (!is.factor(labels)) {
- labels <- factor(labels)
- }
- # compute the average expression per group
- data.use.avg <- aggregate(t(data.use), list(labels), FUN = FunMean)
- data.use.avg <- t(data.use.avg[,-1])
- rownames(data.use.avg) <- features.use
- colnames(data.use.avg) <- levels(labels)
- return(data.use.avg)
- }
- #' Compute the expression of complex in individual cells using geometric mean
- #' @param complex_input the complex_input from CellChatDB
- #' @param data.use data matrix (row are genes and columns are cells or cell groups)
- #' @param complex the names of complex
- #' @return
- #' @importFrom dplyr select starts_with
- #' @importFrom future nbrOfWorkers
- #' @importFrom future.apply future_sapply
- #' @importFrom pbapply pbsapply
- #' @export
- computeExpr_complex <- function(complex_input, data.use, complex) {
- Rsubunits <- complex_input[complex,] %>% dplyr::select(starts_with("subunit"))
- my.sapply <- ifelse(
- test = future::nbrOfWorkers() == 1,
- yes = sapply,
- no = future.apply::future_sapply
- )
- data.complex = my.sapply(
- X = 1:nrow(Rsubunits),
- FUN = function(x) {
- RsubunitsV <- unlist(Rsubunits[x,], use.names = F)
- RsubunitsV <- RsubunitsV[RsubunitsV != ""]
- return(geometricMean(data.use[RsubunitsV, , drop = FALSE]))
- }
- )
- data.complex <- t(data.complex)
- return(data.complex)
- }
- # Compute the average expression of complex per cell group using geometric mean
- # @param complex_input the complex_input from CellChatDB
- # @param data.use data matrix (rows are genes and columns are cells)
- # @param complex the names of complex
- # @param group a factor defining the cell groups
- # @param FunMean the function for computing mean expression per group
- # @return
- # @importFrom dplyr select starts_with
- # @importFrom future nbrOfWorkers
- # @importFrom future.apply future_sapply
- # @importFrom pbapply pbsapply
- # #' @export
- .computeExprGroup_complex <- function(complex_input, data.use, complex, group, FunMean) {
- Rsubunits <- complex_input[complex,] %>% dplyr::select(starts_with("subunit"))
- my.sapply <- ifelse(
- test = future::nbrOfWorkers() == 1,
- yes = pbapply::pbsapply,
- no = future.apply::future_sapply
- )
- data.complex = my.sapply(
- X = 1:nrow(Rsubunits),
- FUN = function(x) {
- RsubunitsV <- unlist(Rsubunits[x,], use.names = F)
- RsubunitsV <- RsubunitsV[RsubunitsV != ""]
- RsubunitsV <- intersect(RsubunitsV, rownames(data.use))
- if (length(RsubunitsV) > 1) {
- data.avg <- aggregate(t(data.use[RsubunitsV, ,drop = FALSE]), list(group), FUN = FunMean)
- data.avg <- t(data.avg[,-1])
- } else if (length(RsubunitsV) == 1) {
- data.avg <- aggregate(matrix(data.use[RsubunitsV,], ncol = 1), list(group), FUN = FunMean)
- data.avg <- t(data.avg[,-1])
- } else {
- data.avg = matrix(0, nrow = 1, ncol = length(unique(group)))
- }
- return(geometricMean(data.avg))
- }
- )
- data.complex <- t(data.complex)
- return(data.complex)
- }
- #' Compute the expression of ligands or receptors using geometric mean
- #' @param geneLR a char vector giving a set of ligands or receptors
- #' @param data.use data matrix (row are genes and columns are cells or cell groups)
- #' @param complex_input the complex_input from CellChatDB
- # #' @param group a factor defining the cell groups; If NULL, compute the expression of ligands or receptors in individual cells; otherwise, compute the average expression of ligands or receptors per cell group
- # #' @param FunMean the function for computing average expression per cell group
- #' @return
- #' @export
- computeExpr_LR <- function(geneLR, data.use, complex_input){
- nLR <- length(geneLR)
- numCluster <- ncol(data.use)
- index.singleL <- which(geneLR %in% rownames(data.use))
- dataL1avg <- data.use[geneLR[index.singleL],]
- dataLavg <- matrix(nrow = nLR, ncol = numCluster)
- dataLavg[index.singleL,] <- dataL1avg
- index.complexL <- setdiff(1:nLR, index.singleL)
- if (length(index.complexL) > 0) {
- complex <- geneLR[index.complexL]
- data.complex <- computeExpr_complex(complex_input, data.use, complex)
- dataLavg[index.complexL,] <- data.complex
- }
- return(dataLavg)
- }
- #' Modeling the effect of coreceptor on the ligand-receptor interaction
- #'
- #' @param data.use data matrix
- #' @param cofactor_input the cofactor_input from CellChatDB
- #' @param pairLRsig a data frame giving ligand-receptor interactions
- #' @param type when type == "A", computing expression of co-activation receptor; when type == "I", computing expression of co-inhibition receptor.
- #' @return
- #' @importFrom future nbrOfWorkers
- #' @importFrom future.apply future_sapply
- #' @importFrom pbapply pbsapply
- #' @export
- computeExpr_coreceptor <- function(cofactor_input, data.use, pairLRsig, type = c("A", "I")) {
- type <- match.arg(type)
- if (type == "A") {
- coreceptor.all = pairLRsig$co_A_receptor
- } else if (type == "I"){
- coreceptor.all = pairLRsig$co_I_receptor
- }
- index.coreceptor <- which(!is.na(coreceptor.all) & coreceptor.all != "")
- if (length(index.coreceptor) > 0) {
- my.sapply <- ifelse(
- test = future::nbrOfWorkers() == 1,
- yes = sapply,
- no = future.apply::future_sapply
- )
- coreceptor <- coreceptor.all[index.coreceptor]
- coreceptor.ind <- cofactor_input[coreceptor, grepl("cofactor" , colnames(cofactor_input) )]
- data.coreceptor.ind = my.sapply(
- X = 1:nrow(coreceptor.ind),
- FUN = function(x) {
- coreceptor.indV <- unlist(coreceptor.ind[x,], use.names = F)
- coreceptor.indV <- coreceptor.indV[coreceptor.indV != ""]
- coreceptor.indV <- intersect(coreceptor.indV, rownames(data.use))
- if (length(coreceptor.indV) == 1) {
- return(1 + data.use[coreceptor.indV, ])
- } else if (length(coreceptor.indV) > 1) {
- return(apply(1 + data.use[coreceptor.indV, ], 2, prod))
- } else {
- return(matrix(1, nrow = 1, ncol = ncol(data.use)))
- }
- }
- )
- data.coreceptor.ind <- t(data.coreceptor.ind)
- data.coreceptor <- matrix(1, nrow = length(coreceptor.all), ncol = ncol(data.use))
- data.coreceptor[index.coreceptor,] <- data.coreceptor.ind
- } else {
- data.coreceptor <- matrix(1, nrow = length(coreceptor.all), ncol = ncol(data.use))
- }
- return(data.coreceptor)
- }
- # Modeling the effect of coreceptor on the ligand-receptor interaction
- #
- # @param data.use data matrix
- # @param cofactor_input the cofactor_input from CellChatDB
- # @param pairLRsig a data frame giving ligand-receptor interactions
- # @param type when type == "A", computing expression of co-activation receptor; when type == "I", computing expression of co-inhibition receptor.
- # @param group a factor defining the cell groups
- # @param FunMean the function for computing mean expression per group
- # @return
- # @importFrom future nbrOfWorkers
- # @importFrom future.apply future_sapply
- # @importFrom pbapply pbsapply
- # #' @export
- .computeExprGroup_coreceptor <- function(cofactor_input, data.use, pairLRsig, type = c("A", "I"), group, FunMean) {
- type <- match.arg(type)
- if (type == "A") {
- coreceptor.all = pairLRsig$co_A_receptor
- } else if (type == "I"){
- coreceptor.all = pairLRsig$co_I_receptor
- }
- index.coreceptor <- which(!is.na(coreceptor.all) & coreceptor.all != "")
- if (length(index.coreceptor) > 0) {
- my.sapply <- ifelse(
- test = future::nbrOfWorkers() == 1,
- yes = pbapply::pbsapply,
- no = future.apply::future_sapply
- )
- coreceptor <- coreceptor.all[index.coreceptor]
- coreceptor.ind <- cofactor_input[coreceptor, grepl("cofactor" , colnames(cofactor_input) )]
- data.coreceptor.ind = my.sapply(
- X = 1:nrow(coreceptor.ind),
- FUN = function(x) {
- coreceptor.indV <- unlist(coreceptor.ind[x,], use.names = F)
- coreceptor.indV <- coreceptor.indV[coreceptor.indV != ""]
- coreceptor.indV <- intersect(coreceptor.indV, rownames(data.use))
- if (length(coreceptor.indV) > 1) {
- data.avg <- aggregate(t(data.use[coreceptor.indV,]), list(group), FUN = FunMean)
- data.avg <- t(data.avg[,-1])
- return(apply(1 + data.avg, 2, prod))
- # return(1 + apply(data.avg, 2, mean))
- } else if (length(coreceptor.indV) == 1) {
- data.avg <- aggregate(matrix(data.use[coreceptor.indV,], ncol = 1), list(group), FUN = FunMean)
- data.avg <- t(data.avg[,-1])
- return(1 + data.avg)
- } else {
- return(matrix(1, nrow = 1, ncol = length(unique(group))))
- }
- }
- )
- data.coreceptor.ind <- t(data.coreceptor.ind)
- data.coreceptor <- matrix(1, nrow = length(coreceptor.all), ncol = length(unique(group)))
- data.coreceptor[index.coreceptor,] <- data.coreceptor.ind
- } else {
- data.coreceptor <- matrix(1, nrow = length(coreceptor.all), ncol = length(unique(group)))
- }
- return(data.coreceptor)
- }
- #' Modeling the effect of agonist on the ligand-receptor interaction
- #' @param data.use data matrix
- #' @param cofactor_input the cofactor_input from CellChatDB
- #' @param pairLRsig the L-R interactions
- #' @param group a factor defining the cell groups
- #' @param index.agonist the index of agonist in the database
- #' @param Kh a parameter in Hill function
- #' @param FunMean the function for computing mean expression per group
- #' @param n Hill coefficient
- #' @return
- #' @export
- #' @importFrom stats aggregate
- computeExprGroup_agonist <- function(data.use, pairLRsig, cofactor_input, group, index.agonist, Kh, FunMean, n) {
- agonist <- pairLRsig$agonist[index.agonist]
- agonist.ind <- cofactor_input[agonist, grepl("cofactor" , colnames(cofactor_input))]
- agonist.indV <- unlist(agonist.ind, use.names = F)
- agonist.indV <- agonist.indV[agonist.indV != ""]
- agonist.indV <- intersect(agonist.indV, rownames(data.use))
- if (length(agonist.indV) == 1) {
- data.avg <- aggregate(matrix(data.use[agonist.indV,], ncol = 1), list(group), FUN = FunMean)
- data.avg <- t(data.avg[,-1])
- data.agonist <- 1 + data.avg^n/(Kh^n + data.avg^n)
- } else if (length(agonist.indV) > 1) {
- data.avg <- aggregate(t(data.use[agonist.indV,]), list(group), FUN = FunMean)
- data.avg <- t(data.avg[,-1])
- data.agonist <- apply(1 + data.avg^n/(Kh^n + data.avg^n), 2, prod)
- } else {
- data.agonist = matrix(1, nrow = 1, ncol = length(unique(group)))
- }
- return(data.agonist)
- }
- #' Modeling the effect of antagonist on the ligand-receptor interaction
- #'
- #' @param data.use data matrix
- #' @param cofactor_input the cofactor_input from CellChatDB
- #' @param pairLRsig the L-R interactions
- #' @param group a factor defining the cell groups
- #' @param index.antagonist the index of antagonist in the database
- #' @param Kh a parameter in Hill function
- #' @param n Hill coefficient
- #' @param FunMean the function for computing mean expression per group
- #' @return
- #' @export
- #' @importFrom stats aggregate
- computeExprGroup_antagonist <- function(data.use, pairLRsig, cofactor_input, group, index.antagonist, Kh, FunMean, n) {
- antagonist <- pairLRsig$antagonist[index.antagonist]
- antagonist.ind <- cofactor_input[antagonist, grepl( "cofactor" , colnames(cofactor_input) )]
- antagonist.indV <- unlist(antagonist.ind, use.names = F)
- antagonist.indV <- antagonist.indV[antagonist.indV != ""]
- antagonist.indV <- intersect(antagonist.indV, rownames(data.use))
- if (length(antagonist.indV) == 1) {
- data.avg <- aggregate(matrix(data.use[antagonist.indV,], ncol = 1), list(group), FUN = FunMean)
- data.avg <- t(data.avg[,-1])
- data.antagonist <- Kh^n/(Kh^n + data.avg^n)
- } else if (length(antagonist.indV) > 1) {
- data.avg <- aggregate(t(data.use[antagonist.indV,]), list(group), FUN = FunMean)
- data.avg <- t(data.avg[,-1])
- data.antagonist <- apply(Kh^n/(Kh^n + data.avg^n), 2, prod)
- } else {
- data.antagonist = matrix(1, nrow = 1, ncol = length(unique(group)))
- }
- return(data.antagonist)
- }
- #' Modeling the effect of agonist on the ligand-receptor interaction
- #' @param data.use data matrix
- #' @param cofactor_input the cofactor_input from CellChatDB
- #' @param pairLRsig the L-R interactions
- # #' @param group a factor defining the cell groups
- #' @param index.agonist the index of agonist in the database
- #' @param Kh a parameter in Hill function
- # #' @param FunMean the function for computing mean expression per group
- #' @param n Hill coefficient
- #' @return
- #' @export
- #' @importFrom stats aggregate
- computeExpr_agonist <- function(data.use, pairLRsig, cofactor_input, index.agonist, Kh, n) {
- agonist <- pairLRsig$agonist[index.agonist]
- agonist.ind <- cofactor_input[agonist, grepl("cofactor" , colnames(cofactor_input))]
- agonist.indV <- unlist(agonist.ind, use.names = F)
- agonist.indV <- agonist.indV[agonist.indV != ""]
- agonist.indV <- intersect(agonist.indV, rownames(data.use))
- if (length(agonist.indV) == 1) {
- # data.avg <- aggregate(matrix(data.use[agonist.indV,], ncol = 1), list(group), FUN = FunMean)
- # data.avg <- t(data.avg[,-1])
- data.avg <- data.use[agonist.indV,, drop = FALSE]
- data.agonist <- 1 + data.avg^n/(Kh^n + data.avg^n)
- } else if (length(agonist.indV) > 1) {
- # data.avg <- aggregate(t(data.use[agonist.indV,]), list(group), FUN = FunMean)
- # data.avg <- t(data.avg[,-1])
- data.avg <- data.use[agonist.indV,, drop = FALSE]
- data.agonist <- apply(1 + data.avg^n/(Kh^n + data.avg^n), 2, prod)
- } else {
- # data.agonist = matrix(1, nrow = 1, ncol = length(unique(group)))
- data.agonist = matrix(1, nrow = 1, ncol = ncol(data.use))
- }
- return(data.agonist)
- }
- #' Modeling the effect of antagonist on the ligand-receptor interaction
- #'
- #' @param data.use data matrix
- #' @param cofactor_input the cofactor_input from CellChatDB
- #' @param pairLRsig the L-R interactions
- # #' @param group a factor defining the cell groups
- #' @param index.antagonist the index of antagonist in the database
- #' @param Kh a parameter in Hill function
- #' @param n Hill coefficient
- # #' @param FunMean the function for computing mean expression per group
- #' @return
- #' @export
- #' @importFrom stats aggregate
- computeExpr_antagonist <- function(data.use, pairLRsig, cofactor_input, index.antagonist, Kh, n) {
- antagonist <- pairLRsig$antagonist[index.antagonist]
- antagonist.ind <- cofactor_input[antagonist, grepl( "cofactor" , colnames(cofactor_input) )]
- antagonist.indV <- unlist(antagonist.ind, use.names = F)
- antagonist.indV <- antagonist.indV[antagonist.indV != ""]
- antagonist.indV <- intersect(antagonist.indV, rownames(data.use))
- if (length(antagonist.indV) == 1) {
- # data.avg <- aggregate(matrix(data.use[antagonist.indV,], ncol = 1), list(group), FUN = FunMean)
- # data.avg <- t(data.avg[,-1])
- data.avg <- data.use[antagonist.indV,, drop = FALSE]
- data.antagonist <- Kh^n/(Kh^n + data.avg^n)
- } else if (length(antagonist.indV) > 1) {
- # data.avg <- aggregate(t(data.use[antagonist.indV,]), list(group), FUN = FunMean)
- # data.avg <- t(data.avg[,-1])
- data.avg <- data.use[antagonist.indV,, drop = FALSE]
- data.antagonist <- apply(Kh^n/(Kh^n + data.avg^n), 2, prod)
- } else {
- # data.antagonist = matrix(1, nrow = 1, ncol = length(unique(group)))
- data.antagonist = matrix(1, nrow = 1, ncol = ncol(data.use))
- }
- return(data.antagonist)
- }
- #' Compute the geometric mean
- #' @param x a numeric vector
- #' @param na.rm whether remove na
- #' @return
- #' @export
- geometricMean <- function(x,na.rm=TRUE){
- if (is.null(nrow(x))) {
- exp(mean(log(x),na.rm=na.rm))
- } else {
- exp(apply(log(x),2,mean,na.rm=na.rm))
- }
- }
- #' Compute the Tukey's trimean
- #' @param x a numeric vector
- #' @param na.rm whether remove na
- #' @return
- #' @importFrom collapse fquantile
- #' @export
- triMean <- function(x, na.rm = TRUE) {
- mean(collapse::fquantile(x, probs = c(0.25, 0.50, 0.50, 0.75), na.rm = na.rm))
- }
- #' Compute the average expression per cell group when the percent of expressing cells per cell group larger than a threshold
- #' @param x a numeric vector
- #' @param trim the percent of expressing cells per cell group to be considered as zero
- #' @param na.rm whether remove na
- #' @return
- #' @importFrom Matrix nnzero
- # #' @export
- thresholdedMean <- function(x, trim = 0.1, na.rm = TRUE) {
- percent <- Matrix::nnzero(x)/length(x)
- if (percent < trim) {
- return(0)
- } else {
- return(mean(x, na.rm = na.rm))
- }
- }
- #' Filter cell-cell communication if there are only few number of cells in certain cell groups or inconsistent cell-cell communication across samples
- #'
- #' @param object CellChat object
- #' @param min.cells The minmum number of cells required in each cell group for cell-cell communication
- #' @param min.samples The minmum number of samples required for consistent cell-cell communication across samples (that is an interaction present in at least `min.samples` samples) when mutiple samples/replicates/batches are merged as an input for CellChat analysis.
- #' @param rare.keep Whether to keep the interactions associated with the rare populations when min.samples >= 2. When a rare population is identified in the merged samples (say 15 cells in this rare population from two samples), it is likely to filter out the interactions associated with this rare population when setting min.samples >= 2. Setting `rare.keep = TRUE` to retain the identified interactions associated with this rare population.
- #' @param nonFilter.keep Whether to keep the non-filtered cell-cell communication in the CellChat object. This is useful for avoiding re-running `computeCommunProb` if you want to adjust the parameters when running `filterCommunication`.
- #' @return CellChat object with an updated slot net
- #' @export
- #'
- filterCommunication <- function(object, min.cells = 10, min.samples = NULL, rare.keep = FALSE, nonFilter.keep = FALSE) {
- net <- object@net
- if (nonFilter.keep == TRUE) {
- cat("The non-filtered cell-cell communication is stored in `object@net$prob.nonFilter` and `object@net$pval.nonFilter`. \n")
- object@net$prob.nonFilter <- net$prob
- object@net$pval.nonFilter <- net$pval
- }
- num.interaction0 <- sum(net$prob > 0)
- cell.excludes <- which(as.numeric(table(object@idents)) <= min.cells)
- if (length(cell.excludes) > 0) {
- cat("The cell-cell communication related with the following cell groups are excluded due to the few number of cells: ", toString(levels(object@idents)[cell.excludes]), "!",'\t')
- net$prob[cell.excludes,,] <- 0
- net$prob[,cell.excludes,] <- 0
- num.interaction1 <- sum(net$prob > 0)
- pct.dicrease <- scales::percent((num.interaction0-num.interaction1)/num.interaction0, accuracy = .1)
- cat(paste0(pct.dicrease, " interactions are removed!",'\n'))
- } else {
- num.interaction1 <- num.interaction0
- }
- sample.info <- object@meta$samples
- sample.id <- levels(sample.info)
- if (is.null(min.samples)) {
- min.samples <- 1
- } else if (min.samples > length(sample.id)) {
- stop(paste0("There are only ", length(sample.id), " samples in the data. Please change the value of `min.samples`! "))
- }
- if (length(sample.id) >= 2 & min.samples >= 2) {
- if (object@options$parameter$raw.use == TRUE) {
- data <- as.matrix([email hidden])
- } else {
- if ("data.smooth" %in% methods::slotNames(object) == FALSE) {
- stop("`[email hidden]` is missing. Please update the CellChat object via `updateCellChat`! \n")
- }
- data <- as.matrix([email hidden])
- }
- data.use <- data/max(data)
- group <- object@idents
- type <- object@options$parameter$type.mean
- trim <- object@options$parameter$trim
- FunMean <- switch(type,
- triMean = triMean,
- truncatedMean = function(x) mean(x, trim = trim, na.rm = TRUE),
- thresholdedMean = function(x) thresholdedMean(x, trim = trim, na.rm = TRUE),
- median = function(x) median(x, na.rm = TRUE))
- LR <- dimnames(net$prob)[[3]]
- idx.nonzero <- which(apply(net$prob, 3, sum) != 0)
- LR.nonzero <- LR[idx.nonzero] # only examine the L-R pairs with nonzero communication probabilities.
- interaction_input <- object@DB$interaction
- complex_input <- object@DB$complex
- geneIfo <- object@DB$geneInfo
- idx <- match(LR.nonzero, interaction_input$interaction_name)
- geneL <- as.character(interaction_input$ligand[idx])
- geneR <- as.character(interaction_input$receptor[idx])
- geneLR <- c(unique(geneL), unique(geneR))
- geneLR <- extractGeneSubset(geneLR, complex_input, geneIfo)
- data.use <- data.use[rownames(data.use) %in% geneLR, ]
- score.LR <- array(0, dim = c(nlevels(group),nlevels(group),length(LR.nonzero), length(sample.id)))
- LR.nonzero.all <- c()
- cell.excludes.sample <- c()
- for (i in 1:length(sample.id)) {
- cell.use <- which(sample.info == sample.id[i])
- group.use <- group[cell.use]
- group.use <- droplevels(group.use)
- # get the rare populations with few cells in each sample
- cell.excludes.sample.i <- which(as.numeric(table(object@idents[cell.use])) <= min.cells)
- cell.excludes.sample <- c(cell.excludes.sample, cell.excludes.sample.i)
- # compute average expression per cell group
- data.use.i <- data.use[, cell.use]
- data.use.avg <- aggregate(t(data.use.i), list(group.use), FUN = FunMean)
- data.use.avg <- t(data.use.avg[,-1])
- group.exist <- which(levels(group) %in% unique(group.use))
- if (length(group.exist) < nlevels(group)) {
- data.use.avg.temp <- matrix(0, nrow = nrow(data.use), ncol = nlevels(group))
- data.use.avg.temp[ , group.exist] <- data.use.avg
- rownames(data.use.avg.temp) <- rownames(data.use.avg)
- data.use.avg <- data.use.avg.temp
- }
- colnames(data.use.avg) <- levels(group)
- # compute the average expression of ligand or receptor in each cell group
- dataLavg <- computeExpr_LR(geneL, data.use.avg, complex_input)
- dataRavg <- computeExpr_LR(geneR, data.use.avg, complex_input)
- # compute the interaction scores for each ligand-receptor pair based on their expression
- for (jj in 1:length(LR.nonzero)) { # It is not good to use parallel here because it will change the order of LR
- score.LR[,,jj,i] <- Matrix::crossprod(matrix(dataLavg[jj, ], nrow = 1), matrix(dataRavg[jj, ], nrow = 1))
- }
- if (length(cell.excludes.sample.i) > 0) {
- cat(paste0("The number of cells of the following cell groups in ", sample.id[i], " sample are less than ", min.cells, " cells: ",toString(levels(object@idents)[cell.excludes.sample.i]), "!",'\n'))
- score.LR[cell.excludes.sample.i, , , i] <- 0
- score.LR[ ,cell.excludes.sample.i, , i] <- 0
- }
- #LR.nonzero.all <- c(LR.nonzero.all, LR.nonzero[apply(score.LR[ , , , i], 3, sum) != 0])
- }
- #LR.nonzero.jointOnly <- setdiff(LR.nonzero, unique(LR.nonzero.all))
- # get the excluded cell groups that are not observed in the merged data, which is very possible for rare populations
- cell.excludes.sample <- unique(cell.excludes.sample)
- if (length(cell.excludes.sample) > 0) {
- cell.excludes.sample <- setdiff(cell.excludes.sample, cell.excludes)
- }
- score.LR[score.LR > 0] <- 1 # binarize the interaction score
- score.LR.consitent <- array(0, dim = c(nlevels(group),nlevels(group),length(LR.nonzero)))
- LR.inconsitent <- c()
- for (jj in 1:length(LR.nonzero)) {
- score.LR.sum <- apply(score.LR[ , , jj, ], c(1,2), sum) # elements 2 and 1 means consistent and inconsistent interactions across samples, respectively.
- # set communication probability to be zero for inconsistent interactions across samples
- if (sum((score.LR.sum > 0) * (score.LR.sum < min.samples)) > 0) {
- #LR.inconsitent <- c(LR.inconsitent, LR.nonzero[jj])
- score.LR.consitent <- (score.LR.sum >= min.samples) * 1
- if (rare.keep == TRUE & length(cell.excludes.sample) > 0) {
- score.LR.consitent[cell.excludes.sample, ] <- 1
- score.LR.consitent[ ,cell.excludes.sample] <- 1
- }
- net$prob[ , , LR.nonzero[jj]] <- net$prob[ , , LR.nonzero[jj]] * score.LR.consitent
- }
- }
- num.interaction2 <- sum(net$prob > 0)
- pct.dicrease <- scales::percent((num.interaction1-num.interaction2)/num.interaction1, accuracy = .1)
- cat(paste0(pct.dicrease, " interactions are removed due to their inconsistence across ", min.samples, " samples!",'\n'))
- }
- object@net <- net
- return(object)
- }
- #' Identify all the significant interactions (L-R pairs) from some cell groups to other cell groups
- #'
- #' @param object CellChat object
- #' @param from a vector giving the index or the name of source cell groups
- #' @param to a corresponding vector giving the index or the name of target cell groups. Note: The length of 'from' and 'to' must be the same, giving the corresponding pair of cell groups for communication.
- #' @param bidirection whether show the bidirectional communication, i.e., both 'from'->'to' and 'to'->'from'.
- #' @param pair.only whether only return ligand-receptor pairs without pathway names and communication strength
- #' @param pairLR.use0 ligand-receptor pairs to use; default is all the significant interactions
- #' @param thresh threshold of the p-value for determining significant interaction
- #'
- #' @return
- #' @export
- #'
- identifyEnrichedInteractions <- function(object, from, to, bidirection = FALSE, pair.only = TRUE, pairLR.use0 = NULL, thresh = 0.05){
- pairwiseLR <- object@net$pairwiseRank
- if (is.null(pairwiseLR)) {
- stop("The interactions between pairwise cell groups have not been extracted!
- Please first run `object <- rankNetPairwise(object)`")
- }
- group.names.all <- names(pairwiseLR)
- if (!is.numeric(from)) {
- from <- match(from, group.names.all)
- if (sum(is.na(from)) > 0) {
- message("Some input cell group names in 'from' do not exist!")
- from <- from[!is.na(from)]
- }
- }
- if (!is.numeric(to)) {
- to <- match(to, group.names.all)
- if (sum(is.na(to)) > 0) {
- message("Some input cell group names in 'to' do not exist!")
- to <- to[!is.na(to)]
- }
- }
- if (length(from) != length(to)) {
- stop("The length of 'from' and 'to' must be the same!")
- }
- if (bidirection) {
- from2 <- c(from, to)
- to <- c(to, from)
- from <- from2
- }
- if (is.null(pairLR.use0)) {
- k <- 0
- pairLR.use0 <- list()
- for (i in 1:length(from)){
- pairwiseLR_ij <- pairwiseLR[[from[i]]][[to[i]]]
- idx <- pairwiseLR_ij$pval < thresh
- if (length(idx) > 0) {
- k <- k +1
- pairLR.use0[[k]] <- pairwiseLR_ij[idx,]
- }
- }
- pairLR.use0 <- do.call(rbind, pairLR.use0)
- }
- k <- 0
- pval <- matrix(nrow = length(rownames(pairLR.use0)), ncol = length(from))
- prob <- pval
- group.names <- c()
- for (i in 1:length(from)) {
- k <- k+1
- pairwiseLR_ij <- pairwiseLR[[from[i]]][[to[i]]]
- pairwiseLR_ij <- pairwiseLR_ij[rownames(pairLR.use0),]
- pval_ij <- pairwiseLR_ij$pval
- prob_ij <- pairwiseLR_ij$prob
- pval_ij[pval_ij > 0.05] = 1
- pval_ij[pval_ij > 0.01 & pval_ij <= 0.05] = 2
- pval_ij[pval_ij <= 0.01] = 3
- prob_ij[pval_ij ==1] <- 0
- pval[,k] <- pval_ij
- prob[,k] <- prob_ij
- group.names <- c(group.names, paste(group.names.all[from[i]], group.names.all[to[i]], sep = " - "))
- }
- prob[which(prob == 0)] <- NA
- # remove rows that are entirely NA
- pval <- pval[rowSums(is.na(prob)) != ncol(prob), ,drop = FALSE]
- pairLR.use0 <- pairLR.use0[rowSums(is.na(prob)) != ncol(prob), ,drop = FALSE]
- prob <- prob[rowSums(is.na(prob)) != ncol(prob), ,drop = FALSE]
- if (pair.only) {
- pairLR.use0 <- dplyr::select(pairLR.use0, ligand, receptor)
- }
- return(pairLR.use0)
- }
- #' Compute the region distance based on the spatial locations of each splot/cell of the spatial transcriptomics
- #'
- #' @param coordinates a data matrix in which each row gives the spatial locations/coordinates of each cell/spot
- #' @param meta a data frame including at least two columns named `group` and `samples`. `meta$group` is a factor vector defining the regions/labels of each cell/spot. `meta$samples` is a factor vector defining the sample labels of each dataset.
- #' @param interaction.range The maximum interaction/diffusion range of ligands. This hard threshold is used to filter out the connections between spatially distant regions
- #' @param ratio a numerical vector giving the conversion factor when converting spatial coordinates from Pixels or other units to Micrometers (i.e.,Microns).
- #'
- #' For example, setting `ratio = 0.18` indicates that 1 pixel equals 0.18um in the coordinates.
- #' For 10X visium, it is the ratio of the theoretical spot size (i.e., 65um) over the number of pixels that span the diameter of a theoretical spot size in the full-resolution image (i.e., 'spot.size.fullres' in the 'scalefactors_json.json' file).
- #' @param tol a numerical vector giving the tolerance factor to increase the robustness when comparing the center-to-center distance against the `interaction.range`. This can be the half value of cell/spot size in the unit of um.
- #'
- #' For example, for 10X visium, `tol` can be set as `65/2`; for slide-seq, `tol` can be set as `10/2`.
- #' If the cell/spot size is not known, we provide a function `computeCellDistance` to compute the center-to-center distance. `tol` can be the the half value of the minimum center-to-center distance.
- #' @param k.min the minimum number of interacting cell pairs required for defining adjacent cell groups
- #' @param contact.dependent Whether determining spatially proximal cell groups based on either the contact.range or the k-nearest neighbors (knn). By default `contact.dependent = TRUE` when inferring contact-dependent and juxtacrine signaling (including ECM-Receptor and Cell-Cell Contact signaling classified in CellChatDB$interaction$annotation).
- #' If only focusing on `Secreted Signaling`, the `contact.dependent` will be automatically set as FALSE except for `contact.dependent.forced = TRUE`.
- #' @param contact.range The interaction range (Unit: microns) to restrict the contact-dependent signaling.
- #' For spatial transcriptomics in a single-cell resolution, `contact.range` is approximately equal to the estimated cell diameter (i.e., the cell center-to-center distance), which means that contact-dependent and juxtacrine signaling can only happens when the two cells are contact to each other.
- #'
- #' Typically, `contact.range = 10`, which is a typical human cell size. However, for low-resolution spatial data such as 10X visium, it should be the cell center-to-center distance (i.e., `contact.range = 100` for visium data). The function `computeCellDistance` can compute the center-to-center distance.
- #'
- #' @param contact.knn.k Number of neighbors to restrict the contact-dependent signaling within the neatest neighbors. By default, CellChat uses `contact.range` to restrict the contact-dependent signaling; however, users can also provide a value of `contact.knn.k`, in order to determine spatially proximal cell groups based on the k-nearest neighbors (knn).
- #' For 10X visium, contact.knn.k = 6. For other spatial technologies, this value may be hard to determine because the sequenced cells/spots are usually not regularly arranged.
- #' @param do.symmetric Whether converting the adjacent matrix into symmetric one when determining spatially proximal cell groups. Default is TRUE, indicating that if adj(i,j) or adj(j,i) is zero, then both are zeros.
- #'
- #' @importFrom BiocNeighbors queryKNN AnnoyParam
- #' @return A list including a square matrix giving the pairwise region distances and an adjacent matrix indicating physically contacting cell groups based on either the contact.range or the k-nearest neighbors
- #'
- #' @export
- computeRegionDistance <- function(coordinates, meta,
- interaction.range = NULL, ratio = NULL, tol = NULL, k.min = 10,
- contact.dependent = TRUE, contact.range = NULL, contact.knn.k = NULL, do.symmetric = TRUE
- ) {
- trim <- 0.1
- FunMean <- function(x) mean(x, trim = trim, na.rm = TRUE) # This is used for computing the average distance between two cell groups
- group <- meta$group
- numCluster <- nlevels(group)
- level.use <- levels(group)
- level.use <- level.use[level.use %in% unique(group)]
- samples <- meta$samples
- samples.use <- levels(samples)
- d.spatial <- array(NaN, dim = c(numCluster,numCluster,length(samples.use)))
- adj.spatial <- array(0, dim = c(numCluster,numCluster,length(samples.use)))
- adj.contact <- array(0, dim = c(numCluster,numCluster,length(samples.use)))
- adj.contact.knn <- array(0, dim = c(numCluster,numCluster,length(samples.use)))
- if (contact.dependent == TRUE & !is.null(contact.knn.k)) {
- ## find the k-nearest neighbors for each single cell
- # my.knn <- FNN::get.knn(coordinates, k = contact.knn.k)
- # nn.ranked <- my.knn$nn.index # this is a matrix with the size of nCell * contact.knn.k
- nn.ranked <- matrix(NA, nrow = nrow(coordinates), ncol = contact.knn.k)
- for (k in 1:length(samples.use)) {
- idx.k <- which(samples == samples.use[k])
- my.knn <- suppressWarnings(BiocNeighbors::findKNN(coordinates[idx.k, ], k = contact.knn.k, BNPARAM = BiocNeighbors::AnnoyParam(), get.index = TRUE))
- nn.ranked[idx.k, ] <- my.knn$index # this is a matrix with the size of nCell * contact.knn.k
- }
- k.min.contact <- k.min
- } else {
- nn.ranked <- matrix(1, nrow = nrow(coordinates), ncol = 1)
- k.min.contact <- -1 # this produces adj.contact.knn with all elements being 1
- }
- if (contact.dependent == TRUE) {
- if (is.null(contact.range) & is.null(contact.knn.k)) {
- stop("Please check the documentation of `computeCommunProb` and provide the value of either `contact.range` or `contact.knn.k`")
- }
- } else {
- contact.range <- 10000 # this produces adj.contact with all elements being 1
- }
- for (k in 1:length(samples.use)) {
- idx.k <- samples == samples.use[k]
- for (i in 1:numCluster) {
- for (j in 1:numCluster) {
- idx.i <- which((group == level.use[i]) & idx.k)
- idx.j <- which((group == level.use[j]) & idx.k)
- if (length(idx.i) == 0 | length(idx.j) == 0) {
- next # if one cell group is missing in one sample, just goes to next loop
- }
- data.spatial.i <- coordinates[idx.i, , drop = FALSE]
- data.spatial.j <- coordinates[idx.j, , drop = FALSE]
- # for each point in the i-th cell group, find its 1-nearest neighbor in the j-th cell group
- #qout <- suppressWarnings(BiocNeighbors::queryKNN(data.spatial.j, data.spatial.i, k = 1, BNPARAM = BiocNeighbors::KmknnParam(), get.index = TRUE))
- qout <- suppressWarnings(BiocNeighbors::queryKNN(data.spatial.j, data.spatial.i, k = 1, BNPARAM = BiocNeighbors::AnnoyParam(), get.index = TRUE))
- # qout$index is an one column matrix with length being `length(idx.i)`, which is the index of the 1-nearest neighbor in the j-th cell group defined by `idx.j`
- # qout$distance is an one column matrix with length being `length(idx.i)`, which is the distance to the 1-nearest neighbor in the j-th cell group defined by `idx.j`
- # conver the calculated distance into the distance in micrometers
- qout$distance <- qout$distance*ratio[k]
- # long-range distance
- idx <- qout$distance - interaction.range < tol[k]
- adj.spatial[i,j,k] <- (length(unique(qout$index[idx])) >= k.min) * 1
- # short-range distance based on contact.range
- idx2 <- qout$distance - contact.range < tol[k]
- adj.contact[i,j,k] <- (length(unique(qout$index[idx2])) >= k.min) * 1
- # short-range distance based on knn
- knn.i <- unique(as.vector(nn.ranked[idx.i, ]))
- #adj.contact.knn[i,j,k] <- (length(intersect(knn.i, idx.j)) >= k.min.contact) * 1
- adj.contact.knn[i,j,k] <- (length(intersect(knn.i, unique(qout$index[idx]))) >= k.min.contact) * 1 # knn within the long-range distance
- # computing the average distance between two cell groups
- d.spatial[i,j,k] <- FunMean(qout$distance) # since distances are positive values, different ways for computing the mean have little effects.
- }
- }
- }
- # merged spatial information from different samples
- d.spatial <- apply(d.spatial, c(1,2), function(x) mean(x, na.rm = TRUE))
- adj.spatial <- apply(adj.spatial, c(1,2), mean)
- adj.contact <- apply(adj.contact, c(1,2), mean)
- adj.contact.knn <- apply(adj.contact.knn, c(1,2), mean)
- # for multi-samples analysis, the following is needed
- adj.spatial[adj.spatial > 0] <- 1
- adj.contact[adj.contact > 0] <- 1
- adj.contact.knn[adj.contact.knn > 0] <- 1
- # make these adjacent matrix as symmetric
- if (do.symmetric) {
- adj.spatial <- adj.spatial * t(adj.spatial) # if one is zero, then both are zeros.
- adj.contact <- adj.contact * t(adj.contact) # if one is zero, then both are zeros.
- adj.contact.knn <- adj.contact.knn * t(adj.contact.knn) # if one is zero, then both are zeros.
- }
- d.spatial <- (d.spatial + t(d.spatial))/2
- # filter out the spatially distant cell groups
- adj.spatial[adj.spatial == 0] <- NaN
- d.spatial <- d.spatial * adj.spatial
- rownames(d.spatial) <- levels(group); colnames(d.spatial) <- levels(group)
- if (length(contact.knn.k) > 0) {
- adj.contact = adj.contact.knn
- }
- res <- list(d.spatial = d.spatial, adj.contact = adj.contact)
- return(res)
- }
- #' Compute cell-cell distance based on the spatial coordinates
- #'
- #' @param coordinates a data matrix in which each row gives the spatial locations/coordinates of each cell/spot
- #' @param interaction.range The maximum interaction/diffusion range of ligands. This hard threshold is used to filter out the connections between spatially distant cells
- #' @param ratio The conversion factor when converting spatial coordinates from Pixels or other units to Micrometers (i.e.,Microns).
- #'
- #' For example, setting `ratio = 0.18` indicates that 1 pixel equals 0.18um in the coordinates.
- #' For 10X visium, it is the ratio of the theoretical spot size (i.e., 65um) over the number of pixels that span the diameter of a theoretical spot size in the full-resolution image (i.e., 'spot.size.fullres' in the 'scalefactors_json.json' file).
- #' @param tol The tolerance factor to increase the robustness when comparing the center-to-center distance against the `interaction.range`. This can be the half value of cell/spot size in the unit of um.
- #'
- #' For example, for 10X visium, `tol` can be set as `65/2`; for slide-seq, `tol` can be set as `10/2`.
- #' If the cell/spot size is not known, we provide a function `computeCellDistance` to compute the center-to-center distance. `tol` can be the the half value of the minimum center-to-center distance.
- #'
- #' @return an object of class "dist" giving the pairwise cell-cell distance
- #' @export
- #'
- computeCellDistance <- function(coordinates, interaction.range = NULL, ratio = NULL, tol = NULL){
- if (ncol(coordinates) == 2) {
- colnames(coordinates) <- c("x_cent","y_cent")
- } else {
- stop("Please check the input 'coordinates' and make sure it is a two column matrix.")
- }
- d.spatial <- collapse::fdist(coordinates)
- if (!is.null(ratio)) {
- d.spatial <- d.spatial*ratio
- }
- if(!is.null(interaction.range) & !is.null(tol)){
- message("\n Apply a predefined spatial distance threshold based on the interaction length...")
- d.spatial[d.spatial > (interaction.range + tol)] <- NaN
- }
- return(d.spatial)
- }
modeling.R at commit 75253cd, under GPL-3.0 · at the source
Overview
- Laboratoire de génétique moléculaire, Institut de recherches cliniques de Montréal (IRCM), 110 Avenue des Pins Ouest, Montréal, QC H2W 1R7, Canada
- Department of Neurosurgery and Department of Neuroscience, New York University Grossman School of Medicine, 435 E 30th Street, New York, NY 10016, USA
- Laboratory of Stem Cell Biology and Developmental Genetics, The Francis Crick Institute, London NW1 1AT, UK
- Centre for Endocrinology, William Harvey Research Institute, Faculty of Medicine and Dentistry, Queen Mary University of London, London, UK
Abstract
The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.
Repositories
Its files are read in the Code ↔ Paper reader above, with 6 matches between paragraphs and lines of code.
jinworks/CellChat
75253cd0c9e68410e6e721a6d3a0419a1d7e358f, 4 March 2026Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
23 files
- R/
CellChat-package.R , R, 9 lines - R/
CellChat_class.R , R, 965 lines, 2 matches - R/
RcppExports.R , R, 7 lines - R/
analysis.R , R, 3,148 lines - R/
app.R , R, 1,982 lines - R/
data.R , R, 41 lines - R/
database.R , R, 507 lines - R/
modeling.R , R, 1,297 lines, 2 matches - R/
utilities.R , R, 1,328 lines, 2 matches - R/
visualization.R , R, 3,721 lines - src/
CellChat_Rcpp.cpp , C++, 31 lines - src/
RcppExports.cpp , C++, 35 lines - tutorial/
CellChat-vignette.Rmd , R, 548 lines - tutorial/
CellChat_analysis_of_mul , R, 268 linestiple_spatial_transcript omics_datasets.Rmd - tutorial/
CellChat_analysis_of_spa , R, 258 linestial_multiomics_data.Rmd - tutorial/
CellChat_analysis_of_spa , R, 300 linestial_transcriptomics_dat a.Rmd - tutorial/
Comparison_analysis_of_m , R, 436 linesultiple_datasets.Rmd - tutorial/
Comparison_analysis_of_m , R, 128 linesultiple_datasets_with_di fferent_cellular_composi tions.Rmd - tutorial/
FAQ_on_applying_CellChat , R, 120 lines_to_spatial_transcriptom ics_data.Rmd - tutorial/
Interface_with_other_sin , R, 206 linesgle-cell_analysis_toolki ts.Rmd - tutorial/
Update-CellChatDB.Rmd , R, 251 lines - LICENSE, License, 674 lines
- README.md, Text, 137 lines
alexdobin/STAR
b1edc1208d91a53bf40ebae8669f71d50b994851, 25 January 2024Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
331 files
- extras/
scripts/ , Shell, 10 linesextractSJfromGTF.sh - extras/
scripts/ , MATLAB, 45 linessjMotif.m - source/
AlignVsTranscript.h , C/C++, 9 lines - source/
BAMbinSortByCoordinate.c , C++, 81 linespp - source/
BAMbinSortByCoordinate.h , C/C++, 12 lines - source/
BAMbinSortUnmapped.cpp , C++, 91 lines - source/
BAMbinSortUnmapped.h , C/C++, 12 lines - source/
BAMfunctions.cpp , C++, 194 lines - source/
BAMfunctions.h , C/C++, 79 lines - source/
BAMoutput.cpp , C++, 186 lines - source/
BAMoutput.h , C/C++, 37 lines - source/
Chain.cpp , C++, 126 lines - source/
Chain.h , C/C++, 30 lines - source/
ChimericAlign.cpp , C++, 32 lines - source/
ChimericAlign.h , C/C++, 41 lines - source/
ChimericAlign_chimericBA , C++, 105 linesMoutput.cpp - source/
ChimericAlign_chimericJu , C++, 23 linesnctionOutput.cpp - source/
ChimericAlign_chimericSt , C++, 181 linesitching.cpp - source/
ChimericDetection.cpp , C++, 6 lines - source/
ChimericDetection.h , C/C++, 29 lines - source/
ChimericDetection_chimer , C++, 138 linesicDetectionMult.cpp - source/
ChimericSegment.cpp , C++, 32 lines - source/
ChimericSegment.h , C/C++, 23 lines - source/
ChimericTranscript.h , C/C++, 19 lines - source/
ClipCR4.cpp , C++, 109 lines - source/
ClipCR4.h , C/C++, 41 lines - source/
ClipMate.h , C/C++, 34 lines - source/
ClipMate_clip.cpp , C++, 78 lines - source/
ClipMate_clipChunk.cpp , C++, 62 lines - source/
ClipMate_initialize.cpp , C++, 32 lines - source/
ErrorWarning.cpp , C++, 37 lines - source/
ErrorWarning.h , C/C++, 9 lines - source/
GTF.cpp , C++, 171 lines - source/
GTF.h , C/C++, 36 lines - source/
GTF_superTranscript.cpp , C++, 257 lines - source/
GTF_transcriptGeneSJ.cpp , C++, 183 lines - source/
Genome.cpp , C++, 234 lines - source/
Genome.h , C/C++, 107 lines - source/
Genome_genomeGenerate.cp , C++, 438 linesp - source/
Genome_genomeLoad.cpp , C++, 521 lines - source/
Genome_genomeOutLoad.cpp , C++, 58 lines - source/
Genome_insertSequences.c , C++, 33 linespp - source/
Genome_transformGenome.c , C++, 324 linespp - source/
GlobalVariables.cpp , C++, 4 lines - source/
GlobalVariables.h , C/C++, 9 lines - source/
InOutStreams.cpp , C++, 44 lines - source/
InOutStreams.h , C/C++, 23 lines - source/
IncludeDefine.h , C/C++, 255 lines - source/
OutSJ.cpp , C++, 123 lines - source/
OutSJ.h , C/C++, 59 lines - source/
PackedArray.cpp , C++, 43 lines - source/
PackedArray.h , C/C++, 34 lines - source/
ParameterInfo.h , C/C++, 112 lines - source/
Parameters.cpp , C++, 1,269 lines - source/
Parameters.h , C/C++, 374 lines - source/
ParametersChimeric.h , C/C++, 41 lines - source/
ParametersChimeric_initi , C++, 118 linesalize.cpp - source/
ParametersClip.h , C/C++, 37 lines - source/
ParametersClip_initializ , C++, 107 linese.cpp - source/
ParametersGenome.cpp , C++, 59 lines - source/
ParametersGenome.h , C/C++, 63 lines - source/
ParametersSolo.cpp , C++, 721 lines - source/
ParametersSolo.h , C/C++, 220 lines - source/
Parameters_closeReadsFil , C++, 12 lineses.cpp - source/
Parameters_openReadsFile , C++, 111 liness.cpp - source/
Parameters_readFilesInit , C++, 167 lines.cpp - source/
Parameters_readSAMheader , C++, 44 lines.cpp - source/
Parameters_samAttributes , C++, 263 lines.cpp - source/
Quantifications.cpp , C++, 37 lines - source/
Quantifications.h , C/C++, 22 lines - source/
ReadAlign.cpp , C++, 125 lines - source/
ReadAlign.h , C/C++, 239 lines - source/
ReadAlignChunk.cpp , C++, 170 lines - source/
ReadAlignChunk.h , C/C++, 49 lines - source/
ReadAlignChunk_mapChunk. , C++, 128 linescpp - source/
ReadAlignChunk_processCh , C++, 302 linesunks.cpp - source/
ReadAlign_CIGAR.cpp , C++, 62 lines - source/
ReadAlign_alignBAM.cpp , C++, 614 lines - source/
ReadAlign_assignAlignToW , C++, 130 linesindow.cpp - source/
ReadAlign_calcCIGAR.cpp , C++, 58 lines - source/
ReadAlign_chimericDetect , C++, 57 linesion.cpp - source/
ReadAlign_chimericDetect , C++, 312 linesionOld.cpp - source/
ReadAlign_chimericDetect , C++, 74 linesionOldOutput.cpp - source/
ReadAlign_chimericDetect , C++, 39 linesionPEmerged.cpp - source/
ReadAlign_createExtendWi , C++, 85 linesndowsWithAlign.cpp - source/
ReadAlign_mapOneRead.cpp , C++, 118 lines - source/
ReadAlign_mapOneReadSpli , C++, 40 linesceGraph.cpp - source/
ReadAlign_mappedFilter.c , C++, 21 linespp - source/
ReadAlign_maxMappableLen , C++, 115 linesgth2strands.cpp - source/
ReadAlign_multMapSelect. , C++, 95 linescpp - source/
ReadAlign_oneRead.cpp , C++, 124 lines - source/
ReadAlign_outputAlignmen , C++, 325 linests.cpp - source/
ReadAlign_outputSpliceGr , C++, 164 linesaphSAM.cpp - source/
ReadAlign_outputTranscri , C++, 65 linesptCIGARp.cpp - source/
ReadAlign_outputTranscri , C++, 359 linesptSAM.cpp - source/
ReadAlign_outputTranscri , C++, 56 linesptSJ.cpp - source/
ReadAlign_outputVariatio , C++, 13 linesn.cpp - source/
ReadAlign_peOverlapMerge , C++, 368 linesMap.cpp - source/
ReadAlign_quantTranscrip , C++, 91 linestome.cpp - source/
ReadAlign_stitchPieces.c , C++, 350 linespp - source/
ReadAlign_stitchWindowSe , C++, 278 lineseds.cpp - source/
ReadAlign_storeAligns.cp , C++, 160 linesp - source/
ReadAlign_transformGenom , C++, 74 linese.cpp - source/
ReadAlign_waspMap.cpp , C++, 128 lines - source/
ReadAnnotations.h , C/C++, 47 lines - source/
STAR.cpp , C++, 313 lines - source/
SequenceFuns.cpp , C++, 445 lines - source/
SequenceFuns.h , C/C++, 32 lines - source/
SharedMemory.cpp , C++, 291 lines - source/
SharedMemory.h , C/C++, 182 lines - source/
SimpleGoodTuring/ , C/C++, 300 linessgt.h - source/
SjdbClass.h , C/C++, 17 lines - source/
Solo.cpp , C++, 91 lines - source/
Solo.h , C/C++, 30 lines - source/
SoloBarcode.cpp , C++, 152 lines - source/
SoloBarcode.h , C/C++, 38 lines - source/
SoloBarcode_extractBarco , C++, 34 linesde.cpp - source/
SoloCommon.h , C/C++, 80 lines - source/
SoloFeature.cpp , C++, 65 lines - source/
SoloFeature.h , C/C++, 110 lines - source/
SoloFeatureTypes.h , C/C++, 12 lines - source/
SoloFeature_addBAMtags.c , C++, 26 linespp - source/
SoloFeature_cellFilterin , C++, 131 linesg.cpp - source/
SoloFeature_collapseUMI_ , C++, 172 linesGraph.cpp - source/
SoloFeature_collapseUMIa , C++, 658 linesll.cpp - source/
SoloFeature_countCBgeneU , C++, 112 linesMI.cpp - source/
SoloFeature_countSmartSe , C++, 159 linesq.cpp - source/
SoloFeature_countVelocyt , C++, 166 lineso.cpp - source/
SoloFeature_emptyDrops_C , C++, 231 linesR.cpp - source/
SoloFeature_loadRawMatri , C++, 141 linesx.cpp - source/
SoloFeature_outputResult , C++, 241 liness.cpp - source/
SoloFeature_processRecor , C++, 87 linesds.cpp - source/
SoloFeature_quantTranscr , C++, 327 linesipt.cpp - source/
SoloFeature_redistribute , C++, 80 linesReadsByCB.cpp - source/
SoloFeature_statsOutput. , C++, 123 linescpp - source/
SoloFeature_sumThreads.c , C++, 101 linespp - source/
SoloFilteredCells.h , C/C++, 33 lines - source/
SoloRead.cpp , C++, 22 lines - source/
SoloRead.h , C/C++, 23 lines - source/
SoloReadBarcode.cpp , C++, 51 lines - source/
SoloReadBarcode.h , C/C++, 46 lines - source/
SoloReadBarcodeStats.h , C/C++, 27 lines - source/
SoloReadBarcode_getCBand , C++, 429 linesUMI.cpp - source/
SoloReadFeature.cpp , C++, 63 lines - source/
SoloReadFeature.h , C/C++, 50 lines - source/
SoloReadFeatureStats.h , C/C++, 49 lines - source/
SoloReadFeature_inputRec , C++, 172 linesords.cpp - source/
SoloReadFeature_record.c , C++, 276 linespp - source/
SoloRead_record.cpp , C++, 15 lines - source/
SpliceGraph.cpp , C++, 33 lines - source/
SpliceGraph.h , C/C++, 58 lines - source/
SpliceGraph_findSuperTr. , C++, 186 linescpp - source/
SpliceGraph_swScoreSplic , C++, 249 linesed.cpp - source/
SpliceGraph_swTraceBack. , C++, 19 linescpp - source/
Stats.cpp , C++, 156 lines - source/
Stats.h , C/C++, 41 lines - source/
SuffixArrayFuns.cpp , C++, 410 lines - source/
SuffixArrayFuns.h , C/C++, 18 lines - source/
SuperTranscriptome.cpp , C++, 92 lines - source/
SuperTranscriptome.h , C/C++, 42 lines - source/
ThreadControl.cpp , C++, 7 lines - source/
ThreadControl.h , C/C++, 29 lines - source/
TimeFunctions.cpp , C++, 20 lines - source/
TimeFunctions.h , C/C++, 9 lines - source/
Transcript.cpp , C++, 59 lines - source/
Transcript.h , C/C++, 83 lines - source/
Transcript_alignScore.cp , C++, 60 linesp - source/
Transcript_convertGenome , C++, 161 linesCigar.cpp - source/
Transcript_generateCigar , C++, 63 linesP.cpp - source/
Transcript_transformGeno , C++, 167 linesme.cpp - source/
Transcript_variationAdju , C++, 74 linesst.cpp - source/
Transcript_variationOutp , C++, 6 linesut.cpp - source/
Transcriptome.cpp , C++, 190 lines - source/
Transcriptome.h , C/C++, 63 lines - source/
Transcriptome_alignExonO , C++, 278 linesverlap.cpp - source/
Transcriptome_classifyAl , C++, 267 linesign.cpp - source/
Transcriptome_geneCounts , C++, 63 linesAddAlign.cpp - source/
Transcriptome_geneFullAl , C++, 56 linesignOverlap.cpp - source/
Transcriptome_geneFullAl , C++, 43 linesignOverlap_ExonOverIntro n.cpp - source/
Transcriptome_quantAlign , C++, 114 lines.cpp - source/
Variation.cpp , C++, 157 lines - source/
Variation.h , C/C++, 53 lines - source/
bamRemoveDuplicates.cpp , C++, 271 lines - source/
bamRemoveDuplicates.h , C/C++, 10 lines - source/
bamSortByCoordinate.cpp , C++, 97 lines - source/
bamSortByCoordinate.h , C/C++, 11 lines - source/
bam_cat.c , C, 143 lines - source/
bam_cat.h , C/C++, 8 lines - source/
binarySearch2.cpp , C++, 43 lines - source/
binarySearch2.h , C/C++, 7 lines - source/
blocksOverlap.cpp , C++, 41 lines - source/
blocksOverlap.h , C/C++, 10 lines - source/
extendAlign.cpp , C++, 93 lines - source/
extendAlign.h , C/C++, 6 lines - source/
funCompareUintAndSuffixe , C++, 40 liness.cpp - source/
funCompareUintAndSuffixe , C/C++, 11 liness.h - source/
funCompareUintAndSuffixe , C++, 33 linessMemcmp.cpp - source/
funCompareUintAndSuffixe , C/C++, 10 linessMemcmp.h - source/
funPrimaryAlignMark.cpp , C++, 43 lines - source/
funPrimaryAlignMark.h , C/C++, 5 lines - source/
genomeGenerate.h , C/C++, 4 lines - source/
genomeParametersWrite.cp , C++, 45 linesp - source/
genomeParametersWrite.h , C/C++, 9 lines - source/
genomeSAindex.cpp , C++, 217 lines - source/
genomeSAindex.h , C/C++, 11 lines - source/
genomeScanFastaFiles.cpp , C++, 92 lines - source/
genomeScanFastaFiles.h , C/C++, 10 lines - source/
htslib/ , C, 1,085 linesbgzf.c - source/
htslib/ , C, 283 linesbgzip.c - source/
htslib/ , C/C++, 3 linesconfig.h - source/
htslib/ , C/C++, 66 linescram/ cram.h - source/
htslib/ , C, 1,764 linescram/ cram_codecs.c - source/
htslib/ , C/C++, 155 linescram/ cram_codecs.h - source/
htslib/ , C, 2,138 linescram/ cram_decode.c - source/
htslib/ , C/C++, 112 linescram/ cram_decode.h - source/
htslib/ , C, 2,630 linescram/ cram_encode.c - source/
htslib/ , C/C++, 105 linescram/ cram_encode.h - source/
htslib/ , C, 503 linescram/ cram_index.c - source/
htslib/ , C/C++, 98 linescram/ cram_index.h - source/
htslib/ , C, 3,652 linescram/ cram_io.c - source/
htslib/ , C/C++, 532 linescram/ cram_io.h - source/
htslib/ , C, 144 linescram/ cram_samtools.c - source/
htslib/ , C/C++, 97 linescram/ cram_samtools.h - source/
htslib/ , C, 357 linescram/ cram_stats.c - source/
htslib/ , C/C++, 59 linescram/ cram_stats.h - source/
htslib/ , C/C++, 752 linescram/ cram_structs.h - source/
htslib/ , C, 76 linescram/ files.c - source/
htslib/ , C, 634 linescram/ mFILE.c - source/
htslib/ , C/C++, 88 linescram/ mFILE.h - source/
htslib/ , C, 295 linescram/ md5.c - source/
htslib/ , C/C++, 54 linescram/ md5.h - source/
htslib/ , C/C++, 110 linescram/ misc.h - source/
htslib/ , C, 386 linescram/ open_trace_file.c - source/
htslib/ , C/C++, 115 linescram/ open_trace_file.h - source/
htslib/ , C/C++, 306 linescram/ os.h - source/
htslib/ , C, 170 linescram/ pooled_alloc.c - source/
htslib/ , C/C++, 56 linescram/ pooled_alloc.h - source/
htslib/ , C, 1,222 linescram/ sam_header.c - source/
htslib/ , C/C++, 452 linescram/ sam_header.h - source/
htslib/ , C, 153 linescram/ string_alloc.c - source/
htslib/ , C/C++, 69 linescram/ string_alloc.h - source/
htslib/ , C, 713 linescram/ thread_pool.c - source/
htslib/ , C/C++, 197 linescram/ thread_pool.h - source/
htslib/ , C, 432 linescram/ vlen.c - source/
htslib/ , C/C++, 48 linescram/ vlen.h - source/
htslib/ , C, 185 linescram/ zfio.c - source/
htslib/ , C/C++, 54 linescram/ zfio.h - source/
htslib/ , C, 421 linesfaidx.c - source/
htslib/ , C, 526 lineshfile.c - source/
htslib/ , C/C++, 75 lineshfile_internal.h - source/
htslib/ , C, 99 lineshfile_net.c - source/
htslib/ , C, 1,326 lineshts.c - source/
htslib/ , C/C++, 313 lineshtslib/ bgzf.h - source/
htslib/ , C/C++, 112 lineshtslib/ faidx.h - source/
htslib/ , C/C++, 204 lineshtslib/ hfile.h - source/
htslib/ , C/C++, 305 lineshtslib/ hts.h - source/
htslib/ , C/C++, 47 lineshtslib/ hts_defs.h - source/
htslib/ , C/C++, 49 lineshtslib/ kfunc.h - source/
htslib/ , C/C++, 617 lineshtslib/ khash.h - source/
htslib/ , C/C++, 98 lineshtslib/ khash_str2int.h - source/
htslib/ , C/C++, 121 lineshtslib/ klist.h - source/
htslib/ , C/C++, 75 lineshtslib/ knetfile.h - source/
htslib/ , C/C++, 253 lineshtslib/ kseq.h - source/
htslib/ , C/C++, 285 lineshtslib/ ksort.h - source/
htslib/ , C/C++, 64 lineshtslib/ kstdint.h - source/
htslib/ , C/C++, 270 lineshtslib/ kstring.h - source/
htslib/ , C/C++, 401 lineshtslib/ sam.h - source/
htslib/ , C/C++, 255 lineshtslib/ synced_bcf_reader.h - source/
htslib/ , C/C++, 52 lineshtslib/ tbx.h - source/
htslib/ , C/C++, 824 lineshtslib/ vcf.h - source/
htslib/ , C/C++, 15 lineshtslib/ vcf_sweep.h - source/
htslib/ , C/C++, 94 lineshtslib/ vcfutils.h - source/
htslib/ , C, 254 lineskfunc.c - source/
htslib/ , C, 622 linesknetfile.c - source/
htslib/ , C, 229 lineskstring.c - source/
htslib/ , C, 1,797 linessam.c - source/
htslib/ , C, 1,183 linessynced_bcf_reader.c - source/
htslib/ , C, 374 linestabix.c - source/
htslib/ , C, 290 linestbx.c - source/
htslib/ , C, 2,967 linesvcf.c - source/
htslib/ , C, 158 linesvcf_sweep.c - source/
htslib/ , C, 642 linesvcfutils.c - source/
insertSeqSA.cpp , C++, 319 lines - source/
insertSeqSA.h , C/C++, 11 lines - source/
mapThreadsSpawn.cpp , C++, 33 lines - source/
mapThreadsSpawn.h , C/C++, 7 lines - source/
opal/ , C++, 1,568 linesopal.cpp - source/
opal/ , C/C++, 171 linesopal.h - source/
opal/ , C/C++, 5,590 linessimde_avx2.h - source/
outputSJ.cpp , C++, 163 lines - source/
outputSJ.h , C/C++, 4 lines - source/
readBarcodeLoad.h , C/C++, 9 lines - source/
readLoad.cpp , C++, 100 lines - source/
readLoad.h , C/C++, 12 lines - source/
samHeaders.cpp , C++, 108 lines - source/
samHeaders.h , C/C++, 10 lines - source/
serviceFuns.cpp , C++, 351 lines - source/
signalFromBAM.cpp , C++, 209 lines - source/
signalFromBAM.h , C/C++, 13 lines - source/
sjAlignSplit.cpp , C++, 15 lines - source/
sjAlignSplit.h , C/C++, 9 lines - source/
sjdbBuildIndex.cpp , C++, 333 lines - source/
sjdbBuildIndex.h , C/C++, 10 lines - source/
sjdbInsertJunctions.cpp , C++, 102 lines - source/
sjdbInsertJunctions.h , C/C++, 10 lines - source/
sjdbLoadFromFiles.cpp , C++, 27 lines - source/
sjdbLoadFromFiles.h , C/C++, 10 lines - source/
sjdbLoadFromStream.cpp , C++, 29 lines - source/
sjdbLoadFromStream.h , C/C++, 8 lines - source/
sjdbPrepare.cpp , C++, 225 lines - source/
sjdbPrepare.h , C/C++, 10 lines - source/
soloInputFeatureUMI.cpp , C++, 44 lines - source/
soloInputFeatureUMI.h , C/C++, 13 lines - source/
sortSuffixesBucket.h , C/C++, 3 lines - source/
stitchAlignToTranscript. , C++, 415 linescpp - source/
stitchAlignToTranscript. , C/C++, 7 linesh - source/
stitchGapIndel.cpp , C++, 59 lines - source/
stitchWindowAligns.cpp , C++, 355 lines - source/
stitchWindowAligns.h , C/C++, 12 lines - source/
streamFuns.cpp , C++, 149 lines - source/
streamFuns.h , C/C++, 17 lines - source/
stringSubstituteAll.cpp , C++, 10 lines - source/
stringSubstituteAll.h , C/C++, 8 lines - source/
sysRemoveDir.cpp , C++, 28 lines - source/
sysRemoveDir.h , C/C++, 8 lines - source/
systemFunctions.cpp , C++, 27 lines - source/
systemFunctions.h , C/C++, 6 lines - source/
twoPassRunPass1.cpp , C++, 97 lines - source/
twoPassRunPass1.h , C/C++, 11 lines - LICENSE, License, 21 lines
- README.md, Text, 115 lines
The paper's code and data availability statement is in the Data section.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 2 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 350 scripts, each with its path and the digest of its content;
- 6 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
No dataset and no data link were found in the paper.
Code and data availability statement
The paper has a code and data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:
- it says that the data are available on request
- it says that the code is available on request
Read it in the paper: doi.org/10.1016/j.stemcr.2026.102997.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 27 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 9 authors, 10 keywords, 12 MeSH terms, 6 funders, 45 references, 8 RRIDs.
Cite
This paper
Sochodolsky, K., Khetchoumian, K., Balsalobre, A., Feeley, R. M., Rice, M. E., Chakravarty, P., Lovell-Badge, R., Rizzoti, K., & Drouin, J. (2026). BDNF regulates pituitary stem cell engagement toward precursor state. Stem cell reports, 21(7), 102997. https://
BibTeX
@article{sochodolsky2026
author = {Sochodolsky, Kevin and Khetchoumian, Konstantin and Balsalobre, Aurelio and Feeley, Ryan M. and Rice, Margaret E. and Chakravarty, Probir and Lovell-Badge, Robin and Rizzoti, Karine and Drouin, Jacques},
title = {{BDNF regulates pituitary stem cell engagement toward precursor state}},
journal = {Stem cell reports},
year = {2026},
month = jul,
volume = {21},
number = {7},
pages = {102997},
publisher = {Elsevier},
issn = {2213-6711},
doi = {10.1016/
url = {https://
pmid = {42392084},
pmcid = {PMC13385446}
}
RIS
TY - JOUR
AU - Sochodolsky, Kevin
AU - Khetchoumian, Konstantin
AU - Balsalobre, Aurelio
AU - Feeley, Ryan M.
AU - Rice, Margaret E.
AU - Chakravarty, Probir
AU - Lovell-Badge, Robin
AU - Rizzoti, Karine
AU - Drouin, Jacques
TI - BDNF regulates pituitary stem cell engagement toward precursor state
T2 - Stem cell reports
J2 - Stem Cell Reports
PY - 2026
DA - 2026/
VL - 21
IS - 7
SP - 102997
SN - 2213-6711
PB - Elsevier
DO - 10.1016/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1016/
"type": "article-journal",
"title": "BDNF regulates pituitary stem cell engagement toward precursor state",
"container-title": "Stem cell reports",
"author": [
{
"family": "Sochodolsky",
"given": "Kevin"
},
{
"family": "Khetchoumian",
"given": "Konstantin"
},
{
"family": "Balsalobre",
"given": "Aurelio"
},
{
"family": "Feeley",
"given": "Ryan M."
},
{
"family": "Rice",
"given": "Margaret E."
},
{
"family": "Chakravarty",
"given": "Probir"
},
{
"family": "Lovell-Badge",
"given": "Robin"
},
{
"family": "Rizzoti",
"given": "Karine"
},
{
"family": "Drouin",
"given": "Jacques"
}
],
"container-title-short":
"volume": "21",
"issue": "7",
"page": "102997",
"DOI": "10.1016/
"PMID": "42392084",
"PMCID": "PMC13385446",
"ISSN": "2213-6711",
"publisher": "Elsevier",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
7,
2
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.1016/j.stemcr.2026.102922 [code]
- Spatially resolved transcriptomics identifies intercellular signaling post-ischemic stroke that controls neural stem cell proliferation.Journal: Stem cell reportsIn common: SingleCellExperiment, reticulate, UMAP, 10 other tools, mouse, 2 references
- [2] doi:10.1016/j.xcrm.2026.102766 [code]
- A longitudinal single-cell and spatial multiomic atlas of pediatric high-grade glioma.Journal: Cell reports. MedicineIn common: SingleCellExperiment, UMAP, igraph, 9 other tools, cellular / molecular, 3 references
- [3] doi:10.1016/j.xcrm.2026.102651 [code]
- Integrative CSF profiling identifies disease-specific immune responses in leptomeningeal disease.Journal: Cell reports. MedicineIn common: SingleCellExperiment, reticulate, UMAP, 10 other tools, cellular / molecular, 1 reference
- [4] doi:10.1016/j.celrep.2026.117500 [code]
- Spatio-molecular gene expression reflects dorsal anterior cingulate cortex structure and function in the human brain.Journal: Cell reportsIn common: SingleCellExperiment, reticulate, igraph, 8 other tools, cellular / molecular, 2 references
- [5] doi:10.3390/ijms27104466 [code]
- Uncovering the Key Circuit FOSL2/
FOS/ EGR3/ EGR1, Contributing to the Hyperexcitability of Excitatory Neurons in the Epileptic Temporal Cortex and Hippocampus. Journal: International journal of molecular sciencesIn common: reticulate, UMAP, igraph, 9 other tools, 1 reference - [6] doi:10.1038/s41380-026-03585-5 [code]
- Multiomics analysis identifies VPA-induced changes in neural progenitor cells, ventricular-like regions, and cellular microenvironment in dorsal forebrain organoids.Journal: Molecular psychiatryIn common: reticulate, UMAP, igraph, 8 other tools, mouse, 2 references
- [7] doi:10.1038/s41467-026-76232-w [code]
- Th17 effector cytokines induce shared and distinct microglial and endothelial cell responses in a mouse model for post-streptococcal encephalitis.Journal: Nature communicationsIn common: SingleCellExperiment, reticulate, UMAP, 8 other tools, mouse, cellular / molecular, 1 reference
- [8] doi:10.1038/s42003-026-10957-8 [code]
- Brain defence by the extracellular matrix protein Cochlin.Journal: Communications biologyIn common: reticulate, UMAP, igraph, 8 other tools, mouse, cellular / molecular, 1 reference
- [9] doi:10.1073/pnas.2523130123 [code]
- FABP7 controls radial glial scaffold stability during human cortical development.Journal: Proceedings of the National Academy of Sciences of the United States of AmericaIn common: reticulate, UMAP, igraph, 9 other tools, mouse
- [10] doi:10.1002/imt2.70163 [code]
- Spatial multi-omics unveils sphingolipid metabolic reprogramming within the retinal pathological niche.Journal: iMetaIn common: SingleCellExperiment, igraph, circlize, 8 other tools, mouse, cellular / molecular, 1 reference
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 2 repositories of the authors' code, each at its verified commit and with its license, 350 scripts, and 6 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:199591a948b0de03…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
