OSCR

The extreme diversity of retinal amacrine cells has deep evolutionary roots.

Code ↔ Paper

30 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 30 matches
  1. [1] § RESULTS › Evolutionarily grounded annotation of oACs ↔ src/5_tf_analysis.Rmd, lines 1831–1919 · score 0.96 · oAC39, oAC14, oAC7, oAC37, oAC13, oAC19
  2. [2] § RESULTS › A conserved regulatory logic underlies AC heterogeneity ↔ src/5_tf_analysis.Rmd, lines 1831–1919 · score 0.96 · ZNF804A, oAC4, oAC3, oAC7, oAC6, oAC2
  3. [3] § RESULTS › Evolutionarily grounded annotation of oACs ↔ src/utils/objects.R, lines 3–12 · score 0.96 · oAC39, oAC14, oAC7, oAC37, oAC13, oAC19
  4. [4] § RESULTS › Conservation of AC diversity in basal vertebrates ↔ src/utils/objects.R, lines 3–12 · score 0.91 · oAC37, oAC8, oAC6, oAC2, oAC36, oAC1
  5. [5] § RESULTS › Evolutionarily grounded annotation of oACs ↔ src/8_figures.Rmd, lines 3708–3741 · score 0.89 · oAC20, oAC40, oAC14, oAC18, oAC38, oAC13
  6. [6] § RESULTS › A conserved regulatory logic underlies AC heterogeneity ↔ src/2_orthotype_analysis.Rmd, lines 4058–4131 · score 0.82 · ZNF804A, TFAP2B, EBF1, NEUROD2, BNC1, BNC2
  7. [7] § RESULTS › Neurotransmitter identity of oACs ↔ src/1_species_clustering.Rmd, lines 715–734 · score 0.80 · Slc6a11, Slc6a13, Slc6a5, Slc6a9, GAD2, GABAergic
  8. [8] § RESULTS › Coordinated evolution of AC and RGC diversity ↔ src/8_figures.Rmd, lines 2662–2742 · score 0.76 · nearest neighbor, SAMap alignment, TFAP2B, lamprey clusters, NN, RBPMS
  9. [9] § RESULTS › Integration across amniotes identifies 42 oACs ↔ src/8_figures.Rmd, lines 1008–1076 · score 0.70 · confidence interval, ferret SACs, SLC5A7, precision, recall, discrete
  10. [10] § MATERIALS AND METHODS › Regulatory tree construction by MP ↔ src/utils/wrappers.R, lines 3032–3148 · score 0.68 · equally parsimonious trees, consensus tree, pratchet, binary, MP, seq
  11. [11] § MATERIALS AND METHODS › Integration of nonmammalian atlases ↔ src/8_figures.Rmd, lines 2662–2742 · score 0.67 · nearest neighbor classification, lamprey cluster, unmapped, alignment, MG, predict
  12. [12] § MATERIALS AND METHODS › Statistical analysis › Enrichment of protein-protein interactions ↔ src/7_sac_analysis.Rmd, lines 724–770 · score 0.66 · protein interactions, interaction score, STRINGdb, v12, downloaded, genes
  13. [13] § RESULTS › Cross-species histological validation of select AC orthotypes ↔ src/8_figures.Rmd, lines 1604–1649 · score 0.65 · VGluT3, SLC17A8, nNOS, GAD, NOS1, NXPH1
  14. [14] § RESULTS › Shared evolutionary origin of GABAergic ACs and RGCs ↔ src/8_figures.Rmd, lines 2848–2880 · score 0.63 · TFAP2B, ambiguous cluster, NEFL, NEFM, OPN4, RBPMS2
  15. [15] § RESULTS › Integration across amniotes identifies 42 oACs ↔ src/2_orthotype_analysis.Rmd, lines 839–865 · score 0.59 · integrated LISI, iLISI, cLISI, VG3, Seurat, SAC
  16. [16] § MATERIALS AND METHODS › Regulatory tree construction by MP ↔ src/utils/wrappers.R, lines 3032–3148 · score 0.58 · equally parsimonious, Branch lengths, ACCTRAN, MP, tree
  17. [17] § MATERIALS AND METHODS › Statistical analysis › Enrichment of protein-protein interactions ↔ src/5_tf_analysis.Rmd, lines 2007–2062 · score 0.57 · STRINGdb, protein interactions, shuffled, Enrichment, tree, score
  18. [18] § MATERIALS AND METHODS › Assessing robustness of amniote orthotypes ↔ src/2_orthotype_analysis.Rmd, lines 839–865 · score 0.57 · iLISI, cLISI, metrics, precision, recall, VG3
  19. [19] § MATERIALS AND METHODS › Dimensionality reduction and clustering within each species ↔ src/utils/documented-functions.R/clustering.R, lines 76–193 · score 0.57 · principal components, PCs, dimensionality, Seurat, variable, log
  20. [20] § MATERIALS AND METHODS › Assessing robustness of amniote orthotypes ↔ src/8_figures.Rmd, lines 799–843 · score 0.56 · cLISI, iLISI, mixing, amniote, VG3, SAC
  21. [21] § RESULTS › Shared evolutionary origin of GABAergic ACs and RGCs ↔ src/utils/objects.R, lines 839–905 · score 0.54 · TFAP2B, NEFL, NEFM, OPN4, RBPMS2, NOS1
  22. [22] § RESULTS › AC atlases across 24 vertebrates ↔ src/utils/objects.R, lines 1040–1085 · score 0.54 · snRNA, mouse lemur, sc, newt, axolotl, killifish
  23. [23] § RESULTS › Integration across amniotes identifies 42 oACs ↔ src/8_figures.Rmd, lines 799–843 · score 0.53 · cLISI, iLISI, mixed, shuffled, amniotes, VG3
  24. [24] § MATERIALS AND METHODS › Integration of nonmammalian atlases ↔ src/8_figures.Rmd, lines 3018–3119 · score 0.52 · BC integration, Leiden clustering, cell class, nonmammals, Jaccard, heatmaps
  25. [25] § MATERIALS AND METHODS › Assessing robustness of amniote orthotypes ↔ src/utils/documented-functions.R/clustering.R, lines 1–73 · score 0.52 · nearest neighbors, clustering resolution, identity
  26. [26] § RESULTS › Conservation of AC diversity across amniotes ↔ src/8_figures.Rmd, lines 2055–2143 · score 0.51 · tree shrew, species clusters, curve, abundance, quantify, opossum
  27. [27] § RESULTS › Conservation of AC diversity in basal vertebrates ↔ src/utils/wrappers.R, lines 3448–3561 · score 0.51 · genome duplication, cell classes, retinal, PR, goldfish, orthology
  28. [28] § MATERIALS AND METHODS › Regulatory tree construction by MP ↔ src/5_tf_analysis.Rmd, lines 1243–1277 · score 0.51 · anc_pars, ACCTRAN, reconstructing, TF, tree
  29. [29] § MATERIALS AND METHODS › Statistical analysis › Divergence analysis ↔ src/utils/wrappers.R, lines 547–608 · score 0.51 · pseudo bulked, PC, space, distances, BC, RGC
  30. [30] § MATERIALS AND METHODS › Integration of nonmammalian atlases ↔ src/utils/wrappers.R, lines 3448–3561 · score 0.50 · clustering resolutions, cell class, downstream, atlases, Seurat, goldfish

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 Markdown · 4,412 lines · 195 KB · MIT · 10 matches

  1. ---
  2. title: "Amacrine cell manuscript figures"
  3. output:
  4. BiocStyle::html_document:
  5. toc: true
  6. ---
  7. Load necessary libraries for analysis
  8. ```{r setup}
  9. source("../../utils/dario_functions.R")
  10. LoadLibraries(load.lisi = FALSE)
  11. SourceFiles()
  12. JS.THRESHOLD = 0.10
  13. ```
  14. Add new orthotype labels
  15. ```{r}
  16. ac.ortho = LoadACOrtho()
  17. # order = levels(ac.ortho$type)
  18. meta = Metadata2(ac.ortho, c('type', 'type_no', 'lit_type', 'displaced'))
  19. old.values = levels(ac.ortho$type)
  20. # annotation = ExtractString(old.values, before = '_')
  21. # new.levels = gsub(' \\[\\]', '', paste0('oAC', 1:42, ' [', annotation, ']'))
  22. number = paste0('oAC', 1:42, ifelse(meta$displaced, '*', ''))
  23. new.levels = gsub(' \\[NA\\]', '', paste0(number, ' [', meta$lit_type, ']'))
  24. ac.ortho$orthotype = factor(convert_values(ac.ortho$type, key_table = data.frame(old.names = old.values,
  25. new.names = new.levels)),
  26. levels = new.levels)
  27. table(ac.ortho$orthotype)
  28. saveRDS(ac.ortho, '../../Ortho_Objects/vertebrateAC_BIGSEURAT.rds')
  29. ```
  30. # Species figures
  31. ## Raster solution
  32. ```{r}
  33. library(magick)
  34. dir.create('../../Evolution/images/PhyloPic/colored2/')
  35. colors = species_palette3
  36. input_dir <- "../../Evolution/images/PhyloPic"
  37. files <- list.files(input_dir, pattern = "\\.svg$", full.names = TRUE)
  38. for (f in files) {
  39. nm <- tools::file_path_sans_ext(basename(f))
  40. if (!nm %in% names(colors)) next
  41. img <- image_read_svg(f)
  42. img <- image_colorize(img, opacity = 100, color = colors[nm])
  43. image_write(img, paste0('../../Evolution/images/PhyloPic/colored2/', gsub('.svg', '.png', basename(f))), format = "png")
  44. image_write(img, paste0('../../Evolution/images/PhyloPic/colored2/', basename(f)), format = "svg")
  45. image_write(img, paste0('../../Evolution/images/PhyloPic/colored2/', gsub('.svg', '.pdf', basename(f))), format = "pdf")
  46. }
  47. ```
  48. ## Raster solution (gray)
  49. ```{r}
  50. library(magick)
  51. dir.create('../../Evolution/images/PhyloPic/gray/')
  52. colors = species_palette3
  53. input_dir <- "../../Evolution/images/PhyloPic"
  54. files <- list.files(input_dir, pattern = "\\.svg$", full.names = TRUE)
  55. for (f in files) {
  56. nm <- tools::file_path_sans_ext(basename(f))
  57. if (!nm %in% names(colors)) next
  58. img <- image_read_svg(f)
  59. img <- image_colorize(img, opacity = 100, color = 'grey15')
  60. image_write(img, paste0('../../Evolution/images/PhyloPic/gray/', basename(f)), format = "svg")
  61. image_write(img, paste0('../../Evolution/images/PhyloPic/gray/', gsub('.svg', '.pdf', basename(f))), format = "pdf")
  62. }
  63. ```
  64. ## SVG solution (fails for half)
  65. ```{r}
  66. library(rsvg)
  67. outdir <- "../../Evolution/images/PhyloPic/colored3/"
  68. dir.create(outdir, showWarnings = FALSE)
  69. colors <- species_palette3
  70. input_dir <- "../../Evolution/images/PhyloPic"
  71. files <- list.files(input_dir, pattern = "\\.svg$", full.names = TRUE)
  72. for (f in files) {
  73. nm <- tools::file_path_sans_ext(basename(f))
  74. if (!nm %in% names(colors)) next
  75. color <- colors[nm]
  76. # Read SVG as text
  77. svg_text <- readLines(f, warn = FALSE)
  78. svg_text <- paste(svg_text, collapse = "\n")
  79. # Replace all black fills (both style and direct attribute)
  80. new_svg_text <- svg_text
  81. new_svg_text <- gsub("fill:#000000", paste0("fill:", color), new_svg_text, ignore.case = TRUE)
  82. new_svg_text <- gsub('fill="#000000"', paste0('fill="', color, '"'), new_svg_text, ignore.case = TRUE)
  83. if(identical(svg_text, new_svg_text)){
  84. new_svg_text <- gsub(
  85. '<path([^>]*?)(/?>)',
  86. paste0('<path\\1 fill="', color, '"\\2'),
  87. svg_text
  88. )
  89. }
  90. if (identical(svg_text, new_svg_text)) {
  91. message("No black fill found in ", nm, "; skipping PDF.")
  92. next
  93. }
  94. # Save to temporary SVG
  95. tmp_svg <- tempfile(fileext = ".svg")
  96. writeLines(new_svg_text, tmp_svg)
  97. # Output PDF
  98. out_pdf <- file.path(outdir, paste0(nm, ".pdf"))
  99. if (file.exists(out_pdf)) file.remove(out_pdf)
  100. rsvg::rsvg_pdf(tmp_svg, out_pdf)
  101. message("Saved PDF for ", nm, " with fill color ", color)
  102. }
  103. ```
  104. # Legends
  105. ```{r}
  106. ggarrange(get_legend(JSHeatmap2(ac.umap$orthotypes, ac.umap$leiden_clusters, col.high = 'chartreuse4') + theme(legend.position = "bottom")),
  107. get_legend(JSHeatmap2(ac.umap$orthotypes, ac.umap$leiden_clusters) + theme(legend.position = "bottom")),
  108. get_legend(JSHeatmap2(ac.umap$orthotypes, ac.umap$leiden_clusters, col.high = 'cyan4') + theme(legend.position = "bottom")))
  109. ggsave('../../figures/my_figs/jaccard-legends.pdf')
  110. ```
  111. ```{r}
  112. plot_grid(get_legend(PrettyUmap2(ac.ortho.no.tetrapods,
  113. group.by = "orthotype.no",
  114. color.by = "species",
  115. cols = species_palette2,
  116. show.legend = TRUE,
  117. geom.label = geom_label,
  118. color = 'black', fill = 'white',
  119. label.size = 0, alpha = 0.5,
  120. label.padding = unit(0, "lines"),
  121. label.r = unit(0.2, "lines"),
  122. label = TRUE)))
  123. ggsave('figures/mammals-legend.png')
  124. ```
  125. # Figure 1: intro
  126. ## Phylogeny
  127. ```{r, fig.height=5, fig.width=10}
  128. key = data.table::fread("../../Evolution/phylogeny/species_common_latin_24.txt")
  129. write.table(key$LatinName, "../../Evolution/phylogeny/species_latin_24.txt", quote = FALSE, row.names = FALSE, col.names = FALSE)
  130. # Make newick tree using timetree (https://timetree.org)
  131. tree = ape::read.tree("../../Evolution/phylogeny/species_latin_24.nwk")
  132. tree$tip.label = key$CommonName[match(gsub("_", " ", tree$tip.label), key$LatinName)]
  133. tree = ape::rotate(tree, node = c(25))
  134. plot(tree)
  135. saveRDS(tree, '../../Ortho_Objects/phylo.hs.pm.rds')
  136. # Pruned
  137. dendro = phylogram::as.dendrogram.phylo(tree)
  138. sorted.dendro = reorder(dendro, 1:length(tree$tip.label))
  139. dendro.hs.liz = dendextend::prune(sorted.dendro, c('Lamprey', 'Cat shark', 'Killifish', "Zebrafish", 'Goldfish', 'Newt', 'Axolotl'))
  140. dendro.hs.liz
  141. labels(dendro.hs.liz)
  142. plot(as.phylo(dendro.hs.liz))
  143. saveRDS(as.phylo(dendro.hs.liz), '../../Ortho_Objects/phylo.hs.liz.rds')
  144. ```
  145. ```{r, fig.height=2.5, fig.width=6}
  146. tree = readRDS('../../Ortho_Objects/phylo.hs.pm.rds')
  147. tree_fixed = tree
  148. tree_fixed$edge.length <- tree$edge.length / 2
  149. dendro = as.dendrogram(tree_fixed)
  150. labels(dendro) = species_names_pretty((labels(dendro)))
  151. # Sort by species order
  152. dendro = dendextend::rotate(dendro, rev(species.names.pretty))
  153. plot(dendro)
  154. # saveRDS(dendro, '../../Ortho_Objects/phylo.hs.pm.sorted.dendro.rds')
  155. library(ggdendro)
  156. ggdendrogram(dendro) +
  157. # coord_flip() +
  158. # scale_y_reverse(expand = c(0.2, 0))+
  159. # theme_classic()+
  160. ylab("Evolutionary distance (MYA)")+
  161. # theme(axis.text.x = element_text(size = 13, hjust = 1, vjust = 1, angle = 45), axis.ticks.length.y = unit(.25, "cm"))+
  162. scale_y_continuous(breaks = seq(0, 500, len = 6), expand = expansion(mult = c(0.01,0.01)))+ #expand = expansion(add = c(0,0.1)))+
  163. scale_x_discrete(expand = expansion(add = 0.6))+
  164. theme_cowplot()+
  165. theme(axis.line.x=element_blank(),
  166. axis.text.x=element_blank(),
  167. axis.ticks.x=element_blank(),
  168. axis.title.x=element_blank(),
  169. axis.title.y = element_text(angle = -90, hjust = 0.5),
  170. axis.text.y = element_text(angle = -90, hjust = 0.5),
  171. panel.grid.minor.x=element_blank(),
  172. panel.grid.major.x=element_blank())
  173. ggsave('../../figures/my_figs/fig-phylo-24.pdf', height=2.5, width=6)
  174. ```
  175. ```{r, fig.height=2.5, fig.width=6}
  176. dendro = readRDS('../../Ortho_Objects/phylo.hs.pm.sorted.dendro.rds')
  177. dd <- dendro_data(dendro)
  178. ggplot() +
  179. geom_segment(
  180. data = dd$segments,
  181. aes(x = x, y = y, xend = xend, yend = yend),
  182. linewidth = .75
  183. ) +
  184. ylab("Evolutionary distance (MYA)") +
  185. scale_y_continuous(
  186. breaks = seq(0, 500, length.out = 6),
  187. expand = expansion(mult = c(0.01, 0.01))
  188. ) +
  189. scale_x_discrete(
  190. expand = expansion(add = 0.6)
  191. ) +
  192. theme_cowplot() +
  193. theme(
  194. axis.line.y = element_line(linewidth = 0.75),
  195. axis.line.x = element_blank(),
  196. axis.title.x = element_blank(),
  197. axis.text.x = element_blank(),
  198. axis.ticks.x = element_blank(),
  199. axis.title.y = element_text(angle = -90, hjust = 0.5),
  200. axis.text.y = element_text(angle = -90, hjust = 0.5),
  201. panel.grid.major.x = element_blank(),
  202. panel.grid.minor.x = element_blank()
  203. )
  204. ggsave('../../figures/my_figs/fig-phylo-24.pdf', height=2.5, width=6)
  205. ```
  206. ## Quantification
  207. ```{r}
  208. # Save Catshark
  209. temp = readRDS('../../Full_Objects/Shark_full_v5.rds')
  210. temp$type = temp$annotated
  211. temp$animal = temp$orig.ident
  212. saveRDS(subset(temp, cell_class == 'AC'), '../../Species_Objects/SharkAC_v6.rds')
  213. # Save Axolotl
  214. temp = readRDS('../../Full_Objects/Axolotl_full_v3.rds')
  215. temp$type = temp$annotated
  216. temp$animal = temp$animal_group
  217. temp$species = 'Axolotl'
  218. saveRDS(subset(temp, cell_class == 'AC'), '../../Species_Objects/AxolotlAC_v6.rds')
  219. # Save Newt
  220. temp = readRDS('../../Full_Objects/Newt_full_v3.rds')
  221. temp$type = temp$annotated
  222. temp$animal = 'N1'
  223. temp$species = 'Newt'
  224. saveRDS(subset(temp, cell_class == 'AC'), '../../Species_Objects/NewtAC_v6.rds')
  225. # Save Killifish
  226. temp = readRDS('../../Species_Objects/Killifish_ncbiAC_v6.rds')
  227. temp$animal = temp$orig.file
  228. temp$classification = ifelse(temp$cell_class2 == 'gabaAC', 'GABA', 'Gly')
  229. saveRDS(temp, '../../Species_Objects/Killifish_ncbiAC_v6.rds')
  230. ```
  231. ```{r}
  232. objectList = ReadAmacrineData2()
  233. objectList$Zebrafish$animal = objectList$Zebrafish$sample
  234. objectList$Mouse$animal = objectList$Mouse$batch
  235. # If there is no enrichment info, set enrichment to none
  236. objectList = lapply(objectList, function(object) {
  237. if(!'enrichment' %in% colnames([email hidden])){
  238. object$enrichment = "NONE"
  239. }
  240. object
  241. })
  242. # Count total cells
  243. sum(sapply(objectList, function(object) ncol(object)))
  244. max(sapply(objectList, function(object) ncol(object)))
  245. ```
  246. ```{r, fig.height=6, fig.width=7}
  247. # nTypes.df = readRDS('metadata/nTypes.df.v2.rds')
  248. # PrettyBarplot(nTypes.df, x = 'species', y = 'nCells') + coord_flip()
  249. line.width = 0.5
  250. bar.width = 0.85
  251. nTypes.df = data.frame(species = factor(names(objectList), levels = names(objectList)),
  252. nClusters = sapply(objectList, function(object) length(unique(object$type))),
  253. nCells = sapply(objectList, function(object) ncol(object)),
  254. nReplicates = sapply(objectList, function(object) length(unique(object$animal))),
  255. nUMI = sapply(objectList, function(object) mean(object$nFeature_RNA)))
  256. # Use Yan et al. number of clusters for mouse
  257. nTypes.df$nClusters[nTypes.df$species == 'Mouse'] = 63
  258. nTypes.df$nClusters[nTypes.df$species == 'Macaque'] = 44
  259. nTypes.df$species2 = sapply(seq_along(nTypes.df$species), function(x) {
  260. if(x %% 2 == 0) paste0('', nTypes.df$species[[x]]) else paste0('', nTypes.df$species[[x]])
  261. }) %>% species_labels
  262. nTypes.df$species2 = factor(nTypes.df$species2, levels = unique(nTypes.df$species2))
  263. # coord_flip_discrete(ggbarplot(nTypes.df, x = 'species', y = 'nCells'), 'species')
  264. PrettyBarplot(flip_var(nTypes.df, 'species'), x = 'species', y = 'nCells', fill = 'species', color = 'black', width = bar.width) +
  265. # scale_y_continuous(name = '# of cells', labels = label_number(scale = 1e-3, suffix = "k"), expand = expansion(mult = c(0,0)))+
  266. # scale_y_continuous(name = '# of cells', transform = 'log10', expand = expansion(mult = c(0,0)))+
  267. # scale_y_log10(name = 'Number of\ncells', breaks = 10^(0:4),
  268. # # labels = comma,
  269. # labels = scales::trans_format("log10", scales::math_format(10^.x)),
  270. # minor_breaks = rep(1:9, times = 4) * 10^(rep(0:3, each = 9)),
  271. # expand = expansion(mult = c(0,0))) +
  272. scale_y_log10(
  273. name = 'Number of\ncells',
  274. # limits = c(10^(1), 10^(5)),
  275. # limits = c(10, NA),
  276. breaks = 10^(1:4),
  277. labels = scales::trans_format("log10", scales::math_format(10^.x)),
  278. minor_breaks = rep(1:9, times = 3) * 10^(rep(1:3, each = 9)),
  279. expand = expansion(mult = c(0, 0))
  280. )+
  281. # coord_cartesian(ylim = c(10, Inf))+
  282. annotation_logticks(sides = "b", outside = TRUE,
  283. short = unit(0.6,"mm"), mid = unit(0.5,"mm"),long = unit(1,"mm")) +
  284. # coord_cartesian(clip = 'off')+
  285. scale_fill_manual(values = species_palette3)+
  286. theme(axis.ticks.y = element_blank(),
  287. axis.text.y = element_blank(),
  288. axis.line = element_line(linewidth = line.width),
  289. # axis.text.x = element_text(angle = 90),
  290. # axis.title.x = element_text(angle = 180),
  291. axis.title.y = element_blank()
  292. )+
  293. coord_flip(clip = 'off')+
  294. NoLegend() |
  295. PrettyBarplot(flip_var(nTypes.df, 'species'), x = 'species', y = 'nUMI', fill = 'species', color = 'black', width = bar.width) +
  296. # scale_y_continuous(name = 'Number of cells', labels = label_number(scale = 1e-3, suffix = "k"), expand = expansion(mult = c(0,0)))+
  297. scale_fill_manual(values = species_palette3)+
  298. # ylab('Number of\nbiological\nreplicates')+
  299. ylab('Number of\ngenes detected')+
  300. theme(axis.ticks.y = element_blank(),
  301. axis.text.y = element_blank(),
  302. axis.ticks = element_line(linewidth = line.width),
  303. axis.line = element_line(linewidth = line.width),
  304. axis.title.y = element_blank(),
  305. # axis.text.x = element_text(angle = 90),
  306. # axis.title.x = element_text(angle = 180)
  307. )+
  308. coord_flip()+
  309. NoLegend() |
  310. PrettyBarplot(flip_var(nTypes.df, 'species2'), x = 'species2', y = 'nClusters', fill = 'species', color = 'black', width = bar.width) +
  311. # scale_y_continuous(name = 'Number of cells', labels = label_number(scale = 1e-3, suffix = "k"), expand = expansion(mult = c(0,0)))+
  312. scale_fill_manual(values = species_palette3)+
  313. scale_x_discrete(position = "top")+ # labels = sapply(1:24, function(x) ))+
  314. # scale_y_
  315. ylab('Number of\nnominal\nclusters')+
  316. geom_hline(yintercept = 0, linewidth = line.width)+
  317. theme(axis.title.y = element_blank(),
  318. axis.line = element_line(linewidth = line.width),
  319. # axis.text.x = element_text(angle = 90),
  320. axis.ticks = element_line(linewidth = line.width),
  321. axis.text.y.right = element_text(size = 12, margin = margin(l = 3), color = darken(rev(species_palette3), 0.1)),
  322. # axis.title.x = element_text(angle = 180)
  323. )+
  324. # axis.text.y.right = element_text(angle = 135, hjust = 1, vjust = 1))+# = element_text(angle = 135, hjust = 0, vjust = 0.5))+
  325. coord_flip(clip = 'off')+
  326. NoLegend()
  327. ggsave('../../figures/my_figs/species-cell-cluster-quant-tight.pdf', height = 6, width = 5)
  328. ```
  329. ```{r, fig.height=6, fig.width=7}
  330. # objectList = mclapply(speciesList, function(species) readRDS(paste0("../../Species_Objects/", species, "AC_v6.rds")), mc.cores = 1)
  331. # names(objectList) = speciesList
  332. merged.metadata = Reduce(rbind, lapply(objectList, function(object) [email hidden][,c("classification", "enrichment", "seurat_clusters", "type", 'animal')])) #"lit_type",
  333. merged.metadata$species = factor(rep(speciesList, sapply(objectList, ncol)), levels = speciesList)
  334. merged.metadata[,"enrichment"] = toupper(merged.metadata[,"enrichment"])
  335. merged.metadata$`Enrichment group` = gsub('\n', '', merged.metadata$enrichment)
  336. merged.metadata$`Enrichment group` = gsub('NONE', 'No enrichment', merged.metadata$`Enrichment group`)
  337. merged.metadata$`Enrichment group` = factor(merged.metadata$`Enrichment group`,
  338. levels = c('NEUN+', 'NEUN+CHX10-',
  339. 'CHX10+',
  340. 'NEUN-', 'NEUN-CHX10-', 'NEUN-CHX10+',
  341. 'CD90+',
  342. 'CD73-',
  343. 'No enrichment'))
  344. coord_flip_discrete(stackedBarGraph2(merged.metadata, x = 'species', y = 'Enrichment group', normalize = FALSE, border.color = 'black'), discrete_axis = 'Var1') +
  345. scale_fill_manual(values = ClusterPalette(c(3,3,1,4,4,4,5,2,6), vary.by = 0.2,
  346. colors = c('deeppink', 'orange', 'chartreuse1', 'cyan2', 'violet', 'antiquewhite2'), dark.first = FALSE)) +
  347. theme(axis.text.y = element_blank(), axis.title.y = element_blank(), axis.title.x = element_text()) +
  348. ArialFont()+
  349. scale_y_continuous(name = 'Number of cells', labels = label_number(scale = 1e-3, suffix = "k"), expand = expansion(mult = c(0,0)))
  350. ggsave('../../figures/my_figs/species-enrich-quant.pdf', height = 6, width = 7)
  351. ```
  352. Number of cells and number of nominal clusters
  353. ```{r, fig.height=6, fig.width=7}
  354. nTypes.df = readRDS('metadata/nTypes.df.v2.rds')
  355. nReplicates = apply(table(merged.metadata$animal, merged.metadata$species), 2, function(col) length(which(col > 0)))
  356. nTypes.df$nReplicates = nReplicates[match(nTypes.df$species, names(nReplicates))]
  357. saveRDS(nTypes.df, 'metadata/nTypes.df.v2.rds')
  358. ```
  359. ```{r, fig.height=5, fig.width=7}
  360. nTypes.df = readRDS('metadata/nTypes.df.v2.rds')
  361. # PrettyBarplot(nTypes.df, x = 'species', y = 'nCells') + coord_flip()
  362. library(ggplot2)
  363. library(scales)
  364. library(patchwork)
  365. log10_reverse <- trans_new(
  366. name = "log10-reverse",
  367. transform = function(x) -log10(x),
  368. inverse = function(x) 10^(-x),
  369. breaks = log_breaks(base = 10),
  370. format = math_format(10^.x)
  371. )
  372. species_order <- rev(unique(nTypes.df$species)) # reverse order for downward bars
  373. p1 <- PrettyBarplot(flip_var(nTypes.df, 'species'),
  374. x = 'species', y = 'nCells', fill = 'species',
  375. color = NA, width = 0.9) +
  376. # scale_y_log10(name = 'Number of\ncells', breaks = 10^(0:4),
  377. # labels = trans_format("log10", math_format(10^.x)),
  378. # minor_breaks = rep(1:9, times = 4) * 10^(rep(0:3, each = 9)),
  379. # expand = expansion(mult = c(0,0))) +
  380. scale_y_continuous(
  381. name = 'Number of\ncells',
  382. trans = log10_reverse,
  383. breaks = 10^(0:4),
  384. minor_breaks = rep(1:9, times = 4) * 10^(rep(0:3, each = 9)),
  385. expand = expansion(mult = c(0, 0))
  386. ) +
  387. annotation_logticks(sides = "l", outside = TRUE,
  388. short = unit(0.6,"mm"), mid = unit(0.5,"mm"), long = unit(1,"mm")) +
  389. scale_fill_manual(values = species_palette2) +
  390. scale_x_discrete(limits = species_order) +
  391. theme(#axis.ticks.y = element_blank(),
  392. axis.ticks.x = element_blank(),
  393. axis.title.x = element_blank(),
  394. axis.text.x = element_blank(),
  395. axis.text.y = element_text(),
  396. axis.line.y = element_line(),
  397. axis.title.y = element_text()) +
  398. # coord_flip(clip = 'off') +
  399. NoLegend()
  400. p2 <- PrettyBarplot(flip_var(nTypes.df, 'species'),
  401. x = 'species', y = 'nReplicates', fill = 'species',
  402. color = NA, width = 0.9) +
  403. scale_fill_manual(values = species_palette2) +
  404. ylab('Number of\nbiological\nreplicates') +
  405. scale_x_discrete(limits = species_order) +
  406. scale_y_continuous(trans = "reverse")+
  407. theme(#axis.ticks.y = element_blank(),
  408. axis.ticks.x = element_blank(),
  409. axis.text.y = element_text(),
  410. axis.line.y = element_line(),
  411. axis.title.y = element_text(),
  412. axis.text.x = element_blank(),
  413. axis.title.x = element_blank()) +
  414. # coord_flip() +
  415. NoLegend()
  416. p3 <- PrettyBarplot(flip_var(nTypes.df, 'species'),
  417. x = 'species', y = 'nClusters', fill = 'species',
  418. color = NA, width = 0.9) +
  419. scale_fill_manual(values = species_palette2) +
  420. scale_x_discrete(limits = species_order, position = "bottom") +
  421. scale_y_continuous(trans = "reverse")+
  422. ylab('Number of\nnominal\nclusters') +
  423. # geom_hline(yintercept = -0.5, linewidth = 1) +
  424. theme(axis.title.y = element_text(),
  425. axis.title.x = element_blank()) +
  426. # coord_flip() +
  427. NoLegend()
  428. # Combine plots vertically
  429. p1 / p2 / p3
  430. # ggsave('../../figures/my_figs/species-cell-cluster-quant.pdf', height = 5.4, width = 5)
  431. ```
  432. ## Manual annotation of select ACs
  433. ```{r, fig.height=8, fig.width=6}
  434. DotPlot3(objectList$Killifish, features = c('LOC107381579', 'slc5a7a', 'isl1a', 'slc17a8', 'prox1a'), group.by = 'annotated')
  435. # DotPlot3(objectList$Goldfish, features = toupper(c('slc5a7a', 'slc17a8', 'prox1a', 'dab1')), group.by = 'type')
  436. DotPlot3(objectList$CatShark, features = c('chata', 'slc5a7a', 'slc17a8', 'prox1a'), group.by = 'annotated')
  437. DotPlot3(objectList$Axolotl, features = c('CHAT', 'SLC5A7', 'SLC17A8', 'GJD2', 'PROX1', 'NFIA'), group.by = 'annotated')
  438. DotPlot3(objectList$Newt, features = c('CHAT', 'SLC5A7', 'SLC17A8', 'GJD2', 'PROX1', 'NFIA'), group.by = 'annotated')
  439. objectList$Axolotl = AssignAnnotations(objectList$Axolotl, list(SAC = 'gabaAC-1', VG3 = 'glyAC-12', A2 = 'glyAC-3'),
  440. use = 'annotated')
  441. objectList$Newt = AssignAnnotations(objectList$Newt, list(SAC = 'gabaAC-1', VG3 = 'glyAC-7', A2 = 'glyAC-21'),
  442. use = 'annotated')
  443. objectList$Killifish = AssignAnnotations(objectList$Killifish, list(SAC = 'AC-1'),
  444. use = 'annotated')
  445. objectList$CatShark = AssignAnnotations(objectList$CatShark, list(SAC = 'gabaAC-3', VG3 = 'glyAC-13'),
  446. use = 'annotated')
  447. # None found in goldfish by manual annotation
  448. objectList2 = objectList[!names(objectList) %in% c('Goldfish')]
  449. # Remove zebrafish types found by SAMap integration
  450. objectList2$Zebrafish$lit_type[objectList2$Zebrafish$lit_type == 'A2'] = NA
  451. # Remove rhabdomys A2 which doesn't express markers
  452. objectList2$Rhabdomys$lit_type[objectList2$Rhabdomys$lit_type == 'A2'] = NA
  453. # Keep lamprey SAC
  454. objectList2$Lamprey$lit_type[objectList2$Lamprey$lit_type == 'VG3'] = NA
  455. # marker.df = data.frame(matrix(rep(c('CHAT', 'SLC5A7', 'ISL1', 'SOX2', 'SLC18A3', 'GJD2', 'PROX1', 'NFIA', 'DAB1', 'SLC17A8', 'SDK2'), 20), ncol = 20)) %>% setNames(speciesList)
  456. marker.df = data.frame(matrix(rep(c('CHAT', 'SLC5A7', 'ISL1',
  457. 'GJD2', 'PROX1', 'NFIA',
  458. 'SLC17A8', 'SDK2', 'NXPH1'), length(objectList2)),
  459. ncol = length(objectList2))) %>% setNames(names(objectList2))
  460. marker.df$row_annotation = c(rep('SAC', 3), rep('A2', 3), rep('VG3', 3))
  461. marker.df
  462. # Modify symbols for killifish and catshark, which were not converted
  463. marker.df$Killifish = c('LOC107381579', 'slc5a7a', 'isl1a', 'gjd2a', 'prox1a', 'nfia', 'slc17a8', 'sdk2', 'nxph1')
  464. marker.df$CatShark = c('chata', 'slc5a7a', 'isl1a', 'gjd2a', 'prox1a', 'nfia', 'slc17a8', 'sdk2', 'nxph1')
  465. # Subset to annotated cells
  466. objectList2 = lapply(objectList2, function(object) {
  467. object$annotated = as.character(object$type)
  468. object$annotated[object$lit_type %in% c('SAC', 'A2', 'VG3')] = object$lit_type[object$lit_type %in% c('SAC', 'A2', 'VG3')]
  469. object
  470. })
  471. # species_palette = colorRampPalette(as.character(paletteer::paletteer_d("lisa::OskarSchlemmer", 5)))(19) %>% setNames(speciesList)
  472. # species_palette = colorspace::darken(rainbow(19), 0.2) %>% setNames(speciesList)
  473. pdf('../../figures/my_figs/manual-annotation-3.pdf', width=5, height=7, family = 'ArialMT')
  474. SAMapHeatmap2(objectList2,
  475. marker.df,
  476. type_palette = rep('white', 3) %>% setNames(c('SAC', 'A2', 'VG3')),
  477. #colorspace::lighten(AcPalette2(3) %>% setNames(c('SAC', 'A2', 'VG3')), 0.2),
  478. #colorspace::lighten(c('blue', 'orange2', 'deeppink3'), 0.5) %>% setNames(c('SAC', 'A2', 'VG3')),
  479. species_palette = species_palette3, #colorspace::darken(AcPalette2(length(speciesList)), 0) %>% setNames(speciesList),
  480. species.use = names(objectList2), #names(species_ids),
  481. types.use = c('SAC', 'A2', 'VG3'),
  482. # font.size = 12,
  483. show_annotation_legend = FALSE,
  484. show_row_names = FALSE,
  485. show_column_names = TRUE,
  486. # pseudocount = 10,
  487. font.family = 'ArialMT',
  488. column_names_gp = gpar(fontface = "italic", fontsize = 10),
  489. row_title_gp = gpar(fontsize = 30),
  490. row_title_rot = 45,
  491. column_names_rot = 45,
  492. names.show = 'Human',
  493. # width = unit(4, "in"),
  494. rotate = TRUE,
  495. dotplot = TRUE,
  496. dot.scale.factor = 0.18)
  497. dev.off()
  498. ```
  499. ## Amniote integration
  500. ```{r}
  501. types.to.consider = c('A2', 'SAC', 'VG3')
  502. vertebrateAC_unintegrated = readRDS("../../Ortho_Objects/vertebrateAC_unintegrated.rds")
  503. vertebrateAC_unintegrated$species_littype = str_split_fixed(vertebrateAC_unintegrated$species_type, "_", 2)[,2]
  504. vertebrateAC_unintegrated$species_littype[!vertebrateAC_unintegrated$species_littype %in% types.to.consider] = "Other"
  505. vertebrateAC_unintegrated$species_littype = factor(vertebrateAC_unintegrated$species_littype, levels = c('SAC', 'A2', 'VG3', 'Other'))
  506. vertebrateAC_integrated = readRDS("../../Ortho_Objects/vertebrateAC_seurat.rds")
  507. vertebrateAC_integrated$species_littype = str_split_fixed(vertebrateAC_integrated$species_type, "_", 2)[,2]
  508. vertebrateAC_integrated$species_littype[!vertebrateAC_integrated$species_littype %in% types.to.consider] = "Other"
  509. vertebrateAC_integrated$species_littype = factor(vertebrateAC_integrated$species_littype, levels = c('SAC', 'A2', 'VG3', 'Other'))
  510. # Remove cluster 0 (poorly integrated cells)
  511. vertebrateAC_integrated = subset(vertebrateAC_integrated, seurat_clusters == 0, invert = TRUE)
  512. vertebrateAC_shuffled = readRDS("../../Ortho_Objects/vertebrateAC_shuffled_row_entries.rds")
  513. vertebrateAC_shuffled$species_littype = str_split_fixed(vertebrateAC_shuffled$species_type, "_", 2)[,2]
  514. vertebrateAC_shuffled$species_littype[!vertebrateAC_shuffled$species_littype %in% types.to.consider] = "Other"
  515. vertebrateAC_shuffled$species_littype = factor(vertebrateAC_shuffled$species_littype, levels = c('SAC', 'A2', 'VG3', 'Other'))
  516. ortho_path = '../../Ortho_Objects/'
  517. vertebrateAC_iLISI = readRDS(paste0(ortho_path, 'vertebrateAC_iLISI.rds'))
  518. vertebrateAC_seurat_iLISI = readRDS(paste0(ortho_path, 'vertebrateAC_seurat_iLISI.rds'))
  519. shuffledAC_iLISI = readRDS(paste0(ortho_path, 'shuffledAC_iLISI.rds'))
  520. vertebrateAC_cLISI = readRDS(paste0(ortho_path, 'vertebrateAC_cLISI.rds'))
  521. vertebrateAC_seurat_cLISI = readRDS(paste0(ortho_path, 'vertebrateAC_seurat_cLISI.rds'))
  522. shuffledAC_cLISI = readRDS(paste0(ortho_path, 'shuffledAC_cLISI.rds'))
  523. ```
  524. ### Simple for main figure
  525. ```{r, fig.height=4, fig.width=12}
  526. # types.to.consider = c('A2', 'SAC', 'VG3')
  527. # vertebrateAC_unintegrated = readRDS("../../Ortho_Objects/vertebrateAC_unintegrated.rds")
  528. # vertebrateAC_unintegrated$species_littype = str_split_fixed(vertebrateAC_unintegrated$species_type, "_", 2)[,2]
  529. # vertebrateAC_unintegrated$species_littype[!vertebrateAC_unintegrated$species_littype %in% types.to.consider] = "Other"
  530. # vertebrateAC_unintegrated$species_littype = factor(vertebrateAC_unintegrated$species_littype, levels = c('SAC', 'A2', 'VG3', 'Other'))
  531. #
  532. # vertebrateAC_integrated = readRDS("../../Ortho_Objects/vertebrateAC_seurat.rds")
  533. # vertebrateAC_integrated$species_littype = str_split_fixed(vertebrateAC_integrated$species_type, "_", 2)[,2]
  534. # vertebrateAC_integrated$species_littype[!vertebrateAC_integrated$species_littype %in% types.to.consider] = "Other"
  535. # vertebrateAC_integrated$species_littype = factor(vertebrateAC_integrated$species_littype, levels = c('SAC', 'A2', 'VG3', 'Other'))
  536. #
  537. # ortho_path = '../../Ortho_Objects/'
  538. # shuffledAC_cLISI = readRDS(paste0(ortho_path, 'shuffledAC_cLISI.rds'))
  539. # shuffledAC_cLISI$species_littype = factor(shuffledAC_cLISI$species_littype, levels = c('SAC', 'A2', 'VG3', 'Other'))
  540. umap.params = list(shuffle = TRUE, raster.dpi = 1000, pad = 0.1, pt.size = 0.001, pt.alpha = 1, nbreaks = 30, rasterise = TRUE)
  541. theme_umap(
  542. do.call(PrettyUmap2, c(list(vertebrateAC_unintegrated,
  543. group.by = "species",
  544. color.by = 'species_littype',
  545. title = 'Unintegrated',
  546. cols = lighten(c(AcPalette3(3), 'grey'), 0.3),
  547. label = TRUE),
  548. umap.params))
  549. ) + NoLegend() |
  550. theme_umap(
  551. do.call(PrettyUmap2, c(list(vertebrateAC_integrated,
  552. group.by = "species_littype",
  553. # color.by = "species_littype",
  554. title = 'Integrated',
  555. cols = lighten(c(AcPalette3(3), 'grey'), 0.3),
  556. label = TRUE,
  557. geom.label = geom_text_repel,
  558. box.padding = 1), umap.params))
  559. ) + NoLegend() |
  560. theme_umap(
  561. do.call(PrettyUmap2, c(list(vertebrateAC_shuffled,
  562. group.by = "species_littype",
  563. # color.by = "species_littype",
  564. title = 'Shuffled + integrated',
  565. cols = lighten(c(AcPalette3(3), 'grey'), 0.3),
  566. label = FALSE), umap.params))
  567. ) + NoLegend()
  568. # ggsave("../../figures/my_figs/fig-tetrapod-integration-simple.pdf", width=8, height=4)
  569. # ggsave("../../figures/my_figs/fig-tetrapod-integration-simple.png", width=8, height=4)
  570. ggsave("../../figures/my_figs/fig-tetrapod-integration-supp.png", width=11, height=4)
  571. ```
  572. ### Just mammals
  573. ```{r, fig.height=4, fig.width=8}
  574. ac.ortho = LoadACOrtho()
  575. ac.ortho$orthotype.no = gsub('oAC|\\*', '', ExtractString(ac.ortho$orthotype, after = ' '))
  576. # ac.ortho.no.tetrapods = subset(ac.ortho, species %in% c("Chicken", "Lizard"), invert = TRUE)
  577. types.to.consider = c('A2', 'SAC', 'VG3')
  578. ac.ortho$species_littype[!ac.ortho$species_littype %in% types.to.consider] = "Other"
  579. ac.ortho$species_littype = factor(ac.ortho$species_littype, levels = c('SAC', 'A2', 'VG3', 'Other'))
  580. umap.params = list(shuffle = TRUE, raster.dpi = 1000, pad = 0.1,
  581. pt.size = 0.001, pt.alpha = 1, nbreaks = 30, rasterise = TRUE)
  582. theme_umap(
  583. do.call(PrettyUmap2, c(list(ac.ortho,
  584. group.by = "orthotype.no",
  585. color.by = "species",
  586. cols = species_palette2,
  587. geom.label = geom_label,
  588. color = 'black', fill = 'white',
  589. label.size = 0, alpha = 0.5,
  590. label.padding = unit(0, "lines"),
  591. label.r = unit(0.2, "lines"),
  592. label = TRUE), umap.params))
  593. ) + NoLegend() + theme(plot.title = element_blank()) |
  594. theme_umap(
  595. do.call(PrettyUmap2, c(list(ac.ortho,
  596. group.by = "species_littype",
  597. # color.by = "species_littype",
  598. cols = lighten(c(AcPalette3(3), 'grey'), 0.3),
  599. label = TRUE), umap.params))
  600. ) + NoLegend() + theme(plot.title = element_blank())
  601. # ggsave("../../figures/my_figs/fig-tetrapod-integration-mammals.pdf", width=8, height=4)
  602. ggsave("../../figures/my_figs/fig-tetrapod-integration-amniotes.pdf", width=8, height=4)
  603. ```
  604. ### Without shuffled control
  605. ```{r, fig.width=9, fig.height=7.5}
  606. # raster.dpi = 1024
  607. separator = 0
  608. # nbreaks = 30
  609. umap.params = list(shuffle = TRUE, raster.dpi = 1000, pad = 0.1, pt.size = 0.001, pt.alpha = 1, nbreaks = 30, rasterise = TRUE)
  610. LISI_umap <- plot_grid(
  611. theme_umap(
  612. do.call(PrettyUmap2, c(list(vertebrateAC_unintegrated, group.by = "species", label = TRUE, cols = colorspace::lighten(species_palette2, 0.3)), umap.params)),
  613. title = "Unintegrated"
  614. ) + NoLegend(), #+ theme(plot.title = element_blank()),
  615. NULL,
  616. theme_umap(
  617. do.call(PrettyUmap2, c(list(vertebrateAC_integrated, group.by = "species", label = FALSE, cols = colorspace::lighten(species_palette2, 0.3)), umap.params)),
  618. title = "Integrated"
  619. ) + NoLegend(), #+ theme(plot.title = element_blank()),
  620. theme_umap(
  621. do.call(PrettyUmap2, c(list(vertebrateAC_unintegrated, group.by = "species_littype", cols = lighten(c(AcPalette3(3), 'grey'), 0.3), label = FALSE), umap.params))
  622. ) + NoLegend() + theme(plot.title = element_blank()),
  623. NULL,
  624. theme_umap(
  625. do.call(PrettyUmap2, c(list(vertebrateAC_integrated, group.by = "species_littype", cols = lighten(c(AcPalette3(3), 'grey'), 0.3), label = TRUE), umap.params))
  626. ) + NoLegend() + theme(plot.title = element_blank()),
  627. nrow = 2, ncol = 3,
  628. rel_heights = c(1.1, 1),
  629. rel_widths = c(1, separator, 1, separator, 1),
  630. align = 'v', axis = 'lr'
  631. )
  632. # LISI_umap
  633. iLISI.df = data.frame(unintegrated = vertebrateAC_iLISI$normalized.iLISI,
  634. integrated = vertebrateAC_seurat_iLISI$normalized.iLISI,
  635. shuffled = shuffledAC_iLISI$normalized.iLISI)
  636. cLISI.df = data.frame(unintegrated = subset(vertebrateAC_cLISI, species_littype %in% c("A2", "SAC", "VG3"))$normalized.cLISI,
  637. integrated = subset(vertebrateAC_seurat_cLISI, species_littype %in% c("A2", "SAC", "VG3"))$normalized.cLISI,
  638. shuffled = subset(shuffledAC_cLISI, species_littype %in% c("A2", "SAC", "VG3"))$normalized.cLISI)
  639. boxplots = plot_grid(
  640. NULL,
  641. ggplot(reshape2::melt(iLISI.df), aes(x = variable, y = value, color = variable))+
  642. geom_boxplot(linetype = "dashed", outlier.shape = NA) +
  643. stat_boxplot(aes(ymin = ..lower.., ymax = ..upper..), outlier.shape = NA) +
  644. stat_boxplot(geom = "errorbar", aes(ymin = ..ymax..), width = 0.5) +
  645. stat_boxplot(geom = "errorbar", aes(ymax = ..ymin..), width = 0.5) +
  646. ylab("Species mixing (iLISI)")+
  647. # ggtitle("Mixing of species")+
  648. theme_cowplot()+
  649. theme(axis.text.x = element_blank(), legend.position = "none", axis.title.x = element_blank()),
  650. NULL,
  651. ggplot(reshape2::melt(cLISI.df), aes(x = variable, y = value, color = variable))+
  652. geom_boxplot(linetype = "dashed", outlier.shape = NA) +
  653. stat_boxplot(aes(ymin = ..lower.., ymax = ..upper..), outlier.shape = NA) +
  654. stat_boxplot(geom = "errorbar", aes(ymin = ..ymax..), width = 0.5) +
  655. stat_boxplot(geom = "errorbar", aes(ymax = ..ymin..), width = 0.5) +
  656. ylab("Cell type mixing (cLISI)")+
  657. xlab(NULL)+
  658. # ggtitle("Mixing of cell types")+
  659. theme_cowplot()+
  660. theme(legend.position = "none")+
  661. RotatedAxis(),
  662. nrow = 4, rel_heights = c(0.2, 1, 0.2, 1.25), align = "v"
  663. )
  664. lisi_summary = plot_grid(
  665. LISI_umap,
  666. # plot_grid(iLISI_umap, plot_grid(cLISI_umap, NULL, nrow = 1, rel_widths = c(1,0.03)), nrow = 2, rel_heights = c(1,1)),
  667. NULL,
  668. boxplots,
  669. ncol = 3,
  670. rel_widths = c(4, 0.1, 1))
  671. lisi_summary
  672. # ggsave("../../figures/my_figs/LISI-summary-cairo.pdf", width=14.5, height=7.5, device = cairo_pdf)
  673. ggsave("../../figures/my_figs/LISI-summary-small.pdf", width=11, height=7.5)
  674. ```
  675. ### Just boxplots
  676. ```{r, fig.height=4, fig.width=4}
  677. #' Run amniote integration chunk to load files
  678. iLISI.df = data.frame(Unintegrated = vertebrateAC_iLISI$normalized.iLISI,
  679. Integrated = vertebrateAC_seurat_iLISI$normalized.iLISI,
  680. Shuffled = shuffledAC_iLISI$normalized.iLISI)
  681. cLISI.df = data.frame(Unintegrated = subset(vertebrateAC_cLISI, species_littype %in% c("A2", "SAC", "VG3"))$normalized.cLISI,
  682. Integrated = subset(vertebrateAC_seurat_cLISI, species_littype %in% c("A2", "SAC", "VG3"))$normalized.cLISI,
  683. Shuffled = subset(shuffledAC_cLISI, species_littype %in% c("A2", "SAC", "VG3"))$normalized.cLISI)
  684. plot_grid(
  685. ggplot(reshape2::melt(iLISI.df), aes(x = factor(variable, levels = rev(c('Unintegrated', 'Integrated', 'Shuffled'))), y = value, color = variable))+
  686. geom_boxplot(linetype = "dashed", outlier.shape = NA) +
  687. stat_boxplot(aes(ymin = ..lower.., ymax = ..upper..), outlier.shape = NA) +
  688. stat_boxplot(geom = "errorbar", aes(ymin = ..ymax..), width = 0.5) +
  689. stat_boxplot(geom = "errorbar", aes(ymax = ..ymin..), width = 0.5) +
  690. scale_color_manual(values = c(Shuffled = '#4646FD', Integrated = '#A63FE4', Unintegrated = 'darkgrey'))+
  691. ylab("Species mixing (iLISI)")+
  692. # ggtitle("Mixing of species")+
  693. theme_cowplot()+
  694. coord_flip()+
  695. RotatedAxis()+
  696. theme(legend.position = "none", axis.title.y = element_blank()),
  697. ggplot(reshape2::melt(cLISI.df), aes(x = factor(variable, levels = rev(c('Unintegrated', 'Integrated', 'Shuffled'))), y = value, color = variable))+
  698. geom_boxplot(linetype = "dashed", outlier.shape = NA) +
  699. stat_boxplot(aes(ymin = ..lower.., ymax = ..upper..), outlier.shape = NA) +
  700. stat_boxplot(geom = "errorbar", aes(ymin = ..ymax..), width = 0.5) +
  701. stat_boxplot(geom = "errorbar", aes(ymax = ..ymin..), width = 0.5) +
  702. scale_color_manual(values = c(Shuffled = '#4646FD', Integrated = '#A63FE4', Unintegrated = 'darkgrey'))+
  703. ylab("Cell type mixing (cLISI)")+
  704. xlab(NULL)+
  705. # ggtitle("Mixing of cell types")+
  706. theme_cowplot()+
  707. theme(legend.position = "none")+
  708. coord_flip()+
  709. RotatedAxis(),
  710. ncol = 1,
  711. align = "v", axis = 'lr'
  712. )
  713. ggsave("../../figures/my_figs/LISI-boxplots.pdf", width=3.5, height=4)
  714. ```
  715. ### With shuffled control
  716. ```{r, fig.width=14.5, fig.height=7.5}
  717. # raster.dpi = 1024
  718. separator = -0.3
  719. # nbreaks = 30
  720. umap.params = list(shuffle = TRUE, raster.dpi = 1000, pad = 0.1, pt.size = 0.001, pt.alpha = 1, nbreaks = 30, label = FALSE, rasterise = TRUE)
  721. LISI_umap <- plot_grid(
  722. theme_umap(
  723. do.call(PrettyUmap2, c(list(vertebrateAC_unintegrated, group.by = "species"), umap.params)),
  724. title = "Unintegrated"
  725. ) + NoLegend(), #+ theme(plot.title = element_blank()),
  726. NULL,
  727. theme_umap(
  728. do.call(PrettyUmap2, c(list(vertebrateAC_integrated, group.by = "species"), umap.params)),
  729. title = "Integrated"
  730. ) + NoLegend(), #+ theme(plot.title = element_blank()),
  731. NULL,
  732. theme_umap(
  733. do.call(PrettyUmap2, c(list(vertebrateAC_shuffled, group.by = "species", show.legend = TRUE), umap.params)),
  734. title = "Integrated & shuffled"
  735. ) + theme(legend.key.height = unit(1, "lines")) +
  736. guides(color = guide_legend(override.aes = list(size = 3))),
  737. theme_umap(
  738. do.call(PrettyUmap2, c(list(vertebrateAC_unintegrated, group.by = "species_littype", cols = c(AcPalette2(4)[1:3], 'grey')), umap.params))
  739. ) + NoLegend() + theme(plot.title = element_blank()),
  740. NULL,
  741. theme_umap(
  742. do.call(PrettyUmap2, c(list(vertebrateAC_integrated, group.by = "species_littype", cols = c(AcPalette2(4)[1:3], 'grey')), umap.params))
  743. ) + NoLegend() + theme(plot.title = element_blank()),
  744. NULL,
  745. theme_umap(
  746. do.call(PrettyUmap2, c(list(vertebrateAC_shuffled, group.by = "species_littype", show.legend = TRUE, cols = c(AcPalette2(4)[1:3], 'grey')), umap.params))
  747. ) + theme(plot.title = element_blank(), legend.key.height = unit(1, "lines")) +
  748. guides(color = guide_legend(override.aes = list(size = 3))),
  749. nrow = 2, ncol = 5,
  750. rel_heights = c(1.1, 1),
  751. rel_widths = c(1, separator, 1, separator, 1),
  752. align = 'v', axis = 'lr'
  753. )
  754. # LISI_umap
  755. iLISI.df = data.frame(unintegrated = vertebrateAC_iLISI$normalized.iLISI,
  756. integrated = vertebrateAC_seurat_iLISI$normalized.iLISI,
  757. shuffled = shuffledAC_iLISI$normalized.iLISI)
  758. cLISI.df = data.frame(unintegrated = subset(vertebrateAC_cLISI, species_littype %in% c("A2", "SAC", "VG3"))$normalized.cLISI,
  759. integrated = subset(vertebrateAC_seurat_cLISI, species_littype %in% c("A2", "SAC", "VG3"))$normalized.cLISI,
  760. shuffled = subset(shuffledAC_cLISI, species_littype %in% c("A2", "SAC", "VG3"))$normalized.cLISI)
  761. boxplots = plot_grid(
  762. NULL,
  763. ggplot(reshape2::melt(iLISI.df), aes(x = variable, y = value, color = variable))+
  764. geom_boxplot(linetype = "dashed", outlier.shape = NA) +
  765. stat_boxplot(aes(ymin = ..lower.., ymax = ..upper..), outlier.shape = NA) +
  766. stat_boxplot(geom = "errorbar", aes(ymin = ..ymax..), width = 0.5) +
  767. stat_boxplot(geom = "errorbar", aes(ymax = ..ymin..), width = 0.5) +
  768. ylab("Species mixing (iLISI)")+
  769. # ggtitle("Mixing of species")+
  770. theme_cowplot()+
  771. theme(axis.text.x = element_blank(), legend.position = "none", axis.title.x = element_blank()),
  772. NULL,
  773. ggplot(reshape2::melt(cLISI.df), aes(x = variable, y = value, color = variable))+
  774. geom_boxplot(linetype = "dashed", outlier.shape = NA) +
  775. stat_boxplot(aes(ymin = ..lower.., ymax = ..upper..), outlier.shape = NA) +
  776. stat_boxplot(geom = "errorbar", aes(ymin = ..ymax..), width = 0.5) +
  777. stat_boxplot(geom = "errorbar", aes(ymax = ..ymin..), width = 0.5) +
  778. ylab("Cell type mixing (cLISI)")+
  779. xlab(NULL)+
  780. # ggtitle("Mixing of cell types")+
  781. theme_cowplot()+
  782. theme(legend.position = "none")+
  783. RotatedAxis(),
  784. nrow = 4, rel_heights = c(0.2, 1, 0.2, 1.25), align = "v"
  785. )
  786. lisi_summary = plot_grid(
  787. LISI_umap,
  788. # plot_grid(iLISI_umap, plot_grid(cLISI_umap, NULL, nrow = 1, rel_widths = c(1,0.03)), nrow = 2, rel_heights = c(1,1)),
  789. NULL,
  790. boxplots,
  791. ncol = 3,
  792. rel_widths = c(6, 0.1, 1))
  793. # lisi_summary
  794. # ggsave("../../figures/my_figs/LISI-summary-cairo.pdf", width=14.5, height=7.5, device = cairo_pdf)
  795. ggsave("../../figures/my_figs/LISI-summary.pdf", width=14.5, height=7.5)
  796. ```
  797. ```{r LISI-summary, fig.width=15, fig.height=8.5}
  798. ggsave("../../figures/my_figs/LISI-summary-cairo.pdf", width=14.5, height=7.5, device = cairo_pdf)
  799. ggsave("../../figures/my_figs/LISI-summary.pdf", width=14.5, height=7.5)
  800. ```
  801. ## AC orthotypes
  802. ```{r}
  803. ac.ortho = LoadACOrtho()
  804. ```
  805. ```{r, fig.height=5, fig.width=5}
  806. # pdf('../../figures/my_figs/umap-orthotypes.pdf', height = 4, width = 4.5) # family="ArialMT")
  807. TitlePlot(PrettyUmap2(ac.ortho, group.by = 'type_no', nbreaks = 30, pt.size = 0.2,
  808. raster.dpi = 1000, cols = type_cols2.no,
  809. geom.label = geom_label, color = 'black', fill = 'white',
  810. label.size = 0, alpha = 0.2, label.padding = unit(0, "lines"),
  811. label.r = unit(0.2, "lines")), #label.size = NA, label.r = unit(0, "lines"))
  812. title = '42 unsupervised clusters')
  813. # dev.off()
  814. ```
  815. ## Species composition
  816. ```{r, fig.height=5, fig.width=9}
  817. # stackedBarGraph2(ac.ortho, 'type', 'species', border.color = 'black') +
  818. # theme(text = element_text(family = 'ArialMT'), axis.text.x = element_text(size = 8)) +
  819. # ArialFont()+
  820. # scale_fill_manual(name = 'Species', values = lighten(species_palette2, 0.2))
  821. # ggsave('../../figures/my_figs/figS_species-composition-1.pdf', height=2.5, width=9)
  822. ```
  823. ```{r, fig.height=6, fig.width=12}
  824. # ac.ortho$orthotype_no = factor(as.character((gsub('\\*', '', ExtractString(ac.ortho$orthotype, after = ' ')))),
  825. # levels = paste0('oAC', 1:42))
  826. # coord_flip_discrete(
  827. # TitlePlot(stackedBarGraph2(ac.ortho, 'orthotype_no', 'species', border.color = 'black'), 'Proportion') +
  828. # # scale_x_discrete(labels = function(x) str_split_fixed(gsub('*', '', x), '_', 2)[,1])+
  829. # theme(text = element_text(family = 'ArialMT'), axis.text.y = element_text(size = 10)) +
  830. # ArialFont()+
  831. # xlab(NULL) + ylab(NULL)+
  832. # scale_fill_manual(name = 'Species', values = lighten(species_palette2, 0.2)), discrete_axis = 'Var1')
  833. # stackedBarGraph2(ac.ortho, 'type', 'species', border.color = NA) +
  834. # # scale_x_discrete(labels = function(x) str_split_fixed(gsub('*', '', x), '_', 2)[,1])+
  835. # theme(text = element_text(family = 'ArialMT'), axis.text.y = element_text(size = 10)) +
  836. # ArialFont()+
  837. # xlab(NULL) + ylab('y')+
  838. # scale_fill_manual(name = 'Species', values = lighten(species_palette2, 0.2)) + coord_flip()
  839. TitlePlot(stackedBarGraph2(ac.ortho, 'orthotype', 'species', border.color = 'black'), 'Species composition') +
  840. # scale_x_discrete(labels = function(x) str_split_fixed(gsub('*', '', x), '_', 2)[,1])+
  841. theme(text = element_text(family = 'ArialMT'), axis.text.y = element_text(size = 10)) +
  842. ArialFont()+
  843. xlab(NULL) +
  844. ylab('Percent')+
  845. theme(legend.position = 'bottom')+
  846. scale_fill_manual(name = 'Species', values = lighten(species_palette2, 0.2))
  847. ggsave('../../figures/my_figs/figS_species-composition-1.pdf')
  848. ```
  849. ## Precision and recall across species
  850. ```{r, fig.height=6, fig.width=6}
  851. # ac.ortho = readRDS('../../Ortho_Objects/vertebrateAC_BIGSEURAT.rds')
  852. vertebrateAC = ac.ortho
  853. vertebrateAC = AssignAnnotations(ac.ortho, list(SAC = 8, A2 = 22, VG3 = 27), use = 'type_no')
  854. # Ferret SACs post hoc
  855. [email hidden][WhichCells(PositiveCell(subset(vertebrateAC, species == 'Ferret'), features = 'SLC5A7', return.object = TRUE), expr = positive),'species_littype'] = 'SAC'
  856. raw_tables = lapply(speciesList.liz, function(this.species) {
  857. lapply(KNOWNTYPES, function(type) {
  858. # if(this.species == 'Ferret' & type == 'SAC') {
  859. # matrix(NA, nrow = 2, ncol = 2)
  860. # } else {
  861. message(paste0('working on ', this.species, ' and ', type))
  862. lit_types = vertebrateAC$lit_type[vertebrateAC$species == this.species]
  863. species_littype = vertebrateAC$species_littype[vertebrateAC$species == this.species]
  864. lit_types[is.na(lit_types)] = 'other'
  865. raw_table = table(lit_types == type, species_littype == type)[2:1,2:1]
  866. raw_table
  867. # }
  868. })
  869. })
  870. res = lapply(unlist(raw_tables, recursive = FALSE), EvaluateModel)
  871. res
  872. # make a matrix
  873. precision = matrix(sapply(res, function(x) x$precision),
  874. nrow = length(speciesList.liz),
  875. ncol = 3,
  876. dimnames = list(speciesList.liz, KNOWNTYPES),
  877. byrow = TRUE)
  878. recall = matrix(sapply(res, function(x) x$recall),
  879. nrow = length(speciesList.liz),
  880. ncol = 3,
  881. dimnames = list(speciesList.liz, KNOWNTYPES),
  882. byrow = TRUE)
  883. # barplot(t(precision))
  884. # barplot(t(recall))
  885. metrics.df = rbind(reshape2::melt(precision) %>% mutate(group = 'precision'),
  886. reshape2::melt(recall) %>% mutate(group = 'recall')) %>%
  887. setNames(c('Species', 'Type', 'Value', 'Metric'))
  888. # coord_flip_discrete(ggbarplot(subset(metrics.df, Metric == 'precision'), x = 'Species', y = 'Value', fill = 'Type', position = position_dodge()), discrete_axis = 'Species')
  889. metrics.df$Species = factor(factor(metrics.df$Species, levels = rev(phylogenetic_order)))
  890. # Subset to mammals
  891. # metrics.df = subset(metrics.df, Species %in% species_metadata$Species[1:15]) # leave all species in
  892. TitlePlot(ggbarplot(subset(metrics.df, Metric == 'precision'),
  893. x = 'Species', y = 'Value', fill = 'Type', color = 'black',
  894. position = position_dodge(width = 0.7)), title = 'Precision') +
  895. coord_flip() + NoLegend() + #RotatedAxis() +
  896. ylab(NULL) + xlab(NULL) +
  897. scale_y_continuous(expand = expansion(mult = c(0,0.1)), labels = c(0, '', '', '', 1)) |
  898. TitlePlot(ggbarplot(subset(metrics.df, Metric == 'recall'), x = 'Species', y = 'Value', fill = 'Type',
  899. position = position_dodge(width = 0.7), legend = "right", color = 'black'), 'Recall') +
  900. coord_flip() + #RotatedAxis() +
  901. ylab(NULL) + scale_y_continuous(expand = expansion(mult = c(0,0.1)), labels = c(0, '', '', '', 1)) +
  902. ArialFont() + theme(axis.text.y = element_blank(), axis.title.y = element_blank()) #+NoLegend()
  903. ggsave('../../figures/my_figs/fig-precision-recall.pdf', height = 6, width = 4.5)
  904. # Confidence intervals
  905. paste0(round(t.test(subset(metrics.df, Metric == 'precision')$Value)$conf.int, 2), collapse = '-')
  906. paste0(round(t.test(subset(metrics.df, Metric == 'recall')$Value)$conf.int, 2), collapse = '-')
  907. ```
  908. Averaged across species
  909. ```{r}
  910. vertebrateAC = AssignAnnotations(vertebrateAC, list(SAC = 8, A2 = 22, VG3 = 27), use = 'type_no')
  911. KNOWNTYPES = c('SAC', 'A2', 'VG3')
  912. # Raw tabulation
  913. lit_types = vertebrateAC$lit_type
  914. lit_types[is.na(lit_types)] = 'other'
  915. raw_tables = lapply(KNOWNTYPES, function(type) {
  916. raw_table = table(lit_types == type, vertebrateAC$species_littype == type)[2:1,2:1]
  917. return(raw_table)
  918. })
  919. lapply(raw_tables, EvaluateModel)
  920. ```
  921. Averaged across types
  922. ```{r}
  923. raw_tables = lapply(speciesList.liz, function(this.species) {
  924. # lapply(KNOWNTYPES, function(type) {
  925. message(paste0('working on ', this.species))
  926. lit_types = vertebrateAC$lit_type[vertebrateAC$species == this.species]
  927. species_littype = vertebrateAC$species_littype[vertebrateAC$species == this.species]
  928. lit_types[is.na(lit_types)] = 'other'
  929. raw_table = table(lit_types == type, species_littype == type)[2:1,2:1]
  930. raw_table
  931. # })
  932. })
  933. ```
  934. ## Conserved genes in primates, rodents, and laurasiatherans
  935. ```{r, fig.height=3, fig.width=12}
  936. primate.ortho = DownsampleSeurat(subset(ac.ortho, species %in% subset(species_metadata, Clade == 'Primate')$Species),
  937. group.by = 'orthotype', size = 50)
  938. rodent.ortho = DownsampleSeurat(subset(ac.ortho, species %in% subset(species_metadata, Clade == 'Rodent')$Species),
  939. group.by = 'orthotype', size = 50)
  940. laurasia.ortho = DownsampleSeurat(subset(ac.ortho, species %in% subset(species_metadata, Clade == 'Laurasiatheria')$Species),
  941. group.by = 'orthotype', size = 50)
  942. ac.ortho.sub = DownsampleSeurat(ac.ortho, group.by = 'orthotype', size = 500)
  943. de_all = TopNDEGs(ac.ortho.sub, group.by = 'orthotype', n = 100, sort.by = )
  944. primate.ortho = ScaleData(primate.ortho, features = unique(de_all$gene))
  945. rodent.ortho = ScaleData(rodent.ortho, features = unique(de_all$gene))
  946. laurasia.ortho = ScaleData(laurasia.ortho, features = unique(de_all$gene))
  947. SeuratHeatmap(ShuffleObject(primate.ortho, group.by = 'orthotype'), features = de_all$gene, group.by = 'orthotype',
  948. show_row_names = FALSE, show_column_names = FALSE, color = c('white', 'white', 'deeppink'))
  949. SeuratHeatmap(rodent.ortho, features = de_all$gene, group.by = 'orthotype',
  950. show_row_names = FALSE, show_column_names = FALSE, color = c('white', 'white', 'orange2')) +
  951. SeuratHeatmap(laurasia.ortho, features = de_all$gene, group.by = 'orthotype',
  952. show_row_names = FALSE, show_column_names = FALSE, color = c('white', 'white', 'chartreuse3'))
  953. ```
  954. # Figure 2: classification and annotation of ACs
  955. ## GABA gly scores
  956. ```{r, fig.height=2.5, fig.width=2.5}
  957. BIGSEURAT = readRDS('../../Ortho_Objects/vertebrateAC_BIGSEURAT.rds')
  958. # Check OT presence in species
  959. table(BIGSEURAT$species, BIGSEURAT$type)
  960. BIGSEURAT$species_type2 = paste0(BIGSEURAT$species, '-', BIGSEURAT$species_type)
  961. X = as.matrix(ConfusionMatrix(BIGSEURAT$type, BIGSEURAT$species_type2, plot = FALSE))
  962. dim(X)
  963. colnames(X)
  964. class.meta = readRDS('metadata/GabaGlyMetadata.rds')
  965. class.meta = dapply(seq_along(class.meta), function(i) {
  966. class.meta[[i]]$species_type2 = paste0(names(class.meta)[[i]], '-', class.meta[[i]]$type)
  967. return(class.meta[[i]])
  968. })
  969. # names(class.meta) = names(SPECIESFILES)
  970. Vdata = do.call(rbind, class.meta[!names(class.meta) %in% c('Zebrafish', 'Goldfish', 'Lamprey')])
  971. dim(Vdata)
  972. data.frame(c(colnames(X), rep(0, length(Vdata$type) - length(colnames(X)))), Vdata$species_type2)
  973. # Two lizard clusters are missing as expected (HC contamination)
  974. VennDiagram(colnames(X), Vdata$species_type2)
  975. # V = as.matrix(data.frame(pGly = Vdata$Gly_posterior[match(colnames(X), Vdata$species_type2)],
  976. # pGaba = Vdata$GABA_posterior[match(colnames(X), Vdata$species_type2)]))
  977. V = as.matrix(data.frame(`Gly_score` = Vdata$Gly_score[match(colnames(X), Vdata$species_type2)],
  978. `GABA_score` = Vdata$GABA_score[match(colnames(X), Vdata$species_type2)]))
  979. # Check dimensions
  980. dim(X)
  981. dim(V)
  982. U = as.data.frame(X %*% V)
  983. U$cluster = rownames(U)
  984. U$Subclass = 'GABAergic'
  985. U$Subclass[U$GABA_score < 0.2] = 'Glycinergic'
  986. U$cluster_no = convert_values(U$cluster, Metadata(ac.ortho, 'type', 'type_no') %>% setNames(c('old.names', 'new.names')))
  987. U$orthotype.no = orthotype_no_labels(U$cluster_no)
  988. ScatterPlot(U, 'GABA_score', 'Gly_score', fill = 'Subclass', r_pval = FALSE, lm = FALSE, labels = 'orthotype.no',
  989. max.overlaps = 10, xlab = 'GABAergic score', ylab = 'Glycinergic score') +
  990. scale_fill_manual(values = c('cyan', 'cyan4') %>% setNames(c('GABAergic', 'Glycinergic'))) +
  991. LegendTopRight()+
  992. # LegendLowerRight(x = 0.99, y = 0.53) +
  993. geom_vline(xintercept = 0.2, linetype = 'dashed', color = 'black', alpha = 0.2) +
  994. geom_hline(yintercept = 0.2, linetype = 'dashed', color = 'black', alpha = 0.2)
  995. ggsave('../../figures/my_figs/gaba-gly-scores.pdf', width = 2.5, height = 2.5)
  996. ```
  997. ## nGnGs from mouse have lowest scores
  998. ```{r, fig.height=3, fig.width=3}
  999. # c('16_NNgaba*', '2_NNgly')
  1000. # vec1 = as.character(ac.ortho$type)
  1001. # vec1[!vec1 %in% c('16_NNgaba*', '2_NNgly')] = 'Other'
  1002. # vec2 = as.character(ac.ortho$mouse.annotated)
  1003. # vec2[!vec2 %in% c('36', '10_CCK', '24', '30')] = 'Other'
  1004. # nn_matrix = JSMatrix(table(vec1, vec2))
  1005. nn_matrix = JSMatrix(table(ifelse(ac.ortho$type == '16_NNgaba*', '16_NNgaba*', ifelse(ac.ortho$type == '2_NNgly', '2_NNgly', 'Other')), ac.ortho$mouse.annotated))[, c('36', '10_CCK', '24', '30')]
  1006. colnames(nn_matrix) = ExtractString(colnames(nn_matrix), after = '_')
  1007. rownames(nn_matrix) = c('oAC36', 'oAC8', 'Other') #as.character((rownames(nn_matrix)))
  1008. rownames(nn_matrix)[is.na(rownames(nn_matrix))] = 'Other'
  1009. JSHeatmap(t(nn_matrix), title = 'nGnG oACs') +
  1010. ylab('Yan et al. 2020')+
  1011. ArialFont()+
  1012. theme(plot.margin = unit(c(1,1,1,1.3),"cm"))+
  1013. xlab(NULL)
  1014. ggsave('../../figures/my_figs/fig-ngng-yan-comparison.pdf', height=2.8, width=3)
  1015. ```
  1016. ```{r, fig.height=4, fig.width=9}
  1017. dendro = readRDS('../../Ortho_Objects/dendro.hs.liz.rds')
  1018. gaba.scores = readRDS('../../Ortho_Objects/gaba-scores.rds')
  1019. gly.scores = readRDS('../../Ortho_Objects/gly-scores.rds')
  1020. bar.col = 'black'
  1021. gly.df = data.frame(`NNgly` = gly.scores[,'2_NNgly'],
  1022. `NNgaba` = gly.scores[,'16_NNgaba*']) %>% rownames_to_column('Species')
  1023. gaba.df = data.frame(`NNgly` = gaba.scores[,'2_NNgly'],
  1024. `NNgaba` = gaba.scores[,'16_NNgaba*']) %>% rownames_to_column('Species')
  1025. # Define individual plots
  1026. p1_title <- TitlePlot(dendro, orthotype_labels('2_NNgly')) +
  1027. theme(panel.background = element_rect(fill = "transparent", color = NA),
  1028. plot.background = element_rect(fill = "transparent", color = NA))
  1029. p1_top <- PrettyBarplot(gly.df, x = 'Species', y = 'NNgly',
  1030. fill = 'cyan4', color = bar.col) +
  1031. # geom_hline(yintercept = 0.2, linetype = 'dashed', color = 'grey') +
  1032. scale_y_reverse(name = 'Glycinergic', limits = c(1, 0)) +
  1033. theme(axis.text.x = element_blank(),
  1034. axis.title.x = element_blank(),
  1035. axis.line.x = element_blank(),
  1036. panel.background = element_rect(fill = "transparent", color = NA),
  1037. plot.background = element_rect(fill = "transparent", color = NA),
  1038. axis.ticks.x = element_blank())
  1039. p1_bottom <- PrettyBarplot(gaba.df, x = 'Species', y = 'NNgly',
  1040. fill = 'cyan', color = bar.col) +
  1041. # geom_hline(yintercept = 0.2, linetype = 'dashed', color = 'grey') +
  1042. RotatedAxis() +
  1043. scale_y_reverse(name = 'GABAergic', limits = c(1, 0))
  1044. # Left column: Glycinergic score
  1045. left_col <- plot_grid(p1_title + scale_x_reverse(),
  1046. NULL,
  1047. p1_top + theme(plot.margin = unit(c(0,0,0,0), 'cm'),
  1048. panel.background = element_rect(fill = "transparent", color = NA),
  1049. plot.background = element_rect(fill = "transparent", color = NA)),
  1050. p1_bottom + theme(axis.title.x = element_blank(),
  1051. panel.background = element_rect(fill = "transparent", color = NA),
  1052. plot.background = element_rect(fill = "transparent", color = NA)),
  1053. ncol = 1,
  1054. align = "v",
  1055. rel_heights = c(0.4, -0.11, 0.3, 0.7))
  1056. # Right column: GABAergic score
  1057. p2_title <- TitlePlot(dendro, orthotype_labels('16_NNgaba*'))+
  1058. theme(panel.background = element_rect(fill = "transparent", color = NA),
  1059. plot.background = element_rect(fill = "transparent", color = NA))
  1060. p2_top <- PrettyBarplot(gly.df, x = 'Species', y = 'NNgaba',
  1061. fill = 'cyan4', color = bar.col) +
  1062. # geom_hline(yintercept = 0.2, linetype = 'dashed', color = 'grey') +
  1063. scale_y_reverse(limits = c(1, 0)) +
  1064. theme(axis.text.x = element_blank(),
  1065. axis.title.x = element_blank(),
  1066. panel.background = element_rect(fill = "transparent", color = NA),
  1067. plot.background = element_rect(fill = "transparent", color = NA),
  1068. axis.line.x = element_blank(),
  1069. axis.ticks.x = element_blank())
  1070. p2_bottom <- add_rectangle_annotation(
  1071. PrettyBarplot(gaba.df, x = 'Species', y = 'NNgaba', fill = c('cyan'), color = bar.col), index = 7, axis = 'row') +
  1072. RotatedAxis()+
  1073. # geom_hline(yintercept = 0.2, linetype = 'dashed', color = 'grey') +
  1074. scale_y_reverse(limits = c(1, 0))
  1075. # Left column: Glycinergic score
  1076. right_col <- plot_grid(p2_title + scale_x_reverse(),
  1077. NULL,
  1078. p2_top + theme(plot.margin = unit(c(0,0,0,0), 'cm'),
  1079. panel.background = element_rect(fill = "transparent", color = NA),
  1080. plot.background = element_rect(fill = "transparent", color = NA),
  1081. axis.text.y = element_blank(),
  1082. axis.title.y = element_blank()),
  1083. p2_bottom + theme(
  1084. panel.background = element_rect(fill = "transparent", color = NA),
  1085. plot.background = element_rect(fill = "transparent", color = NA),
  1086. axis.text.y = element_blank(),
  1087. axis.title.y = element_blank(),
  1088. axis.title.x = element_blank()),
  1089. ncol = 1,
  1090. align = "v",
  1091. rel_heights = c(0.4, -0.11, 0.3, 0.7))
  1092. # Combine both columns
  1093. final_plot <- plot_grid(left_col, right_col, ncol = 2, rel_widths = c(1,0.9))
  1094. final_plot
  1095. ggsave('../../figures/my_figs/fig-ngng-scores.pdf', height=3.5, width=8)
  1096. ```
  1097. Dendrogram
  1098. ```{r phylogeny-ncells-barplot, fig.height=6, fig.width=8}
  1099. library(ggdendro)
  1100. # Convert to common name
  1101. key = data.table::fread("../../Evolution/phylogeny/species_common_latin.txt")
  1102. tree = ape::read.tree("../../Evolution/phylogeny/20_species.nwk")
  1103. tree$tip.label = key$CommonName[match(gsub("_", " ", tree$tip.label), key$LatinName)]
  1104. dendro = phylogram::as.dendrogram.phylo(tree)
  1105. sorted.dendro = reorder(dendro, 1:20)
  1106. dendro = ggdendrogram(dendextend::prune(sorted.dendro, c("Zebrafish", 'Lamprey', 'Goldfish')))+
  1107. theme(axis.text.y = element_blank(), axis.text.x = element_blank())
  1108. dendro
  1109. saveRDS(dendextend::prune(sorted.dendro, c("Zebrafish", 'Lamprey', 'Goldfish')), '../../Ortho_Objects/phylo.hs.liz.rds')
  1110. saveRDS(dendro, '../../Ortho_Objects/dendro.hs.liz.rds')
  1111. ggsave('../../figures/my_figs/17-species-phylo.pdf', height = 1, width = 5)
  1112. # ylab("Evolutionary distance (MYA)")
  1113. # theme(axis.text.x = element_text(size = 13, hjust = 1, vjust = 1, angle = 45), axis.ticks.length.y = unit(.25, "cm"))+
  1114. # scale_y_continuous(breaks = seq(0, 500, len = 6))+ #expand = expansion(add = c(0,0.1)))+
  1115. # scale_x_discrete(expand = expansion(add = 0.6))+
  1116. # theme_cowplot()
  1117. # theme(axis.line.x=element_blank(),
  1118. # # axis.text.x=element_blank(),
  1119. # axis.ticks.x=element_blank(),
  1120. # axis.title.x=element_blank(),
  1121. # panel.grid.minor.x=element_blank(),
  1122. # panel.grid.major.x=element_blank())
  1123. ```
  1124. New phylogeny
  1125. ```{r, fig.height=5, fig.width=4}
  1126. library(ggdendro)
  1127. # Convert to common name
  1128. key = data.table::fread("../../Evolution/phylogeny/species_common_latin.txt")
  1129. tree = ape::read.tree("../../Evolution/phylogeny/22_species.nwk")
  1130. tree$tip.label = key$CommonName[match(gsub("_", " ", tree$tip.label), key$LatinName)]
  1131. dendro = phylogram::as.dendrogram.phylo(tree)
  1132. sorted.dendro = reorder(dendro, 1:20)
  1133. sorted.dendro.filt = sorted.dendro#dendextend::prune(sorted.dendro, c("Zebrafish", 'Lamprey', 'Goldfish'))
  1134. # dendro = ggdendrogram(sorted.dendro.filt)+
  1135. # # scale_y_reverse()
  1136. # coord_flip()
  1137. # theme(axis.text.y = element_blank(), axis.text.x = element_blank())
  1138. dendro
  1139. library(ape)
  1140. phylo = ape::as.phylo(sorted.dendro.filt)
  1141. library(ggtree)
  1142. ggtree(phylo) +
  1143. geom_tiplab() +
  1144. coord_cartesian(clip = 'off')+
  1145. # theme_tree2() +
  1146. theme(plot.margin = unit(c(1, 3, 1, 1), 'cm')) # xlim(0, max(nodeHeights(phylo)) + 1)
  1147. ggsave('figures/phylogeny-22-species.pdf', height=5, width=4.5)
  1148. ```
  1149. ## Manhattan marker plot
  1150. ```{r, fig.width=20}
  1151. BIGSEURAT = smartReadRDS("../../Ortho_Objects/vertebrateAC_BIGSEURAT.rds")
  1152. gene_type = fread('../../reference_files/gene-type.csv')
  1153. markers = gene_type$gene
  1154. scores.matrix = readRDS("../../Ortho_Objects/scores.matrix.rds")
  1155. scores.matrix.shuffled = readRDS("../../Ortho_Objects/scores.matrix.shuffled.rds")
  1156. conservation.summary = readRDS("../../Ortho_Objects/vertebrateAC_conservation.rds")
  1157. # Normalization
  1158. scores.matrix.melt = reshape2::melt(scores.matrix) %>% setNames(c("gene", "OT", "score"))
  1159. scores.matrix.melt$rand.score = reshape2::melt(scores.matrix.shuffled)[,3]
  1160. scores.matrix.melt$normalized.score = (scores.matrix.melt$score - mean(scores.matrix.melt$rand.score))/(0 - mean(scores.matrix.melt$rand.score))
  1161. scores.matrix.melt$normalized.rand.score = (scores.matrix.melt$rand.score - mean(scores.matrix.melt$rand.score))/(0 - mean(scores.matrix.melt$rand.score))
  1162. conservation.summary$best.normalized.score = apply(reshape2::dcast(scores.matrix.melt, gene ~ OT, value.var = 'normalized.score') %>% select(-gene), 1, function(x) max(x))
  1163. saveRDS(conservation.summary, "../../Ortho_Objects/vertebrateAC_conservation.rds")
  1164. ```
  1165. ```{r, fig.width=20}
  1166. BIGSEURAT = LoadACOrtho()
  1167. gene_type = fread('../../reference_files/gene-type.csv')
  1168. markers = gene_type$gene
  1169. scores.matrix = readRDS("../../Ortho_Objects/scores.matrix.rds")
  1170. scores.matrix.shuffled = readRDS("../../Ortho_Objects/scores.matrix.shuffled.rds")
  1171. conservation.summary = readRDS("../../Ortho_Objects/vertebrateAC_conservation.rds")
  1172. # Score normalization
  1173. scores.matrix.melt = reshape2::melt(scores.matrix) %>% setNames(c("gene", "OT", "score"))
  1174. scores.matrix.melt$rand.score = reshape2::melt(scores.matrix.shuffled)[,3]
  1175. scores.matrix.melt$normalized.score = (scores.matrix.melt$score - mean(scores.matrix.melt$rand.score))/(0 - mean(scores.matrix.melt$rand.score))
  1176. scores.matrix.melt$normalized.rand.score = (scores.matrix.melt$rand.score - mean(scores.matrix.melt$rand.score))/(0 - mean(scores.matrix.melt$rand.score))
  1177. # Threshold selection
  1178. specificity.threshold.low = min(scores.matrix.melt$normalized.rand.score)
  1179. specificity.threshold.high = max(scores.matrix.melt$normalized.rand.score)
  1180. # Marker selection
  1181. scores.matrix.melt$marker = scores.matrix.melt$gene %in% markers
  1182. scores.matrix.melt$significant = scores.matrix.melt$normalized.score > specificity.threshold.high
  1183. scores.matrix.melt$label_all = paste0("italic('", as.character(scores.matrix.melt$gene), "')")
  1184. scores.matrix.melt$label_marker = ifelse(scores.matrix.melt$marker & scores.matrix.melt$significant, paste0("italic('", as.character(scores.matrix.melt$gene), "')"), NA)
  1185. scores.matrix.melt$label_signif = ifelse(scores.matrix.melt$significant, paste0("italic('", as.character(scores.matrix.melt$gene), "')"), NA)
  1186. scores.matrix.melt$label_high = ifelse(scores.matrix.melt$normalized.score > 0.5, paste0("italic('", as.character(scores.matrix.melt$gene), "')"), NA)
  1187. # Top 2
  1188. scores.matrix.melt %>%
  1189. mutate(RowIndex = row_number()) %>%
  1190. group_by(OT) %>%
  1191. arrange(-normalized.score) %>%
  1192. slice_head(n = 2) %>%
  1193. ungroup() %>%
  1194. pull(RowIndex) -> top2_indices
  1195. scores.matrix.melt$label_top2 = NA
  1196. scores.matrix.melt$label_top2[top2_indices] = scores.matrix.melt$label_all[top2_indices]
  1197. scores.matrix.melt$top2 = FALSE
  1198. scores.matrix.melt$top2[top2_indices] = TRUE
  1199. scores.matrix.melt$show.label = scores.matrix.melt$top2 | scores.matrix.melt$significant & scores.matrix.melt$marker
  1200. # Final labels
  1201. scores.matrix.melt$label = ifelse(scores.matrix.melt$show.label, paste0("italic('", as.character(scores.matrix.melt$gene), "')"), NA)
  1202. # Odd and even for manhattan plot
  1203. scores.matrix.melt$odd = as.logical(scores.matrix.melt$OT %% 2)
  1204. # Colors
  1205. scores.matrix.melt$color = ifelse(scores.matrix.melt$significant & scores.matrix.melt$marker,
  1206. 'signif_marker',
  1207. ifelse(scores.matrix.melt$significant,
  1208. 'signif', 'other'))
  1209. # scores.matrix.melt$fill = ifelse(scores.matrix.melt$top2, 'signif', 'other'))
  1210. ots.with.markers = subset(scores.matrix.melt, marker & normalized.score > specificity.threshold.high)$OT %>% unique
  1211. message('Number of OTs with specific and conserved known markers: ', length(ots.with.markers))
  1212. ots.with.anymarkers = subset(scores.matrix.melt, normalized.score > specificity.threshold.high)$OT %>% unique
  1213. message('Number of OTs with specific and conserved any markers: ', length(ots.with.anymarkers))
  1214. scores.matrix.melt$ot.with.markers = scores.matrix.melt$OT %in% ots.with.markers
  1215. scores.matrix.melt$ot.with.anymarkers = scores.matrix.melt$OT %in% ots.with.anymarkers
  1216. xmin = 1
  1217. xmax = nClusters(BIGSEURAT)
  1218. ymin = min(scores.matrix.melt$normalized.score)
  1219. ymax = max(scores.matrix.melt$normalized.score)
  1220. scores.matrix.melt$OT = factor(scores.matrix.melt$OT, levels = levels(BIGSEURAT$dendro.order.type))
  1221. scores.matrix.melt = scores.matrix.melt %>% arrange(show.label)
  1222. # scores.matrix.melt$type = Metadata(BIGSEURAT, 'type_no', 'type')$type[match(scores.matrix.melt$OT, Metadata(BIGSEURAT, 'type_no', 'type')$type_no)]
  1223. scores.matrix.melt$orthotype = Metadata(BIGSEURAT, 'type_no', 'orthotype')$orthotype[match(scores.matrix.melt$OT, Metadata(BIGSEURAT, 'type_no', 'orthotype')$type_no)]
  1224. obs = scores.matrix.melt$normalized.score
  1225. null = scores.matrix.melt$normalized.rand.score # length 718746 (42 oAC x 17k genes)
  1226. # PrettyHistogram2(scores.matrix.melt$normalized.score,
  1227. # scores.matrix.melt$normalized.rand.score,
  1228. # bins = 100, logY = F,
  1229. # vline = max(null)) +
  1230. # scale_x_continuous(limits = c(0.1,1))
  1231. # coord_cartesian(xlim = c(0.1,1), expand = 0)
  1232. # qqplot(
  1233. # quantile(null, probs = ppoints(length(obs))),
  1234. # sort(obs),
  1235. # xlab = "Null distribution quantiles",
  1236. # ylab = "Observed quantiles"
  1237. # )
  1238. # abline(0, 1, col = "red")
  1239. p.val <- (length(null) - findInterval(obs, sort(null)) + 1) /
  1240. (length(null) + 1)
  1241. # Adjustment
  1242. p.val.adj = p.adjust(p.val, method = 'fdr')
  1243. head(sort(unique(p.val.adj))) # Current cutoff translates to an adjusted p-value of 0.002456999
  1244. scores.matrix.melt$p.val = p.val
  1245. scores.matrix.melt$p.adj = p.val.adj
  1246. # Save top 50 markers for each oAC
  1247. # top50_markers = TopN(scores.matrix.melt, 'orthotype', 'normalized.score', 50)
  1248. # library(openxlsx)
  1249. # wb <- loadWorkbook("../../manuscript/AC/supplement/TableS3-orthotype_markers.xlsx")
  1250. # addWorksheet(wb, "Conserved markers 2") # give your new sheet a name
  1251. # writeData(wb, sheet = "Conserved markers 2", top50_markers[,c('gene', 'orthotype', 'normalized.score', 'p.val', 'p.adj', 'significant')])
  1252. # saveWorkbook(wb, "../../manuscript/AC/supplement/TableS3-orthotype_markers.xlsx", overwrite = TRUE)
  1253. ```
  1254. ```{r, fig.width=11, fig.height=4, dev='cairo_pdf''}
  1255. p2 = ggplot(scores.matrix.melt,
  1256. aes(x = orthotype, y = normalized.score, label = label, color = show.label, fill = color, alpha = show.label))+
  1257. annotate("rect",
  1258. xmin = seq(xmin-0.5, xmax-0.5, by = 1),
  1259. xmax = seq(xmin+0.5, xmax+0.5, by = 1),
  1260. ymin = 0, #min(scores.matrix.melt$normalized.score),
  1261. ymax = 1, #max(scores.matrix.melt$normalized.score),
  1262. alpha = .2, fill = rep(c('white', 'lightgrey'), nClusters(BIGSEURAT)/2))+
  1263. # ggtitle('Orthotype markers Known, specific markers Other specific markers Non-specific markers')+
  1264. # scale_shape_manual(values = c(21, 21, 21))+
  1265. # geom_bin2d()+
  1266. # scale_fill_continuous(type = "viridis") +
  1267. xlab('Orthotype')+
  1268. ylab('Specificity score')+
  1269. scale_y_continuous(expand = expansion(mult = c(0, 0)), limits = c(0, 1))+
  1270. scale_x_discrete(expand = expansion(mult = c(0, 0)))+ #breaks = seq(1,nClusters(BIGSEURAT),1),
  1271. ggrastr::rasterise(geom_jitter(data = subset(scores.matrix.melt, !show.label), position = position_jitter(seed = 1), shape = 21), dpi = 300)+
  1272. geom_jitter(data = subset(scores.matrix.melt, show.label), position = position_jitter(seed = 1), shape = 21)+
  1273. # geom_jitter(data = subset(scores.matrix.melt, !show.label), position = position_jitter(seed = 1), shape = 21)+
  1274. geom_hline(yintercept = c(specificity.threshold.high), linetype = 'dashed', color = fcols[2], linewidth = 0.25)+
  1275. # geom_jitter(data = subset(scores.matrix.melt, !significant), position = position_jitter(seed = 1), shape = 21, alpha = 0.1)+
  1276. # geom_jitter(data = subset(scores.matrix.melt, significant), position = position_jitter(seed = 1), shape = 21)+
  1277. scale_color_manual('', values = c('grey', 'black'), labels = c('Novel', 'Known'))+
  1278. scale_fill_manual('', values = c('grey', 'grey', fcols[2]), labels = c('Novel', 'Novel', 'Known'))+
  1279. scale_alpha_manual(values = c(1, 1))+
  1280. guides(color = 'none', alpha = 'none', label = 'none')+
  1281. geom_text_repel(data = subset(scores.matrix.melt, show.label), max.overlaps = Inf, min.segment.length = 0.05, position = position_jitter(seed = 1), size = 2, parse = TRUE)+
  1282. theme_dario() +
  1283. theme(axis.title.x = element_blank())+
  1284. RotatedAxis() +
  1285. NoLegend() +
  1286. ArialFont()
  1287. # theme(legend.position = 'right')
  1288. p2
  1289. # ggsave('../../figures/my_figs/specificity-scores.pdf', width = 11, height = 4, device = cairo_pdf)
  1290. ggsave('../../figures/my_figs/specificity-scores.pdf', width = 11, height = 4.2)
  1291. ```
  1292. Only displaced ACs
  1293. ```{r}
  1294. p3 = ggplot(scores.matrix.melt[grepl('\\*', scores.matrix.melt$type),],
  1295. aes(x = type, y = normalized.score, label = label, color = show.label, fill = color, alpha = show.label))+
  1296. annotate("rect",
  1297. xmin = seq(1-0.5, 11-0.5, by = 1),
  1298. xmax = seq(1+0.5, 11+0.5, by = 1),
  1299. ymin = 0, #min(scores.matrix.melt$normalized.score),
  1300. ymax = 1, #max(scores.matrix.melt$normalized.score),
  1301. alpha = .2, fill = rep(c('white', 'lightgrey'), 12/2)[1:11])+
  1302. # ggtitle('Orthotype markers Known, specific markers Other specific markers Non-specific markers')+
  1303. # scale_shape_manual(values = c(21, 21, 21))+
  1304. # geom_bin2d()+
  1305. # scale_fill_continuous(type = "viridis") +
  1306. xlab('Orthotype')+
  1307. ylab('Specificity score')+
  1308. scale_y_continuous(expand = expansion(mult = c(0, 0)), limits = c(0, 1))+
  1309. scale_x_discrete(expand = expansion(mult = c(0, 0)))+ #breaks = seq(1,nClusters(BIGSEURAT),1),
  1310. ggrastr::rasterise(geom_jitter(data = subset(scores.matrix.melt[grepl('\\*', scores.matrix.melt$type),], !show.label),
  1311. position = position_jitter(seed = 1), shape = 21), dpi = 300)+
  1312. geom_jitter(data = subset(scores.matrix.melt[grepl('\\*', scores.matrix.melt$type),], show.label),
  1313. position = position_jitter(seed = 1), shape = 21)+
  1314. # geom_jitter(data = subset(scores.matrix.melt, !show.label), position = position_jitter(seed = 1), shape = 21)+
  1315. geom_hline(yintercept = c(specificity.threshold.high), linetype = 'dashed', color = fcols[2], linewidth = 0.25)+
  1316. # geom_jitter(data = subset(scores.matrix.melt, !significant), position = position_jitter(seed = 1), shape = 21, alpha = 0.1)+
  1317. # geom_jitter(data = subset(scores.matrix.melt, significant), position = position_jitter(seed = 1), shape = 21)+
  1318. scale_color_manual('', values = c('grey', 'black'), labels = c('Novel', 'Known'))+
  1319. scale_fill_manual('', values = c('grey', 'grey', fcols[2]), labels = c('Novel', 'Novel', 'Known'))+
  1320. scale_alpha_manual(values = c(1, 1))+
  1321. guides(color = 'none', alpha = 'none', label = 'none')+
  1322. geom_text_repel(data = subset(scores.matrix.melt[grepl('\\*', scores.matrix.melt$type),], show.label),
  1323. max.overlaps = Inf, min.segment.length = 0.05, position = position_jitter(seed = 1), size = 2, parse = TRUE)+
  1324. theme_dario() +
  1325. RotatedAxis() +
  1326. NoLegend() +
  1327. ArialFont()
  1328. # theme(legend.position = 'right')
  1329. p3
  1330. # ggsave('../../figures/my_figs/specificity-scores.pdf', width = 11, height = 4, device = cairo_pdf)
  1331. ggsave('../../figures/my_figs/specificity-scores-dACs.pdf', width = 4, height = 4)
  1332. ```
  1333. ## Conserved markers example
  1334. ```{r, fig.width=4, fig.height=2.5}
  1335. # coord_flip_discrete(geneDotPlotFast(ac.ortho, gene = 'PDGFRA', mini = TRUE), discrete_axis = 'OT')
  1336. # MultigeneDotPlot(ac.ortho, c('PDGFRA', 'EOMES'), mini = TRUE)
  1337. geneDotPlotFast(ac.ortho, gene = 'VIP', mini = TRUE) +
  1338. coord_cartesian(clip = 'off') +
  1339. theme_void() + theme_dario(linewidth = 0.6) + NoLegend() + theme(plot.title = element_blank())
  1340. ggsave('../../figures/my_figs/fig3-vip-example.pdf', width = 5.5, height = 3)
  1341. ```
  1342. # Figure 3: histological validation
  1343. ```{r, fig.height=3, fig.width=2}
  1344. TwoGeneDotPlot(ac.ortho, '27_VG3', c('SLC17A8', 'NXPH1'), font.size = 12, legend = TRUE) +
  1345. scale_color_manual(values = c('magenta3', 'cyan3'), guide = "none") +
  1346. theme(plot.margin = unit(c(0,0.5,0,0.5), 'cm')) + ArialFont()
  1347. ggsave('../../figures/my_figs/vglut3-nxph1-dot-legend.pdf', height=3, width=3)
  1348. width = 1.9
  1349. # VGluT3
  1350. TwoGeneDotPlot(ac.ortho, '27_VG3', c('SLC17A8', 'NXPH1'), font.size = 12) +
  1351. scale_color_manual(values = c('magenta3', 'cyan3'), guide = "none") +
  1352. theme(plot.margin = unit(c(0,0.5,0,0.5), 'cm'))
  1353. ggsave('../../figures/my_figs/vglut3-nxph1-dot.pdf', height=3, width=width)
  1354. # PDGFRA
  1355. TwoGeneDotPlot(ac.ortho, '21_PDGFRA', c('PDGFRA', 'GAD1')) +
  1356. scale_color_manual(values = c('magenta3', 'cyan3'), guide = "none") +
  1357. theme(plot.margin = unit(c(0,0.5,0,0.5), 'cm'))
  1358. ggsave('../../figures/my_figs/pdgfra-gad1-dot.pdf', height=3, width=width)
  1359. # CART SLC35D3
  1360. TwoGeneDotPlot(ac.ortho, '29_SLC35D3', c('SLC35D3', 'CARTPT')) +
  1361. scale_color_manual(values = c('magenta3', 'cyan3'), guide = "none") +
  1362. theme(plot.margin = unit(c(0,0.5,0,0.5), 'cm'))
  1363. ggsave('../../figures/my_figs/slc35d3-cartpt-dot.pdf', height=3, width=width)
  1364. # MAF GAD
  1365. TwoGeneDotPlot(ac.ortho, '1_MAF*', c('MAF', 'GAD1')) +
  1366. scale_color_manual(values = c('magenta3', 'cyan3'), guide = "none") +
  1367. theme(plot.margin = unit(c(0,0.5,0,0.5), 'cm'))
  1368. ggsave('../../figures/my_figs/maf1-gad-dot.pdf', height=3, width=width)
  1369. TwoGeneDotPlot(ac.ortho, '10_MAF*', c('MAF', 'GAD1')) +
  1370. scale_color_manual(values = c('magenta3', 'cyan3'), guide = "none") +
  1371. theme(plot.margin = unit(c(0,0.5,0,0.5), 'cm'))
  1372. ggsave('../../figures/my_figs/maf10-gad-dot.pdf', height=3, width=width)
  1373. # NOS/EOMES
  1374. TwoGeneDotPlot(ac.ortho, '12_nNOS*', c('NOS1', 'EOMES')) +
  1375. scale_color_manual(values = c('magenta3', 'cyan3'), guide = "none") +
  1376. theme(plot.margin = unit(c(0,0.5,0,0.5), 'cm'))
  1377. ggsave('../../figures/my_figs/nos-eomes-dot.pdf', height=3, width=width)
  1378. ```
  1379. ## MAF proportion displaced quantification
  1380. ```{r, fig.height=3.5, fig.width=2.6}
  1381. YanAC = readRDS('../../Species_Reference/YanAC_v4.rds')
  1382. table(YanAC$cluster_no)
  1383. prop.displaced.merfish = readRDS('../../reference_files/Choi_fig4d_automeris.rds')
  1384. prop.displaced.merfish
  1385. # 1_MAF is 2, 10_MAF is 32
  1386. ac2.prop = prop.displaced.merfish$proportion[prop.displaced.merfish$type == 'AC-2']
  1387. ac32.prop = prop.displaced.merfish$proportion[prop.displaced.merfish$type == 'AC-32']
  1388. weighted.average = (ac2.prop*table(YanAC$cluster_no)[[2]] + ac32.prop*table(YanAC$cluster_no)[[32]])/
  1389. (table(YanAC$cluster_no)[[2]] + table(YanAC$cluster_no)[[32]])
  1390. # Mouse replicates: C538A, C580, C588
  1391. # Macaque replicates: C285, C271, C292
  1392. prop.displaced.df = data.frame(Method = c('Mouse MERFISH', 'Mouse IHC 1', 'Mouse IHC 2 ', 'Mouse IHC 3', 'Macaque IHC 1', 'Macaque IHC 2', 'Macaque IHC 3'),
  1393. Sample = c('Mouse MERFISH', 'C538', 'C580', 'C588', 'C285', 'C271', 'C292'),
  1394. GCL = c(304, 13, 10, 18, 4, 7, 16),
  1395. INL = c(1000-304, 37-13, (23), (34), 12-4, (12), (27)),
  1396. proportion.displaced = c(weighted.average, 13/37, 10/(23+10), 18/(34+18), 4/12, 7/(12+7), 16/(27+16))) # 196 MAF+ cells counted
  1397. # prop.displaced.df$Method = factor(prop.displaced.df$Method, levels = rev(c('Mouse MERFISH', 'Mouse IHC', 'Macaque IHC')))
  1398. # prop.displaced.df$prop.displaced = prop.displaced.df$n.cells.GCL/(prop.displaced.df$n.cells.GCL + prop.displaced.df$n.cells.INL)
  1399. # TitlePlot(
  1400. # PrettyBarplot(prop.displaced.df, x = 'Method', y = 'proportion.displaced', add = c('mean_sd'), fill = 'white', width = 0.6) +
  1401. # geom_jitter(color = 'darkgrey')+
  1402. # ylab('Proportion\nin GCL') +
  1403. # xlab(NULL)+
  1404. # # RotatedAxis()+
  1405. # scale_x_discrete(labels = function(x) gsub(' ', '\n', x))+
  1406. # RotatedXAxis(angle = 0, hjust = 0.5)+
  1407. # # scale_y_continuous(labels = c(0,'', '', '', 0.4))
  1408. # # scale_y_continuous(breaks = function(x) range(x))+
  1409. # # scale_y_continuous(
  1410. # # breaks = c(0,0.4)
  1411. # # # breaks = function(x) {
  1412. # # # b <- scales::pretty_breaks()(x)
  1413. # # # c(min(b), max(b))
  1414. # # # }
  1415. # # )
  1416. # scale_ticks_first_last()+
  1417. # coord_flip()
  1418. # # theme(plot.margin = unit(c(0,0,0,0.5), 'cm'), axis.title.x = element_text(size = 16), axis.text.y = element_text(size = 14))
  1419. # # ylab(NULL)+
  1420. # # theme(axis.text.x = element_text(hjust = 0.5, angle = 0, size = 9))
  1421. # # 'Proportion\ndisplaced')
  1422. temp = reshape2::melt(prop.displaced.df[,c('Method', 'INL', 'GCL')])
  1423. ggplot(temp, aes(fill=variable, y=value, x=Method)) +
  1424. geom_bar(position="fill", stat="identity", color = "black") +
  1425. scale_x_discrete(labels = function(x) gsub(' ', '\n', gsub(" [0-9]+", "", x)))+
  1426. theme_minimal()+
  1427. # ggtitle(title)+
  1428. # xlab(feature.2)+
  1429. # labs(fill=feature.1)+
  1430. theme_cowplot(font_family = 'ArialMT')+
  1431. scale_fill_manual(name = '', values = c(INL = 'cyan3', GCL = 'deeppink2'))+
  1432. coord_flip()+
  1433. scale_ticks_first_last()+
  1434. # scale_x_continuous(labels = function(x) gsub('0\\.', '', x))+
  1435. ylab('Proportion')+
  1436. xlab(NULL)+
  1437. theme(legend.position = 'top')
  1438. # theme(axis.text.x = element_text(hjust = 1, angle = 45), plot.title = element_text(hjust = 0.5))
  1439. # ggsave('../../figures/my_figs/fig-hist-maf-prop.pdf', height = 3.5, width = 2.6)
  1440. ```
  1441. ## oAC30 [PDGFRA] abundance
  1442. ```{r, fig.width = 4.5, fig.height = 2.6}
  1443. freq.data2 = readRDS('../../Ortho_Objects/freq.data2.rds')
  1444. # PDGFRA is enriched in higher primates
  1445. PrettyBarplot(subset(freq.data2, Type == '21_PDGFRA' & jaccard > 0.25), x = 'Species', y = 'Frequency', add = c('mean_sd'), fill = 'white') +
  1446. geom_jitter(aes(color = Region), width = 0.2)+
  1447. scale_color_manual(values = c(Periphery = 'cyan3', Fovea = 'deeppink2'), na.value = "darkgrey")+
  1448. ylab('oAC30 [PDGFRA] frequency')+
  1449. xlab(NULL)+
  1450. theme(axis.title.y = element_text(hjust = 1, size = 13))+
  1451. NoLegend()+
  1452. RotatedAxis()
  1453. ggsave('../../figures/my_figs/fig-pdgfra-freq.pdf', width = 4.5, height = 2.6)
  1454. ```
  1455. # Figure 4: conservation of orthotypes
  1456. ```{r, fig.height=9, fig.width=10}
  1457. ac.ortho = LoadACOrtho()
  1458. js.matrices = lapply(speciesList.liz, function(this.species){
  1459. object = subset(ac.ortho, species == this.species)
  1460. JSMatrix(table(object$type_unordered, object$species_type2))
  1461. # addmargins(table(object$type, object$species_type2))
  1462. })
  1463. best.jaccard = do.call(cbind, lapply(js.matrices, function(matrix){
  1464. apply(matrix, 1, max)
  1465. }))
  1466. saveRDS(best.jaccard, '../../Ortho_Objects/best.jaccard.matrix.rds')
  1467. ```
  1468. ## Panel A: jaccard matrices
  1469. ```{r orthotype-speciestype-tight, fig.height=3, fig.width=20}
  1470. nTypes.df = readRDS('metadata/nTypes.df.rds')
  1471. tableList = readRDS('../../Ortho_Objects/tableList.rds')
  1472. ncells = nTypes.df$nCells[match(c(speciesList, 'Zebrafish', 'Lamprey'), nTypes.df$species)] %>% setNames(c(speciesList, 'Zebrafish', 'Lamprey'))
  1473. heatmapList2 = lapply(seq_along(tableList), function(index) {
  1474. JSHeatmap(JSMatrix(tableList[[index]]),
  1475. heatmap = TRUE,
  1476. border.col = NA,
  1477. title = paste0(unique(BIGSEURAT$species)[[index]], '\n(', ncells[[index]], ')'),
  1478. row.order = levels(ac.ortho$type),
  1479. stagger.threshold = 0.20) + theme(axis.text.x = element_blank(),
  1480. axis.text.y = element_blank(),
  1481. axis.title = element_blank(),
  1482. plot.margin=grid::unit(c(0,0,0,0), "mm"),
  1483. axis.ticks = element_blank()) + NoLegend()
  1484. })
  1485. nclusters = sapply(speciesACList, function(object) length(unique(object$species_type)))
  1486. ggarrange(plotlist = heatmapList2,
  1487. ncol = (length(heatmapList2)),
  1488. nrow = 1,
  1489. widths = nclusters)
  1490. ```
  1491. ```{r orthotype-speciestype-tight, fig.height=4, fig.width=20}
  1492. nTypes.df = readRDS('metadata/nTypes.df.rds')
  1493. tableList = readRDS('../../Ortho_Objects/tableList.rds')
  1494. ncells = nTypes.df$nCells[match(c(speciesList, 'Zebrafish', 'Lamprey'), nTypes.df$species)] %>% setNames(c(speciesList, 'Zebrafish', 'Lamprey'))
  1495. heatmapList2 = lapply(seq_along(tableList), function(index) {
  1496. JSHeatmap(JSMatrix(tableList[[index]]),
  1497. heatmap = TRUE,
  1498. border.col = NA,
  1499. title = paste0(unique(BIGSEURAT$species)[[index]], '\n(', comma(ncells[[index]]), ')'),
  1500. row.order = levels(ac.ortho$type),
  1501. stagger.threshold = 0.20) + theme(axis.text.x = element_blank(),
  1502. axis.text.y = element_blank(),
  1503. axis.title = element_blank(),
  1504. plot.margin=grid::unit(c(0,0,0,0), "mm"),
  1505. axis.ticks = element_blank()) + NoLegend() + ArialFont()
  1506. })
  1507. nclusters = sapply(speciesACList, function(object) length(unique(object$species_type)))
  1508. ggarrange(plotlist = heatmapList2,
  1509. ncol = (length(heatmapList2)),
  1510. nrow = 1,
  1511. widths = nclusters)
  1512. ggsave('../../figures/my_figs/orthotype-speciestype-supertight.pdf')
  1513. ```
  1514. Split by clades
  1515. ```{r, fig.height=7, fig.width=14}
  1516. # plot_grid(
  1517. # ggarrange(plotlist = heatmapList2[1:5],
  1518. # ncol = 5,
  1519. # nrow = 1,
  1520. # widths = nclusters[1:5]),
  1521. # ggarrange(plotlist = heatmapList2[6:10],
  1522. # ncol = 5,
  1523. # nrow = 1,
  1524. # widths = nclusters[6:10]),
  1525. # ggarrange(plotlist = heatmapList2[11:14],
  1526. # ncol = 5,
  1527. # nrow = 1,
  1528. # widths = nclusters[11:14]),
  1529. # ggarrange(plotlist = heatmapList2[15],
  1530. # ncol = 5,
  1531. # nrow = 1,
  1532. # widths = nclusters[[15]]),
  1533. # ggarrange(plotlist = heatmapList2[16:17],
  1534. # ncol = 5,
  1535. # nrow = 1,
  1536. # widths = nclusters[16:17]),
  1537. # ncol = 1, nrow = 2, labels = LETTERS, label_size = 20
  1538. # )
  1539. plot_grid(
  1540. ggarrange(plotlist = heatmapList2[1:8],
  1541. ncol = 8,
  1542. nrow = 1,
  1543. widths = nclusters[1:8]),
  1544. NULL,
  1545. ggarrange(plotlist = heatmapList2[9:17],
  1546. ncol = 9,
  1547. nrow = 1,
  1548. widths = nclusters[9:17]),
  1549. ncol = 1, nrow = 3, rel_heights = c(1,0.1,1) #, labels = LETTERS, label_size = 20
  1550. ) + theme(plot.margin = unit(c(1,1,1,1), units = 'cm'))
  1551. ggsave('../../figures/my_figs/orthotype-speciestype-two-row.pdf')
  1552. ```
  1553. ## Cluster merges plot
  1554. ```{r}
  1555. bestMatchDf = readRDS('../../Ortho_Objects/best-match.rds')[,speciesList.liz]
  1556. bestJaccardDf = readRDS('../../Ortho_Objects/best-jaccard.rds')[,speciesList.liz]
  1557. summary = reshape2::melt(as.matrix(bestMatchDf[,speciesList.liz])) %>% setNames(c('type', 'species', 'label'))
  1558. summary$score = reshape2::melt(as.matrix(bestJaccardDf[,speciesList.liz]))$value
  1559. # For each label in each species, find its best type (that will be its color!)
  1560. summary$species_type = paste0(summary$species, '-', summary$label)
  1561. best.ot = dapply(unique(summary$species_type), function(x) {
  1562. this = subset(summary, species_type == x)
  1563. as.character(this$type[which.max(this$score)])
  1564. })
  1565. summary$best.ot = best.ot[summary$species_type]
  1566. cor.mat = reshape2::dcast(summary, species ~ type, value.var = "best.ot")[,-1]
  1567. cor.mat <- apply(cor.mat, 2, as.character)
  1568. jac.mat = t(bestJaccardDf)
  1569. cor.mat[jac.mat < JS.THRESHOLD] = NA
  1570. rownames(cor.mat) = speciesList.liz
  1571. colnames(cor.mat) = orthotype_labels(colnames(cor.mat))
  1572. # pdf('../../figures/my_figs/merged-clusters-plot.pdf', height = 4, width = 12)
  1573. # Heatmap(as.matrix(cor.mat),
  1574. # cell_fun = function(j, i, x, y, width, height, fill) {
  1575. # grid.text(round(jac.mat[i, j], 2), x, y, gp = gpar(fontsize = 6))
  1576. # },
  1577. # col = type_cols2,
  1578. # cluster_rows = FALSE,
  1579. # cluster_columns = FALSE)
  1580. # dev.off()
  1581. ```
  1582. ```{r, fig.height=5.5, fig.width=11}
  1583. # Make colors a bit more distinct
  1584. type_cols4
  1585. # Quantification
  1586. ac.enriched = readRDS('../../Ortho_Objects/AC-frequency-all.rds')
  1587. ac.enriched.df = reshape2::melt(ac.enriched) %>% setNames(c('Species', 'Orthotype', 'Frequency'))
  1588. ac.enriched.df$Orthotype2 = orthotype_labels(gsub('\\*', '', ac.enriched.df$Orthotype), asterisk = F)
  1589. plt1 = PrettyBoxplot2(ac.enriched.df, x = 'Orthotype2', y = 'Frequency', color = 'Orthotype2', jitter = F) +
  1590. ylab('Observed\nfrequency')+
  1591. scale_color_manual(values = darken(type_cols4, 0.1))+
  1592. theme(axis.line.x = element_blank(), axis.ticks.x = element_blank(), axis.text.x = element_blank(),
  1593. plot.margin = unit(c(0.5,0,0,0), 'cm')) +
  1594. scale_y_continuous(expand = expansion(mult = c(0,0)))+
  1595. coord_cartesian(ylim = c(0, 0.1501))
  1596. # Snake
  1597. rownames(cor.mat) = speciesList.liz
  1598. cor.mat2 = matrix(orthotype_labels(cor.mat), nrow = nrow(cor.mat), ncol = ncol(cor.mat), dimnames = dimnames(cor.mat))
  1599. plt2 = SnakePlot(cor.mat2,
  1600. pt.size = 4,
  1601. lwd1 = 5,
  1602. lwd2 = NA,
  1603. lty2 = 'solid',
  1604. grid.pt.size = 0.2,
  1605. cols = lighten(type_cols4, 0.1))
  1606. plot_grid(plt1, plt2, nrow = 2, align = 'v', axis = 'lr', rel_heights = c(1,3.5))
  1607. ggsave('../../figures/my_figs/fig3-snake-plot.pdf', height=5.5, width=11)
  1608. ```
  1609. ```{r, fig.height=3.8, fig.width=10}
  1610. cor.mat.mammal = cor.mat[rownames(cor.mat) %in% speciesList.mammals,]
  1611. SnakePlot(cor.mat.mammal, pt.size = 4, lwd1 = 5, grid.pt.size = 0.2)
  1612. ggsave('../../figures/my_figs/fig3-snake-plot-mammal.pdf')
  1613. ```
  1614. Investigate human NN-gly cluster to see if they can be subclustered
  1615. ```{r}
  1616. human = readRDS('../../Species_Objects/HumanAC_v6.rds')
  1617. BIGSEURAT = readRDS('../../Ortho_Objects/vertebrateAC-allcells-counts.rds')
  1618. human.10 = subset(BIGSEURAT, species_type == 'Human-10_SEG')
  1619. human.10 = MapBack(human.10, human, group.by = 'donor')
  1620. human.10.harmony = Harmonize(human.10, batch = 'donor')
  1621. DimPlotLabeled(human.10.harmony, 'type')
  1622. DimPlotLabeled(human.10.harmony, 'donor')
  1623. human.10.int = ClusterSeurat(human.10, integrate.by = 'donor')
  1624. DimPlotLabeled(human.10.int, 'type')
  1625. DimPlotLabeled(human.10.int, 'donor')
  1626. stackedBarGraph2(human.10.int, 'type', 'donor')
  1627. FeaturePlot(human.10.int, 'PROM1')
  1628. FeaturePlot(human.10.int, 'SATB2')
  1629. FeaturePlot(human.10.int, 'NFIB')
  1630. # Challenging to split these three types
  1631. # Human and macaque integration
  1632. hum_mac = subset(BIGSEURAT, species %in% c('Human', 'Macaque'))
  1633. # hum_mac = ClusterSeurat(hum_mac, integrate.by = 'species')
  1634. ```
  1635. Also interested in oAC splits, not just merges
  1636. ```{r}
  1637. jaccardList = readRDS('../../Ortho_Objects/jaccardList.rds')
  1638. jaccardList
  1639. # How many species types map to this orthotype above some threshold?
  1640. type.depth = lapply(jaccardList, function(this.species) apply(this.species, 1, function(row) length(which(row > js.threshold))))
  1641. type.depth.mat = do.call(rbind, type.depth)
  1642. Heatmap2(type.depth.mat)
  1643. ```
  1644. Co-clustering frequency
  1645. ```{r}
  1646. tableList = readRDS('../../Ortho_Objects/tableList.rds')
  1647. # JSHeatmap(t(jaccardList$Human) %*% jaccardList$Mouse)
  1648. tableList = lapply(names(tableList), function(species) {
  1649. colnames(tableList[[species]]) = paste0(species, '-', colnames(tableList[[species]]))
  1650. tableList[[species]]
  1651. })
  1652. names(tableList) = speciesList.liz
  1653. ccf = row_norm(t(tableList$Human)) %*% row_norm(tableList$Rat)
  1654. JSHeatmap(ccf, stagger.threshold = 0.2)
  1655. ccf = row_norm(t(tableList$Chicken)) %*% row_norm(tableList$Rat)
  1656. JSHeatmap(ccf, stagger.threshold = 0.2)
  1657. ```
  1658. ```{r, fig.height=6, fig.width=15}
  1659. library(ggplot2)
  1660. library(dplyr)
  1661. library(tidyr)
  1662. # Example character matrix (3 rows x 4 cols)
  1663. # mat <- matrix(
  1664. # c("A", "A", "B", "C",
  1665. # "B", "B", "B", "C",
  1666. # "C", "C", "A", "A"),
  1667. # nrow = 3, byrow = TRUE,
  1668. # dimnames = list(paste0("row", 1:3), paste0("col", 1:4))
  1669. # )
  1670. mat = cor.mat
  1671. rownames(mat) = speciesList.liz
  1672. # Convert to long
  1673. df <- as.data.frame(mat) %>%
  1674. tibble::rownames_to_column("row") %>%
  1675. pivot_longer(-row, names_to = "col", values_to = "value")
  1676. # Create numeric coordinates once (consistent for points & segments)
  1677. # Keep the column order as in mat and row order as in mat
  1678. col_levels <- colnames(mat)
  1679. row_levels <- rownames(mat)
  1680. df <- df %>%
  1681. mutate(
  1682. col_num = as.integer(factor(col, levels = col_levels)),
  1683. row_num = as.integer(factor(row, levels = row_levels))
  1684. )
  1685. # Build segments: connect adjacent columns within the same row when values match
  1686. segments <- df %>%
  1687. arrange(row_num, col_num) %>%
  1688. group_by(row) %>%
  1689. mutate(next_value = lead(value), next_col_num = lead(col_num)) %>%
  1690. filter(value == next_value) %>%
  1691. transmute(
  1692. row, value,
  1693. x = col_num,
  1694. xend = next_col_num,
  1695. y = row_num,
  1696. yend = row_num
  1697. ) %>%
  1698. ungroup()
  1699. # Plot: use numeric coords, convert axes to show labels
  1700. ggplot() +
  1701. # segments first so points draw on top
  1702. geom_segment(data = segments,
  1703. aes(x = x, xend = xend, y = y, yend = yend, color = value),
  1704. linewidth = 1.2, lineend = "round", show.legend = FALSE) +
  1705. geom_point(data = df,
  1706. aes(x = col_num, y = row_num, color = value),
  1707. size = 5, show.legend = FALSE) +
  1708. scale_x_continuous(breaks = seq_along(col_levels), labels = col_levels, expand = expansion(0.1)) +
  1709. # reverse y so row1 is on top (optional, UpSet-like)
  1710. scale_y_reverse(breaks = seq_along(row_levels), labels = row_levels, expand = expansion(0.1)) +
  1711. theme_minimal() +
  1712. RotatedAxis()+
  1713. theme(panel.grid = element_blank(),
  1714. axis.title = element_blank())
  1715. ```
  1716. ## Conservation level quantification and comparison
  1717. ```{r, fig.height=3, fig.width=3.2}
  1718. # Quantification of AC conservation in mammals; we have no way of disentangling presence and conservation
  1719. # bestMatchDf = readRDS('../../Ortho_Objects/best-match.rds')[,speciesList.liz]
  1720. # bestJaccardDf = readRDS('../../Ortho_Objects/best-jaccard.rds')[,speciesList.liz]
  1721. # jac.mat = t(bestJaccardDf[,speciesList.mammals])
  1722. # Area under the presence cutoff curve
  1723. AUPCC = function(jac.mat, return.values = FALSE){
  1724. library(pracma)
  1725. x = seq(0, 1, length.out = 101)
  1726. y = sapply(x, function(i) length(which(jac.mat > i)) / prod(dim(jac.mat)))
  1727. plot(x, y)
  1728. area <- trapz(x, y)
  1729. auc_norm <- area / (max(x) - min(x))
  1730. if(return.values) {
  1731. y
  1732. } else {
  1733. auc_norm
  1734. }
  1735. }
  1736. # With ferret
  1737. ac.ortho = LoadACOrtho()
  1738. ac.match = MakeBestMatchDF(ac.ortho)
  1739. # AUPCC(t(ac.match[[2]]))
  1740. # Removing some species to make sure they have the same set
  1741. species.use = c('Human', 'Macaque', 'Marmoset', 'TreeShrew',
  1742. 'Mouse', 'Rhabdomys', 'Peromyscus', 'Squirrel',
  1743. 'Sheep', 'Pig','Opossum')
  1744. # Remove some lowly abundant clusters
  1745. ac.match = MakeBestMatchDF(ac.ortho)
  1746. ac.match2 = ac.match[[2]]
  1747. # ac.match2 = ac.match2[,!colnames(ac.match2) %in% c('Ferret', 'Chicken', 'Lizard')]
  1748. ac.match2 = ac.match2[!rownames(ac.match2) %in% c('38', '39', '40*', '42'), colnames(ac.match2) %in% species.use]
  1749. AUPCC(t(ac.match2))
  1750. # BCs
  1751. bc.ortho = readRDS('../../Ortho_Objects/vertebrateBC_BIGSEURAT.rds')
  1752. bc.match = MakeBestMatchDF(bc.ortho, species_cluster = 'species_type', orthotype = 'NOG')
  1753. AUPCC(t(bc.match[[2]] %>% dplyr::select(species.use)))
  1754. # RGCs
  1755. rgc.ortho = readRDS('../../Ortho_Objects/vertebrateRGC_BIGSEURAT.rds')
  1756. rgc.match = MakeBestMatchDF(rgc.ortho, species_cluster = 'species_type', orthotype = 'NOG')
  1757. AUPCC(t(rgc.match[[2]] %>% dplyr::select(species.use)))
  1758. # Collect the values
  1759. auc.df = data.frame(cutoff = rep(seq(0, 1, length.out = 101), 3),
  1760. AUC = factor_unique(c(rep(paste0(c('BC', round(AUPCC(t(bc.match[[2]] %>% dplyr::select(species.use))), 2)), collapse = ' = '), 101),
  1761. rep(paste0(c('AC', round(AUPCC(t(ac.match[[2]] %>% dplyr::select(species.use))), 2)), collapse = ' = '), 101),
  1762. rep(paste0(c('RGC', round(AUPCC(t(rgc.match[[2]] %>% dplyr::select(species.use))), 2)), collapse = ' = '), 101))),
  1763. fraction = c(AUPCC(t(bc.match[[2]] %>% dplyr::select(species.use)), return.values = T),
  1764. AUPCC(t(ac.match[[2]] %>% dplyr::select(species.use)), return.values = T),
  1765. AUPCC(t(rgc.match[[2]] %>% dplyr::select(species.use)), return.values = T)))
  1766. ggplot(auc.df, aes(x = cutoff, y = fraction * 100, color = AUC)) +
  1767. LegendLowerLeft(background.col = 'white', x = 0.01, y = 0.04, background.alpha = 1)+
  1768. geom_line() +
  1769. theme_dario(linewidth = 1) +
  1770. ylab('% orthotypes found')+
  1771. xlab('Jaccard index')+
  1772. scale_x_continuous(
  1773. breaks = seq(0, 1, by = 0.25),
  1774. labels = function(b) {
  1775. labs <- rep("", length(b))
  1776. labs[1] <- b[1]
  1777. labs[length(b)] <- b[length(b)]
  1778. labs
  1779. })+
  1780. scale_y_continuous(
  1781. breaks = seq(0, 100, by = 25),
  1782. labels = function(b) {
  1783. labs <- rep("", length(b))
  1784. labs[1] <- b[1]
  1785. labs[length(b)] <- b[length(b)]
  1786. labs
  1787. })+
  1788. theme(axis.title = element_text(size = 12))+
  1789. ArialFont()+
  1790. geom_vline(xintercept = 0.1, linetype = 'dashed', color = 'grey')
  1791. ggsave('../../figures/my_figs/fig-aupcc.pdf', height=3, width=3.2)
  1792. ```
  1793. ## SAC UMAPs
  1794. ```{r, fig.height=8, fig.width=10}
  1795. objectList = list()
  1796. objectList$Primates = readRDS('../../Ortho_Objects/primateSAC.rds')
  1797. objectList$TreeShrew = subset(readRDS('../../Ortho_Objects/otherSAC.rds'), species == 'TreeShrew')
  1798. objectList$Rodents = readRDS('../../Ortho_Objects/rodentSAC.rds')
  1799. objectList$Laurasiatherians = readRDS('../../Ortho_Objects/lauraSAC.rds')
  1800. # objectList$Other = readRDS('../../Ortho_Objects/otherSAC.rds')
  1801. objectList$Opossum = subset(readRDS('../../Ortho_Objects/otherSAC.rds'), species == 'Opossum')
  1802. objectList$Sauropsids = readRDS('../../Ortho_Objects/sauroSAC.rds')
  1803. objectList$Amphibians = readRDS('../../Ortho_Objects/amph.SAC.rds')
  1804. objectList$Zebrafish = readRDS('../../Ortho_Objects/zeSAC.rds')
  1805. objectList$Lamprey = readRDS('../../Ortho_Objects/SAC.pm.clean.rds')
  1806. pm2ch = readRDS('../cones/orthology_graphs/pm2ch.rds')
  1807. objectList$Lamprey = ConvertGeneSymbols2(objectList$Lamprey, pm2ch)
  1808. umap_params = list(group.by = 'species', cols = species_palette3, label = FALSE, show.legend = FALSE, pad = 0.4, pt.size = 2, pt.alpha = 0.6)
  1809. # angle.list = c(0, pi, pi/1.1, 0, pi, pi, pi/1.5, 0)
  1810. angle.list = c(0, pi+0.1, pi, -0.3, pi+0.1, pi, pi, pi/1.3, 0.3)
  1811. plt.list = lapply(seq_along(objectList), function(i){
  1812. theme_umap(
  1813. do.call(PrettyUmap2, c(objectList[[i]], umap_params, angle = angle.list[[i]])) +
  1814. theme(plot.background = element_rect(fill = 'transparent')),
  1815. remove.axes = T) + theme(plot.margin = unit(c(2,10,10,10), 'mm'))
  1816. # LegendLowerLeft(background.col = 'white')
  1817. })
  1818. plot_grid(plotlist = plt.list)
  1819. ggsave('../../figures/my_figs/fig-sac-umap-2.pdf', width = 10, height = 7)
  1820. # FeaturePlot(objectList$Amphibians, features = 'TENM3')
  1821. # FeaturePlot(objectList$Zebrafish, features = 'tenm3')
  1822. # ON SAC is on the left
  1823. ```
  1824. ```{r}
  1825. umap_params = list(group.by = 'lit_subtype', label = FALSE, show.legend = TRUE, pad = 0.4, pt.size = 2, pt.alpha = 0.6)
  1826. angle.list = c(0, pi, 0, pi, pi, 0, 0, 0)
  1827. plt.list = lapply(seq_along(objectList), function(i){
  1828. do.call(PrettyUmap2, c(objectList[[i]], umap_params, angle = angle.list[[i]])) +
  1829. LegendLowerLeft()
  1830. })
  1831. plot_grid(plotlist = plt.list)
  1832. ```
  1833. ```{r, fig.height=4, fig.width=15}
  1834. lamprey.full = readRDS('../../Full_Objects/Lamprey_Wang_full_v2.rds')
  1835. lamprey.full = ConvertGeneSymbols2(lamprey.full, pm2ch)
  1836. DotPlot3(lamprey.full, features = c('NOS1', 'OPN4'), group.by = 'annotated')
  1837. FeaturePlot(objectList$Lamprey, 'LOC116944204') | DimPlotLabeled(objectList$Lamprey, 'annotated')
  1838. DotPlot3(objectList$Lamprey, features = c('TENM3', 'FEZF1', 'FEZF2', 'LOC116944204'), group.by = 'annotated')
  1839. de = TopNDEGs(objectList$Lamprey, group.by = 'annotated')
  1840. obj = load('../../Species_Reference/Wang_Lamprey/seu.lamprey.SAC.types.rda')
  1841. wang_lamprey <- get(obj)
  1842. DotPlot3(wang_lamprey, features = c('TENM3', 'FEZF2'), group.by = 'subtype')
  1843. objectList$Lamprey = MapBack(objectList$Lamprey, wang_lamprey, group.by = 'subtype')
  1844. table(objectList$Lamprey$annotated, objectList$Lamprey$subtype)
  1845. ```
  1846. ## SAC clustering
  1847. ```{r}
  1848. # Need to redo some graph because I removed a cluster
  1849. objectList$Amphibians = ClusterSeurat(objectList$Amphibians, integrate.by = 'species')
  1850. objectList$Zebrafish = ClusterSeurat(objectList$Zebrafish)
  1851. # DimPlotLabeled(objectList$Amphibians)
  1852. DimPlotLabeled(objectList$Zebrafish)
  1853. objectList$Lamprey = Harmonize(objectList$Lamprey, batch = 'animal')
  1854. objectList2 = dapply(names(objectList), function(group){
  1855. message('Trying ', group, '...')
  1856. object = objectList[[group]]
  1857. if(!group %in% c('Zebrafish', 'Lamprey')) DefaultAssay(object) = 'integrated'
  1858. ClusterUntil(object, k = 2)
  1859. # DimPlotLabeled(objectList$Primates)
  1860. })
  1861. umap_params = list(group.by = 'seurat_clusters', label = FALSE, show.legend = FALSE, pad = 0.4, pt.size = 2, pt.alpha = 0.6)
  1862. angle.list = c(0, pi, pi/1.1, 0, pi, pi, pi/1.5, 0)
  1863. plt.list = lapply(seq_along(objectList2), function(i){
  1864. theme_umap(
  1865. do.call(PrettyUmap2, c(objectList2[[i]], umap_params, angle = angle.list[[i]])) +
  1866. theme(plot.background = element_rect(fill = 'transparent')),
  1867. remove.axes = T) + theme(plot.margin = unit(c(2,10,10,10), 'mm'))
  1868. # LegendLowerLeft(background.col = 'white')
  1869. })
  1870. plot_grid(plotlist = plt.list)
  1871. # Fix the sauropsids
  1872. objectList2$Sauropsids = FindClusters(objectList2$Sauropsids, resolution = 0.2)
  1873. DimPlotLabeled(objectList2$Sauropsids)
  1874. objectList2$Sauropsids = MergeClusters(objectList2$Sauropsids, c(1,2), refactor = TRUE)
  1875. DimPlotLabeled(objectList2$Sauropsids)
  1876. saveRDS(objectList2, '../../Ortho_Objects/sac-ortho-list.rds')
  1877. ```
  1878. ## SAC violin
  1879. ```{r, fig.height=7, fig.width=6}
  1880. objectList2 = readRDS('../../Ortho_Objects/sac-ortho-list.rds')
  1881. ```
  1882. ```{r, fig.height=6, fig.width=10}
  1883. # Annotate on and off sacs
  1884. anno_list = list(Primates = list('SAC' = c(0,1)),
  1885. Rodents = list('ON' = c(1), 'OFF' = c(0)),
  1886. Laurasiatherians = list('ON' = c(0), 'OFF' = c(1)),
  1887. Other = list('ON' = c(1), 'OFF' = c(0)),
  1888. Sauropsids = list('ON' = c(1), 'OFF' = c(0)),
  1889. Amphibians = list('ON' = c(1), 'OFF' = c(0)),
  1890. Zebrafish = list('ON' = c(0), 'OFF' = c(1)),
  1891. Lamprey = list('ON' = c(0), 'OFF' = c(1)))
  1892. objectList2 = dapply(names(objectList2), function(group){
  1893. AssignAnnotations(objectList2[[group]], anno_list[[group]])
  1894. })
  1895. umap_params = list(group.by = 'lit_type', label = FALSE, show.legend = TRUE, pad = 0.4, pt.size = 2, pt.alpha = 0.6)
  1896. angle.list = c(0, pi, -0.3, pi, pi, pi, pi/1.3, 0.3)
  1897. plt.list = lapply(seq_along(objectList2), function(i){
  1898. theme_umap(
  1899. do.call(PrettyUmap2, c(objectList2[[i]], umap_params, angle = angle.list[[i]])) +
  1900. theme(plot.background = element_rect(fill = 'transparent')),
  1901. remove.axes = T) + theme(plot.margin = unit(c(2,10,10,10), 'mm'))
  1902. # LegendLowerLeft(background.col = 'white')
  1903. })
  1904. plot_grid(plotlist = plt.list)
  1905. ```
  1906. ```{r, fig.height=7, fig.width=6}
  1907. # Convert some gene symbols
  1908. objectList2$Zebrafish = RenameFeatures(objectList2$Zebrafish, gsub('tenm3', 'TENM3',
  1909. gsub('zfhx3', 'ZFHX3',
  1910. gsub('rnd3a', 'RND3',
  1911. gsub('fezf1', 'FEZF1',
  1912. gsub('fezf2', 'FEZF2',
  1913. rownames(objectList2$Zebrafish)))))))
  1914. # Add FEZF2 from Wang et al. (replacing a random unexpressed gene)
  1915. obj = load('../../Species_Reference/Wang_Lamprey/seu.lamprey.SAC.types.rda')
  1916. wang_sac <- get(obj)
  1917. objectList2$Lamprey@assays$RNA@data['LOC116942270',] = wang_sac@assays$RNA@data['FEZF2',Cells(objectList2$Lamprey)]
  1918. objectList2$Lamprey = RenameFeatures(objectList2$Lamprey, gsub('LOC116944204', 'TENM3',
  1919. gsub('TENM3', 'TENM4',
  1920. gsub('LOC116942270', 'FEZF2',
  1921. rownames(objectList2$Lamprey)))))
  1922. merged = merge(objectList2[[1]], objectList2[2:length(objectList2)])
  1923. merged # 11.5k SACs
  1924. merged$species = factor(merged$species, levels = rev(phylogenetic_order2))
  1925. # Switch to RNA assay
  1926. DefaultAssay(merged) = 'RNA'
  1927. # VlnPlot(merged, features = c('FEZF1', 'FEZF2', 'TENM3', 'ZFHX3', 'RND3'),
  1928. # split.by = 'lit_type', group.by = 'species', stack = TRUE, flip = FALSE,
  1929. # cols = c(ON = col1, OFF = col2, SAC = 'grey'))
  1930. # FeaturePlot(objectList2$Lamprey, 'TENM3')
  1931. # FeaturePlot(objectList2$Sauropsids, 'RND3')
  1932. # VlnPlot(objectList2$Lamprey, group.by = 'lit_type', features = 'TENM3')
  1933. col1 = 'deeppink2'
  1934. col2 = 'chartreuse2'
  1935. # Linear combination
  1936. merged$FEZF1_FEZF2 = merged@assays$RNA@data['FEZF1',] + merged@assays$RNA@data['FEZF2',]
  1937. merged$TENM3_ZFHX3_RND3 = merged@assays$RNA@data['TENM3',] + merged@assays$RNA@data['ZFHX3',] + merged@assays$RNA@data['RND3',]
  1938. merged$Subtype = merged$lit_type
  1939. merged$`Off.score` = (merged@assays$RNA@data['TENM3',] + merged@assays$RNA@data['ZFHX3',] + merged@assays$RNA@data['RND3',] -
  1940. merged@assays$RNA@data['FEZF1',] - merged@assays$RNA@data['FEZF2',]) / 5
  1941. # VlnPlot(merged, features = c('FEZF1_FEZF2', 'TENM3_ZFHX3_RND3'),
  1942. # split.by = 'lit_type', group.by = 'species', stack = TRUE, flip = FALSE,
  1943. # cols = c(ON = 'deeppink3', OFF = 'cyan3', SAC = 'grey'))
  1944. # plot_grid(VlnPlot(merged,
  1945. # features = c("FEZF1_FEZF2", "TENM3_ZFHX3_RND3"),
  1946. # group.by = "species",
  1947. # # cols = c(ON = col1, OFF = col2, SAC = 'grey'),
  1948. # split.by = "Subtype",
  1949. # split.plot = FALSE,
  1950. # pt.size = 100,
  1951. # stack = TRUE) +
  1952. # scale_fill_manual(values = c(ON = col1, OFF = col2, SAC = 'grey'))+
  1953. # NoLegend() +
  1954. # theme(axis.title.y = element_blank()),
  1955. # stackedBarGraph(merged, feature.2 = "species", feature.1 = "Subtype") +
  1956. # labs(y = 'Proportion')+
  1957. # scale_fill_manual(values = c(ON = col1, OFF = col2, SAC = 'grey'))+
  1958. # guides(fill = guide_legend(title = "Subtype"))+
  1959. # # scale_fill_manual(values = c(params$color1, params$color2))+
  1960. # coord_flip() +
  1961. # scale_y_continuous(expand = expansion(mult = c(0,0)))+
  1962. # guides(fill = guide_legend(ncol = 1))+
  1963. # theme(axis.text.y = element_blank(),
  1964. # legend.position = 'top',
  1965. # axis.title.y = element_blank(),
  1966. # axis.ticks.y = element_blank()),
  1967. # ncol = 2, rel_widths = c(2,1), align = "h", axis = "bt")
  1968. # ggsave('../../figures/my_figs/sac-violn-1.pdf', height = 8, width = 4.5)
  1969. # plt.list = VlnPlot(merged,
  1970. # features = c("FEZF1_FEZF2", "TENM3_ZFHX3_RND3"),
  1971. # group.by = "species",
  1972. # # cols = c(ON = col1, OFF = col2, SAC = 'grey'),
  1973. # split.by = "Subtype",
  1974. # split.plot = FALSE,
  1975. # pt.size = 0.01,
  1976. # stack = FALSE,
  1977. # combine = FALSE)
  1978. #
  1979. # wrap_plots(lapply(plt.list, function(x) x + coord_flip()))
  1980. #
  1981. # plt.list[[1]] + coord_flip()
  1982. col1 = 'orange2'
  1983. col2 = 'cyan3'
  1984. merged2 = subset(merged, species %in% c('Human', 'Macaque', 'Marmoset', 'MouseLemur'), invert = T)
  1985. merged2$species_pretty = factor(factor(species_names_pretty(merged2$species), levels = rev(phylogenetic_order_pretty)))
  1986. PrettyBarplot([email hidden], x = 'species_pretty', y = 'FEZF1_FEZF2', fill = 'Subtype',
  1987. add = c('mean_se'), position = position_dodge(width = 0.8), width = 0.8) +
  1988. scale_fill_manual(values = c(ON = col1, OFF = col2, SAC = 'grey')) +
  1989. ylab('FEZF1+\nFEZF2') +
  1990. scale_ticks_first_last()+
  1991. NoRotatedXAxis()+
  1992. theme(axis.title.x = element_text(face = 'italic'), axis.title.y = element_blank())+
  1993. coord_flip() + NoLegend() |
  1994. PrettyBarplot([email hidden], x = 'species_pretty', y = 'TENM3_ZFHX3_RND3', fill = 'Subtype',
  1995. add = c('mean_se'), position = position_dodge(width = 0.8), width = 0.8) +
  1996. scale_fill_manual(values = c(ON = col1, OFF = col2, SAC = 'grey')) +
  1997. ylab('TENM3+\nZFXH3+\nRND3') +
  1998. scale_ticks_first_last()+
  1999. NoRotatedXAxis()+
  2000. theme(axis.title.x = element_text(face = 'italic'), axis.title.y = element_blank())+
  2001. coord_flip() +
  2002. theme(axis.text.y = element_blank(), axis.title.y = element_blank(), legend.position = 'top') |
  2003. stackedBarGraph(merged2, feature.2 = "species_pretty", feature.1 = "Subtype", percent = F) +
  2004. labs(y = 'Percent')+
  2005. scale_fill_manual(values = c(ON = col1, OFF = col2, SAC = 'grey'))+
  2006. guides(fill = guide_legend(title = "Subtype"))+
  2007. # scale_fill_manual(values = c(params$color1, params$color2))+
  2008. coord_flip() +
  2009. NoLegend()+
  2010. NoRotatedXAxis()+
  2011. # scale_y_continuous(expand = expansion(mult = c(0,0)), labels = function(x) x*100)+
  2012. scale_ticks_first_last(do = function(x) x*100)+
  2013. # guides(fill = guide_legend(ncol = 1))+
  2014. theme(axis.text.y = element_blank(),
  2015. axis.title.y = element_blank(),
  2016. axis.ticks.y = element_blank())
  2017. ggsave('../../figures/my_figs/sac-violn-1.pdf', height = 6, width = 4.5)
  2018. ```
  2019. # Figure 6: non-mammal integration
  2020. ## Read in samap data
  2021. ```{r, fig.height=8, fig.width=10}
  2022. #' Prepare umap metadata
  2023. class.umap = as.data.frame(fread('samap/pm_sh_ca_kf_ze_ne_am_ch_li-class-v2-umap.csv'))
  2024. # colnames(class.umap) = gsub('UMAP', 'UMAP_', colnames(class.umap))
  2025. class.umap$species_full = convert_values(class.umap$species, index$species %>% setNames(index$ident))
  2026. class.umap$species_full = factor(factor(class.umap$species_full, levels = index$species))
  2027. # ac.umap = as.data.frame(fread('samap/pm_sh_ca_kf_ze_am_ch_li-ac-v1-umap.csv')) # v1 used Wang annotations
  2028. # ac.umap = as.data.frame(fread('samap/pm_sh_ca_kf_ze_am_ch_li-ac-v2-umap.csv'))
  2029. ac.umap = as.data.frame(fread('samap/pm_sh_ca_kf_ze_ne_am_ch_li-ac-v3-umap.csv'))
  2030. # colnames(ac.umap) = gsub('UMAP', 'UMAP_', colnames(ac.umap))
  2031. ac.umap$species_full = convert_values(ac.umap$species, index$species %>% setNames(index$ident))
  2032. ac.umap$species_full = factor(factor(ac.umap$species_full, levels = index$species))
  2033. # rgc.umap = as.data.frame(fread('samap/pm_sh_ca_kf_ze_am_ch_li-class-v1-umap.csv'))
  2034. # colnames(rgc.umap) = gsub('UMAP', 'UMAP_', colnames(rgc.umap))
  2035. bc.umap = as.data.frame(fread('samap/pm_sh_ca_kf_ze_ne_am_ch_li-bc-v2-umap.csv'))
  2036. # colnames(bc.umap) = gsub('UMAP', 'UMAP_', colnames(bc.umap))
  2037. bc.umap$species_full = convert_values(bc.umap$species, index$species %>% setNames(index$ident))
  2038. bc.umap$species_full = factor(factor(bc.umap$species_full, levels = index$species))
  2039. prefix.key = index$species %>% setNames(index$ident)
  2040. ```
  2041. ## Cell class confusion matrix
  2042. ```{r, fig.height=4.5, fig.width=16}
  2043. # Assign majority class
  2044. class.umap$leiden_clusters = class.umap$leiden_clusters_5
  2045. # Remove leiden cluster 33 (poorly integrated cells)
  2046. class.umap = subset(class.umap, leiden_clusters != 31)
  2047. class.umap$leiden_clusters = as.numeric(as.character(RenumberClustering(class.umap$leiden_clusters)))
  2048. cm = ConfusionMatrix(subset(class.umap, species_full != "Lamprey")$leiden_clusters,
  2049. subset(class.umap, species_full != "Lamprey")$cell_class, plot = FALSE)
  2050. majority.class = factor(apply(cm, 1, function(x) colnames(cm)[which.max(x)]),
  2051. levels = c('PR', 'onBC', 'offBC', 'HC', 'glyAC', 'gabaAC', 'AC', 'RGC', 'MG'))
  2052. cluster.order = seq(0, length(majority.class)-1)[rev(order(majority.class))]
  2053. bg = stackedBarGraph2(subset(class.umap, species_full != 'Lamprey') %>%
  2054. mutate(leiden_clusters = factor(as.character(leiden_clusters),
  2055. levels = (cluster.order))),
  2056. 'leiden_clusters', 'cell_class', as.factor = TRUE) +
  2057. scale_y_continuous(expand = c(0, 0),
  2058. breaks = c(0, 0.25, 0.5, 0.75, 1), # only first and last
  2059. labels = c('0', '', '', '', '1'),
  2060. minor_breaks = waiver() # keeps automatic minor ticks
  2061. )+
  2062. coord_flip() +
  2063. scale_fill_manual(values = cell_class3_colors)+
  2064. theme_cowplot()+
  2065. theme(axis.text.y = element_blank(),
  2066. axis.title.y = element_blank(),
  2067. axis.ticks.y = element_blank(),
  2068. axis.title.x = element_text(size = 12),
  2069. axis.text.x = element_text(angle = 0, hjust = 0.5))
  2070. ident.2 = 'annotated'
  2071. ident.1 = 'leiden_clusters'
  2072. objectList = split(class.umap, class.umap$species_full)
  2073. heatmapList = lapply(seq_along(objectList), function(index) {
  2074. JSHeatmap2(objectList[[index]][[ident.1]],
  2075. objectList[[index]][[ident.2]],
  2076. title = names(objectList)[[index]],
  2077. row.order = rev(cluster.order),
  2078. border.col = NA,
  2079. max.value = 0.5,
  2080. stagger.threshold = 0.1) +
  2081. theme(axis.ticks = element_blank(),
  2082. axis.text.x = element_blank(),
  2083. axis.text.y = element_blank(),
  2084. plot.margin = margin(0, 0, 0, 0))
  2085. #seq(0, max(class.umap$leiden_clusters)))
  2086. })
  2087. names(heatmapList) = names(objectList)
  2088. ncol = length(objectList)+2
  2089. nrow = 1
  2090. # ggarrange(plotlist = c(list(NULL),
  2091. # ggarrange(plotlist = heatmapList,
  2092. # widths = sapply(objectList, function(x) length(unique(x$annotated))),
  2093. # common.legend = TRUE), list(bg)),
  2094. # ncol = ncol,
  2095. # nrow = nrow,
  2096. # # common.legend = TRUE,
  2097. # widths = c(10, 1000, 50),
  2098. # legend = "none",
  2099. # align = 'hv',
  2100. # axis = 'btlr')
  2101. # ggarrange(plotlist = c(list(NULL), heatmapList, list(bg)))
  2102. # ggsave('../../figures/my_figs/nonmammal-integration.pdf', height=4, width=12)
  2103. # JSHeatmap2(objectList[[3]][[ident.1]],
  2104. # objectList[[3]][[ident.2]],
  2105. # title = names(objectList)[[3]],
  2106. # row.order = cluster.order)
  2107. ggarrange(plotlist = c(heatmapList, list(bg)),
  2108. widths = c(sapply(objectList, function(x) length(unique(x$annotated))), 40),
  2109. common.legend = TRUE,
  2110. align = 'h',
  2111. nrow = 1)
  2112. ggsave('../../figures/my_figs/nonmammal-class-jaccard.pdf', height=4.5, width=16)
  2113. ```
  2114. ## Cell class UMAPs
  2115. ```{r, fig.height=4, fig.width=15}
  2116. PrettyUmap2(class.umap, group.by = 'species_full',
  2117. label = FALSE, geom.label = geom_text_repel,
  2118. box.padding = 0.7, show.legend = TRUE,
  2119. title = 'Non-mammal integration (species)', pt.alpha = 0.1,
  2120. cols = species_palette3, rasterise = TRUE,
  2121. nbreaks = 30, remove.times = 3) |
  2122. PrettyUmap2(subset(class.umap, species_full != 'Lamprey'), group.by = 'cell_class2',
  2123. label = TRUE, geom.label = geom_text_repel,
  2124. box.padding = 0.7,
  2125. title = 'Manually annotated cell classes (excluding lamprey)', pt.alpha = 0.1,
  2126. cols = cell_class3_colors, rasterise = TRUE,
  2127. nbreaks = 30, remove.times = 3) |
  2128. PrettyUmap2(subset(class.umap, species_full == 'Lamprey'), group.by = 'cell_class2',
  2129. label = TRUE, geom.label = geom_text_repel,
  2130. box.padding = 0.7,
  2131. title = 'Manually annotated cell classes (lamprey)', pt.alpha = 0.2,
  2132. cols = cell_class3_colors, rasterise = TRUE,
  2133. nbreaks = 30, remove.times = 3)
  2134. ggsave('../../figures/my_figs/nonmammal-class-umap.pdf', height=4, width=15)
  2135. ```
  2136. ```{r}
  2137. #' Tabulate errors
  2138. class.umap$cell_class2_inferred = MatchClusters(class.umap$leiden_clusters, class.umap$cell_class2)
  2139. accuracies = dapply(levels(class.umap$species_full), function(this.species){
  2140. sub = subset(class.umap, species_full == this.species)
  2141. mat = table(sub$cell_class2_inferred, sub$cell_class2)
  2142. diag(mat) = 0
  2143. # Print accuracy
  2144. (1 - sum(mat) / nrow(sub)) * 100
  2145. })
  2146. paste0(round(quantile(unlist(accuracies[-1]), 0.025), 2), '-', round(quantile(unlist(accuracies[-1]), 0.975), 2))
  2147. dapply(levels(class.umap$species_full), function(this.species){
  2148. sub = subset(class.umap, species_full == this.species)
  2149. table(sub$cell_class2_inferred, sub$cell_class2)
  2150. })
  2151. ```
  2152. ```{r, fig.height=10, fig.width=10}
  2153. # Cluster 33 is suspicious
  2154. class.umap$leiden_clusters = as.character(class.umap$leiden_clusters)
  2155. PrettyUmap2(class.umap,
  2156. group.by = 'leiden_clusters',
  2157. # color.by = 'cell_class2',
  2158. label = TRUE,
  2159. geom.label = geom_text_repel,
  2160. # nudge_x = 2, nudge_y = ,
  2161. title = 'Non-mammal integration', pt.alpha = 0.1,
  2162. # cols = cell_class3_colors,
  2163. cols = c(`33` = 'red'),
  2164. rasterise = FALSE, nbreaks = 30, remove.times = 3)
  2165. # Which species are in 33
  2166. table(subset(class.umap, leiden_clusters == 33)$species) # pretty even
  2167. sort(table(subset(class.umap, species == 'ze')$leiden_clusters,
  2168. subset(class.umap, species == 'ze')$annotated)['33',]) # ze_glyAC-43
  2169. sort(table(subset(class.umap, species == 'pm')$leiden_clusters,
  2170. subset(class.umap, species == 'pm')$annotated)['33',]) # pm_MG-4
  2171. sort(table(subset(class.umap, species == 'ne')$leiden_clusters,
  2172. subset(class.umap, species == 'ne')$annotated)['33',]) # multiple
  2173. sort(table(subset(class.umap, species == 'ca')$leiden_clusters,
  2174. subset(class.umap, species == 'ca')$annotated)['33',]) # multiple
  2175. # Seems like a cluster of poorly integrated cells more than contamination
  2176. # Shark HCs? 15, 21
  2177. JSHeatmap2(subset(class.umap, species == 'sh')$leiden_clusters,
  2178. subset(class.umap, species == 'sh')$annotated)
  2179. cm[as.character(cluster.order),]
  2180. # Cluster 39 (RGC) has some ACs
  2181. sort(table(subset(class.umap, species == 'ze')$leiden_clusters,
  2182. subset(class.umap, species == 'ze')$annotated)['39',]) # no cells
  2183. sort(table(subset(class.umap, species == 'ne')$leiden_clusters,
  2184. subset(class.umap, species == 'ne')$annotated)['39',]) # RGC
  2185. sort(table(subset(class.umap, species == 'sh')$leiden_clusters,
  2186. subset(class.umap, species == 'sh')$annotated)['39',]) # no cells
  2187. sort(table(subset(class.umap, species == 'li')$leiden_clusters,
  2188. subset(class.umap, species == 'li')$annotated)['39',]) # RGC
  2189. sort(table(subset(class.umap, species == 'ch')$leiden_clusters,
  2190. subset(class.umap, species == 'ch')$annotated)['39',]) # ch_gabaAC-34; no contamination tho
  2191. sort(table(subset(class.umap, leiden_clusters == '39')$annotated))
  2192. ```
  2193. ## Alignment matrix: class
  2194. ```{r, fig.height=8, fig.width=9}
  2195. samap_alignment = as.matrix(read.csv("samap/pm_sh_ca_kf_ze_am_ch_li-class-v1-mappingtable.csv", row.names = 1))
  2196. pdf('../../figures/my_figs/nonmammal-integration-matrix.pdf', height=5, width=6)
  2197. sm.class = SAMapAlignmentHeatmap2(samap_alignment,
  2198. cell_class3_colors,
  2199. nm_palette2,
  2200. # width = unit(19, "in"),
  2201. # height = unit(19, "in"),
  2202. show_annotation_legend = TRUE,
  2203. show_row_names = FALSE,
  2204. show_column_names = FALSE,
  2205. species.use = c('pm', 'sh', 'kf', 'ca', 'ze', 'am', 'ch', 'li'),
  2206. type.order = CELL_CLASSES3,
  2207. max.value = 0.4,
  2208. cols = c('white', 'deeppink', 'deeppink4'),
  2209. rect_gp = gpar(col = "grey", lwd = 0),
  2210. use_raster = TRUE,
  2211. raster_quality = 2,
  2212. raster_by_magick = TRUE)
  2213. dev.off()
  2214. cnames = rownames([email hidden])
  2215. pdf('../../figures/my_figs/nonmammal-integration-matrix-class.pdf', height=50, width=50)
  2216. sm.class = SAMapAlignmentHeatmap2(samap_alignment,
  2217. cell_class3_colors,
  2218. nm_palette2,
  2219. show_annotation_legend = TRUE,
  2220. show_row_names = TRUE,
  2221. show_column_names = TRUE,
  2222. species.use = c('pm', 'sh', 'kf', 'ca', 'ze', 'am', 'ch', 'li'),
  2223. type.order = CELL_CLASSES3,
  2224. max.value = 0.4,
  2225. cols = c('white', 'deeppink', 'deeppink4'),
  2226. rect_gp = gpar(col = "grey", lwd = 0),
  2227. use_raster = TRUE,
  2228. raster_quality = 2,
  2229. raster_by_magick = TRUE)
  2230. dev.off()
  2231. ```
  2232. ## One nearest neighbor classification for lamprey
  2233. ```{r, fig.height=5, fig.width=14}
  2234. # samap_alignment = (read.csv("samap/pm_sh_ca_kf_ze_am_ch_li-class-v1-mappingtable.csv", row.names = 1))
  2235. samap_alignment = (read.csv("samap/pm_sh_ca_kf_ze_ne_am_ch_li-class-v2-mappingtable.csv", row.names = 1))
  2236. species = str_split_fixed(rownames(samap_alignment), "_", 2)[,1]
  2237. types = str_split_fixed(str_split_fixed(rownames(samap_alignment), "_", 2)[,2], '-', 2)[,1]
  2238. idents = str_split_fixed(str_split_fixed(rownames(samap_alignment), "_", 2)[,2], '-', 2)[,2]
  2239. smatrix = SmartMatrix(as.matrix(samap_alignment), row.data = data.frame(species, types, idents), col.data = data.frame(species, types, idents))
  2240. # Set threshold of alignment score
  2241. # smatrix@matrix[smatrix@matrix < 0.1] = 0
  2242. score.threshold = 0.05
  2243. # For each lamprey cluster, find its nearest neighbor in each species
  2244. matrix.list = list(Shark = smatrix[[email hidden]$species == 'pm', [email hidden]$species == 'sh'],
  2245. Killifish = smatrix[[email hidden]$species == 'pm', [email hidden]$species == 'kf'],
  2246. Goldfish = smatrix[[email hidden]$species == 'pm', [email hidden]$species == 'ca'],
  2247. Zebrafish = smatrix[[email hidden]$species == 'pm', [email hidden]$species == 'ze'],
  2248. Newt = smatrix[[email hidden]$species == 'pm', [email hidden]$species == 'ne'],
  2249. Axolotl = smatrix[[email hidden]$species == 'pm', [email hidden]$species == 'am'],
  2250. Chicken = smatrix[[email hidden]$species == 'pm', [email hidden]$species == 'ch'],
  2251. Lizard = smatrix[[email hidden]$species == 'pm', [email hidden]$species == 'li'])
  2252. nn.res = do.call(cbind, lapply(matrix.list, function(smat)
  2253. apply(smat@matrix, 1, function(x) {
  2254. this.max = max(x)
  2255. if(this.max > score.threshold)
  2256. [email hidden]$type[which.max(x)]
  2257. else
  2258. 'Unmapped'
  2259. })))
  2260. nn.res
  2261. tabulation = do.call(gtools::smartbind, apply(nn.res, 1, function(x) t(as.data.frame.vector(table(x)))))
  2262. tabulation[is.na(tabulation)] = 0
  2263. melted = reshape2::melt(as.matrix(tabulation)) %>% setNames(c('Cluster', 'Prediction', 'nSpecies'))
  2264. melted = subset(melted, Prediction != 'Unmapped')
  2265. max.value = 8; col.high = "#584B9FFF"; col.low = 'white'; legend_name = '# species';
  2266. if(!exists('objectList')) objectList = ReadSAMapObjects()
  2267. lamprey = objectList$Lamprey
  2268. # lamprey = OrderAnnotated(readRDS('../../Full_Objects/Lamprey_Wang_full_v1.rds'))
  2269. # Make dotplot first
  2270. pm2ch = readRDS('../cones/orthology_graphs/pm2ch.rds')
  2271. lamprey = ConvertGeneSymbols2(lamprey, pm2ch)
  2272. plt2 = AnnotatedUmap(lamprey,
  2273. annotation = subset(major_annotation_lamprey_on_off,
  2274. genes = c('PDE6H', 'RHO', 'VSX2', 'GRIK1', 'ONECUT3', 'SLC6A9', 'SLC6A5', 'PAX6',
  2275. 'TFAP2B', 'GAD1', 'RBPMS', 'RBPMS2', 'SLC17A6', 'POU4F3', 'NEFL', 'NEFM', 'RLBP1')),
  2276. group.by = 'annotated',
  2277. color.clusters.by = 'cell_class2',
  2278. umap.legend = TRUE,
  2279. plot.umap = FALSE,
  2280. title = 'Lamprey')
  2281. # Make NN plot after, same order as dotplot
  2282. melted = subset(melted, Cluster %in% paste0('pm_', lamprey$annotated))
  2283. melted$Cluster = factor(melted$Cluster, levels = paste0('pm_', levels(plt2$data$id)))
  2284. melted$Prediction = factor(melted$Prediction, levels = rev(c('PR', 'onBC', 'offBC', 'HC', 'glyAC', 'gabaAC', 'RGC', 'MG')))
  2285. plt1 = ggplot(melted, aes(x = Cluster, y = Prediction))+
  2286. geom_point(aes(colour = nSpecies, size=nSpecies))+
  2287. scale_color_gradient(legend_name, low=col.low, high = col.high, limits=c(0, max.value), na.value = 'grey') +
  2288. scale_radius(legend_name, limits=c(0, max.value)) +
  2289. # scale_size(range = c(1, max.size), limits = c(0, max.perc))+
  2290. theme_bw() +
  2291. RotatedAxis() +
  2292. # ylab('True')+
  2293. # xlab('Predicted')+
  2294. theme(axis.title = element_text(color = 'black'),
  2295. axis.text = element_text(color = 'black'),
  2296. plot.title = element_text(hjust = 0.5))
  2297. plot_grid(plt1 + theme(axis.text.x = element_blank(), axis.title.x = element_blank()),
  2298. plt2, nrow = 2, align = 'v', axis = 'lr', rel_heights = c(1,2))
  2299. # ggsave('figures/lamprey-1NN-predictions-05.pdf', height=5, width=14)
  2300. ```
  2301. Permissive: 9, 27, 30, 34, 35, 37, 39, 41
  2302. Stringent: 27, 34
  2303. ```{r, fig.height=3, fig.width=10}
  2304. # Best alignment score within each species... 3 entries x 382 rows
  2305. best.scores = do.call(rbind, lapply(1:nrow(sm.class@matrix), function(i){
  2306. species = unique([email hidden]$species)
  2307. this.species = [email hidden][i,'species']
  2308. do.call(cbind, lapply(species, function(other.species){
  2309. max(sm.class@matrix[i,[email hidden]$species == other.species])
  2310. }) %>% setNames(species))
  2311. }))
  2312. best.scores.df = reshape2::melt(best.scores) %>% setNames(c('id', 'target', 'Score'))
  2313. best.scores.df$species = rep([email hidden]$species, 4)
  2314. best.scores.df$type = rep([email hidden]$types, 4)
  2315. ggboxplot(subset(best.scores.df, type %in% c('PR', 'HC', 'MG')), x = 'type', y = 'Score', color = 'species', legend = 'none') |
  2316. ggboxplot(subset(best.scores.df, !type %in% c('PR', 'HC', 'MG')), x = 'type', y = 'Score', color = 'species', legend = 'right')
  2317. ```
  2318. ### Heatmap variant for SFN
  2319. ```{r, fig.width=4, fig.height=6}
  2320. # melted2$Cluster = factor(melted2$Cluster,
  2321. # levels = unique(arrange(melted2, Prediction, nSpecies)$Cluster))
  2322. tabulation2 = tabulation[,colnames(tabulation) != 'Unmapped']
  2323. tabulation2$BC = tabulation2$onBC + tabulation2$offBC
  2324. tabulation2 = tabulation2[,!colnames(tabulation2) %in% c('onBC', 'offBC')]
  2325. best.match = apply(tabulation2, 1, function(x) colnames(tabulation2)[which.max(x)])
  2326. rgc.fraction = apply(tabulation2, 1, function(x) x['RGC'] / 7) #max(x)/7)
  2327. ac.fraction = apply(tabulation2, 1, function(x) 1 - x['gabaAC'] / 7)
  2328. sort.df = data.frame(Cluster = rownames(tabulation2),
  2329. best.match = best.match,
  2330. rgc.fraction = rgc.fraction,
  2331. ac.fraction = ac.fraction)
  2332. melted2 = reshape2::melt(as.matrix(tabulation2)) %>% setNames(c('Cluster', 'Prediction', 'nSpecies'))
  2333. # melted2 = subset(melted, Prediction != 'Unmapped')
  2334. melted2$Prediction = gsub('gabaAC', 'gaAC', gsub('glyAC', 'glAC', melted2$Prediction))
  2335. melted2$Prediction = factor(melted2$Prediction, levels = (c('PR', 'BC', 'HC', 'glAC', 'gaAC', 'RGC', 'MG')))
  2336. # melted2$Cluster = factor(melted2$Cluster, levels = rev(arrange(sort.df,
  2337. # factor(best.match,
  2338. # levels = (c('PR', 'BC', 'HC', 'glyAC', 'gabaAC', 'RGC', 'MG'))),
  2339. # rgc.fraction,
  2340. # ac.fraction)$Cluster))
  2341. pm_order = c("pm_MG-3", "pm_MG-2", "pm_MG-1", "pm_RGC-34", "pm_RGC-30", "pm_RGC-37", "pm_RGC-27",
  2342. "pm_RGC-9", "pm_RGC-39", "pm_RGC-35", "pm_RGC-3", "pm_RGC-41",
  2343. "pm_RGC-1", "pm_RGC-33", "pm_MG-4", "pm_RGC-26", "pm_gabaAC-3", "pm_RGC-22",
  2344. "pm_RGC-23", "pm_RGC-7", "pm_RGC-31", "pm_RGC-20", "pm_RGC-2", "pm_RGC-18",
  2345. "pm_RGC-11", "pm_RGC-8", "pm_RGC-19", "pm_RGC-4", "pm_RGC-36", "pm_RGC-28",
  2346. "pm_RGC-5", "pm_RGC-21", "pm_RGC-15", "pm_gabaAC-4", "pm_gabaAC-2",
  2347. "pm_gabaAC-1", "pm_RGC-25", "pm_RGC-24", "pm_RGC-12", "pm_RGC-6",
  2348. "pm_RGC-40", "pm_RGC-38", "pm_RGC-32", "pm_RGC-29", "pm_RGC-17",
  2349. "pm_RGC-16", "pm_RGC-14", "pm_RGC-10", "pm_RGC-13", "pm_glyAC-4", "pm_offBC-6",
  2350. "pm_glyAC-9", "pm_glyAC-8", "pm_glyAC-7", "pm_glyAC-6", "pm_glyAC-5",
  2351. "pm_glyAC-3", "pm_glyAC-2", "pm_glyAC-11", "pm_glyAC-10", "pm_glyAC-1",
  2352. "pm_HC-4", "pm_HC-3", "pm_HC-2", "pm_HC-1", "pm_onBC-5",
  2353. "pm_onBC-3", "pm_onBC-1", "pm_offBC-8", "pm_offBC-7", "pm_offBC-4",
  2354. "pm_offBC-2", "pm_PR-2", "pm_PR-1")
  2355. melted2$Cluster <- factor(melted2$Cluster,
  2356. levels = pm_order
  2357. )
  2358. # Remove suspicious clusters
  2359. sus.clusters = c('pm_offBC-6', 'pm_MG-4', 'pm_gabaAC-3', 'pm_gabaAC-4')
  2360. melted2 = subset(melted2, !Cluster %in% sus.clusters)
  2361. # Plot
  2362. ggplot(melted2, aes(y = Cluster, x = Prediction))+
  2363. geom_tile(aes(fill = nSpecies))+
  2364. scale_fill_gradient(legend_name, low='white', high = 'deeppink2', limits=c(0, max.value), na.value = 'grey',
  2365. guide = guide_colorbar(frame.colour = "black", ticks.colour = "black")) +
  2366. # scale_radius(legend_name, limits=c(0, max.value)) +
  2367. # scale_size(range = c(1, max.size), limits = c(0, max.perc))+
  2368. theme_dario() +
  2369. scale_x_discrete(expand = expansion(mult = c(0,0)))+
  2370. RotatedAxis() +
  2371. ArialFont()+
  2372. # ylab('True')+
  2373. # xlab('Predicted')+
  2374. theme(axis.title = element_text(color = 'black'),
  2375. axis.text = element_text(color = 'black'),
  2376. plot.title = element_text(hjust = 0.5),
  2377. axis.ticks.y = element_blank(),
  2378. axis.text.x = element_text(size = 12))
  2379. ggsave('../../figures/my_figs/lamprey-1NN-heatmap-v2.pdf', width=3.9, height=5)
  2380. # ggsave('figures/lamprey-1NN-heatmap.png')
  2381. ```
  2382. Check for doublet clusters in lamprey
  2383. ```{r, fig.height=8, fig.width=15}
  2384. objectList$Lamprey = FindDoublets(objectList$Lamprey, channels = 'animal')
  2385. DoubletAnalysis(objectList$Lamprey, group.by = 'annotated')
  2386. BrowseSeurat(objectList$Lamprey)
  2387. VlnPlot(objectList$Lamprey, features = 'nCount_RNA', group.by = 'annotated')
  2388. ```
  2389. Check ambiguous clusters
  2390. ```{r, fig.height=4.8, fig.width=4.2}
  2391. objectList = ReadSAMapObjects(new.lamprey = TRUE)
  2392. pm2ch = readRDS('../cones/orthology_graphs/pm2ch.rds')
  2393. objectList$Lamprey = ConvertGeneSymbols2(objectList$Lamprey, pm2ch)
  2394. # ClusterFeaturePlot(objectList$Lamprey, group.by = 'annotated', features = c('TFAP2B', 'RBPMS2'), cols = c('white', 'deeppink2'))
  2395. # clusters.of.interest = gsub('pm_', '', c("pm_RGC-34", "pm_RGC-30", "pm_RGC-27", "pm_RGC-37", "pm_RGC-9", "pm_RGC-35", "pm_RGC-41", "pm_RGC-3", "pm_RGC-39", "pm_RGC-1", "pm_RGC-33", "pm_RGC-26", "pm_RGC-31", "pm_RGC-23", "pm_gabaAC-4", "pm_RGC-7"))
  2396. clusters.of.interest = gsub('pm_', '', c("pm_RGC-27", "pm_RGC-9", "pm_RGC-39", "pm_RGC-35", "pm_RGC-3",
  2397. "pm_RGC-41", "pm_RGC-1", "pm_RGC-33", "pm_RGC-26",
  2398. "pm_RGC-22", "pm_RGC-23", "pm_RGC-7", "pm_RGC-31"))
  2399. # pm.ambig = subset(objectList$Lamprey, annotated %in% clusters.of.interest)
  2400. # pm.ambig$annotated = factor(pm.ambig$annotated, levels = rev(clusters.of.interest))
  2401. # objectList$Lamprey$annotated = factor(objectList$Lamprey$annotated, levels = gsub('pm_', '', rev(c(tail(pm_order, -6), pm_order[1:6]))))
  2402. objectList$Lamprey$annotated = factor(objectList$Lamprey$annotated,
  2403. levels = rev(unique(c(clusters.of.interest, levels(objectList$Lamprey$annotated)))))
  2404. sus.clusters = c('pm_offBC-6', 'pm_MG-4', 'pm_gabaAC-3', 'pm_gabaAC-4')
  2405. DotPlot3(subset(objectList$Lamprey, annotated %in% gsub('pm_', '', sus.clusters), invert = T),
  2406. features = c('TFAP2B', 'GAD1', 'RBPMS', 'RBPMS2', 'NEFL', 'NEFM',
  2407. 'OPN4', 'LOC116943951', 'NOS1', 'NPY'),
  2408. # idents = clusters.of.interest,
  2409. show = clusters.of.interest,
  2410. coord.flip = FALSE,
  2411. group.by = 'annotated',
  2412. col.low = 'grey90',
  2413. col.high = 'deeppink3')
  2414. ggsave('figures/fig-lamprey-amiguous-dotplots.pdf', height=4.8, width=4.2)
  2415. ```
  2416. ```{r, fig.height=5, fig.width=20}
  2417. DotPlot3(subset(objectList$Lamprey, annotated %in% gsub('pm_', '', sus.clusters), invert = T),
  2418. features = c('TFAP2B', 'GAD1', 'RBPMS', 'RBPMS2', 'NEFL', 'NEFM',
  2419. 'OPN4', 'LOC116943951', 'NOS1', 'NPY'),
  2420. # idents = clusters.of.interest,
  2421. # show = clusters.of.interest,
  2422. coord.flip = TRUE,
  2423. group.by = 'annotated',
  2424. col.low = 'grey90',
  2425. col.high = 'deeppink3')
  2426. ```
  2427. ## Gene heatmaps
  2428. ```{r, fig.height=5, fig.width=10}
  2429. nmList = ReadSAMapObjects()
  2430. nmList = lapply(nmList, DownsampleSeurat, group.by = 'annotated', size = 50)
  2431. nmList = sapply(names(nmList), function(species){
  2432. nmList[[species]]$annotated = paste0(index$ident[index$species == species], '_', nmList[[species]]$annotated)
  2433. nmList[[species]]
  2434. }, USE.NAMES = TRUE)
  2435. nmList$Zebrafish = NormalizeData(nmList$Zebrafish)
  2436. # nmList$Killifish$annotated = factor(nmList$Killifish$annotated)
  2437. ```
  2438. ```{r, fig.height=5, fig.width=10}
  2439. gene_pairs = as.data.frame(fread('samap/pm_sh_ca_kf_ze_am_ch_li-class-v1-genepairs.csv')[,-1])
  2440. markers.dfs = lapply(setdiff(CELL_CLASSES3, 'Other'), function(class){
  2441. df_onecol = pivot_longer(head(gene_pairs[,grepl(class, colnames(gene_pairs)) &
  2442. !grepl('pval', colnames(gene_pairs))], 600),
  2443. everything(),
  2444. values_to = "value")
  2445. if(class %in% c('onBC', 'offBC', 'gabaAC', 'glyAC', 'RGC'))
  2446. df_onecol = df_onecol[df_onecol$value %in% names(which(table(df_onecol$value) >= 2)), ]
  2447. df_onecol$species1 = ExtractString(ExtractString(df_onecol$value, after = ';'), after = '_')
  2448. df_onecol$gene1 = ExtractString(ExtractString(df_onecol$value, after = ';'), before = '_')
  2449. df_onecol$species2 = ExtractString(ExtractString(df_onecol$value, before = ';'), after = '_')
  2450. df_onecol$gene2 = ExtractString(ExtractString(df_onecol$value, before = ';'), before = '_')
  2451. # browser()
  2452. if(class == 'RGC') browser()
  2453. Reduce(function(dtf1,dtf2) merge(dtf1, dtf2, by="Chicken", all = TRUE), list(
  2454. subset(df_onecol, species1 == 'ch' & species2 == 'pm')[,c('gene1', 'gene2')] %>% setNames(c('Chicken', 'Lamprey')),
  2455. subset(df_onecol, species1 == 'ch' & species2 == 'sh')[,c('gene1', 'gene2')] %>% setNames(c('Chicken', 'Shark')),
  2456. subset(df_onecol, species1 == 'ch' & species2 == 'kf')[,c('gene1', 'gene2')] %>% setNames(c('Chicken', 'Killifish')),
  2457. subset(df_onecol, species1 == 'ch' & species2 == 'ca')[,c('gene1', 'gene2')] %>% setNames(c('Chicken', 'Goldfish')),
  2458. subset(df_onecol, species1 == 'ch' & species2 == 'ze')[,c('gene1', 'gene2')] %>% setNames(c('Chicken', 'Zebrafish')),
  2459. subset(df_onecol, species1 == 'ch' & species2 == 'am')[,c('gene1', 'gene2')] %>% setNames(c('Chicken', 'Axolotl')),
  2460. subset(df_onecol, species1 == 'ch' & species2 == 'li')[,c('gene1', 'gene2')] %>% setNames(c('Chicken', 'Lizard'))
  2461. )) %>% unique
  2462. })
  2463. markers.df = do.call(rbind, lapply(markers.dfs, function(x) {
  2464. # Each gene can appear no more than n times
  2465. x = x %>%
  2466. group_by(Chicken) %>%
  2467. slice_head(n = 10) %>%
  2468. ungroup() %>% as.data.frame()
  2469. # if(nrow(x) >= 1000) x[sample(seq_len(nrow(x)), 1000),] else x[sample(seq_len(nrow(x))),]
  2470. # if(nrow(x) >= 1000) x[1:1000,] else x
  2471. # Scramble order to make prettier
  2472. x[sample(seq_len(nrow(x))),]
  2473. }))
  2474. markers.df$row_annotation = ExtractString(rownames(markers.df), after = '\\.')
  2475. table(markers.df$row_annotation)
  2476. types.use = gsub('PR-L-M', 'PR-L/M', gsub('\\.', '-', cnames))
  2477. types.order = paste0(prefix.key[ExtractString(types.use, after = '_')], ' ', types.use)
  2478. # Check types
  2479. stopifnot(all(types.use %in% unlist(lapply(nmList, function(x) unique(x$annotated)))))
  2480. setdiff(types.use, unlist(lapply(nmList, function(x) unique(x$annotated))))
  2481. setdiff(unlist(lapply(nmList, function(x) unique(x$annotated))), types.use)
  2482. # Check convergence (10:1)
  2483. length(unique(markers.df$Chicken))
  2484. length(unique(markers.df$Lizard))
  2485. length(unique(markers.df$Zebrafish))
  2486. length(unique(markers.df$Killifish))
  2487. # pdf('../../figures/my_figs/nonmammal-integration-genes.pdf', height=5, width=9)
  2488. SAMapHeatmap3(nmList,
  2489. markers.df,
  2490. type_palette = major_annotation_palette2,
  2491. species_palette = species_palette2,
  2492. species.use = c("Chicken", "Lizard", 'Killifish', "Zebrafish"),
  2493. types.use = types.use, #rownames(samap_alignment),
  2494. show_heatmap_legend = FALSE,
  2495. show_row_names = FALSE,
  2496. show_column_names = FALSE,
  2497. min.z.score = -1,
  2498. max.z.score = 2,
  2499. col_fun = circlize::colorRamp2(c(-1, 0, 2), c("white", "white", "deeppink")),
  2500. # width = unit(10, "in"),
  2501. rotate = TRUE,
  2502. types.order = types.order, #rownames(samap_alignment),
  2503. use_raster = TRUE)
  2504. # dev.off()
  2505. ```
  2506. Troubleshooting
  2507. ```{r}
  2508. SAMapHeatmap3(nmList,
  2509. head(subset(markers.df, row_annotation == 'gabaAC'), 20),
  2510. type_palette = major_annotation_palette2,
  2511. species_palette = species_palette2,
  2512. species.use = c("Chicken", "Lizard", 'Killifish', "Zebrafish"),
  2513. types.use = types.use, #rownames(samap_alignment),
  2514. show_heatmap_legend = FALSE,
  2515. show_row_names = FALSE,
  2516. show_column_names = TRUE,
  2517. min.z.score = -2,
  2518. max.z.score = 2,
  2519. col_fun = circlize::colorRamp2(c(-2, 0, 2), c("white", "white", "deeppink")),
  2520. # width = unit(10, "in"),
  2521. rotate = TRUE,
  2522. types.order = types.order, #rownames(samap_alignment),
  2523. use_raster = TRUE)
  2524. ```
  2525. ## Clustered heatmap
  2526. ```{r, fig.height=50, fig.width=50}
  2527. pdf('figures/nonmammals-clustered-heatmap.pdf', height=50, width=50)
  2528. Heatmap(sm.class@matrix)
  2529. Heatmap(sm.bc@matrix)
  2530. dev.off()
  2531. ```
  2532. ## Confusion matrix: BC
  2533. ```{r, fig.height=4, fig.width=15}
  2534. # Assign majority class
  2535. bc.umap$leiden_clusters = bc.umap$leiden_clusters_2
  2536. # bc.umap$leiden_clusters[bc.umap$leiden_clusters == 10] = 6
  2537. cm = ConfusionMatrix(bc.umap$leiden_clusters, bc.umap$cell_class, plot = FALSE)
  2538. # majority.class = factor(apply(cm, 1, function(x) colnames(cm)[which.max(x)]),
  2539. # levels = c('PR', 'onBC', 'offBC', 'HC', 'glyAC', 'gabaAC', 'AC', 'RGC', 'MG'))
  2540. # How many onBC clusters?
  2541. n.clusters = length(which(cm[,'onBC'] > 0.5))
  2542. cluster.order = rev(rownames(cm %>% arrange(offBC)))
  2543. bg = stackedBarGraph2(bc.umap %>%
  2544. mutate(leiden_clusters = factor(as.character(leiden_clusters),
  2545. levels = rev(cluster.order))),
  2546. 'leiden_clusters', 'cell_class', as.factor = TRUE) +
  2547. scale_y_continuous(expand = c(0, 0),
  2548. breaks = c(0, 0.25, 0.5, 0.75, 1), # only first and last
  2549. labels = c('0', '', '', '', '1'),
  2550. minor_breaks = waiver() # keeps automatic minor ticks
  2551. )+
  2552. coord_flip() +
  2553. scale_fill_manual(values = cell_class3_colors)+
  2554. theme_cowplot()+
  2555. NoLegend()+
  2556. theme(axis.text.y = element_blank(),
  2557. axis.title.y = element_blank(),
  2558. axis.ticks.y = element_blank(),
  2559. axis.title.x = element_text(size = 12),
  2560. axis.text.x = element_text(angle = 0, hjust = 0.5))
  2561. ident.2 = 'annotated'
  2562. ident.1 = 'leiden_clusters'
  2563. ob.list = split(bc.umap, bc.umap$species_full)
  2564. heatmapList = lapply(seq_along(ob.list), function(index) {
  2565. JSHeatmap2(ob.list[[index]][[ident.1]],
  2566. ob.list[[index]][[ident.2]],
  2567. title = names(ob.list)[[index]],
  2568. row.order = cluster.order,
  2569. border.col = NA,
  2570. # col.high = 'chartreuse4',
  2571. max.value = 0.5,
  2572. stagger.threshold = 0.15) +
  2573. geom_hline(yintercept = n.clusters+0.5, linetype = 'dashed', color = 'grey')+
  2574. theme(axis.ticks = element_blank(),
  2575. axis.text.x = element_blank(),
  2576. axis.text.y = element_blank(),
  2577. plot.margin = margin(0, 0, 0, 0),
  2578. plot.background = element_rect(fill = "transparent", colour = NA)) +
  2579. NoLegend()
  2580. #seq(0, max(class.umap$leiden_clusters)))
  2581. })
  2582. names(heatmapList) = names(ob.list)
  2583. ncol = length(ob.list)+2
  2584. nrow = 1
  2585. # plt.umap = PrettyUmap2(bc.umap,
  2586. # group.by = 'species_full',
  2587. # label = FALSE,
  2588. # geom.label = geom_text_repel,
  2589. # cols = species_palette3, #major_annotation_palette2,
  2590. # show.legend = FALSE,
  2591. # title = 'BC integration',
  2592. # pt.alpha = 0.3,
  2593. # rasterise = FALSE, pad = 0) +
  2594. # LegendLowerRight(x = 0.99, y = 0.1)
  2595. #
  2596. # plt.umap2 = PrettyUmap2(bc.umap,
  2597. # group.by = 'cell_class2',
  2598. # label = TRUE,
  2599. # geom.label = geom_text_repel,
  2600. # cols = cell_class3_colors,
  2601. # show.legend = FALSE,
  2602. # title = 'BC subclass',
  2603. # pt.alpha = 0.3,
  2604. # rasterise = FALSE,
  2605. # pad = 0) +
  2606. # LegendLowerRight(x = 0.7, y = 0.6) +
  2607. # theme(axis.title.y = element_blank(),
  2608. # plot.margin = unit(c(0,0,0,0), 'cm'))
  2609. #
  2610. # ggarrange(plotlist = c(list(plt.umap),
  2611. # list(plt.umap2),
  2612. # list(NULL), heatmapList, list(bg)),
  2613. # ncol = ncol,
  2614. # nrow = nrow,
  2615. # # common.legend = TRUE,
  2616. # widths = c(40, 35, 8, sapply(ob.list, function(x) length(unique(x$annotated))), 13),
  2617. # # legend = "none",
  2618. # align = 'h')
  2619. ggarrange(plotlist = c(list(NULL), heatmapList, list(bg)),
  2620. ncol = ncol,
  2621. nrow = nrow,
  2622. common.legend = TRUE,
  2623. widths = c(8, sapply(ob.list, function(x) length(unique(x$annotated))), 13),
  2624. # legend = "none",
  2625. align = 'h')
  2626. ggsave('../../figures/my_figs/nonmammal-bc-jaccard.pdf', height=3.5, width=15)
  2627. ```
  2628. Find the errors for each species
  2629. ```{r, fig.height=5, fig.width=20}
  2630. bc.umap$cell_class2_inferred = MatchClusters(bc.umap$leiden_clusters, bc.umap$cell_class2)
  2631. EvaluateModel(table(bc.umap$cell_class2_inferred, bc.umap$cell_class2))
  2632. dapply(levels(bc.umap$species_full), function(this.species){
  2633. sub = subset(bc.umap, species_full == this.species)
  2634. EvaluateModel(table(sub$cell_class2_inferred, sub$cell_class2))
  2635. })
  2636. # Goldfish has most errors
  2637. # What are these clusters being inferred as
  2638. subset(bc.umap, species_full == 'Goldfish')[,c('annotated', 'cell_class2', 'cell_class2_inferred')] %>% unique
  2639. table(subset(bc.umap, species_full == 'Goldfish')$cell_class2,
  2640. subset(bc.umap, species_full == 'Goldfish')$annotated)
  2641. table(subset(bc.umap, species_full == 'Goldfish')$cell_class2_inferred,
  2642. subset(bc.umap, species_full == 'Goldfish')$annotated)
  2643. # ca_onBC-13, ca_onBC-12 is flipped, ca_offBC-10 is mixed (might be low quality or doublets)
  2644. # 12 and 13 seem OFF
  2645. goldfish = readRDS('../../Full_Objects/Goldfish_full_v2.rds')
  2646. DotPlot3(subset(goldfish, cell_class == 'BC'), features = c('isl1', 'grm6a', 'grm6b', 'grik1a', 'grik1b'), group.by = 'annotated')
  2647. VlnPlot(goldfish, features = 'nFeature_RNA', group.by = 'annotated', pt.size = 0) + NoLegend()
  2648. # Check for doublets
  2649. goldfish = FindDoublets(goldfish, 'orig.ident')
  2650. DoubletAnalysis(goldfish, group.by = 'annotated')
  2651. # Other classes
  2652. class.umap$cell_class2_inferred = MatchClusters(class.umap$leiden_clusters, class.umap$cell_class2)
  2653. dapply(levels(bc.umap$species_full), function(this.species){
  2654. sub = subset(class.umap, species_full == this.species)
  2655. table(sub$cell_class2_inferred, sub$cell_class2)
  2656. })
  2657. table(subset(class.umap, species_full == 'Goldfish')$cell_class2_inferred,
  2658. subset(class.umap, species_full == 'Goldfish')$cell_class2)
  2659. # Updated to goldfish v3
  2660. # Check newt; ne_offBC-17 (GRIK1+), onBC-18, 20 as ISL1 low GRIK high so moving to offBC
  2661. table(subset(class.umap, species_full == 'Newt')$cell_class2_inferred,
  2662. subset(class.umap, species_full == 'Newt')$annotated)
  2663. table(subset(bc.umap, species_full == 'Newt')$cell_class2_inferred,
  2664. subset(bc.umap, species_full == 'Newt')$annotated)
  2665. # Check killifish; kf_offBC-17 (mixed), kf_onBC-19 (off, not on), kf_onBC-7 (mixed)
  2666. table(subset(bc.umap, species_full == 'Killifish')$cell_class2_inferred,
  2667. subset(bc.umap, species_full == 'Killifish')$annotated)
  2668. # Check kf for doublets
  2669. kf = readRDS('../../Species_Objects/Killifish_ncbi_initial_v5.rds')
  2670. kf = FindDoublets(kf, 'orig.file')
  2671. DoubletAnalysis(kf, group.by = 'annotated')
  2672. # Not many doublets found, keeping v5 as is
  2673. ```
  2674. ```{r}
  2675. ob.list = split(bc.umap, bc.umap$species_full)
  2676. lapply(seq_along(ob.list), function(index) {
  2677. JSHeatmap2(ob.list[[index]][[ident.1]],
  2678. ob.list[[index]][[ident.2]],
  2679. title = names(ob.list)[[index]],
  2680. row.order = cluster.order,
  2681. # border.col = NA,
  2682. col.high = 'chartreuse4',
  2683. max.value = 0.5,
  2684. stagger.threshold = 0.15) +
  2685. theme(axis.ticks = element_blank(),
  2686. # axis.text.x = element_blank(),
  2687. # axis.text.y = element_blank(),
  2688. plot.margin = margin(0, 0, 0, 0)) +
  2689. NoLegend()
  2690. })
  2691. ```
  2692. RBC:
  2693. pm onBC-5
  2694. sh onBC-3
  2695. ze onBC-14
  2696. ```{r}
  2697. PrettyUmap2(bc.umap %>% mutate(leiden_clusters = as.character(leiden_clusters)), group.by = 'leiden_clusters')
  2698. PrettyUmap2(subset(bc.umap, species == 'ch'), group.by = 'annotated')
  2699. PrettyUmap2(subset(bc.umap, species == 'li'), group.by = 'annotated')
  2700. PrettyUmap2(subset(bc.umap, species == 'ze'), group.by = 'annotated')
  2701. PrettyUmap2(subset(bc.umap, species == 'kf'), group.by = 'annotated')
  2702. ```
  2703. ```{r, fig.width=10, fig.height=3}
  2704. DotPlot3(subset(nmList$Chicken, cell_class == 'BC'), features = c('PRKCA'))
  2705. DotPlot3(nmList$Lizard, features = c('PRKCA'))
  2706. DotPlot3(nmList$Zebrafish, features = c('gramd1bb', 'gramd1ba', 'prkcaa', 'isl1'))
  2707. # LOC107381579 (megf11) LOC107387807 (chat)
  2708. DotPlot3(nmList$Killifish, features = c('gramd1bb', 'gramd1ba', 'prkcaa', 'isl1a','syt5b', 's100a10b'), group.by = 'annotated')
  2709. ```
  2710. Addition of mammals
  2711. ```{r}
  2712. bc.umap2 = as.data.frame(fread('samap/kf_ze_ch_li_mf-BC-v1-umap.csv'))
  2713. colnames(bc.umap2) = gsub('UMAP', 'UMAP_', colnames(bc.umap2))
  2714. bc.umap2$leiden_clusters = as.character(bc.umap2$leiden_clusters_1.5)
  2715. bc.umap2$leiden_clusters[bc.umap2$leiden_clusters == '5'] = '0'
  2716. PrettyUmap2(bc.umap2, group.by = 'leiden_clusters')
  2717. ob.list = split(bc.umap2, bc.umap2$species)
  2718. lapply(seq_along(ob.list), function(index) {
  2719. JSHeatmap2(ob.list[[index]][['leiden_clusters']],
  2720. ob.list[[index]][['annotated']],
  2721. title = names(ob.list)[[index]],
  2722. row.order = sort(unique(bc.umap2$leiden_clusters)),
  2723. # border.col = NA,
  2724. col.high = 'chartreuse4',
  2725. max.value = 0.5,
  2726. stagger.threshold = 0.15) +
  2727. theme(axis.ticks = element_blank(),
  2728. # axis.text.x = element_blank(),
  2729. # axis.text.y = element_blank(),
  2730. plot.margin = margin(0, 0, 0, 0)) +
  2731. NoLegend()
  2732. })
  2733. ```
  2734. Validate SAMap signatures
  2735. ```{r, fig.height=10, fig.width=15}
  2736. gene_pairs = read.csv('samap/kf_ze_ch_li_mf-BC-v1-genepairs.csv', row.names = 1, check.names = FALSE)
  2737. gene_pairs = gene_pairs[,!grepl('pval', colnames(gene_pairs))]
  2738. pdf('samap/kf_ze_ch_li_mf-BC-v1-genepairs.pdf', width = 15, height = 15)
  2739. lapply(colnames(gene_pairs), function(cname){
  2740. # x = gsub('BC.', 'BC-', cname)
  2741. x = cname
  2742. t1 = ExtractString(x, after = ';')
  2743. t2 = ExtractString(x, before = ';')
  2744. s1 = ExtractString(t1, after = '_')
  2745. s2 = ExtractString(t2, after = '_')
  2746. species1 = prefix.key[s1]
  2747. species2 = prefix.key[s2]
  2748. object1 = nmList[[species1]]
  2749. object2 = nmList[[species2]]
  2750. features1 = setdiff(ExtractString(ExtractString(gene_pairs[,cname], after = ';'), before = '_'), '')
  2751. features2 = setdiff(ExtractString(ExtractString(gene_pairs[,cname], before = ';'), before = '_'), '')
  2752. print(paste0(species1, '-', species2))
  2753. TitlePlot(DotPlot3(subset(object1, cell_class == 'BC'), features = features1), paste0(species1, '-', t1)) + NoLegend() |
  2754. TitlePlot(DotPlot3(subset(object2, cell_class == 'BC'), features = features2), paste0(species2, '-', t2))
  2755. })
  2756. dev.off()
  2757. DotPlot3(subset(nmList$Chicken, cell_class == 'BC'), features = 'PRKCA')
  2758. DotPlot3(subset(nmList$Lizard, cell_class == 'BC'), features = 'PRKCA')
  2759. ```
  2760. ## UMAP: BCs
  2761. ```{r, fig.height=4, fig.width=15}
  2762. PrettyUmap2(bc.umap, group.by = 'species_full',
  2763. label = FALSE, geom.label = geom_text_repel,
  2764. box.padding = 0.7, show.legend = TRUE,
  2765. title = 'BC integration (species)', pt.alpha = 0.2,
  2766. cols = species_palette3, rasterise = TRUE,
  2767. nbreaks = 30, remove.times = 3) |
  2768. PrettyUmap2(subset(bc.umap, species_full != 'Lamprey'), group.by = 'cell_class2',
  2769. label = FALSE, geom.label = geom_text_repel,
  2770. box.padding = 2, show.legend = TRUE,
  2771. title = 'Manually annotated BC subclasses (excluding lamprey)', pt.alpha = 0.2,
  2772. cols = cell_class3_colors, rasterise = TRUE,
  2773. nbreaks = 30, remove.times = 3) + LegendLowerLeft() |
  2774. PrettyUmap2(subset(bc.umap, species_full == 'Lamprey'), group.by = 'cell_class2',
  2775. label = FALSE, geom.label = geom_text_repel,
  2776. box.padding = 2, show.legend = TRUE,
  2777. title = 'Manually annotated BC subclasses (lamprey)', pt.alpha = 0.4,
  2778. cols = cell_class3_colors, rasterise = TRUE,
  2779. nbreaks = 30, remove.times = 3) + LegendLowerLeft()
  2780. ggsave('../../figures/my_figs/nonmammal-bc-umap.pdf', height=4, width=15)
  2781. ```
  2782. ## Confusion matrix: AC
  2783. ```{r, fig.height=8, fig.width=10}
  2784. # Assign majority class
  2785. ac.umap$leiden_clusters = factor(as.numeric(factor(ac.umap$leiden_clusters_4.5)))
  2786. message('Found ', length(unique(ac.umap$leiden_clusters)), ' clusters!')
  2787. # Remove tiny clusters
  2788. table(ac.umap$leiden_clusters)
  2789. ac.umap = subset(ac.umap, !leiden_clusters %in% names(which(table(ac.umap$leiden_clusters) < 5)))
  2790. # Merge similar clusters
  2791. # Heatmap(CoclusteringMatrix(factor(subset(ac.umap, species == 'ch')$leiden_clusters),
  2792. # subset(ac.umap, species == 'ch')$annotated))
  2793. # Heatmap(CoclusteringMatrix(factor(subset(ac.umap, species == 'ze')$leiden_clusters),
  2794. # subset(ac.umap, species == 'ze')$annotated))
  2795. # Averged across all species
  2796. Heatmap(CoclusteringMatrix(factor(ac.umap$leiden_clusters),
  2797. ac.umap$annotated))
  2798. # clust = hclust(dist(1-CoclusteringMatrix(factor(subset(ac.umap, species == 'ch')$leiden_clusters),
  2799. # subset(ac.umap, species == 'ch')$annotated)), method = 'average')
  2800. # plot(clust)
  2801. # Merge 12 and 26 with resolution 4
  2802. # ac.umap$leiden_clusters[ac.umap$leiden_clusters == 26] = 12
  2803. # Merge 35/7, 20/2, 12/4, 5/6, 24/13 with resolution 4.5
  2804. # ac.umap$leiden_clusters[ac.umap$leiden_clusters == 35] = 7
  2805. # ac.umap$leiden_clusters[ac.umap$leiden_clusters == 20] = 2
  2806. # ac.umap$leiden_clusters[ac.umap$leiden_clusters == 12] = 4
  2807. # ac.umap$leiden_clusters[ac.umap$leiden_clusters == 6] = 5
  2808. # ac.umap$leiden_clusters[ac.umap$leiden_clusters == 24] = 13
  2809. # ac.umap$leiden_clusters = factor(ac.umap$leiden_clusters)
  2810. # Merge 32 and 12 with resolution 5
  2811. # Merge 35 and 11 with resolution 4.5
  2812. ac.umap$leiden_clusters[ac.umap$leiden_clusters == 35] = 11
  2813. ac.umap$leiden_clusters = RenumberClustering(ac.umap$leiden_clusters, zero.base = FALSE)
  2814. table(ac.umap$leiden_clusters)
  2815. ```
  2816. Supplementary figure
  2817. ```{r}
  2818. # ac.umap = as.data.frame(fread('samap/pm_sh_ca_kf_ze_ne_am_ch_li-ac-v3-umap.csv'))
  2819. # ac.umap$species_full = convert_values(ac.umap$species, index$species %>% setNames(index$ident))
  2820. # ac.umap$species_full = factor(factor(ac.umap$species_full, levels = index$species))
  2821. # prefix.key = index$species %>% setNames(index$ident)
  2822. ac.umap$cell_class2 = gsub('gabaAC', 'gaAC', gsub('glyAC', 'glAC', ac.umap$cell_class2))
  2823. major_annotation_palette3 = major_annotation_palette2
  2824. names(major_annotation_palette3) = gsub('gabaAC', 'gaAC', gsub('glyAC', 'glAC', names(major_annotation_palette3)))
  2825. PrettyUmap2(ac.umap,
  2826. group.by = 'cell_class2',
  2827. label = FALSE,
  2828. geom.label = geom_text_repel,
  2829. cols = major_annotation_palette3,
  2830. show.legend = TRUE,
  2831. title = 'Non-mammalian AC integration (subclass)',
  2832. pt.alpha = 0.2,
  2833. remove.times = 3,
  2834. rasterise = FALSE,
  2835. pad = 0) +
  2836. LegendTopLeft() +
  2837. theme(axis.title.y = element_blank(),
  2838. plot.margin = unit(c(0,0,0,0), units = 'cm')) |
  2839. PrettyUmap2(ac.umap,
  2840. group.by = 'leiden_clusters',
  2841. label = TRUE,
  2842. geom.label = geom_text_repel,
  2843. # cols = species_palette2,
  2844. show.legend = FALSE,
  2845. title = 'Non-mammalian oACs',
  2846. pt.alpha = 0.2,
  2847. remove.times = 3,
  2848. rasterise = FALSE,
  2849. min.segment.length = 0.1,
  2850. size = 2.5,
  2851. pad = 0)
  2852. ggsave('../../figures/my_figs/nonmammalian-oacs-umap.pdf', height = 3.2, width = 8)
  2853. ```
  2854. ```{r, fig.height=3.5, fig.width=18}
  2855. #' Assign majority class, plot umap, and plot jaccard matrices
  2856. # ac.umap$leiden_clusters = factor(as.numeric(factor(ac.umap$leiden_clusters_4.5)))
  2857. message('Found ', length(unique(ac.umap$leiden_clusters)), ' clusters!')
  2858. cm = ConfusionMatrix(ac.umap$leiden_clusters, ac.umap$cell_class2, plot = FALSE)
  2859. cluster.order = rev(rownames(cm %>% arrange(glyAC)))
  2860. majority.class = factor(apply(cm, 1, function(x) colnames(cm)[which.max(x)]), levels = c('PR', 'onBC', 'offBC', 'HC', 'glyAC', 'gabaAC', 'AC', 'RGC', 'MG'))
  2861. # apply(cm[cluster.order, ], 1, max)
  2862. bg = stackedBarGraph2(ac.umap %>%
  2863. mutate(leiden_clusters = factor(as.character(leiden_clusters),
  2864. levels = rev(cluster.order))),
  2865. 'leiden_clusters', 'cell_class2', as.factor = TRUE) +
  2866. scale_y_continuous(expand = c(0, 0),
  2867. breaks = c(0, 0.25, 0.5, 0.75, 1), # only first and last
  2868. labels = c('0', '', '', '', '1'),
  2869. minor_breaks = waiver() # keeps automatic minor ticks
  2870. )+
  2871. coord_flip() +
  2872. scale_fill_manual(values = major_annotation_palette2)+
  2873. theme_cowplot()+
  2874. NoLegend()+
  2875. theme(axis.text.y = element_blank(),
  2876. axis.title.y = element_blank(),
  2877. axis.ticks.y = element_blank(),
  2878. axis.title.x = element_text(size = 12),
  2879. axis.text.x = element_text(angle = 0, hjust = 0.5, size = 10))
  2880. ident.2 = 'annotated'
  2881. ident.1 = 'leiden_clusters'
  2882. ob.list = split(ac.umap, ac.umap$species_full)
  2883. heatmapList = lapply(seq_along(ob.list), function(index) {
  2884. JSHeatmap2(ob.list[[index]][[ident.1]],
  2885. ob.list[[index]][[ident.2]],
  2886. title = names(ob.list)[[index]],
  2887. row.order = cluster.order,
  2888. border.col = NA,
  2889. # col.high = 'cyan4',
  2890. max.value = 0.5,
  2891. stagger.threshold = 0.10) +
  2892. # geom_hline(yintercept = difference(majority.class[rev(cluster.order)]) - 0.5, linetype = 'solid', color = 'grey', linewidth = 0.4, alpha = 0.4)+
  2893. theme(axis.ticks = element_blank(),
  2894. axis.text.x = element_blank(),
  2895. axis.text.y = element_blank(),
  2896. plot.margin = margin(0, 0, 0, 0),
  2897. plot.background = element_rect(fill = "transparent", colour = NA)) +
  2898. NoLegend()
  2899. #seq(0, max(class.umap$leiden_clusters)))
  2900. })
  2901. names(heatmapList) = names(ob.list)
  2902. ncol = length(ob.list)+3
  2903. nrow = 1
  2904. ac.umap$species_full2 = as.character(ac.umap$species_full)
  2905. plt.umap = PrettyUmap2(ac.umap,
  2906. group.by = 'species_full',
  2907. label = FALSE,
  2908. geom.label = geom_text_repel,
  2909. cols = species_palette2,
  2910. show.legend = TRUE,
  2911. title = 'Non-mammal integration',
  2912. pt.alpha = 0.2,
  2913. remove.times = 3,
  2914. rasterise = FALSE,
  2915. pad = 0) +
  2916. LegendLowerRight(size = 8, line.spacing = 0.7, x = 1.01)
  2917. plt.umap2 = PrettyUmap2(ac.umap,
  2918. group.by = 'cell_class2',
  2919. label = FALSE,
  2920. geom.label = geom_text_repel,
  2921. cols = major_annotation_palette2,
  2922. show.legend = TRUE,
  2923. title = 'AC subclasses',
  2924. pt.alpha = 0.2,
  2925. rasterise = FALSE,
  2926. pad = 0) +
  2927. LegendLowerLeft() +
  2928. theme(axis.title.y = element_blank(),
  2929. plot.margin = unit(c(0,0,0,0), units = 'cm'))
  2930. ggarrange(plotlist = c(list(plt.umap),
  2931. # list(plt.umap2),
  2932. list(NULL), heatmapList, list(bg)),
  2933. ncol = ncol,
  2934. nrow = nrow,
  2935. # common.legend = TRUE,
  2936. widths = c(100, 10, sapply(ob.list, function(x) length(unique(x$annotated))), 22),
  2937. # legend = "none",
  2938. align = 'h')
  2939. # ggsave('../../figures/my_figs/nonmammal-integration-AC-noline.pdf', height=3.5, width=18)
  2940. ```
  2941. ```{r, fig.height=5, fig.width=40}
  2942. # ac.umap$leiden_clusters = factor(as.numeric(factor(ac.umap$leiden_clusters_4.5)))
  2943. # ac.umap$leiden_clusters[ac.umap$leiden_clusters == 10] = 6
  2944. cm = ConfusionMatrix(ac.umap$leiden_clusters, ac.umap$cell_class, plot = FALSE)
  2945. # majority.class = factor(apply(cm, 1, function(x) colnames(cm)[which.max(x)]),
  2946. # levels = c('PR', 'onBC', 'offBC', 'HC', 'glyAC', 'gabaAC', 'AC', 'RGC', 'MG'))
  2947. cluster.order = rev(rownames(cm %>% arrange(glyAC)))
  2948. majority.class = factor(apply(cm, 1, function(x) colnames(cm)[which.max(x)]), levels = c('PR', 'onBC', 'offBC', 'HC', 'glyAC', 'gabaAC', 'AC', 'RGC', 'MG'))
  2949. ident.2 = 'annotated'
  2950. ident.1 = 'leiden_clusters'
  2951. ob.list = split(ac.umap, ac.umap$species_full)
  2952. heatmapList = lapply(seq_along(ob.list), function(index) {
  2953. JSHeatmap2(ob.list[[index]][[ident.1]],
  2954. ob.list[[index]][[ident.2]],
  2955. title = names(ob.list)[[index]],
  2956. row.order = cluster.order,
  2957. border.col = 'black',
  2958. # col.high = 'cyan4',
  2959. max.value = 0.5,
  2960. stagger.threshold = 0.10) +
  2961. geom_hline(yintercept = difference(majority.class[rev(cluster.order)]) - 0.5, linetype = 'dashed', color = 'grey')+
  2962. theme(axis.ticks = element_blank(),
  2963. #axis.text.x = element_blank(),
  2964. #axis.text.y = element_blank(),
  2965. plot.margin = margin(0, 0, 0, 0)) +
  2966. NoLegend()
  2967. #seq(0, max(class.umap$leiden_clusters)))
  2968. })
  2969. plot_grid(plotlist = heatmapList, nrow = 1, align = 'h', axis = 'bt', rel_widths = sapply(ob.list, function(x) length(unique(x$annotated))))
  2970. ggsave('figures/nonmammal-ac-jaccard-v3.pdf')
  2971. ```
  2972. ```{r, fig.height=5, fig.width=30}
  2973. #' Find the errors
  2974. ac.umap$cell_class2_inferred = MatchClusters(ac.umap$leiden_clusters, ac.umap$cell_class2)
  2975. EvaluateModel(table(ac.umap$cell_class2_inferred, ac.umap$cell_class2))
  2976. dapply(levels(ac.umap$species_full), function(this.species){
  2977. sub = subset(ac.umap, species_full == this.species)
  2978. message(this.species)
  2979. EvaluateModel(table(sub$cell_class2_inferred, sub$cell_class2))
  2980. })
  2981. # errors are rare
  2982. # Zebrafish has one cluster ze_glyAC-18 but it is solidly slc6a9+ and gad1/2-
  2983. table(subset(ac.umap, species == 'ze')$cell_class2_inferred,
  2984. subset(ac.umap, species == 'ze')$annotated)
  2985. ze = readRDS('../../Full_Objects/Zebrafish_full_v3.rds')
  2986. DotPlot3(ze, group.by = 'annotated', features = c('gad1a', 'gad1b', 'gad2', 'slc6a9', 'slc6a5'))
  2987. ```
  2988. pm_RGC-13 seems glycinergic, expresses GlyT2
  2989. pm_RGC-4
  2990. pm_RGC-19
  2991. Near perfect 1:1 correspondence between chicken and zebrafish
  2992. ```{r}
  2993. PrettyUmap2(subset(ac.umap, species_full == 'Lamprey'),
  2994. group.by = 'cell_class2',
  2995. label = FALSE,
  2996. geom.label = geom_text_repel,
  2997. cols = major_annotation_palette2,
  2998. show.legend = FALSE,
  2999. title = 'AC subclass',
  3000. pt.alpha = 1,
  3001. rasterise = FALSE,
  3002. pad = 0)
  3003. PrettyUmap2(subset(ac.umap, species_full == 'Killifish'),
  3004. group.by = 'cell_class2',
  3005. label = FALSE,
  3006. geom.label = geom_text_repel,
  3007. cols = major_annotation_palette2,
  3008. show.legend = FALSE,
  3009. title = 'AC subclass',
  3010. pt.alpha = 1,
  3011. rasterise = FALSE,
  3012. pad = 0)
  3013. ```
  3014. ```{r, fig.height=8, fig.width=30}
  3015. PrettyUmap2(ac.umap,
  3016. group.by = 'leiden_clusters',
  3017. label = TRUE,
  3018. geom.label = geom_text_repel,
  3019. # cols = major_annotation_palette2,
  3020. show.legend = FALSE,
  3021. title = 'AC subclass',
  3022. pt.alpha = 0.2,
  3023. rasterise = FALSE,
  3024. pad = 0)
  3025. # ConfusionMatrix(ac.umap$leiden_clusters, ac.umap$annotated, plot = FALSE)['27',] %>% unlist %>% sort %>% tail # oAC37 ortholog
  3026. # ConfusionMatrix(ac.umap$leiden_clusters, ac.umap$annotated, plot = FALSE)['23',] %>% unlist %>% sort %>% tail # VG3 ortholog
  3027. # ConfusionMatrix(ac.umap$leiden_clusters, ac.umap$annotated, plot = FALSE)['29',] %>% unlist %>% sort %>% tail # VG3 ortholog
  3028. plot_grid(
  3029. plotlist = lapply(seq_along(ob.list), function(index) {
  3030. JSHeatmap2(ob.list[[index]][[ident.1]],
  3031. ob.list[[index]][[ident.2]],
  3032. title = names(ob.list)[[index]],
  3033. row.order = cluster.order,
  3034. border.col = NA,
  3035. col.high = 'cyan4',
  3036. max.value = 0.5,
  3037. stagger.threshold = 0.15) +
  3038. theme(axis.ticks = element_blank(),
  3039. # axis.text.x = element_blank(),
  3040. # axis.text.y = element_blank(),
  3041. plot.margin = margin(0, 0, 0, 0)) +
  3042. NoLegend()
  3043. #seq(0, max(class.umap$leiden_clusters)))
  3044. }),
  3045. align = 'h',
  3046. rel_widths = sapply(ob.list, function(x) length(unique(x$annotated))),
  3047. nrow = 1)
  3048. ```
  3049. ## Alignment matrix: AC
  3050. ```{r, fig.height=8, fig.width=9}
  3051. ac_alignment = as.matrix(read.csv("samap/pm_sh_ca_kf_ze_ne_am_ch_li-ac-v2-mappingtable.csv", row.names = 1))
  3052. pdf('../../figures/my_figs/nonmammal-integration-matrix-ac.pdf', height=45, width=46)
  3053. sm.class = SAMapAlignmentHeatmap2(ac_alignment,
  3054. cell_class3_colors,
  3055. nm_palette2,
  3056. # width = unit(19, "in"),
  3057. # height = unit(19, "in"),
  3058. show_annotation_legend = TRUE,
  3059. show_row_names = TRUE,
  3060. show_column_names = TRUE,
  3061. species.use = c('pm', 'sh', 'kf', 'ca', 'ze', 'ne', 'am', 'ch', 'li'),
  3062. type.order = CELL_CLASSES3,
  3063. max.value = 0.4,
  3064. cols = c('white', 'deeppink', 'deeppink4'),
  3065. rect_gp = gpar(col = "grey", lwd = 0),
  3066. use_raster = TRUE,
  3067. raster_quality = 2,
  3068. raster_by_magick = TRUE)
  3069. dev.off()
  3070. cnames = rownames([email hidden])
  3071. ```
  3072. ## Orthotype correspondence
  3073. ```{r, fig.height=5, fig.width=6}
  3074. if(!exists('ac.ortho')) ac.ortho = LoadACOrtho()
  3075. ac.umap$orthotypes_li = ac.ortho$type[paste0(ac.umap$species_full, '_', apply(str_split_fixed(ac.umap$V1, '-', 3)[,1:2], 1, paste, collapse = '-'))]
  3076. ac.umap$orthotypes_ch = ac.ortho$type[paste0(ac.umap$species_full, '_', ExtractString(ac.umap$V1, after = '-'))]
  3077. ac.umap$orthotypes = ifelse(is.na(ac.umap$orthotypes_li), as.character(ac.umap$orthotypes_ch), as.character(ac.umap$orthotypes_li))
  3078. ac.umap$orthotypes = orthotype_labels(ac.umap$orthotypes, as.factor = FALSE)
  3079. # Tabulation and counting
  3080. js.mat = JSMatrix(table(factor(ac.umap$orthotypes, ORTHOTYPES), ac.umap$leiden_clusters))
  3081. apply(js.mat, 1, function(x) max(x) > 0.25)
  3082. over.stats = OverlapStatistics(table(factor(ac.umap$orthotypes, ORTHOTYPES), ac.umap$leiden_clusters))
  3083. unique(subset(over.stats, padj < 0.05)$ident1)
  3084. # ac.umap$leiden_clusters = ac.umap$leiden_clusters_4
  3085. # JSHeatmap2(subset(ac.umap, species == 'ch')$orthotypes_ch, subset(ac.umap, species == 'ch')$leiden_clusters, stagger.threshold = 0.1)
  3086. # JSHeatmap2(subset(ac.umap, species == 'ch')$orthotypes_ch, subset(ac.umap, species == 'ch')$annotated, stagger.threshold = 0.1)
  3087. # JSHeatmap2(subset(ac.umap, species == 'li')$orthotypes_li, subset(ac.umap, species == 'li')$leiden_clusters, stagger.threshold = 0.1)
  3088. # JSHeatmap2(ac.umap$orthotypes, ac.umap$leiden_clusters, stagger.threshold = 0.1, row.order = levels(ac.ortho$orthotype))
  3089. ggarrange(
  3090. JSHeatmap2(factor(ac.umap$orthotypes, ORTHOTYPES),
  3091. ac.umap$leiden_clusters,
  3092. stagger.threshold = 0.1,
  3093. row.order = ORTHOTYPES,
  3094. border.col = NA,
  3095. title = '') +
  3096. # coord_flip()+
  3097. ArialFont()+
  3098. theme(axis.text.y = element_text(size = 5, color = 'black',
  3099. # margin = margin(b = -200)
  3100. # margin = unit(c(0,0,0,0), 'cm')
  3101. ),
  3102. axis.ticks.length.y = unit(1, "pt"),
  3103. axis.ticks = element_blank(),
  3104. axis.text.x = element_blank(), #element_text(size = 5, color = 'black'),
  3105. plot.background = element_rect(fill = "transparent", colour = NA)) +
  3106. scale_y_discrete(position = "right"),
  3107. common.legend = TRUE,
  3108. legend = 'none')
  3109. ggsave('../../figures/my_figs/orthotype-correspondence.pdf', height = 3.5, width = 3.5)
  3110. js.dat = JSHeatmap2(ac.umap$orthotypes,
  3111. ac.umap$leiden_clusters,
  3112. stagger.threshold = 0.1,
  3113. # row.order = levels(ac.ortho$type),
  3114. border.col = NA,
  3115. title = '')
  3116. saveRDS(js.dat, '../../Ortho_Objects/js.dat.rds')
  3117. overlap.list = OverlapStatistics(table(ac.umap$orthotypes, ac.umap$leiden_clusters))
  3118. lapply(unique(overlap.list$ident1), function(i) CorrespondingCluster(overlap.list, cluster = i))
  3119. key = MatchClusters(ac.umap$orthotypes, ac.umap$leiden_clusters, return.key = TRUE)
  3120. table(MatchClusters(subset(ac.umap, species %in% c('ch', 'li'))$orthotypes,
  3121. subset(ac.umap, species %in% c('ch', 'li'))$leiden_clusters, return.key = FALSE))
  3122. # Bidirectional best hits (25)
  3123. bbh = BidirectionalBestHits(JSMatrix(table(ac.umap$orthotypes, ac.umap$leiden_clusters)))
  3124. bbh = subset(cbind(bbh, do.call(rbind, apply(bbh, 1, function(x) subset(overlap.list, ident1 == x['row'] & ident2 == x['col'])))), overlap > 9)
  3125. saveRDS(bbh, '../../Ortho_Objects/bbh_v2.rds')
  3126. ```
  3127. Unordered for SFN
  3128. ```{r, fig.height=4, fig.width=4}
  3129. custom.order = c(
  3130. "oAC1 [A2]", "oAC2 [VG3]", "oAC3 [TRHDE]", "oAC4 [TRHDE]", "oAC5",
  3131. "oAC6 [A8]", "oAC7 [SEG]", "oAC8 [NNgly]", "oAC9", "oAC10 [ROBO3]",
  3132. "oAC11 [SLC35D3]", "oAC12", "oAC13 [A17]", "oAC14 [A17]", "oAC15", "oAC20 [NPY]",
  3133. "oAC16* [MAF]", "oAC21* [MAF]", "oAC17*", "oAC29", "oAC18 [nNOS]", "oAC19 [CA2]",
  3134. "oAC22*", "oAC23*", "oAC24", "oAC25*", "oAC26", "oAC27",
  3135. "oAC28", "oAC30 [PDGFRA]", "oAC31", "oAC32", "oAC33 [VIP]",
  3136. "oAC34 [RXRG]", "oAC35", "oAC36* [NNgaba]", "oAC37* [CRH]",
  3137. "oAC38* [nNOS]", "oAC39* [CA1]", "oAC40 [nNOS]", "oAC41",
  3138. "oAC42* [SAC]"
  3139. )
  3140. ggarrange(
  3141. JSHeatmap2(ac.umap$orthotypes,
  3142. ac.umap$leiden_clusters,
  3143. stagger.threshold = 0.1,
  3144. row.order = custom.order,
  3145. border.col = NA) +
  3146. # coord_flip()+
  3147. ArialFont()+
  3148. theme(axis.text.y = element_text(size = 5, color = 'black'),
  3149. axis.ticks = element_blank(),
  3150. plot.title = element_blank(),
  3151. axis.text.x = element_blank(), #element_text(size = 5, color = 'black'),
  3152. plot.background = element_rect(fill = "transparent", colour = NA)) +
  3153. scale_y_discrete(position = "right"),
  3154. common.legend = TRUE,
  3155. legend = 'none')
  3156. ggsave('../../figures/my_figs/orthotype-correspondence-unordered.pdf', height = 3.5, width = 3.5)
  3157. ```
  3158. Need to run cells above (confusion AC, ac alignment, and bbh before this)
  3159. ```{r, fig.height=20, fig.width=20}
  3160. # Split by species
  3161. cm.ac = do.call(cbind, lapply(seq_along(ob.list), function(index) JSMatrix(table(ob.list[[index]]$leiden_clusters, ob.list[[index]]$annotated))))
  3162. # cm.ac = ConfusionMatrix(ac.umap$leiden_clusters, ac.umap$annotated, plot = FALSE, row.norm = TRUE)
  3163. ac.groups = lapply(seq_len(nrow(cm.ac)), function(i) colnames(cm.ac)[which(cm.ac[i,] > 0.15)]) # jaccard threshold
  3164. ac.groups.sorted = ac.groups[as.numeric((levels(js.dat$data$col)))]
  3165. names(ac.groups.sorted) = levels(js.dat$data$col)
  3166. saveRDS(ac.groups.sorted, 'samap/ac.groups.sorted.rds')
  3167. # Remove singletons? Removing any cluster who's max alignment score was less than some threshold
  3168. singletons = rownames(ac_alignment)[apply(ac_alignment, 1, function(x) max(x) < 0.20)]
  3169. ac.groups.sorted = lapply(ac.groups.sorted, function(x) setdiff(x, singletons))
  3170. ac.groups = lapply(ac.groups, function(x) setdiff(x, singletons))
  3171. saveRDS(ac.groups, 'samap/ac.groups.rds')
  3172. ```
  3173. <!-- ## Generate correspondences between amniotes and non-mammals -->
  3174. ```{r, fig.height=4, fig.width=20}
  3175. # NNgaba
  3176. sm.ac@matrix['li_gabaAC-36',] %>% sort
  3177. sm.ac@matrix['li_gabaAC-32',] %>% sort
  3178. sm.ac@matrix['ch_gabaAC-62',] %>% sort
  3179. # BHLHE22+
  3180. sm.ac@matrix['ze_glyAC-18',] %>% sort
  3181. sm.ac@matrix['ze_gabaAC-39',] %>% sort
  3182. DotPlot3(nmList$Chicken, features = c('BHLHE22', 'CHAT', 'SLC18A3', 'CADPS2', 'KCNH5', 'MAP7D2', 'CARMIL1', 'PCDH11X', 'ARHGAP21'), group.by = 'annotated')
  3183. DotPlot3(nmList$Lizard, features = c('BHLHE22', 'CHAT', 'SLC18A3', 'CADPS2', 'KCNH5', 'MAP7D2', 'CARMIL1', 'PCDH11X', 'ARHGAP21'))
  3184. DotPlot3(nmList$Zebrafish, features = c('bhlhe22', 'chata', 'slc18a3a', 'cadps2', 'kcnh5a', 'map7d2a', 'foxp4', 'carmil3', 'pcdh11', 'arhgap23b'))
  3185. DotPlot3(nmList$Killifish, features = c('bhlhe22', 'chata', 'slc18a3a', 'cadps2', 'kcnh5a', 'map7d2a', 'foxp4', 'carmil3', 'pcdh11', 'arhgap23b'), group.by = 'annotated')
  3186. DotPlot3(nmList$Goldfish, features = c('bhlhe22', 'chata', 'slc18a3a', 'cadps2', 'kcnh5a', 'map7d2a', 'foxp4', 'carmil3', 'pcdh11', 'arhgap23b'), group.by = 'annotated')
  3187. # PDGFRA
  3188. sm.ac@matrix['li_gabaAC-35',] %>% sort
  3189. sm.ac@matrix['ch_gabaAC-20',] %>% sort
  3190. sm.ac@matrix['ze_gabaAC-50_nNOS',] %>% sort
  3191. sm.ac@matrix['ze_gabaAC-30',] %>% sort
  3192. sm.class@matrix['ze_gabaAC-50_nNOS',] %>% sort
  3193. sm.class@matrix['ze_gabaAC-30',] %>% sort
  3194. DotPlot3(nmList$Killifish, features = c('pdgfra', 'ddc'))
  3195. DotPlot3(nmList$Zebrafish, features = c('pdgfra', 'ddc'))
  3196. DotPlot3(nmList$Chicken, features = 'PDGFRA')
  3197. DotPlot3(nmList$Lizard, features = 'PDGFRA')
  3198. kfish.ac = Harmonize(subset(nmList$Killifish, cell_class == 'AC'), 'orig.file')
  3199. FeaturePlot(kfish.ac, features = 'pdgfra', order = TRUE)
  3200. # li_CADPS2;ze_cadps2
  3201. # li_KCNH5;ze_kcnh5a
  3202. # li_MAP7D2;ze_map7d2a
  3203. # li_FOXP1;ze_foxp4
  3204. # li_CARMIL1;ze_carmil3
  3205. # li_PCDH11X;ze_pcdh11
  3206. # li_ARHGAP21;ze_arhgap23b
  3207. ```
  3208. ### Figure S11
  3209. ```{r, fig.height=4, fig.width=15}
  3210. ac.umap = readRDS('../../Ortho_Objects/ac.umap.final.rds')
  3211. ac.umap$orthotypes_li = ac.ortho$type[paste0(ac.umap$species_full, '_', apply(str_split_fixed(ac.umap$V1, '-', 3)[,1:2], 1, paste, collapse = '-'))]
  3212. ac.umap$orthotypes_ch = ac.ortho$type[paste0(ac.umap$species_full, '_', ExtractString(ac.umap$V1, after = '-'))]
  3213. ac.umap$orthotypes = ifelse(is.na(ac.umap$orthotypes_li), as.character(ac.umap$orthotypes_ch), as.character(ac.umap$orthotypes_li))
  3214. ac.umap$orthotypes = orthotype_labels(ac.umap$orthotypes, as.factor = FALSE)
  3215. # Tabulation and counting
  3216. js.mat = JSMatrix(table(factor(ac.umap$orthotypes, ORTHOTYPES), ac.umap$leiden_clusters))
  3217. p1 = JSHeatmap2(factor(ac.umap$orthotypes, ORTHOTYPES),
  3218. ac.umap$leiden_clusters,
  3219. stagger.threshold = 0.1,
  3220. row.order = ORTHOTYPES,
  3221. border.col = NA,
  3222. title = paste0('Bridge: chicken and lizard', '\n ARI: ',
  3223. round(adj.rand.index(factor(ac.umap$orthotypes, ORTHOTYPES), ac.umap$leiden_clusters), 2))) +
  3224. # coord_flip()+
  3225. ArialFont()+
  3226. theme(axis.text.y = element_text(size = 6, color = 'black',
  3227. # margin = margin(b = -200)
  3228. # margin = unit(c(0,0,0,0), 'cm')
  3229. ),
  3230. axis.ticks.length.y = unit(1, "pt"),
  3231. axis.ticks = element_blank(),
  3232. axis.text.x = element_blank(), #element_text(size = 5, color = 'black'),
  3233. plot.background = element_rect(fill = "transparent", colour = NA)) +
  3234. scale_y_discrete(position = "right") + NoLegend()
  3235. # res.chli = process_ortho_heatmap('samap/pm_sh_ca_kf_ze_ne_am_ch_li-ac-v1-umap.csv',
  3236. # stagger.threshold = 0.1,
  3237. # cluster_col = "leiden_clusters_4.5")
  3238. res.ch = process_ortho_heatmap('samap/pm_sh_ca_kf_ze_ne_am_ch-ac-v1-umap.csv',
  3239. stagger.threshold = 0.1,
  3240. cluster_col = "leiden_clusters_5",
  3241. title_label = 'Bridge: chicken')
  3242. res.chop = process_ortho_heatmap('samap/pm_sh_ca_kf_ze_ne_am_ch_op-ac-v1-umap.csv',
  3243. stagger.threshold = 0.1,
  3244. cluster_col = "leiden_clusters_4",
  3245. title_label = 'Bridge: chicken and opossum')
  3246. res.chliop = process_ortho_heatmap('samap/pm_sh_ca_kf_ze_ne_am_ch_li_op-ac-v1-umap.csv',
  3247. stagger.threshold = 0.15,
  3248. cluster_col = "leiden_clusters_4.5",
  3249. title_label = 'Bridge: chicken, lizard, opossum')
  3250. res.mfms = process_ortho_heatmap('samap/pm_sh_kf_ze_am_ch_li_op_mm_mf-ac-v1-umap.csv',
  3251. stagger.threshold = 0.15,
  3252. cluster_col = "leiden_clusters_4",
  3253. title_label = 'Bridge: chicken, lizard, \nopossum, mouse, macaque')
  3254. p1 | res.ch$plot | res.chop$plot | res.chliop$plot | res.mfms$plot
  3255. ggsave('../../figures/my_figs/samap-robustness.pdf')
  3256. # res.ch$plot | p2
  3257. ```
  3258. ```{r}
  3259. ac.umap.chliop = as.data.frame(fread('samap/pm_sh_ca_kf_ze_ne_am_ch-ac-v1-umap.csv')) # chicken and opossum
  3260. ac.umap.chliop$leiden_clusters = ac.umap.chliop$leiden_clusters_5
  3261. ac.umap.chliop$species_full = convert_values(ac.umap.chliop$species, index$species %>% setNames(index$ident))
  3262. ac.umap.chliop$species_full = factor(factor(ac.umap.chliop$species_full, levels = index$species))
  3263. ac.umap.chliop$orthotypes_li = ac.ortho$type[paste0(ac.umap.chliop$species_full, '_', apply(str_split_fixed(ac.umap.chliop$V1, '-', 3)[,1:2], 1, paste, collapse = '-'))]
  3264. ac.umap.chliop$orthotypes_ch = ac.ortho$type[paste0(ac.umap.chliop$species_full, '_', ExtractString(ac.umap.chliop$V1, after = '-'))]
  3265. ac.umap.chliop$orthotypes = ifelse(is.na(ac.umap.chliop$orthotypes_li), as.character(ac.umap.chliop$orthotypes_ch), as.character(ac.umap.chliop$orthotypes_li))
  3266. ac.umap.chliop$orthotypes = orthotype_labels(ac.umap.chliop$orthotypes, as.factor = FALSE)
  3267. # Tabulation and counting
  3268. js.mat.chliop = JSMatrix(table(factor(ac.umap.chliop$orthotypes, ORTHOTYPES), ac.umap.chliop$leiden_clusters))
  3269. # over.stats = OverlapStatistics(table(factor(ac.umap.noliz$orthotypes, ORTHOTYPES), ac.umap.noliz$leiden_clusters))
  3270. ggarrange(
  3271. JSHeatmap2(factor(ac.umap.chliop$orthotypes, ORTHOTYPES),
  3272. ac.umap.chliop$leiden_clusters,
  3273. stagger.threshold = 0.15,
  3274. row.order = ORTHOTYPES,
  3275. border.col = NA,
  3276. title = 'Bridge: chicken, lizard, and opossum') +
  3277. # coord_flip()+
  3278. ArialFont()+
  3279. theme(axis.text.y = element_text(size = 6, color = 'black',
  3280. # margin = margin(b = -200)
  3281. # margin = unit(c(0,0,0,0), 'cm')
  3282. ),
  3283. axis.ticks.length.y = unit(1, "pt"),
  3284. axis.ticks = element_blank(),
  3285. axis.text.x = element_blank(), #element_text(size = 5, color = 'black'),
  3286. plot.background = element_rect(fill = "transparent", colour = NA)) +
  3287. scale_y_discrete(position = "right"),
  3288. common.legend = TRUE,
  3289. legend = 'none')
  3290. ```
  3291. ```{r, fig.height= 4, fig.width=16}
  3292. nrow(BidirectionalBestHits(js.mat, verbose = F))
  3293. nrow(BidirectionalBestHits(res.ch$matrix, verbose = F))
  3294. nrow(BidirectionalBestHits(res.chop$matrix, verbose = F))
  3295. nrow(BidirectionalBestHits(res.chliop$matrix, verbose = F))
  3296. nrow(BidirectionalBestHits(res.mfms$matrix, verbose = F))
  3297. best.jac.df = data.frame(orthotype = get_numbers(rownames(js.mat)),
  3298. best.chli = apply(js.mat, 1, max),
  3299. best.ch = apply(res.ch$matrix, 1, max),
  3300. best.chop = apply(res.chop$matrix, 1, max),
  3301. best.chliop = apply(res.chliop$matrix, 1, max),
  3302. best.chliopmmmf = apply(res.mfms$matrix, 1, max)
  3303. )
  3304. ScatterPlot(best.jac.df, x = 'best.ch', y = 'best.chli', y_equals_x = T, labels = 'orthotype', max.overlaps = 10,
  3305. ylab = 'Best jaccard score\n(chicken and lizard)', xlab = 'Best jaccard score\n(chicken)', r = T) |
  3306. ScatterPlot(best.jac.df, x = 'best.chop', y = 'best.chli', y_equals_x = T, labels = 'orthotype', max.overlaps = 10,
  3307. ylab = 'Best jaccard score\n(chicken and lizard)', xlab = 'Best jaccard score\n(chicken and opossum)', r = T) |
  3308. ScatterPlot(best.jac.df, x = 'best.chliop', y = 'best.chli', y_equals_x = T, labels = 'orthotype', max.overlaps = 10,
  3309. ylab = 'Best jaccard score\n(chicken and lizard)', xlab = 'Best jaccard score\n(chicken, lizard, and opossum)', r = T) |
  3310. ScatterPlot(best.jac.df, x = 'best.chliopmmmf', y = 'best.chli', y_equals_x = T, labels = 'orthotype', max.overlaps = 10,
  3311. ylab = 'Best jaccard score\n(chicken and lizard)', xlab = 'Best jaccard score \n(chicken, lizard, opossum, mouse, macaque)', r = T)
  3312. ggsave('../../figures/my_figs/conservation-robustness.pdf')
  3313. ```
  3314. ```{r, fig.height=8, fig.width=14}
  3315. res.mfms$data$leiden_clusters = as.character(res.mfms$data$leiden_clusters)
  3316. (TitlePlot((PrettyUmap(ac.ortho, group.by = 'species', alpha = 0.6, pt.size = 0.1, label = F, show.legend = T) +
  3317. guides(color = guide_legend(byrow = TRUE)) + theme(legend.key.height = unit(12, "pt"))), 'Seurat CCA (17 amniotes)') |
  3318. TitlePlot(PrettyUmap(ac.ortho, group.by = 'classification', alpha = 0.6, pt.size = 0.1), 'Subclass') |
  3319. TitlePlot(PrettyUmap(ac.ortho, group.by = 'orthotype.no', alpha = 0.6, pt.size = 0.1), 'Mean silhouette: 0.6')) /
  3320. (TitlePlot((PrettyUmap(res.mfms$data, group.by = 'species_full', alpha = 0.6, pt.size = 0.1, label = F, show.legend = T) +
  3321. guides(color = guide_legend(byrow = TRUE)) + theme(legend.key.height = unit(12, "pt"))), 'SAMap (10 vertebrates)') |
  3322. TitlePlot(PrettyUmap(res.mfms$data, group.by = 'cell_class2', alpha = 0.6, pt.size = 0.1), 'Subclass') |
  3323. TitlePlot(PrettyUmap(res.mfms$data, group.by = 'leiden_clusters', alpha = 0.6, pt.size = 0.1), 'Mean silhouette: 0.2'))
  3324. ggsave('../../figures/my_figs/samap-lower-res.pdf')
  3325. ```
  3326. ```{r, fig.height=6, fig.width=7}
  3327. JSHeatmap2(res.mfms$data$orthotypes, res.mfms$data$leiden_clusters, row.order = ORTHOTYPES,
  3328. xlab = 'SAMap vertebrate leiden clusters', ylab = 'Seurat amniote orthotypes', ari = T)
  3329. ```
  3330. ```{r, fig.height=5, fig.width=10}
  3331. seurat = readRDS('../../Ortho_Objects/vertebrateAC_seurat.rds')
  3332. seurat = MapBack(seurat, ac.ortho, group.by = 'orthotype.no')
  3333. seurat.ds = DownsampleSeurat(seurat[,!is.na(seurat$orthotype.no)], group.by = 'orthotype.no', size = 1000)
  3334. # seurat.ds = seurat[,!is.na(seurat$orthotype.no)]
  3335. # dist = 1-seurat@graphs$integrated_snn[Cells(seurat.ds), Cells(seurat.ds)]
  3336. # Computing silhouette in UMAP space because neither PCA nor graph space are comparable between Seurat and SAMap
  3337. silhouttes = FindSilhouette(seurat.ds,
  3338. group.by = 'orthotype.no',
  3339. # dist = dist,
  3340. reduction = 'umap',
  3341. method = 'Euclidean',
  3342. average = T
  3343. )
  3344. silhouttes
  3345. paste0('Mean cluster silhouette Seurat: ', mean(silhouttes$sil_width))
  3346. res.mfms
  3347. res.mfms.ds = res.mfms$data[sample(1:nrow(res.mfms$data), 10000),]
  3348. sil.samap = FindSilhouette(res.mfms.ds,
  3349. group.by = 'leiden_clusters',
  3350. dist = dist(res.mfms.ds[,c('UMAP_1', 'UMAP_2')]),
  3351. # reduction = 'umap',
  3352. # method = 'Euclidean',
  3353. average = T
  3354. )
  3355. paste0('Mean cluster silhouette SAMap: ', mean(sil.samap$sil_width))
  3356. ```
  3357. ## Checkpoint: Heatmap 1
  3358. ```{r, fig.height=3, fig.width=10, dpi=300}
  3359. nmList = ReadSAMapObjects()
  3360. nmList = lapply(nmList, DownsampleSeurat, group.by = 'annotated', size = 50)
  3361. nmList = sapply(names(nmList), function(species){
  3362. nmList[[species]]$annotated = paste0(index$ident[index$species == species], '_', nmList[[species]]$annotated)
  3363. nmList[[species]]
  3364. }, USE.NAMES = TRUE)
  3365. nmList$Zebrafish = NormalizeData(nmList$Zebrafish)
  3366. # Newest version of files
  3367. gene_pairs = fread('samap/pm_sh_ca_kf_ze_ne_am_ch_li-ac-v3-genepairs.csv')[,-1] %>% data.frame()
  3368. # gene_pairs = fread('samap/kf_ze_ch_li-AC-v5-genepairs.csv')[,-1] %>% data.frame()
  3369. # gene_pairs = fread('samap/pm_sh_ca_kf_ze_am_ch_li-ac-v2-genepairs.csv')[,-1] %>% data.frame()
  3370. bbh = readRDS('../../Ortho_Objects/bbh_v2.rds')
  3371. ac.groups = readRDS('samap/ac.groups.rds')
  3372. ac.groups.sorted = readRDS('samap/ac.groups.sorted.rds')
  3373. # Get markers for each group of cell types!
  3374. marker.dfs = lapply(seq_along(ac.groups), function(i){
  3375. this.group = ac.groups[[i]]
  3376. message('Working on group ', i)
  3377. # print(this.group)
  3378. this.species = unique(ExtractString(this.group, after = '_'))
  3379. if(length(this.group) < 2) return(NULL)
  3380. col.names = gsub('-', '\\.', unlist(Iterate(sort(this.group), function(x,y) paste0(x, '.', y), return.matrix = FALSE)))
  3381. col.names = intersect(unlist(col.names), colnames(gene_pairs))
  3382. if(length(col.names) == 0) return(NULL)
  3383. df_onecol = pivot_longer(gene_pairs[,col.names,drop = FALSE],
  3384. everything(),
  3385. values_to = "value")
  3386. df_onecol$species1 = ExtractString(ExtractString(df_onecol$value, after = ';'), after = '_')
  3387. df_onecol$gene1 = ExtractString(ExtractString(df_onecol$value, after = ';'), before = '_')
  3388. df_onecol$species2 = ExtractString(ExtractString(df_onecol$value, before = ';'), after = '_')
  3389. df_onecol$gene2 = ExtractString(ExtractString(df_onecol$value, before = ';'), before = '_')
  3390. df_onecol = subset(df_onecol, value != '') # Remove rows with empty values
  3391. # Chicken symbols and lizard symbols
  3392. chicken.symbols = unique(c(subset(df_onecol, species1 == 'ch')$gene1, subset(df_onecol, species2 == 'ch')$gene2))
  3393. lizard.symbols = unique(c(subset(df_onecol, species1 == 'li')$gene1, subset(df_onecol, species2 == 'li')$gene2))
  3394. # Projection onto chicken
  3395. marker.df.ch = Reduce(function(dtf1,dtf2) full_join(dtf1, dtf2, by="Chicken", relationship = "many-to-many"), list(
  3396. unique(subset(df_onecol, species1 == 'ch' & species2 == 'pm')[,c('gene1', 'gene2')] %>% setNames(c('Chicken', 'Lamprey'))),
  3397. unique(subset(df_onecol, species1 == 'ch' & species2 == 'sh')[,c('gene1', 'gene2')] %>% setNames(c('Chicken', 'Shark'))),
  3398. unique(subset(df_onecol, species1 == 'ch' & species2 == 'kf')[,c('gene1', 'gene2')] %>% setNames(c('Chicken', 'Killifish'))),
  3399. unique(subset(df_onecol, species1 == 'ca' & species2 == 'ch')[,c('gene1', 'gene2')] %>% setNames(c('Goldfish', 'Chicken'))),
  3400. unique(subset(df_onecol, species1 == 'ch' & species2 == 'ze')[,c('gene1', 'gene2')] %>% setNames(c('Chicken', 'Zebrafish'))),
  3401. unique(subset(df_onecol, species1 == 'am' & species2 == 'ch')[,c('gene1', 'gene2')] %>% setNames(c('Axolotl', 'Chicken'))),
  3402. unique(subset(df_onecol, species1 == 'ch' & species2 == 'ne')[,c('gene1', 'gene2')] %>% setNames(c('Chicken', 'Newt'))),
  3403. unique(subset(df_onecol, species1 == 'ch' & species2 == 'li')[,c('gene1', 'gene2')] %>% setNames(c('Chicken', 'Lizard')))
  3404. )) %>% unique
  3405. # Projection onto lizard
  3406. marker.df.li = Reduce(function(dtf1,dtf2) full_join(dtf1, dtf2, by="Lizard", relationship = "many-to-many"), list(
  3407. unique(subset(df_onecol, species1 == 'li' & species2 == 'pm')[,c('gene1', 'gene2')] %>% setNames(c('Lizard', 'Lamprey'))),
  3408. unique(subset(df_onecol, species1 == 'li' & species2 == 'sh')[,c('gene1', 'gene2')] %>% setNames(c('Lizard', 'Shark'))),
  3409. unique(subset(df_onecol, species1 == 'kf' & species2 == 'li')[,c('gene1', 'gene2')] %>% setNames(c('Killifish', 'Lizard'))),
  3410. unique(subset(df_onecol, species1 == 'ca' & species2 == 'li')[,c('gene1', 'gene2')] %>% setNames(c('Goldfish', 'Lizard'))),
  3411. unique(subset(df_onecol, species1 == 'li' & species2 == 'ze')[,c('gene1', 'gene2')] %>% setNames(c('Lizard', 'Zebrafish'))),
  3412. unique(subset(df_onecol, species1 == 'am' & species2 == 'li')[,c('gene1', 'gene2')] %>% setNames(c('Axolotl', 'Lizard'))),
  3413. unique(subset(df_onecol, species1 == 'li' & species2 == 'ne')[,c('gene1', 'gene2')] %>% setNames(c('Lizard', 'Newt'))),
  3414. unique(subset(df_onecol, species1 == 'ch' & species2 == 'li')[,c('gene1', 'gene2')] %>% setNames(c('Chicken', 'Lizard')))
  3415. )) %>% unique
  3416. # Found in chicken, but not in lizard? or vice versa
  3417. # Retreive genes missed from chicken projection
  3418. missed.by.ch = subset(marker.df.li, Lizard %in% setdiff(lizard.symbols, marker.df.ch$Lizard))
  3419. # Retrieve genes missed from lizard projection
  3420. missed.by.li = subset(marker.df.ch, Chicken %in% setdiff(chicken.symbols, marker.df.li$Chicken))
  3421. marker.df1 = rbind(marker.df.li, missed.by.li)
  3422. marker.df2 = rbind(marker.df.ch, missed.by.ch)
  3423. if(nrow(marker.df1) > nrow(marker.df2)){
  3424. message('Using lizard as primary reference...')
  3425. marker.df = marker.df1
  3426. } else {
  3427. message('Using chicken as primary reference...')
  3428. marker.df = marker.df2
  3429. }
  3430. # Add annotation
  3431. marker.df$row_annotation = as.character(i)
  3432. marker.df$fraction = apply(marker.df, 1, function(x) length(which(!is.na(x[1:8]))) / length(this.species))
  3433. if(nrow(marker.df) == 0) return(NULL) else as.data.frame(unique(marker.df))
  3434. })
  3435. # Check redundancy factor
  3436. lapply(marker.dfs, function(x) nrow(x) / length(unique(x[,1])))
  3437. # Mostly good, only cluster 1 (NNgly) has high value
  3438. # Which clusters did we not find genes for?
  3439. missing.clusters = which(sapply(marker.dfs, is.null))
  3440. # nmListModified = nmList[NM_SPECIES]
  3441. markers.df = Reduce(gtools::smartbind, marker.dfs[-missing.clusters])[,c(NM_SPECIES, 'row_annotation', 'fraction')] #lapply(marker.dfs, function(x) x[,NM_SPECIES]))
  3442. js.dat = readRDS('../../Ortho_Objects/js.dat.rds')
  3443. markers.df.sorted = markers.df %>% arrange(factor(row_annotation, levels = (levels(js.dat$data$col))))
  3444. dir.create('samap/genes', showWarnings = F)
  3445. saveRDS(markers.df.sorted, 'samap/genes/markers.df.sorted.20251230.rds')
  3446. # pdf('../../figures/my_figs/ac-fish-types-heatmap-v6.pdf', height=5, width=10)
  3447. # SAMapHeatmap4(nmListModified,
  3448. # markers.df.sorted[,c(NM_SPECIES, 'row_annotation')],
  3449. # # type_palette = colorspace::lighten(c('SAC' = 'orangered', PDGFRA = 'chartreuse', A2 = 'deepskyblue', VG3 = 'pink'), 0.2),
  3450. # species_palette = species_palette2,
  3451. # species.use = NM_SPECIES, #c("Chicken", "Lizard", "Zebrafish", "Killifish"), # names(species_ids),
  3452. # types.use = unlist(ac.groups.sorted),
  3453. # show_heatmap_legend = FALSE,
  3454. # show_row_names = FALSE,
  3455. # show_column_names = FALSE,
  3456. # col_fun = circlize::colorRamp2(c(-1, 0, 2), c("white", "white", "#584B9FFF")),
  3457. # types.order = unlist(ac.groups.sorted),
  3458. # # min.z.score = -1,
  3459. # # max.z.score = 2,
  3460. # # width = unit(10, "in"),
  3461. # rotate = TRUE,
  3462. # dotplot = FALSE,
  3463. # use_raster = TRUE,
  3464. # add.breaks = FALSE)
  3465. # dev.off()
  3466. ```
  3467. ## Heatmap 2: controlled for multiplicity
  3468. ```{r}
  3469. markers.df.sorted = readRDS('samap/genes/markers.df.sorted.20251230.rds')
  3470. markers.df.sorted.trimmed = ControlMultiplicity(markers.df.sorted, multiplicity = 2, sort = TRUE)
  3471. bbh = readRDS('../../Ortho_Objects/bbh_v2.rds')
  3472. markers.df.sorted.trimmed.filtered = subset(markers.df.sorted.trimmed, row_annotation %in% bbh$ident2)
  3473. ha.metadata = data.frame(
  3474. name = rep(names(ac.groups.sorted), lengths(ac.groups.sorted)),
  3475. value = unlist(ac.groups.sorted)
  3476. )
  3477. ha.metadata$species = ExtractString(ha.metadata$value, after = '_')
  3478. ha.metadata$type = as.character(bbh$ident1[match(ha.metadata$name, bbh$ident2)])
  3479. pdf('../../figures/my_figs/ac-fish-types-heatmap-v6.pdf', height=5, width=10)
  3480. SAMapHeatmap4(nmList,
  3481. markers.df.sorted.trimmed.filtered, # subset(markers.df.sorted, row_annotation %in% c(5))[1:20,],
  3482. # type_palette = colorspace::lighten(c('SAC' = 'orangered', PDGFRA = 'chartreuse', A2 = 'deepskyblue', VG3 = 'pink'), 0.2),
  3483. species_palette = species_palette3,
  3484. species.use = NM_SPECIES, #c("Chicken", "Lizard", "Zebrafish", "Killifish"), #names(species_ids),
  3485. types.use = unlist(ac.groups.sorted),
  3486. show_heatmap_legend = TRUE,
  3487. show_row_names = FALSE,
  3488. show_column_names = FALSE,
  3489. col_fun = circlize::colorRamp2(c(-1, 0, 2), c("white", "white", "#584B9FFF")),
  3490. types.order = (unlist(ac.groups.sorted)),
  3491. show_annotation_legend = TRUE,
  3492. # min.z.score = -1,
  3493. # max.z.score = 2,
  3494. # width = unit(10, "in"),
  3495. rotate = TRUE,
  3496. dotplot = FALSE,
  3497. use_raster = TRUE,
  3498. raster_quality = 5,
  3499. add.breaks = FALSE,
  3500. na_col = "grey90",
  3501. mybreaks = ha.metadata$name,
  3502. left_annotation = rowAnnotation(type = ha.metadata$type,
  3503. species = factor(ha.metadata$species, levels = names(prefix.key)),
  3504. col = list(type = type_cols3, species = nm_palette2),
  3505. border = TRUE,
  3506. show_legend = TRUE)
  3507. )
  3508. dev.off()
  3509. unique(ha.metadata$type)
  3510. ```
  3511. ## Fig. 5D: SAMap gene combo heatmap
  3512. ```{r}
  3513. ha.metadata = data.frame(
  3514. leiden_clusters = rep(names(ac.groups.sorted), lengths(ac.groups.sorted)),
  3515. species_type = unlist(ac.groups.sorted)
  3516. )
  3517. ha.metadata$species = ExtractString(ha.metadata$species_type, after = '_')
  3518. ha.metadata$type = as.character(bbh$ident1[match(ha.metadata$leiden_clusters, bbh$ident2)])
  3519. write.csv(bbh, 'figures/bbh_v2.csv')
  3520. write.csv(ha.metadata, 'figures/ha.metadata.v7.csv')
  3521. # write.csv(ha.metadata.clean, 'figures/ha.metadata.clean.v5.csv')
  3522. # Now its correct:
  3523. # subset(ha.metadata, species_type == 'ch_gabaAC-60')
  3524. # leiden_clusters species_type species type
  3525. # 48 35 ch_gabaAC-60 ch oAC41
  3526. ```
  3527. ```{r}
  3528. # ha.metadata.clean = read.csv('figures/ha.metadata.clean.csv')
  3529. # ha.metadata.clean = subset(ha.metadata.clean, !leiden_clusters %in% c('17', '22', '11', '20'))
  3530. ha.metadata = read.csv('figures/ha.metadata.v7.csv')
  3531. ha.metadata.clean = ha.metadata[!is.na(ha.metadata$type),]
  3532. ha.metadata.clean = subset(ha.metadata.clean, !type %in% c('oAC27'))
  3533. # Order by oAC
  3534. custom.order = levels(orthotype_labels(c("22_A2", "27_VG3", "18_TRHDE", "41_TRHDE", "34", "26_A8", "24_SEG", "2_NNgly", "15",
  3535. "17_ROBO3", "29_SLC35D3", "35", "30_A17", "32_A17", "9", "1_MAF*", "3*", "20", "4_nNOS",
  3536. "14_CA2", "6_NPY", "10_MAF*", "11*", "25*", "13", "40*", "42", "38", "7", "21_PDGFRA",
  3537. "28", "5", "36_VIP", "23_RXRG", "39", "16_NNgaba*", "19_CRH*", "12_nNOS*", "33_CA1*", "31_nNOS", "37", "8_SAC*")))
  3538. ha.metadata.clean = ha.metadata.clean %>% arrange(factor(type, levels = custom.order))
  3539. markers.clean = subset(markers.df.sorted.trimmed, row_annotation %in% ha.metadata.clean$leiden_clusters) %>%
  3540. arrange(factor(row_annotation, levels = unique(ha.metadata.clean$leiden_clusters)))
  3541. saveRDS(markers.clean, 'samap/genes/markers.clean.v2.rds')
  3542. stopifnot(all(ha.metadata.clean$species_type %in% unlist(lapply(nmList, function(x) unique(x$annotated)))))
  3543. pdf('../../figures/my_figs/ac-fish-types-heatmap-v3.pdf', height=3.5, width=7.6)
  3544. SAMapHeatmap4(nmList,
  3545. subset(markers.clean, fraction > 0.3), # subset(markers.df.sorted, row_annotation %in% c(5))[1:20,],
  3546. # type_palette = colorspace::lighten(c('SAC' = 'orangered', PDGFRA = 'chartreuse', A2 = 'deepskyblue', VG3 = 'pink'), 0.2),
  3547. species_palette = species_palette3,
  3548. species.use = NM_SPECIES, #names(species_ids),
  3549. types.use = ha.metadata.clean$species_type,
  3550. show_heatmap_legend = TRUE,
  3551. show_row_names = FALSE,
  3552. show_column_names = FALSE,
  3553. col_fun = circlize::colorRamp2(c(-1, 0, 2), c("white", "white", "#584B9FFF")),
  3554. types.order = ha.metadata.clean$species_type,
  3555. show_annotation_legend = TRUE,
  3556. na_col = "grey90",
  3557. # min.z.score = -1,
  3558. # max.z.score = 2,
  3559. # width = unit(10, "in"),
  3560. rotate = TRUE,
  3561. dotplot = FALSE,
  3562. use_raster = TRUE,
  3563. raster_quality = 5,
  3564. add.rectangles = TRUE,
  3565. row.breaks = ha.metadata.clean$type,
  3566. col.breaks = subset(markers.clean, fraction > 0.3)$row_annotation,
  3567. left_annotation = rowAnnotation(type = factor(ha.metadata.clean$type, levels = unique(ha.metadata.clean$type)),
  3568. species = ha.metadata.clean$species,
  3569. col = list(type = type_cols3, species = nm_palette2),
  3570. border = TRUE,
  3571. show_legend = TRUE),
  3572. lty = 2,
  3573. lwd = 0.75
  3574. )
  3575. dev.off()
  3576. unique(ha.metadata.clean$type)
  3577. ```
  3578. ## Figure 5E: Custom dotplots for select types
  3579. SAC BHLEH22 PDGFRA A8 VG3
  3580. Might consider also
  3581. 37 very nice but not famous
  3582. 14_CA2 no teleosts
  3583. 33_CA1 not very clean markers
  3584. 10_MAF try this next
  3585. ```{r, fig.height=15, fig.width=16}
  3586. # Load nmList
  3587. # Load ha.metadata.clean
  3588. ha.metadata = read.csv('figures/ha.metadata.v7.csv')
  3589. ha.metadata.clean = ha.metadata[!is.na(ha.metadata$type),]
  3590. markers.clean = readRDS('samap/genes/markers.clean.v2.rds')
  3591. markers.clean.1 = ControlMultiplicity(markers.clean, multiplicity = 1, sort = FALSE)
  3592. # lc.use = c(5, 3, 12, 28, 36, 11, 19, 1, 10, 2)
  3593. orthotype.use = c('oAC42* [SAC]', 'oAC17*', 'oAC30 [PDGFRA]', 'oAC41',' oAC19 [CA2]', 'oAC39* [CA1]', 'oAC2 [VG3]', 'oAC1 [A2]', 'oAC6 [A8]', 'oAC7 [SEG]')
  3594. types.use = subset(ha.metadata.clean, type %in% orthotype.use) %>%
  3595. # arrange(factor(leiden_clusters, levels = lc.use)) %>%
  3596. arrange(factor(leiden_clusters, levels = orthotype.use)) %>%
  3597. pull(species_type)
  3598. n_genes = 30
  3599. # markers.clean.subset = do.call(rbind, lapply(lc.use, function(lc) head(subset(markers.clean.1, row_annotation == lc), n_genes)))
  3600. # pdf('figures/nonmammal-ac-dotplots-v3.pdf', height=30, width=20)
  3601. # SAMapHeatmap4(nmList,
  3602. # markers.clean.subset,
  3603. # # type_palette = colorspace::lighten(c('SAC' = 'orangered', PDGFRA = 'chartreuse', A2 = 'deepskyblue', VG3 = 'pink'), 0.2),
  3604. # species_palette = species_palette2,
  3605. # species.use = names(nmList), #setdiff(names(nmList), 'Goldfish'),
  3606. # types.use = types.use,
  3607. # show_heatmap_legend = TRUE,
  3608. # show_row_names = TRUE,
  3609. # show_column_names = TRUE,
  3610. # col_fun = circlize::colorRamp2(c(-1, 0, 2), c("white", "white", "#584B9FFF")),
  3611. # types.order = types.use,
  3612. # show_annotation_legend = TRUE,
  3613. # font.size = 8,
  3614. # rotate = FALSE,
  3615. # dot.scale.factor = 0.2,
  3616. # dotplot = TRUE,
  3617. # lty = 2
  3618. # )
  3619. # dev.off()
  3620. ```
  3621. ```{r, fig.width=15, fig.width=15}
  3622. markers.clean.1 = ControlMultiplicity(markers.clean, multiplicity = 1, sort = FALSE)
  3623. # Additional filtration; doing it manually
  3624. # singletons_0.4 = rownames(ac_alignment)[apply(ac_alignment, 1, function(x) max(x) < 0.4)]
  3625. # pdf('../../figures/my_figs/nonmammal-integration-matrix-ac-subset.pdf', height=35, width=36)
  3626. sm = MakeSmartMatrix(ac_alignment[unique(types.use),unique(gsub('-', '\\.', types.use))])
  3627. SmartHeatmap2(sm)
  3628. # dev.off()
  3629. ```
  3630. ```{r, fig.height=8, fig.width=12}
  3631. markers.clean.1 = ControlMultiplicity(markers.clean, multiplicity = 1, sort = FALSE)
  3632. orthotype.use = c('oAC42* [SAC]', 'oAC17*', 'oAC30 [PDGFRA]', 'oAC41','oAC2 [VG3]', 'oAC1 [A2]', 'oAC6 [A8]', 'oAC7 [SEG]')
  3633. types.use2 = c(
  3634. # SAC oAC42* [SAC]
  3635. "pm_gabaAC-1", #"pm_gabaAC-2", "pm_gabaAC-3", "pm_gabaAC-4",
  3636. "sh_gabaAC-3",
  3637. "kf_gabaAC-1",
  3638. "ze_gabaAC-0_SAC",
  3639. "ne_gabaAC-1", #'ne_gabaAC-14',
  3640. "am_gabaAC-1", #'am_gabaAC-17',
  3641. "ch_gabaAC-2_SAC", "li_gabaAC-14_SAC", #"li_gabaAC-24_SAC",
  3642. # BHLHE22 (oAC17*)
  3643. "kf_gabaAC-9",
  3644. "ze_glyAC-18", # "ze_gabaAC-39",
  3645. # "am_gabaAC-5", 'am_gabaAC-16',
  3646. 'am_gabaAC-28',
  3647. "ch_gabaAC-13", #"ch_gabaAC-57",
  3648. 'li_gabaAC-5', #"li_gabaAC-0", 'li_gabaAC-2',
  3649. # PDGFRA (oAC30 [PDGFRA])
  3650. "pm_RGC-5",
  3651. # 'sh_gabaAC-8',
  3652. "kf_gabaAC-10", #"kf_gabaAC-3",
  3653. "ze_gabaAC-50_nNOS",
  3654. 'ne_gabaAC-23',
  3655. "am_gabaAC-13",
  3656. "ch_gabaAC-20", #"ch_gabaAC-61",
  3657. "li_gabaAC-35",
  3658. # 37 (oAC41)
  3659. "kf_gabaAC-19",
  3660. "ze_gabaAC-37",
  3661. 'ne_gabaAC-28',
  3662. "am_gabaAC-54",
  3663. "ch_gabaAC-60",
  3664. "li_gabaAC-23",
  3665. # 14_CA2
  3666. # "kf_gabaAC-19", "ca_gabaAC-2", "ze_gabaAC-37", "am_gabaAC-35", "ch_gabaAC-60", "li_gabaAC-23",
  3667. # VG3
  3668. "pm_glyAC-1",
  3669. "sh_glyAC-12",
  3670. "ca_glyAC-3",
  3671. "ze_glyAC-9",
  3672. 'ne_glyAC-7',
  3673. "am_glyAC-12",
  3674. "ch_glyAC-40_VG3",
  3675. "li_glyAC-21_VG3",
  3676. # A2
  3677. "pm_glyAC-8",
  3678. "sh_glyAC-10",
  3679. "kf_glyAC-8",
  3680. "ze_glyAC-13_A2",
  3681. 'ne_glyAC-21',
  3682. "am_glyAC-3",
  3683. "ch_glyAC-1_A2",
  3684. "li_glyAC-17_A2",
  3685. # A8
  3686. "pm_glyAC-5",
  3687. "sh_glyAC-4",
  3688. "kf_glyAC-7",
  3689. "ca_glyAC-7",
  3690. "ze_glyAC-16",
  3691. # "ze_glyAC-44_SEG",
  3692. # 'ne_glyAC-24',
  3693. 'ne_glyAC-34',
  3694. # 'am_glyAC-27',
  3695. 'am_glyAC-8',
  3696. # "ch_glyAC-0",
  3697. "ch_glyAC-14_SEG",
  3698. # "ch_glyAC-33",
  3699. "li_glyAC-19"
  3700. # nGnG-GLY
  3701. # "pm_RGC-5", "kf_gabaAC-10", "kf_gabaAC-3",
  3702. # "ze_gabaAC-50_nNOS", "am_gabaAC-21", "ch_gabaAC-20", "ch_gabaAC-61",
  3703. # "li_gabaAC-35",
  3704. )
  3705. # Get corresponding leiden clusters
  3706. # ha.metadata$leiden_clusters[match(orthotype.use, ha.metadata$type)]
  3707. markers.clean.subset2 = rbind(subset(markers.clean.1, row_annotation %in% c(1) & (Chicken %in% c('ISL1', 'SLC5A7', 'MEF10', 'MEGF11', 'CHAT') |
  3708. Lizard %in% c('ISL1', 'SLC5A7', 'MEF10', 'MEGF11'))),
  3709. c('SOX2', 'SOX2', 'SOX2', 'SOX2', 'sox2', 'sox2', NA, 'sox2', 'LOC116954613', 1, 0.75), # SOX2 probe not working in chicken
  3710. subset(markers.clean.1, row_annotation %in% c(5) & (Chicken %in% c('BHLHE22', 'BHLHE23', 'CHAT', 'SYT7', 'SEMA6B') |
  3711. Lizard %in% c('BHLHE22', 'BHLHE23', 'CHAT'))),
  3712. # Recover some genes for oAC30
  3713. c('GJC2', 'GJC2', 'GJC1', 'LOC138259626', 'cx47.1', 'gjc1', NA, NA, 'LOC116937600', 21, 0.75),
  3714. c('TJP1', 'TJP1', 'TJP1', 'TJP1', 'tjp2b', 'tjp1a', NA, NA, 'LOC116939131', 21, 0.75),
  3715. c('PDGFRA', 'PDGFRA', 'PDGFRA', 'PDGFRA', 'pdgfra', NA, NA, NA, 'FLT1', 21, 0.444),
  3716. c('CBLN1', NA, 'CBLN1', 'CBLN1', 'cbln1', 'cbln1', 'cbln1', 'cbln2b', 'LOC116954123', 21, 0.889),
  3717. # subset(markers.clean.1, row_annotation %in% c(21) & (Chicken %in% c('PDGFRA', 'GJC1', 'GJC2', 'TJP1', 'CBLN1') |
  3718. # Lizard %in% c('PDGFRA', 'GJC1', 'GJC2', 'TJP1', 'CBLN1'))),
  3719. subset(markers.clean.1, row_annotation %in% c(35) & (Chicken %in% c('FSTL5', 'CNTNAP5', 'NR2F1', 'EPHA5', 'NAV2', 'ELAVL2'))),
  3720. # Lizard %in% c('PDGFRA', 'GJC1', 'GJC2', 'TJP1', 'CBLN1'))),
  3721. subset(markers.clean.1, row_annotation %in% c(19) & (Chicken %in% c('SLC17A8', 'ERBB4', 'NXPH1', 'BNC2') |
  3722. Lizard %in% c('SLC17A8', 'ERBB4', 'NXPH1', 'BNC2'))),
  3723. subset(markers.clean.1, row_annotation %in% c(22) & (Chicken %in% c('NFIA', 'PROX1', 'ESRRG') | #'CNTFR'
  3724. Lizard %in% c('NFIA', 'PROX1', 'ESRRG'))),
  3725. c('PTPRZ1', 'PTPRZ1', 'LOC138497686',

8_figures.Rmd at commit 560dae2, under MIT · at the source

Overview

  1. Department of Neuroscience, University of California, Berkeley, Berkeley, CA, USA
  2. Helen Wills Neuroscience Institute, University of California, Berkeley, Berkeley, CA, USA
  3. Department of Molecular and Cellular Biology and Center for Brain Science, Harvard University, Cambridge, MA, USA
  4. Department of Chemical and Biomolecular Engineering, University of California, Berkeley, Berkeley, CA, USA
  5. Solomon H. Snyder Department of Neuroscience, Johns Hopkins University, Baltimore, MD, USA
  6. Institut de la Vision, Sorbonne Université, INSERM, CNRS, Paris, France
  7. Rothschild Foundation Hospital, Paris, France
  8. Herbert Wertheim School of Optometry and Vision Science, University of California, Berkeley, Berkeley, CA, USA
  9. Vision Sciences Graduate Program, University of California, Berkeley, Berkeley, CA, USA
  10. Center for Computational Biology, University of California, Berkeley, CA, USA
  11. Biophysics Graduate Group, University of California, Berkeley, Berkeley, CA, USA
  12. Biological Systems Division, Lawrence Berkeley National Laboratory, Berkeley, CA, USA
Journal: Science advances, volume 12, issue 33, article eaeg3223
Dates: received 9 February 2026; accepted 7 July 2026; published online 14 August 2026; in print August 2026
Type: Research article · Language: English
License: CC BY-NC
Identifiers: DOI 10.1126/sciadv.aeg3223 · PMID 42600003 · PMCID PMC13475493 · OpenAlex W7134841878
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: genetics / omics (modality), human (organism), cellular / molecular (subfield)
Methods: Connectivity, Statistics, Smoothing, state filtering, decompositions, Machine learning
MeSH: Amacrine Cells*, Biological Evolution*, Retina*, Animals, Evolution, Molecular, Humans, Phylogeny, Retinal Ganglion Cells, Transcriptome, Vertebrates (* major topic)
Journal subjects: Neuroscience, Evolutionary Biology
Topic: Retinal Development and Disorders (Molecular Biology, Biochemistry, Genetics and Molecular Biology), according to OpenAlex
Funding: National Institutes of Health (EY028625, EY024265, F31EY038101, EY028633, MH105960, U01NS136405); Research Corporation for Science Advancement (SA-MND-2023-031); Glaucoma Research Foundation; McKnight Foundation; National Science Foundation CRCNS (2309039); BrightFocus Foundation (BFF) (National Glaucoma Award); Howard Hughes Medical Institute Hanna H. Gray; Burroughs Wellcome Fund Postdoctoral Diversity Enrichment Program (1287193); European Research Council DEEPRETINA (101045253)
Citations: not cited yet (Europe PMC); 94 references in the paper
Research resources: RRID:SCR_017852

Abstract

Amacrine cells (ACs) comprise a heterogeneous class of inhibitory neurons in the vertebrate retina, exhibiting morphological and functional complexity rivaling that of cortical interneurons. Here, we integrate single-cell and single-nucleus transcriptomic atlases from 24 vertebrate species to reconstruct the evolutionary origins of this extreme diversity. We identify 42 orthologous AC types, most of which exhibit a one-to-one correspondence across amniotes and, in many cases, across vertebrates. While core molecular identities are conserved, AC types vary in abundance and gene expression across species, likely reflecting adaptations to distinct visual ecologies. AC diversity scales with that of retinal ganglion cells (RGCs), indicative of coevolution. Last, we suggest that ACs arose from an AC-RGC hybrid precursor, with glycinergic ACs diverging early in vertebrate evolution, followed by a bifurcation between RGCs and GABAergic ACs. Together, these findings establish a unified evolutionary framework for understanding the diversity, development, and function of a class of inhibitory neurons across vertebrates.

Reproduced under the paper's license (CC BY-NC), from the paper cited above.

Repositories

Its files are read in the Code ↔ Paper reader above, with 30 matches between paragraphs and lines of code.

shekharlab/AmacrineCells

License: MIT
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 560dae2585e4d5a6115e5f1a7e03f5add2ae4133, 2 June 2026
Languages: R (20), Python (2), Jupyter (1), Shell (1)
Size: 28 files, 24 scripts
Software Heritage: not archived
Found in: “Data, code, and materials availability:”
Holds: README, license file, 8 notebooks
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Tools: reshape2 (9 files), tidyverse (6 files), XGBoost (4 files), data.table (3 files), ggplot2 (3 files), SciPy (3 files), anndata (2 files), circlize (2 files), Matplotlib (2 files), NumPy (2 files), pandas (2 files), Scanpy (2 files), scikit-learn (2 files), seaborn (2 files), WGCNA (2 files), clusterProfiler (1 file), ComplexHeatmap (1 file), cowplot (1 file), DESeq2 (1 file), glmnet (1 file), igraph (1 file), patchwork (1 file), Plotly (1 file), psych (1 file), reticulate (1 file), rstatix (1 file), Seurat (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
26 files

Zenodo 20451319

License: MIT
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: “Data, code, and materials availability:”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: reshape2 (9 files), tidyverse (6 files), XGBoost (4 files), data.table (3 files), ggplot2 (3 files), SciPy (3 files), anndata (2 files), circlize (2 files), Matplotlib (2 files), NumPy (2 files), pandas (2 files), Scanpy (2 files), scikit-learn (2 files), seaborn (2 files), WGCNA (2 files), clusterProfiler (1 file), ComplexHeatmap (1 file), cowplot (1 file), DESeq2 (1 file), glmnet (1 file), igraph (1 file), patchwork (1 file), Plotly (1 file), psych (1 file), reticulate (1 file), rstatix (1 file), Seurat (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
  • 27 September 2026: the link answers (HTTP 200)
26 files

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;
  • 48 scripts, each with its path and the digest of its content;
  • 30 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.

Data, code, and materials availability

All data and code needed to evaluate and reproduce the results in the paper are present in the paper and/or the Supplementary Materials. This study did not generate new materials. The raw and processed sequencing data produced in this work are available via the Gene Expression Omnibus (GEO): GSE332621 (mouse lemur), GSE331097 (rat), GSE335334 (axolotl), and GSE335331 (Iberian ribbed newt). Species reference genomes are described in table S2 and are available on Ensembl (jun2026.archive.ensembl.org) or NCBI (https://ncbi.nlm.nih.gov/datasets/genome/). Code to reproduce the analyses is available on GitHub (https://github.com/shekharlab/AmacrineCells) and Zenodo (https://doi.org/10.5281/zenodo.20451319). Interactive visualization of orthotype atlases is available on the Single Cell Portal (https://singlecell.broadinstitute.org/single_cell): SCP3480 (BC, AC, and RGC orthotypes), SCP3462 (mouse lemur), SCP3446 (rat), SCP3463 (axolotl), and SCP3454 (newt).

Reproduced under the paper's license (CC BY-NC), from the paper cited above.

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, 10 authors, 10 MeSH terms, 9 funders, 91 references, 1 RRID.

Cite

This paper

Tommasini, D., Monavarfeshani, A., Dinesh, V., Hahn, J., Tangeman, J., Marre, O., Blackshaw, S., Puthussery, T., Sanes, J. R., & Shekhar, K. (2026). The extreme diversity of retinal amacrine cells has deep evolutionary roots. Science advances, 12(33), eaeg3223. https://doi.org/10.1126/sciadv.aeg3223

BibTeX

@article{tommasini2026extreme,
author = {Tommasini, Dario and Monavarfeshani, Aboozar and Dinesh, Vishruth and Hahn, Joshua and Tangeman, Jared and Marre, Olivier and Blackshaw, Seth and Puthussery, Teresa and Sanes, Joshua R. and Shekhar, Karthik},
title = {{The extreme diversity of retinal amacrine cells has deep evolutionary roots}},
journal = {Science advances},
year = {2026},
month = aug,
volume = {12},
number = {33},
pages = {eaeg3223},
publisher = {American Association for the Advancement of Science},
issn = {2375-2548},
doi = {10.1126/sciadv.aeg3223},
url = {https://doi.org/10.1126/sciadv.aeg3223},
pmid = {42600003},
pmcid = {PMC13475493}
}

RIS

TY - JOUR
AU - Tommasini, Dario
AU - Monavarfeshani, Aboozar
AU - Dinesh, Vishruth
AU - Hahn, Joshua
AU - Tangeman, Jared
AU - Marre, Olivier
AU - Blackshaw, Seth
AU - Puthussery, Teresa
AU - Sanes, Joshua R.
AU - Shekhar, Karthik
TI - The extreme diversity of retinal amacrine cells has deep evolutionary roots
T2 - Science advances
J2 - Sci Adv
PY - 2026
DA - 2026/08/14
VL - 12
IS - 33
SP - eaeg3223
SN - 2375-2548
PB - American Association for the Advancement of Science
DO - 10.1126/sciadv.aeg3223
UR - https://doi.org/10.1126/sciadv.aeg3223
LA - en
ER -

CSL-JSON

{
"id": "10.1126/sciadv.aeg3223",
"type": "article-journal",
"title": "The extreme diversity of retinal amacrine cells has deep evolutionary roots",
"container-title": "Science advances",
"author": [
{
"family": "Tommasini",
"given": "Dario"
},
{
"family": "Monavarfeshani",
"given": "Aboozar"
},
{
"family": "Dinesh",
"given": "Vishruth"
},
{
"family": "Hahn",
"given": "Joshua"
},
{
"family": "Tangeman",
"given": "Jared"
},
{
"family": "Marre",
"given": "Olivier"
},
{
"family": "Blackshaw",
"given": "Seth"
},
{
"family": "Puthussery",
"given": "Teresa"
},
{
"family": "Sanes",
"given": "Joshua R."
},
{
"family": "Shekhar",
"given": "Karthik"
}
],
"container-title-short": "Sci Adv",
"volume": "12",
"issue": "33",
"page": "eaeg3223",
"DOI": "10.1126/sciadv.aeg3223",
"PMID": "42600003",
"PMCID": "PMC13475493",
"ISSN": "2375-2548",
"publisher": "American Association for the Advancement of Science",
"URL": "https://doi.org/10.1126/sciadv.aeg3223",
"language": "en",
"issued": {
"date-parts": [
[
2026,
8,
14
]
]
}
}

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.1038/s41586-026-10629-x [code]
Whole-genome duplication shaped cell-type evolution in the vertebrate brain.
Journal: Nature
In common: reticulate, rstatix, anndata, 17 other tools, genetics / omics, cellular / molecular, 3 references
[2] doi:10.1002/imt2.70163 [code]
Spatial multi-omics unveils sphingolipid metabolic reprogramming within the retinal pathological niche.
Journal: iMeta
In common: rstatix, anndata, DESeq2, 19 other tools, genetics / omics, cellular / molecular, 1 reference
[3] doi:10.1038/s42003-026-10957-8 [code]
Brain defence by the extracellular matrix protein Cochlin.
Journal: Communications biology
In common: glmnet, WGCNA, XGBoost, 19 other tools, cellular / molecular
[4] doi:10.1093/bioinformatics/btag592 [code]
Network-based stratification of allele-specific expression reveals patient subgroups in Huntington's disease.
Journal: Bioinformatics (Oxford, England)
In common: WGCNA, reticulate, rstatix, 18 other tools, genetics / omics, 1 reference
[5] doi:10.1186/s13059-026-04177-w [code]
Genomic sequence evolution underlying human neocortical interareal diversification.
Journal: Genome biology
In common: reticulate, rstatix, anndata, 16 other tools, genetics / omics, cellular / molecular, 1 reference
[6] doi:10.3389/fnmol.2026.1844705 [code]
Risperidone regulates the expression of schizophrenia-related genes in the forebrain of adult male mice.
Journal: Frontiers in molecular neuroscience
In common: psych, anndata, DESeq2, 17 other tools, genetics / omics, cellular / molecular
[7] 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 sciences
In common: glmnet, reticulate, anndata, 14 other tools, genetics / omics
[8] doi:10.1038/s41593-026-02300-5 [code]
Integrated single-cell and spatial transcriptomic profiling in ALS uncovers peripheral-to-central immune infiltration and reprogramming.
Journal: Nature neuroscience
In common: anndata, DESeq2, igraph, 16 other tools, genetics / omics, cellular / molecular
[9] doi:10.1038/s41467-026-76675-1 [code]
Long-read proteogenomic atlas of human neuronal differentiation reveals isoform diversity informing neurodevelopmental risk mechanisms.
Journal: Nature communications
In common: WGCNA, reticulate, rstatix, 16 other tools, genetics / omics
[10] doi:10.1038/s41380-026-03629-w [code]
Maternal fasting during early gestation induces epigenetic alterations and schizophrenia-related phenotypes.
Journal: Molecular psychiatry
In common: WGCNA, anndata, DESeq2, 14 other tools, genetics / omics, 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.

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.