OSCR

Astrocyte glucocorticoid receptor signalling restricts neuronal plasticity.

Code ↔ Paper

13 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 13 matches
  1. [1] § Methods › Bioinformatics and data analysis › SHARE-seq data processing and analysis ↔ Astro_GR_KO_snRNA-final.ipynb, lines 66–74 · score 0.90 · FindVariableFeatures, NormalizeData, ScaleData, RunPCA, RunUMAP, doublets
  2. [2] § Astrocyte GR promotes neural circuit maturation ↔ Astro_GR_KO_snRNA-final.ipynb, lines 794–811 · score 0.81 · L5NP, L5PT, L6CT, L6IT, L5IT, excitatory neuron
  3. [3] § Atlas of experience-dependent V1 development ↔ Astro_GR_KO_snRNA-final.ipynb, lines 399–454 · score 0.79 · L5NP, L5PT, L6CT, L5IT, CR, Endo
  4. [4] § Methods › Bioinformatics and data analysis › Human brain multiome analysis ↔ Human_brain_development_multiome_analysis-final.ipynb, lines 432–497 · score 0.79 · L4IT, Human brain, L6IT, L5IT, multiome, L2
  5. [5] § Methods › Bioinformatics and data analysis › Mouse developmental astrocyte snRNA-seq analysis ↔ Astrocyte_mouse_atlas_snRNAseq-final.ipynb, lines 90–97 · score 0.75 · AddModuleScore, GR repressed, GR activated, Seurat, Mouse, astrocyte
  6. [6] § Atlas of experience-dependent V1 development ↔ Human_brain_development_multiome_analysis-final.ipynb, lines 432–497 · score 0.74 · L5PT, L6CT, L5IT, vascular, Fosl2, Endo
  7. [7] § Methods › Bioinformatics and data analysis › CUT&RUN data processing and analysis ↔ GR_NFIA_CUTnRUN_analysis-final.ipynb, lines 221–226 · score 0.73 · ChIP, BEDtools intersect, GR CUT, NFIA, edgeR, overlapped
  8. [8] § Methods › Bioinformatics and data analysis › Human brain multiome analysis ↔ Human_brain_development_multiome_analysis-final.ipynb, lines 1142–1166 · score 0.64 · FindMotifs, enriched motifs, human, multiome, clustered, brain
  9. [9] § Methods › Bioinformatics and data analysis › SHARE-seq data processing and analysis ↔ Human_brain_development_multiome_analysis-final.ipynb, lines 365–381 · score 0.57 · FindMarkers, chromVAR score, MAST, FC, row, motifs
  10. [10] § Methods › Bioinformatics and data analysis › Bulk nuclear RNA-seq data processing and analysis ↔ Share_seqV2_example.sh, lines 851–903 · score 0.56 · featureCounts, RNA seq, exons, log, mm10
  11. [11] § Methods › Bioinformatics and data analysis › MERFISH data processing and analysis ↔ Astro_GR_KO_snRNA-final.ipynb, lines 643–696 · score 0.54 · glmLRT, edgeR, subset, matrix, DR, NR
  12. [12] § GR regulates postnatal astrocyte maturation ↔ Human_brain_development_multiome_analysis-final.ipynb, lines 562–614 · score 0.52 · chromVAR score, CTX, infant, Adoles, Tri, age
  13. [13] § Methods › Bioinformatics and data analysis › CUT&RUN data processing and analysis ↔ Share_seqV2_example.sh, lines 605–655 · score 0.51 · mapping quality, samtools, duplicate, BAM, CUT, filtering

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Jupyter notebook · 2,255 lines · 102 KB · no license · 5 matches

  1. # %% [markdown]
  2. # # Load libraries
  3. # %%
  4. # Load in libraries
  5. library(Seurat)
  6. library(ggplot2)
  7. library(data.table)
  8. library(stringr)
  9. library(Signac)
  10. library(tradeSeq)
  11. library(BSgenome.Hsapiens.UCSC.hg38)
  12. library(EnsDb.Hsapiens.v86)
  13. library(monaLisa)
  14. library(edgeR)
  15. library(DESeq2)
  16. library(RColorBrewer)
  17. library(pheatmap)
  18. library(paletteer)
  19. library(JASPAR2020)
  20. library(TFBSTools)
  21. library(BiocParallel)
  22. library(paletteer)
  23. library(ghibli)
  24. library(Rmisc)
  25. library(ggbreak)
  26. library(colorspace)
  27. library(pheatmap)
  28. library(RColorBrewer)
  29. library(viridis)
  30. library(ComplexHeatmap)
  31. library(circlize)
  32. library(clusterProfiler)
  33. library(ChIPseeker)
  34. # %%
  35. # Create 'regionize' function for conveniency
  36. regionize <- function(x) {
  37. y <- gsub(',', '', gsub(':', '-', x))
  38. paste0(unlist(strsplit(y,'-'))[1],'-',
  39. as.numeric(unlist(strsplit(y,'-'))[2]) - 5000,'-',
  40. as.numeric(unlist(strsplit(y,'-'))[3]) + 5000)
  41. }
  42. # %%
  43. #library(future)
  44. #plan("multicore", workers = 2)
  45. #options(future.globals.maxSize = 100 * 1024 ^ 3) # for 180 Gb RAM
  46. # %% [markdown]
  47. # # Initial processing
  48. # %%
  49. # Load in data
  50. human_multiome <- readRDS('/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/snMultiome_atlas_Seurat_object.rds')
  51. # %%
  52. DefaultAssay(human_multiome) <- 'ATAC'
  53. # %%
  54. frag_list <- list('/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/ARKFrozen-18-PFC_atac_fragments.tsv.gz',
  55. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/ARKFrozen-19-V1_atac_fragments.tsv.gz',
  56. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/ARKFrozen-1-PFC_atac_fragments.tsv.gz',
  57. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/ARKFrozen-20-CTX_atac_fragments.tsv.gz',
  58. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/ARKFrozen-32-V1_atac_fragments.tsv.gz',
  59. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/ARKFrozen-37-CTX_atac_fragments.tsv.gz',
  60. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/ARKFrozen-41-PFC-2_atac_fragments.tsv.gz',
  61. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/ARKFrozen-41-V1_atac_fragments.tsv.gz',
  62. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/ARKFrozen-43-PFC_atac_fragments.tsv.gz',
  63. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/ARKFrozen-45-CTX_atac_fragments.tsv.gz',
  64. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/ARKFrozen-8-V1_atac_fragments.tsv.gz',
  65. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/GW27-2-7-18-PFC_atac_fragments.tsv.gz',
  66. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/HDBR-14584-CTX_atac_fragments.tsv.gz',
  67. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/HDBR-14831-CTX_atac_fragments.tsv.gz',
  68. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/HDBR-14834-TC_atac_fragments.tsv.gz',
  69. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/HDBR-15020-FB_atac_fragments.tsv.gz',
  70. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-1325-BA10-2_atac_fragments.tsv.gz',
  71. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-1325-BA17_atac_fragments.tsv.gz',
  72. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-1671-BA10-2_atac_fragments.tsv.gz',
  73. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-1671-BA17_atac_fragments.tsv.gz',
  74. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-4267-BA10-2_atac_fragments.tsv.gz',
  75. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-4341-BA17_atac_fragments.tsv.gz',
  76. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-4341-BA9_atac_fragments.tsv.gz',
  77. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-4373-BA17_atac_fragments.tsv.gz',
  78. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-4373-BA9-3_atac_fragments.tsv.gz',
  79. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-4392-BA17_atac_fragments.tsv.gz',
  80. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-4392-BA9_atac_fragments.tsv.gz',
  81. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-4458-BA17_atac_fragments.tsv.gz',
  82. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-4458-BA9-3_atac_fragments.tsv.gz',
  83. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-5162-BA17_atac_fragments.tsv.gz',
  84. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-5162-BA9_atac_fragments.tsv.gz',
  85. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-5376-BA17_atac_fragments.tsv.gz',
  86. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-5376-BA9_atac_fragments.tsv.gz',
  87. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-5554-BA17_atac_fragments.tsv.gz',
  88. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-5554-BA9_atac_fragments.tsv.gz',
  89. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-5900-BA17_atac_fragments.tsv.gz',
  90. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-M1154-BA10-2_atac_fragments.tsv.gz',
  91. '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/NIH-M2837-BA10-2_atac_fragments.tsv.gz')
  92. # %%
  93. frags <- Fragments(human_multiome) # get list of fragment objects
  94. Fragments(human_multiome) <- NULL # remove fragment information from assay
  95. frags[[1]] <- UpdatePath(frags[[1]], new.path = frag_list[[1]])
  96. frags[[2]] <- UpdatePath(frags[[2]], new.path = frag_list[[2]])
  97. frags[[3]] <- UpdatePath(frags[[3]], new.path = frag_list[[3]])
  98. frags[[4]] <- UpdatePath(frags[[4]], new.path = frag_list[[4]])
  99. frags[[5]] <- UpdatePath(frags[[5]], new.path = frag_list[[5]])
  100. frags[[6]] <- UpdatePath(frags[[6]], new.path = frag_list[[6]])
  101. frags[[7]] <- UpdatePath(frags[[7]], new.path = frag_list[[7]])
  102. frags[[8]] <- UpdatePath(frags[[8]], new.path = frag_list[[8]])
  103. frags[[9]] <- UpdatePath(frags[[9]], new.path = frag_list[[9]])
  104. frags[[10]] <- UpdatePath(frags[[10]], new.path = frag_list[[10]])
  105. frags[[11]] <- UpdatePath(frags[[11]], new.path = frag_list[[11]])
  106. frags[[12]] <- UpdatePath(frags[[12]], new.path = frag_list[[12]])
  107. frags[[13]] <- UpdatePath(frags[[13]], new.path = frag_list[[13]])
  108. frags[[14]] <- UpdatePath(frags[[14]], new.path = frag_list[[14]])
  109. frags[[15]] <- UpdatePath(frags[[15]], new.path = frag_list[[15]])
  110. frags[[16]] <- UpdatePath(frags[[16]], new.path = frag_list[[16]])
  111. frags[[17]] <- UpdatePath(frags[[17]], new.path = frag_list[[17]])
  112. frags[[18]] <- UpdatePath(frags[[18]], new.path = frag_list[[18]])
  113. frags[[19]] <- UpdatePath(frags[[19]], new.path = frag_list[[19]])
  114. frags[[20]] <- UpdatePath(frags[[20]], new.path = frag_list[[20]])
  115. frags[[21]] <- UpdatePath(frags[[21]], new.path = frag_list[[21]])
  116. frags[[22]] <- UpdatePath(frags[[22]], new.path = frag_list[[22]])
  117. frags[[23]] <- UpdatePath(frags[[23]], new.path = frag_list[[23]])
  118. frags[[24]] <- UpdatePath(frags[[24]], new.path = frag_list[[24]])
  119. frags[[25]] <- UpdatePath(frags[[25]], new.path = frag_list[[25]])
  120. frags[[26]] <- UpdatePath(frags[[26]], new.path = frag_list[[26]])
  121. frags[[27]] <- UpdatePath(frags[[27]], new.path = frag_list[[27]])
  122. frags[[28]] <- UpdatePath(frags[[28]], new.path = frag_list[[28]])
  123. frags[[29]] <- UpdatePath(frags[[29]], new.path = frag_list[[29]])
  124. frags[[30]] <- UpdatePath(frags[[30]], new.path = frag_list[[30]])
  125. frags[[31]] <- UpdatePath(frags[[31]], new.path = frag_list[[31]])
  126. frags[[32]] <- UpdatePath(frags[[32]], new.path = frag_list[[32]])
  127. frags[[33]] <- UpdatePath(frags[[33]], new.path = frag_list[[33]])
  128. frags[[34]] <- UpdatePath(frags[[34]], new.path = frag_list[[34]])
  129. frags[[35]] <- UpdatePath(frags[[35]], new.path = frag_list[[35]])
  130. frags[[36]] <- UpdatePath(frags[[36]], new.path = frag_list[[36]])
  131. frags[[37]] <- UpdatePath(frags[[37]], new.path = frag_list[[37]])
  132. frags[[38]] <- UpdatePath(frags[[38]], new.path = frag_list[[38]])
  133. Fragments(human_multiome) <- frags # assign update list of fragment objects back to the assay
  134. # %%
  135. # Save RDS object (w/fragments file added)
  136. saveRDS(human_multiome, '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/human_multiome_w_frags.rds')
  137. # %% [markdown]
  138. # # Call peaks & runChromVAR on whole dataset
  139. # %%
  140. # Read RDS object (w/fragments file added)
  141. human_multiome <- readRDS('/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/human_multiome_w_frags.rds')
  142. # %%
  143. DefaultAssay(human_multiome) <- 'ATAC'
  144. peaks_group <- CallPeaks(
  145. object = human_multiome,
  146. group.by = 'Group',
  147. outdir = '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte',
  148. fragment.tempdir = '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte',
  149. macs2.path = '/n/groups/neuroduo/Bruno/jupytervenv_gcc92_gdal314/bin/macs2',
  150. )
  151. # %%
  152. # Save object
  153. saveRDS(peaks_group, '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/peaks_group.rds')
  154. # %%
  155. # Quantify reads in peaks
  156. macs2_counts <- FeatureMatrix(
  157. fragments = Fragments(human_multiome),
  158. features = peaks_group,
  159. process_n = 5000,
  160. cells = colnames(human_multiome)
  161. )
  162. # %%
  163. # Create new chromatin assay with peaks
  164. annotation <- GetGRangesFromEnsDb(ensdb = EnsDb.Hsapiens.v86)
  165. seqlevelsStyle(annotation) <- "UCSC"
  166. human_multiome[["peaks_group"]] <- CreateChromatinAssay(
  167. counts = macs2_counts,
  168. fragments = Fragments(human_multiome),
  169. annotation = annotation,
  170. genome = "hg38"
  171. )
  172. # %%
  173. # Keep peaks only on standard chromosomes
  174. peaks.keep <- seqnames(granges(human_multiome)) %in% standardChromosomes(granges(human_multiome))
  175. # %%
  176. human_multiome[["peaks_group_filt"]] <- CreateChromatinAssay(
  177. counts = human_multiome[['peaks_group']]@data[as.vector(peaks.keep), ],
  178. fragments = Fragments(human_multiome),
  179. annotation = annotation,
  180. genome = "hg38"
  181. )
  182. # %%
  183. # Save object after peaks as chromatin assay
  184. saveRDS(human_multiome, '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/250422_human_multiome_V2_peaks_group.rds')
  185. # %%
  186. # Run region stats
  187. DefaultAssay(human_multiome) <- 'peaks_group_filt'
  188. human_multiome <- RegionStats(human_multiome, genome = BSgenome.Hsapiens.UCSC.hg38)
  189. # %%
  190. # Get JASPAR database
  191. jaspar_pfm <- getMatrixSet(
  192. x = JASPAR2020,
  193. opts = list(collection = "CORE", tax_group = 'vertebrates', all_versions = FALSE)
  194. )
  195. # %%
  196. # Add jaspar motifs
  197. human_multiome <- AddMotifs(
  198. object = human_multiome,
  199. genome = BSgenome.Hsapiens.UCSC.hg38,
  200. pfm = jaspar_pfm,
  201. assay = 'peaks_group_filt'
  202. )
  203. # %%
  204. # Run chromVAR for human dataset
  205. human_multiome <- RunChromVAR(
  206. object = human_multiome,
  207. new.assay.name = "chromvar_peaks_group",
  208. genome = BSgenome.Hsapiens.UCSC.hg38,
  209. assay = 'peaks_group_filt'
  210. )
  211. # %%
  212. saveRDS(human_multiome, '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/250423_human_multiome_jaspar_V2_peaks_group_chromvar.rds')
  213. # %% [markdown]
  214. # # Find differential motifs across all cell types & plot heatmap for Fig. 3
  215. # %%
  216. human_multiome_group_chromvar <- readRDS('/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/250423_human_multiome_jaspar_V2_peaks_group_chromvar.rds')
  217. # %%
  218. DefaultAssay(human_multiome_group_chromvar) <- 'chromvar_peaks_group'
  219. # %%
  220. # For each terminal-differentiated EN type: combine RG-vRG, RG-tRG, RG-oRG, IPC-EN, EN-Newborn, either EN-IT-Immature (l23-IT,L4-IT, L5-IT, L6-IT)
  221. # or EN-Non-IT-Immature (L5-ET, L56_NP, L6-CT, L6b)
  222. # For each terminal-differentiated IN type: combine IN-CGE-Immature w/ IN-CGE-VIP or IN-CGE-SNCG
  223. # combine IN-MGE-Immature w/ IN-MGE-SST or IN-MGE-PV
  224. # Combine Oligodendrocye-Immature w/Oligodendrocyte
  225. # Combine Astrocyte-Immature w/Astrocyte-protoplasmic, Astrocyte-fibrous
  226. # %%
  227. # keep only chromvar assay for analysis (to prevent memory issue)
  228. human_multiome_group_chromvar_only <- human_multiome_group_chromvar[['chromvar_peaks_group']]
  229. # %%
  230. # Convert to seurat object
  231. human_multiome_group_chromvar_only_seu <- CreateSeuratObject(human_multiome_group_chromvar_only)
  232. [email hidden] <- [email hidden]
  233. # %%
  234. # Generate list of downsampled Seurat objects for each mature type
  235. down_obj_list <- list()
  236. # IT neurons
  237. EN_IT_list <- c('EN-L2_3-IT','EN-L4-IT','EN-L5-IT','EN-L6-IT')
  238. for (i in EN_IT_list) {
  239. seurat_sub <- subset(human_multiome_group_chromvar_only_seu, subset = type_updated %in% c(i,
  240. 'RG-vRG',
  241. 'RG-tRG',
  242. 'RG-oRG',
  243. 'IPC-EN',
  244. 'EN-Newborn',
  245. 'EN-IT-Immature'))
  246. if(dim(seurat_sub)[2] > 4000) {
  247. seurat_down <- seurat_sub[,sample(colnames(seurat_sub), size =4000, replace=F)]
  248. down_obj_list[[i]] <- seurat_down}
  249. else if (dim(seurat_sub)[2] <= 4000) {
  250. down_obj_list[[i]] <- seurat_sub}
  251. }
  252. # ET neurons
  253. EN_nonIT_list <- c('EN-L5-ET','EN-L5_6-NP','EN-L6-CT','EN-L6b')
  254. for (i in EN_nonIT_list) {
  255. seurat_sub <- subset(human_multiome_group_chromvar_only_seu, subset = type_updated %in% c(i,'RG-vRG',
  256. 'RG-tRG',
  257. 'RG-oRG',
  258. 'IPC-EN',
  259. 'EN-Newborn',
  260. 'EN-Non-IT-Immature'))
  261. if(dim(seurat_sub)[2] > 10000) {
  262. seurat_down <- seurat_sub[,sample(colnames(seurat_sub), size =10000, replace=F)]
  263. down_obj_list[[i]] <- seurat_down}
  264. else if (dim(seurat_sub)[2] <= 10000) {
  265. down_obj_list[[i]] <- seurat_sub}
  266. }
  267. # CGE neurons
  268. IN_CGE_list <- c('IN-CGE-VIP','IN-CGE-SNCG')
  269. for (i in IN_CGE_list) {
  270. seurat_sub <- subset(human_multiome_group_chromvar_only_seu, subset = type_updated %in% c(i,'IN-CGE-Immature'))
  271. if(dim(seurat_sub)[2] > 10000) {
  272. seurat_down <- seurat_sub[,sample(colnames(seurat_sub), size =10000, replace=F)]
  273. down_obj_list[[i]] <- seurat_down}
  274. else if (dim(seurat_sub)[2] <= 10000) {
  275. down_obj_list[[i]] <- seurat_sub}
  276. }
  277. # MGE neurons
  278. IN_MGE_list <- c('IN-MGE-SST','IN-MGE-PV')
  279. for (i in IN_MGE_list) {
  280. seurat_sub <- subset(human_multiome_group_chromvar_only_seu, subset = type_updated %in% c(i,'IN-MGE-Immature'))
  281. if(dim(seurat_sub)[2] > 6000) {
  282. seurat_down <- seurat_sub[,sample(colnames(seurat_sub), size =6000, replace=F)]
  283. down_obj_list[[i]] <- seurat_down}
  284. else if (dim(seurat_sub)[2] <= 6000) {
  285. down_obj_list[[i]] <- seurat_sub}
  286. }
  287. # Oligodendrocyte
  288. oligo_list <- c('Oligodendrocyte')
  289. for (i in oligo_list) {
  290. seurat_sub <- subset(human_multiome_group_chromvar_only_seu, subset = type_updated %in% c(i,'Oligodendrocyte-Immature'))
  291. if(dim(seurat_sub)[2] > 10000) {
  292. seurat_down <- seurat_sub[,sample(colnames(seurat_sub), size =10000, replace=F)]
  293. down_obj_list[[i]] <- seurat_down}
  294. else if (dim(seurat_sub)[2] <= 10000) {
  295. down_obj_list[[i]] <- seurat_sub}
  296. }
  297. # Other cells
  298. other_list <- c('Microglia','Vascular','OPC','IN-Mix-LAMP5')
  299. for (i in other_list) {
  300. seurat_sub <- subset(human_multiome_group_chromvar_only_seu, subset = type_updated == i)
  301. if(dim(seurat_sub)[2] > 10000) {
  302. seurat_down <- seurat_sub[,sample(colnames(seurat_sub), size =10000, replace=F)]
  303. down_obj_list[[i]] <- seurat_down}
  304. else if (dim(seurat_sub)[2] <= 10000) {
  305. down_obj_list[[i]] <- seurat_sub}
  306. }
  307. # Astrocytes
  308. astro_list <- c('Astrocyte-Protoplasmic')
  309. for (i in astro_list) {
  310. seurat_sub <- subset(human_multiome_group_chromvar_only_seu, subset = type_updated %in% c(i,
  311. 'Astrocyte-Fibrous',
  312. 'Astrocyte-Immature'))
  313. if(dim(seurat_sub)[2] > 10000) {
  314. seurat_down <- seurat_sub[,sample(colnames(seurat_sub), size =10000, replace=F)]
  315. down_obj_list[[i]] <- seurat_down}
  316. else if (dim(seurat_sub)[2] <= 10000) {
  317. down_obj_list[[i]] <- seurat_sub}
  318. }
  319. # %%
  320. # Run FindMarkers on chromvar score for each cell type
  321. DefaultAssay(human_multiome_group_chromvar) <- 'peaks_group_filt'
  322. diff_chromvar_results <- lapply(down_obj_list, function(x){
  323. Idents(x) <- 'Group'
  324. test_res <- FindMarkers(
  325. object = x,
  326. ident.1 = 'Adolescence',
  327. ident.2 = 'First_trimester',
  328. mean.fxn = rowMeans,
  329. test.use='MAST',
  330. fc.name = "avg_diff")
  331. test_res$TF <- ConvertMotifID(Motifs(human_multiome_group_chromvar),id=rownames(test_res))
  332. return(test_res)
  333. })
  334. # %%
  335. # Convert -log10(padj) for each type & calculate scaled padj for induced TFs
  336. diff_chromvar_results_induced_TF <- lapply(diff_chromvar_results, function(x){
  337. x$log10padj <- -log10(x$p_val_adj)
  338. x_up <- x[x$avg_diff>0,]
  339. x_up$scaled_padj <- x_up$log10padj / x_up[1,'log10padj']
  340. return(x_up)
  341. })
  342. # Set cell type column
  343. for (i in names(diff_chromvar_results_induced_TF)){
  344. diff_chromvar_results_induced_TF[[i]]$celltype <- i
  345. }
  346. # %%
  347. # Save results
  348. saveRDS(diff_chromvar_results_induced_TF, '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/250425_diff_chromvar_results_induced_TF.rds')
  349. # %%
  350. # Read results
  351. diff_chromvar_results_induced_TF <- readRDS('/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/250425_diff_chromvar_results_induced_TF.rds')
  352. # %%
  353. # Combine into dataframe
  354. df <- do.call(rbind, diff_chromvar_results_induced_TF)
  355. # %%
  356. # Collect top 2 motifs per cell type
  357. top_motifs <- list()
  358. top_motifs <- lapply(diff_chromvar_results_induced_TF, function(x){
  359. top2 <- x[1:2,'TF']
  360. })
  361. # Combine into single df
  362. top_motif_df <- reshape2::melt(do.call(cbind, top_motifs))
  363. # Collect unique motifs for plotting
  364. uniq_motifs <- unique(top_motif_df$value)
  365. # %%
  366. # Subset results for unique motifs
  367. df_motif_ploting <- df[df$TF %in% uniq_motifs,
  368. c('TF','scaled_padj','celltype')]
  369. # %%
  370. # Cast dataframe to wide form
  371. plot_df_cast <- reshape2::acast(setDT(df_motif_ploting), celltype~TF,value.var='scaled_padj')
  372. plot_df_cast[is.na(plot_df_cast)] <- 0
  373. # %%
  374. # Order cell types by class
  375. plot_df_cast_reorder <- plot_df_cast[c('EN-L2_3-IT',
  376. 'EN-L4-IT',
  377. 'EN-L5-IT',
  378. 'EN-L5-ET',
  379. 'EN-L5_6-NP',
  380. 'EN-L6-IT',
  381. 'EN-L6-CT',
  382. 'EN-L6b',
  383. 'IN-MGE-PV',
  384. 'IN-MGE-SST',
  385. 'IN-CGE-SNCG',
  386. 'IN-CGE-VIP',
  387. 'IN-Mix-LAMP5',
  388. 'Vascular',
  389. 'Microglia',
  390. 'Oligodendrocyte',
  391. 'OPC',
  392. 'Astrocyte-Protoplasmic'),]
  393. rownames(plot_df_cast_reorder)[1] <- 'L2/3'
  394. rownames(plot_df_cast_reorder)[2] <- 'L4IT'
  395. rownames(plot_df_cast_reorder)[3] <- 'L5IT'
  396. rownames(plot_df_cast_reorder)[4] <- 'L5PT'
  397. rownames(plot_df_cast_reorder)[5] <- 'L5/6NP'
  398. rownames(plot_df_cast_reorder)[6] <- 'L6IT'
  399. rownames(plot_df_cast_reorder)[7] <- 'L6CT'
  400. rownames(plot_df_cast_reorder)[8] <- 'L6b'
  401. rownames(plot_df_cast_reorder)[9] <- 'PV+'
  402. rownames(plot_df_cast_reorder)[10] <- 'SST+'
  403. rownames(plot_df_cast_reorder)[11] <- 'SNCG+'
  404. rownames(plot_df_cast_reorder)[12] <- 'VIP+'
  405. rownames(plot_df_cast_reorder)[13] <- 'LAMP5+'
  406. rownames(plot_df_cast_reorder)[14] <- 'Endo'
  407. rownames(plot_df_cast_reorder)[15] <- 'Micro'
  408. rownames(plot_df_cast_reorder)[16] <- 'Oligo'
  409. rownames(plot_df_cast_reorder)[18] <- 'Astro'
  410. # Order motifs
  411. plot_df_cast_reorder <- plot_df_cast_reorder[,c('EGR1',
  412. 'Wt1',
  413. 'EGR3',
  414. 'ZNF75D',
  415. 'MEF2A',
  416. 'MEF2B',
  417. 'MEF2C',
  418. 'FOS',
  419. 'FOS::JUN',
  420. 'FOS::JUND',
  421. 'FOSL2',
  422. 'JUN(var.2)',
  423. 'Smad2::Smad3',
  424. 'BATF3',
  425. 'DBP',
  426. 'TEF',
  427. 'GABPA',
  428. 'ELF1',
  429. 'ELF3',
  430. 'SPI1',
  431. 'NR4A2',
  432. 'NR2C1',
  433. 'ASCL1',
  434. 'NFIC',
  435. 'NR3C1',
  436. 'NR3C2')]
  437. # %%
  438. # Re-label Smad2::Smad3 for space
  439. colnames(plot_df_cast_reorder)[colnames(plot_df_cast_reorder) == 'Smad2::Smad3'] <- 'Smad2/3'
  440. colnames(plot_df_cast_reorder)[colnames(plot_df_cast_reorder) == 'NR3C1'] <- 'GR'
  441. colnames(plot_df_cast_reorder)[colnames(plot_df_cast_reorder) == 'NR3C2'] <- 'MR'
  442. # %%
  443. options(repr.plot.width = 8.7, repr.plot.height = 6.2,repr.plot.res=500)
  444. col_fun = colorRamp2(seq(0, 1,length.out=9), rev(brewer.pal(9, "RdYlBu")))
  445. p <- ComplexHeatmap::pheatmap(plot_df_cast_reorder,
  446. color = col_fun,
  447. cluster_rows = F,
  448. cluster_cols = F,
  449. fontsize = 20,
  450. column_split = c(rep("Group1", 24), rep("Group2", 2)),
  451. column_gap = unit(2, "mm"),
  452. column_title = NULL,
  453. row_names_side = "left",
  454. border_color = 'grey30',
  455. legend=F,
  456. show_rownames = T)
  457. custom_lgd <- Legend(
  458. col_fun = col_fun,
  459. title = "-log10\n(padj)",
  460. legend_height = unit(0.1, "cm"),
  461. legend_width = unit(.5, "cm"),
  462. at = c(0,1),
  463. title_position = "topleft",
  464. labels = c('ns','max'),
  465. title_gp = gpar(fontsize = 18),
  466. labels_gp = gpar(fontsize = 16),
  467. title_gap = unit(4, "mm") # <-- This WILL work here
  468. )
  469. draw(p, heatmap_legend_side="right", heatmap_legend_list = list(custom_lgd))
  470. # %% [markdown]
  471. # # Generate astrocyte GR chromVAR line plots, separately for V1 & PFC
  472. # %%
  473. # Load in dataset
  474. human_multiome_group_chromvar <- readRDS('/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/250423_human_multiome_jaspar_V2_peaks_group_chromvar.rds')
  475. # %%
  476. DefaultAssay(human_multiome_group_chromvar) <- 'chromvar_peaks_group'
  477. # %%
  478. # keep only chromvar assay for analysis (to prevent memory issue)
  479. human_multiome_group_chromvar_only <- human_multiome_group_chromvar[['chromvar_peaks_group']]
  480. # %%
  481. # Convert to seurat object
  482. human_multiome_group_chromvar_only_seu <- CreateSeuratObject(human_multiome_group_chromvar_only)
  483. [email hidden] <- [email hidden]
  484. # %%
  485. # Subset to astrocytes
  486. human_multiome_group_chromvar_only_seu_astro <- subset(human_multiome_group_chromvar_only_seu, subset = subclass == 'Astrocyte')
  487. # %%
  488. options(repr.plot.width=3.9, repr.plot.height=4.5,repr.plot.res=500)
  489. # Create dataframe of chromvar score
  490. astro_nr3c1_df <- data.frame(counts = GetAssayData(human_multiome_group_chromvar_only_seu_astro, slot = "data")['MA0113.3',],
  491. Region = human_multiome_group_chromvar_only_seu_astro$region_summary,
  492. group = human_multiome_group_chromvar_only_seu_astro$Group,
  493. pcd = human_multiome_group_chromvar_only_seu_astro$Estimated_postconceptional_age_in_days)
  494. # Add time variable for plotting
  495. astro_nr3c1_df$Time <- ifelse(astro_nr3c1_df$group=='First_trimester',1,
  496. ifelse(astro_nr3c1_df$group=='Second_trimester',2,
  497. ifelse(astro_nr3c1_df$group=='Third_trimester',3,
  498. ifelse(astro_nr3c1_df$group=='Infancy',4,5))))
  499. astro_nr3c1_df_summary <- summarySE(astro_nr3c1_df, measurevar="counts", conf.interval = 0.95, groupvars=c("Region","Time"))
  500. # Replace General with CTX for plotting
  501. astro_nr3c1_df_summary$Region <- gsub('General','CTX',astro_nr3c1_df_summary$Region)
  502. scaleFUN <- function(x) sprintf("%.1f", x)
  503. ggplot(astro_nr3c1_df_summary, aes(x=Time, y=counts, colour=Region)) +
  504. geom_ribbon(aes(x=as.numeric(Time),ymax = counts + ci, ymin = counts - ci,fill=Region),
  505. alpha = 0.3,
  506. linetype=0) +
  507. geom_line(aes(group=Region),linewidth=2) +
  508. geom_point(size=4) +
  509. geom_hline(yintercept=0,lwd=1,linetype=1,alpha=0.5) + theme_classic() +
  510. ylab('GR chromVAR score') +
  511. xlab('Stage') +
  512. scale_y_continuous(labels=scaleFUN) +
  513. theme(legend.position='right',
  514. axis.text=element_text(size=16,color='black'),
  515. legend.text=element_text(size=16,color='black'),
  516. legend.margin=margin(0,8,0,0),
  517. axis.text.x=element_text(angle=90,vjust=0.5,margin=margin(5,0,0,0)),
  518. axis.title=element_text(size=18,color='black'),
  519. legend.title=element_text(size=18,color='black'),
  520. axis.title.y = element_text(margin = margin(0,5,0,0)),
  521. axis.title.x = element_text(margin = margin(12,0,0,0))) + coord_cartesian(ylim=c(-1.5,1.5)) +
  522. scale_x_continuous(breaks=seq(1,5,1),
  523. labels = c('1st Tri.',
  524. '2nd Tri.',
  525. '3rd Tri.',
  526. 'Infant',
  527. 'Adoles.')) +
  528. scale_color_manual(name = "Human\nbrain region", values=c('grey70',
  529. paletteer::paletteer_d("colorBlindness::Blue2Orange8Steps")[1],
  530. paletteer::paletteer_d("colorBlindness::Blue2Orange8Steps")[8]))+
  531. scale_fill_manual(name = "Human\nbrain region", values=c('grey70',
  532. paletteer::paletteer_d("colorBlindness::Blue2Orange8Steps")[1],
  533. paletteer::paletteer_d("colorBlindness::Blue2Orange8Steps")[8]))
  534. # %%
  535. options(repr.plot.width = 10, repr.plot.height = 3.5, repr.plot.res = 800)
  536. VlnPlot(human_multiome_group_chromvar_only_seu_astro, group.by='Estimated_postconceptional_age_in_days', features= 'MA0113.3',pt.size=0) +
  537. ggtitle('') +
  538. theme(legend.position = 'none',
  539. axis.ticks.x = element_blank(),
  540. axis.title = element_text(size=14,color='black'),
  541. axis.title.x = element_text(margin=margin(10,0,0,0)),
  542. axis.text = element_text(size=12,color='black'),
  543. axis.text.x = element_text(color='black',angle=90,hjust=1,vjust=0.5),
  544. axis.line.x=element_blank()) +
  545. geom_boxplot(fill='grey90',outlier.size=0,width=0.4,lwd=0.3,color='black') +
  546. geom_hline(yintercept=-.9,alpha=0.5) +
  547. ylab('Human astrocyte\nGR chromVAR score') +
  548. xlab('Estimated days post-conception') +
  549. scale_fill_manual(values = c(rep(colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[1],3),
  550. rep(colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[8],7),
  551. rep(colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[12],5),
  552. rep(colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[17],5),
  553. rep(colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[23],4)))
  554. # %% [markdown]
  555. # # Plot chromVAR results for astrocytes as separate volcano plots for V1 & PFC
  556. # %%
  557. # Run chromVAR separately on V1 & PFC astrocytes
  558. human_multiome_group_chromvar_only_seu_astro <- subset(human_multiome_group_chromvar_only_seu, subset = subclass == 'Astrocyte')
  559. # %%
  560. # Subset to V1 and PFC cells
  561. V1_astro <- human_multiome_group_chromvar_only_seu_astro[,human_multiome_group_chromvar_only_seu_astro$region_summary %in% c('General','V1')]
  562. PFC_astro <- human_multiome_group_chromvar_only_seu_astro[,human_multiome_group_chromvar_only_seu_astro$region_summary %in% c('General','PFC')]
  563. # %%
  564. # Test in V1 astrocytes
  565. Idents(V1_astro) <- 'Group'
  566. test_V1_astro <- FindMarkers(
  567. object = V1_astro,
  568. ident.1 = 'Adolescence',
  569. ident.2 = 'First_trimester',
  570. mean.fxn = rowMeans,
  571. test.use='MAST',
  572. fc.name = "avg_diff")
  573. DefaultAssay(human_multiome_group_chromvar) <-'peaks_group_filt'
  574. test_V1_astro$TF <- ConvertMotifID(Motifs(human_multiome_group_chromvar),id=rownames(test_V1_astro))
  575. # Test in PFC astrocytes
  576. Idents(PFC_astro) <- 'Group'
  577. test_PFC_astro <- FindMarkers(
  578. object = PFC_astro,
  579. ident.1 = 'Adolescence',
  580. ident.2 = 'First_trimester',
  581. mean.fxn = rowMeans,
  582. test.use='MAST',
  583. fc.name = "avg_diff")
  584. test_PFC_astro$TF <- ConvertMotifID(Motifs(human_multiome_group_chromvar),id=rownames(test_PFC_astro))
  585. # %%
  586. # Make Volcano plot
  587. options(repr.plot.width=3, repr.plot.height=4.3,repr.plot.res=900)
  588. # Add a column of NAs
  589. test_V1_astro$significant <- "NO"
  590. # Set differential motifs to "induced or repressed"
  591. test_V1_astro$significant[ (test_V1_astro$avg_diff > 1) & (test_V1_astro$p_val_adj < 0.01)] <- "Up"
  592. test_V1_astro$significant[ (test_V1_astro$avg_diff < -1) & (test_V1_astro$p_val_adj < 0.01)] <- "Down"
  593. test_V1_astro$significant <- factor(test_V1_astro$significant, levels = c("NO","Up","Down"))
  594. test_pos <- test_V1_astro[test_V1_astro$avg_diff>0,]
  595. p8 <- ggplot(data = test_pos %>% arrange(significant), aes(x = avg_diff, y = -log10(p_val), col = significant)) + geom_point() +
  596. theme_classic() +
  597. scale_color_manual(values = c("grey70",paletteer::paletteer_d("colorBlindness::Blue2Orange8Steps")[8])) +
  598. theme(axis.text = element_text(size = 20, color = 'black'),
  599. axis.title = element_text(size = 20),
  600. plot.margin=margin(0,40,0,0),
  601. plot.title = element_text(size = 20, hjust = 0.5),
  602. legend.position = 'None') +
  603. xlab('Adoles. vs. 1st Tri.\nchromVAR FC') +
  604. ylab('-log10(p-value)') + ylim(c(0,160)) + xlim(c(0,3))
  605. p8
  606. # %%
  607. # Make Volcano plot
  608. options(repr.plot.width=3, repr.plot.height=4.3,repr.plot.res=900)
  609. # Add a column of NAs
  610. test_PFC_astro$significant <- "NO"
  611. # Set differential motifs to "induced or repressed"
  612. test_PFC_astro$significant[ (test_PFC_astro$avg_diff > 1) & (test_PFC_astro$p_val_adj < 0.01)] <- "Up"
  613. test_PFC_astro$significant[ (test_PFC_astro$avg_diff < -1) & (test_PFC_astro$p_val_adj < 0.01)] <- "Down"
  614. test_PFC_astro$significant <- factor(test_PFC_astro$significant, levels = c("NO","Up","Down"))
  615. test_pos <- test_PFC_astro[test_PFC_astro$avg_diff>0,]
  616. p8 <- ggplot(data = test_pos %>% arrange(significant), aes(x = avg_diff, y = -log10(p_val), col = significant)) + geom_point() +
  617. theme_classic() +
  618. scale_color_manual(values = c("grey70",paletteer::paletteer_d("colorBlindness::Blue2Orange8Steps")[1])) +
  619. theme(axis.text = element_text(size = 20, color = 'black'),
  620. axis.title = element_text(size = 20),
  621. plot.margin=margin(0,40,0,0),
  622. plot.title = element_text(size = 20, hjust = 0.5),
  623. legend.position = 'None') +
  624. xlab('Adoles. vs. 1st Tri.\nchromVAR FC') +
  625. ylab('-log10(p-value)') + ylim(c(0,160)) + xlim(c(0,3))
  626. p8
  627. # %% [markdown]
  628. # # Call peaks only on astrocytes
  629. # %%
  630. # Read RDS object (w/fragments file added)
  631. human_multiome <- readRDS('/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/human_multiome_w_frags.rds')
  632. # %%
  633. # Subset astrocytes
  634. human_multiome_astro <- subset(human_multiome, subset = subclass == 'Astrocyte')
  635. # %%
  636. # Call peaks on astrocytes
  637. DefaultAssay(human_multiome_astro) <- 'ATAC'
  638. peaks <- CallPeaks(
  639. object = human_multiome_astro,
  640. macs2.path = '/n/groups/neuroduo/Bruno/jupytervenv_gcc92_gdal314/bin/macs2',
  641. group.by = 'Group'
  642. )
  643. # %%
  644. # Save object
  645. saveRDS(peaks,'/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/peaks_240121.rds')
  646. # %%
  647. # Quantify reads in peaks
  648. macs2_counts <- FeatureMatrix(
  649. fragments = Fragments(human_multiome_astro),
  650. features = peaks,
  651. cells = colnames(human_multiome_astro)
  652. )
  653. # %%
  654. # Save object
  655. saveRDS(macs2_counts,'/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/macs2_counts_240121.rds')
  656. # %%
  657. # Create new chromatin assay with peaks
  658. annotation <- GetGRangesFromEnsDb(ensdb = EnsDb.Hsapiens.v86)
  659. seqlevelsStyle(annotation) <- "UCSC"
  660. human_multiome_astro[["peaks"]] <- CreateChromatinAssay(
  661. counts = macs2_counts,
  662. fragments = Fragments(human_multiome_astro),
  663. annotation = annotation,
  664. genome = "hg38"
  665. )
  666. # %%
  667. # Save object after peaks as chromatin assay
  668. saveRDS(human_multiome_astro,'/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/250427_human_multiome_astro_v2.rds')
  669. # %% [markdown]
  670. # # Compute astrocyte developmental DEGs (devDEGs) for Fig. 3
  671. # %%
  672. # Read RDS file
  673. human_multiome_astro_v2 <- readRDS('/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/250427_human_multiome_astro_v2.rds')
  674. # %%
  675. # Aggregate counts
  676. human_multiome_astro_agg <- AggregateExpression(human_multiome_astro_v2,
  677. assays = 'RNA',
  678. group.by = 'Ident',
  679. slot='counts',
  680. return.seurat = TRUE)
  681. # %%
  682. # Create metadata
  683. meta_df <- unique(data.frame([email hidden][human_multiome_astro_v2$Ident %in% human_multiome_astro_v2$Ident,'Ident'],
  684. [email hidden][human_multiome_astro_v2$Ident %in% human_multiome_astro_v2$Ident,c('Group','region_summary')]))
  685. metadata_df <- data.frame(Sample = meta_df[,1],
  686. Group = meta_df[,2],
  687. Region = meta_df[,3],
  688. Group_region = paste0(meta_df[,2], '_', meta_df[,3]))
  689. # %%
  690. # Run DESeq2 analysis (use this to match DESeq analysis used for bulk astrocyte RNA-seq)
  691. deseq_obj <- DESeqDataSetFromMatrix(countData = GetAssayData(human_multiome_astro_agg,slot='counts'),
  692. colData = metadata_df[match(colnames(GetAssayData(human_multiome_astro_agg,slot='counts')),metadata_df$Sample),],
  693. design = ~ Group)
  694. # %%
  695. # Run Deseq2
  696. deseq_obj <- DESeq(deseq_obj)
  697. resdf <- na.omit(as.data.frame(results(deseq_obj, contrast=c("Group","Adolescence","First_trimester"),lfcThreshold=1)))
  698. # %%
  699. # Normalize data
  700. ntd <- normTransform(deseq_obj)
  701. # %%
  702. # Compute mean expression per group for plotting
  703. df <- data.frame(First_trimester = rowMeans(assay(ntd)[,c(13:16)]),
  704. Second_trimester = rowMeans(assay(ntd)[,c(1:11)]),
  705. Third_trimester = rowMeans(assay(ntd)[,c(12,21,36:38)]),
  706. Infant = rowMeans(assay(ntd)[,c(17:20,24:29)]),
  707. Adolescence = rowMeans(assay(ntd)[,c(22,23,30:35)]))
  708. names(df) <- c('1st Tri.',
  709. '2nd Tri.',
  710. '3rd Tri.',
  711. 'Infant',
  712. 'Adoles.')
  713. # %%
  714. # Set colors for plotting
  715. my_palette <- colorRampPalette(rev(brewer.pal(9,'RdBu')))(1000) # 1000 colors
  716. my_breaks <- seq(-2, 2, length.out = 1001)
  717. # %%
  718. # Generate initial plot
  719. options(repr.plot.width = 2, repr.plot.height = 4,repr.plot.res=500)
  720. t <- df[rownames(resdf[resdf$padj<0.01,]),]
  721. p <- ComplexHeatmap::pheatmap(t(scale(t(t))),
  722. cluster_cols = FALSE,
  723. color = my_palette,
  724. cluster_rows = T,
  725. clustering_method = 'ward.D2',
  726. cutree_rows=4,
  727. treeheight_row = unit(6, "mm"),
  728. show_rownames = FALSE,
  729. heatmap_legend_param = list(title = "Scaled RNA",at = c(-2,0,2),
  730. labels = c('-2','0','2'),
  731. legend_height = unit(1, "cm"),
  732. legend_width = unit(1.5, "cm"),
  733. title_position = "topcenter",
  734. legend_direction = "horizontal",
  735. title_gp = gpar(fontsize = 10),
  736. labels_gp = gpar(fontsize = 10)),
  737. border_color=NA,
  738. border=TRUE)
  739. draw(p, heatmap_legend_side="bottom")
  740. # %%
  741. # Extract clustering results
  742. p2 <- pheatmap::pheatmap(t,
  743. cluster_cols = FALSE,
  744. cluster_rows = T,
  745. clustering_method = 'ward.D2',
  746. cutree_rows=4,
  747. scale = 'row',
  748. silent=T)
  749. t.clust <- as.data.frame(cbind(t,
  750. cluster = cutree(p2$tree_row,
  751. k = 4)))
  752. table(t.clust$cluster)
  753. # %%
  754. # Suppose you want the slices to appear in order 3, 1, 2 & without dendrogram
  755. new_order <- c(1, 3, 2, 4)
  756. # Convert to factor with desired order
  757. row_split <- factor(cutree(p2$tree_row, k = 4), levels = new_order)
  758. row_order <- order.dendrogram(as.dendrogram(p2$tree_row))
  759. options(repr.plot.width = 1.8, repr.plot.height = 4,repr.plot.res=900)
  760. t <- df[rownames(resdf[resdf$padj<0.01,]),]
  761. p <- ComplexHeatmap::pheatmap(t(scale(t(t))),
  762. cluster_cols = FALSE,
  763. color = my_palette,
  764. cluster_rows = F,
  765. clustering_method = 'ward.D2',
  766. row_split = row_split,
  767. row_order = row_order,
  768. row_title =NULL,
  769. treeheight_row = unit(6, "mm"),
  770. show_rownames = FALSE,
  771. border = TRUE,
  772. heatmap_legend_param = list(title = "Scaled RNA",at = c(-2,0,2),
  773. labels = c('-2','0','2'),
  774. legend_height = unit(1, "cm"),
  775. legend_width = unit(1.5, "cm"),
  776. title_position = "topcenter",
  777. legend_direction = "horizontal",
  778. title_gp = gpar(fontsize = 10),
  779. labels_gp = gpar(fontsize = 10)),
  780. border_color=NA)
  781. draw(p, heatmap_legend_side="bottom")
  782. # %%
  783. # Process data
  784. sample_df <- data.frame(t(scale(t(data.frame(assay(ntd)[rownames(t.clust),])))))
  785. sample_df$gene <- rownames(sample_df)
  786. sample_df_melt <- reshape2::melt(sample_df, id='gene')
  787. sample_df_melt$Group <- rep(metadata_df[match(colnames(GetAssayData(human_multiome_astro_agg,slot='counts')),metadata_df$Sample),c('Group')],
  788. each=dim(t.clust)[1])
  789. sample_df_melt$cluster <- as.character(rep(t.clust$cluster, times = (dim(sample_df)[2]-1)))
  790. # %%
  791. # Add time variable for plotting
  792. sample_df_melt$Time <- ifelse(sample_df_melt$Group=='First_trimester',1,
  793. ifelse(sample_df_melt$Group=='Second_trimester',2,
  794. ifelse(sample_df_melt$Group=='Third_trimester',3,
  795. ifelse(sample_df_melt$Group=='Infancy',4,5))))
  796. sample_df_melt_summary <- summarySE(sample_df_melt, measurevar="value", conf.interval = 0.95, groupvars=c('Time','cluster'))
  797. # %%
  798. # Generate scaled expression for gene clusters as line plot
  799. options(repr.plot.width=3.4, repr.plot.height=4.5,repr.plot.res=500)
  800. scaleFUN <- function(x) sprintf("%.1f", x)
  801. ggplot(sample_df_melt_summary, aes(x=Time, y=value, group=cluster, color=cluster)) +
  802. geom_ribbon(aes(x=as.numeric(Time),ymax = value + se, ymin = value - se,fill=cluster,color=cluster),
  803. alpha = 0.3,
  804. linetype=0) +
  805. geom_line(aes(group=cluster),linewidth=2) +
  806. geom_point(size=4) +
  807. geom_hline(yintercept=0,lwd=1,linetype=1,alpha=0.5) + theme_classic() +
  808. ylab('Scaled expression') +
  809. xlab('Stage') +
  810. scale_y_continuous(labels=scaleFUN) +
  811. theme(legend.position='right',
  812. axis.text=element_text(size=16,color='black'),
  813. legend.text=element_text(size=16,color='black'),
  814. legend.margin=margin(0,8,0,0),
  815. axis.text.x=element_text(angle=90,vjust=0.5,margin=margin(5,0,0,0)),
  816. axis.title=element_text(size=18,color='black'),
  817. legend.title=element_text(size=18,color='black'),
  818. axis.title.y = element_text(margin = margin(0,5,0,0)),
  819. axis.title.x = element_text(margin = margin(12,0,0,0))) +
  820. scale_x_continuous(breaks=seq(1,5,1),
  821. labels = c('1st Tri.',
  822. '2nd Tri.',
  823. '3rd Tri.',
  824. 'Infant',
  825. 'Adoles.')) +
  826. scale_color_manual(name = 'Cluster', values = as.vector(paletteer::paletteer_d("fishualize::Pseudocheilinus_tetrataenia")[1:4])) +
  827. scale_fill_manual(name = 'Cluster', values = as.vector(paletteer::paletteer_d("fishualize::Pseudocheilinus_tetrataenia")[1:4]))
  828. # %% [markdown]
  829. # # Compute overlap b/w devDEG clusters & mouse GR targets for Fig. 3
  830. # %%
  831. # Convert mouse genes to human
  832. library(dplyr)
  833. mouse_human_genes = read.csv("http://www.informatics.jax.org/downloads/reports/HOM_MouseHumanSequence.rpt",sep="\t")
  834. convert_mouse_to_human <- function(gene_list){
  835. output = c()
  836. for(gene in gene_list){
  837. class_key = (mouse_human_genes %>% filter(Symbol == gene & Common.Organism.Name=="mouse, laboratory"))[['DB.Class.Key']]
  838. if(!identical(class_key, integer(0)) ){
  839. human_genes = (mouse_human_genes %>% filter(DB.Class.Key == class_key & Common.Organism.Name=="human"))[,"Symbol"]
  840. for(human_gene in human_genes){
  841. output = append(output,human_gene)
  842. }
  843. }
  844. }
  845. return (output)
  846. }
  847. # %%
  848. # Read in GR-target gene data
  849. P21_DEG_relax <- readRDS('/n/groups/neuroduo/Bruno/Astro_NR_DR_RNA_analysis/P21_GR_dep_res_relax.rds')
  850. # %%
  851. # Convert mouse to human gene symbols
  852. P21_DEG_relax_sig_human <- convert_mouse_to_human(rownames(P21_DEG_relax[P21_DEG_relax$padj<0.05,]))
  853. # %%
  854. # Compute overlap with each cluster
  855. overlap_df <- data.frame(overlap = c(table(rownames(t.clust[t.clust$cluster == 1,]) %in%
  856. P21_DEG_relax_sig_human)[2] / length(rownames(t.clust[t.clust$cluster == 1,])),
  857. table(rownames(t.clust[t.clust$cluster == 2,]) %in%
  858. P21_DEG_relax_sig_human)[2] / length(rownames(t.clust[t.clust$cluster == 2,])),
  859. table(rownames(t.clust[t.clust$cluster == 3,]) %in%
  860. P21_DEG_relax_sig_human)[2] / length(rownames(t.clust[t.clust$cluster == 3,])),
  861. table(rownames(t.clust[t.clust$cluster == 4,]) %in%
  862. P21_DEG_relax_sig_human)[2] / length(rownames(t.clust[t.clust$cluster == 4,]))),
  863. cluster = c('1','2','3','4'))
  864. overlap_df$overlap <- overlap_df$overlap * 100
  865. overlap_df$x <- '1'
  866. # %%
  867. # Calculate overlaps for Fisher test
  868. ov1 <- rbind(table(rownames(t.clust[t.clust$cluster == 1,]) %in%
  869. P21_DEG_relax_sig_human),
  870. table(rownames(resdf[rownames(resdf) %notin% rownames(t.clust[t.clust$cluster ==1,]),]) %in%
  871. P21_DEG_relax_sig_human))
  872. ov2 <- rbind(table(rownames(t.clust[t.clust$cluster == 2,]) %in%
  873. P21_DEG_relax_sig_human),
  874. table(rownames(resdf[rownames(resdf) %notin% rownames(t.clust[t.clust$cluster ==2,]),]) %in%
  875. P21_DEG_relax_sig_human))
  876. ov3 <- rbind(table(rownames(t.clust[t.clust$cluster == 3,]) %in%
  877. P21_DEG_relax_sig_human),
  878. table(rownames(resdf[rownames(resdf) %notin% rownames(t.clust[t.clust$cluster ==3,]),]) %in%
  879. P21_DEG_relax_sig_human))
  880. ov4 <- rbind(table(rownames(t.clust[t.clust$cluster == 4,]) %in%
  881. P21_DEG_relax_sig_human),
  882. table(rownames(resdf[rownames(resdf) %notin% rownames(t.clust[t.clust$cluster ==4,]),]) %in%
  883. P21_DEG_relax_sig_human))
  884. # %%
  885. # Add Fisher test results to object
  886. overlap_df$pval <- c(fisher.test(ov1)$p.value,
  887. fisher.test(ov2)$p.value,
  888. fisher.test(ov3)$p.value,
  889. fisher.test(ov4)$p.value)
  890. overlap_df$logpval <- -log10(overlap_df$pval)
  891. # %%
  892. # Set order for plotting
  893. overlap_df$cluster <- factor(overlap_df$cluster, levels = rev(c('1','3','2','4')))
  894. # %%
  895. # Generate dot plot of overlap and Fisher test p-value
  896. options(repr.plot.width=1.6, repr.plot.height=2,repr.plot.res=1200)
  897. ggplot(overlap_df, aes(x=x, y=cluster, size = overlap, fill=logpval)) +
  898. geom_point(shape=21,alpha=1,stroke=0.4) + theme_bw() + scale_radius(breaks = c(6,18)) + theme(axis.title = element_blank(),
  899. axis.text.x = element_blank(),
  900. panel.grid.major = element_line(color = "grey98"),
  901. axis.text.y = element_blank(),
  902. legend.title=element_text(hjust=0,size=10),
  903. legend.text=element_text(size=10),
  904. legend.margin=margin(0,5,0,0),
  905. legend.key.height = unit(1,'mm'),
  906. legend.key.width = unit(4,'mm'),
  907. legend.position='right',
  908. axis.ticks.x = element_blank()) + labs(size = "% overlap",fill='-log10\n(p-val)') +
  909. scale_fill_viridis(option='rocket',breaks=c(2,25),labels=c('ns','25'))
  910. # %% [markdown]
  911. # # Link peaks to astrocyte devDEGs for motif analysis
  912. # %%
  913. library(future)
  914. plan("multicore", workers = 8)
  915. options(future.globals.maxSize = 100 * 1024 ^ 3) # for 100 Gb RAM
  916. # %%
  917. # Read RDS file
  918. human_multiome_astro_v2 <- readRDS('/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/250427_human_multiome_astro_v2.rds')
  919. # %%
  920. # Run region stats
  921. DefaultAssay(human_multiome_astro_v2) <- 'peaks'
  922. human_multiome_astro_v2 <- RegionStats(human_multiome_astro_v2, genome = BSgenome.Hsapiens.UCSC.hg38)
  923. # %%
  924. # Get JASPAR database
  925. jaspar_pfm <- getMatrixSet(
  926. x = JASPAR2020,
  927. opts = list(collection = "CORE", tax_group = 'vertebrates', all_versions = FALSE)
  928. )
  929. # %%
  930. # Add jaspar motifs
  931. human_multiome_astro_v2 <- AddMotifs(
  932. object = human_multiome_astro_v2,
  933. genome = BSgenome.Hsapiens.UCSC.hg38,
  934. pfm = jaspar_pfm,
  935. assay = 'peaks'
  936. )
  937. # %%
  938. # Save RDS file w/motif object for astrocyte-called peaks
  939. saveRDS(human_multiome_astro_v2, '/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/250427_human_multiome_astro_v2.rds')
  940. # %%
  941. # Run LinkPeaks on devDEGs
  942. DefaultAssay(human_multiome_astro_v2) <- 'RNA'
  943. c1_links <- LinkPeaks(human_multiome_astro_v2,
  944. expression.assay = 'RNA',
  945. peak.assay = 'peaks',
  946. min.distance = 5000,
  947. distance = 300000,
  948. genes.use = rownames(t.clust[t.clust$cluster == 1,]))
  949. c2_links <- LinkPeaks(human_multiome_astro_v2,
  950. expression.assay = 'RNA',
  951. peak.assay = 'peaks',
  952. min.distance = 5000,
  953. distance = 300000,
  954. genes.use = rownames(t.clust[t.clust$cluster == 2,]))
  955. c3_links <- LinkPeaks(human_multiome_astro_v2,
  956. expression.assay = 'RNA',
  957. peak.assay = 'peaks',
  958. min.distance = 5000,
  959. distance = 300000,
  960. genes.use = rownames(t.clust[t.clust$cluster == 3,]))
  961. c4_links <- LinkPeaks(human_multiome_astro_v2,
  962. expression.assay = 'RNA',
  963. peak.assay = 'peaks',
  964. min.distance = 5000,
  965. distance = 300000,
  966. genes.use = rownames(t.clust[t.clust$cluster == 4,]))
  967. # %%
  968. # Convert results to dataframe
  969. DefaultAssay(c1_links) <- 'peaks'
  970. c1_links_df <- as.data.frame(Links(c1_links))
  971. DefaultAssay(c2_links) <- 'peaks'
  972. c2_links_df <- as.data.frame(Links(c2_links))
  973. DefaultAssay(c3_links) <- 'peaks'
  974. c3_links_df <- as.data.frame(Links(c3_links))
  975. DefaultAssay(c4_links) <- 'peaks'
  976. c4_links_df <- as.data.frame(Links(c4_links))
  977. # %%
  978. # Find enriched motifs in top-ranked peaks for each cluster
  979. enriched.motifs1 <- FindMotifs(
  980. object = c1_links,
  981. c1_links_df[(c1_links_df$pvalue <0.001) &
  982. (c1_links_df$score>0),'peak']
  983. )
  984. enriched.motifs2 <- FindMotifs(
  985. object = c2_links,
  986. c2_links_df[(c2_links_df$pvalue <0.001) &
  987. (c2_links_df$score>0),'peak']
  988. )
  989. enriched.motifs3 <- FindMotifs(
  990. object = c3_links,
  991. c3_links_df[(c3_links_df$pvalue <0.001) &
  992. (c3_links_df$score>0),'peak']
  993. )
  994. enriched.motifs4 <- FindMotifs(
  995. object = c4_links,
  996. c4_links_df[(c4_links_df$pvalue <0.001) &
  997. (c4_links_df$score>0),'peak']
  998. )
  999. # %%
  1000. # Generate plot for cluster 1
  1001. options(repr.plot.width=3, repr.plot.height=4,repr.plot.res=900)
  1002. enriched.motifs1$motif.name <- gsub('FOSL1::JUN\\(var\\.2\\)', 'FOSL1::\nJUN(var.2)', enriched.motifs1$motif.name)
  1003. enriched.motifs1$motif.name <- factor(enriched.motifs1$motif.name, levels = enriched.motifs1$motif.name)
  1004. p3 <- ggplot(enriched.motifs1[1:5,], aes(x=motif.name, y=-log10(p.adjust))) +
  1005. geom_bar(stat = "identity",width=0.7,fill=as.vector(paletteer::paletteer_d("fishualize::Pseudocheilinus_tetrataenia")[1])) + theme_classic() +
  1006. xlab('TF motif') +
  1007. ylab('-log10(padj)') +
  1008. theme(axis.text = element_text(color='black',size=18),
  1009. axis.text.x = element_text(angle=45,hjust=1),
  1010. axis.title = element_text(color='black',size=18),
  1011. plot.margin=margin(5,8,5,0),
  1012. axis.title.x=element_blank())
  1013. # %%
  1014. # Generate plot for cluster 2
  1015. options(repr.plot.width=3, repr.plot.height=4,repr.plot.res=900)
  1016. enriched.motifs2$motif.name <- gsub('NR3C1', 'GR', enriched.motifs2$motif.name)
  1017. enriched.motifs2$motif.name <- gsub('NR3C2', 'MR', enriched.motifs2$motif.name)
  1018. enriched.motifs2$motif.name <- factor(enriched.motifs2$motif.name, levels = enriched.motifs2$motif.name)
  1019. p2 <- ggplot(enriched.motifs2[1:5,], aes(x=motif.name, y=-log10(p.adjust))) +
  1020. geom_bar(stat = "identity",width=0.7,fill=as.vector(paletteer::paletteer_d("fishualize::Pseudocheilinus_tetrataenia")[2])) + theme_classic() +
  1021. xlab('TF motif') +
  1022. ylab('-log10(padj)') +
  1023. theme(axis.text = element_text(color='black',size=18),
  1024. axis.text.x = element_text(angle=45,hjust=1),
  1025. plot.margin=margin(40,8,-10,0),
  1026. axis.title = element_text(color='black',size=18),
  1027. axis.title.x=element_blank())
  1028. # %%
  1029. # Generate plot for cluster 3
  1030. options(repr.plot.width=3, repr.plot.height=4,repr.plot.res=900)
  1031. enriched.motifs3$motif.name <- factor(enriched.motifs3$motif.name, levels = enriched.motifs3$motif.name)
  1032. p4 <- ggplot(enriched.motifs3[1:5,], aes(x=motif.name, y=-log10(p.adjust))) +
  1033. geom_bar(stat = "identity",width=0.7,fill=as.vector(paletteer::paletteer_d("fishualize::Pseudocheilinus_tetrataenia")[3])) + theme_classic() +
  1034. xlab('TF motif') +
  1035. ylab('-log10(padj)') +
  1036. theme(axis.text = element_text(color='black',size=18),
  1037. axis.text.x = element_text(angle=45,hjust=1),
  1038. plot.margin=margin(5,0,5,0),
  1039. axis.title = element_text(color='black',size=18),
  1040. axis.title.x=element_blank())
  1041. # %%
  1042. # Generate plot for cluster 4
  1043. options(repr.plot.width=3, repr.plot.height=4,repr.plot.res=900)
  1044. enriched.motifs4$motif.name <- factor(enriched.motifs4$motif.name, levels = enriched.motifs4$motif.name)
  1045. p1 <- ggplot(enriched.motifs4[1:5,], aes(x=motif.name, y=-log10(p.adjust))) +
  1046. geom_bar(stat = "identity",width=0.7,fill=as.vector(paletteer::paletteer_d("fishualize::Pseudocheilinus_tetrataenia")[4])) + theme_classic() +
  1047. xlab('TF motif') +
  1048. ylab('-log10(padj)') +
  1049. theme(axis.text = element_text(color='black',size=18),
  1050. axis.text.x = element_text(angle=45,hjust=1),
  1051. plot.margin=margin(40,0,-10,0),
  1052. axis.title = element_text(color='black',size=18),
  1053. axis.title.x=element_blank())
  1054. # %%
  1055. # Assemble plots
  1056. options(repr.plot.width=5.2, repr.plot.height=6.8,repr.plot.res=1200)
  1057. cowplot::plot_grid(p3,p4,p2,p1,ncol=2,align='hv')
  1058. # %% [markdown]
  1059. # # Identify astrocyte developmental DARs (devDARs) using DESeq2
  1060. # %%
  1061. # Read RDS file w/motif object for astrocyte-called peaks
  1062. human_multiome_astro_v2 <- readRDS('/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/250427_human_multiome_astro_v2.rds')
  1063. # %%
  1064. # Aggregate ATAC peak counts per sample
  1065. human_multiome_astro_agg <- AggregateExpression(human_multiome_astro_v2,
  1066. assays = 'peaks',
  1067. group.by = 'Ident',
  1068. slot = 'counts',
  1069. return.seurat = TRUE)
  1070. # %%
  1071. # Create metadata
  1072. meta_df <- unique(data.frame([email hidden][human_multiome_astro_v2$Ident %in% human_multiome_astro_v2$Ident,'Ident'],
  1073. [email hidden][human_multiome_astro_v2$Ident %in% human_multiome_astro_v2$Ident,c('Group','region_summary')]))
  1074. metadata_df <- data.frame(Sample = meta_df[,1],
  1075. Group = meta_df[,2],
  1076. Region = meta_df[,3],
  1077. Group_region = paste0(meta_df[,2], '_', meta_df[,3]))
  1078. # %%
  1079. # Run DESeq2 analysis on ATAC peaks
  1080. deseq_obj <- DESeqDataSetFromMatrix(countData = GetAssayData(human_multiome_astro_agg,slot='counts'),
  1081. colData = metadata_df[match(colnames(GetAssayData(human_multiome_astro_agg,slot='counts')),metadata_df$Sample),],
  1082. design = ~ Group)
  1083. # Run Deseq2
  1084. deseq_obj <- DESeq(deseq_obj)
  1085. resdf <- na.omit(as.data.frame(results(deseq_obj,contrast=c("Group","Adolescence","First_trimester"),lfcThreshold=1)))
  1086. # %%
  1087. # Normalize data
  1088. ntd <- normTransform(deseq_obj)
  1089. # %%
  1090. # Compute mean expression per group for plotting
  1091. df <- data.frame(First_trimester = rowMeans(assay(ntd)[,c(13:16)]),
  1092. Second_trimester = rowMeans(assay(ntd)[,c(1:11)]),
  1093. Third_trimester = rowMeans(assay(ntd)[,c(12,21,36:38)]),
  1094. Infant = rowMeans(assay(ntd)[,c(17:20,24:29)]),
  1095. Adolescence = rowMeans(assay(ntd)[,c(22,23,30:35)]))
  1096. names(df) <- c('1st Tri.',
  1097. '2nd Tri.',
  1098. '3rd Tri.',
  1099. 'Infant',
  1100. 'Adoles.')
  1101. # %%
  1102. # Create color palette
  1103. my_palette <- colorRampPalette(rev(brewer.pal(9,'RdBu')))(1000) # 1000 colors
  1104. my_breaks <- seq(-2, 2, length.out = 1001)
  1105. # %%
  1106. # Generate initial heatmap
  1107. options(repr.plot.width = 2, repr.plot.height = 4,repr.plot.res=500)
  1108. t <- df[rownames(resdf[resdf$padj<0.05,]),]
  1109. p <- ComplexHeatmap::pheatmap(t(scale(t(t))),
  1110. cluster_cols = FALSE,
  1111. color = my_palette,
  1112. cluster_rows = T,
  1113. clustering_method = 'ward.D2',
  1114. cutree_rows=4,
  1115. treeheight_row = unit(6, "mm"),
  1116. show_rownames = FALSE,
  1117. heatmap_legend_param = list(title = "Scaled ATAC",at = c(-2,0,2),
  1118. labels = c('-2','0','2'),
  1119. legend_height = unit(1, "cm"),
  1120. legend_width = unit(1.5, "cm"),
  1121. title_position = "topcenter",
  1122. legend_direction = "horizontal",
  1123. title_gp = gpar(fontsize = 10),
  1124. labels_gp = gpar(fontsize = 10)),
  1125. border_color=NA,
  1126. border=TRUE)
  1127. draw(p, heatmap_legend_side="bottom")
  1128. # %%
  1129. # Extract clustering results
  1130. t <- df[rownames(resdf[resdf$padj<0.05,]),]
  1131. p2 <- pheatmap::pheatmap(t,
  1132. cluster_cols = FALSE,
  1133. cluster_rows = T,
  1134. clustering_method = 'ward.D2',
  1135. cutree_rows=4,
  1136. scale = 'row',
  1137. silent=T)
  1138. t.clust <- as.data.frame(cbind(t,
  1139. cluster = cutree(p2$tree_row,
  1140. k = 4)))
  1141. table(t.clust$cluster)
  1142. # %%
  1143. # Suppose you want the slices to appear in order & without dendrogram
  1144. new_order <- c(3, 1, 4, 2)
  1145. # Convert to factor with desired order
  1146. row_split <- factor(cutree(p2$tree_row, k = 4), levels = new_order)
  1147. row_order <- order.dendrogram(as.dendrogram(p2$tree_row))
  1148. options(repr.plot.width = 1.8, repr.plot.height = 4,repr.plot.res=900)
  1149. t <- df[rownames(resdf[resdf$padj<0.05,]),]
  1150. p <- ComplexHeatmap::pheatmap(t(scale(t(t))),
  1151. cluster_cols = FALSE,
  1152. color = my_palette,
  1153. cluster_rows = F,
  1154. clustering_method = 'ward.D2',
  1155. row_split = row_split,
  1156. row_order = row_order,
  1157. row_title =NULL,
  1158. treeheight_row = unit(6, "mm"),
  1159. show_rownames = FALSE,
  1160. border = TRUE,
  1161. heatmap_legend_param = list(title = "Scaled ATAC",at = c(-2,0,2),
  1162. labels = c('-2','0','2'),
  1163. legend_height = unit(1, "cm"),
  1164. legend_width = unit(1.5, "cm"),
  1165. title_position = "topcenter",
  1166. legend_direction = "horizontal",
  1167. title_gp = gpar(fontsize = 10),
  1168. labels_gp = gpar(fontsize = 10)),
  1169. border_color=NA)
  1170. draw(p, heatmap_legend_side="bottom")
  1171. # %%
  1172. # Process data
  1173. sample_df <- data.frame(t(scale(t(data.frame(assay(ntd)[rownames(t.clust),])))))
  1174. sample_df$peak <- rownames(sample_df)
  1175. sample_df_melt <- reshape2::melt(sample_df, id='peak')
  1176. sample_df_melt$Group <- rep(metadata_df[match(colnames(GetAssayData(human_multiome_astro_agg,slot='counts')),metadata_df$Sample),c('Group')],
  1177. each=dim(t.clust)[1])
  1178. sample_df_melt$cluster <- as.character(rep(t.clust$cluster, times = (dim(sample_df)[2]-1)))
  1179. # %%
  1180. # Add time variable for plotting
  1181. sample_df_melt$Time <- ifelse(sample_df_melt$Group=='First_trimester',1,
  1182. ifelse(sample_df_melt$Group=='Second_trimester',2,
  1183. ifelse(sample_df_melt$Group=='Third_trimester',3,
  1184. ifelse(sample_df_melt$Group=='Infancy',4,5))))
  1185. sample_df_melt_summary <- summarySE(sample_df_melt, measurevar="value", conf.interval = 0.95, groupvars=c('Time','cluster'))
  1186. # %%
  1187. # Generate line plots of scaled accessibility within peak clusters
  1188. options(repr.plot.width=3.4, repr.plot.height=4.5,repr.plot.res=500)
  1189. scaleFUN <- function(x) sprintf("%.1f", x)
  1190. ggplot(sample_df_melt_summary, aes(x=Time, y=value, group=cluster, color=cluster)) +
  1191. geom_ribbon(aes(x=as.numeric(Time),ymax = value + se, ymin = value - se,fill=cluster,color=cluster),
  1192. alpha = 0.3,
  1193. linetype=0) +
  1194. geom_line(aes(group=cluster),linewidth=2) +
  1195. geom_point(size=4) +
  1196. geom_hline(yintercept=0,lwd=1,linetype=1,alpha=0.5) + theme_classic() +
  1197. ylab('Scaled accessibility') +
  1198. xlab('Stage') +
  1199. scale_y_continuous(labels=scaleFUN) +
  1200. theme(legend.position='right',
  1201. axis.text=element_text(size=16,color='black'),
  1202. legend.text=element_text(size=16,color='black'),
  1203. legend.margin=margin(0,8,0,0),
  1204. axis.text.x=element_text(angle=90,vjust=0.5,margin=margin(5,0,0,0)),
  1205. axis.title=element_text(size=18,color='black'),
  1206. legend.title=element_text(size=18,color='black'),
  1207. axis.title.y = element_text(margin = margin(0,5,0,0)),
  1208. axis.title.x = element_text(margin = margin(12,0,0,0))) +
  1209. scale_x_continuous(breaks=seq(1,5,1),
  1210. labels = c('1st Tri.',
  1211. '2nd Tri.',
  1212. '3rd Tri.',
  1213. 'Infant',
  1214. 'Adoles.')) +
  1215. scale_color_manual(name = 'Cluster', values = as.vector(paletteer::paletteer_d("fishualize::Pseudocheilinus_tetrataenia")[c(3,4,1,2)])) +
  1216. scale_fill_manual(name = 'Cluster', values = as.vector(paletteer::paletteer_d("fishualize::Pseudocheilinus_tetrataenia")[c(3,4,1,2)]))
  1217. # %% [markdown]
  1218. # # Compare to astrocyte devDARs to liftover mouse GR binding sites
  1219. # %%
  1220. # Read in GR sites (lifted over already to hg38 w/UCSC)
  1221. GR_sites <- rtracklayer::import.bed('/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_DR_NR/CR01_count_edger_report_str_FC25.col.human.bed')
  1222. # %%
  1223. # Collect ATAC peaks in each cluster
  1224. c1 <- t.clust[t.clust$cluster==1,]
  1225. c2 <- t.clust[t.clust$cluster==2,]
  1226. c3 <- t.clust[t.clust$cluster==3,]
  1227. c4 <- t.clust[t.clust$cluster==4,]
  1228. # %%
  1229. # Convert human ATAC sites to granges objects
  1230. c1_gr <- GRanges(
  1231. seqnames = do.call(rbind,strsplit(rownames(c1),'-'))[,1],
  1232. ranges = IRanges(start = as.numeric(do.call(rbind,strsplit(rownames(c1),'-'))[,2]),
  1233. end = as.numeric(do.call(rbind,strsplit(rownames(c1),'-'))[,3])))
  1234. c2_gr <- GRanges(
  1235. seqnames = do.call(rbind,strsplit(rownames(c2),'-'))[,1],
  1236. ranges = IRanges(start = as.numeric(do.call(rbind,strsplit(rownames(c2),'-'))[,2]),
  1237. end = as.numeric(do.call(rbind,strsplit(rownames(c2),'-'))[,3])))
  1238. c3_gr <- GRanges(
  1239. seqnames = do.call(rbind,strsplit(rownames(c3),'-'))[,1],
  1240. ranges = IRanges(start = as.numeric(do.call(rbind,strsplit(rownames(c3),'-'))[,2]),
  1241. end = as.numeric(do.call(rbind,strsplit(rownames(c3),'-'))[,3])))
  1242. c4_gr <- GRanges(
  1243. seqnames = do.call(rbind,strsplit(rownames(c4),'-'))[,1],
  1244. ranges = IRanges(start = as.numeric(do.call(rbind,strsplit(rownames(c4),'-'))[,2]),
  1245. end = as.numeric(do.call(rbind,strsplit(rownames(c4),'-'))[,3])))
  1246. # Generate total ATAC sites as background for Fisher's test
  1247. DefaultAssay(human_multiome_astro_v2) <- 'peaks'
  1248. total_gr <- GRanges(
  1249. seqnames = do.call(rbind,strsplit(rownames(human_multiome_astro_v2),'-'))[,1],
  1250. ranges = IRanges(start = as.numeric(do.call(rbind,strsplit(rownames(human_multiome_astro_v2),'-'))[,2]),
  1251. end = as.numeric(do.call(rbind,strsplit(rownames(human_multiome_astro_v2),'-'))[,3])))
  1252. # %%
  1253. # Compute overlap with each cluster
  1254. overlap_df <- data.frame(overlap = c(length(findOverlaps(GR_sites, c1_gr)) / length(c1_gr),
  1255. length(findOverlaps(GR_sites, c2_gr)) / length(c2_gr),
  1256. length(findOverlaps(GR_sites, c3_gr)) / length(c3_gr),
  1257. length(findOverlaps(GR_sites, c4_gr)) / length(c4_gr)),
  1258. oldcluster = c('1','2','3','4'),
  1259. newcluster = c('3','1','4','2'))
  1260. overlap_df$overlap <- overlap_df$overlap * 100
  1261. overlap_df$x <- '1'
  1262. # %%
  1263. # Calculate overlaps for Fisher test
  1264. ov1 <- rbind(data.frame(neg = length(c1_gr) - length(findOverlaps(c1_gr,GR_sites)),
  1265. pos = length(findOverlaps(c1_gr,GR_sites))),
  1266. data.frame(neg = length(total_gr[-subjectHits(findOverlaps(c1_gr,total_gr))]) - length(findOverlaps(GR_sites,total_gr[-subjectHits(findOverlaps(c1_gr,total_gr))])),
  1267. pos = length(findOverlaps(GR_sites,total_gr[-subjectHits(findOverlaps(c1_gr,total_gr))]))))
  1268. ov2 <- rbind(data.frame(neg = length(c2_gr) - length(findOverlaps(c2_gr, GR_sites)),
  1269. pos = length(findOverlaps(c2_gr,GR_sites))),
  1270. data.frame(neg = length(total_gr[-subjectHits(findOverlaps(c2_gr,total_gr))]) - length(findOverlaps(GR_sites,total_gr[-subjectHits(findOverlaps(c2_gr,total_gr))])),
  1271. pos = length(findOverlaps(GR_sites,total_gr[-subjectHits(findOverlaps(c2_gr,total_gr))]))))
  1272. ov3 <- rbind(data.frame(neg = length(c3_gr) - length(findOverlaps(c3_gr,GR_sites)),
  1273. pos = length(findOverlaps(c3_gr,GR_sites))),
  1274. data.frame(neg = length(total_gr[-subjectHits(findOverlaps(c3_gr,total_gr))]) - length(findOverlaps(GR_sites,total_gr[-subjectHits(findOverlaps(c3_gr,total_gr))])),
  1275. pos = length(findOverlaps(GR_sites,total_gr[-subjectHits(findOverlaps(c3_gr,total_gr))]))))
  1276. ov4 <- rbind(data.frame(neg = length(c4_gr) - length(findOverlaps(c4_gr,GR_sites)),
  1277. pos = length(findOverlaps(c4_gr,GR_sites))),
  1278. data.frame(neg = length(total_gr[-subjectHits(findOverlaps(c4_gr,total_gr))]) - length(findOverlaps(GR_sites,total_gr[-subjectHits(findOverlaps(c4_gr,total_gr))])),
  1279. pos = length(findOverlaps(GR_sites,total_gr[-subjectHits(findOverlaps(c4_gr,total_gr))]))))
  1280. # %%
  1281. # Add Fisher test results to object
  1282. overlap_df$pval <- c(fisher.test(ov1,alternative='less')$p.value,
  1283. fisher.test(ov2,alternative='less')$p.value,
  1284. fisher.test(ov3,alternative='less')$p.value,
  1285. fisher.test(ov4,alternative='less')$p.value)
  1286. overlap_df$logpval <- -log10(overlap_df$pval)
  1287. # %%
  1288. # Set order for plotting
  1289. overlap_df$oldcluster <- factor(overlap_df$oldcluster, levels = rev(c('3','1','4','2')))
  1290. # %%
  1291. # Print results
  1292. overlap_df
  1293. # %%
  1294. # Generate dot plot of % overlap and Fisher's test p-value
  1295. options(repr.plot.width=1.6, repr.plot.height=2.0,repr.plot.res=1200)
  1296. ggplot(overlap_df, aes(x=x, y=oldcluster, size = overlap, fill=logpval)) +
  1297. geom_point(shape=21,alpha=1,stroke=0.4) + theme_bw() + scale_radius(breaks = c(4,14)) + theme(axis.title = element_blank(),
  1298. axis.text.x = element_blank(),
  1299. panel.grid.major = element_line(color = "grey98"),
  1300. axis.text.y = element_blank(),
  1301. legend.title=element_text(hjust=0,size=10),
  1302. legend.text=element_text(size=10),
  1303. legend.margin=margin(0,5,0,0),
  1304. legend.key.height = unit(1,'mm'),
  1305. legend.key.width = unit(4,'mm'),
  1306. legend.position='right',
  1307. axis.ticks.x = element_blank()) + labs(size = "% overlap",fill='-log10\n(p-val)') +
  1308. scale_fill_viridis(option='rocket',breaks=c(2,50),labels=c('ns','50'))
  1309. # %% [markdown]
  1310. # # Generate human astrocyte UMAPs
  1311. # %%
  1312. # Read RDS file w/motif object for astrocyte-called peaks
  1313. human_multiome_astro_v2 <- readRDS('/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/250427_human_multiome_astro_v2.rds')
  1314. # %%
  1315. # Generate plots
  1316. options(repr.plot.width = 4.5*1.5, repr.plot.height = 3*1.5, repr.plot.res=500)
  1317. human_multiome_astro_v2$Group <- factor(human_multiome_astro_v2$Group,levels=
  1318. c('First_trimester','Second_trimester','Third_trimester','Infancy','Adolescence'))
  1319. p1 <- DimPlot(human_multiome_astro_v2, group.by = 'Group',shuffle=T) + theme_void() + theme(plot.title=element_blank(),
  1320. plot.margin=margin(0,10,0,0),
  1321. legend.position='none') +
  1322. scale_color_manual(values = c(colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[1],
  1323. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[8],
  1324. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[12],
  1325. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[17],
  1326. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[23]))
  1327. human_multiome_astro_v2$region_summary <- factor(human_multiome_astro_v2$region_summary,levels = c('General',
  1328. 'PFC',
  1329. 'V1'))
  1330. p2 <- DimPlot(human_multiome_astro_v2, group.by = 'region_summary',shuffle=T) + theme_void() + theme(plot.title=element_blank(),
  1331. plot.margin=margin(0,0,0,10),
  1332. legend.position='none') +
  1333. scale_color_manual(values=c('grey70',
  1334. paletteer::paletteer_d("colorBlindness::Blue2Orange8Steps")[1],
  1335. paletteer::paletteer_d("colorBlindness::Blue2Orange8Steps")[8]))
  1336. p1 + p2
  1337. # %% [markdown]
  1338. # # Generate human and mouse astrocyte RNA & track plots
  1339. # %%
  1340. # Load in dataset
  1341. human_multiome_astro_v2 <- readRDS('/n/groups/neuroduo/Bruno/Wang_2025_human_astrocyte/250427_human_multiome_astro_v2.rds')
  1342. # %%
  1343. # Aggregate RNA counts by sample
  1344. human_multiome_astro_agg <- AggregateExpression(human_multiome_astro_v2,
  1345. assays = 'RNA',
  1346. group.by = 'Ident',
  1347. return.seurat = TRUE)
  1348. # %%
  1349. # Create metadata
  1350. meta_df <- unique(data.frame([email hidden][human_multiome_astro_v2$Ident %in% human_multiome_astro_v2$Ident,'Ident'],
  1351. [email hidden][human_multiome_astro_v2$Ident %in% human_multiome_astro_v2$Ident,c('Group','region_summary')]))
  1352. metadata_df <- data.frame(Sample = meta_df[,1],
  1353. Group = meta_df[,2],
  1354. Region = meta_df[,3],
  1355. Group_region = paste0(meta_df[,2], '_', meta_df[,3]))
  1356. # %%
  1357. # Create deseq2 object
  1358. deseq_obj <- DESeqDataSetFromMatrix(countData = GetAssayData(human_multiome_astro_agg,slot='counts'),
  1359. colData = metadata_df[match(colnames(GetAssayData(human_multiome_astro_agg,slot='counts')),metadata_df$Sample),],
  1360. design = ~ Group)
  1361. # %%
  1362. # Generate boxplots
  1363. options(repr.plot.width=2.4, repr.plot.height=4,repr.plot.res=500)
  1364. goi <- 'ETNPPL'
  1365. data <- plotCounts(deseq_obj, gene = goi, intgroup = c('Group'),returnData = TRUE)
  1366. data$Group <- gsub('First_trimester', '1st Tri.',data$Group)
  1367. data$Group <- gsub('Second_trimester', '2nd Tri.',data$Group)
  1368. data$Group <- gsub('Third_trimester', '3rd Tri.',data$Group)
  1369. data$Group <- gsub('Infancy', 'Infant', data$Group)
  1370. data$Group <- gsub('Adolescence', 'Adoles.', data$Group)
  1371. data$Group <- factor(data$Group, levels = c('1st Tri.','2nd Tri.',
  1372. '3rd Tri.','Infant','Adoles.'))
  1373. ggplot(data, aes(x=Group, y=count, color=Group,fill=Group)) +
  1374. geom_boxplot(alpha=0.2,outlier.size=0)+
  1375. geom_point(size=1.5, shape=21,position = position_jitterdodge(jitter.width=1)) + theme_classic() +
  1376. theme(axis.title = element_text(size=16,color='black'),
  1377. axis.text = element_text(size=14,color='black'),
  1378. axis.text.x = element_text(angle=90,vjust=0.5,hjust=1),
  1379. legend.text = element_text(size=14,color='black'),
  1380. axis.title.y = element_text(margin = margin(0,2,0,0)),
  1381. axis.title.x = element_text(margin = margin(10,0,0,0)),
  1382. plot.margin=margin(5,22,0,1),
  1383. legend.box.margin=margin(0,0,-10,-10),
  1384. legend.position='none') + #ylim(c(0,max(data$count) * 1.1)) +
  1385. scale_color_manual(values = c(colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[1],
  1386. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[8],
  1387. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[12],
  1388. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[17],
  1389. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[23])) +
  1390. scale_fill_manual(values = c(colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[1],
  1391. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[8],
  1392. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[12],
  1393. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[17],
  1394. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[23])) +
  1395. guides(fill = "none") + labs(color="") + labs(x = 'Stage', y = paste0(goi, ' expression'))
  1396. # %%
  1397. # Generate boxplots
  1398. options(repr.plot.width=2.4, repr.plot.height=4,repr.plot.res=500)
  1399. goi <- 'GJB6'
  1400. data <- plotCounts(deseq_obj, gene = goi, intgroup = c('Group'),returnData = TRUE)
  1401. data$Group <- gsub('First_trimester', '1st Tri.',data$Group)
  1402. data$Group <- gsub('Second_trimester', '2nd Tri.',data$Group)
  1403. data$Group <- gsub('Third_trimester', '3rd Tri.',data$Group)
  1404. data$Group <- gsub('Infancy', 'Infant', data$Group)
  1405. data$Group <- gsub('Adolescence', 'Adoles.', data$Group)
  1406. data$Group <- factor(data$Group, levels = c('1st Tri.','2nd Tri.',
  1407. '3rd Tri.','Infant','Adoles.'))
  1408. ggplot(data, aes(x=Group, y=count, color=Group,fill=Group)) +
  1409. geom_boxplot(alpha=0.2,outlier.size=0)+
  1410. geom_point(size=1.5, shape=21,position = position_jitterdodge(jitter.width=1)) + theme_classic() +
  1411. theme(axis.title = element_text(size=16,color='black'),
  1412. axis.text = element_text(size=14,color='black'),
  1413. axis.text.x = element_text(angle=90,vjust=0.5,hjust=1),
  1414. legend.text = element_text(size=14,color='black'),
  1415. axis.title.y = element_text(margin = margin(0,2,0,0)),
  1416. axis.title.x = element_text(margin = margin(10,0,0,0)),
  1417. plot.margin=margin(5,22,0,1),
  1418. legend.box.margin=margin(0,0,-10,-10),
  1419. legend.position='none') + #ylim(c(0,max(data$count) * 1.1)) +
  1420. scale_color_manual(values = c(colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[1],
  1421. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[8],
  1422. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[12],
  1423. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[17],
  1424. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[23])) +
  1425. scale_fill_manual(values = c(colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[1],
  1426. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[8],
  1427. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[12],
  1428. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[17],
  1429. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[23])) +
  1430. guides(fill = "none") + labs(color="") + labs(x = 'Stage', y = paste0(goi, ' expression'))
  1431. # %%
  1432. # Generate boxplots
  1433. options(repr.plot.width=2.4, repr.plot.height=4,repr.plot.res=500)
  1434. goi <- 'HTRA1'
  1435. data <- plotCounts(deseq_obj, gene = goi, intgroup = c('Group'),returnData = TRUE)
  1436. data$Group <- gsub('First_trimester', '1st Tri.',data$Group)
  1437. data$Group <- gsub('Second_trimester', '2nd Tri.',data$Group)
  1438. data$Group <- gsub('Third_trimester', '3rd Tri.',data$Group)
  1439. data$Group <- gsub('Infancy', 'Infant', data$Group)
  1440. data$Group <- gsub('Adolescence', 'Adoles.', data$Group)
  1441. data$Group <- factor(data$Group, levels = c('1st Tri.','2nd Tri.',
  1442. '3rd Tri.','Infant','Adoles.'))
  1443. ggplot(data, aes(x=Group, y=count, color=Group,fill=Group)) +
  1444. geom_boxplot(alpha=0.2,outlier.size=0)+
  1445. geom_point(size=1.5, shape=21,position = position_jitterdodge(jitter.width=1)) + theme_classic() +
  1446. theme(axis.title = element_text(size=16,color='black'),
  1447. axis.text = element_text(size=14,color='black'),
  1448. axis.text.x = element_text(angle=90,vjust=0.5,hjust=1),
  1449. legend.text = element_text(size=14,color='black'),
  1450. axis.title.y = element_text(margin = margin(0,2,0,0)),
  1451. axis.title.x = element_text(margin = margin(10,0,0,0)),
  1452. plot.margin=margin(5,22,0,1),
  1453. legend.box.margin=margin(0,0,-10,-10),
  1454. legend.position='none') + #ylim(c(0,max(data$count) * 1.1)) +
  1455. scale_color_manual(values = c(colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[1],
  1456. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[8],
  1457. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[12],
  1458. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[17],
  1459. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[23])) +
  1460. scale_fill_manual(values = c(colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[1],
  1461. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[8],
  1462. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[12],
  1463. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[17],
  1464. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[23])) +
  1465. guides(fill = "none") + labs(color="") + labs(x = 'Stage', y = paste0(goi, ' expression'))
  1466. # %%
  1467. # Generate boxplots
  1468. options(repr.plot.width=2.4, repr.plot.height=4,repr.plot.res=500)
  1469. goi <- 'PHYHD1'
  1470. data <- plotCounts(deseq_obj, gene = goi, intgroup = c('Group'),returnData = TRUE)
  1471. data$Group <- gsub('First_trimester', '1st Tri.',data$Group)
  1472. data$Group <- gsub('Second_trimester', '2nd Tri.',data$Group)
  1473. data$Group <- gsub('Third_trimester', '3rd Tri.',data$Group)
  1474. data$Group <- gsub('Infancy', 'Infant', data$Group)
  1475. data$Group <- gsub('Adolescence', 'Adoles.', data$Group)
  1476. data$Group <- factor(data$Group, levels = c('1st Tri.','2nd Tri.',
  1477. '3rd Tri.','Infant','Adoles.'))
  1478. ggplot(data, aes(x=Group, y=count, color=Group,fill=Group)) +
  1479. geom_boxplot(alpha=0.2,outlier.size=0)+
  1480. geom_point(size=1.5, shape=21,position = position_jitterdodge(jitter.width=1)) + theme_classic() +
  1481. theme(axis.title = element_text(size=16,color='black'),
  1482. axis.text = element_text(size=14,color='black'),
  1483. axis.text.x = element_text(angle=90,vjust=0.5,hjust=1),
  1484. legend.text = element_text(size=14,color='black'),
  1485. axis.title.y = element_text(margin = margin(0,2,0,0)),
  1486. axis.title.x = element_text(margin = margin(10,0,0,0)),
  1487. plot.margin=margin(5,22,0,1),
  1488. legend.box.margin=margin(0,0,-10,-10),
  1489. legend.position='none') + #ylim(c(0,max(data$count) * 1.1)) +
  1490. scale_color_manual(values = c(colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[1],
  1491. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[8],
  1492. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[12],
  1493. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[17],
  1494. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[23])) +
  1495. scale_fill_manual(values = c(colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[1],
  1496. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[8],
  1497. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[12],
  1498. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[17],
  1499. colorRampPalette(paletteer_d("PNWColors::Sunset2"))(24)[23])) +
  1500. guides(fill = "none") + labs(color="") + labs(x = 'Stage', y = paste0(goi, ' expression'))
  1501. # %%
  1502. # Change group labels for plotting
  1503. human_multiome_astro_v2$Group_plotting <- ifelse(human_multiome_astro_v2$Group == 'First_trimester','1st Tri.',
  1504. ifelse(human_multiome_astro_v2$Group == 'Second_trimester','2nd Tri.',
  1505. ifelse(human_multiome_astro_v2$Group == 'Third_trimester','3rd Tri.',
  1506. ifelse(human_multiome_astro_v2$Group == 'Infancy','Infant','Adoles.'))))
  1507. human_multiome_astro_v2$Group_plotting <- factor(human_multiome_astro_v2$Group_plotting,
  1508. levels = c('1st Tri.',
  1509. '2nd Tri.',
  1510. '3rd Tri.',
  1511. 'Infant',
  1512. 'Adoles.'))
  1513. # %%
  1514. # Generate ETNPPL track
  1515. options(repr.plot.width = 3, repr.plot.height = 4.4, repr.plot.res = 700)
  1516. roi <- 'chr4-108739887-108745637'
  1517. min <- floor(as.numeric(str_split(roi,'-')[[1]][2]) / 100) * 100
  1518. max <- floor(as.numeric(str_split(roi,'-')[[1]][3]) / 100) * 100
  1519. goi <- 'ETNPPL'
  1520. human_multiome_astro_v2 <- LinkPeaks(human_multiome_astro_v2, peak.assay = 'peaks', expression.assay = 'RNA', genes.use = goi,
  1521. score_cutoff = 0.01)
  1522. cov_plot <- CoveragePlot(
  1523. object = human_multiome_astro_v2,
  1524. region = roi,
  1525. assay='peaks',
  1526. annotation = FALSE,
  1527. peaks = FALSE,
  1528. links =FALSE,
  1529. group.by = 'Group_plotting'
  1530. ) + theme(axis.line.y = element_blank(),
  1531. text = element_text(size=18),
  1532. axis.ticks.y = element_blank(),
  1533. axis.title.y = element_blank(),
  1534. axis.label.y = element_text(hjust=1),
  1535. plot.title = element_text(hjust=1)) +
  1536. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1537. DefaultAssay(human_multiome_astro_v2) <-'peaks'
  1538. gene_plot <- AnnotationPlot(
  1539. object = human_multiome_astro_v2,
  1540. region = roi
  1541. ) + scale_color_manual(values='black') + ylab('') +
  1542. theme(
  1543. axis.text = element_text(size=12,color='black'),
  1544. axis.title = element_text(size=14,color='black'),
  1545. axis.line.y = element_blank(),
  1546. plot.margin=margin(0,0,0,0)) +
  1547. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1548. gene_plot$layers[[4]]$aes_params$size <- 5 # Increase gene font size
  1549. peak_plot <- PeakPlot(
  1550. object = human_multiome_astro_v2,
  1551. region = roi
  1552. ) + theme(axis.text.x = element_text(color = 'black', size = 7),
  1553. axis.line.y = element_blank())
  1554. df <- as.data.frame(Links(human_multiome_astro_v2))
  1555. poi <- paste0(peak_plot$data$seqnames,'-',
  1556. peak_plot$data$start,'-',
  1557. peak_plot$data$end)
  1558. peak_plot$data$PCC <- df[df$peak %in% poi,'score']
  1559. peak_plot <- peak_plot + aes(color = peak_plot$data$PCC) +
  1560. theme(legend.position='left',
  1561. axis.line.y = element_blank(),
  1562. legend.text=element_text(size=12),
  1563. legend.title=element_text(size=14,margin=margin(0,0,8,0)),
  1564. legend.key.height = unit(0.1, "cm"),
  1565. legend.margin = margin(20,-110,0,0),
  1566. legend.background = element_rect(fill = "transparent", color = NA),
  1567. legend.box.background = element_rect(fill = "transparent", color = NA),
  1568. legend.key.width = unit(0.2, "cm"),
  1569. plot.margin=margin(0,0,0,0)) + labs(color = "PCC") + ylab('') +
  1570. scale_color_gradientn(colors = brewer.pal(1000, 'Reds'),
  1571. limits=c(0,ceiling(max(peak_plot$data$PCC)*100)/100 ),
  1572. breaks = seq(0, ceiling(max(peak_plot$data$PCC)*100)/100,
  1573. by = ceiling((max(peak_plot$data$PCC))*100)/100)) +
  1574. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1575. CombineTracks(
  1576. plotlist = list(cov_plot, peak_plot,gene_plot),
  1577. heights = c(16, 0.5,3),
  1578. widths = c(10, 2)) &
  1579. scale_fill_manual(values = paletteer_d("PNWColors::Sunset2")) & theme(plot.margin = margin(0,15,0,0))
  1580. # %%
  1581. # Generate GJB6 track for supplement
  1582. options(repr.plot.width = 3, repr.plot.height = 4.4, repr.plot.res = 700)
  1583. roi <- regionize('chr13:20228936-20233410')
  1584. min <- floor(as.numeric(str_split(roi,'-')[[1]][2]) / 100) * 100
  1585. max <- floor(as.numeric(str_split(roi,'-')[[1]][3]) / 100) * 100
  1586. goi <- 'GJB6'
  1587. human_multiome_astro_v2 <- LinkPeaks(human_multiome_astro_v2, peak.assay = 'peaks', expression.assay = 'RNA', genes.use = goi,
  1588. score_cutoff = 0.01)
  1589. cov_plot <- CoveragePlot(
  1590. object = human_multiome_astro_v2,
  1591. region = roi,
  1592. assay='peaks',
  1593. annotation = FALSE,
  1594. peaks = FALSE,
  1595. links =FALSE,
  1596. group.by = 'Group_plotting'
  1597. ) + theme(axis.line.y = element_blank(),
  1598. text = element_text(size=18),
  1599. axis.ticks.y = element_blank(),
  1600. axis.title.y = element_blank(),
  1601. axis.label.y = element_text(hjust=1),
  1602. plot.title = element_text(hjust=1)) +
  1603. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1604. DefaultAssay(human_multiome_astro_v2) <-'peaks'
  1605. gene_plot <- AnnotationPlot(
  1606. object = human_multiome_astro_v2,
  1607. region = roi
  1608. ) + scale_color_manual(values='black') + ylab('') +
  1609. theme(
  1610. axis.text = element_text(size=12,color='black'),
  1611. axis.title = element_text(size=14,color='black'),
  1612. axis.line.y = element_blank(),
  1613. plot.margin=margin(0,0,0,0)) +
  1614. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1615. gene_plot$layers[[4]]$aes_params$size <- 5 # Increase gene font size
  1616. peak_plot <- PeakPlot(
  1617. object = human_multiome_astro_v2,
  1618. region = roi
  1619. ) + theme(axis.text.x = element_text(color = 'black', size = 7),
  1620. axis.line.y = element_blank())
  1621. df <- as.data.frame(Links(human_multiome_astro_v2))
  1622. poi <- paste0(peak_plot$data$seqnames,'-',
  1623. peak_plot$data$start,'-',
  1624. peak_plot$data$end)
  1625. peak_plot$data$PCC <- df[df$peak %in% poi,'score']
  1626. peak_plot <- peak_plot + aes(color = peak_plot$data$PCC) +
  1627. theme(legend.position='left',
  1628. axis.line.y = element_blank(),
  1629. legend.text=element_text(size=12),
  1630. legend.title=element_text(size=14,margin=margin(0,0,8,0)),
  1631. legend.key.height = unit(0.1, "cm"),
  1632. legend.margin = margin(20,-110,0,0),
  1633. legend.background = element_rect(fill = "transparent", color = NA),
  1634. legend.box.background = element_rect(fill = "transparent", color = NA),
  1635. legend.key.width = unit(0.2, "cm"),
  1636. plot.margin=margin(0,0,0,0)) + labs(color = "PCC") +ylab('') +
  1637. scale_color_gradientn(colors = brewer.pal(1000, 'Reds'),
  1638. limits=c(0,ceiling(max(peak_plot$data$PCC)*100)/100 ),
  1639. breaks = seq(0, ceiling(max(peak_plot$data$PCC)*100)/100,
  1640. by = ceiling((max(peak_plot$data$PCC))*100)/100)) +
  1641. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1642. CombineTracks(
  1643. plotlist = list(cov_plot, peak_plot,gene_plot),
  1644. heights = c(16, 0.5,3),
  1645. widths = c(10, 2)) &
  1646. scale_fill_manual(values = paletteer_d("PNWColors::Sunset2")) & theme(plot.margin = margin(0,15,0,0))
  1647. # %%
  1648. # Generate GJB6 track for supplement
  1649. options(repr.plot.width = 3, repr.plot.height = 4.4, repr.plot.res = 700)
  1650. roi <- regionize('chr9:128917629-128922835')
  1651. min <- floor(as.numeric(str_split(roi,'-')[[1]][2]) / 100) * 100
  1652. max <- floor(as.numeric(str_split(roi,'-')[[1]][3]) / 100) * 100
  1653. goi <- 'LRRC8A'
  1654. human_multiome_astro_v2 <- LinkPeaks(human_multiome_astro_v2, peak.assay = 'peaks', expression.assay = 'RNA', genes.use = goi,
  1655. score_cutoff = 0,pvalue_cutoff = 1)
  1656. # Collect peaks for plotting
  1657. roi_gr <- GRanges(seqnames = str_split(roi,'-')[[1]][1],
  1658. IRanges(start = as.numeric(str_split(roi,'-')[[1]][2]),
  1659. end = as.numeric(str_split(roi,'-')[[1]][3])))
  1660. links_gr <- GRanges(seqnames = do.call(rbind,str_split(Links(human_multiome_astro_v2)$peak,'-'))[,1],
  1661. IRanges(start = as.numeric(do.call(rbind,str_split(Links(human_multiome_astro_v2)$peak,'-'))[,2]),
  1662. end = as.numeric(do.call(rbind,str_split(Links(human_multiome_astro_v2)$peak,'-'))[,3])))
  1663. cov_plot <- CoveragePlot(
  1664. object = human_multiome_astro_v2,
  1665. region = roi,
  1666. assay='peaks',
  1667. annotation = FALSE,
  1668. peaks = FALSE,
  1669. links =FALSE,
  1670. group.by = 'Group_plotting'
  1671. ) + theme(axis.line.y = element_blank(),
  1672. text = element_text(size=18),
  1673. axis.ticks.y = element_blank(),
  1674. axis.title.y = element_blank(),
  1675. axis.label.y = element_text(hjust=1),
  1676. plot.title = element_text(hjust=1)) +
  1677. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1678. DefaultAssay(human_multiome_astro_v2) <-'peaks'
  1679. gene_plot <- AnnotationPlot(
  1680. object = human_multiome_astro_v2,
  1681. region = roi
  1682. ) + scale_color_manual(values='black') + ylab('') +
  1683. theme(
  1684. axis.text = element_text(size=12,color='black'),
  1685. axis.title = element_text(size=14,color='black'),
  1686. axis.line.y = element_blank(),
  1687. plot.margin=margin(0,0,0,0)) +
  1688. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1689. gene_plot$layers[[4]]$aes_params$size <- 4 # Increase gene font size
  1690. peak_plot <- PeakPlot(
  1691. object = human_multiome_astro_v2,
  1692. region = roi
  1693. ) + theme(axis.text.x = element_text(color = 'black', size = 7),
  1694. axis.line.y = element_blank())
  1695. df <- as.data.frame(Links(human_multiome_astro_v2))
  1696. poi <- paste0(peak_plot$data$seqnames,'-',
  1697. peak_plot$data$start,'-',
  1698. peak_plot$data$end)
  1699. peak_plot$data$PCC <- df[queryHits(findOverlaps(links_gr, roi_gr)),'score']
  1700. peak_plot <- peak_plot + aes(color = peak_plot$data$PCC) +
  1701. theme(legend.position='left',
  1702. axis.line.y = element_blank(),
  1703. legend.text=element_text(size=12),
  1704. legend.title=element_text(size=14,margin=margin(0,0,8,0)),
  1705. legend.key.height = unit(0.1, "cm"),
  1706. legend.margin = margin(20,-110,0,0),
  1707. legend.background = element_rect(fill = "transparent", color = NA),
  1708. legend.box.background = element_rect(fill = "transparent", color = NA),
  1709. legend.key.width = unit(0.2, "cm"),
  1710. plot.margin=margin(0,0,0,0)) + labs(color = "PCC") +ylab('') +
  1711. scale_color_gradientn(colors = brewer.pal(1000, 'Reds'),
  1712. limits=c(floor(min(peak_plot$data$PCC)*100)/100,ceiling(max(peak_plot$data$PCC)*100)/100 ),
  1713. breaks = seq(floor(min(peak_plot$data$PCC)*100)/100, ceiling(max(peak_plot$data$PCC)*100)/100,
  1714. by = ceiling(max(peak_plot$data$PCC)*100)/100 - floor(min(peak_plot$data$PCC)*100)/100)) +
  1715. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1716. CombineTracks(
  1717. plotlist = list(cov_plot, peak_plot,gene_plot),
  1718. heights = c(16, 0.5,3),
  1719. widths = c(10, 2)) &
  1720. scale_fill_manual(values = paletteer_d("PNWColors::Sunset2")) & theme(plot.margin = margin(0,15,0,0))
  1721. # %%
  1722. # Generate CSRP1 track
  1723. options(repr.plot.width = 3, repr.plot.height = 4.4, repr.plot.res = 700)
  1724. roi <- regionize('chr1:201498321-201503221')
  1725. min <- floor(as.numeric(str_split(roi,'-')[[1]][2]) / 100) * 100
  1726. max <- floor(as.numeric(str_split(roi,'-')[[1]][3]) / 100) * 100
  1727. goi <- 'CSRP1'
  1728. human_multiome_astro_v2 <- LinkPeaks(human_multiome_astro_v2, peak.assay = 'peaks', expression.assay = 'RNA', genes.use = goi,
  1729. score_cutoff = 0,pvalue_cutoff = 1)
  1730. cov_plot <- CoveragePlot(
  1731. object = human_multiome_astro_v2,
  1732. region = roi,
  1733. assay='peaks',
  1734. annotation = FALSE,
  1735. peaks = FALSE,
  1736. links =FALSE,
  1737. group.by = 'Group_plotting'
  1738. ) + theme(axis.line.y = element_blank(),
  1739. text = element_text(size=18),
  1740. axis.ticks.y = element_blank(),
  1741. #axis.title.y = element_blank(),
  1742. axis.label.y = element_text(hjust=1),
  1743. plot.title = element_text(hjust=1)) +
  1744. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1745. DefaultAssay(human_multiome_astro_v2) <-'peaks'
  1746. gene_plot <- AnnotationPlot(
  1747. object = human_multiome_astro_v2,
  1748. region = roi
  1749. ) + scale_color_manual(values='black') + ylab('') +
  1750. theme(
  1751. axis.text = element_text(size=12,color='black'),
  1752. axis.title = element_text(size=14,color='black'),
  1753. axis.line.y = element_blank(),
  1754. plot.margin=margin(0,0,0,0)) +
  1755. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1756. gene_plot$layers[[4]]$aes_params$size <- 5 # Increase gene font size
  1757. peak_plot <- PeakPlot(
  1758. object = human_multiome_astro_v2,
  1759. region = roi
  1760. ) + theme(axis.text.x = element_text(color = 'black', size = 7),
  1761. axis.line.y = element_blank())
  1762. df <- as.data.frame(Links(human_multiome_astro_v2))
  1763. poi <- paste0(peak_plot$data$seqnames,'-',
  1764. peak_plot$data$start,'-',
  1765. peak_plot$data$end)
  1766. peak_plot$data$PCC <- df[df$peak %in% poi,'score']
  1767. peak_plot <- peak_plot + aes(color = peak_plot$data$PCC) +
  1768. theme(legend.position='left',
  1769. axis.line.y = element_blank(),
  1770. legend.text=element_text(size=12),
  1771. legend.title=element_text(size=14,margin=margin(0,0,8,0)),
  1772. legend.key.height = unit(0.1, "cm"),
  1773. legend.margin = margin(20,-110,0,0),
  1774. legend.background = element_rect(fill = "transparent", color = NA),
  1775. legend.box.background = element_rect(fill = "transparent", color = NA),
  1776. legend.key.width = unit(0.2, "cm"),
  1777. plot.margin=margin(0,0,0,0)) + labs(color = "PCC") +ylab('') +
  1778. scale_color_gradientn(colors = brewer.pal(1000, 'Reds'),
  1779. limits=c(floor(min(peak_plot$data$PCC)*100)/100,ceiling(max(peak_plot$data$PCC)*100)/100 ),
  1780. breaks = seq(floor(min(peak_plot$data$PCC)*100)/100, ceiling(max(peak_plot$data$PCC)*100)/100,
  1781. by = ceiling(max(peak_plot$data$PCC)*100)/100 - floor(min(peak_plot$data$PCC)*100)/100)) +
  1782. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1783. CombineTracks(
  1784. plotlist = list(cov_plot, peak_plot,gene_plot),
  1785. heights = c(16, 0.5,3),
  1786. widths = c(10, 2)) &
  1787. scale_fill_manual(values = paletteer_d("PNWColors::Sunset2")) & theme(plot.margin = margin(0,15,0,0))
  1788. # %%
  1789. # Load in mouse multiome data
  1790. final_obj_motif_chromVAR <- readRDS('/n/groups/neuroduo/Bruno/RDS_files/230810_final_obj_motif_chromVAR.rds')
  1791. # %%
  1792. # Generate mouse Etnppl track
  1793. options(repr.plot.width = 2.7, repr.plot.height = 4.4, repr.plot.res = 500)
  1794. roi <- 'chr3-130632373-130635599'
  1795. min <- floor(as.numeric(str_split(roi,'-')[[1]][2]) / 100) * 100
  1796. max <- floor(as.numeric(str_split(roi,'-')[[1]][3]) / 100) * 100
  1797. cov_plot <- BigwigTrack(
  1798. bigwig = list('DR\nGR' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_DR_NR/Astro_DR_GR_merge.bw',
  1799. 'NR\nGR' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_DR_NR/Astro_NR_GR_merge.bw',
  1800. 'GR\nCon' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_cre_delta/delCre_pos_GR_merge.bw',
  1801. 'GR\nKO' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_cre_delta/Cre_pos_GR_merge.bw',
  1802. 'ATAC\nGR-Con' = '/n/groups/neuroduo/Bruno/Astro_GR_KO_ATAC/BAMs/ATAC_deltaCre_GR.merge.bw',
  1803. 'ATAC\nGR-KO' = '/n/groups/neuroduo/Bruno/Astro_GR_KO_ATAC/BAMs/ATAC_Cre_GR.merge.bw'),
  1804. region = roi,
  1805. smooth=5) + theme(legend.position='none',
  1806. axis.title.y=element_blank(),
  1807. axis.ticks.y=element_blank(),
  1808. axis.text.y=element_blank(),
  1809. text = element_text(size=18),
  1810. axis.label.y = element_text(hjust=1),
  1811. axis.line.y = element_blank(),
  1812. plot.title = element_text(hjust=1)) +
  1813. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) )) +
  1814. scale_fill_manual(values = c("#675478","#D49E78",
  1815. rep(c('#EBAE00','#019CB5'),2)))
  1816. gene_plot <- AnnotationPlot(
  1817. object = final_obj_motif_chromVAR,
  1818. region = roi
  1819. ) + scale_color_manual(values='black') + ylab('') +
  1820. theme(
  1821. axis.text = element_text(size=12,color='black'),
  1822. axis.title = element_text(size=14,color='black'),
  1823. axis.line.y = element_blank(),
  1824. plot.margin=margin(0,0,0,0)) +
  1825. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1826. gene_plot$layers[[4]]$aes_params$size <- 5 # Increase gene font size
  1827. CombineTracks(
  1828. plotlist = list(cov_plot,gene_plot),
  1829. heights = c(16, 3)) & theme(plot.margin = margin(0,15,0,0))
  1830. # %%
  1831. # Generate mouse Gjb6 track
  1832. options(repr.plot.width = 2.7, repr.plot.height = 4.4, repr.plot.res = 900)
  1833. roi <- regionize('chr14:57130226-57134463')
  1834. min <- floor(as.numeric(str_split(roi,'-')[[1]][2]) / 100) * 100
  1835. max <- floor(as.numeric(str_split(roi,'-')[[1]][3]) / 100) * 100
  1836. cov_plot <- BigwigTrack(
  1837. bigwig = list('DR\nGR' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_DR_NR/Astro_DR_GR_merge.bw',
  1838. 'NR\nGR' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_DR_NR/Astro_NR_GR_merge.bw',
  1839. 'GR\nCon' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_cre_delta/delCre_pos_GR_merge.bw',
  1840. 'GR\nKO' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_cre_delta/Cre_pos_GR_merge.bw',
  1841. 'ATAC\nGR-Con' = '/n/groups/neuroduo/Bruno/Astro_GR_KO_ATAC/BAMs/ATAC_deltaCre_GR.merge.bw',
  1842. 'ATAC\nGR-KO' = '/n/groups/neuroduo/Bruno/Astro_GR_KO_ATAC/BAMs/ATAC_Cre_GR.merge.bw'),
  1843. region = roi,
  1844. smooth=10) + theme(legend.position='none',
  1845. axis.title.y=element_blank(),
  1846. axis.ticks.y=element_blank(),
  1847. axis.text.y=element_blank(),
  1848. text = element_text(size=18),
  1849. axis.label.y = element_text(hjust=1),
  1850. axis.line.y = element_blank(),
  1851. plot.title = element_text(hjust=1)) +
  1852. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) )) +
  1853. scale_fill_manual(values = c("#675478","#D49E78",
  1854. rep(c('#EBAE00','#019CB5'),2)))
  1855. gene_plot <- AnnotationPlot(
  1856. object = final_obj_motif_chromVAR,
  1857. region = roi
  1858. ) + scale_color_manual(values='black') + ylab('') +
  1859. theme(
  1860. axis.text = element_text(size=12,color='black'),
  1861. axis.title = element_text(size=14,color='black'),
  1862. axis.line.y = element_blank(),
  1863. plot.margin=margin(0,0,0,0)) +
  1864. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1865. gene_plot$layers[[4]]$aes_params$size <- 5 # Increase gene font size
  1866. CombineTracks(
  1867. plotlist = list(cov_plot,gene_plot),
  1868. heights = c(16, 3)) & theme(plot.margin = margin(0,15,0,0))
  1869. # %%
  1870. # Generate mouse Csrp1 track
  1871. options(repr.plot.width = 2.7, repr.plot.height = 4.4, repr.plot.res = 900)
  1872. roi <- regionize('chr1:135732451-135737114')
  1873. min <- floor(as.numeric(str_split(roi,'-')[[1]][2]) / 100) * 100
  1874. max <- floor(as.numeric(str_split(roi,'-')[[1]][3]) / 100) * 100
  1875. cov_plot <- BigwigTrack(
  1876. bigwig = list('DR\nGR' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_DR_NR/Astro_DR_GR_merge.bw',
  1877. 'NR\nGR' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_DR_NR/Astro_NR_GR_merge.bw',
  1878. 'GR\nCon' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_cre_delta/delCre_pos_GR_merge.bw',
  1879. 'GR\nKO' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_cre_delta/Cre_pos_GR_merge.bw',
  1880. 'ATAC\nGR-Con' = '/n/groups/neuroduo/Bruno/Astro_GR_KO_ATAC/BAMs/ATAC_deltaCre_GR.merge.bw',
  1881. 'ATAC\nGR-KO' = '/n/groups/neuroduo/Bruno/Astro_GR_KO_ATAC/BAMs/ATAC_Cre_GR.merge.bw'),
  1882. region = roi,
  1883. smooth=10) + theme(legend.position='none',
  1884. axis.title.y=element_blank(),
  1885. axis.ticks.y=element_blank(),
  1886. axis.text.y=element_blank(),
  1887. text = element_text(size=18),
  1888. axis.label.y = element_text(hjust=1),
  1889. axis.line.y = element_blank(),
  1890. plot.title = element_text(hjust=1)) +
  1891. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) )) +
  1892. scale_fill_manual(values = c("#675478","#D49E78",
  1893. rep(c('#EBAE00','#019CB5'),2)))
  1894. gene_plot <- AnnotationPlot(
  1895. object = final_obj_motif_chromVAR,
  1896. region = roi
  1897. ) + scale_color_manual(values='black') + ylab('') +
  1898. theme(
  1899. axis.text = element_text(size=12,color='black'),
  1900. axis.title = element_text(size=14,color='black'),
  1901. axis.line.y = element_blank(),
  1902. plot.margin=margin(0,0,0,0)) +
  1903. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1904. gene_plot$layers[[4]]$aes_params$size <- 5 # Increase gene font size
  1905. CombineTracks(
  1906. plotlist = list(cov_plot,gene_plot),
  1907. heights = c(16, 3)) & theme(plot.margin = margin(0,15,0,0))
  1908. # %%
  1909. # Generate mouse Lrrc8a/Phyhd1 tracks
  1910. options(repr.plot.width = 2.7, repr.plot.height = 4.4, repr.plot.res = 900)
  1911. roi <- regionize('chr2:30,263,378-30,268,744')
  1912. min <- floor(as.numeric(str_split(roi,'-')[[1]][2]) / 100) * 100
  1913. max <- floor(as.numeric(str_split(roi,'-')[[1]][3]) / 100) * 100
  1914. cov_plot <- BigwigTrack(
  1915. bigwig = list('DR\nGR' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_DR_NR/Astro_DR_GR_merge.bw',
  1916. 'NR\nGR' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_DR_NR/Astro_NR_GR_merge.bw',
  1917. 'GR\nCon' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_cre_delta/delCre_pos_GR_merge.bw',
  1918. 'GR\nKO' = '/n/groups/neuroduo/Bruno/Cell_type_GR_CnR_v2/Astro_cre_delta/Cre_pos_GR_merge.bw',
  1919. 'ATAC\nGR-Con' = '/n/groups/neuroduo/Bruno/Astro_GR_KO_ATAC/BAMs/ATAC_deltaCre_GR.merge.bw',
  1920. 'ATAC\nGR-KO' = '/n/groups/neuroduo/Bruno/Astro_GR_KO_ATAC/BAMs/ATAC_Cre_GR.merge.bw'),
  1921. region = roi,
  1922. smooth=2) + theme(legend.position='none',
  1923. axis.title.y=element_blank(),
  1924. axis.ticks.y=element_blank(),
  1925. axis.text.y=element_blank(),
  1926. text = element_text(size=18),
  1927. axis.label.y = element_text(hjust=1),
  1928. axis.line.y = element_blank(),
  1929. plot.title = element_text(hjust=1)) +
  1930. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) )) +
  1931. scale_fill_manual(values = c("#675478","#D49E78",
  1932. rep(c('#EBAE00','#019CB5'),2)))
  1933. Annotation(final_obj_motif_chromVAR)[Annotation(final_obj_motif_chromVAR)$gene_name == 'Gm28035'] <- NULL
  1934. gene_plot <- AnnotationPlot(
  1935. object = final_obj_motif_chromVAR,
  1936. region = roi
  1937. ) + scale_color_manual(values='black') + ylab('') +
  1938. theme(
  1939. axis.text = element_text(size=12,color='black'),
  1940. axis.title = element_text(size=14,color='black'),
  1941. axis.line.y = element_blank(),
  1942. plot.margin=margin(0,0,0,0)) +
  1943. scale_x_continuous(limits = c(min,max), breaks = seq(min, max, by = (max - min) ))
  1944. gene_plot$layers[[4]]$aes_params$size <- 4.1 # Increase gene font size
  1945. CombineTracks(
  1946. plotlist = list(cov_plot,gene_plot),
  1947. heights = c(16, 3)) & theme(plot.margin = margin(0,15,0,0))

Human_brain_development_multiome_analysis-final.ipynb at commit 2536cae, no license · at the source

Overview

Authors: Bruno Gegenhuber1, Takuma Sonoda1,2, Lisa Traunmüller1, Christopher P. Davis1, Shon A. Koren1, Eric C. Griffith1, Chinfei Chen1,2, Michael E. Greenberg1
  1. Department of Neurobiology, Harvard Medical School,Boston, MA USA
  2. Department of Neurology, F. M. Kirby Neurobiology Center, Boston Children’s Hospital,Boston, MA USA
Institutions: Harvard University (United States); Boston Children's Hospital (United States)
Journal: Nature, volume 655, issue 8125, pages 1233-1241
Dates: received 9 June 2025; accepted 8 April 2026; published online 20 May 2026; in print 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1038/s41586-026-10512-9 · PMID 42162428 · PMCID PMC13421323 · OpenAlex W7161786132
Open access: hybrid, a free copy (OpenAlex)
Status: code verified
Categories: human (organism), mouse (organism), cellular / molecular (subfield)
Methods: Statistics, Smoothing, state filtering, decompositions, Evoked potentials, Connectivity, fMRI & imaging, Single-unit activity, calcium imaging
Keywords: Molecular neuroscience, Astrocyte, Glial development, Epigenetics and plasticity, Visual system
MeSH: Astrocytes*, Neuronal Plasticity*, Receptors, Glucocorticoid*, Signal Transduction*, Animals, Chromatin, Female, Gene Expression Regulation, Developmental, Glucocorticoids, Humans, Male, Mice, Visual Cortex (* major topic)
Topic: Neurogenesis and neuroplasticity mechanisms (Developmental Neuroscience, Neuroscience), according to OpenAlex
Funding: NINDS NIH HHS (F32 NS134623, T32 NS007473, R35 NS143029, F32 NS112455)
Citations: cited by 2 papers (Europe PMC); 97 references in the paper

Abstract

Sensory experience refines neural circuits during critical periods of postnatal development1–3. Although neuronal activity is known to orchestrate the circuit wiring that underlies this process4,5, the environmental cues that restrain developmental plasticity as animals mature are less clear. Here we examine the experience-dependent maturation of the mouse primary visual cortex across postnatal development using paired single-cell transcriptomic and chromatin accessibility sequencing. In addition to identifying the activity-dependent gene programs that emerge within each cortical cell type, we find that light exposure drives astrocyte maturation through cell-type-specific recruitment of the glucocorticoid receptor (encoded by Nr3c1) to chromatin. Astrocyte glucocorticoid receptor signalling activates an extensive gene regulatory program that is partially conserved in human brain development and promotes maturation processes that may regulate critical period closure. Collectively, these findings reveal that astrocyte glucocorticoid receptor signalling restricts neuronal plasticity. Glucocorticoid regulation of astrocyte maturation may also contribute to the effects of early-life stress across the brain, and the disruption of this process may increase susceptibility to neuropsychiatric disease.

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

Repositories

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

masai1116/SHARE-seq-alignmentV2

License: GPL-3.0
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Commit: 68f80379f4bf64eff9b4f1962b864a9330456a34, 20 April 2023
Languages: R (6), Python (4), Shell (1)
Size: 55 files, 11 scripts
Software Heritage: not archived
Found in: the text, “SHARE-seq data processing and analysis”
Holds: README, license file
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Biopython (2 files), NumPy (2 files), tidyverse (2 files), BEDTools (1 file), data.table (1 file), Matplotlib (1 file), pandas (1 file), pysam (1 file), reshape2 (1 file), SAMtools (1 file), SciPy (1 file), STAR (1 file), Subread (featureCounts) (1 file)
Availability: 1 check, the latest on 28 September 2026: the link answers
  • 28 September 2026: the link answers
13 files

broadinstitute.github.io/picard

License: none: the authors keep all their rights
State: the link answers, verified on 27 September 2026
Evidence: the link answers
Software Heritage: not checked
Found in: the text, “CUT&RUN data processing and analysis”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
  • 27 September 2026: the link answers (HTTP 200)

brunogegenhuber/GR_gene_reg

License: none: the authors keep all their rights
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Commit: 2536caed625a91bb02fb1a630bd5107543286489, 20 March 2026
Languages: Jupyter (8)
Size: 9 files, 8 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, 8 notebooks
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: DESeq2 (6 files), ggplot2 (6 files), edgeR (5 files), tidyverse (5 files), cowplot (4 files), reshape2 (4 files), circlize (3 files), clusterProfiler (3 files), ComplexHeatmap (3 files), Seurat (3 files), data.table (2 files), ggpubr (2 files), pheatmap (2 files)
Availability: 1 check, the latest on 28 September 2026: the link answers
  • 28 September 2026: the link answers
6 files

Code availability

Custom scripts can be found at https://github.com/brunogegenhuber/GR_gene_reg.

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

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:

  • 3 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 17 scripts, each with its path and the digest of its content;
  • 13 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

Datasets cited

Data availability

All sequencing data generated in this study have been deposited in GEO (GSE306265 (https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE306265)). MERFISH data are available at 10.6084/m9.figshare.29971903 (ref. 95). The following publicly available datasets were also analysed: mouse kidney GR ChIP–seq (GSE115368 (https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE115368)), mouse liver GR ChIP–seq (GSE72087 (https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE72087)), mouse primary brown preadipocyte GR ChIP–seq (GSE76619 (https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE76619)), mouse embryonic fibroblast GR ChIP–seq (GSE69947 (https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE69947)), mouse mammary gland GR ChIP–seq (GSE74826 (https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE74826)), mouse primary bone marrow-derived macrophage GR ChIP–seq (GSE99887 (https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE99887)), human brain development single-nucleus multiome-seq (10.5061/dryad.2280gb612 (ref. 96)), and mouse astrocyte development snRNA-seq (https://singlecell.broadinstitute.org/single_cell/study/SCP2719/a-multi-region-transcriptomic-atlas-of-developmental-cell-type-diversity-in-mouse-brain). The following publicly available databases were used for data processing: NCBI mm10 genome and RefSeq gene annotation (https://www.ncbi.nlm.nih.gov/datasets/genome/GCF_000001635.20), NCBI hg38 genome and RefSeq gene annotation (https://www.ncbi.nlm.nih.gov/datasets/genome/GCF_000001405.26), and UCSC mm10 refGene annotation (http://hgdownload.soe.ucsc.edu/goldenPath/mm10/bigZips/genes). Source data are provided with this paper.

Reproduced under the paper's license (CC BY), 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 2, 28 September 2026

  • Publisher: n/a → Nature Portfolio

Version 1, 28 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 8 authors, 5 keywords, 13 MeSH terms, 1 funder, 96 references.

Cite

This paper

Gegenhuber, B., Sonoda, T., Traunmüller, L., Davis, C. P., Koren, S. A., Griffith, E. C., Chen, C., & Greenberg, M. E. (2026). Astrocyte glucocorticoid receptor signalling restricts neuronal plasticity. Nature, 655(8125), 1233-1241. https://doi.org/10.1038/s41586-026-10512-9

BibTeX

@article{gegenhuber2026astrocyte,
author = {Gegenhuber, Bruno and Sonoda, Takuma and Traunmüller, Lisa and Davis, Christopher P. and Koren, Shon A. and Griffith, Eric C. and Chen, Chinfei and Greenberg, Michael E.},
title = {{Astrocyte glucocorticoid receptor signalling restricts neuronal plasticity}},
journal = {Nature},
year = {2026},
month = may,
volume = {655},
number = {8125},
pages = {1233--1241},
publisher = {Nature Portfolio},
issn = {0028-0836},
doi = {10.1038/s41586-026-10512-9},
url = {https://doi.org/10.1038/s41586-026-10512-9},
pmid = {42162428},
pmcid = {PMC13421323}
}

RIS

TY - JOUR
AU - Gegenhuber, Bruno
AU - Sonoda, Takuma
AU - Traunmüller, Lisa
AU - Davis, Christopher P.
AU - Koren, Shon A.
AU - Griffith, Eric C.
AU - Chen, Chinfei
AU - Greenberg, Michael E.
TI - Astrocyte glucocorticoid receptor signalling restricts neuronal plasticity
T2 - Nature
J2 - Nature
PY - 2026
DA - 2026/05/20
VL - 655
IS - 8125
SP - 1233
EP - 1241
SN - 0028-0836
PB - Nature Portfolio
DO - 10.1038/s41586-026-10512-9
UR - https://doi.org/10.1038/s41586-026-10512-9
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41586-026-10512-9",
"type": "article-journal",
"title": "Astrocyte glucocorticoid receptor signalling restricts neuronal plasticity",
"container-title": "Nature",
"author": [
{
"family": "Gegenhuber",
"given": "Bruno"
},
{
"family": "Sonoda",
"given": "Takuma"
},
{
"family": "Traunmüller",
"given": "Lisa"
},
{
"family": "Davis",
"given": "Christopher P."
},
{
"family": "Koren",
"given": "Shon A."
},
{
"family": "Griffith",
"given": "Eric C."
},
{
"family": "Chen",
"given": "Chinfei"
},
{
"family": "Greenberg",
"given": "Michael E."
}
],
"container-title-short": "Nature",
"volume": "655",
"issue": "8125",
"page": "1233-1241",
"DOI": "10.1038/s41586-026-10512-9",
"PMID": "42162428",
"PMCID": "PMC13421323",
"ISSN": "0028-0836",
"publisher": "Nature Portfolio",
"URL": "https://doi.org/10.1038/s41586-026-10512-9",
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
20
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1016/j.celrep.2026.117073 [code]
Single-cell epigenomics uncovers heterochromatin instability and transcription factor dysfunction during mouse brain aging.
Journal: Cell reports
In common: Subread (featureCounts), pysam, BEDTools, 16 other tools, mouse, cellular / molecular, 6 references
[2] doi:10.21203/rs.3.rs-9927928/v1 [code]
Genome-wide and allele-resolved maps of the radial architecture of the mouse genome
Journal: Research Square (preprint)
In common: Subread (featureCounts), STAR, pysam, 15 other tools, mouse, 6 references
[3] doi:10.1126/sciadv.aed2952 [code]
Activation of transposable elements is linked to a region- and cell type-specific interferon response in Parkinson's disease.
Journal: Science advances
In common: Subread (featureCounts), STAR, pysam, 16 other tools, cellular / molecular, 3 references
[4] doi:10.1016/j.xcrm.2026.102766 [code]
A longitudinal single-cell and spatial multiomic atlas of pediatric high-grade glioma.
Journal: Cell reports. Medicine
In common: pysam, edgeR, circlize, 15 other tools, cellular / molecular, 6 references
[5] doi:10.7554/elife.107393 [code]
Chromosome-scale genome assembly of the European common cuttlefish &lt;i&gt;Sepia officinalis&lt;/i&gt;.
Journal: eLife
In common: Subread (featureCounts), STAR, pysam, 15 other tools, cellular / molecular, 4 references
[6] doi:10.1186/s13059-026-04177-w [code]
Genomic sequence evolution underlying human neocortical interareal diversification.
Journal: Genome biology
In common: pysam, BEDTools, SAMtools, 13 other tools, mouse, cellular / molecular, 7 references
[7] doi:10.1038/s41467-026-69944-6 [code]
Multi-modal dissection of cell-type specific TDP-43 pathology in the motor cortex.
Journal: Nature communications
In common: pysam, BEDTools, SAMtools, 15 other tools, 5 references
[8] 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: Subread (featureCounts), STAR, SAMtools, 16 other tools, 3 references
[9] doi:10.1038/s41467-026-71803-3 [code]
Charting the transition from in vitro gliogenesis to the in vivo maturation of human glial progenitor cells transplanted into the hypomyelinated mouse brain.
Journal: Nature communications
In common: BEDTools, SAMtools, DESeq2, 11 other tools, mouse, cellular / molecular, 9 references
[10] 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: STAR, pysam, Biopython, 16 other tools, 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.