OSCR

TNF-α induces type I IFN signalling to suppress neurogenesis and recruit T cells.

Code ↔ Paper

7 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 7 matches
  1. [1] § Methods › Normalisation, dimensionality reduction, and clustering ↔ scripts/02_normalisation_and_clustering.Rmd, lines 67–79 · score 0.80 · FindClusters, FindNeighbors, RunUMAP, neighbour, resolutions, dims
  2. [2] § Results › Chronic TNF-α disrupts neuronal differentiation and upregulates a transcriptional type I IFN signature ↔ scripts/03_analysis.Rmd, lines 544–578 · score 0.76 · IFN responsive glial, wound healing, immature neuron, reactive astrocyte, IPC, RGL
  3. [3] § Results › Chronic TNF-α disrupts neuronal differentiation and upregulates a transcriptional type I IFN signature ↔ scripts/03_analysis.Rmd, lines 544–578 · score 0.67 · IFN responsive glial, wound healing, reactive astrocyte, high TNF, IPC, RGL
  4. [4] § Methods › Quality control ↔ scripts/01_load_and_qc.Rmd, lines 401–410 · score 0.66 · mitochondrial gene expression, novelty score, quality cells, QC
  5. [5] § Results › Chronic TNF-α disrupts neuronal differentiation and upregulates a transcriptional type I IFN signature ↔ scripts/03_analysis.Rmd, lines 171–178 · score 0.61 · S100B, AQP4, CD44, CLU, GFAP, ID4
  6. [6] § Results › Chronic TNF-α disrupts neuronal differentiation and upregulates a transcriptional type I IFN signature ↔ scripts/03_analysis.Rmd, lines 146–169 · score 0.61 · Stacked bar, Cluster proportions, low TNF, high TNF, UMAP, treatment
  7. [7] § Methods › Gene module scoring for human immature dentate granule cell signature ↔ scripts/03_analysis.Rmd, lines 181–204 · score 0.51 · AddModuleScore, immature, scored, human, signature, genes

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 · 1,162 lines · 43 KB · MIT · 5 matches

  1. ---
  2. title: "03 Analysis"
  3. output: html_document
  4. ---
  5. ```{r setup, include=FALSE}
  6. # If running interactively from within /scripts, move up to project root
  7. # If running interactively from within /scripts, move up to project root
  8. if (basename(getwd()) == "scripts") setwd("..")
  9. # Now we are in the project root
  10. knitr::opts_knit$set(root.dir = normalizePath("."))
  11. knitr::opts_chunk$set(echo = FALSE, message = FALSE, warning = FALSE)
  12. source("scripts/00_setup.R")
  13. ```
  14. # Load the seurat object
  15. ```{r}
  16. # load diff
  17. seurat_pipeline_cluster <- readRDS(file.path(RESULTS_DIR, "seurat_pipeline_cluster.rds"))
  18. seurat_pipeline_cluster$active_ident <- Idents(seurat_pipeline_cluster)
  19. ```
  20. # generating figure 2b
  21. ```{r}
  22. new_order <- c("Astro-like 1", "Astro-like 2", "Astro-like 3", "Astro-like 4", "RGL-like 1", "RGL-like 2", "IPC-like 1", "IPC-like 2", "IPC-like 3", "IPC-like 4", "Neuroblast-like", "Immature neuron-like", "IFN-responsive glial/progenitor-like", "Reactive astrocyte-like", "Wound healing-like")
  23. seurat_pipeline_cluster <- SetIdent(seurat_pipeline_cluster, value = factor(Idents(seurat_pipeline_cluster), levels = new_order))
  24. colors_UMAP <- c(
  25. "#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2",
  26. "#E55AA4", "#43BDB2", "#EECAA4", "#050B8D", "#FF6347",
  27. "#9C73B4", "#B3D500", "#27601C", "#DC95E3", "#995D07")
  28. UMAP_plot <- DimPlot(seurat_pipeline_cluster, cols = colors_UMAP) + labs(x = "UMAP1", y = "UMAP2")
  29. ggsave(filename = "Fig2b.pdf", path =FIGURES_DIR , plot = UMAP_plot, width = 200, height = 100, device = cairo_pdf, units = "mm")
  30. ```
  31. # generating figure 2c
  32. Add timepoint to metadata:
  33. ```{r}
  34. # Make a new metadata column
  35. seurat_pipeline_cluster$timepoint <- 'Time'
  36. # Fix meta data
  37. metadata_seurat_pipeline_cluster <- [email hidden] %>%
  38. mutate(Time = case_when(
  39. sample.ID == "Proliferation control" ~ "Proliferation (2 days)",
  40. sample.ID == "Proliferation low TNF" ~ "Proliferation (2 days)",
  41. sample.ID == "Proliferation high TNF" ~ "Proliferation (2 days)",
  42. sample.ID == "Differentiation control (7 days)" ~ "Differentiation (7 days)",
  43. sample.ID == "Differentiation low TNF (7 days)" ~ "Differentiation (7 days)",
  44. sample.ID == "Differentiation high TNF (7 days)" ~ "Differentiation (7 days)",
  45. sample.ID == "Differentiation control (14 days)" ~ "Differentiation (14 days)",
  46. sample.ID == "Differentiation low TNF (14 days)" ~ "Differentiation (14 days)",
  47. sample.ID == "Differentiation high TNF (14 days)" ~ "Differentiation (14 days)"))
  48. # Add new metadata
  49. [email hidden] <- metadata_seurat_pipeline_cluster
  50. ```
  51. Add treatment column
  52. ```{r}
  53. # Make a new metadata column
  54. seurat_pipeline_cluster$treatment <- NULL
  55. # Fix meta data
  56. metadata_seurat_pipeline_cluster <- [email hidden] %>%
  57. mutate(treatment = case_when(
  58. sample.ID == "Proliferation control" ~ "Control",
  59. sample.ID == "Proliferation low TNF" ~ "Low TNF",
  60. sample.ID == "Proliferation high TNF" ~ "High TNF",
  61. sample.ID == "Differentiation control (7 days)" ~ "Control",
  62. sample.ID == "Differentiation low TNF (7 days)" ~ "Low TNF",
  63. sample.ID == "Differentiation high TNF (7 days)" ~ "High TNF",
  64. sample.ID == "Differentiation control (14 days)" ~ "Control",
  65. sample.ID == "Differentiation low TNF (14 days)" ~ "Low TNF",
  66. sample.ID == "Differentiation high TNF (14 days)" ~ "High TNF"))
  67. # Add new metadata
  68. [email hidden] <- metadata_seurat_pipeline_cluster
  69. ```
  70. Take a look at number of cells belonging to each cluster by line and timepoint. For this we make a contingency table.
  71. ```{r}
  72. Prol <- subset(seurat_pipeline_cluster, Time =="Proliferation (2 days)")
  73. Dif7 <- subset(seurat_pipeline_cluster,Time == "Differentiation (7 days)")
  74. Dif14 <- subset(seurat_pipeline_cluster,Time == "Differentiation (14 days)")
  75. Idents(Prol) <- "active_ident"
  76. Idents(Dif7) <- "active_ident"
  77. Idents(Dif14) <- "active_ident"
  78. ```
  79. Look at cell frequencies in each sample:
  80. ```{r}
  81. table(Idents(Prol), Prol$treatment)
  82. table(Idents(Dif7), Dif7$treatment)
  83. table(Idents(Dif14), Dif14$treatment)
  84. to_df <- function(df) {
  85. df %>%
  86. as.data.frame() %>%
  87. as_tibble() %>%
  88. dplyr::rename("active_ident"=Var1,"treatment"=Var2,"count"=Freq) %>%
  89. arrange(active_ident)
  90. }
  91. ```
  92. Turn frequency tables into tidy data
  93. ```{r}
  94. Prol <- table(Idents(Prol), Prol$treatment) %>%
  95. to_df() %>%
  96. mutate(sample = "2-Day Proliferation")
  97. Dif7 <- table(Idents(Dif7), Dif7$treatment) %>%
  98. to_df() %>%
  99. mutate(sample = "7-Day Differentiation")
  100. Dif14 <- table(Idents(Dif14), Dif14$treatment) %>%
  101. to_df() %>%
  102. mutate(sample = "14-Day Differentiation")
  103. my_data <- Prol %>%
  104. bind_rows(Dif7) %>%
  105. bind_rows(Dif14) %>%
  106. mutate(active_ident = factor(active_ident,
  107. levels=c("Astro-like 1","Astro-like 2","Astro-like 3","Astro-like 4","RGL-like 1","RGL-like 2","IPC-like 1","IPC-like 2", "IPC-like 3","IPC-like 4", 'Neuroblast-like', 'Immature neuron-like', 'IFN-responsive glial/progenitor-like', 'Reactive astrocyte-like', 'Wound healing-like'))) %>%
  108. mutate(sample = factor(sample,levels = c("2-Day Proliferation",
  109. "7-Day Differentiation",
  110. "14-Day Differentiation")))
  111. ```
  112. Make stacked bar plots of cell type proportions
  113. ```{r}
  114. my_data <- my_data %>%
  115. mutate(treatment = factor(treatment, levels = c("High TNF", "Low TNF", "Control")))
  116. bar_plot <- my_data %>%
  117. ggplot(aes(y=count,x=treatment,fill=active_ident)) +
  118. geom_bar(position="fill",stat="identity") +
  119. coord_flip() +
  120. scale_fill_manual(values = colors_UMAP,name="") +
  121. scale_y_continuous(expand = c(0,0),
  122. labels = percent_format()) +
  123. facet_wrap(~sample,ncol = 1) +
  124. theme(axis.line.y = element_blank(),
  125. axis.text.y = element_text(size = 10, color = "black", face = "bold"),
  126. axis.ticks.y = element_blank(),
  127. strip.text = element_text(size = 10,face = "bold")) +
  128. labs(x="",y="Cluster Proportion") +
  129. theme(plot.margin = margin(0,1,0.5,0, "cm"),panel.grid.major = element_blank(), panel.grid.minor = element_blank(),panel.background = element_blank(),plot.background = element_blank() )
  130. ggsave(filename = "Fig2c.pdf", path =FIGURES_DIR , plot = bar_plot, width = 200, height = 120, device = cairo_pdf, units = "mm")
  131. ```
  132. # generating figure 2d
  133. ```{r}
  134. all_markers <- c('AQP4','S100B', 'GFAP', 'BCAN', 'CLU', 'ID4', 'FABP7', 'PTN', 'CDH4', 'CD44' ,'HES1','STMN1', 'MKI67', 'HMGB2','DCX','IGFBPL1' ,'PROX1','MAP2', 'NRXN3', 'TUBB3','SYNPR', 'DSCAM', 'CALB2')
  135. dotplot <- DotPlot_scCustom(seurat_pipeline_cluster,features = all_markers, x_lab_rotate = TRUE)
  136. ggsave(filename = "Fig2d.pdf", path =FIGURES_DIR , plot = dotplot, width = 240, height = 120, device = cairo_pdf, units = "mm")
  137. ```
  138. #generating figure 2e
  139. ```{r}
  140. human_genes <- read.csv("scripts/NIHMS1815814-supplement-1815814_Tab_4.csv")
  141. top_twenty <- human_genes[1:20, ]
  142. top_twenty_genes <- top_twenty$Gene
  143. seurat_pipeline_cluster <- AddModuleScore(
  144. seurat_pipeline_cluster,
  145. features = list(top_twenty_genes),
  146. name = c('Immature DG cell signature'),
  147. search = TRUE,
  148. )
  149. Immature_DG <- FeaturePlot_scCustom(
  150. seurat_pipeline_cluster,
  151. features = "Immature DG cell signature1",
  152. colors_use = viridis_plasma_dark_high,
  153. na_color = "grey90",
  154. na_cutoff = 0.15) + xlab('UMAP1') + ylab('UMAP2') + theme(plot.title = element_text(hjust = 0.5)) + coord_fixed() + ggtitle('Human imGCs signature')
  155. ggsave(filename = "Fig2e.pdf", path =FIGURES_DIR , plot = Immature_DG, width = 200, height =200, device = cairo_pdf, units = "mm")
  156. ```
  157. # generating figure 2f-g
  158. ```{r}
  159. DefaultAssay(seurat_pipeline_cluster) <- "SCT"
  160. seurat_pipeline_cluster <- PrepSCTFindMarkers(seurat_pipeline_cluster)
  161. markers_clusters <-FindAllMarkers(seurat_pipeline_cluster,assay = 'SCT', only.pos = TRUE, min.pct=0.25, test.use = "wilcox", logfc.threshold = 0.25)
  162. markers_clusters %>% group_by(cluster) %>% arrange(desc(avg_log2FC)) %>% slice_head(n = 20) %>% ungroup() -> top20
  163. ```
  164. ```{r}
  165. # get topp 100 genes from neuroblast and immature neuronal cluster
  166. neuroblast_top_100 <- markers_clusters %>% filter(cluster == 'Neuroblast-like') %>% arrange(desc(avg_log2FC)) %>% top_n(100, wt = avg_log2FC)
  167. neuro_top_100 <- markers_clusters %>% filter(cluster == 'Immature neuron-like') %>% arrange(desc(avg_log2FC)) %>% top_n(100, wt = avg_log2FC)
  168. # getting the genes
  169. neuroblast_genes <- neuroblast_top_100$gene
  170. neuro_genes <- neuro_top_100$gene
  171. # convert gene symbols to entrez IDs
  172. entrez_ids_neuroblast <- bitr(neuroblast_genes,
  173. fromType = "SYMBOL",
  174. toType = "ENTREZID",
  175. OrgDb = org.Hs.eg.db)
  176. entrez_ids_neuro<- bitr(neuro_genes,
  177. fromType = "SYMBOL",
  178. toType = "ENTREZID",
  179. OrgDb = org.Hs.eg.db)
  180. ```
  181. ```{r}
  182. # run GO enrinchment - BP
  183. go_results_neuroblasts <- enrichGO(gene = entrez_ids_neuroblast$ENTREZID,
  184. OrgDb = org.Hs.eg.db,
  185. keyType = "ENTREZID",
  186. ont = "BP", # Can be "BP", "MF", or "CC"
  187. pAdjustMethod = "BH",
  188. pvalueCutoff = 0.05,
  189. qvalueCutoff = 0.2,
  190. readable = TRUE)
  191. go_results_neuro <- enrichGO(gene = entrez_ids_neuro$ENTREZID,
  192. OrgDb = org.Hs.eg.db,
  193. keyType = "ENTREZID",
  194. ont = "BP", # Can be "BP", "MF", or "CC"
  195. pAdjustMethod = "BH",
  196. pvalueCutoff = 0.05,
  197. qvalueCutoff = 0.2,
  198. readable = TRUE)
  199. ```
  200. Make dotplots
  201. ```{r}
  202. neuroblast_bb <- dotplot(go_results_neuroblasts, showCategory = 15)
  203. ggsave(filename = "Fig2f.pdf", path = FIGURES_DIR , plot = neuroblast_bb, width = 200, height =200, device = cairo_pdf, units = "mm")
  204. ```
  205. ```{r}
  206. neuro_bb <-dotplot(go_results_neuro, showCategory = 15)
  207. ggsave(filename = "Fig2g.pdf", path = FIGURES_DIR , plot = neuro_bb, width = 200, height =200, device = cairo_pdf, units = "mm")
  208. ```
  209. # generating figure 2h
  210. ```{r}
  211. # Step 1: Subset to 7d and 14d differentiation samples
  212. diff_cells <- subset(seurat_pipeline_cluster, subset = Time %in% c("Differentiation (7 days)", "Differentiation (14 days)"))
  213. # Step 2: Subset only neuroblast and immature neurons
  214. target_cells <- [email hidden] %>%filter(active_ident %in% c("Neuroblast-like", "Immature neuron-like"))
  215. # Step 3: Count cells per treatment and type
  216. counts <- target_cells %>%
  217. group_by(treatment, active_ident) %>%
  218. summarise(n = n(), .groups = "drop")
  219. # Step 4: Get total number of cells per condition (in differentiation samples)
  220. total_per_condition <- [email hidden] %>%
  221. group_by(treatment) %>%
  222. summarise(total = n(), .groups = "drop")
  223. # Step 5: Merge counts and total, compute percentages
  224. counts <- left_join(counts, total_per_condition, by = "treatment") %>%
  225. mutate(percent = (n / total) * 100)
  226. counts$treatment <- factor(counts$treatment, levels = c("Control", "Low TNF", "High TNF"))
  227. # Step 6: Plot
  228. treatment_neurogenesis <- ggplot(counts, aes(x = treatment, y = percent, fill = active_ident)) +
  229. geom_bar(stat = "identity", position = "stack") +
  230. labs(x = "Treatment", y = "Percentage of cells in neurogenic clusters", fill = "Cluster") +
  231. scale_fill_manual(values = c("Neuroblast-like" = "#9C73B4", "Immature neuron-like" = "#B3D500")) +
  232. theme_minimal() + theme(
  233. axis.text.x = element_text(face = "bold"),
  234. axis.title.y = element_text(face = "bold"))
  235. ggsave(filename = "Fig2h.pdf", path = FIGURES_DIR , plot = treatment_neurogenesis, width = 200, height =200, device = cairo_pdf, units = "mm")
  236. ```
  237. # generate figure 3a
  238. Generate heatmap comparing RGL vs. RGL immune
  239. ```{r}
  240. # Use then SCT assay - find markers expressed in minimum 25% of cells in the cluster
  241. RGL_vs_RGL_immune <-FindMarkers(seurat_pipeline_cluster,ident.1 = 'RGL-like 2', ident.2 = 'RGL-like 1', assay = 'SCT', only.pos = TRUE, min.pct=0.25, test.use = "wilcox", logfc.threshold = 0.25) %>% rownames_to_column(var = "gene")
  242. # get the data from the top 40 genes in each cluster based on avg_log2FC
  243. RGL_vs_RGL_immune %>% arrange(desc(avg_log2FC)) %>% slice_head(n = 40) %>% ungroup() -> top40_RGL_vs_RGL_immune
  244. RGL_heatmap_genes <- top40_RGL_vs_RGL_immune$gene
  245. # subset the seurat object
  246. RGL_all <- subset(seurat_pipeline_cluster, idents = c('RGL-like 2', 'RGL-like 1'))
  247. # colors to use
  248. colors_RGL_heatmap <- c( "#0072B2", "#E55AA4")
  249. # do heatmap - genes expressed in 25% of cells
  250. heatmap_RGL_vs_RGL_immune <- DoHeatmap(RGL_all, features = RGL_heatmap_genes, assay = 'SCT', slot = "scale.data",label = FALSE, group.colors = colors_RGL_heatmap)
  251. # save the plot
  252. ggsave(filename = "Fig3a.pdf", path = FIGURES_DIR , plot = heatmap_RGL_vs_RGL_immune, width = 200, height =200, device = cairo_pdf, units = "mm")
  253. ```
  254. # generate figure 3b
  255. ```{r}
  256. # Use then SCT assay - find markers expressed in minimum 25% of cells in the cluster
  257. IPC_TNF_vs_IPCs <-FindMarkers(seurat_pipeline_cluster,ident.1 = 'IPC-like 4', ident.2 = c('IPC-like 1', 'IPC-like 2', 'IPC-like 3'), assay = 'SCT', only.pos = TRUE, min.pct=0.25, test.use = "wilcox", logfc.threshold = 0.25) %>% rownames_to_column(var = "gene")
  258. # get the data from the top 40 genes in each cluster based on avg_log2FC
  259. IPC_TNF_vs_IPCs %>% arrange(desc(avg_log2FC)) %>% slice_head(n = 40) %>% ungroup() -> topIPC_TNF_vs_IPCs
  260. IPC_heatmap_genes <- topIPC_TNF_vs_IPCs$gene
  261. # subset the seurat object
  262. IPC_all <- subset(seurat_pipeline_cluster, idents = c('IPC-like 1', 'IPC-like 2', 'IPC-like 3', 'IPC-like 4'))
  263. # colors to use
  264. colors_IPC_heatmap <- c("#43BDB2", "#EECAA4", "#050B8D", "#FF6347")
  265. # do heatmap - genes expressed in 25% of cells
  266. heatmap_IPC_vs_IPC_immune <- DoHeatmap(IPC_all, features = IPC_heatmap_genes, assay = 'SCT', slot = "scale.data",label = FALSE, group.colors = colors_IPC_heatmap)
  267. # save the plot
  268. ggsave(filename = "Fig3b.pdf", path = FIGURES_DIR , plot = heatmap_IPC_vs_IPC_immune, width = 200, height =200, device = cairo_pdf, units = "mm")
  269. ```
  270. # generate figure 3c
  271. ```{r}
  272. IFN_genes <- c('MX1', 'ISG15', 'OAS1', 'OAS2', 'IFI6', 'IFI27', 'IFI35','IFI44', 'IFI44L','IFI16', 'IFIT1', 'IFIT3', 'STAT1', 'STAT2', 'TRIM22', 'BST2', 'CXCL10','IFITM1', 'IFITM3', 'B2M', 'IL32', 'HLA-B')
  273. IFN_dotplot <- DotPlot_scCustom(seurat_pipeline_cluster,features = IFN_genes, x_lab_rotate = TRUE)
  274. ggsave(filename = "Fig3c.pdf", path = FIGURES_DIR , plot = IFN_dotplot, width = 325, height =125, device = cairo_pdf, units = "mm")
  275. ```
  276. # generate figure d-f
  277. ```{r}
  278. IFN_astroglial_top_100 <- markers_clusters %>% filter(cluster == 'IFN-responsive glial/progenitor-like') %>% arrange(desc(avg_log2FC)) %>% top_n(100, wt = avg_log2FC)
  279. reactive_astro_top_100 <- markers_clusters %>% filter(cluster == 'Reactive astrocyte-like') %>% arrange(desc(avg_log2FC)) %>% top_n(100, wt = avg_log2FC)
  280. wound_healing_top_100 <- markers_clusters %>% filter(cluster == 'Wound healing-like') %>% arrange(desc(avg_log2FC)) %>% top_n(100, wt = avg_log2FC)
  281. # getting the genes
  282. IFN_astroglial_top_100_genes <- IFN_astroglial_top_100$gene
  283. reactive_astro_top_100_genes <- reactive_astro_top_100$gene
  284. wound_healing_top_100_genes <- wound_healing_top_100$gene
  285. # convert gene symbols to entrez IDs
  286. entrez_ids_IFN_astroglial_top_100_genes <- bitr(IFN_astroglial_top_100_genes,
  287. fromType = "SYMBOL",
  288. toType = "ENTREZID",
  289. OrgDb = org.Hs.eg.db)
  290. entrez_ids_reactive_astro_top_100_genes<- bitr(reactive_astro_top_100_genes,
  291. fromType = "SYMBOL",
  292. toType = "ENTREZID",
  293. OrgDb = org.Hs.eg.db)
  294. entrez_ids_wound_healing_top_100_genes<- bitr(wound_healing_top_100_genes,
  295. fromType = "SYMBOL",
  296. toType = "ENTREZID",
  297. OrgDb = org.Hs.eg.db)
  298. ```
  299. Go enrichment - BP - biologial process
  300. ```{r}
  301. # run GO enrinchment - BP
  302. go_results_IFN_astroglial <- enrichGO(gene = entrez_ids_IFN_astroglial_top_100_genes$ENTREZID,
  303. OrgDb = org.Hs.eg.db,
  304. keyType = "ENTREZID",
  305. ont = "BP", # Can be "BP", "MF", or "CC"
  306. pAdjustMethod = "BH",
  307. pvalueCutoff = 0.05,
  308. qvalueCutoff = 0.2,
  309. readable = TRUE)
  310. go_results_reactive_astro <- enrichGO(gene = entrez_ids_reactive_astro_top_100_genes$ENTREZID,
  311. OrgDb = org.Hs.eg.db,
  312. keyType = "ENTREZID",
  313. ont = "BP", # Can be "BP", "MF", or "CC"
  314. pAdjustMethod = "BH",
  315. pvalueCutoff = 0.05,
  316. qvalueCutoff = 0.2,
  317. readable = TRUE)
  318. go_results_wound_healing <- enrichGO(gene = entrez_ids_wound_healing_top_100_genes$ENTREZID,
  319. OrgDb = org.Hs.eg.db,
  320. keyType = "ENTREZID",
  321. ont = "BP", # Can be "BP", "MF", or "CC"
  322. pAdjustMethod = "BH",
  323. pvalueCutoff = 0.05,
  324. qvalueCutoff = 0.2,
  325. readable = TRUE)
  326. ```
  327. Dot plots:
  328. ```{r}
  329. go_results_IFN_astroglial_bb <- dotplot(go_results_IFN_astroglial, showCategory = 15)
  330. ggsave(filename = "Fig3d.pdf", path = FIGURES_DIR , plot = go_results_IFN_astroglial_bb, width = 150, height =250, device = cairo_pdf, units = "mm")
  331. ```
  332. ```{r}
  333. go_results_reactive_astro_bb <- dotplot(go_results_reactive_astro, showCategory = 15)
  334. ggsave(filename = "Fig3e.pdf", path = FIGURES_DIR , plot = go_results_reactive_astro_bb, width = 150, height =300, device = cairo_pdf, units = "mm")
  335. ```
  336. ```{r}
  337. go_results_wound_healing_bb <- dotplot(go_results_wound_healing, showCategory = 15)
  338. ggsave(filename = "Fig3f.pdf", path = FIGURES_DIR , plot = go_results_wound_healing_bb, width = 150, height =200, device = cairo_pdf, units = "mm")
  339. ```
  340. # generate figure 3g
  341. IFN-beta NSC signature - https://www.embopress.org/doi/full/10.15252/emmm.202216434
  342. ```{r}
  343. IFN_B_response_genes_df <- read.csv("scripts/NSC_IFN_b_genes.csv")
  344. IFN_B_response_genes <- IFN_B_response_genes_df$Genes
  345. seurat_pipeline_cluster <- AddModuleScore(
  346. seurat_pipeline_cluster,
  347. features = list(IFN_B_response_genes),
  348. name = c('NSC IFN-β signature'),
  349. search = TRUE,
  350. )
  351. IFN_signature <- FeaturePlot_scCustom(
  352. seurat_pipeline_cluster,
  353. features = "NSC IFN-β signature1", # your module score metadata
  354. colors_use = viridis_plasma_dark_high, # or your preferred gradient
  355. na_color = "grey90", # color for low module scores
  356. na_cutoff = 0.05) + xlab('UMAP1') + ylab('UMAP2') + theme(plot.title = element_text(hjust = 0.5)) + coord_fixed() + ggtitle('NSC IFN-β signature') # everything ≤ 0 is grey; >0 uses gradient
  357. ggsave(filename = "Fig3g.pdf", path = FIGURES_DIR , plot = IFN_signature, width = 325, height =125, device = cairo_pdf, units = "mm")
  358. ```
  359. # generate figure 3h
  360. ```{r}
  361. # generate net
  362. net <- get_collectri(organism='human', split_complexes=FALSE)
  363. # Extract the normalized log-transformed counts
  364. mat <- seurat_pipeline_cluster[["SCT"]]$data
  365. # Run ulm
  366. acts <- run_ulm(mat=mat, net=net, .source='source', .target='target',.mor='mor', minsize = 5)
  367. ```
  368. ```{r}
  369. # Extract ulm and store it in tfsulm
  370. seurat_pipeline_cluster[['tfsulm']] <- acts %>%
  371. pivot_wider(id_cols = 'source', names_from = 'condition',
  372. values_from = 'score') %>%
  373. column_to_rownames('source') %>%
  374. Seurat::CreateAssayObject(.)
  375. # Change assay
  376. DefaultAssay(object = seurat_pipeline_cluster) <- "tfsulm"
  377. # Scale the data
  378. seurat_pipeline_cluster <- ScaleData(seurat_pipeline_cluster)
  379. seurat_pipeline_cluster@assays$tfsulm@data <- seurat_pipeline_cluster@assays$[email hidden]
  380. ```
  381. ```{r}
  382. n_tfs <- 50
  383. Idents(seurat_pipeline_cluster) <- seurat_pipeline_cluster$active_ident
  384. # Extract activities from object as a long dataframe
  385. df <- t(as.matrix(seurat_pipeline_cluster@assays$tfsulm$data)) %>%
  386. as.data.frame() %>%
  387. mutate(cluster = Idents(seurat_pipeline_cluster)) %>%
  388. pivot_longer(cols = -cluster, names_to = "source", values_to = "score") %>%
  389. group_by(cluster, source) %>%
  390. summarise(mean = mean(score))
  391. # Get top tfs with more variable means across clusters
  392. tfs <- df %>%
  393. group_by(source) %>%
  394. summarise(std = sd(mean)) %>%
  395. arrange(-abs(std)) %>%
  396. head(n_tfs) %>%
  397. pull(source)
  398. # Subset long data frame to top tfs and transform to wide matrix
  399. top_acts_mat <- df %>%
  400. filter(source %in% tfs) %>%
  401. pivot_wider(id_cols = 'cluster', names_from = 'source',
  402. values_from = 'mean') %>%
  403. column_to_rownames('cluster') %>%
  404. as.matrix()
  405. # Choose color palette
  406. palette_length = 100
  407. my_color = colorRampPalette(c("Darkblue", "white","red"))(palette_length)
  408. my_breaks <- c(seq(-3, 0, length.out=ceiling(palette_length/2) + 1),
  409. seq(0.05, 3, length.out=floor(palette_length/2)))
  410. mat2 <- t(top_acts_mat)
  411. # Plot
  412. pheatmap(mat2,border_color = NA, color=my_color, breaks = my_breaks, filename = 'figures/fig3h.pdf',width = 7,height = 10)
  413. ```
  414. # extended data fig 1a
  415. ```{r}
  416. DefaultAssay(object = seurat_pipeline_cluster) <- "SCT"
  417. Idents(seurat_pipeline_cluster) <- 'sample.ID'
  418. seurat_pipeline_cluster$sample.ID <- factor(seurat_pipeline_cluster$sample.ID , levels = c("Proliferation control","Proliferation low TNF","Proliferation high TNF","Differentiation control (7 days)","Differentiation low TNF (7 days)","Differentiation high TNF (7 days)","Differentiation control (14 days)","Differentiation low TNF (14 days)","Differentiation high TNF (14 days)"))
  419. Idents(seurat_pipeline_cluster) <- 'active_ident'
  420. new_order <- c("Astro-like 1", "Astro-like 2", "Astro-like 3", "Astro-like 4", "RGL-like 1", "RGL-like 2", "IPC-like 1", "IPC-like 2", "IPC-like 3", "IPC-like 4", "Neuroblast-like", "Immature neuron-like", "IFN-responsive glial/progenitor-like", "Reactive astrocyte-like", "Wound healing-like")
  421. seurat_pipeline_cluster <- SetIdent(seurat_pipeline_cluster, value = factor(Idents(seurat_pipeline_cluster), levels = new_order))
  422. sample_ID_plot <- DimPlot_scCustom(
  423. seurat_pipeline_cluster,
  424. label = FALSE,
  425. split.by = "sample.ID",
  426. repel = TRUE,
  427. num_columns = 3,
  428. split_seurat = TRUE,
  429. colors_use = colors_UMAP,
  430. pt.size = 0.1
  431. ) +
  432. xlab("UMAP1") +
  433. ylab("UMAP2") +
  434. NoAxes() +
  435. theme(
  436. strip.text = element_text(size =9), # 👈 changes panel title size
  437. legend.title = element_text(size = 5))
  438. ggsave(filename = "extended_fig1a.pdf", path = FIGURES_DIR , plot = sample_ID_plot, width = 325, height =125, device = cairo_pdf, units = "mm")
  439. ```
  440. # extended data fig 1b
  441. ```{r}
  442. # subset prol data
  443. prol <- subset(seurat_pipeline_cluster, subset = Time == 'Proliferation (2 days)')
  444. prol$treatment <- factor(x = prol$treatment, levels = c('Control','Low TNF','High TNF'))
  445. Idents(prol) <- 'treatment'
  446. # violin plots
  447. ISG15 <- VlnPlot(prol, features = 'ISG15')
  448. IFI27 <- VlnPlot(prol, features = 'IFI27')
  449. IFI6 <- VlnPlot(prol, features = 'IFI6')
  450. IFITM3 <- VlnPlot(prol, features = 'IFITM3')
  451. dose_dependent1 <- ISG15 |IFI27
  452. dose_dependent2 <- IFI6 |IFITM3
  453. ggsave(filename = "extended_fig1b1.pdf", path = FIGURES_DIR , plot = dose_dependent1, width = 325, height =125, device = cairo_pdf, units = "mm")
  454. ggsave(filename = "extended_fig1b2.pdf", path = FIGURES_DIR , plot = dose_dependent2, width = 325, height =125, device = cairo_pdf, units = "mm")
  455. ```
  456. # extended data fig 1c
  457. ```{r}
  458. RGLs_markers <-FindMarkers(seurat_pipeline_cluster,ident.1 = 'RGL-like 2', ident.2 = 'RGL-like 1', assay = 'SCT', only.pos = TRUE, min.pct=0.25, test.use = "wilcox", logfc.threshold = 0.25) %>% rownames_to_column(var = "gene")
  459. RGLs_markers %>% arrange(desc(avg_log2FC)) %>% slice_head(n = 100) %>% ungroup() -> RGL_results
  460. RGL_results_genes <- RGL_results$gene
  461. # convert gene symbols to entrez IDs
  462. RGL_entrez <- bitr(RGL_results_genes,
  463. fromType = "SYMBOL",
  464. toType = "ENTREZID",
  465. OrgDb = org.Hs.eg.db)
  466. RGL_BP <- enrichGO(gene = RGL_entrez$ENTREZID,
  467. OrgDb = org.Hs.eg.db,
  468. keyType = "ENTREZID",
  469. ont = "BP", # Can be "BP", "MF", or "CC"
  470. pAdjustMethod = "BH",
  471. pvalueCutoff = 0.05,
  472. qvalueCutoff = 0.2,
  473. readable = TRUE)
  474. RGL_downregulated_tnf <- dotplot(RGL_BP, showCategory = 15)
  475. ggsave(filename = "extended_fig1c.pdf", path = FIGURES_DIR , plot = RGL_downregulated_tnf, width = 200, height =150, device = cairo_pdf, units = "mm")
  476. ```
  477. # extended data fig 1d
  478. ```{r}
  479. IPC_down_TNF <-FindMarkers(seurat_pipeline_cluster,ident.1 = 'IPC-like 4', ident.2 = c('IPC-like 1', 'IPC-like 2', 'IPC-like 3'), assay = 'SCT', only.pos = TRUE, min.pct=0.25, test.use = "wilcox", logfc.threshold = 0.25) %>% rownames_to_column(var = "gene")
  480. IPC_down_TNF %>% arrange(desc(avg_log2FC)) %>% slice_head(n = 100) %>% ungroup() -> IPC_down_TNF_top_100
  481. IPC_down_TNF_top_100_genes <- IPC_down_TNF_top_100$gene
  482. IPC_TNF_down <- bitr(IPC_down_TNF_top_100_genes,
  483. fromType = "SYMBOL",
  484. toType = "ENTREZID",
  485. OrgDb = org.Hs.eg.db)
  486. IPC_TNF_down_BP <- enrichGO(gene = IPC_TNF_down$ENTREZID,
  487. OrgDb = org.Hs.eg.db,
  488. keyType = "ENTREZID",
  489. ont = "BP", # Can be "BP", "MF", or "CC"
  490. pAdjustMethod = "BH",
  491. pvalueCutoff = 0.05,
  492. qvalueCutoff = 0.2,
  493. readable = TRUE)
  494. extended_fig1d <- dotplot(IPC_TNF_down_BP, showCategory = 15)
  495. ggsave(filename = "extended_fig1d.pdf", path = FIGURES_DIR , plot = extended_fig1d, width = 200, height =150, device = cairo_pdf, units = "mm")
  496. ```
  497. # extended data fig 1e-f
  498. ```{r}
  499. DefaultAssay(object = seurat_pipeline_cluster) <- "tfsulm"
  500. STAT1 <- FeaturePlot_scCustom(
  501. seurat_pipeline_cluster,
  502. features = "STAT1", # your module score metadata
  503. colors_use = viridis_plasma_dark_high, # or your preferred gradient
  504. na_color = "grey90", # color for low module scores
  505. na_cutoff = 0.5) + xlab('UMAP1') + ylab('UMAP2') + theme(plot.title = element_text(hjust = 0.5)) + coord_fixed() + ggtitle('STAT1 activity') # everything ≤ 0 is grey; >0 uses gradient
  506. ggsave(filename = "extended_fig1e.pdf", path = FIGURES_DIR , plot = STAT1, width = 200, height =150, device = cairo_pdf, units = "mm")
  507. STAT2 <- FeaturePlot_scCustom(
  508. seurat_pipeline_cluster,
  509. features = "STAT2", # your module score metadata
  510. colors_use = viridis_plasma_dark_high, # or your preferred gradient
  511. na_color = "grey90", # color for low module scores
  512. na_cutoff = 0.5) + xlab('UMAP1') + ylab('UMAP2') + theme(plot.title = element_text(hjust = 0.5)) + coord_fixed() + ggtitle('STAT2 activity') # everything ≤ 0 is grey; >0 uses gradient
  513. ggsave(filename = "extended_fig1f.pdf", path = FIGURES_DIR , plot = STAT2, width = 200, height =150, device = cairo_pdf, units = "mm")
  514. ```
  515. # supplementary Fig. 8
  516. ```{r}
  517. go_results_neuro_cc <- enrichGO(gene = entrez_ids_neuro$ENTREZID,
  518. OrgDb = org.Hs.eg.db,
  519. keyType = "ENTREZID",
  520. ont = "CC", # Can be "BP", "MF", or "CC"
  521. pAdjustMethod = "BH",
  522. pvalueCutoff = 0.05,
  523. qvalueCutoff = 0.2,
  524. readable = TRUE)
  525. cc_neuro_dotplot <- dotplot(go_results_neuro_cc, showCategory = 15)
  526. ggsave(filename = "supplementary_fig8.pdf", path = FIGURES_DIR , plot = cc_neuro_dotplot, width = 200, height =150, device = cairo_pdf, units = "mm")
  527. ```
  528. # supplementary Fig. 9a
  529. ```{r}
  530. DefaultAssay(seurat_pipeline_cluster) <- 'SCT'
  531. # Parameters - change gene and object name if needed
  532. gene <- "TNFRSF1A" # <- replace with your gene name
  533. seu_obj <- seurat_pipeline_cluster
  534. # Check gene presence
  535. if (!(gene %in% rownames(seu_obj))) {
  536. stop(paste0("Gene '", gene, "' not found in the Seurat object."))
  537. }
  538. # Pull expression data
  539. expr_mat <- GetAssayData(seu_obj, assay = DefaultAssay(seu_obj), slot = "data")
  540. expr_vec <- as.numeric(expr_mat[gene, ])
  541. # Build dataframe with cluster identity and expression
  542. df <- data.frame(
  543. cluster = as.character(Idents(seu_obj)),
  544. expr = expr_vec,
  545. stringsAsFactors = FALSE
  546. )
  547. # Convert cluster to numeric if possible (to ensure natural order)
  548. df <- df %>%
  549. mutate(cluster_num = suppressWarnings(as.numeric(cluster))) %>%
  550. mutate(cluster_num = ifelse(is.na(cluster_num), cluster, cluster)) # fallback for non-numeric
  551. # Summarise: percent of cells with expr > 0 per cluster
  552. summary_df <- df %>%
  553. group_by(cluster, cluster_num) %>%
  554. summarise(
  555. n_cells = n(),
  556. n_expressing = sum(expr > 0),
  557. pct_expressing = 100 * (n_expressing / n_cells),
  558. .groups = "drop"
  559. ) %>%
  560. arrange(as.numeric(cluster_num))
  561. # Ensure numeric ordering of x-axis
  562. summary_df$cluster <- factor(summary_df$cluster, levels = summary_df$cluster)
  563. # Plot
  564. p1 <- ggplot(summary_df, aes(x = cluster, y = pct_expressing)) +
  565. geom_col(width = 0.7, fill = "#4682B4") +
  566. geom_text(aes(label = paste0(round(pct_expressing, 1), "%")),
  567. vjust = -0.3, size = 3) +
  568. scale_y_continuous(expand = expansion(mult = c(0, 0.12)), limits = c(0, NA)) +
  569. labs(
  570. title = paste0("Percent of cells expressing ", gene, " per cluster"),
  571. x = "Cluster",
  572. y = "Percent expressing (%)"
  573. ) +
  574. theme_minimal(base_size = 14) +
  575. theme(
  576. axis.text.x = element_text(
  577. angle = 45,
  578. hjust = 1
  579. )
  580. )
  581. ggsave(filename = "supplementary_fig9a.pdf", path = FIGURES_DIR , plot = p1, width = 200, height =150, device = cairo_pdf, units = "mm")
  582. ```
  583. # supplementary Fig. 9b
  584. ```{r}
  585. DefaultAssay(seurat_pipeline_cluster) <- 'SCT'
  586. # Parameters - change gene and object name if needed
  587. gene <- "TNFRSF1B" # <- replace with your gene name
  588. seu_obj <- seurat_pipeline_cluster
  589. # Check gene presence
  590. if (!(gene %in% rownames(seu_obj))) {
  591. stop(paste0("Gene '", gene, "' not found in the Seurat object."))
  592. }
  593. # Pull expression data
  594. expr_mat <- GetAssayData(seu_obj, assay = DefaultAssay(seu_obj), slot = "data")
  595. expr_vec <- as.numeric(expr_mat[gene, ])
  596. # Build dataframe with cluster identity and expression
  597. df <- data.frame(
  598. cluster = as.character(Idents(seu_obj)),
  599. expr = expr_vec,
  600. stringsAsFactors = FALSE
  601. )
  602. # Convert cluster to numeric if possible (to ensure natural order)
  603. df <- df %>%
  604. mutate(cluster_num = suppressWarnings(as.numeric(cluster))) %>%
  605. mutate(cluster_num = ifelse(is.na(cluster_num), cluster, cluster)) # fallback for non-numeric
  606. # Summarise: percent of cells with expr > 0 per cluster
  607. summary_df <- df %>%
  608. group_by(cluster, cluster_num) %>%
  609. summarise(
  610. n_cells = n(),
  611. n_expressing = sum(expr > 0),
  612. pct_expressing = 100 * (n_expressing / n_cells),
  613. .groups = "drop"
  614. ) %>%
  615. arrange(as.numeric(cluster_num))
  616. # Ensure numeric ordering of x-axis
  617. summary_df$cluster <- factor(summary_df$cluster, levels = summary_df$cluster)
  618. # Plot
  619. p2 <- ggplot(summary_df, aes(x = cluster, y = pct_expressing)) +
  620. geom_col(width = 0.7, fill = "#4682B4") +
  621. geom_text(aes(label = paste0(round(pct_expressing, 1), "%")),
  622. vjust = -0.3, size = 3) +
  623. scale_y_continuous(expand = expansion(mult = c(0, 0.12)), limits = c(0, NA)) +
  624. labs(
  625. title = paste0("Percent of cells expressing ", gene, " per cluster"),
  626. x = "Cluster",
  627. y = "Percent expressing (%)"
  628. ) +
  629. theme_minimal(base_size = 14) +
  630. theme(
  631. axis.text.x = element_text(
  632. angle = 45,
  633. hjust = 1
  634. )
  635. )
  636. ggsave(filename = "supplementary_fig9b.pdf", path = FIGURES_DIR , plot = p2, width = 200, height =150, device = cairo_pdf, units = "mm")
  637. ```
  638. # supplementary Fig. 9c
  639. ```{r}
  640. DefaultAssay(seurat_pipeline_cluster) <- 'SCT'
  641. TNFR1_violin <- VlnPlot_scCustom(seurat_pipeline_cluster,features = "TNFRSF1A", colors_use = colors_UMAP)
  642. ggsave(filename = "supplementary_fig9c.pdf", path = FIGURES_DIR , plot = TNFR1_violin, width = 200, height =150, device = cairo_pdf, units = "mm")
  643. ```
  644. # supplementary Fig. 9d
  645. ```{r}
  646. DefaultAssay(seurat_pipeline_cluster) <- 'SCT'
  647. TNFR2_violin <- VlnPlot_scCustom(seurat_pipeline_cluster,features = "TNFRSF1B", colors_use = colors_UMAP)
  648. ggsave(filename = "supplementary_fig9d.pdf", path = FIGURES_DIR , plot = TNFR2_violin, width = 200, height =150, device = cairo_pdf, units = "mm")
  649. ```
  650. # supplementary Fig. 9e
  651. ```{r}
  652. TNFRSF1A_dotplot <- DotPlot(seurat_pipeline_cluster,features = c("TNFRSF1A"))
  653. ggsave(filename = "supplementary_fig9e.pdf", path = FIGURES_DIR , plot = TNFRSF1A_dotplot, width = 200, height =150, device = cairo_pdf, units = "mm")
  654. ```
  655. # supplementary Fig. 9f
  656. ```{r}
  657. TNFRSF1B_dotplot <-DotPlot(seurat_pipeline_cluster,features = c("TNFRSF1B"))
  658. ggsave(filename = "supplementary_fig9f.pdf", path = FIGURES_DIR , plot = TNFRSF1B_dotplot, width = 200, height =150, device = cairo_pdf, units = "mm")
  659. ```
  660. # supplementary Fig. 10a and c
  661. ```{r}
  662. ensembl <- useMart("ensembl",dataset="hsapiens_gene_ensembl")
  663. apoptosis <- getBM(attributes=c('hgnc_symbol', 'reactome'),
  664. filters = 'reactome',
  665. values = 'R-HSA-109581', mart = ensembl)
  666. apoptosis_genes <- unique(apoptosis$hgnc_symbol)
  667. ```
  668. ```{r}
  669. seurat_pipeline_cluster <- AddModuleScore(
  670. seurat_pipeline_cluster,
  671. features = list(apoptosis_genes),
  672. pool = NULL,
  673. nbin = 24,
  674. ctrl = 100,
  675. k = FALSE,
  676. assay = NULL,
  677. name = c("apoptosis_score"),
  678. seed = 1,
  679. search = TRUE,
  680. )
  681. apoptosis_Violinplot <- VlnPlot(seurat_pipeline_cluster,features = "apoptosis_score1")+ labs(title = "Apoptosis (R-HSA-109581)")
  682. ggsave(filename = "supplementary_fig10a.pdf", path = FIGURES_DIR , plot = apoptosis_Violinplot, width = 200, height =150, device = cairo_pdf, units = "mm")
  683. ```
  684. ```{r}
  685. seurat_pipeline_cluster$treatment <- factor(seurat_pipeline_cluster$treatment,
  686. levels = c("Control", "Low TNF", "High TNF"))
  687. apoptosis_score_1 <- VlnPlot(seurat_pipeline_cluster, features = "apoptosis_score1", group.by = "treatment") +
  688. labs(title = "Apoptosis") + theme_minimal(base_size = 14)
  689. ggsave(filename = "supplementary_fig10c.pdf", path = FIGURES_DIR , plot = apoptosis_score_1, width = 200, height =150, device = cairo_pdf, units = "mm")
  690. ```
  691. # supplementary Fig. 10b and d
  692. ```{r}
  693. ensembl <- useMart("ensembl",dataset="hsapiens_gene_ensembl")
  694. apoptosis_2 <- getBM(attributes=c('hgnc_symbol', 'reactome'),
  695. filters = 'reactome',
  696. values = 'R-HSA-5357801', mart = ensembl)
  697. apoptosis_genes_2 <- unique(apoptosis_2$hgnc_symbol)
  698. ```
  699. ```{r}
  700. seurat_pipeline_cluster <- AddModuleScore(
  701. seurat_pipeline_cluster,
  702. features = list(apoptosis_genes_2),
  703. pool = NULL,
  704. nbin = 24,
  705. ctrl = 100,
  706. k = FALSE,
  707. assay = NULL,
  708. name = c("apoptosis_score_2"),
  709. seed = 1,
  710. search = TRUE,
  711. )
  712. ```
  713. ```{r}
  714. programmed_cell_death_Violinplot_2 <- VlnPlot(seurat_pipeline_cluster,features = "apoptosis_score_21")+ labs(title = "Programmed Cell Death (R-HSA-5357801)")
  715. ggsave(filename = "supplementary_fig10b.pdf", path = FIGURES_DIR , plot = programmed_cell_death_Violinplot_2, width = 200, height =150, device = cairo_pdf, units = "mm")
  716. apoptosis_score_2 <- VlnPlot(seurat_pipeline_cluster, features = "apoptosis_score_21", group.by = "treatment") + labs(title = "Programmed Cell Death") +theme_minimal(base_size = 14)
  717. ggsave(filename = "supplementary_fig10d.pdf", path = FIGURES_DIR , plot = apoptosis_score_2, width = 200, height =150, device = cairo_pdf, units = "mm")
  718. ```
  719. # supplementary Fig. 11
  720. RGL
  721. ```{r}
  722. RGL_CC <- enrichGO(gene = RGL_entrez$ENTREZID,
  723. OrgDb = org.Hs.eg.db,
  724. keyType = "ENTREZID",
  725. ont = "CC", # Can be "BP", "MF", or "CC"
  726. pAdjustMethod = "BH",
  727. pvalueCutoff = 0.05,
  728. qvalueCutoff = 0.2,
  729. readable = TRUE)
  730. RGL_CC_dotplot <- dotplot(RGL_CC, showCategory = 15)
  731. ggsave(filename = "supplementary_fig11_RGL.pdf", path = FIGURES_DIR , plot = RGL_CC_dotplot, width = 200, height =150, device = cairo_pdf, units = "mm")
  732. ```
  733. IPC:
  734. ```{r}
  735. IPC_CC <- enrichGO(gene = IPC_TNF_down$ENTREZID,
  736. OrgDb = org.Hs.eg.db,
  737. keyType = "ENTREZID",
  738. ont = "CC", # Can be "BP", "MF", or "CC"
  739. pAdjustMethod = "BH",
  740. pvalueCutoff = 0.05,
  741. qvalueCutoff = 0.2,
  742. readable = TRUE)
  743. IPC_CC_dotplot <- dotplot(IPC_CC, showCategory = 15)
  744. ggsave(filename = "supplementary_fig11_IPC.pdf", path = FIGURES_DIR , plot = IPC_CC_dotplot, width = 200, height =150, device = cairo_pdf, units = "mm")
  745. ```
  746. # supplementary Fig. 12
  747. ```{r}
  748. IFNAR1 <- FeaturePlot(seurat_pipeline_cluster, features = "IFNAR1", order = TRUE )+ xlab('UMAP1') + ylab('UMAP2') + theme(plot.title = element_text(hjust = 0.5)) + coord_fixed()
  749. ggsave(filename = "supplementary_fig12_ifnar1.pdf", path = FIGURES_DIR , plot = IFNAR1, width = 200, height =150, device = cairo_pdf, units = "mm")
  750. IFNAR2 <- FeaturePlot(seurat_pipeline_cluster, features = "IFNAR2", order = TRUE)+ xlab('UMAP1') + ylab('UMAP2') + theme(plot.title = element_text(hjust = 0.5)) + coord_fixed()
  751. ggsave(filename = "supplementary_fig12_ifnar2.pdf", path = FIGURES_DIR , plot = IFNAR2, width = 200, height =150, device = cairo_pdf, units = "mm")
  752. JAK1 <- FeaturePlot(seurat_pipeline_cluster, features = "JAK1", order = TRUE )+ xlab('UMAP1') + ylab('UMAP2') + theme(plot.title = element_text(hjust = 0.5)) + coord_fixed()
  753. ggsave(filename = "supplementary_fig12_jak1.pdf", path = FIGURES_DIR , plot = JAK1, width = 200, height =150, device = cairo_pdf, units = "mm")
  754. TYK2 <- FeaturePlot(seurat_pipeline_cluster, features = "TYK2", order = TRUE )+ xlab('UMAP1') + ylab('UMAP2') + theme(plot.title = element_text(hjust = 0.5)) + coord_fixed()
  755. ggsave(filename = "supplementary_fig12_tyk2.pdf", path = FIGURES_DIR , plot = TYK2, width = 200, height =150, device = cairo_pdf, units = "mm")
  756. STAT1 <- FeaturePlot(seurat_pipeline_cluster, features = "STAT1", order = TRUE )+ xlab('UMAP1') + ylab('UMAP2') + theme(plot.title = element_text(hjust = 0.5)) + coord_fixed()
  757. ggsave(filename = "supplementary_fig12_stat1.pdf", path = FIGURES_DIR , plot = STAT1, width = 200, height =150, device = cairo_pdf, units = "mm")
  758. STAT2 <- FeaturePlot(seurat_pipeline_cluster, features = "STAT2", order = TRUE )+ xlab('UMAP1') + ylab('UMAP2') + theme(plot.title = element_text(hjust = 0.5)) + coord_fixed()
  759. ggsave(filename = "supplementary_fig12_stat2.pdf", path = FIGURES_DIR , plot = STAT2, width = 200, height =150, device = cairo_pdf, units = "mm")
  760. IRF9 <- FeaturePlot(seurat_pipeline_cluster, features = "IRF9", order = TRUE )+ xlab('UMAP1') + ylab('UMAP2') + theme(plot.title = element_text(hjust = 0.5)) + coord_fixed()
  761. ggsave(filename = "supplementary_fig12_irf9.pdf", path = FIGURES_DIR , plot = IRF9, width = 200, height =150, device = cairo_pdf, units = "mm")
  762. ```
  763. # supplementary Fig. 14a
  764. ```{r}
  765. CGAS <- FeaturePlot(seurat_pipeline_cluster, features = "CGAS", order = TRUE)+ xlab('UMAP1') + ylab('UMAP2') + theme(plot.title = element_text(hjust = 0.5)) + coord_fixed()
  766. ggsave(filename = "supplementary_fig14.pdf", path = FIGURES_DIR , plot = CGAS, width = 200, height =150, device = cairo_pdf, units = "mm")
  767. ```
  768. # supplementary Fig. 19a
  769. ```{r}
  770. # Parameters - change gene and object name if needed
  771. gene <- "CXCL10"
  772. seu_obj <- seurat_pipeline_cluster
  773. # Check gene presence
  774. if (!(gene %in% rownames(seu_obj))) {
  775. stop(paste0("Gene '", gene, "' not found in the Seurat object."))
  776. }
  777. # Pull expression data
  778. expr_mat <- GetAssayData(seu_obj, assay = DefaultAssay(seu_obj), slot = "data")
  779. expr_vec <- as.numeric(expr_mat[gene, ])
  780. # Build dataframe with cluster identity and expression
  781. df <- data.frame(
  782. cluster = as.character(Idents(seu_obj)),
  783. expr = expr_vec,
  784. stringsAsFactors = FALSE
  785. )
  786. # Convert cluster to numeric if possible (to ensure natural order)
  787. df <- df %>%
  788. mutate(cluster_num = suppressWarnings(as.numeric(cluster))) %>%
  789. mutate(cluster_num = ifelse(is.na(cluster_num), cluster, cluster)) # fallback for non-numeric
  790. # Summarise: percent of cells with expr > 0 per cluster
  791. summary_df <- df %>%
  792. group_by(cluster, cluster_num) %>%
  793. summarise(
  794. n_cells = n(),
  795. n_expressing = sum(expr > 0),
  796. pct_expressing = 100 * (n_expressing / n_cells),
  797. .groups = "drop"
  798. ) %>%
  799. arrange(as.numeric(cluster_num))
  800. # Ensure numeric ordering of x-axis
  801. summary_df$cluster <- factor(summary_df$cluster, levels = summary_df$cluster)
  802. # Plot
  803. CXCL10 <- ggplot(summary_df, aes(x = cluster, y = pct_expressing)) +
  804. geom_col(width = 0.7, fill = "#4682B4") +
  805. geom_text(aes(label = paste0(round(pct_expressing, 1), "%")),
  806. vjust = -0.3, size = 3) +
  807. scale_y_continuous(expand = expansion(mult = c(0, 0.12)), limits = c(0, NA)) +
  808. labs(
  809. title = paste0("Percent of cells expressing ", gene, " per cluster"),
  810. x = "Cluster",
  811. y = "Percent expressing (%)"
  812. ) +
  813. theme_minimal(base_size = 14) +
  814. theme(
  815. axis.text.x = element_text(
  816. angle = 45,
  817. hjust = 1
  818. )
  819. )
  820. ggsave(filename = "supplementary_fig19a.pdf", path = FIGURES_DIR , plot = CXCL10, width = 200, height =150, device = cairo_pdf, units = "mm")
  821. ```
  822. # supplementary Fig. 19b
  823. ```{r}
  824. # Parameters - change gene and object name if needed
  825. gene <- "CXCL11"
  826. seu_obj <- seurat_pipeline_cluster
  827. # Check gene presence
  828. if (!(gene %in% rownames(seu_obj))) {
  829. stop(paste0("Gene '", gene, "' not found in the Seurat object."))
  830. }
  831. # Pull expression data
  832. expr_mat <- GetAssayData(seu_obj, assay = DefaultAssay(seu_obj), slot = "data")
  833. expr_vec <- as.numeric(expr_mat[gene, ])
  834. # Build dataframe with cluster identity and expression
  835. df <- data.frame(
  836. cluster = as.character(Idents(seu_obj)),
  837. expr = expr_vec,
  838. stringsAsFactors = FALSE
  839. )
  840. # Convert cluster to numeric if possible (to ensure natural order)
  841. df <- df %>%
  842. mutate(cluster_num = suppressWarnings(as.numeric(cluster))) %>%
  843. mutate(cluster_num = ifelse(is.na(cluster_num), cluster, cluster)) # fallback for non-numeric
  844. # Summarise: percent of cells with expr > 0 per cluster
  845. summary_df <- df %>%
  846. group_by(cluster, cluster_num) %>%
  847. summarise(
  848. n_cells = n(),
  849. n_expressing = sum(expr > 0),
  850. pct_expressing = 100 * (n_expressing / n_cells),
  851. .groups = "drop"
  852. ) %>%
  853. arrange(as.numeric(cluster_num))
  854. # Ensure numeric ordering of x-axis
  855. summary_df$cluster <- factor(summary_df$cluster, levels = summary_df$cluster)
  856. # Plot
  857. CXCL11 <- ggplot(summary_df, aes(x = cluster, y = pct_expressing)) +
  858. geom_col(width = 0.7, fill = "#4682B4") +
  859. geom_text(aes(label = paste0(round(pct_expressing, 1), "%")),
  860. vjust = -0.3, size = 3) +
  861. scale_y_continuous(expand = expansion(mult = c(0, 0.12)), limits = c(0, NA)) +
  862. labs(
  863. title = paste0("Percent of cells expressing ", gene, " per cluster"),
  864. x = "Cluster",
  865. y = "Percent expressing (%)"
  866. ) +
  867. theme_minimal(base_size = 14) +
  868. theme(
  869. axis.text.x = element_text(
  870. angle = 45,
  871. hjust = 1
  872. )
  873. )
  874. ggsave(filename = "supplementary_fig19b.pdf", path = FIGURES_DIR , plot = CXCL11, width = 200, height =150, device = cairo_pdf, units = "mm")
  875. ```
  876. # supplementary Fig. 19c
  877. ```{r}
  878. CXCL10_violin <- VlnPlot_scCustom(seurat_pipeline_cluster,features = "CXCL10", colors_use = colors_UMAP)
  879. ggsave(filename = "supplementary_fig19c.pdf", path = FIGURES_DIR , plot = CXCL10_violin, width = 200, height =150, device = cairo_pdf, units = "mm")
  880. ```
  881. # supplementary Fig. 19d
  882. ```{r}
  883. CXCL11_violin <- VlnPlot_scCustom(seurat_pipeline_cluster,features = "CXCL11", colors_use = colors_UMAP)
  884. ggsave(filename = "supplementary_fig19d.pdf", path = FIGURES_DIR , plot = CXCL11_violin, width = 200, height =150, device = cairo_pdf, units = "mm")
  885. ```

03_analysis.Rmd at commit bdf43f5, under MIT · at the source

Overview

Authors: Tinne A. D. Nissen1,2, Arishma Baig1, Sahand Farmand2, Daniel T. Rock2, Sandra Shibu2, Hyunah Lee2, Lauren A. O’Neill1, Vikki Houghton2,3, Susan John3, Linda S. Klavinskis1, Sandrine Thuret2
  1. Department of Infectious Diseases, School of Immunology & Microbial Sciences, King’s College London,London, UK
  2. Department of Basic and Clinical Neuroscience, Institute of Psychiatry, Psychology and Neuroscience, King’s College London,London, UK
  3. Peter Gorer Department of Immunobiology, King’s College London,London, UK
Institutions: King's College London (United Kingdom)
Journal: Nature communications, volume 17, issue 1, article 5287
Dates: received 9 August 2025; accepted 26 May 2026; published online 7 July 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1038/s41467-026-74104-x · PMID 42414275 · PMCID PMC13342090 · OpenAlex W7167611941
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: human (organism)
Methods: Spectral & time-frequency, Statistics, Smoothing, state filtering, decompositions, Machine learning
Keywords: Cellular neuroscience, Neural stem cells, Neurogenesis
MeSH: Interferon Type I*, Neurogenesis*, T-Lymphocytes*, Tumor Necrosis Factor-alpha*, Animals, Cell Movement, Cells, Cultured, Female, Hippocampus, Humans, Inflammation, Neural Stem Cells, Signal Transduction (* major topic)
Topic: Neurogenesis and neuroplasticity mechanisms (Developmental Neuroscience, Neuroscience), according to OpenAlex
Funding: UK Medical Research Council (MR/S00484X/1); Wellcome Trust (Wellcome) (218452/Z/19/Z); RCUK | MRC | Medical Research Foundation (MR/R015643/1, MR/N012345/1); Galen and Hilary Weston Foundation
Citations: not cited yet (Europe PMC); 120 references in the paper

Abstract

Adult hippocampal neurogenesis is essential for learning, memory, and mood regulation, and its disruption is implicated in ageing, neurodegeneration, and mood disorders. However, the mechanisms linking inflammation to adult hippocampal neurogenesis impairment remain unclear. Here, we identify chronic tumour necrosis factor-alpha signalling as a key driver of neurogenic dysregulation via a previously unrecognised type I interferon autocrine/paracrine loop in human hippocampal progenitor cells. Using a female-derived human in vitro neurogenesis model, single-cell RNA sequencing, and functional T cell migration assays, we show that tumour necrosis factor-alpha induces a robust type I interferon response in hippocampal progenitor cells, promoting chemokine-mediated and CXC motif chemokine receptor 3-dependent T cell recruitment and suppressing neurogenesis. This inflammatory signalling cascade drives a fate switch in hippocampal progenitor cells from a neurogenic trajectory towards an immune-defensive phenotype, with critical implications for infectious and inflammatory disease pathogenesis. These findings uncover a key inflammatory checkpoint regulating human adult hippocampal neurogenesis and highlight potential therapeutic targets to restore neurogenesis in chronic inflammatory states.

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

Repository

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

thuretlabkcl/TNF-scRNAseq-neurogenesis

License: MIT
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: bdf43f5618a7eb675c8e753c7171e0419a88783b, 22 April 2026
Languages: R (6)
Size: 18 files, 6 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, license file, environment (renv.lock), 3 notebooks
Not found: CITATION.cff, tests, continuous integration, documentation
Tools: tidyverse (3 files), Seurat (2 files), clusterProfiler (1 file), ggplot2 (1 file), pheatmap (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
8 files

Code availability

The code used for the ScRNA-seq analysis is available at: https://github.com/thuretlabkcl/TNF-scRNAseq-neurogenesis.

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:

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

Source data are provided with this paper. Raw sequencing data have been deposited in the NCBI Sequence Read Archive under BioProject accession PRJNA1397568 (https://www.ncbi.nlm.nih.gov/bioproject/?term=PRJNA1397568). 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 1, 27 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 11 authors, 3 keywords, 13 MeSH terms, 4 funders, 120 references.

Cite

This paper

Nissen, T. A. D., Baig, A., Farmand, S., Rock, D. T., Shibu, S., Lee, H., O’Neill, L. A., Houghton, V., John, S., Klavinskis, L. S., & Thuret, S. (2026). TNF-α induces type I IFN signalling to suppress neurogenesis and recruit T cells. Nature communications, 17(1), 5287. https://doi.org/10.1038/s41467-026-74104-x

BibTeX

@article{nissen2026tnf,
author = {Nissen, Tinne A. D. and Baig, Arishma and Farmand, Sahand and Rock, Daniel T. and Shibu, Sandra and Lee, Hyunah and O’Neill, Lauren A. and Houghton, Vikki and John, Susan and Klavinskis, Linda S. and Thuret, Sandrine},
title = {{TNF-α induces type I IFN signalling to suppress neurogenesis and recruit T cells}},
journal = {Nature communications},
year = {2026},
month = jul,
volume = {17},
number = {1},
pages = {5287},
publisher = {Nature Publishing Group},
issn = {2041-1723},
doi = {10.1038/s41467-026-74104-x},
url = {https://doi.org/10.1038/s41467-026-74104-x},
pmid = {42414275},
pmcid = {PMC13342090}
}

RIS

TY - JOUR
AU - Nissen, Tinne A. D.
AU - Baig, Arishma
AU - Farmand, Sahand
AU - Rock, Daniel T.
AU - Shibu, Sandra
AU - Lee, Hyunah
AU - O’Neill, Lauren A.
AU - Houghton, Vikki
AU - John, Susan
AU - Klavinskis, Linda S.
AU - Thuret, Sandrine
TI - TNF-α induces type I IFN signalling to suppress neurogenesis and recruit T cells
T2 - Nature communications
J2 - Nat Commun
PY - 2026
DA - 2026/07/07
VL - 17
IS - 1
SP - 5287
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/s41467-026-74104-x
UR - https://doi.org/10.1038/s41467-026-74104-x
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41467-026-74104-x",
"type": "article-journal",
"title": "TNF-α induces type I IFN signalling to suppress neurogenesis and recruit T cells",
"container-title": "Nature communications",
"author": [
{
"family": "Nissen",
"given": "Tinne A. D."
},
{
"family": "Baig",
"given": "Arishma"
},
{
"family": "Farmand",
"given": "Sahand"
},
{
"family": "Rock",
"given": "Daniel T."
},
{
"family": "Shibu",
"given": "Sandra"
},
{
"family": "Lee",
"given": "Hyunah"
},
{
"family": "O’Neill",
"given": "Lauren A."
},
{
"family": "Houghton",
"given": "Vikki"
},
{
"family": "John",
"given": "Susan"
},
{
"family": "Klavinskis",
"given": "Linda S."
},
{
"family": "Thuret",
"given": "Sandrine"
}
],
"container-title-short": "Nat Commun",
"volume": "17",
"issue": "1",
"page": "5287",
"DOI": "10.1038/s41467-026-74104-x",
"PMID": "42414275",
"PMCID": "PMC13342090",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41467-026-74104-x",
"language": "en",
"issued": {
"date-parts": [
[
2026,
7,
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/s41514-026-00439-w [code]
Effects of a three-month exercise programme on cognition, mood and neurogenesis: the NeuroFit randomised controlled trial.
Journal: npj aging
In common: ggplot2, tidyverse, 7 references, 2 authors
[2] doi:10.1038/s44400-026-00125-4 [code]
Regulators of interferon-responsive microglia uncovered by Genome-wide CRISPRi screening.
Journal: NPJ dementia
In common: Seurat, ggplot2, tidyverse, 6 references
[3] doi:10.1038/s41514-026-00397-3 [code]
Nasal administration of Protollin enhances monocyte phagocytosis and decreases CD8&lt;sup&gt;+&lt;/sup&gt; T cell cytotoxicity in subjects with early Alzheimer's disease: a Phase 1 clinical trial.
Journal: npj aging
In common: pheatmap, Seurat, ggplot2, 1 other tool, 4 references
[4] doi:10.1038/s41467-026-76232-w [code]
Th17 effector cytokines induce shared and distinct microglial and endothelial cell responses in a mouse model for post-streptococcal encephalitis.
Journal: Nature communications
In common: clusterProfiler, Seurat, ggplot2, 1 other tool, 3 references
[5] 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: clusterProfiler, pheatmap, Seurat, 2 other tools, 2 references
[6] doi:10.1101/gr.281113.125 [code]
Single-nucleus multiomic profiling of the aging mouse substantia nigra reveals conserved gene alterations linked to Parkinson's disease.
Journal: Genome research
In common: clusterProfiler, Seurat, ggplot2, 1 other tool, 3 references
[7] 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: clusterProfiler, pheatmap, Seurat, 2 other tools, 2 references
[8] doi:10.1038/s41593-026-02354-5 [code]
Focal astrocyte loss reveals nuclear translocation during lesion repopulation.
Journal: Nature neuroscience
In common: clusterProfiler, Seurat, ggplot2, 1 other tool, 3 references
[9] doi:10.1186/s44342-026-00076-5 [code]
Exploratory strain-associated patterns of antiviral transcriptional responses to Zika virus exposure in developing human neural tissue.
Journal: Genomics & informatics
In common: pheatmap, Seurat, ggplot2, 1 other tool, 2 references
[10] doi:10.1038/s41467-026-76341-6 [code]
Neonatal inflammation disrupts a temporally restricted postnatal Numb-enriched microglial state in mice.
Journal: Nature communications
In common: clusterProfiler, pheatmap, Seurat, 2 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.