OSCR

Modelling synaptic dysfunction in childhood dementia using human iPSC-derived cortical networks.

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 › Electrophysiological feature analysis › Gene set enrichment analysis (GSEA) ↔ Rscripts/Differential_Expression_Analysis_120D.Rmd, lines 694–780 · score 0.96 · simplifyGO, GO IDs, Cellular metabolism, avglog2FC, common words, downregulated genes
  2. [2] § Methods › Electrophysiological feature analysis › Single nuclei data processing ↔ Rscripts/QualityControl_120Day.Rmd, lines 255–289 · score 0.95 · generate cell clusters, Principal component, FindClusters, FindNeighbors, RunUMAP, SCTransform
  3. [3] § Methods › Electrophysiological feature analysis › Differential expression analysis ↔ Rscripts/Differential_Expression_Analysis_120D.Rmd, lines 782–901 · score 0.92 · FindMarkers, min.diff.pct, logfc.threshold, fold change, log normalised, excitatory neurons
  4. [4] § Methods › Electrophysiological feature analysis › Gene set enrichment analysis (GSEA) ↔ Rscripts/Differential_Expression_Analysis_120D.Rmd, lines 607–652 · score 0.90 · minSize, nPermSimple, gseaParam, maxSize, synaptic genes, inhibitory neurons
  5. [5] § Methods › Electrophysiological feature analysis › scMayoMap cell annotations ↔ Rscripts/Neuronal_Glial_Types_Analysis_120D.Rmd, lines 325–401 · score 0.85 · FindConservedMarkers, cluster_type2, scMayoMap, cluster_type1, cell annotations, database
  6. [6] § Methods › Electrophysiological feature analysis › Integration with neurotypical, human cortical biopsies ↔ Rscripts/QualityControl_120Day.Rmd, lines 255–289 · score 0.80 · SCT assay, variable features, RunPCA, Principal component, SCTransform, days
  7. [7] § Results › MPS IIIA neurons reveal dysregulated gene expression implicated in synaptic homeostasis ↔ Rscripts/Differential_Expression_Analysis_120D.Rmd, lines 694–780 · score 0.71 · Cellular metabolism, Ions, transport, inhibitory neurons, organising, upregulated
  8. [8] § Methods › Electrophysiological feature analysis › UMAP and Seurat cluster-based cell classification ↔ Rscripts/Neuronal_Glial_Types_Analysis_120D.Rmd, lines 572–609 · score 0.71 · FindClusters, FindNeighbors, RunUMAP, Seurat cluster, harmony, cells
  9. [9] § Methods › Electrophysiological feature analysis › Classification of cycling cells ↔ Rscripts/Neuronal_Glial_Types_Analysis_120D.Rmd, lines 211–278 · score 0.71 · cell cycle scores, NonCycling, AddModuleScore, G2M, G1S, gene
  10. [10] § Results › MPS IIIA neurons reveal dysregulated gene expression implicated in synaptic homeostasis ↔ Rscripts/Differential_Expression_Analysis_120D.Rmd, lines 506–563 · score 0.61 · expressed genes, NEUROD6, SATB2, excitatory neurons, inhibitory neurons, overlap
  11. [11] § Methods › Electrophysiological feature analysis › Calculation of cell type scores ↔ Rscripts/Neuronal_Glial_Types_Analysis_120D.Rmd, lines 150–209 · score 0.54 · AddModuleScore, Immature Neurons, Nowakowski, scores, OPCs, Astrocytes
  12. [12] § Methods › Electrophysiological feature analysis › Final cell type assignments ↔ Rscripts/Neuronal_Glial_Types_Analysis_120D.Rmd, lines 325–401 · score 0.51 · scMayoMap, cluster_type1, Seurat cluster, Inhibitory, Excitatory, cell
  13. [13] § Methods › Electrophysiological feature analysis › Unsupervised clustering analysis ↔ Rscripts/QualityControl_120Day.Rmd, lines 291–323 · score 0.50 · principal components, elbow, variance, PCA, clustering, filtered

Paper

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

The paper is loaded when this pane is shown.

The authors' code

R Markdown · 929 lines · 54 KB · no license · 5 matches

  1. ---
  2. title: "{[Sanfilippo] Differential expression analysis - 120 Day"
  3. author: "Inushi De Silva & Paris Mazzachi"
  4. date: "2023-11-16"
  5. output: html_document
  6. editor_options:
  7. chunk_output_type: console
  8. chunk_output_type: console
  9. ---
  10. ```{r setup, include=FALSE}
  11. knitr::opts_chunk$set(echo = TRUE)
  12. ```
  13. 1. ***First we will load the required libraries and set workingdirectories, datadirectories and plotdirectories.***
  14. ```{r Load Libraries and Set Directory Paths}
  15. options(future.globals.maxSize=1000* 1024^3)
  16. script_path <- rstudioapi::getActiveDocumentContext()$path
  17. script_dir <- dirname(script_path)
  18. workingdirectory <- dirname(script_dir)
  19. setwd(workingdirectory)
  20. datadirectory <- paste0(workingdirectory,"/data")
  21. resultsdirectory <- paste0(workingdirectory, "/results")
  22. RData_directory <- paste0(datadirectory,"/RData")
  23. ##dir.create(resultsdirectory)
  24. ## Load required libraries
  25. if(!require(dplyr)){
  26. install.packages("dplyr")
  27. library(dplyr)
  28. }
  29. if(!require(Seurat)){
  30. install.packages("Seurat")
  31. library(Seurat)
  32. }
  33. if(!require(ggplot2)){
  34. install.packages("ggplot2")
  35. library(ggplot2)
  36. }
  37. if(!require(sctransform)){
  38. install.packages("sctransform")
  39. library(sctransform)
  40. }
  41. if(!require(RColorBrewer)){
  42. install.packages("RColorBrewer")
  43. library(RColorBrewer)
  44. }
  45. if(!require(ggpointdensity)){
  46. install.packages("ggpointdensity")
  47. library(ggpointdensity)
  48. }
  49. if(!require(devtools)){
  50. install.packages("devtools")
  51. library(devtools)
  52. }
  53. if(!require(BiocManager)){
  54. install.packages("BiocManager")
  55. library(BiocManager)
  56. }
  57. if(!require(patchwork)){
  58. install.packages("patchwork")
  59. library(patchwork)
  60. }
  61. ```
  62. ```{r Other functions required in this markdown}
  63. ## A function to calculate differentially and significantly expressed geens
  64. significantly_expressed_genes <- function(differential_genes_df){
  65. differential_genes_df <- differential_genes_df[order(-differential_genes_df$avg_log2FC, differential_genes_df$p_val_adj),]
  66. differential_genes_df$p_val_adj[differential_genes_df$p_val_adj == 0] <- 1e-304
  67. differential_genes_df$log10p_adj <- -log10(differential_genes_df$p_val_adj)
  68. differential_genes_df$rank <- (differential_genes_df$avg_log2FC)*(differential_genes_df$log10p_adj)
  69. differential_genes_df <- differential_genes_df[order(differential_genes_df$rank, decreasing = T),]
  70. top <- differential_genes_df %>% top_n(15, rank)
  71. bottom <- differential_genes_df %>% top_n(-15, rank)
  72. label_genes <- c(rownames(top), rownames(bottom))
  73. differential_genes_df$diffexpressed <- ifelse(differential_genes_df$p_val_adj < 0.05 & differential_genes_df$avg_log2FC > 0, "TOP UP", ifelse(differential_genes_df$p_val_ad < 0.05 & differential_genes_df$avg_log2FC < 0,"TOP DOWN", "NO"))
  74. differential_genes_df$delabel <- NA
  75. differential_genes_df$delabel[(rownames(differential_genes_df) %in% label_genes)] <- rownames(differential_genes_df)[(rownames(differential_genes_df) %in% label_genes)]
  76. differential_genes_df$diffexpressed[is.na(differential_genes_df$delabel)] <- "NO"
  77. df_name <- deparse(substitute(differential_genes_df))
  78. return(differential_genes_df)
  79. }
  80. ## Adjusted EnrichmentPlot
  81. EnrichmentPlot <- function (pathway, stats, gseaParam = 1, ticksSize = 0.2)
  82. {
  83. pd <- plotEnrichmentData(pathway = pathway, stats = stats,
  84. gseaParam = gseaParam)
  85. with(pd, ggplot(data = curve) + geom_line(aes(x = rank, y = ES),
  86. color = "deepskyblue") + geom_segment(data = ticks, mapping = aes(x = rank,
  87. y = -spreadES/16, xend = rank, yend = spreadES/16), linewidth = ticksSize) +
  88. #geom_hline(yintercept = posES, colour = "red", linetype = "dashed") +
  89. #geom_hline(yintercept = negES, colour = "red", linetype = "dashed") +
  90. geom_hline(yintercept = 0, colour = "black") + theme(panel.background = element_blank(),
  91. panel.grid.major = element_line(color = "grey92"), axis.text.x = element_text(size = 18, angle = 90, vjust = 0.5), axis.text.y = element_text(size = 18, hjust = 0.5), axis.title.x = element_text(size = 18), axis.title.y = element_text(size = 18)) +
  92. labs(x = "Gene rank", y = "Enrichment score")) # + coord_cartesian(ylim = c(-0.025,0.45))
  93. }
  94. ## Manually calculate percentage of cells
  95. PrctCellExpringGene <- function(object, genes, group.by = "all"){
  96. if(group.by == "all"){
  97. prct = unlist(lapply(genes,calc_helper, object=object))
  98. result = data.frame(Markers = genes, Cell_proportion = prct)
  99. return(result)
  100. }
  101. else{
  102. list = SplitObject(object, group.by)
  103. factors = names(list)
  104. results = lapply(list, PrctCellExpringGene, genes=genes)
  105. for(i in 1:length(factors)){
  106. results[[i]]$Feature = factors[i]
  107. }
  108. combined = do.call("rbind", results)
  109. return(combined)
  110. }
  111. }
  112. calc_helper <- function(object,genes){
  113. counts = object[['RNA']]@data
  114. ncells = ncol(counts)
  115. if(genes %in% row.names(counts)){
  116. sum(counts[genes,]>0)/ncells
  117. }else{return(NA)}
  118. }
  119. ## function detect the most common words per cluster
  120. most_common_word=function(x){
  121. #Split every word into single words for counting
  122. splitTest=unlist(strsplit(x," "))
  123. #Counting words
  124. count=table(splitTest)
  125. #Sorting to select only the highest value, which is the first one
  126. count=count[order(count, decreasing=TRUE)][1:50]
  127. #Return the desired character.
  128. #By changing this you can choose whether it show the number of times a word repeats
  129. return(names(count))
  130. }
  131. # from https://hbctraining.github.io/scRNA-seq/lessons/elbow_plot_metric.html
  132. significant_pcs <- function(x){
  133. stdv <- x@reductions$pca@stdev # stdev per PC
  134. sum.stdv <- sum(x@reductions$pca@stdev) # Sum of stdev
  135. percent.stdv <- (stdv/sum.stdv)*100 # percentage of variation associated with each PC
  136. cumulative <- cumsum(percent.stdv) # cumulative percent of each PC
  137. # Determine which PC exhibits cumulative percent greater than 90% and % variation associated with the PC as less than 5
  138. co1 <- which(cumulative > 90 & percent.stdv < 5)[1]
  139. # Determine the difference between variation of PC and subsequent PC
  140. co2 <- sort(which((percent.stdv[1:length(percent.stdv) - 1] - percent.stdv[2:length(percent.stdv)]) > 0.1),
  141. decreasing = T)[1] + 1
  142. # Minimum of the two calculations used for clustering
  143. min.pc <- min(co1, co2)
  144. return(min.pc)
  145. }
  146. ```
  147. 2. ***Load the required RData files that have previously been QC'd***
  148. ```{r Load RData files that have previously been QC'd}
  149. ## Load required datasets
  150. set.seed(1)
  151. file_names <- list.files(paste0(RData_directory,"/120D/revisions/"), pattern = "*RData",full.names = T)
  152. lapply(file_names[c(6, 8)], load, .GlobalEnv)
  153. rm(file_names)
  154. ```
  155. 3. ***We now load in genes from the Nowakowski and Liddelow datasets***
  156. ```{r Load in neuronal gene lists and create colour scheme}
  157. ##load updated neuronal gene lists
  158. ##The gene names have been updated previously.
  159. load(file = paste0(datadirectory, "/reference_sheets/updated_neuronal_genes_ls.RData"))
  160. library(readxl)
  161. synaptic_genes <- read_excel(paste0(datadirectory, "/reference_sheets/syngo_genes.xlsx")) # SynGO Portal v1.2 (2023-12-01)
  162. stress_genes <- read_excel(paste0(datadirectory, "/reference_sheets/response_to_stress_genes.xlsx"))
  163. neuronal_genes_ls <- updated_neuronal_genes_ls
  164. rm(updated_neuronal_genes_ls)
  165. ## We also create a colour palette for each of the cell types
  166. library(colorspace)
  167. colour_palette <- data.frame(matrix(nrow = 44, ncol = 2))
  168. colour_palette$X1 <- c(names(neuronal_genes_ls)[1:43], "Other")
  169. colour_palette$X2[grepl("Astrocyte", colour_palette$X1, ignore.case = T)] <- colorRampPalette(c("salmon", "red"))(3)
  170. colour_palette$X2[grepl("eN", colour_palette$X1, ignore.case = T)] <- colorRampPalette(c("chocolate4", "tan"))(18)
  171. colour_palette$X2[grepl("RG", colour_palette$X1, ignore.case = T)] <- colorRampPalette(c("limegreen", "palegreen"))(11)
  172. colour_palette$X2[grepl("MGE_newborn", colour_palette$X1, ignore.case = T)] <- colorRampPalette(c("plum", "plum4"))(5)
  173. colour_palette$X2[grepl("MGE_Ctx", colour_palette$X1, ignore.case = T)] <- colorRampPalette(c("purple", "purple3"))(2)
  174. colour_palette$X2[grepl("CGE_LGE", colour_palette$X1, ignore.case = T)] <- colorRampPalette(c("slateblue", "slateblue4"))(2)
  175. colour_palette$X2[grepl("OPC", colour_palette$X1, ignore.case = T)] <- colorRampPalette(c("royalblue", "royalblue"))(1)
  176. colour_palette$X2[grepl("Striatal", colour_palette$X1, ignore.case = T)] <- colorRampPalette(c("sienna", "sienna"))(1)
  177. colour_palette$X2[grepl("Microglia", colour_palette$X1, ignore.case = T)] <- colorRampPalette(c("aquamarine3", "aquamarine3"))(1)
  178. colour_palette$X2[grepl("Mural", colour_palette$X1, ignore.case = T)] <- colorRampPalette(c("khaki", "khaki"))(1)
  179. colour_palette$X2[grepl("Other", colour_palette$X1, ignore.case = T)] <- colorRampPalette(c("black", "black"))(1)
  180. ##convert to named vector
  181. colours <- as.vector(colour_palette$X2)
  182. names(colours) <- colour_palette$X1
  183. ```
  184. 4. ***We now perform a differential expression analysis between control and MPSIIIA***
  185. ```{r Differential Expression Analysis and Volcano Plots - ALL}
  186. ## To perform differential expression analysis we first merge the two Seurat objects together.
  187. ## We will use the datasets which do not contain any "Unassigned" values for the donor id
  188. Sanfilippo_120D <- merge(Control_filtered_ambientRNA_120D, MPSIIIA_filtered_ambientRNA_120D) # remove 2 unassigned from MPSIIIA seurat
  189. table(Sanfilippo_120D$orig.ident)
  190. tbl <- [email hidden] %>% group_by(orig.ident, BIAD_id, final_cell_type) %>% summarise(n = n())
  191. cells_to_remove <- c("unassigned", "doublet") # remove doublets and unassigned cells
  192. Sanfilippo_120D <- subset(Sanfilippo_120D, cells = which(Sanfilippo_120D$BIAD_id %in% cells_to_remove), invert = T) # need to removed 2 unassigned from sanfil + striatal neurons
  193. tbl <- [email hidden] %>% group_by(orig.ident, BIAD_id, final_cell_type) %>% summarise(n = n())
  194. [email hidden] %>% group_by(orig.ident) %>% summarise(n = n())
  195. Idents(Sanfilippo_120D) <- 'orig.ident'
  196. Idents(Sanfilippo_120D) <- 'final_cell_type'
  197. Sanfilippo_120D <- subset(Sanfilippo_120D, downsample = 6619) # Downsample to have same pool of cells in each genotype
  198. [email hidden] %>% group_by(orig.ident) %>% summarise(n = n())
  199. ## We now SCTransform, RunPCA and UMAP to normalise gene expressions.
  200. Sanfilippo_120D <- JoinLayers(Sanfilippo_120D, assay = 'RNA')
  201. Sanfilippo_120D <- SCTransform(Sanfilippo_120D, vars.to.regress = c("percent.mt", "BIAD_id"))
  202. ## Save the seurat object to save time in future without re-running SCTransform each time
  203. save(Sanfilippo_120D, file = paste0(datadirectory, "/RData/120D/revisions/Combined_Control_MPSIIIA_120D_NOambientRNA.RData"))
  204. load(file = paste0(datadirectory, "/RData/120D/revisions/Combined_Control_MPSIIIA_120D_NOambientRNA.RData")) # Once run SCTransform once, can load the save RData file
  205. ## Run PCA and clustering for visualisation of cell types
  206. Sanfilippo_120D <- RunPCA(Sanfilippo_120D, npcs = 100, assay = "SCT")
  207. Sanfilippo_120D <- NormalizeData(Sanfilippo_120D, assay = "RNA", normalization.method = "LogNormalize")
  208. min.pc <- significant_pcs(Sanfilippo_120D)
  209. Sanfilippo_120D <- FindNeighbors(Sanfilippo_120D, dims = 1:min.pc, reduction = "pca")
  210. Sanfilippo_120D <- FindClusters(Sanfilippo_120D, resolution = 0.1)
  211. Sanfilippo_120D <- RunUMAP(Sanfilippo_120D, reduction = "pca", dims= 1:min.pc, n.components = 2L)
  212. tbl <- [email hidden] %>%
  213. group_by(orig.ident, BIAD_id, final_cell_type) %>%
  214. summarise(n = n()) %>%
  215. mutate(freq = (n / sum(n))*100)
  216. tbl
  217. write.csv(tbl, file = paste0(resultsdirectory, "/sheets/revisions_120D/20250717_MPSIIIAvHealthy_CellTypes_PatientProportions.csv"))
  218. Sanfilippo_120D$final_cell_type <- factor(Sanfilippo_120D$final_cell_type, levels = c( "Astrocyte","OPC","RG","Immature Neurons","Inhibitory","Excitatory")) # Re-order cell types for visualisation
  219. ## Visualisation of different cell types in culture - Fig 1B ##
  220. umap <- DimPlot(Sanfilippo_120D, reduction = "umap", group.by = "final_cell_type", split.by = "orig.ident", cols = c("firebrick4", "darkorchid2", "orange", "forestgreen", "mediumblue","deeppink2"), pt.size = 0.5, alpha = 1.0, order = T, label = FALSE, repel = FALSE) + ##you can replace the group.by variable to any column on the metadata
  221. theme(legend.position = "bottom", legend.text = element_text(size = 10), legend.justification = "center",
  222. axis.text.x = element_text(size = 22), axis.text.y = element_text(size = 22),
  223. axis.title.x = element_text(size = 22), axis.title.y = element_text(size = 22),
  224. panel.border = element_rect(fill=NA, colour = "black", size=0.5), plot.title= element_blank()) +
  225. coord_cartesian(ylim = c(-10, 10))
  226. umap <- umap + NoAxes() #+ NoLegend()
  227. umap
  228. ggsave(umap, filename = paste0(resultsdirectory,"/plots/revisions_120D/UMAPs_120D/20250717_ControlMPSIIIA_CellTypes_E-ISplit_percent.mito_BIAD-id.pdf", sep = ""), height = 6, width = 10, dpi = 300, useDingbats = FALSE, limitsize = F)
  229. ## Cell types separated by each donor - Supp Fig 3A ##
  230. Sanfilippo_120D$BIAD_id <- factor(Sanfilippo_120D$BIAD_id, levels = c( "B04-cNP11","B13-cNP20","B12-cNP24","B06-cNP08","B05-cNP21","B11-cNP30", "B03-cNP13", "B02-cNP16", "B01-cNP06", "B10-cNP25"))
  231. biad_ids <- unique(Sanfilippo_120D$BIAD_id)[1:10]
  232. umap_plots <- list()
  233. for (id in biad_ids) {
  234. umap <- DimPlot(Sanfilippo_120D, reduction = "umap", group.by = "final_cell_type",
  235. cells = which(Sanfilippo_120D$BIAD_id == id), # Subset cells by BIAD_id
  236. cols = c("firebrick4", "darkorchid2", "orange", "forestgreen", "mediumblue","deeppink2"),
  237. pt.size = 0.5, alpha = 1.0, order = TRUE, label = FALSE, repel = FALSE) +
  238. ggtitle(id) +
  239. theme(legend.position = "bottom",
  240. legend.text = element_text(size = 10),
  241. legend.justification = "center",
  242. axis.text.x = element_text(size = 22),
  243. axis.text.y = element_text(size = 22),
  244. axis.title.x = element_text(size = 22),
  245. axis.title.y = element_text(size = 22),
  246. panel.border = element_rect(fill = NA, colour = "black", size = 0.5),
  247. plot.title = element_text(size = 22, hjust = 0.5)) +
  248. coord_cartesian(ylim = c(-10, 10)) +
  249. NoAxes() #+ NoLegend() # Uncomment NoLegend if desired
  250. umap_plots[[id]] <- umap
  251. }
  252. combined_plot <- wrap_plots(umap_plots, nrow = 2, ncol = 5)
  253. combined_plot
  254. ggsave(combined_plot, filename = paste0(resultsdirectory,"/plots/revisions_120D/UMAPs_120D/20250718_ControlMPSIIIA_BIAD-id_neurons-split_noaxes_percent.mito_BIAD-id.pdf", sep = ""), height = 10.5, width = 20, dpi = 300, useDingbats = FALSE, limitsize = F)
  255. tbl <- [email hidden] %>%
  256. group_by(orig.ident, BIAD_id, final_cell_type) %>%
  257. summarise(n = n()) %>%
  258. mutate(freq = (n / sum(n))*100)
  259. tbl
  260. write.csv(tbl, file = paste0(resultsdirectory, '/sheets/revisions_120D/20250604_120D_BIAD-id_nodonordownsample_cell_types.csv'))
  261. ## Cell cycle analysis - Supp Fig 3F ##
  262. umap_density <- [email hidden][,c("orig.ident","cell_cycle")]
  263. umap_density <- cbind(umap_density, Sanfilippo_120D@reductions$[email hidden])
  264. scatterPlot <- ggplot(umap_density[na.omit(umap_density$cell_cycle == "NonCycling"),], aes(x = umap_1, y = umap_2)) +
  265. geom_point(data = umap_density[na.omit(umap_density$cell_cycle != "NonCycling"),], color = "grey90", size = 0.5) +
  266. geom_pointdensity(adjust = 0.2, size = 0.5) +
  267. scale_colour_gradient(low = "ghostwhite", high = "firebrick1", breaks = c(0,45,90), limits=c(0,90), na.value = "black") + #
  268. facet_wrap(~orig.ident, labeller = labeller(orig.ident = c("Control_120D" = "Healthy\n n= 6464 (98%)", "Sanfilippo_120D" = "MPSIIIA\n n= 6348 (96%)"))) +
  269. theme_bw() +
  270. theme(plot.title = element_text(size = 20, hjust = 0.5), plot.tag.position = "top",plot.subtitle = element_text(size = 20, hjust = 0.5, face = "plain"), plot.title.position = "plot", legend.position = "bottom", legend.text = element_text(size = 16, vjust = 0.5), legend.title = element_blank(), axis.text.x = element_text(size = 20), axis.text.y = element_text(size = 20), axis.title.x = element_text(size = 20), axis.title.y = element_text(size = 20), panel.border = element_rect(fill=NA, colour = "black", size=0.5), panel.grid = element_blank(), strip.text.x = element_text(size=20),strip.background = element_blank()) + NoAxes()
  271. scatterPlot
  272. scatterPlot <- ggplot(umap_density[na.omit(umap_density$cell_cycle == "G1S"),], aes(x = umap_1, y = umap_2)) +
  273. geom_point(data = umap_density[na.omit(umap_density$cell_cycle != "G1S"),], color = "grey90", size = 0.5) +
  274. geom_pointdensity(adjust = 0.2, size = 0.5) +
  275. scale_colour_gradient(low = "ghostwhite", high = "green1", breaks = c(0,25), limits=c(0,25), na.value = "black") + #
  276. facet_wrap(~orig.ident, labeller = labeller(orig.ident = c("Control_120D" = "Healthy\n n= 91 (1%)", "Sanfilippo_120D" = "MPSIIIA\n n= 153 (2%)"))) +
  277. theme_bw() +
  278. theme(plot.title = element_text(size = 20, hjust = 0.5), plot.tag.position = "top",plot.subtitle = element_text(size = 20, hjust = 0.5, face = "plain"), plot.title.position = "plot", legend.position = "bottom", legend.text = element_text(size = 16, vjust = 0.5), legend.title = element_blank(), axis.text.x = element_text(size = 20), axis.text.y = element_text(size = 20), axis.title.x = element_text(size = 20), axis.title.y = element_text(size = 20), panel.border = element_rect(fill=NA, colour = "black", size=0.5), panel.grid = element_blank(), strip.text.x = element_text(size=20),strip.background = element_blank()) + NoAxes()
  279. scatterPlot
  280. scatterPlot <- ggplot(umap_density[na.omit(umap_density$cell_cycle == "G2M"),], aes(x = umap_1, y = umap_2)) +
  281. geom_point(data = umap_density[na.omit(umap_density$cell_cycle != "G2M"),], color = "grey90", size = 0.5) +
  282. geom_pointdensity(adjust = 0.2, size = 0.5) +
  283. scale_colour_gradient(low = "ghostwhite", high = "gold", breaks = c(0,16,32), limits=c(0,32), na.value = "black") + #
  284. facet_wrap(~orig.ident, labeller = labeller(orig.ident = c("Control_120D" = "Healthy\n n= 64 (1%)", "Sanfilippo_120D" = "MPSIIIA\n n= 118 (2%)"))) +
  285. theme_bw() +
  286. theme(plot.title = element_text(size = 20, hjust = 0.5), plot.tag.position = "top",plot.subtitle = element_text(size = 20, hjust = 0.5, face = "plain"), plot.title.position = "plot", legend.position = "bottom", legend.text = element_text(size = 16, vjust = 0.5), legend.title = element_blank(), axis.text.x = element_text(size = 20), axis.text.y = element_text(size = 20), axis.title.x = element_text(size = 20), axis.title.y = element_text(size = 20), panel.border = element_rect(fill=NA, colour = "black", size=0.5), panel.grid = element_blank(), strip.text.x = element_text(size=20),strip.background = element_blank()) + NoAxes()
  287. scatterPlot
  288. ggsave(scatterPlot, filename = paste0(resultsdirectory,"/plots/revisions_120D/UMAPs_120D/20250523_Control_MPSIIIA_G2M_Density_final.pdf", sep = ""), height = 6.5, width = 10, dpi = 300, useDingbats = FALSE, limitsize = F)
  289. tbl <- [email hidden] %>%
  290. group_by(final_cell_type, new_cell_types) %>%
  291. summarise(n = n()) %>%
  292. mutate(freq = (n / sum(n))*100)
  293. tbl
  294. ```
  295. 4. ***Now we isolate just the neurons and separate them into excitatory and inhibitory neurons***
  296. ```{Identify excitatory and inhibitory neurons}
  297. ## Isolate the 'Neurons' from broad_cell_types to further separate them into excitatory and inhibitory neurons
  298. table([email hidden][['final_cell_type']])
  299. Idents(Sanfilippo_120D) <- 'final_cell_type'
  300. Sanfilippo_120D_Neurons <- subset(Sanfilippo_120D, idents = c('Excitatory', 'Inhibitory'))
  301. table(Sanfilippo_120D_Neurons$orig.ident)
  302. Idents(Sanfilippo_120D_Neurons) <- "orig.ident"
  303. Sanfilippo_120D_Neurons <- subset(Sanfilippo_120D_Neurons, downsample = 1015)
  304. [email hidden] %>% group_by(orig.ident) %>% summarise(n = n())
  305. Sanfilippo_120D_Neurons$neuron_types_ident <- paste(Sanfilippo_120D_Neurons$orig.ident, Sanfilippo_120D_Neurons$final_cell_type, sep = "_")
  306. Sanfilippo_120D_Neurons$biad_id_type <- paste(Sanfilippo_120D_Neurons$BIAD_id, Sanfilippo_120D_Neurons$final_cell_type, sep = "_")
  307. ## Save out proportion of excitatory and inhibitory neurons
  308. tbl <- [email hidden] %>%
  309. group_by(orig.ident, final_cell_type) %>%
  310. summarise(n = n()) %>%
  311. mutate(freq = (n / sum(n))*100)
  312. tbl
  313. write.csv(tbl, file = paste0(resultsdirectory, '/sheets/revisions_120D/20250604_120D_BIAD-id_nodonordownsample_Split_Neuron-type-proportions.csv'))
  314. # proportions used in Supp Fig 20B #
  315. tbl <- [email hidden] %>%
  316. group_by(orig.ident, BIAD_id, final_cell_type) %>%
  317. summarise(n = n()) %>%
  318. mutate(freq = (n / sum(n))*100)
  319. tbl
  320. write.csv(tbl, file = paste0(resultsdirectory, '/sheets/[Sanfilippo] DE_120D/20250604_MPSIIIA-Healthy_NeuronType_BIAD-id_proportions.csv'))
  321. ## Prepare object for UMAP reduction
  322. Sanfilippo_120D_Neurons <- SCTransform(Sanfilippo_120D_Neurons, vars.to.regress = c("percent.mt", "BIAD_id"))
  323. ## Save out seurat object
  324. save(Sanfilippo_120D_Neurons_New, file = paste0(datadirectory, "/RData/120D/revisions/Combined_Control_MPSIIIA_120D_NOambientRNA_NeuronsOnly.RData")) # As above, save after running SCTransform to save time
  325. load(file = paste0(datadirectory, "/RData/120D/revisions/Combined_Control_MPSIIIA_120D_NOambientRNA_NeuronsOnly.RData"))
  326. ## Re-run PCA and clustering for visualisation of neuronal subtypes
  327. var_features <- Sanfilippo_120D_Neurons_New@assays[["SCT"]]@var.features
  328. var_features <- var_features[grep("^LINC|^LOC|^AC[0-9]*\\.[0-9]|^AP[0-9]*\\.[0-9]|^AL[0-9]*\\.[0-9]",var_features, invert = T)]
  329. Sanfilippo_120D_Neurons_New <- RunPCA(Sanfilippo_120D_Neurons_New, npcs = 100, assay = "SCT", features = var_features)
  330. Sanfilippo_120D_Neurons_New <- NormalizeData(Sanfilippo_120D_Neurons_New, assay = "RNA", normalization.method = "LogNormalize")
  331. min.pc <- significant_pcs(Sanfilippo_120D_Neurons_New)
  332. Sanfilippo_120D_Neurons_New <- FindNeighbors(Sanfilippo_120D_Neurons_New, dims = 1:min.pc, reduction = "pca")
  333. Sanfilippo_120D_Neurons_New <- FindClusters(Sanfilippo_120D_Neurons_New, resolution = 0.1)
  334. Sanfilippo_120D_Neurons_New <- RunUMAP(Sanfilippo_120D_Neurons_New, reduction = "pca", dims= 1:min.pc, n.components = 2L)
  335. ## Visualise spread of excitatory/inhibitory neurons - Fig 7A ##
  336. umap <- DimPlot(Sanfilippo_120D_Neurons_New, reduction = "umap", group.by = "nowakowski_celltypes", split.by = "orig.ident", pt.size = 1.25, alpha = 1.0, order = T, label = FALSE, repel = FALSE) + ##you can replace the group.by variable to any column on the metadata
  337. theme(legend.position = "bottom", legend.text = element_text(size = 10), legend.justification = "center",
  338. axis.text.x = element_text(size = 22), axis.text.y = element_text(size = 22),
  339. axis.title.x = element_text(size = 22), axis.title.y = element_text(size = 22),
  340. panel.border = element_rect(fill=NA, colour = "black", size=0.5), plot.title= element_blank())# +
  341. #coord_cartesian(ylim = c(-10, 10))
  342. umap <- umap + NoAxes() #+ NoLegend()
  343. umap
  344. ggsave(umap, filename = paste0(resultsdirectory,"/plots/revisions_120D/UMAPs_120D/20250529_Excit-Inhib_percent.mt_BIAD-id_nodonordownsample.pdf", sep = ""), height = 6, width = 10, dpi = 300, useDingbats = FALSE, limitsize = F)
  345. ## Confirm neuronal populations express correct excitatory or inhibitory markers - Fig 7A ##
  346. features <- c("NXPH1","GAD1","GAD2","SOX6","SLC6A1","SHANK2","GRIA2","GRM5","SOX5","CAMK2A") # excitatory and inhibitory markers
  347. Idents(Sanfilippo_120D_Neurons_New) <- 'neuron_types_ident'
  348. dotplot <- DotPlot(Sanfilippo_120D_Neurons_New, features = features, cols = c("blue", "firebrick2"), idents = c("Sanfilippo_120D_Excitatory", "Sanfilippo_120D_Inhibitory")) + theme_bw() +
  349. #labs(title = "Excitatory Neurons", subtitle = "[n = 26 cells]") +
  350. theme(plot.title = element_text(size = 20, hjust = 0.5), plot.tag.position = "top",plot.subtitle = element_text(size = 20, hjust = 0.5, face = "plain"), plot.title.position = "plot", legend.position = "right", legend.text = element_text(size = 16, vjust = 0.5), axis.text.x = element_blank(), axis.text.y = element_text(size = 20), axis.title.x = element_blank(), axis.title.y = element_text(size = 20), panel.border = element_rect(fill=NA, colour = "black", size=0.5), panel.grid = element_blank(), strip.text.x = element_text(size=20),strip.background = element_blank()) + coord_flip() #+ scale_y_reordered()
  351. dotplot$data$id <- factor(dotplot$data$id,
  352. levels = c("Sanfilippo_120D_Excitatory", "Sanfilippo_120D_Inhibitory"))
  353. dotplot
  354. ggsave(dotplot, filename = paste0(resultsdirectory,"/plots/revisions_120D/20250529_MPSIIIA_ExcVInhibNeurons_DotPlot_nodonordownsamp.pdf"), height = 5, width = 4.5, dpi = 300)
  355. ## Density plots separating excitatory and inhibitory neurons - Supp Fig 20C ##
  356. ## Excitatory neurons
  357. umap_density <- [email hidden][,c("orig.ident","final_cell_type")]
  358. umap_density <- cbind(umap_density, Sanfilippo_120D_Neurons_New@reductions$[email hidden])
  359. scatterPlot <- ggplot(umap_density[na.omit(umap_density$final_cell_type == "Excitatory"),], aes(x = umap_1, y = umap_2)) +
  360. geom_point(data = umap_density[na.omit(umap_density$final_cell_type != "Excitatory"),], color = "grey90", size = 1.25) +
  361. geom_pointdensity(adjust = 0.2, size = 1.25) +
  362. scale_colour_gradient(low = "ghostwhite", high = "deeppink2", breaks = c(0,24), limits=c(0,24), na.value = "black") + #
  363. facet_wrap(~orig.ident, labeller = labeller(orig.ident = c("Control_120D" = "Healthy\n n= 320 (31.5%)", "Sanfilippo_120D" = "MPSIIIA\n n= 505 (49.8%)"))) +
  364. theme_bw() +
  365. theme(plot.title = element_text(size = 20, hjust = 0.5), plot.tag.position = "top",plot.subtitle = element_text(size = 20, hjust = 0.5, face = "plain"), plot.title.position = "plot", legend.position = "bottom", legend.text = element_text(size = 16, vjust = 0.5), legend.title = element_blank(), axis.text.x = element_text(size = 20), axis.text.y = element_text(size = 20), axis.title.x = element_text(size = 20), axis.title.y = element_text(size = 20), panel.border = element_rect(fill=NA, colour = "black", size=0.5), panel.grid = element_blank(), strip.text.x = element_text(size=20),strip.background = element_blank()) + NoAxes()
  366. scatterPlot
  367. ggsave(scatterPlot, filename = paste0(resultsdirectory,"/plots/revisions_120D/UMAPs_120D/20250529_Control_MPSIIIA_ExcitatoryNeurons_Density_nodonordownsamp.pdf", sep = ""), height = 6, width = 10, dpi = 300, useDingbats = FALSE, limitsize = F)
  368. ## Inhibitory neurons
  369. scatterPlot <- ggplot(umap_density[na.omit(umap_density$final_cell_type == "Inhibitory"),], aes(x = umap_1, y = umap_2)) +
  370. geom_point(data = umap_density[na.omit(umap_density$final_cell_type != "Inhibitory"),], color = "grey90", size = 1.25) +
  371. geom_pointdensity(adjust = 0.2, size = 1.25) +
  372. scale_colour_gradient(low = "ghostwhite", high = "mediumblue", breaks = c(0,19), limits=c(0,19), na.value = "black") + #
  373. facet_wrap(~orig.ident, labeller = labeller(orig.ident = c("Control_120D" = "Healthy\n n= 695 (68.5%)", "Sanfilippo_120D" = "MPSIIIA\n n= 510 (50.2%)"))) +
  374. theme_bw() +
  375. theme(plot.title = element_text(size = 20, hjust = 0.5), plot.tag.position = "top",plot.subtitle = element_text(size = 20, hjust = 0.5, face = "plain"), plot.title.position = "plot", legend.position = "bottom", legend.text = element_text(size = 16, vjust = 0.5), legend.title = element_blank(), axis.text.x = element_text(size = 20), axis.text.y = element_text(size = 20), axis.title.x = element_text(size = 20), axis.title.y = element_text(size = 20), panel.border = element_rect(fill=NA, colour = "black", size=0.5), panel.grid = element_blank(), strip.text.x = element_text(size=20),strip.background = element_blank()) + NoAxes()
  376. scatterPlot
  377. ggsave(scatterPlot, filename = paste0(resultsdirectory,"/plots/revisions_120D/UMAPs_120D/20250529_Control_MPSIIIA_Inhib_Density_redone_nodonordownsamp.pdf", sep = ""), height = 6, width = 10, dpi = 300, useDingbats = FALSE, limitsize = F)
  378. ## Density plot looking at split of excitatory and inhibitory neurons by donor - Supp Fig 20E ##
  379. Sanfilippo_120D_Neurons_New$BIAD_id <- factor(Sanfilippo_120D_Neurons_New$BIAD_id, levels = c( "B04-cNP11","B13-cNP20","B12-cNP24","B06-cNP08","B05-cNP21","B11-cNP30", "B03-cNP13", "B02-cNP16", "B01-cNP06", "B10-cNP25"))
  380. umap_density <- [email hidden][,c("BIAD_id","final_cell_type")]
  381. umap_density <- cbind(umap_density, Sanfilippo_120D_Neurons_New@reductions$[email hidden])
  382. library(ggnewscale)
  383. scatterPlot <- ggplot(umap_density, aes(x = umap_1, y = umap_2)) +
  384. geom_point(data = umap_density[!(umap_density$final_cell_type %in% c("Excitatory", "Inhibitory")),], color = "grey80", size = 1.25) +
  385. geom_pointdensity(data = umap_density[umap_density$final_cell_type == "Excitatory",], adjust = 0.2, size = 1.25) +
  386. scale_colour_gradient(name = "Excitatory", low = "ghostwhite", high = 'deeppink2', breaks = c(0,24), limits=c(0,24), na.value = 'black') +
  387. new_scale_colour() +
  388. geom_pointdensity(data = umap_density[umap_density$final_cell_type == "Inhibitory",], adjust = 0.2, size = 1.25) +
  389. scale_colour_gradient(name = "Inhibitory", low = "ghostwhite", high = "mediumblue", breaks = c(0,19), limits=c(0,19), na.value = "black") +#breaks = c(0,24), limits = c(0,24),
  390. facet_wrap(~BIAD_id, labeller = labeller(BIAD_id = c(
  391. "B12-cNP24" = 'BIAD12 (2 clones)',
  392. "B06-cNP08" = 'BIAD06 (2 clones)',
  393. "B13-cNP20" = 'BIAD13 (2 clones)',
  394. "B04-cNP11" = 'BIAD04 (2 clones)',
  395. "B05-cNP21" = 'BIAD05 (1 clone)',
  396. "B11-cNP30" = 'BIAD11 (2 clones)',
  397. 'B10-cNP25' = 'BIAD10 (2 clones)',
  398. "B01-cNP06" = 'BIAD01 (2 clones)',
  399. "B03-cNP13" = 'BIAD03 (2 clones)',
  400. "B02-cNP16" = 'BIAD02 (2 clones)')), ncol = 5) +
  401. theme_bw() +
  402. theme(
  403. plot.title = element_text(size = 20, hjust = 0.5),
  404. plot.subtitle = element_text(size = 16, hjust = 0.5, face = "italic"),
  405. legend.position = "bottom",
  406. legend.text = element_text(size = 16, vjust = 0.5),
  407. axis.text.x = element_text(size = 20),
  408. axis.text.y = element_text(size = 20),
  409. axis.title.x = element_text(size = 20),
  410. axis.title.y = element_text(size = 20),
  411. panel.border = element_rect(fill = NA, colour = "black", size = 0.25),
  412. panel.grid = element_blank(),
  413. strip.text.x = element_text(size = 20),
  414. strip.background = element_blank()
  415. ) +
  416. coord_equal() + NoAxes()
  417. # Display the scatter plot
  418. scatterPlot
  419. ggsave(scatterPlot, filename = paste0(resultsdirectory,"/plots/revisions_120D/UMAPs_120D/20250529_ControlMPSIIIA_UMAP_DonorID_ExcitatoryInhibitory_Density_nodonordownsamp.pdf", sep = ""), height = 12, width = 14, dpi = 300, useDingbats = FALSE, limitsize = F)
  420. ```
  421. 5. We perform differential expression analysis on different neuronal subtypes
  422. ``` {DE Analysis and visulation for excitatory and inhibitory neurons}
  423. ## We conduct a differential expression to identify genes that are significantly expressed in Sanfilippo compared to Control.
  424. ## Excitatory neurons
  425. Idents(Sanfilippo_120D_Neurons_New) <- 'neuron_types_ident'
  426. DE_Control_MPSIIIA_EN <- FindMarkers(Sanfilippo_120D_Neurons_New, assay = 'RNA', slot = 'data', ident.1 = "Sanfilippo_120D_Excitatory", ident.2 = "Control_120D_Excitatory", logfc.threshold = 0, min.pct = 0.1, min.diff.pct = 0.1, test.use = "wilcox")
  427. DE_Control_MPSIIIA_EN$hgnc_symbol <- rownames(DE_Control_MPSIIIA_EN)
  428. DE_Control_MPSIIIA_EN <- significantly_expressed_genes(DE_Control_MPSIIIA_EN)
  429. ## Save out DE results
  430. write.csv(DE_Control_MPSIIIA_EN, file = paste0(resultsdirectory, "/sheets/revisions_120D/DE_120D/20250718_DE_Control_MPSIIIA_ExcitatoryNeurons_wilcox_nodonordownsample.csv"))
  431. # #Inhibitory neurons
  432. DE_Control_MPSIIIA_IN <- FindMarkers(Sanfilippo_120D_Neurons_New, assay = 'RNA', slot = 'data', ident.1 = "Sanfilippo_120D_Inhibitory", ident.2 = "Control_120D_Inhibitory", logfc.threshold = 0, min.pct = 0.1, min.diff.pct = 0.1, test.use = "wilcox")
  433. DE_Control_MPSIIIA_IN$hgnc_symbol <- rownames(DE_Control_MPSIIIA_IN)
  434. DE_Control_MPSIIIA_IN <- significantly_expressed_genes(DE_Control_MPSIIIA_IN)
  435. ## Save out DE results
  436. write.csv(DE_Control_MPSIIIA_IN, file = paste0(resultsdirectory, "/sheets/revisions_120D/DE_120D/20250718_DE_Control_MPSIIIA_InhibitoryNeurons_wilcox_nodonordownsample.csv"))
  437. ## Dot plots to visualise key genes up or down regulated in excitatory and inhibitory neurons (disease v healthy) - Figure 5B
  438. excitatory_genes <- c("PEG3", "AC069277.1", "XIST", "AC006115.2", "GRM7-AS3", "IQCJ-SCHIP1", "NELL2", "NEUROD6", "SATB2", "TAFA1") # top 5 up/down DEG
  439. inhibitory_genes <- c("PEG3", "AC069277.1", "MTRNR2L1", "XIST", "GRM7-AS3", "CRLF1", "PTGDS", "CHL1", "IFITM3", "NEUROD6") # top 5 up/down DEG
  440. excit_v_inhib <- DotPlot(Sanfilippo_120D_Neurons_New, features = inhibitory_genes, cols = c("blue", "firebrick2"), idents = c("Sanfilippo_120D_Inhibitory", "Control_120D_Inhibitory")) + theme_bw() +
  441. #labs(title = "Excitatory Neurons", subtitle = "[n = 26 cells]") +
  442. theme(plot.title = element_text(size = 20, hjust = 0.5), plot.tag.position = "top",plot.subtitle = element_text(size = 20, hjust = 0.5, face = "plain"), plot.title.position = "plot", legend.position = "right", legend.text = element_text(size = 16, vjust = 0.5), axis.text.x = element_blank(), axis.text.y = element_text(size = 20), axis.title.x = element_blank(), axis.title.y = element_text(size = 20), panel.border = element_rect(fill=NA, colour = "black", size=0.5), panel.grid = element_blank(), strip.text.x = element_text(size=20),strip.background = element_blank()) + coord_flip() #+ scale_y_reordered()
  443. excit_v_inhib$data$id <- factor(excit_v_inhib$data$id,
  444. levels = c("Sanfilippo_120D_Inhibitory", "Control_120D_Inhibitory"))
  445. excit_v_inhib
  446. ggsave(excit_v_inhib, filename = paste0(resultsdirectory,"/plots/revisions_120D/DE_120D/20250529_SanfilvControl_InhibitoryNeurons_DotPlot_nodonordownsample.pdf"), height = 5, width = 4.75, dpi = 300)
  447. ## Volcano Plot - Fig 7B (swap the data between excitatory or inhibitory DE results) ##
  448. VP <- ggplot(DE_Control_MPSIIIA_EN, aes(avg_log2FC, log10p_adj, label=delabel, color=diffexpressed)) + geom_point(alpha = 1, size = 3, fill = "grey90") + ## transform to change the order of the plots in facet_wrap()
  449. theme_light() +
  450. scale_fill_gradientn(colours = c(rainbow(100)), ## colors in the scale
  451. breaks = seq(0, 1, 0.2),
  452. limits = c(0, 1)) +
  453. scale_color_manual(values = c("grey60","blue","red")) +
  454. geom_text_repel(data=DE_Control_MPSIIIA_EN, size = 8, max.overlaps = 75, direction = "both") +
  455. theme(legend.position = "right", axis.text.x = element_text(size = 28), axis.text.y = element_text(size = 28), axis.title.x = element_text(size = 30), axis.title.y = element_text(size = 30), panel.border = element_rect(fill=NA, colour = "black", size=0.5)) +
  456. labs(y=expression('-Log'[10]*' P'[adj]), x=expression(atop('Log'[2]*' fold change', paste("[MPSIIIA/Control]")))) +
  457. scale_x_continuous(breaks = seq(-7, 7, by = 2)) +
  458. scale_y_continuous(breaks = seq(0, 90, by = 20)) +
  459. coord_cartesian(xlim = c(-7, 7), ylim = c(0, 80)) +
  460. geom_hline(yintercept = -log10(0.05), linetype = "dashed", col = "darkgrey", size = 1) + NoLegend()
  461. VP
  462. ggsave(VP, filename = paste0(resultsdirectory,"/plots/revisions_120D/DE_120D/20250529_VP_MPSIIIA_Control_DE_ExcitatoryNeurons_nodonordownsample.pdf"), height = 10, width = 10, dpi = 300)
  463. # Looking at expression of E/I genes by patient - Fig 7F #
  464. Idents(Sanfilippo_120D_Neurons_New) <- "BIAD_id"
  465. average_expression <- AverageExpression(Sanfilippo_120D_Neurons_New, assay = "RNA", slot = "counts", features = c("NLGN1", "CDKL5", "DISC1", "SHANK2", "DLG4", "GPHN", "NLGN2", "GABRA1", "GLRB", "GRIA1", "GRIA2", "GRIA3", "GRIA4", "HOMER1", "CAMK2A", "ARHGEF9", "KCC2", "GRIN1", "GRIN2A", "GRIN2B", "GABARAP", "GABRA2"), group.by = c("BIAD_id", "final_cell_type"))
  466. average_expression <- as.data.frame(average_expression)
  467. average_expression <- t(average_expression)
  468. write.csv(average_expression, file = paste0(resultsdirectory, "/sheets/revisions_120D/DE_120D/20250717_synapsegenes_e-i-neurons_biad-id_rawcounts_120d.csv"))
  469. ```
  470. 6.***We perform GSEA for excitatory and inhibitory neurons***
  471. ```{r GSEA for differentially expressed genes in excitatory and inhibitory neurons}
  472. ### Use this if you want to run fgsea analysis
  473. library(fgsea)
  474. library(data.table)
  475. ## Isolate avglog2FC values from previously ranked DE list for excitatory and inhibitory neurons
  476. upreg_EN <- DE_Control_MPSIIIA_EN[which(DE_Control_MPSIIIA_EN$avg_log2FC > 0 & DE_Control_MPSIIIA_EN$p_val_adj < 0.05),]
  477. downreg_EN <- DE_Control_MPSIIIA_EN[which(DE_Control_MPSIIIA_EN$avg_log2FC < 0 & DE_Control_MPSIIIA_EN$p_val_adj < 0.05),]
  478. dysreg_EN <- rbind(upreg_EN, downreg_EN)
  479. ranked_genes_EN <- dysreg_EN$avg_log2FC
  480. names(ranked_genes_EN) <- rownames(dysreg_EN)
  481. upreg_IN <- DE_Control_MPSIIIA_IN[which(DE_Control_MPSIIIA_IN$avg_log2FC > 0 & DE_Control_MPSIIIA_IN$p_val_adj < 0.05),]
  482. downreg_IN <- DE_Control_MPSIIIA_IN[which(DE_Control_MPSIIIA_IN$avg_log2FC < 0 & DE_Control_MPSIIIA_IN$p_val_adj < 0.05),]
  483. dysreg_IN <- rbind(upreg_IN, downreg_IN)
  484. ranked_genes_IN <- dysreg_IN$avg_log2FC
  485. names(ranked_genes_IN) <- rownames(dysreg_IN)
  486. Idents(Sanfilippo_120D_Neurons_New) <- 'neuron_types_ident'
  487. # Create a dataframe with avg log2FC values for a list of synaptic genes
  488. av_exp_df <- as.data.frame(AverageExpression(Sanfilippo_120D_Neurons_New, assays = "RNA", slot = "data", features = unique(unlist(synaptic_genes$hgnc_symbol))))
  489. av_exp_df$Logadj_Control_EN <- log2((av_exp_df$RNA.Control.120D.Excitatory))
  490. av_exp_df$Logadj_MPSIIIA_EN <- log2((av_exp_df$RNA.Sanfilippo.120D.Excitatory))
  491. av_exp_df$Logadj_Control_IN <- log2((av_exp_df$RNA.Control.120D.Inhibitory))
  492. av_exp_df$Logadj_MPSIIIA_IN <- log2((av_exp_df$RNA.Sanfilippo.120D.Inhibitory))
  493. av_exp_df$avg_log2FC_ENs <- av_exp_df$Logadj_MPSIIIA_EN - av_exp_df$Logadj_Control_EN
  494. av_exp_df$avg_log2FC_ENs[is.na(av_exp_df$avg_log2FC_ENs)] <- 0
  495. av_exp_df$avg_log2FC_ENs[is.infinite(av_exp_df$avg_log2FC_ENs)] <- 0
  496. av_exp_df$avg_log2FC_INs <- av_exp_df$Logadj_MPSIIIA_IN - av_exp_df$Logadj_Control_IN
  497. av_exp_df$avg_log2FC_INs[is.na(av_exp_df$avg_log2FC_INs)] <- 0
  498. av_exp_df$avg_log2FC_INs[is.infinite(av_exp_df$avg_log2FC_INs)] <- 0
  499. ranked_genes <- as.vector(av_exp_df[,10])
  500. names(ranked_genes) <- rownames(av_exp_df)
  501. ranked_genes <- sort(ranked_genes, decreasing = T)
  502. ## Load list of synaptic genes
  503. pathways <- list("DEGs" = dysreg_EN$hgnc_symbol)
  504. pathways_IN <- list("DEGs" = dysreg_IN$hgnc_symbol)
  505. gse_all_EN <- fgsea(pathways,
  506. stats = ranked_genes,
  507. minSize = 1,
  508. maxSize = 500,
  509. nPermSimple = 10000,
  510. gseaParam = 1,
  511. eps = 0)
  512. gse_all_IN <- fgsea(pathways_IN,
  513. stats = ranked_genes,
  514. minSize = 1,
  515. maxSize = 500,
  516. nPermSimple = 10000,
  517. gseaParam = 1,
  518. eps = 0)
  519. ## Visualise enrichment for excitatory and inhibitory neurons - Fig 7E ##
  520. pdf(paste0(resultsdirectory,"/plots/revisions_120D/DE_120D/20250623_SynapticGene_Enrichment_Plot_InhibitoryNeurons_nodonordownsample.pdf"), width=7.5, height=5)
  521. EP <- EnrichmentPlot(pathways$DEGs,
  522. ranked_genes, gseaParam = 2, ticksSize = 0.2)
  523. EP
  524. dev.off()
  525. test_list <- list(gse_all$leadingEdge)
  526. gse_all_EN <- as.data.frame(gse_all_EN)
  527. gse_all_EN <- gse_all_EN[1:7]
  528. gse_all_IN <- as.data.frame(gse_all_IN)
  529. gse_all_IN <- gse_all_IN[1:7]
  530. write.csv(gse_all_EN, file = paste0(resultsdirectory, '/sheets/revisions_120D/20250623_SynapticEnrich_ExcitatoryNeurons_nodonordownsamp.csv'))
  531. write.csv(gse_all_IN, file = paste0(resultsdirectory, '/sheets/revisions_120D/20250623_SynapticEnrich_InhibitoryNeurons_nodonordownsamp.csv'))
  532. # Perform GO Pathway analysis on significantly dysregulated genes
  533. library(msigdbr)
  534. library(org.Hs.eg.db)
  535. library(enrichplot)
  536. library(clusterProfiler)
  537. library(DOSE)
  538. library(simplifyEnrichment)
  539. library(GOSemSim)
  540. ## Create a vector of all gene names in count matrix to use as background set of genes
  541. all_genes <- as.matrix(Sanfilippo_120D_Neurons_New@assays[["RNA"]]@layers[["counts"]])
  542. rownames(all_genes) <- rownames(Sanfilippo_120D_Neurons_New@assays[['RNA']])
  543. all_genes <- row.names(all_genes)
  544. # Create vector of gene names that are significantly dysregulated for GO enrichment
  545. geneList <- dysreg_EN$hgnc_symbol
  546. geneList_IN <- dysreg_IN$hgnc_symbol
  547. test_enrichment <- enrichGO(gene = geneList, # make sure it's running for either the excitatory list or inhibitory
  548. OrgDb = 'org.Hs.eg.db',
  549. keyType = 'SYMBOL',
  550. ont = 'BP',
  551. universe = all_genes,
  552. pvalueCutoff = 0.05,
  553. pAdjustMethod = 'BH',
  554. qvalueCutoff = 0.1,
  555. minGSSize = 10,
  556. maxGSSize = 500,
  557. readable = TRUE)
  558. job::job({inhib_enrichment <- enrichGO(gene = geneList_IN, # to be able to run two enrichment analyses at once
  559. OrgDb = 'org.Hs.eg.db',
  560. keyType = 'SYMBOL',
  561. ont = 'BP',
  562. universe = all_genes,
  563. pvalueCutoff = 0.05,
  564. pAdjustMethod = 'BH',
  565. qvalueCutoff = 0.1,
  566. minGSSize = 10,
  567. maxGSSize = 500,
  568. readable = TRUE)})
  569. ## Isolate GO ID's for similarity clustering
  570. go_id_EN <- test_enrichment@result$ID
  571. job::job({go_mat <- GO_similarity(go_id_EN, ont = "BP")})
  572. go_id <- inhib_enrichment@result$ID
  573. job::job({go_mat_inhib <- GO_similarity(go_id, ont = "BP")})
  574. ## generate clusters using louvain clustering.
  575. go_cluster_louvain <- simplifyGO(go_mat_inhib, method = "louvain") ## NEED TO RUN THIS FOR INHIBITORY NEURONS AND FINISH CHORD PLOT TO UPDATE FIGURE
  576. test_enrichment@result$Cluster_louvain <- go_cluster_louvain$cluster[match(test_enrichment@result$ID, go_cluster_louvain$id)]
  577. inhib_enrichment@result$Cluster_louvain <- go_cluster_louvain$cluster[match(inhib_enrichment@result$ID, go_cluster_louvain$id)]
  578. enrichment_result <- as.data.frame(test_enrichment@result)
  579. enrichment_result <- as.data.frame(inhib_enrichment@result)
  580. most_common_word=function(x){
  581. #Split every word into single words for counting
  582. splitTest=unlist(strsplit(x," "))
  583. #Counting words
  584. count=table(splitTest)
  585. #Sorting to select only the highest value, which is the first one
  586. count=count[order(count, decreasing=TRUE)][1:50]
  587. #Return the desired character.
  588. #By changing this you can choose whether it show the number of times a word repeats
  589. return(names(count))
  590. }
  591. cluster_words <- vector("list", 12) # List to store results for each cluster
  592. # Loop through clusters 1 to 18
  593. for (i in 1:12) {
  594. # Subset descriptions for the current cluster
  595. cluster_descriptions <- test_enrichment@result[test_enrichment@result$Cluster_louvain == i,]
  596. # Apply most_common_word to the descriptions
  597. cluster_words[[i]] <- most_common_word(cluster_descriptions)
  598. }
  599. # Optionally, name the list elements for clarity
  600. names(cluster_words) <- paste0("Cluster_", 1:18)
  601. ## Add description based on pathways in the clusters and most common word function above
  602. # Excitatory
  603. test_enrichment@result$new_description <- ifelse(test_enrichment@result$Cluster_louvain == "1", "cellular differentiation and development", ifelse(test_enrichment@result$Cluster_louvain == "2", "ions and transport", ifelse(test_enrichment@result$Cluster_louvain == "3", "signaling pathways", ifelse(test_enrichment@result$Cluster_louvain == "4", "regulation and organisation", ifelse(test_enrichment@result$Cluster_louvain == "5", "regulation and organisation", ifelse(test_enrichment@result$Cluster_louvain == "6", "cellular metabolism", "other"
  604. ))))))
  605. # Inhibitory
  606. inhib_enrichment@result$new_description <- ifelse(inhib_enrichment@result$Cluster_louvain == "1", "cellular differentiation and development", ifelse(inhib_enrichment@result$Cluster_louvain == "2", "ions and transport", ifelse(inhib_enrichment@result$Cluster_louvain == "3", "signaling pathways", ifelse(inhib_enrichment@result$Cluster_louvain == "4", "regulation and organisation", ifelse(inhib_enrichment@result$Cluster_louvain == "5", "regulation and organisation", ifelse(inhib_enrichment@result$Cluster_louvain == "6", "cellular metabolism", "other"
  607. ))))))
  608. # Reorder by P.adjust value and save out to create table of top 5 GO IDs - Supp Fig 20E
  609. test_enrichment <- test_enrichment@result[order(test_enrichment@result$p.adjust),]
  610. inhib_enrichment <- inhib_enrichment@result[order(inhib_enrichment@result$p.adjust),]
  611. write.csv(test_enrichment, file = paste0(resultsdirectory, '/sheets/revisions_120D/20250604_Excitatory_neuron_DEG_PathwayAnalysis_nodonordownsample.csv'))
  612. enrichGO_list <- list()
  613. enrichGO_list$results <- data.frame("Category" = "BP","ID" = test_enrichment$Cluster_louvain, "Term" = test_enrichment$new_description, "Genes" = test_enrichment$geneID, "adj_pval" = test_enrichment$p.adjust) # swap enrichment result object between excitatory or inhibitory for cord plot visualisation
  614. enrichGO_list$results$Genes <- gsub("/",",",enrichGO_list$results$Genes)
  615. ## Make list of dysregulated genes in excitatory and inhibitory with their avglog2FC from DE analysis
  616. library(GOplot)
  617. enrichGO_list$geneList <- data.frame("ID" = rownames(dysreg_IN), "logFC" = dysreg_IN$avg_log2FC)
  618. circ <- circle_dat(enrichGO_list$results, enrichGO_list$geneList)
  619. enrichGO_list$process <- unique(circ$term)
  620. chord <- chord_dat(circ, enrichGO_list$geneList, enrichGO_list$process)
  621. chord <- chord[c(1:25, 751:755),] # Filter for the top 15 upregulated and top 15 downregulated genes
  622. chord <- chord[order(chord[,6], decreasing = T), ] # Order by decreasing logFC
  623. ## Order by different cluster descriptions
  624. chord <- chord[, c("cellular metabolism", "signaling pathways", "regulation and organisation", "cellular differentiation and development", "ions and transport", "logFC")] #
  625. ## Visualise chord plot - Fig 7D
  626. pdf(file = paste0(resultsdirectory,"/plots/revisions_120D/DE_120D/20250604_GOChord_top30DEgenes_upanddown_louvainclustering_inhibitoryneurons_nodonordownsample.pdf"), width = 14, height =14)
  627. cplot <- GOChord(chord,
  628. nlfc = 1,
  629. limit = c(0,0),
  630. space = 0.02,
  631. gene.space = 0.25,
  632. gene.order = "logFC",
  633. border.size = 0,
  634. ribbon.col = c("firebrick2", "orange","green3", "dodgerblue2", "deeppink"), #
  635. gene.size = 5,
  636. lfc.min = -7,
  637. lfc.max = 7,
  638. lfc.col = c("red", "grey90", "blue"))
  639. cplot
  640. dev.off()
  641. ```
  642. 7. ddressing reviewer concerns regarding BIAD03's high SOX2 iPSC expression and effect that has on phenotypes identified
  643. ```{Addressing reviewer concerns regarding BIAD03}
  644. ## Isolating excitatory neurons then performing FindMarkers on BIAD03 compared to other excitatory neurons
  645. Idents(Sanfilippo_120D_Neurons_New) <- 'neuron_types_ident'
  646. excitatory_only <- subset(Sanfilippo_120D_Neurons_New, idents = 'Sanfilippo_120D_Excitatory')
  647. excitatory_only <- NormalizeData(excitatory_only, assay = "RNA", normalization.method = "LogNormalize")
  648. # Perform DE on BIAD03 vs all MPSIIIA patients to understand unique population #
  649. Idents(excitatory_only) <- 'biad_id_type'
  650. BIAD03_unique <- FindMarkers(excitatory_only, assay = 'RNA', slot = 'data', ident.1 = "B03-cNP13_Excitatory", ident.2 = NULL, logfc.threshold = 0, min.pct = 0.1, min.diff.pct = 0.1, test.use = "wilcox")
  651. BIAD03_unique$hgnc_symbol <- rownames(BIAD03_unique)
  652. BIAD03_unique <- significantly_expressed_genes(BIAD03_unique)
  653. BIAD03_unique_upreg <- BIAD03_unique[which(BIAD03_unique$avg_log2FC > 0 &BIAD03_unique$p_val_adj < 0.05),] # find uniquely upregulated for GO analysis
  654. BIAD03_unique_downreg <- BIAD03_unique[which(BIAD03_unique$avg_log2FC < 0 &BIAD03_unique$p_val_adj < 0.05),] # find uniquely downregulated for GO analysis
  655. write.csv(BIAD03_unique, file = paste0(resultsdirectory, "/sheets/revisions_120D/DE_120D/20251203_DE_BIAD03-ENs_AllDonors_wilcox_nodonordownsample.csv"))
  656. # Volcano plot of uniquely dysregulated genes
  657. VP <- ggplot(BIAD03_unique, aes(avg_log2FC, log10p_adj, label=delabel, color=diffexpressed)) + geom_point(alpha = 1, size = 3, fill = "grey90") + ## transform to change the order of the plots in facet_wrap()
  658. theme_light() +
  659. scale_fill_gradientn(colours = c(rainbow(100)), ## colors in the scale
  660. breaks = seq(0, 1, 0.2),
  661. limits = c(0, 1)) +
  662. scale_color_manual(values = c("grey60","blue","red")) +
  663. geom_text_repel(data=BIAD03_unique, size = 8, max.overlaps = 75, direction = "both") +
  664. theme(legend.position = "right", axis.text.x = element_text(size = 28), axis.text.y = element_text(size = 28), axis.title.x = element_text(size = 30), axis.title.y = element_text(size = 30), panel.border = element_rect(fill=NA, colour = "black", size=0.5)) +
  665. labs(y=expression('-Log'[10]*' P'[adj]), x=expression(atop('Log'[2]*' fold change', paste("[MPSIIIA/Control]")))) +
  666. scale_x_continuous(breaks = seq(-7, 7, by = 2)) +
  667. scale_y_continuous(breaks = seq(0, 90, by = 20)) +
  668. coord_cartesian(xlim = c(-7, 7), ylim = c(0, 80)) +
  669. geom_hline(yintercept = -log10(0.05), linetype = "dashed", col = "darkgrey", size = 1) + NoLegend()
  670. VP
  671. ggsave(VP, filename = paste0(resultsdirectory,"/plots/revisions_120D/DE_120D/20251203_VP_BIAD03_ENs_GeneExpression_nodonordownsample.pdf"), height = 10, width = 10, dpi = 300)
  672. # pathways of DEGs for BIAD03 ENs
  673. library(msigdbr)
  674. library(org.Hs.eg.db)
  675. library(enrichplot)
  676. library(clusterProfiler)
  677. library(DOSE)
  678. library(simplifyEnrichment)
  679. library(GOSemSim)
  680. ## Create a vector of all gene names in count matrix to use as background set of genes
  681. all_genes <- as.matrix(excitatory_only@assays[["RNA"]]@layers[["counts"]])
  682. rownames(all_genes) <- rownames(excitatory_only@assays[['RNA']])
  683. all_genes <- row.names(all_genes)
  684. # Create vector of gene names that are significantly dysregulated for GO enrichment
  685. geneList <- BIAD03_unique_upreg$hgnc_symbol # swap this between upreg and downreg genes
  686. test_enrichment <- enrichGO(gene = geneList, # make sure it's running for either the excitatory list or inhibitory
  687. OrgDb = 'org.Hs.eg.db',
  688. keyType = 'SYMBOL',
  689. ont = 'BP',
  690. universe = all_genes,
  691. pvalueCutoff = 0.05,
  692. pAdjustMethod = 'BH',
  693. qvalueCutoff = 0.1,
  694. minGSSize = 10,
  695. maxGSSize = 500,
  696. readable = TRUE)
  697. go_id <- test_enrichment@result$ID
  698. GO_pathways <- dotplot(test_enrichment, showCategory = 20)
  699. GO_pathways
  700. ggsave(GO_pathways, filename = paste0(resultsdirectory,"/plots/revisions_120D/DE_120D/20251207_BIAD03_Pathways-upregDEGs.pdf"), height = 10, width = 7, dpi = 300)
  701. ## SOX2 expression per donor
  702. cortical_mark <- c("SOX2")
  703. control_matrix <- GetAssayData(object = Sanfilippo_120D,
  704. assay = "RNA",
  705. layer = "counts")
  706. control_matrix <- as.matrix(control_matrix)
  707. control_matrix <- control_matrix[cortical_mark,, drop = F]
  708. control_matrix <- as.data.frame(t(control_matrix))
  709. control_matrix$BIAD_id[match(rownames(control_matrix), rownames([email hidden]))] <- Sanfilippo_120D$BIAD_id[match(rownames(control_matrix),rownames([email hidden]))]
  710. control_matrix$condition[match(rownames(control_matrix), rownames([email hidden]))] <- Sanfilippo_120D$orig.ident[match(rownames(control_matrix),rownames([email hidden]))]
  711. MPSIIIA_matrix <- control_matrix[control_matrix$condition == "Sanfilippo_120D",]
  712. control_matrix <- control_matrix[control_matrix$condition == "Control_120D",]
  713. control_matrix_noexp <- control_matrix[rowSums(control_matrix[1]) == 0,]
  714. MPSIIIA_matrix_noexp <- MPSIIIA_matrix[rowSums(MPSIIIA_matrix[1]) == 0,]
  715. SOX2_gene_prop <- data.frame("Control_Number" = colSums(control_matrix > 0), "Control_Percent" = (colSums(control_matrix > 0)/nrow(control_matrix))*100,"MPSIIIA_Number" = colSums(MPSIIIA_matrix > 0), "MPSIIIA_Percent" = (colSums(MPSIIIA_matrix > 0)/nrow(MPSIIIA_matrix))*100)
  716. control_gene_prop_per_donor <- control_matrix |>
  717. group_by(BIAD_id) |>
  718. summarize(n = n(),
  719. across(-n, ~sum(. > 0)))
  720. control_gene_prop_per_donor$pct_expressing <- (control_gene_prop_per_donor$SOX2/control_gene_prop_per_donor$n)*100
  721. control_gene_prop_per_donor$condition <- "Healthy"
  722. control_gene_prop_per_donor$DIV <- "120D"
  723. MPSIIIA_gene_prop_per_donor <- MPSIIIA_matrix |>
  724. group_by(BIAD_id) |>
  725. summarize(n = n(),
  726. across(-n, ~sum(. > 0)))
  727. MPSIIIA_gene_prop_per_donor$pct_expressing <- (MPSIIIA_gene_prop_per_donor$SOX2/MPSIIIA_gene_prop_per_donor$n)*100
  728. MPSIIIA_gene_prop_per_donor$condition <- "MPSIIIA"
  729. MPSIIIA_gene_prop_per_donor$DIV <- "120D"
  730. av_exp_120D <- AggregateExpression(Sanfilippo_120D, features = "SOX2", group.by = c("BIAD_id"), assays = "RNA", slot = "counts")
  731. av_exp_120D <- as.data.frame(t(av_exp_120D$RNA))
  732. colnames(av_exp_120D) <- "SOX2_sum_exp"
  733. av_exp_120D$BIAD_id <- rownames(av_exp_120D)
  734. cortical_gene_prop_per_donor <- rbind(control_gene_prop_per_donor, MPSIIIA_gene_prop_per_donor)
  735. rownames(cortical_gene_prop_per_donor) <- cortical_gene_prop_per_donor$BIAD_id
  736. cortical_gene_prop_per_donor <- merge(cortical_gene_prop_per_donor, av_exp_120D, by = "BIAD_id")
  737. write.csv(cortical_gene_prop_per_donor, file = paste0(resultsdirectory, "/sheets/revisions_120D/Control_MPSIIIA_neurons_cortical_SOX2gene_prop_per_donor_nodownsample.csv"))
  738. ```
  739. 6. ***Look at proportion of neurons at 30DIV to address reviewer concerns about uneven proportions at 120D***
  740. ```{Assessing expression of key synaptic genes in 30DIV data}
  741. ### LOAD 30 DAY DATA ###
  742. ## Load required datasets
  743. load(file = paste0(datadirectory, "/RData/30D/Combined_Control_MPSIIIA_30D.RData"))
  744. tbl <- [email hidden] %>% group_by(orig.ident) %>% summarise(n = n())
  745. tbl
  746. Idents(Combined_Healthy_MPSIIIA) <- 'orig.ident'
  747. Combined_Healthy_MPSIIIA <- subset(Combined_Healthy_MPSIIIA, downsample = 4444)
  748. [email hidden] %>% group_by(orig.ident) %>% summarise(n = n())
  749. # Sort into excitatory and inhibitory neurons
  750. Combined_30D_neurons <- subset(Combined_Healthy_MPSIIIA, idents = c('Control_30D', 'Sanfilippo_30D'))
  751. table(Combined_30D_neurons$orig.ident)
  752. Idents(Combined_30D_neurons) <- "final_cell_type"
  753. Combined_30D_neurons <- subset(Combined_30D_neurons, idents = c('Excitatory', 'Inhibitory'))
  754. Idents(Combined_30D_neurons) <- 'orig.ident'
  755. Combined_30D_neurons <- subset(Combined_30D_neurons, downsample = 1952)
  756. # Donor proportions for excitatory and inhibitory neurons - Supp Fig 20A #
  757. tbl <- [email hidden] %>% group_by(orig.ident, BIAD_id, final_cell_type) %>% summarise(n = n())
  758. tbl
  759. write.csv(tbl, file = paste0(resultsdirectory, "/sheets/revisions_120D/DE_120D/20250612_30DIV_neuron-types_biad-id_nodwonsample.csv"))
  760. ```

Differential_Expression_Analysis_120D.Rmd at commit 04a5121, no license · at the source

Overview

  1. Laboratory for Human Neurophysiology and Genetics, South Australian Health and Medical Research Institute (SAHMRI),Adelaide, SA Australia
  2. Flinders Health and Medical Research Institute, College of Medicine and Public Health, Flinders University,Adelaide, SA Australia
  3. Sanfilippo Children’s Foundation, Sydney, NSW Australia
  4. Childhood Dementia Initiative, Sydney, NSW Australia
  5. School of Biomedicine, Adelaide University,Adelaide, SA Australia
  6. Institute for Photonic and Advanced Sensing, Adelaide University,Adelaide, SA Australia
  7. Cure Sanfilippo Foundation, Columbia, SC USA
  8. Department of Neurology and Clinical Neurophysiology, Women’s and Children’s Health Network,Adelaide, SA Australia
  9. Paediatric Neurodegenerative Disease Research Group, Discipline of Paediatrics, College of Health, Adelaide University,Adelaide, SA Australia
  10. Brain Organoid Therapeutics, Adelaide, SA Australia
Journal: Nature communications, volume 17, issue 1, article 3161
Dates: received 12 September 2024; accepted 13 March 2026; published online 7 April 2026
Type: Research article · Language: English
License: CC BY-NC-ND
Identifiers: DOI 10.1038/s41467-026-71112-9 · PMID 41946741 · PMCID PMC13057175 · OpenAlex W7151452559
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: intracellular / patch clamp (modality), human (organism), Alzheimer's / dementia (population), cellular / molecular (subfield)
Methods: Spectral & time-frequency, Statistics, Smoothing, state filtering, decompositions, Machine learning, Preprocessing, Evoked potentials, Single-unit activity, calcium imaging
Keywords: Cellular neuroscience, Phenotypic screening, Patch clamp, Paediatric neurological disorders, Induced pluripotent stem cells
MeSH: Cerebral Cortex*, Dementia*, Induced Pluripotent Stem Cells*, Mucopolysaccharidosis III*, Synapses*, Action Potentials, Child, Humans, Nerve Net, Neurons (* major topic)
Topic: Lysosomal Storage Disorders Research (Physiology, Medicine), according to OpenAlex
Citations: cited by 1 paper (Europe PMC); 128 references in the paper

Abstract

The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.

Repository

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

bardylab/MPSIIIA_snRNAseq_Synaptic_Paper_2026

License: none: the authors keep all their rights
State: the link answers, verified on 29 September 2026
Evidence: files inventoried
Commit: 04a512141b0b5beeb0fe7b925e8b3186311d53a9, 12 February 2026
Languages: R (3)
Size: 12 files, 3 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, 3 notebooks
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: ggplot2 (3 files), Seurat (3 files), tidyverse (3 files), clusterProfiler (1 file), data.table (1 file), Harmony (1 file), patchwork (1 file)
Availability: 1 check, the latest on 29 September 2026: the link answers
  • 29 September 2026: the link answers
4 files

Code availability statement

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

Read it in the paper: doi.org/10.1038/s41467-026-71112-9.

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:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 3 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

No dataset and no data link were found in the paper.

Data availability statement

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

  • it says that the data are available on request

Read it in the paper: doi.org/10.1038/s41467-026-71112-9.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 29 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 20 authors, 5 keywords, 10 MeSH terms, 2 funders, 128 references.

Cite

This paper

Mazzachi, P., McDonald, E., Greenberg, Z., Puerta, A. N., Tran, J., De Silva, M. I., Christensen, C., Adams, R., Loskarn, S., Beard, H., Zabolocki, M., Elmasri, M., Maack, M., Elvidge, K. L., Hutchinson, M. R., O’Neill, C., Hemsley, K. M., Melton, L., Smith, N., & Bardy, C. (2026). Modelling synaptic dysfunction in childhood dementia using human iPSC-derived cortical networks. Nature communications, 17(1), 3161. https://doi.org/10.1038/s41467-026-71112-9

BibTeX

@article{mazzachi2026modelling,
author = {Mazzachi, Paris and McDonald, Ella and Greenberg, Zarina and Puerta, Alejandra Noreña and Tran, Jenne and De Silva, Manam Inushi and Christensen, Cade and Adams, Robert and Loskarn, Sebastian and Beard, Helen and Zabolocki, Michael and Elmasri, Meera and Maack, Megan and Elvidge, Kristina L. and Hutchinson, Mark R. and O’Neill, Cara and Hemsley, Kim M. and Melton, Lisa and Smith, Nicholas and Bardy, Cedric},
title = {{Modelling synaptic dysfunction in childhood dementia using human iPSC-derived cortical networks}},
journal = {Nature communications},
year = {2026},
month = apr,
volume = {17},
number = {1},
pages = {3161},
publisher = {Nature Publishing Group},
issn = {2041-1723},
doi = {10.1038/s41467-026-71112-9},
url = {https://doi.org/10.1038/s41467-026-71112-9},
pmid = {41946741},
pmcid = {PMC13057175}
}

RIS

TY - JOUR
AU - Mazzachi, Paris
AU - McDonald, Ella
AU - Greenberg, Zarina
AU - Puerta, Alejandra Noreña
AU - Tran, Jenne
AU - De Silva, Manam Inushi
AU - Christensen, Cade
AU - Adams, Robert
AU - Loskarn, Sebastian
AU - Beard, Helen
AU - Zabolocki, Michael
AU - Elmasri, Meera
AU - Maack, Megan
AU - Elvidge, Kristina L.
AU - Hutchinson, Mark R.
AU - O’Neill, Cara
AU - Hemsley, Kim M.
AU - Melton, Lisa
AU - Smith, Nicholas
AU - Bardy, Cedric
TI - Modelling synaptic dysfunction in childhood dementia using human iPSC-derived cortical networks
T2 - Nature communications
J2 - Nat Commun
PY - 2026
DA - 2026/04/07
VL - 17
IS - 1
SP - 3161
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/s41467-026-71112-9
UR - https://doi.org/10.1038/s41467-026-71112-9
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41467-026-71112-9",
"type": "article-journal",
"title": "Modelling synaptic dysfunction in childhood dementia using human iPSC-derived cortical networks",
"container-title": "Nature communications",
"author": [
{
"family": "Mazzachi",
"given": "Paris"
},
{
"family": "McDonald",
"given": "Ella"
},
{
"family": "Greenberg",
"given": "Zarina"
},
{
"family": "Puerta",
"given": "Alejandra Noreña"
},
{
"family": "Tran",
"given": "Jenne"
},
{
"family": "De Silva",
"given": "Manam Inushi"
},
{
"family": "Christensen",
"given": "Cade"
},
{
"family": "Adams",
"given": "Robert"
},
{
"family": "Loskarn",
"given": "Sebastian"
},
{
"family": "Beard",
"given": "Helen"
},
{
"family": "Zabolocki",
"given": "Michael"
},
{
"family": "Elmasri",
"given": "Meera"
},
{
"family": "Maack",
"given": "Megan"
},
{
"family": "Elvidge",
"given": "Kristina L."
},
{
"family": "Hutchinson",
"given": "Mark R."
},
{
"family": "O’Neill",
"given": "Cara"
},
{
"family": "Hemsley",
"given": "Kim M."
},
{
"family": "Melton",
"given": "Lisa"
},
{
"family": "Smith",
"given": "Nicholas"
},
{
"family": "Bardy",
"given": "Cedric"
}
],
"container-title-short": "Nat Commun",
"volume": "17",
"issue": "1",
"page": "3161",
"DOI": "10.1038/s41467-026-71112-9",
"PMID": "41946741",
"PMCID": "PMC13057175",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41467-026-71112-9",
"language": "en",
"issued": {
"date-parts": [
[
2026,
4,
7
]
]
}
}

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

Similar papers

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

[1] doi:10.1038/s41467-026-76837-1 [code]
Drug screen and machine learning predict neuroprotective agents in a preclinical human model of childhood dementia.
Journal: Nature communications
In common: Harmony, clusterProfiler, Seurat, 3 other tools, Alzheimer's / dementia, 34 references, 13 authors
[2] doi:10.1093/bib/bbag175 [code]
Uncovering causal relationships in single-cell omic studies with causarray.
Journal: Briefings in bioinformatics
In common: Harmony, clusterProfiler, Seurat, 4 other tools, Alzheimer's / dementia, 2 references
[3] doi:10.1038/s41467-026-71595-6 [code]
A single-cell and spatial atlas of early human olfactory development.
Journal: Nature communications
In common: Harmony, Seurat, patchwork, 2 other tools, 4 references
[4] doi:10.1038/s41593-026-02367-0 [code]
A reproducible three-dimensional model of human brain tissue to investigate physiological and disease-associated microglia phenotypes.
Journal: Nature neuroscience
In common: Harmony, clusterProfiler, Seurat, 4 other tools, Alzheimer's / dementia, cellular / molecular, 2 references
[5] doi:10.1038/s41586-026-10877-x [code]
Human brain organoids record the passage of time over multiple years.
Journal: Nature
In common: Harmony, Seurat, data.table, 2 other tools, 4 references
[6] doi:10.1002/alz.71823 [code]
Cellular transcriptomic signatures underpinning the heterogeneity of depression in Alzheimer's disease.
Journal: Alzheimer's & dementia : the journal of the Alzheimer's Association
In common: Harmony, Seurat, data.table, 3 other tools, Alzheimer's / dementia, cellular / molecular, 2 references
[7] doi:10.1038/s41586-026-10214-2 [code]
Multidimensional profiling of heterogeneity in supratentorial ependymomas.
Journal: Nature
In common: Harmony, clusterProfiler, Seurat, 4 other tools, 2 references
[8] 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: Harmony, clusterProfiler, Seurat, 4 other tools, cellular / molecular, 1 reference
[9] 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: clusterProfiler, Seurat, data.table, 3 other tools, 2 references
[10] doi:10.1016/j.cell.2026.05.026 [code]
The critical role of the endogenous immune compartment after CAR T cell therapy in recurrent GBM.
Journal: Cell
In common: Harmony, clusterProfiler, Seurat, 4 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.