OSCR

Single-nucleus analysis of the adult human olfactory epithelium uncovers shared neurogenesis programs with the brain.

Code ↔ Paper

9 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 9 matches · 1 of them tie a paragraph to a whole file, not to given lines: a weak match, whose lines are not tinted
  1. [1] § Methods › Sample collection ↔ 01b.ent_process_outerMerge_0807.ipynb, lines 47–71 · score 0.77 · superior septum, superior turbinate, middle turbinate, history, surgery, metadata
  2. [2] § Results › Distinct stages of OSNs in adult olfactory epithelium ↔ 02a.traj_integrate_600-6-40-50-graph_k7_FDR_BG-Cov.ipynb, lines 497–515 · score 0.75 · receptor transformations, GBCinp, olfactory neurogenesis, SOX4, precursor, NEUROG1
  3. [3] § Results › Distinct stages of OSNs in adult olfactory epithelium ↔ 01b.ent_process_outerMerge_0807.ipynb, lines 47–71 · score 0.68 · right superior turbinate, superior septum, middle turbinate, surgery
  4. [4] § Methods › Trajectory inference and trajDEG identification ↔ 02a.traj_integrate_600-6-40-50-graph_k7_FDR_BG-Cov.ipynb, lines 76–143 · score 0.65 · graph_test, Moran, fitting, FDR, age, Monocle3
  5. [5] § Results › Distinct stages of OSNs in adult olfactory epithelium ↔ 01d.statstitic.ipynb, lines 22–46 · score 0.61 · cell cycle, l_iOSN, e_iOSN, phase, scores, GBCs
  6. [6] § Methods › snRNA-seq data preprocessing and clustering ↔ 02a.traj_integrate_600-6-40-50-graph_k7_FDR_BG-Cov.ipynb, lines 429–475 · score 0.57 · cell clustering, graph, PCA, PCs, neighborhood, filtered
  7. [7] § Results › Similarities and differences between OSNs and CENs ↔ 02a.traj_integrate_600-6-40-50-graph_k7_FDR_BG-Cov.ipynb, lines 1000–1017 · score 0.56 · trajDEG, DEG trends, biological processes, enriched, genes
  8. [8] § Methods › Genetic enrichment ↔ 01e.scdrs_downstream_stage.R, the whole file · a weak match · score 0.55 · ALS, stroke, ADHD, MDD, MS, PD
  9. [9] § Methods › Data integration ↔ 02a.traj_integrate_600-6-40-50-graph_k7_FDR_BG-Cov.ipynb, lines 429–475 · score 0.53 · IntegrateLayers, anchor, PCs, neighbors, CCA, variables

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

Jupyter notebook · 1,017 lines · 37 KB · no license · 5 matches

  1. # %%
  2. options(repr.plot.width = 10, repr.plot.height = 6, repr.plot.res = 100)
  3. setwd('/sc/arion/projects/roussp01a/liting/Olf')
  4. library(rlang)
  5. library(RColorBrewer)
  6. library(scales)
  7. library(tradeSeq)
  8. library(schard)
  9. library(SeuratWrappers)
  10. library(ggVennDiagram)
  11. library(stringr)
  12. library(rrvgo)
  13. library(slingshot)
  14. library(ComplexHeatmap)
  15. library(circlize)
  16. library(dplyr)
  17. library(gprofiler2)
  18. library(monocle3)
  19. library(ggplot2)
  20. # %%
  21. # functions
  22. scanpy2seurat <- function(file_name){
  23. h5ad=paste0('/sc/arion/projects/CommonMind/roussp01a/ENT/snRNAseq/qc_scanpy/',file_name,'.h5ad')
  24. rds=paste0('/sc/arion/projects/CommonMind/roussp01a/ENT/snRNAseq/qc_scanpy/',file_name,'.rds')
  25. ent = schard::h5ad2seurat(h5ad)
  26. saveRDS(ent,rds)
  27. }
  28. read_obj <- function(file_name, hvg){
  29. ent_N <- readRDS(paste0('/sc/arion/projects/CommonMind/roussp01a/ENT/snRNAseq/qc_scanpy/',file_name,'.rds'))
  30. names(ent_N@reductions) <- gsub('^X|_$','',names(ent_N@reductions))
  31. ent_N <- FindVariableFeatures(ent_N,nfeatures = hvg) # for identify DEGs using slingshot
  32. return(ent_N)
  33. }
  34. #N_color <- c('#1f77b4','#ff7f0e',"#D32B29")
  35. N_color <- c('#1f77b4',"#ea801c","#D32B29")
  36. names(N_color) <- c('GBC','iOSN','mOSN')
  37. get_slingshot_traj <- function(obj){
  38. dimred <- obj@reductions$[email hidden]
  39. #clustering <- as.numeric(obj$N_leiden_res0_25)+1
  40. clustering <- obj$N_types
  41. set.seed(1)
  42. pto <- slingshot(dimred, clustering, start.clus = 'GBC')
  43. obj$sling_pseudotime <- slingPseudotime(pto)
  44. FeaturePlot(object = obj, features = 'sling_pseudotime',reduction = "umap.cca")
  45. png(filename = "./figures/outermerge_slingshot_pseudotime.png",width = 8, height = 8, units = "cm", res=300)
  46. plot(dimred[, 1:2], col = N_color[clustering], cex = 0.5, pch = 16)
  47. lines(SlingshotDataSet(pto), lwd=2, col='black')
  48. dev.off()
  49. return(obj)
  50. }
  51. tradeseq_DEG <- function(data_ns, traj_method){
  52. data_ns$cca_clusters <- obj$cca_clusters
  53. counts <- as.matrix(data_ns@assays$RNA@counts[data_ns@assays$[email hidden], ])
  54. filt_counts <- counts[rowSums(counts > 0) > ncol(counts)/100, ]
  55. Pseudotime <- as.matrix(data_ns$sling_pseudotime)
  56. batch <- data_ns$batch
  57. U <- model.matrix(~batch)
  58. sce <- fitGAM(counts = as.matrix(filt_counts),
  59. pseudotime = Pseudotime,U=U,
  60. cellWeights = as.matrix(rep(1,ncol(data_ns))))
  61. # test for dynamic expression
  62. pseudotime_association <- associationTest(sce)
  63. pseudotime_association$fdr <- p.adjust(pseudotime_association$pvalue, method = "fdr")
  64. pseudotime_association <- pseudotime_association[order(pseudotime_association$pvalue), ]
  65. pseudotime_association$feature_id <- rownames(pseudotime_association)
  66. pseudotime_association_sig <- subset(pseudotime_association, fdr < 0.05)
  67. return(pseudotime_association_sig)
  68. #return(pseudotime_association)
  69. }
  70. get_monocle3_traj <- function(scdata,lab,mm, res_traj){
  71. # input: scanpy data
  72. # get root node from plot_cells
  73. # as Monocle3 data
  74. mnc3_data <- SeuratWrappers::as.cell_data_set(scdata)
  75. mnc3_data <- estimate_size_factors(mnc3_data)
  76. # Cluster your cells
  77. mnc3_data <- cluster_cells(mnc3_data,resolution=res_traj)
  78. mnc3_data <- learn_graph(mnc3_data) # # Learn the trajectory graph
  79. plot_cells(mnc3_data, color_cells_by = "cca_N_types_stage", cell_size = 1, label_principal_points = F, label_leaves=F,
  80. label_branch_points=F)
  81. print('-------------check root cell based on umap--------------------')
  82. if(lab=='x' & mm=='max'){rootcell = names(which.max(subset(data_ns, cca_N_types =='GBC')@reductions$[email hidden][,1])) }
  83. if(lab=='x' & mm=='min'){rootcell = names(which.min(subset(data_ns, cca_N_types =='GBC')@reductions$[email hidden][,1])) }
  84. if(lab=='y' & mm=='max'){rootcell = names(which.max(subset(data_ns, cca_N_types =='GBC')@reductions$[email hidden][,2])) }
  85. if(lab=='y' & mm=='min'){rootcell = names(which.min(subset(data_ns, cca_N_types =='GBC')@reductions$[email hidden][,2])) }
  86. mnc3_data <- order_cells(mnc3_data, root_cells= rootcell )
  87. plot_cells(mnc3_data, color_cells_by = "pseudotime", cell_size = 1)
  88. return(mnc3_data)
  89. }
  90. get_monocle3_DEG <- function(mnc3_data){
  91. pr_test_res <- monocle3:::graph_test(mnc3_data, neighbor_graph="principal_graph", cores=6)
  92. pr_test_res <- pr_test_res[order(pr_test_res$q_value),]
  93. pr_test_res_sig <- subset(pr_test_res ) # get_monocle3_DEG #& morans_I > 0.1 & morans_I > 0.05
  94. return(pr_test_res_sig)
  95. #return(pr_test_res)
  96. }
  97. get_monocle3_DEG_contBatch <- function(mnc3_data){
  98. mnc3_data$Age <- scale(mnc3_data$Age)
  99. pr_test_res <- fit_models(mnc3_data,model_formula_str = "~monocle3_pseudotime + batch + Sex + Age")#expression_family="negbinomial",
  100. pr_test_res <- coefficient_table(pr_test_res)
  101. pr_test_res <- pr_test_res %>% filter(term == "monocle3_pseudotime") %>%
  102. select(gene_id, term, q_value, estimate)
  103. pr_test_res <- pr_test_res[order(pr_test_res$q_value),]
  104. pr_test_res_sig <- subset(pr_test_res, q_value < 0.05 )
  105. pr_test_res_sig <- as.data.frame(pr_test_res_sig)
  106. rownames(pr_test_res_sig) <- pr_test_res_sig$gene_id
  107. return(pr_test_res_sig)
  108. #return(pr_test_res)
  109. }
  110. get_heatmap_re_cluster_kmeans <- function(scdata, method, DEGs, n_split, recluster_id,n_REsplit){
  111. #if (method=='monocle') { pseudoTime <- pseudotime(scdata) }
  112. if (method=='monocle3') { pseudoTime <- scdata$monocle3_pseudotime}
  113. if (method=='slingshot') { pseudoTime <- scdata$sling_pseudotime }
  114. if (method=='palantir') { pseudoTime = scdata$palantir_pseudotime}
  115. if (method=='paga') { pseudoTime = scdata$dpt_pseudotime}
  116. pt.matrix1 <- as.matrix(scdata@assays$RNA@counts[rownames(DEGs),order(pseudoTime)])
  117. #pt.matrix1 <- as.matrix(scdata[["RNA"]]$data[rownames(DEGs),order(pseudoTime)])
  118. #pt.matrix1 <- as.matrix(scdata[["RNA"]]$scale.data[rownames(DEGs),order(pseudoTime)])
  119. #Can also use "normalized_counts" instead of "exprs" to use various normalization methods, for example:
  120. #normalized_counts(cds, norm_method = "log")
  121. pt.matrix <- pt.matrix1
  122. pt.matrix <- t(apply(pt.matrix,1,function(x){smooth.spline(x,df=3)$y}))
  123. pt.matrix <- t(apply(pt.matrix,1,function(x){(x-mean(x))/sd(x)}))
  124. pt.matrix[pt.matrix > 4] = 4
  125. pt.matrix[pt.matrix < -4] = -4
  126. #
  127. rownames(pt.matrix) <- rownames(DEGs);
  128. colnames(pt.matrix) <- colnames(scdata)[order(pseudoTime)]
  129. set.seed(42)
  130. ks_1st <- kmeans(pt.matrix, centers = n_split , iter.max = 100)
  131. C_K1 <- ks_1st$cluster
  132. C_K2 <- ''
  133. if (recluster_id!=''){
  134. ks_2st <- kmeans(pt.matrix[ks_1st$cluster==recluster_id,], centers = n_REsplit, iter.max = 100)
  135. C_K2 <- ks_2st$cluster[names(ks_1st$cluster)]
  136. C_K2 <- ifelse(is.na(C_K2),'',paste0('-',C_K2))
  137. }
  138. rowsplit <- paste0(C_K1,C_K2)
  139. dict_cluster <- c('iOSN','GBC','mOSN')
  140. names(dict_cluster) <- names(sort(table(rowsplit)))
  141. rowsplit=dict_cluster[rowsplit]
  142. hthc=ComplexHeatmap::draw(Heatmap(
  143. pt.matrix,
  144. row_split = rowsplit,
  145. col = colorRamp2(seq(from=-2,to=2,length=11),rev(brewer.pal(11, "Spectral"))),
  146. #row_title = "cluster_%s",
  147. row_gap = unit(c(2.5), "mm"),
  148. cluster_row_slices = FALSE,
  149. cluster_columns = F,
  150. show_row_names = FALSE,
  151. show_column_names = FALSE,
  152. show_row_dend = F,
  153. top_annotation = HeatmapAnnotation(
  154. cell_identity=[email hidden][colnames(pt.matrix),'N_types'],
  155. cell_subcluster=[email hidden][colnames(pt.matrix),'leiden'],
  156. #batch=[email hidden][colnames(pt.matrix),'batch'],
  157. #subc=[email hidden][colnames(pt.matrix),'N_leiden_res0_2'],
  158. pseudotime=sort(pseudoTime),
  159. col = list(cell_identity =N_color)#,
  160. # pseudotime= colorRamp2(c(0, 0.5, 1, 1.5), c("#35008C", "#8700A8", "#D3546F",'#E7F92D'))
  161. #)
  162. )
  163. ))
  164. deg_cl <- as.data.frame(cbind(as.character(rowsplit), rownames(DEGs),method))
  165. colnames(deg_cl) <- c('cluster','DEG','method')
  166. return(deg_cl)
  167. }
  168. library(enrichR)
  169. get_bp_enrichr <- function(query_gene){
  170. dbs <- "GO_Biological_Process_2023"
  171. enriched <- enrichr(query_gene, dbs)
  172. enrr <- enriched[['GO_Biological_Process_2023']]
  173. return(enrr)
  174. }
  175. get_bp_enrichr <- function(cl, md){
  176. query_gene <- subset(DEG_ent, cluster==cl & method==md)[,'DEG']
  177. dbs <- dbs <- c( "GO_Biological_Process_2023",
  178. "KEGG_2021_Human")
  179. enriched <- enrichr(query_gene, dbs)
  180. enrr <- rbind(enriched[['GO_Biological_Process_2023']])
  181. enrr$cluster <- cl
  182. enrr$method <- md
  183. return(enrr)
  184. }
  185. get_bp_enrichr_reducedTerms <- function(DEG_ent, cl,md){
  186. query_gene <- subset(DEG_ent, cluster==cl & method==md)[,'DEG']
  187. dbs <- c( "GO_Biological_Process_2023")
  188. #"KEGG_2021_Human")
  189. enriched <- enrichr(query_gene, dbs)
  190. enrr <- enriched[['GO_Biological_Process_2023']]
  191. enrr$genecluster <- cl
  192. enrr$method <- md
  193. go_analysis <- subset(enrr, p_value < 0.05 )
  194. go_analysis$GOID <- str_split(go_analysis$Term,'\\(|\\)',simplify = T)[,2]
  195. simMatrix <- calculateSimMatrix(go_analysis$GOID,
  196. orgdb="org.Hs.eg.db",
  197. ont="BP",
  198. method="Rel")
  199. scores <- setNames(-log10(as.numeric(go_analysis$p_value)), go_analysis$GOID)
  200. reducedTerms <- reduceSimMatrix(simMatrix,
  201. scores,
  202. orgdb="org.Hs.eg.db")
  203. treemapPlot(reducedTerms)
  204. reducedTerms_sumscore <- aggregate(score~parentTerm,reducedTerms, sum)
  205. reducedTerms_sumscore$genecluster <- cl
  206. reducedTerms_sumscore$method <- md
  207. reducedTerms_sumscore$term <- reducedTerms_sumscore$parentTerm
  208. reducedTerms <- reducedTerms%>%group_by(cluster)%>%top_n(1,score)
  209. reducedTerms$genecluster <- cl
  210. reducedTerms$method <- md
  211. reducedTerms$term <- reducedTerms$parentTerm
  212. return(list(enrr=enrr,reducedTerms=reducedTerms,reducedTerms_sumscore=reducedTerms_sumscore))
  213. }
  214. #table(ent_nn$batch)
  215. # %%
  216. #colData(int_N)
  217. # %%
  218. graph_test_lm_ENT <- function (cds, neighbor_graph = c("knn", "principal_graph"),
  219. reduction_method = "UMAP", k = 25, method = c("Moran_I"),
  220. alternative = "greater", expression_family = "quasipoisson",
  221. cores = 1, verbose = FALSE)
  222. {
  223. #nn_control_default <- get_global_variable('nn_control_annoy_euclidean')
  224. nn_control_default <- list(method='annoy', metric='euclidean', n_trees=50, M=48, ef_construction=200, ef=150, grain_size=1, cores=1)
  225. nn_control <- monocle3:::set_nn_control(mode=3,
  226. nn_control_default=nn_control_default,
  227. nn_index=NULL,
  228. k=k,
  229. verbose=verbose)
  230. neighbor_graph <- match.arg(neighbor_graph)
  231. lw <- monocle3:::calculateLW(cds=cds,
  232. k = k,
  233. neighbor_graph = neighbor_graph,
  234. reduction_method = reduction_method,
  235. verbose = verbose,
  236. nn_control = nn_control_default
  237. )
  238. exprs_mat <- SingleCellExperiment::counts(cds)[, attr(lw, "region.id"), drop = FALSE]
  239. sz <- size_factors(cds)[attr(lw, "region.id")]
  240. wc <- spdep::spweights.constants(lw, zero.policy = TRUE,
  241. adjust.n = TRUE)
  242. test_res <- pbmcapply::pbmclapply(row.names(exprs_mat), FUN = function(x,
  243. sz, alternative, method, expression_family) {
  244. exprs_val <- exprs_mat[x, ]
  245. if (expression_family %in% c("uninormal", "binomialff")) {
  246. exprs_val <- exprs_val
  247. }
  248. else {
  249. exprs_val <- log10(exprs_val/sz + 0.1)
  250. }
  251. df = cbind(as.data.frame(exprs_val), colData(cds)$Sex, scale(colData(cds)$Age),colData(cds)$batch ,log(colData(cds)$nCount_RNA))
  252. colnames(df) <- c("exp", "Sex", "Age",'batch','log1p_total_counts')
  253. test_res <- tryCatch({
  254. if (method == "Moran_I") {
  255. mt <- suppressWarnings(monocle3:::my.moran.test(df, lw, wc, alternative = alternative))
  256. data.frame(status = "OK", p_value = mt$p.value,
  257. morans_test_statistic = mt$statistic, morans_I = mt$estimate[["Moran I statistic"]])
  258. }
  259. else if (method == "Geary_C") {
  260. gt <- suppressWarnings(my.geary.test(exprs_val,
  261. lw, wc, alternative = alternative))
  262. data.frame(status = "OK", p_value = gt$p.value,
  263. geary_test_statistic = gt$statistic, geary_C = gt$estimate[["Geary C statistic"]])
  264. }
  265. }, error = function(e) {
  266. data.frame(status = "FAIL", p_value = NA, morans_test_statistic = NA,
  267. morans_I = NA)
  268. })
  269. }, sz = sz, alternative = alternative, method = method, expression_family = expression_family,
  270. mc.cores = cores, ignore.interactive = TRUE)
  271. if (verbose) {
  272. message("returning results: ...")
  273. }
  274. test_res <- do.call(rbind.data.frame, test_res)
  275. row.names(test_res) <- row.names(cds)
  276. test_res <- merge(test_res, rowData(cds), by = "row.names")
  277. row.names(test_res) <- test_res[, 1]
  278. test_res[, 1] <- NULL
  279. test_res$q_value <- 1
  280. test_res$q_value[which(test_res$status == "OK")] <- stats::p.adjust(subset(test_res,
  281. status == "OK")[, "p_value"], method = "BH")
  282. test_res$status = as.character(test_res$status)
  283. test_res[row.names(cds), ]
  284. }
  285. my.moran.test_lm_ENT <- function (x, listw, wc, alternative = "greater", randomisation = TRUE)
  286. {
  287. zero.policy = TRUE
  288. adjust.n = TRUE
  289. na.action = stats::na.fail
  290. drop.EI2 = FALSE
  291. xname <- deparse(substitute(x))
  292. wname <- deparse(substitute(listw))
  293. NAOK <- deparse(substitute(na.action)) == "na.pass"
  294. x <- na.action(x)
  295. na.act <- attr(x, "na.action")
  296. if (!is.null(na.act)) {
  297. subset <- !(1:length(listw$neighbours) %in% na.act)
  298. listw <- subset(listw, subset, zero.policy = zero.policy)
  299. }
  300. n <- length(listw$neighbours)
  301. S02 <- wc$S0 * wc$S0
  302. model <- lm(exp ~ Age + Sex + batch + log1p_total_counts, data = x) # batch + Sex + Age +as.numeric(log1p_total_counts)
  303. res <- spdep::lm.morantest(model, listw, zero.policy = zero.policy, alternative = alternative)
  304. statistic = as.numeric(res[1])
  305. names(statistic) <- "Moran I statistic standard deviate"
  306. PrI = as.numeric(res[2])
  307. vec <- c(res[3]$estimate[1], res[3]$estimate[2], res[3]$estimate[3])
  308. names(vec) <- c("Moran I statistic", "Expectation", "Variance")
  309. method <- paste("Moran I test under", ifelse(randomisation,
  310. "randomisation", "normality"))
  311. res <- list(statistic = statistic, p.value = PrI, estimate = vec)
  312. if (!is.null(na.act))
  313. attr(res, "na.action") <- na.act
  314. class(res) <- "htest"
  315. res
  316. }
  317. assignInNamespace(x = "graph_test", value = graph_test_lm_ENT, ns = "monocle3")
  318. assignInNamespace(x = "my.moran.test", value = my.moran.test_lm_ENT, ns = "monocle3")
  319. # %%
  320. #xtabs(~batch+N_types,[email hidden])
  321. # %% [markdown]
  322. # ### CCA data integration
  323. # %%
  324. # 1. read tata
  325. # from 2_integrate_Neuron_nn_ent_outer
  326. scanpy2seurat('ent_nn_merge_rawcount')
  327. ent_nn <- read_obj('ent_nn_merge_rawcount', hvg = 3000)
  328. ent_nn=ent_nn[!grepl('^RPS|^RPL|^LINC|^MT',rownames(ent_nn)),]
  329. #data <- subset(data,batch%in%c(setdiff(unique(data$batch),c('Set4_C1','Set4_C2','Set1_C1','Set2_C1','Set2_C2') )))
  330. #ent_nn$batch <- str_split(ent_nn$batch,'_',simplify = T)[,1]
  331. ent_nn$batch <- ent_nn$Set
  332. ent_nn[["RNA"]] <- split(ent_nn[["RNA"]], f = ent_nn$batch)
  333. #data[["RNA"]] <- split(data[["RNA"]], f = data$dataset)
  334. ent_nn <- subset(ent_nn,batch%in%c(setdiff(unique(ent_nn$batch),c('Set2', 'Set3', 'Set4') )))#
  335. # %%
  336. n_features <- c(600)
  337. n_pcs <- c(6)
  338. n_neighbors <- c(40)
  339. n_kweight <- c(50)
  340. for (n_pc in n_pcs){
  341. for (n_feature in n_features){
  342. for (n_neighbor in n_neighbors){
  343. for(kw in n_kweight){
  344. data <- NormalizeData(ent_nn)
  345. data <- FindVariableFeatures(data,selection.method='mean.var.plot',nfeatures=n_feature)
  346. data <- ScaleData(data,features=VariableFeatures(data))
  347. #run PCA. Select significant PCs based on a scree plot. Look for the last point before the plot becomes flat
  348. data <- RunPCA(data,features = VariableFeatures(data),verbose=F)
  349. # 4. batch correction
  350. ## 4.1 cca
  351. obj <- IntegrateLayers(
  352. object = data, method = CCAIntegration,k.weight =kw,
  353. orig.reduction = "pca", new.reduction = "integrated.cca",
  354. verbose = FALSE, dims = 1:n_pc
  355. # k.weight = 10,
  356. # k.anchor = 10,
  357. # k.filter = 10,
  358. # k.score = 10
  359. )#
  360. # 5 identify cell clusters
  361. ## 5.1 cca
  362. obj <- FindNeighbors(obj, reduction = "integrated.cca", dims = 1:n_pc)
  363. obj <- FindClusters(obj, resolution = 0.25, cluster.name = "cca_clusters")
  364. obj <- RunUMAP(obj, reduction = "integrated.cca", dims = 1:n_pc, reduction.name = "umap.cca", n.neighbors=n_neighbor)
  365. p1 <- DimPlot(
  366. obj,
  367. reduction = "umap.cca",
  368. group.by = c("batch" ,'dataset','cca_clusters'),label.size = 2
  369. )
  370. # ggsave(p1, file=paste0('./figures/integrated_pcs/',n_pc,'_',n_feature,"_",n_neighbor,"_",kw,'inte_umap.pdf'), width=14, height=4)
  371. }
  372. }
  373. }}
  374. # %%
  375. # label
  376. DimPlot(
  377. obj,
  378. reduction = "umap.cca",
  379. group.by = c('cca_clusters','N_types'),label.size = 2)
  380. # %%
  381. #DEG_trend_Olf['CALB1',]
  382. #FeaturePlot(obj, features = c('CALB1','CALB2') , cols = c("#FFF5F0",'#F75D42', "#6A010D") )+theme_minimal()+theme_void()+theme(legend.position = '')
  383. #FeaturePlot(obj, features = DEG_trend_Olf$gene[DEG_trend_Olf$cl=='7'][14:18] , cols = c("#FFF5F0",'#F75D42', "#6A010D") )+theme_minimal()+theme_void()+theme(legend.position = '')
  384. #scz_risk_genes <- c("COMT", "DISC1", "ZNF804A", "NRG1", "DTNBP1", "G72", "MAOA", "SLC6A4", "CACNA1C", "TTC28")
  385. #FeaturePlot(obj, pt.size = 1,features =scz_risk_genes[4], cols = c("#FFF5F0",'#F75D42', "#6A010D") )+theme_minimal()+theme_void()+theme(legend.position = '')
  386. # %%
  387. # Single-cell transcriptomics reveals receptor transformations during olfactory neurogenesis
  388. # for progenitors, Ascl1 (achaete-scute complex homolog 1); for precursors, Neurog1 (neurogenin 1) and/or Neurod1 (neurogenic differentiation 1);
  389. GBCinp <- c("HES6","CXCR4","NEUROD1","NEUROG1")
  390. GBCprogenitors <- c('ASCL1','MKI67','TOP2A')
  391. iOSN <- c('GNG8', 'GAP43','LHX2','SOX4')#c('EBF2', 'EMX2')
  392. p1 <- FeaturePlot(obj, features = GBCinp[1], cols = c("#FFF5F0",'#F75D42', "#6A010D") )+theme_void()+theme(legend.position = '', aspect.ratio = 1)
  393. p2 <- FeaturePlot(obj, features = GBCinp[2], cols = c("#FFF5F0",'#F75D42', "#6A010D") )+theme_void()+theme(legend.position = '', aspect.ratio = 1)
  394. p3 <- FeaturePlot(obj, features = GBCinp[3], cols = c("#FFF5F0",'#F75D42', "#6A010D") )+theme_void()+theme(legend.position = '', aspect.ratio = 1)
  395. p4 <- FeaturePlot(obj, features = GBCinp[4], cols = c("#FFF5F0",'#F75D42', "#6A010D") )+theme_void()+theme(legend.position = '', aspect.ratio = 1)
  396. p5 <- FeaturePlot(obj, features = "LHX2", cols = c("#FFF5F0",'#F75D42', "#6A010D") )+theme_void()+theme(legend.position = '', aspect.ratio = 1)
  397. p6 <- FeaturePlot(obj, features = "GAP43", cols = c("#FFF5F0",'#F75D42', "#6A010D") )+theme_void()+theme(legend.position = '', aspect.ratio = 1)
  398. px <- cowplot::plot_grid(p1,p2,p3,p4,nrow=2)
  399. pX2 <- cowplot::plot_grid(p3,p4,p5,p6,nrow=2)
  400. #FeaturePlot(obj, features = GBCprogenitors , cols = c("#FFF5F0",'#F75D42', "#6A010D") )+theme_minimal()+theme_void()+theme(legend.position = '')
  401. ggsave(px, file=paste0('./figures/03GBC_markers.pdf'), width=5, height=5)
  402. ggsave(pX2, file=paste0('./figures/03GBC_markers2.pdf'), width=5, height=5)
  403. # %%
  404. # mesenchymal cells
  405. # iOSN <- c('ACTA2','MAP1B', 'COL1A2','FZD2', 'FZD7', 'ROR2', 'SFRP1' , 'SFRP2', 'CTNNB1' , 'JAG1', 'PSEN1' , 'APH1A')#c('EBF2', 'EMX2')
  406. # FeaturePlot(obj, features = iOSN, cols = c("#FFF5F0",'#F75D42', "#6A010D") )
  407. # iOSN <- c('TAGLN', 'COL1A2', 'COL1A1', 'CALD1', 'TPM2', 'COL3A1', 'TPM1', 'LGALS1')
  408. # FeaturePlot(obj, features = iOSN, cols = c("#FFF5F0",'#F75D42', "#6A010D") ,pt.size = 0.2)
  409. # iOSN <- c('UCHL1', 'MAP1A', 'MAP1B', 'TUBB3', 'INA', 'NRP1', 'MKI67', 'ACTB','NES')
  410. # FeaturePlot(obj, features = iOSN, cols = c("#FFF5F0",'#F75D42', "#6A010D") ,pt.size = 0.2)
  411. iOSN <- mkx <- c('UCHL1', 'MAP1A', 'MAP1B', 'TUBB3', 'INA', 'NRP1', 'MKI67', 'ACTB','NES')
  412. FeaturePlot(obj, features = iOSN, cols = c("#FFF5F0",'#F75D42', "#6A010D") ,pt.size = 0.2)
  413. STK6), PLK1, E2F1, FOXM1, MKI67
  414. # %%
  415. ent_N <- readRDS('/sc/arion/projects/CommonMind/roussp01a/ENT/snRNAseq/qc_scanpy/ent_nn_merge_cca.rds')
  416. # %%
  417. # # #obj <- FindNeighbors(obj, reduction = "integrated.cca", dims = 1:n_pc)
  418. # obj <- FindClusters(obj, resolution = 0.25, cluster.name = "cca_clusters")
  419. # obj <- RunUMAP(obj, reduction = "integrated.cca", dims = 1:n_pc, reduction.name = "umap.cca", n.neighbors=n_neighbor)
  420. # DimPlot(
  421. # obj,
  422. # reduction = "umap.cca",
  423. # group.by = c('cca_clusters'),label.size = 2
  424. # )
  425. cca_label <- c( 'GBC','e_iOSN','l_iOSN','mOSN')
  426. names(cca_label) <- c('3','2','0','1')
  427. obj <- RenameIdents(obj, cca_label)
  428. [email hidden]$cca_N_types_stage <- cca_label[as.character(obj$cca_clusters)]
  429. [email hidden]$cca_N_types <- ifelse([email hidden]$cca_N_types_stage%in%c('e_iOSN','l_iOSN'),'iOSN',[email hidden]$cca_N_types_stage)
  430. DimPlot(
  431. obj,
  432. reduction = "umap.cca",
  433. group.by = c('cca_N_types_stage', 'cca_N_types'),label.size = 2
  434. )
  435. saveRDS(obj,'/sc/arion/projects/CommonMind/roussp01a/ENT/snRNAseq/qc_scanpy/ent_nn_merge_cca.rds')
  436. # %%
  437. options(repr.plot.width = 10, repr.plot.height = 8, repr.plot.res = 100)
  438. FeaturePlot(obj, features = iOSN, cols = c("#FFF5F0",'#F75D42', "#6A010D") )#+theme( aspect.ratio = 1)
  439. DotPlot(obj, features = c('NEUROD1','NEUROG1','SOX4','LHX2','GNG8','GAP43','GNAL','GNG13'),
  440. cols = c("white", "#A40F14"),scale = FALSE) + RotatedAxis()+theme_bw()+
  441. theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),legend.position = 'bottom')+ylab('Cell types')
  442. dev.print(pdf,file = "/sc/arion/projects/roussp01a/liting/Olf/figures/marker_dot.pdf", width = 3.5, height = 5)
  443. # %%
  444. write.csv([email hidden], file='./data/ent_nn_merge_cca.metadata.csv')
  445. # %%
  446. obj_combined <- JoinLayers(object = obj)
  447. #markers_2 <- FindMarkers(CB30_combined, ident.1 = "CD4+", ident.2 = "CD4+ UT", verbose = FALSE)
  448. Idents(obj_combined) <- "cca_N_types_stage"
  449. GBC.de.markers <- FindMarkers(obj_combined, ident.1 = "GBC", ident.2 = NULL, only.pos = TRUE)%>%subset(p_val_adj < 0.05)
  450. e_iOSN.de.markers <- FindMarkers(obj_combined, ident.1 = "e_iOSN", ident.2 = NULL, only.pos = TRUE)%>%subset(p_val_adj < 0.05)
  451. l_iOSN.de.markers <- FindMarkers(obj_combined, ident.1 = "l_iOSN", ident.2 = NULL, only.pos = TRUE)%>%subset(p_val_adj < 0.05)
  452. mOSN.de.markers <- FindMarkers(obj_combined, ident.1 = "mOSN", ident.2 = NULL, only.pos = TRUE)%>%subset(p_val_adj < 0.05)
  453. mOSN.de.markers[1:3,]
  454. # %%
  455. # subset(xx,grepl('apopto',term_name))[1:5,]
  456. # %%
  457. # xx <- gost(rownames(mOSN.de.markers), source='GO:BP' ,
  458. # correction_method = "fdr",user_threshold=0.1,significant=F)$result %>%subset(term_size < 3000)
  459. # xx
  460. # %%
  461. #FeaturePlot(obj, pt.size =0.5, features = rownames(e_iOSN.de.markers)[1:4] ,
  462. # cols = c("#FFF5F0",'#F75D42', "#6A010D") , )+theme(legend.position = "none")
  463. #e_iOSN.de.markers[1:15,]
  464. # %%
  465. #png(filename = "./figures/outermerge_mnc3_pseudotime.png",width = 10, height = 8, units = "cm", res=300)
  466. options(repr.plot.width = 12, repr.plot.height = 12, repr.plot.res = 100)
  467. library(scattermore)#scattermore
  468. UMAPCCA <- as.data.frame(obj@reductions$[email hidden])
  469. UMAPCCA$dataset <- obj$dataset
  470. UMAPCCA$N_types <- obj$N_types
  471. UMAPCCA$N_types_stage <- obj$cca_N_types_stage
  472. brewer.pal(n = 12, name = "Paired")
  473. p1 <- ggplot(UMAPCCA, aes(x=umapcca_1,y=umapcca_2, color=N_types ))+
  474. geom_scattermore(pointsize=5)+theme_bw()+theme(aspect.ratio = 1)+
  475. scale_color_manual(values = c('#1f77b4','#ff7f0e',"#D32B29"),breaks = c('GBC','iOSN','mOSN'))+xlab('UMAP1')+ylab('UMAP2')
  476. p1 <- ggplot(UMAPCCA, aes(x=umapcca_1,y=umapcca_2, color=factor(N_types_stage,levels = c('GBC','e_iOSN','l_iOSN','mOSN') )))+
  477. geom_scattermore(pointsize=5)+theme_bw()+theme(aspect.ratio = 1)+labs(col='Cell types')+
  478. scale_color_manual(values = c('#1f77b4','#FDBF6F','#ff7f0e',"#D32B29"),
  479. breaks = c('GBC','e_iOSN','l_iOSN','mOSN'))+xlab('UMAP1')+ylab('UMAP2')+
  480. theme(panel.grid.major = element_blank(),
  481. panel.grid.minor = element_blank(),
  482. axis.text = element_blank(), # Remove axis text
  483. axis.ticks = element_blank()
  484. )
  485. p2 <- ggplot(UMAPCCA, aes(x=umapcca_1,y=umapcca_2, color=dataset ))+xlab('UMAP1')+ylab('UMAP2')+geom_scattermore(pointsize=5)+theme_bw()+theme(aspect.ratio = 1)+
  486. theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
  487. axis.text = element_blank(), # Remove axis text
  488. axis.ticks = element_blank()
  489. )+scale_color_manual(values = c('#2D81BC','#B8B8B8'))
  490. pdf(file='./figures/03ent_nn_N_merge.umap.pdf',width=8, height=3.5)
  491. p2+p1
  492. dev.off()
  493. # %% [markdown]
  494. # ### slingshot
  495. # %%
  496. #
  497. data_ns <- read_obj('ent_nn_merge_rawcount', hvg = 8000)
  498. data_ns=data_ns[!grepl('^RPS|^RPL|^LINC|^MT',rownames(data_ns)),]
  499. data_ns$batch <- data_ns$Set
  500. #data_ns <- JoinLayers(data_ns)
  501. data_ns <- subset(data_ns, batch%in%c(setdiff(unique(data_ns$batch),c('Set2','Set3','Set4') )))
  502. data_ns <- NormalizeData(data_ns)
  503. data_ns <- FindVariableFeatures(data_ns, selection.method='mean.var.plot')
  504. data_ns@reductions$umap <- obj@reductions$umap.cca
  505. sling_merge <- get_slingshot_traj(obj=obj)
  506. [email hidden]$sling_pseudotime <- sling_merge$sling_pseudotime
  507. [email hidden]$cca_N_types <- [email hidden][rownames([email hidden]),'cca_N_types']
  508. [email hidden]$cca_N_types_stage <- [email hidden][rownames([email hidden]),'cca_N_types_stage']
  509. DEG_sling_merge <- tradeseq_DEG(data_ns=data_ns, 'slingshot')
  510. # %%
  511. get_bg <- function(celltype){
  512. data_sub <- subset(data_ns, cca_N_types_stage=='GBC')
  513. custom_olfbg <- rownames(data_sub)[rowSums(as.data.frame(data_sub@assays$RNA@counts > 0)) > 0.05*ncol(data_sub)]
  514. return(custom_olfbg)
  515. }
  516. custom_olfbg <- lapply(c('GBC','e_iOSN','l_iOSN','mOSN'),get_bg)
  517. custom_olfbg <- unique(unlist(custom_olfbg))
  518. custom_olfbg <- rownames(data_ns)[rowSums(as.data.frame(data_ns@assays$RNA@counts > 0)) > 0.05*ncol(data_ns)]
  519. custom_olfbg <- rownames(data_ns)[rowSums(as.data.frame(data_ns@assays$RNA@counts > 0)) >= 5]
  520. save(custom_olfbg, file='./data/custom_olfbg.RData')
  521. # %% [markdown]
  522. # ### monocle3
  523. # %%
  524. int_N <- get_monocle3_traj(scdata=data_ns,'y','min',res_traj=0.001)
  525. save(int_N, file='./figures/mnc3_ent_nn.RData')
  526. p1 <- plot_cells(int_N, color_cells_by = "pseudotime", cell_size = 0.8,label_roots=F,label_branch_points=F,label_leaves=F)+theme(legend.position = 'top', aspect.ratio = 1)
  527. p2 <- plot_cells(int_N, color_cells_by = "cca_N_types_stage", cell_size = 0.8,label_roots=F,label_branch_points=F,label_leaves=F)+
  528. #scale_color_manual(values = c('#1f77b4','#ff7f0e',"#D32B29"),breaks = c('GBC','iOSN','mOSN'))+
  529. scale_color_manual(values = c('#1f77b4','#FDBF6F','#ff7f0e',"#D32B29"),breaks = c('GBC','e_iOSN','l_iOSN','mOSN'))+
  530. theme(legend.position = 'top', aspect.ratio = 1)
  531. cowplot::plot_grid(p2,p1,nrow = 1)
  532. pdf( "./figures/03outermerge_mnc3_pseudotime_p1.pdf",width = 4, height = 4)
  533. p1
  534. dev.off()
  535. pdf( "./figures/03outermerge_mnc3_pseudotime_p2.pdf",width = 4, height = 4)
  536. p2
  537. dev.off()
  538. # %%
  539. save(int_N, file='./figures/mnc3_ent_nn.RData')
  540. # %%
  541. # %%
  542. data_ns$monocle3_pseudotime <- pseudotime(int_N)
  543. int_N$monocle3_pseudotime <- pseudotime(int_N)
  544. #DEG_mnc3_int_glm <- get_monocle3_DEG_contBatch(int_N)
  545. DEG_mnc3_int_graph <- get_monocle3_DEG(int_N)
  546. # %%
  547. library(ggplot2)
  548. library(ggsignif) # For adding significance tests
  549. library(ggpubr)
  550. N_stage_color <- c('#1f77b4','#FDBF6F','#ff7f0e',"#D32B29")
  551. names(N_stage_color) <- c('GBC','e_iOSN','l_iOSN','mOSN')
  552. [email hidden]$cca_N_types_stage <- factor([email hidden]$cca_N_types_stage, levels = c('GBC','e_iOSN','l_iOSN','mOSN'))
  553. ggboxplot([email hidden], x = "cca_N_types_stage", y = "monocle3_pseudotime",
  554. color = "dataset",
  555. )+stat_compare_means(aes(group = dataset), method = "anova",label = "p.signif")+ylab('Pseudotime') +xlab('')+
  556. scale_color_manual(values = c('#2D81BC','#B8B8B8'))+
  557. theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
  558. dev.print(pdf, file='./figures/pseudo_boxplot.pdf',height=3.8,width=3.5)
  559. # %%
  560. write.table([email hidden], file='./data/integrate_entnn_pseduotime_meta.txt',sep='\t',quote=F)
  561. # %%
  562. DEGs1 <- rownames(subset(DEG_mnc3_int_graph, morans_I > 0.05 & q_value < 0.05))
  563. #DEGs2 <- rownames(subset(DEG_mnc3_int_glm, q_value < 0.05))
  564. #DEGs3 <- unique(c(rownames(GBC.de.markers), rownames(e_iOSN.de.markers), rownames(l_iOSN.de.markers), rownames(mOSN.de.markers)))
  565. # %%
  566. save(DEG_mnc3_int_graph,file='./data/DEG_mnc3_int_graph.RData' )
  567. # %%
  568. length(DEGs1)
  569. #length(DEGs2)
  570. # %% [markdown]
  571. # ### Gene clusters
  572. # %%
  573. DEGs <- DEGs1
  574. options(repr.plot.width = 8, repr.plot.height = 8, repr.plot.res = 100)
  575. scdata <- data_ns
  576. save(scdata, file='./data/scdata.RData')
  577. #pseudoTime = scdata$sling_pseudotime#
  578. pseudoTime = scdata$monocle3_pseudotime
  579. pt.matrix1 <- as.matrix(scdata@assays$RNA@counts[DEGs,order(pseudoTime)])
  580. pt.matrix <- t(apply(pt.matrix1,1,function(x){smooth.spline(x,df=3)$y}))
  581. #pt.matrix <- t(apply(pt.matrix,1,function(x){(x-mean(x))/sd(x)}))
  582. pt.matrix <- t(apply(pt.matrix,1,function(x){(x-min(x))/(max(x)-min(x))}))
  583. rownames(pt.matrix) <- DEGs;
  584. colnames(pt.matrix) <- colnames(scdata)[order(pseudoTime)]
  585. n_cluster <- 7
  586. set.seed(123)
  587. heatmap_cluster <- Heatmap(
  588. pt.matrix,
  589. row_km =n_cluster,
  590. col = colorRamp2(seq(from=0,to=1,length=11),rev(brewer.pal(11, "Spectral"))),
  591. #row_title = "cluster_%s",
  592. row_gap = unit(c(2.5), "mm"),
  593. cluster_row_slices = F,
  594. cluster_columns = F,
  595. show_row_names = FALSE,
  596. show_column_names = FALSE,
  597. show_row_dend = F,
  598. top_annotation = HeatmapAnnotation(
  599. cell_identity=[email hidden][colnames(pt.matrix),'cca_N_types'],
  600. cell_subcluster=[email hidden][colnames(pt.matrix),'cca_N_types_stage'],
  601. #batch=[email hidden][colnames(pt.matrix),'batch'],
  602. #subc=[email hidden][colnames(pt.matrix),'N_leiden_res0_2'],
  603. pseudotime=sort(pseudoTime),
  604. col = list(cell_identity = N_color)
  605. # pseudotime= colorRamp2(c(0, 10, 20, 30), c("#35008C", "#8700A8", "#D3546F",'#E7F92D'))
  606. )
  607. )
  608. hthc=ComplexHeatmap::draw(heatmap_cluster)
  609. hthc
  610. save(hthc,file = './figures/heatmap_cluster_graphK7.RData')
  611. # %%
  612. # %%
  613. #load('./figures/heatmap_cluster_graphK7.RData')
  614. DEG_trend_Olf <- c()
  615. down_cl <- c(1,3)
  616. trans_up_cl <- c(6,5,7)
  617. up_cl <- c(4,2)
  618. trans_down_cl <- c()
  619. # down_cl <- c(1,2,4)
  620. # trans_up_cl <- c(7,6)
  621. # up_cl <- c(5,3)
  622. # trans_down_cl <- c()
  623. for(cl in 1:n_cluster){
  624. deg_td <- cbind(DEGs[row_order(hthc)[[cl]]], cl )
  625. DEG_trend_Olf <- rbind(DEG_trend_Olf, deg_td )
  626. }
  627. DEG_trend_Olf <- as.data.frame(DEG_trend_Olf)
  628. colnames(DEG_trend_Olf) <- c('gene','cl')
  629. DEG_trend_Olf <- within(DEG_trend_Olf,{
  630. trend_class=''
  631. trend_class[cl%in%down_cl] <- 'down'
  632. trend_class[cl%in%trans_up_cl] <- 'trans_up'
  633. trend_class[cl%in%up_cl] <- 'up'
  634. trend_class[cl%in%trans_down_cl] <- 'trans_down'
  635. })
  636. order_c <- as.character(c(down_cl,trans_up_cl,up_cl,trans_down_cl ))
  637. #order_c <- as.character(c(6,2,7,1,4,5,3))
  638. order_n <- c(1:length(order_c))
  639. names(order_c) <- order_n
  640. order_c <- sort(order_c)
  641. order_n <- names(order_c)
  642. rownames(DEG_trend_Olf) <- DEG_trend_Olf$gene
  643. DEG_trend_Olf$g_cluster <- as.character(order_n)[as.numeric(DEG_trend_Olf$cl)]
  644. trend_color <- brewer.pal(n = 8, name = "Paired")[c(1,3,5,7)]
  645. names(trend_color) <- c('down','trans_down','up','trans_up')
  646. Nstage_color <- c('#1f77b4','#FDBF6F','#ff7f0e',"#D32B29")
  647. names(Nstage_color) <- c('GBC','e_iOSN','l_iOSN','mOSN')
  648. # %%
  649. library(RColorBrewer)
  650. brewer.pal(n = 8, name = "Paired")[c(1,3,5,7)]
  651. # %%
  652. save(DEG_trend_Olf, file='/sc/arion/projects/roussp01a/liting/Olf/data/DEG_trend_Olf_k7_graph.RData')
  653. # %%
  654. load('/sc/arion/projects/roussp01a/liting/Olf/data/DEG_trend_Olf_k7_graph.RData')
  655. # %%
  656. supp_degs <- subset(DEG_mnc3_int_graph, morans_I > 0.05 & q_value < 0.05)
  657. supp_degs$trajDEG_cluster <- DEG_trend_Olf[rownames(supp_degs),'g_cluster']
  658. supp_degs$trend_class <- DEG_trend_Olf[rownames(supp_degs),'trend_class']
  659. write.table(supp_degs[,c('morans_I','q_value','trajDEG_cluster','trend_class')],file='./data/supp_DEGs.txt',sep='\t')
  660. # %%
  661. # %%
  662. write.table(DEG_trend_Olf, file='./data/DEG_trend_Olf.txt',sep='\t')
  663. table(DEG_trend_Olf$trend_class)
  664. # %%
  665. DEG_trend_Olf[1:3,]
  666. # %%
  667. # get_bp_enrichr <- function(x){
  668. # query_gene <- subset(DEG_trend_Olf, g_cluster%in%as.character(x))[,'gene']
  669. # dbs <- "GO_Biological_Process_2023"
  670. # enriched <- enrichr(query_gene, dbs)
  671. # enrr <- enriched[['GO_Biological_Process_2023']]
  672. # return(enrr)
  673. # }
  674. # enr <- get_bp_enrichr(c(6,7))
  675. # enr[1:35,]
  676. # %%
  677. #load('/sc/arion/projects/roussp01a/liting/Olf/data/DEG_trend_Olf_k7_graph.RData')
  678. lister_hvg <- read.csv('lister_hvg.csv')
  679. #
  680. table(DEG_trend_Olf$gene%in%lister_hvg$X[lister_hvg$highly_variable=='True'])
  681. #DEG_trend_Olf$gene
  682. # %%
  683. library(viridis)
  684. ptm <- pt.matrix[unlist(row_order(hthc)[order_c] ),]
  685. hthc <- ComplexHeatmap::draw(Heatmap(
  686. ptm, name = "Expression",
  687. col = colorRamp2(seq(from=0,to=1,length=9),rev(brewer.pal(9, "Spectral"))),
  688. row_gap = unit(c(2.5), "mm"),
  689. cluster_rows = FALSE,
  690. cluster_columns = F,
  691. show_row_names = FALSE,
  692. show_column_names = FALSE,
  693. use_raster = TRUE, raster_quality = 5,
  694. show_row_dend = F,
  695. row_split = DEG_trend_Olf[rownames(ptm),'g_cluster'],
  696. #heatmap_legend_param = list(legend_width = unit(20, "cm"),title_gap = unit(10, "cm")),
  697. right_annotation = rowAnnotation(Trend = DEG_trend_Olf[rownames(ptm),'trend_class'],
  698. col=list(Trend = trend_color)),
  699. top_annotation = HeatmapAnnotation(
  700. Neuron = [email hidden][colnames(pt.matrix),'cca_N_types'],
  701. Stage = factor([email hidden][colnames(pt.matrix),'cca_N_types_stage'],levels = c('GBC','e_iOSN','l_iOSN','mOSN')),
  702. Pseudotime=sort(pseudoTime),
  703. col = list(Neuron = N_color,
  704. Stage=Nstage_color ,
  705. Pseudotime=colorRamp2(seq(from=0,to=30,length=50), plasma(50)) ),simple_anno_size = unit(0.3, "cm"))),
  706. heatmap_legend_side = "bottom", annotation_legend_side = "bottom",merge_legend = TRUE )
  707. # %%
  708. #png(filename = './figures/03heatmap_DEG_clusters_k7.png', width = 15, height = 20, units = "cm", res=300)
  709. pdf( './figures/03heatmap_DEG_clusters_k7.pdf', width = 5, height = 10)
  710. hthc
  711. dev.off()
  712. # %%
  713. n_cl <- aggregate(DEG_trend_Olf,cl~g_cluster,length)
  714. # %%
  715. #pt.matrix
  716. # %%
  717. library(splines)
  718. # %%
  719. options(repr.plot.width = 8, repr.plot.height = 8, repr.plot.res = 100)
  720. g_mean <- c()
  721. for (i in unique(DEG_trend_Olf$g_cluster)){
  722. Gene <- subset(DEG_trend_Olf,g_cluster==i)[,'gene']
  723. g1_mean <- as.data.frame(cbind(colMeans(pt.matrix[Gene,]), c(sort(pseudoTime)) ))%>%mutate(g_cluster=i)
  724. g_mean <- rbind(g1_mean,g_mean)
  725. }
  726. g_mean <- merge(g_mean, unique(DEG_trend_Olf[,c('trend_class','g_cluster')]), by='g_cluster')
  727. n_cl <- aggregate(DEG_trend_Olf,cl~g_cluster,length)
  728. g_mean_cl <- merge(g_mean, n_cl)
  729. g_mean_cl$gcl <- paste0(g_mean_cl$g_cluster,' ( N = ',g_mean_cl$cl ,')')
  730. #pdf('./figures/03meanexp_DEG_clusters_k7.pdf', width = 4.5, height = 8)
  731. pdf('./figures/03meanexp_DEG_clusters_k7.pdf', width = 3, height = 7)
  732. ggplot(subset(g_mean_cl), aes(V2, V1, color=trend_class)) +
  733. #geom_smooth(method = "loess")+
  734. geom_smooth(method = "lm", formula = y ~ ns(x, df = 3),se = T)+
  735. xlab('Pseudotime')+ylab('Expression')+theme_light() +
  736. theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), legend.position='bottom',
  737. legend.title = element_blank())+
  738. facet_wrap(~gcl,nrow = length(order_c)) +
  739. scale_color_manual(values = brewer.pal(n = 8, name = "Paired")[c(1,7,5)])+
  740. scale_y_continuous(breaks = seq(0, 1, by = 1))
  741. dev.off()
  742. # %%
  743. library(splines)
  744. Gene <- subset(DEG_trend_Olf,g_cluster==1)[,'gene']
  745. xx <- reshape2::melt(pt.matrix[Gene,])
  746. xx$pseudoTime <- scdata$monocle3_pseudotime[as.character(xx$Var2)]
  747. xxx <- aggregate(xx,value~Var2+pseudoTime , mean)
  748. ggplot(subset(xx), aes(x=pseudoTime, y=value, group=Var1)) +
  749. #geom_smooth(method = "loess")+
  750. geom_smooth(method = "lm", formula = y ~ ns(x, df = 3),se = F)+
  751. xlab('Pseudotime')+ylab('Expression')+theme_light() +
  752. theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), legend.position = '')
  753. ggplot(subset(xxx), aes(pseudoTime, value)) +
  754. #geom_smooth(method = "loess")+
  755. geom_smooth(method = "lm", formula = y ~ ns(x, df = 3),se = F)+
  756. xlab('Pseudotime')+ylab('Expression')+theme_light() +
  757. theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), legend.position = '')
  758. # %%
  759. load('/sc/arion/projects/roussp01a/liting/Olf/data/DEG_trend_Olf_k7.RData')
  760. goterms <- gost(split(DEG_trend_Olf$gene,DEG_trend_Olf$g_cluster ), source='GO:BP' ,#custom_bg = rownames(data) ,
  761. correction_method = "fdr",user_threshold=0.05,significant=F)$result %>%subset(term_size < 2000)
  762. sig_goterms <- subset(goterms, p_value < 0.05)#%>%group_by(query)#%>%top_n(20,-p_value)
  763. sig_goterms <- sig_goterms[,c(1,3:6,9,11)]
  764. colnames(sig_goterms)[1:2] <- c('trajDEG cluster','FDR')
  765. write.table(sig_goterms, file='./figures/supple_DE_cluster_GO_all.txt',row.names = F, sep='\t')
  766. # for(i in 1:7){print(goterms%>%subset(query==i & term_size < 2000 & term_size > 30)%>%top_n(20,-p_value)%>%select(c(query,term_name,p_value)))}
  767. # dbs <- "GO_Biological_Process_2023"
  768. # enriched <- lapply(split(DEG_trend_Olf$gene,DEG_trend_Olf$g_cluster ), function(x)enrichr(x, dbs)[['GO_Biological_Process_2023']])
  769. # enriched

02a.traj_integrate_600-6-40-50-graph_k7_FDR_BG-Cov.ipynb at commit 59edf81, no license · at the source

Overview

Authors: Liting Song1,2,3,4, John F Fullard1,2,3,4, Claire Coleman1,2,3,4, Evelyn Hennigan1,2,3,4, Clara Casey1,2,3,4, Xinyi Wang1,2,3,4, Ayako Kawatake-Kuno1,2,3,4, Stathis Argyriou1,2,3,4, Steven Kleopoulos1,2,3,4, Samuel DeMaria5, Jaroslav Bendl1,2,3,4, Alfred Marc Iloreta6, Pengfei Dong1,2,3,4, Panos Roussos1,2,3,4,7,8
  1. Center for Disease Neurogenomics, Icahn School of Medicine at Mount Sinai, New York, NY USA
  2. Friedman Brain Institute, Icahn School of Medicine at Mount Sinai, New York, NY USA
  3. Department of Psychiatry, Icahn School of Medicine at Mount Sinai, New York, NY USA
  4. Department of Genetics and Genomic Science, Icahn School of Medicine at Mount Sinai, New York, NY USA
  5. Department of Anesthesiology, Icahn School of Medicine at Mount Sinai, New York, NY USA
  6. Department of Otolaryngology, Icahn School of Medicine at Mount Sinai, New York, NY USA
  7. Mental Illness Research Education and Clinical Center (MIRECC), James J. Peters VA Medical Center, Bronx, New York, NY USA
  8. Center for Precision Medicine and Translational Therapeutics, James J. Peters VA Medical Center, Bronx, New York, NY USA
Journal: Nature communications, volume 17, issue 1, article 8744
Dates: received 6 August 2025; accepted 9 July 2026; published online 17 July 2026
Type: Research article · Language: English
License: CC BY-NC-ND
Identifiers: DOI 10.1038/s41467-026-75722-1 · PMID 42463696 · PMCID PMC13494014 · OpenAlex W7169028888
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: genetics / omics (modality), human (organism), developmental (subfield)
Methods: Connectivity, Statistics, Smoothing, state filtering, decompositions, Machine learning, Preprocessing, Evoked potentials
Keywords: Olfactory system, Genetics of the nervous system
MeSH: Brain*, Neurogenesis*, Olfactory Mucosa*, Olfactory Receptor Neurons*, Adult, Cell Differentiation, Cell Nucleus, Female, Gene Expression Profiling, Humans, Male, Neural Stem Cells, Neurodevelopment, RNA-Seq, Single-Cell Analysis, Single-Cell Gene Expression Analysis, Transcription Factors, Transcriptome (* major topic)
Topic: Olfactory and Sensory Function Studies (Sensory Systems, Neuroscience), according to OpenAlex
Funding: NIA NIH HHS (R01 AG067025, R01 AG050986, R01 AG065582, R01 AG082185, U24 AG087563); U.S. Department of Health & Human Services | NIH | National Institute on Aging (U.S. National Institute on Aging) (R01-AG067025, R01-AG065582, R01-AG082185, U24-AG087563, R01-AG050986); NIMH NIH HHS (R01 MH110921, RF1 MH133703, R01 MH125246, U01 MH116442); U.S. Department of Health & Human Services | NIH | National Institute of Mental Health (NIMH) (R01-MH110921, R01-MH125246, RF1-MH133703, U01-MH116442); NINDS NIH HHS (U01 NS125580); U.S. Department of Health & Human Services | NIH | National Institute of Neurological Disorders and Stroke (NINDS) (U01NS125580)
Citations: cited by 1 paper (Europe PMC); 93 references in the paper

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 9 matches between paragraphs and lines of code.

well.ox.ac.uk/~wrayner/tools

License: none: the authors keep all their rights
State: the link is dead, verified on 27 September 2026
Evidence: found in the paper
Software Heritage: not checked
Found in: the text, “SNP array genotyping workflow”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 27 September 2026: the link is dead (HTTP 404)
  • 27 September 2026: the link is dead (HTTP 404)

Zenodo 20867452

License: CC-BY-4.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: “Code availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: anndata (6 files), pandas (6 files), Scanpy (6 files), seaborn (4 files), tidyverse (4 files), ggplot2 (3 files), Matplotlib (3 files), cowplot (2 files), ggpubr (2 files), NumPy (2 files), Seurat (2 files), circlize (1 file), ComplexHeatmap (1 file), Monocle 3 (1 file), reshape2 (1 file), scikit-learn (1 file), SciPy (1 file), SingleCellExperiment (1 file), UMAP (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
  • 27 September 2026: the link answers (HTTP 200)
10 files

Zenodo 20867451

License: CC-BY-4.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: the references
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: anndata (6 files), pandas (6 files), Scanpy (6 files), seaborn (4 files), tidyverse (4 files), ggplot2 (3 files), Matplotlib (3 files), cowplot (2 files), ggpubr (2 files), NumPy (2 files), Seurat (2 files), circlize (1 file), ComplexHeatmap (1 file), Monocle 3 (1 file), reshape2 (1 file), scikit-learn (1 file), SciPy (1 file), SingleCellExperiment (1 file), UMAP (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
  • 27 September 2026: the link answers (HTTP 200)
10 files
At the source:

litingsong/oe_nn

License: none: the authors keep all their rights
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 59edf81e4b2c1655b39e1afa1873dd6968f2ea07, 26 June 2026
Languages: Jupyter (21), R (5), Python (2)
Size: 29 files, 28 scripts
Software Heritage: not archived
Found in: the Zenodo archive record
Holds: README, 21 notebooks
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: anndata (6 files), pandas (6 files), Scanpy (6 files), seaborn (4 files), tidyverse (4 files), ggplot2 (3 files), Matplotlib (3 files), cowplot (2 files), ggpubr (2 files), NumPy (2 files), Seurat (2 files), circlize (1 file), ComplexHeatmap (1 file), Monocle 3 (1 file), reshape2 (1 file), scikit-learn (1 file), SciPy (1 file), SingleCellExperiment (1 file), UMAP (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
10 files

Code availability statement

The paper has a code availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

Read it in the paper: doi.org/10.1038/s41467-026-75722-1.

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:

  • 4 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 30 scripts, each with its path and the digest of its content;
  • 9 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

Datasets cited

Data availability statement

The paper has a data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

Read it in the paper: doi.org/10.1038/s41467-026-75722-1.

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, 14 authors, 2 keywords, 18 MeSH terms, 6 funders, 90 references.

Cite

This paper

Song, L., Fullard, J. F., Coleman, C., Hennigan, E., Casey, C., Wang, X., Kawatake-Kuno, A., Argyriou, S., Kleopoulos, S., DeMaria, S., Bendl, J., Iloreta, A. M., Dong, P., & Roussos, P. (2026). Single-nucleus analysis of the adult human olfactory epithelium uncovers shared neurogenesis programs with the brain. Nature communications, 17(1), 8744. https://doi.org/10.1038/s41467-026-75722-1

BibTeX

@article{song2026single,
author = {Song, Liting and Fullard, John F and Coleman, Claire and Hennigan, Evelyn and Casey, Clara and Wang, Xinyi and Kawatake-Kuno, Ayako and Argyriou, Stathis and Kleopoulos, Steven and DeMaria, Samuel and Bendl, Jaroslav and Iloreta, Alfred Marc and Dong, Pengfei and Roussos, Panos},
title = {{Single-nucleus analysis of the adult human olfactory epithelium uncovers shared neurogenesis programs with the brain}},
journal = {Nature communications},
year = {2026},
month = jul,
volume = {17},
number = {1},
pages = {8744},
publisher = {Nature Publishing Group},
issn = {2041-1723},
doi = {10.1038/s41467-026-75722-1},
url = {https://doi.org/10.1038/s41467-026-75722-1},
pmid = {42463696},
pmcid = {PMC13494014}
}

RIS

TY - JOUR
AU - Song, Liting
AU - Fullard, John F
AU - Coleman, Claire
AU - Hennigan, Evelyn
AU - Casey, Clara
AU - Wang, Xinyi
AU - Kawatake-Kuno, Ayako
AU - Argyriou, Stathis
AU - Kleopoulos, Steven
AU - DeMaria, Samuel
AU - Bendl, Jaroslav
AU - Iloreta, Alfred Marc
AU - Dong, Pengfei
AU - Roussos, Panos
TI - Single-nucleus analysis of the adult human olfactory epithelium uncovers shared neurogenesis programs with the brain
T2 - Nature communications
J2 - Nat Commun
PY - 2026
DA - 2026/07/17
VL - 17
IS - 1
SP - 8744
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/s41467-026-75722-1
UR - https://doi.org/10.1038/s41467-026-75722-1
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41467-026-75722-1",
"type": "article-journal",
"title": "Single-nucleus analysis of the adult human olfactory epithelium uncovers shared neurogenesis programs with the brain",
"container-title": "Nature communications",
"author": [
{
"family": "Song",
"given": "Liting"
},
{
"family": "Fullard",
"given": "John F"
},
{
"family": "Coleman",
"given": "Claire"
},
{
"family": "Hennigan",
"given": "Evelyn"
},
{
"family": "Casey",
"given": "Clara"
},
{
"family": "Wang",
"given": "Xinyi"
},
{
"family": "Kawatake-Kuno",
"given": "Ayako"
},
{
"family": "Argyriou",
"given": "Stathis"
},
{
"family": "Kleopoulos",
"given": "Steven"
},
{
"family": "DeMaria",
"given": "Samuel"
},
{
"family": "Bendl",
"given": "Jaroslav"
},
{
"family": "Iloreta",
"given": "Alfred Marc"
},
{
"family": "Dong",
"given": "Pengfei"
},
{
"family": "Roussos",
"given": "Panos"
}
],
"container-title-short": "Nat Commun",
"volume": "17",
"issue": "1",
"page": "8744",
"DOI": "10.1038/s41467-026-75722-1",
"PMID": "42463696",
"PMCID": "PMC13494014",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41467-026-75722-1",
"language": "en",
"issued": {
"date-parts": [
[
2026,
7,
17
]
]
}
}

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.xcrm.2026.102766 [code]
A longitudinal single-cell and spatial multiomic atlas of pediatric high-grade glioma.
Journal: Cell reports. Medicine
In common: Monocle 3, SingleCellExperiment, UMAP, 16 other tools, genetics / omics, 4 references
[2] doi:10.1038/s41467-026-71595-6 [code]
A single-cell and spatial atlas of early human olfactory development.
Journal: Nature communications
In common: SingleCellExperiment, anndata, circlize, 12 other tools, genetics / omics, 6 references
[3] doi:10.1038/s41467-026-71803-3 [code]
Charting the transition from in vitro gliogenesis to the in vivo maturation of human glial progenitor cells transplanted into the hypomyelinated mouse brain.
Journal: Nature communications
In common: anndata, Scanpy, Seurat, 10 other tools, genetics / omics, 9 references
[4] doi:10.1186/s13059-026-04177-w [code]
Genomic sequence evolution underlying human neocortical interareal diversification.
Journal: Genome biology
In common: Monocle 3, UMAP, anndata, 14 other tools, genetics / omics, 3 references
[5] doi:10.1038/s41467-026-71525-6 [code]
Single-nucleus brain transcriptomics reveals microglia dysfunction in multiple system atrophy.
Journal: Nature communications
In common: UMAP, anndata, circlize, 11 other tools, genetics / omics, 5 references
[6] doi:10.1038/s42003-026-10034-0 [code]
Region- and cell type-specific changes in gene expression in the cerebellum after classical fear conditioning.
Journal: Communications biology
In common: SingleCellExperiment, anndata, circlize, 13 other tools, genetics / omics, 3 references
[7] doi:10.1038/s41586-026-10490-y [code]
Lineage and organ signals sequentially build organ intrinsic nervous systems.
Journal: Nature
In common: Monocle 3, UMAP, anndata, 13 other tools, developmental, 3 references
[8] doi:10.1038/s41586-026-10214-2 [code]
Multidimensional profiling of heterogeneity in supratentorial ependymomas.
Journal: Nature
In common: Monocle 3, SingleCellExperiment, anndata, 15 other tools, genetics / omics
[9] doi:10.1002/imt2.70163 [code]
Spatial multi-omics unveils sphingolipid metabolic reprogramming within the retinal pathological niche.
Journal: iMeta
In common: Monocle 3, SingleCellExperiment, anndata, 15 other tools, genetics / omics
[10] doi:10.1038/s41514-026-00391-9 [code]
Region-specific transcriptional signatures of brain aging in the absence of neuropathology at the single-cell level.
Journal: npj aging
In common: anndata, circlize, Scanpy, 13 other tools, genetics / omics, 3 references

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.

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.