IgLON5 autoimmune antibodies activate Tau via neuronal hyperactivity.
The 1 match
- [1] § MATERIALS AND METHODS › RNA sequencing ↔ 250327_publication.Rmd, lines 416–550 · score 0.72 · fold change, DESeq2, shrinkage, IHW, apeglm, threshold
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,350 lines · 48 KB · LGPL-3.0 · 1 match
- ---
- title: "DESeq2 RNA-seq Analysis"
- author: " Pia Grundschoettel"
- date: "17.04.2025"
- output:
- html_document:
- toc: true
- toc_float: true
- ---
- # 1. R requirements
- ## 1.1 Install and load packages
- ### Install CRAN
- ```{r}
- # CRAN packages
- list.of.packages <- c("apeglm",
- "factoextra",
- "ggbeeswarm",
- "ggplot2",
- "ggrepel",
- "gplots",
- "hexbin",
- "Hmisc",
- "openxlsx",
- "patchwork",
- "plotly",
- "reshape2",
- "scales",
- "tidyr",
- # "VennDiagram",
- "UpSetR",
- "rstatix",
- "ggExtra",
- "multcomp"
- # "RANN",
- # "igraph",
- # "leidenbase"
- )
- new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])]
- if(length(new.packages)>0) install.packages(new.packages)
- ```
- ### Install BioConductor
- ```{r}
- # BioconductoR packages
- list.of.bioc.packages <- c("biomaRt",
- "clusterProfiler",
- "ComplexHeatmap",
- "DESeq2",
- "DOSE",
- "genefilter",
- "ggpubr",
- "GSEABase",
- "GSVA",
- "IHW",
- "limma",
- "org.Hs.eg.db",
- "pheatmap",
- "RColorBrewer",
- "rhdf5",
- # "sva",
- "tximport"
- # "vsn",
- # "Seurat",
- # "SeuratDisk"
- )
- new.packages.bioc <- list.of.bioc.packages[!(list.of.bioc.packages %in% installed.packages()[,"Package"])]
- if(length(new.packages.bioc)>0) if (!requireNamespace("BiocManager")) install.packages("BiocManager")
- BiocManager::install(new.packages.bioc, update = FALSE)
- ```
- ### Load Packages
- ```{r load packages, results='hide',message=FALSE,warning=FALSE}
- lapply(c(list.of.packages,list.of.bioc.packages), require, character.only = TRUE)
- ```
- ```{r}
- rm(list.of.packages,list.of.bioc.packages, new.packages, new.packages.bioc)
- ```
- ## 1.2 Functions used
- ### TX import
- ```{r}
- ### TX import
- tx_import <- function(file,
- aligner = c("STAR", "Kallisto")) {
- if(aligner == "STAR") {
- tx <- read.delim(file = file,
- header = F ,
- stringsAsFactors = F,
- col.names = c("GENEID", "SYMBOL", "GENETYPE"))
- } else if(aligner == "Kallisto") {
- tx <- read.delim(file = file,
- header = F ,
- stringsAsFactors = F,
- col.names = c("GENEID", "TXNAME", "SYMBOL", "GENETYPE"))
- } else {print("Unknown aligner - plase choose STAR or Kallisto")}
- return(tx)
- }
- ```
- ### Generate norm_anno
- ```{r}
- generate_norm_anno <- function(dds_object = dds,
- annotation_file = tx_annotation){
- norm_anno <- as.data.frame(counts(dds_object, normalized=T))
- norm_anno$GENEID <- row.names(norm_anno)
- # add gene annotation
- gene_annotation <- annotation_file[!duplicated(annotation_file$GENEID), c("GENEID", "SYMBOL", "GENETYPE")]
- # merge expression table and annotation
- norm_anno <- dplyr::left_join(norm_anno, gene_annotation, by = "GENEID")
- rownames(norm_anno) <- norm_anno$GENEID
- return(norm_anno)
- }
- ```
- ### Boxplot of normalized expression per sample
- ```{r}
- boxplot_norm <- function(norm_anno = norm_anno,
- col.by = "condition",
- col.use = col_condition){
- # create a sample table just taking the sample ID and condition for boxplot visualization
- box_sample_table <- sample_table[ ,c("ID", col.by)]
- # annotation
- box_norm_table <- norm_anno[ ,colnames(norm_anno) %in% box_sample_table$ID]
- box_norm_table$GENEID <- rownames(box_norm_table)
- # restructuring the table for ggplot2 analysis w/ melt function
- box_norm_table <- melt(box_norm_table, id.vars = c("GENEID"))
- colnames(box_norm_table) <- c("GENEID","sample","expression")
- box_norm_table <- merge(box_norm_table, box_sample_table, by.x="sample", by.y="ID")
- p <- ggplot(box_norm_table, aes(x = sample , y = expression+1))+
- geom_boxplot(aes_string(fill = col.by))+
- scale_y_log10(labels = scales::label_number(big.mark = ","))+
- # scale_y_continuous() +
- scale_fill_manual(values = col.use)+
- theme_bw() +
- theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))+
- xlab("Samples") + ylab("Normalized expression") +
- ggtitle("Normalized gene expression per sample")
- plot(p)
- }
- ```
- ### Generate norm_anno
- ```{r}
- generate_vst_anno <- function(dds_object = dds_vst,
- annotation_file = tx_annotation){
- # get gene annotation
- gene_annotation <- annotation_file[!duplicated(annotation_file$GENEID), c("GENEID", "SYMBOL", "GENETYPE")]
- # vst anno log
- vst_anno_log <- as.data.frame(assay(dds_object))
- vst_anno_log$GENEID <- row.names(vst_anno_log)
- vst_anno_log <- dplyr::left_join(vst_anno_log, gene_annotation, by = "GENEID")
- rownames(vst_anno_log) <- vst_anno_log$GENEID
- # vst anno (unlog)
- vst_anno <- as.data.frame(assay(dds_object))
- vst_anno <- 2^vst_anno
- vst_anno$GENEID <- row.names(vst_anno)
- vst_anno <- dplyr::left_join(vst_anno, gene_annotation, by = "GENEID")
- rownames(vst_anno) <- vst_anno$GENEID
- vst_anno <- list("log" = vst_anno_log,
- "unlog" = vst_anno)
- return(vst_anno)
- }
- ```
- ### Heatmap
- ```{r}
- plotHeatmap <- function(input = norm_anno,
- geneset = "all",
- title = "",
- keyType = "Ensembl",
- gene_type = "all",
- cutree_cols = 1,
- show_rownames = FALSE,
- cluster_cols = FALSE,
- sample_annotation = sample_table,
- plot_mean = FALSE,
- method = "complete",
- distance = "euclidean")
- {
- if (geneset[1] != "all") {
- if (keyType == "Ensembl") {
- input <- input[input$GENEID %in% geneset, ]
- }
- else if (keyType == "Symbol") {
- input <- input[input$SYMBOL %in% geneset, ]
- }
- else {
- print("Wrong keyType. Choose Ensembl or Symbol!")
- }
- }
- if (gene_type != "all") {
- input <- input[input$GENETYPE %in% gene_type, ]
- }
- rownames(input) <- paste(input$GENEID, ":", input$SYMBOL, sep = "")
- if(plot_mean == FALSE ){
- input <- input[ , colnames(input) %in% sample_annotation$ID]
- input_scale <- t(scale(t(input)))
- input_scale <- input_scale[, order(sample_annotation[[plot_order]], decreasing = FALSE)]
- column_annotation <- plot_annotation
- } else {
- input <- input[ , colnames(input) %in% plot_annotation_mean$condition]
- input_scale <- t(scale(t(input)))
- column_annotation <- plot_annotation_mean
- }
- breaks <- scaleColors(data = input_scale, maxvalue = 2)[["breaks"]]
- pheatmap(input_scale, main = as.character(title),
- show_rownames = show_rownames,
- show_colnames = TRUE,
- cluster_cols = cluster_cols,
- clustering_method = method,
- clustering_distance_rows = distance,
- clustering_distance_cols = distance,
- fontsize = 7,
- cutree_cols = cutree_cols,
- border_color = "NA",
- annotation_col = column_annotation,
- annotation_colors = ann_colors,
- breaks = breaks,
- color = scaleColors(data = input_scale, maxvalue = 2)[["color"]])
- }
- ```
- ### Heatmap colors
- ```{r}
- scaleColors <- function(data = input_scale, # data to use
- maxvalue = NULL # value at which the color is fully red / blue
- ){
- if(is.null(maxvalue)){
- maxvalue <- floor(min(abs(min(data)), max(data)))
- }
- if(max(data) > abs(min(data))){
- if(ceiling(max(data)) == maxvalue){
- myBreaks <- c(floor(-max(data)), seq(-maxvalue+0.2, maxvalue-0.2, 0.2), ceiling(max(data)))
- } else{
- myBreaks <- c(floor(-max(data)), seq(-maxvalue, maxvalue, 0.2), ceiling(max(data)))
- }
- paletteLength <- length(myBreaks)
- myColor <- colorRampPalette(c("blue", "white", "red"))(paletteLength)
- } else {
- if(-floor(min(data)) == maxvalue){
- myBreaks <- c(floor(min(data)), seq(-maxvalue+0.2, maxvalue-0.2, 0.2), ceiling(min(data)))
- } else{
- myBreaks <- c(floor(min(data)), seq(-maxvalue, maxvalue, 0.2), ceiling(abs(min(data))))
- }
- paletteLength <- length(myBreaks)
- myColor <- colorRampPalette(c("blue", "white", "red"))(paletteLength)
- }
- ret <- list(breaks = myBreaks, color = myColor)
- return(ret)
- }
- ```
- ### PCA function
- ```{r}
- plotPCA <- function(pca_input = dds_vst,
- pca_sample_table = sample_table,
- ntop=500,
- xPC=1,
- yPC=2,
- color,
- anno_colour,
- add_density = T,
- add_silhouette = T,
- split_by = "NULL",
- shape="NULL",
- point_size=3,
- title="PCA",
- label = NULL,
- label_subset = NULL){
- if(is.character(pca_input)){
- vst_matrix <- as.matrix(removedbatch_dds_vst)
- }else if(!is.data.frame(pca_input)){
- vst_matrix <- as.matrix(assay(pca_input))
- }else{
- vst_matrix <- pca_input
- }
- if(length(ntop)>1){
- pca <- prcomp(t(vst_matrix[dimnames(vst_matrix)[[1]] %in% ntop,]))
- }else if (ntop == "all"){
- pca <- prcomp(t(vst_matrix))
- }else{
- # select the ntop genes by variance
- select <- order(rowVars(vst_matrix), decreasing=TRUE)[c(1:ntop)]
- pca <- prcomp(t(vst_matrix[select,]))
- }
- #calculate explained variance per PC
- explVar <- pca$sdev^2/sum(pca$sdev^2)
- # transform variance to percent
- percentVar <- round(100 * explVar[c(xPC,yPC)], digits=1)
- # Define data for plotting
- pcaData <- data.frame(xPC=pca$x[,xPC],
- yPC=pca$x[,yPC],
- color = pca_sample_table[[color]],
- name= as.character(pca_sample_table$ID),
- stringsAsFactors = F)
- #plot PCA
- if(is.factor(pcaData$color) || is.character(pcaData$color)|| is.integer(pcaData$color)){
- if(shape == "NULL"){
- pca_plot <- ggplot(pcaData, aes(x = xPC, y = yPC, colour=color)) +
- geom_point(size =point_size)
- }else{
- pcaData$shape = pca_sample_table[[shape]]
- pca_plot <- ggplot(pcaData, aes(x = xPC, y = yPC, color = color, shape=shape)) +
- geom_point(size =point_size) +
- scale_shape_discrete(name=shape)
- }
- if(add_silhouette){
- pca_plot <- pca_plot + stat_ellipse(geom = "polygon", aes(fill = color), alpha = 0.05)
- }
- if(anno_colour[1] == "NULL"){
- pca_plot <- pca_plot + scale_color_discrete(name=color)
- }else{
- pca_plot <- pca_plot + scale_color_manual(values=anno_colour, name=color, aesthetics = c("colour", "fill"))
- }
- }else if(is.numeric(pcaData$color)){
- if(shape == "NULL"){
- pca_plot <- ggplot(pcaData, aes(x = xPC, y = yPC, colour=color)) +
- geom_point(size =point_size) +
- scale_color_gradientn(colours = bluered(100),name=color) +
- scale_fill_gradientn(colours = bluered(100),name=color)
- }else{
- pcaData$shape = pca_sample_table[[shape]]
- pca_plot <- ggplot(pcaData, aes(x = xPC, y = yPC, colour=color, shape=shape)) +
- geom_point(size =point_size) +
- scale_color_gradientn(colours = bluered(100),name=color) +
- scale_fill_gradientn(colours = bluered(100),name=color) +
- scale_shape_discrete(name=shape)
- }
- }
- # adds a label to the plot. To label only specific points, put them in the arument label_subset
- if (!is.null(label) == TRUE){
- pcaData$label <- pca_sample_table[[label]]
- if(!is.null(label_subset) == TRUE){
- pcaData_labeled <- pcaData[pcaData$label %in% label_subset,]
- } else {
- pcaData_labeled <- pcaData
- }
- pca_plot <- pca_plot +
- geom_text_repel(data = pcaData_labeled, aes(label = label), nudge_x = 2, nudge_y = 2, colour = "black")
- }
- pca_plot <- pca_plot+
- xlab(paste0("PC ",xPC, ": ", percentVar[1], "% variance")) +
- ylab(paste0("PC ",yPC,": ", percentVar[2], "% variance")) +
- coord_fixed()+
- theme_bw()+
- theme(aspect.ratio = 1,
- legend.position = "bottom")+
- ggtitle(title)
- if(add_density){
- ggMarginal(pca_plot, groupFill = T, type = "density")
- } else if (split_by != "NULL"){
- pca_plot + facet_wrap(~pca_sample_table[[split_by]])
- } else {
- pca_plot
- }
- }
- ```
- ### Wrapper Function to perform DESeq2 differential testing
- ```{r}
- DEAnalysis <- function(input = dds,
- condition,
- comparison_table = comparison_table,
- alpha = 0.05,
- lfcThreshold = 0,
- sigFC = 2,
- multiple_testing = "IHW",
- pAdjustMethod = "BH",
- independentFiltering= TRUE,
- shrinkage = TRUE,
- shrinkType = "normal"){
- setClass(Class = "DESeq2_analysis_object",
- slots = c(results="data.frame", DE_genes="list", Number_DE_genes="list"))
- # create results_list
- results_list <- list()
- # print parameters
- results_list$parameters <-list(multiple_testing = multiple_testing,
- p_value_threshold = alpha,
- log2_FC_threshold = lfcThreshold,
- sigFC = sigFC,
- shrinkage = shrinkage,
- shrinkage_type = shrinkType)
- # Run results() function on comparisons defined in comparison table
- for (x in 1:nrow(comparison_table)){
- # create DE_object
- DE_object <- new(Class = "DESeq2_analysis_object")
- # IHW
- if (multiple_testing=="IHW") {
- res_deseq_lfc <- results(input,
- contrast = c(condition,
- paste(comparison_table$comparison[x]),
- paste(comparison_table$control[x])),
- lfcThreshold = lfcThreshold,
- alpha = alpha,
- filterFun = ihw,
- pAdjustMethod = pAdjustMethod,
- altHypothesis = "greaterAbs")
- # Independent Filtering
- }else {
- res_deseq_lfc <- results(input,
- contrast = c(condition,
- paste(comparison_table$comparison[x]),
- paste(comparison_table$control[x])),
- lfcThreshold = lfcThreshold,
- alpha = alpha,
- independentFiltering = independentFiltering,
- altHypothesis = "greaterAbs",
- pAdjustMethod= pAdjustMethod)
- }
- if(shrinkage == TRUE){
- if(shrinkType %in% c("normal", "ashr")){
- res_deseq_lfc <- lfcShrink(input,
- contrast = c(condition,
- paste(comparison_table$comparison[x]),
- paste(comparison_table$control[x])),
- res=res_deseq_lfc,
- type = shrinkType)
- }else if(shrinkType == "apeglm"){
- res_deseq_lfc <- lfcShrink(input,
- coef = paste0(condition, "_",
- comparison_table$comparison[x], "_vs_",
- comparison_table$control[x]),
- res=res_deseq_lfc,
- type = shrinkType,
- returnList = F)
- }
- }
- res_deseq_lfc <- as.data.frame(res_deseq_lfc)
- # indicate significant DE genes
- res_deseq_lfc$regulation <- ifelse(!is.na(res_deseq_lfc$padj)&
- res_deseq_lfc$padj <= alpha&
- res_deseq_lfc$log2FoldChange > log(sigFC,2),
- "up",
- ifelse(!is.na(res_deseq_lfc$padj)&
- res_deseq_lfc$padj <= alpha&
- res_deseq_lfc$log2FoldChange < -log(sigFC,2),
- "down",
- "n.s."))
- # add gene annotation to results table
- res_deseq_lfc$GENEID <- row.names(res_deseq_lfc)
- res_deseq_lfc <- merge(res_deseq_lfc,
- norm_anno[,c("GENEID",
- "SYMBOL",
- "GENETYPE")],
- by = "GENEID")
- row.names(res_deseq_lfc) <- res_deseq_lfc$GENEID
- res_deseq_lfc$comparison<-paste(comparison_table$comparison[x]," vs ",comparison_table$control[x],
- sep="")
- # re-order results table
- if (multiple_testing=="IHW") {
- res_deseq_lfc<-res_deseq_lfc[,c("GENEID",
- "SYMBOL",
- "GENETYPE",
- "comparison",
- "regulation",
- "baseMean",
- "log2FoldChange",
- "lfcSE",
- "pvalue",
- "padj"
- )]
- }else{
- res_deseq_lfc<-res_deseq_lfc[,c("GENEID",
- "SYMBOL",
- "GENETYPE",
- "comparison",
- "regulation",
- "baseMean",
- "log2FoldChange",
- "lfcSE",
- "pvalue",
- "padj")]
- }
- # print result table
- DE_object@results <- res_deseq_lfc
- # print DE genes in separate tables
- DE_object@DE_genes <- list(up_regulated_Genes = res_deseq_lfc[res_deseq_lfc$regulation =="up",],
- down_regulated_Genes= res_deseq_lfc[res_deseq_lfc$regulation =="down",])
- # print the numbers of DE genes
- DE_object@Number_DE_genes <- list(up_regulated_Genes = nrow(DE_object@DE_genes$up_regulated_Genes),
- down_regulated_Genes= nrow(DE_object@DE_genes$down_regulated_Genes))
- # write DE_object into results_list
- results_list[[paste(comparison_table$comparison[x], "vs", comparison_table$control[x], sep="_")]] <- DE_object
- }
- return(results_list)
- }
- ```
- ### Venn Diagram
- ```{r}
- plotVenn <- function(comparisons,
- regulation=NULL){
- venn <- NULL
- for(i in 1:length(comparisons)){
- res <- DEresults[names(DEresults) %in% comparisons]
- comp <- as.data.frame(res[[i]]@results)
- if(is.null(regulation)){
- DE <- ifelse(comp$regulation %in% c("up","down"), 1, 0)
- venn <- cbind(venn, DE)
- colnames(venn)[i]<- paste(names(res)[[i]], "up&down", sep=": ")
- } else {
- DE <- ifelse(comp$regulation == regulation, 1, 0)
- venn <- cbind(venn, DE)
- colnames(venn)[i]<- paste(names(res)[[i]], regulation, sep=": ")
- }
- }
- vennDiagram(venn,cex = 1, counts.col = "blue")
- }
- ```
- ### GSEA function
- ```{r}
- #' wrapper function for GSEA on different DE calls
- #' @author Charlotte Kröger, Lisa Holsten, Kilian Dahm
- #' @param comparisons name of DE analysis comparisons (class: character)
- #' @param DE_results list object containing DE analysis results (class: list)
- #' @param universe vector of all genes included in the analysis
- #' @param GeneSets databases to be used, one of : 'GO', 'KEGG' or 'HALLMARK'
- #' @param ontology ontology of the GO database to be used, one of: 'BP', 'MF', 'CC'
- #' @param pCorrection p-value adjustment method such as 'BH' (less strict) or 'bonferroni'
- #' @param pvalueCutoff set the unadj. or adj. p-value cutoff (depending on correction method)
- #' @param qvalueCutoff set the q-value (adj. p-value) cutoff
- #'
- enrichGSEA <- function(comparisons,
- DE_results = DEresults,
- universe = universe,
- GeneSets = c("GO","KEGG", "HALLMARK", "REACTOME"),
- pCorrection = "bonferroni",
- pvalueCutoff = 0.05,
- qvalueCutoff = 0.05){
- ## Results lists
- GOresults.list <- list()
- KEGGresults.list <- list()
- HALLMARKresults.list <- list()
- REACTOMEresults.list <- list()
- ## Enrichment
- for(i in comparisons){
- print(paste0("Performing enrichment for ", i))
- ## DEGs
- genes <- DE_results[[i]]@results
- DE_up <- genes[genes$regulation=="up",]$SYMBOL
- DE_down <- genes[genes$regulation=="down",]$SYMBOL
- # Compare the Clusters regarding their GO enrichment
- if("GO" %in% GeneSets){
- print("Performing GO enrichment")
- resGOup <- as.data.frame(enricher(gene = DE_up,
- universe = universe,
- TERM2GENE= GO_terms,
- pAdjustMethod = pCorrection,
- pvalueCutoff = pvalueCutoff,
- qvalueCutoff = qvalueCutoff))
- if(nrow(resGOup)>0){
- resGOup$comparison <- paste0(as.character(i), "_up")
- resGOup$regulation <- "up"
- GOresults.list[[paste(i, "_up")]] <- resGOup
- }
- resGOdown <- as.data.frame(enricher(gene = DE_down,
- universe = universe,
- TERM2GENE= GO_terms,
- pAdjustMethod = pCorrection,
- pvalueCutoff = pvalueCutoff,
- qvalueCutoff = qvalueCutoff))
- if(nrow(resGOdown)>0){
- resGOdown$comparison <- paste0(as.character(i), "_down")
- resGOdown$regulation <- "down"
- GOresults.list[[paste(i, "_down")]] <- resGOdown
- }
- }
- # Compare the Clusters regarding their HALLMARK enrichment
- if("HALLMARK" %in% GeneSets){
- print("Performing HALLMARK enrichment")
- resHMup <- as.data.frame(enricher(gene = DE_up,
- universe = universe,
- TERM2GENE = HALLMARK_terms,
- pAdjustMethod = pCorrection,
- pvalueCutoff = pvalueCutoff,
- qvalueCutoff = qvalueCutoff))
- if(nrow(resHMup)>0){
- resHMup$comparison <- paste0(as.character(i), "_up")
- resHMup$regulation <- "up"
- HALLMARKresults.list[[paste(i, "_up")]] <- resHMup
- }
- resHMdown <- as.data.frame(enricher(gene = DE_down,
- universe = universe,
- TERM2GENE = HALLMARK_terms,
- pAdjustMethod = pCorrection,
- pvalueCutoff = pvalueCutoff,
- qvalueCutoff = qvalueCutoff))
- if(nrow(resHMdown)>0){
- resHMdown$comparison <- paste0(as.character(i), "_down")
- resHMdown$regulation <- "down"
- HALLMARKresults.list[[paste(i, "_down")]] <- resHMdown
- }
- }
- # Compare the Clusters regarding their KEGG enrichment
- if("KEGG" %in% GeneSets){
- print("Performing KEGG enrichment")
- resKEGGup <- as.data.frame(enricher(gene = DE_up,
- universe = universe,
- TERM2GENE = KEGG_terms,
- pAdjustMethod = pCorrection,
- pvalueCutoff = pvalueCutoff,
- qvalueCutoff = qvalueCutoff))
- if(nrow(resKEGGup)>0){
- resKEGGup$comparison <- paste0(as.character(i), "_up")
- resKEGGup$regulation <- "up"
- KEGGresults.list[[paste(i, "_up")]] <- resKEGGup
- }
- resKEGGdown <- as.data.frame(enricher(gene = DE_down,
- universe = universe,
- TERM2GENE = KEGG_terms,
- pAdjustMethod = pCorrection,
- pvalueCutoff = pvalueCutoff,
- qvalueCutoff = qvalueCutoff))
- if(nrow(resKEGGdown)>0){
- resKEGGdown$comparison <- paste0(as.character(i), "_down")
- resKEGGdown$regulation <- "down"
- KEGGresults.list[[paste(i, "_down")]] <- resKEGGdown
- }
- }
- # Compare the Clusters regarding their REACTOME enrichment
- if("REACTOME" %in% GeneSets){
- print("Performing REACTOME enrichment")
- resREACTOMEup <- as.data.frame(enricher(gene = DE_up,
- universe = universe,
- TERM2GENE = REACTOME_terms,
- pAdjustMethod = pCorrection,
- pvalueCutoff = pvalueCutoff,
- qvalueCutoff = qvalueCutoff))
- if(nrow(resREACTOMEup)>0){
- resREACTOMEup$comparison <- paste0(as.character(i), "_up")
- resREACTOMEup$regulation <- "up"
- REACTOMEresults.list[[paste(i, "_up")]] <- resREACTOMEup
- }
- resREACTOMEdown <- as.data.frame(enricher(gene = DE_down,
- universe = universe,
- TERM2GENE = REACTOME_terms,
- pAdjustMethod = pCorrection,
- pvalueCutoff = pvalueCutoff,
- qvalueCutoff = qvalueCutoff))
- if(nrow(resREACTOMEdown)>0){
- resREACTOMEdown$comparison <- paste0(as.character(i), "_down")
- resREACTOMEdown$regulation <- "down"
- REACTOMEresults.list[[paste(i, "_down")]] <- resREACTOMEdown
- }
- }
- }
- GOresults <- do.call("rbind", GOresults.list)
- HALLMARKresults <- do.call("rbind", HALLMARKresults.list)
- KEGGresults <- do.call("rbind", KEGGresults.list)
- REACTOMEresults <- do.call("rbind", REACTOMEresults.list)
- results.list <- list("GO" = GOresults,
- "HALLMARK" = HALLMARKresults,
- "KEGG" = KEGGresults,
- "REACTOME" = REACTOMEresults)
- return(results.list)
- }
- ```
- ### GSEA dotplot
- ```{r}
- #' wrapper function for combined dotplot representation of all comparisons used in the enrichGSEA function
- #' @author Charlotte Kröger, Lisa Holsten, Kilian Dahm
- #' @param enrich.df data frame of enrichGSEA function
- #' @param show number of terms to be shown per comparison
- #' @param orderBy parameter for ordering terms on the y-axis
- #' @param colorBy parameter for coloring the dots
- #' @param scaleBy parameter for scaling the dots
- #'
- dotplotGSEA <- function(enrich.df,
- show =10,
- orderBy = c("padj", "count", "GeneRatio"),
- colorBy = c("padj", "regulation"),
- scaleBy = c("count", "GeneRatio")
- ){
- if(nrow(enrich.df)<1){ print("No enrichment found.")
- } else{
- # ordering
- enrich.df$gene.ratio <- sapply(strsplit(enrich.df$GeneRatio, split = "/"), function(x) as.numeric(x[1]) / as.numeric(x[2]))
- if(orderBy=="padj"){
- enrich.df %>% group_by(comparison) %>% arrange(desc(Count), .by_group = TRUE) -> x
- x %>% group_by(comparison) %>% arrange(desc(Count), .by_group = TRUE) %>% dplyr::top_n(n = -show, wt = p.adjust) %>% dplyr::pull(Description) -> terms
- x <- x[x$Description %in% terms,]
- x$Description <- ifelse(nchar(x$Description)>80, paste(substr(x$Description, 1, 80),"[...]",sep=""), x$Description)
- x$Description <- factor(x$Description, levels = rev(unique(x$Description)))
- } else if (orderBy=="count"){
- enrich.df %>% group_by(comparison) %>% arrange(p.adjust, .by_group = TRUE) -> x
- x %>% group_by(comparison) %>% arrange(p.adjust, .by_group = TRUE) %>% dplyr::top_n(n = show, wt = Count) %>% dplyr::pull(Description) -> terms
- x <- x[x$Description %in% terms,]
- x$Description <- ifelse(nchar(x$Description) > 80, paste(substr(x$Description, 1, 80),"[...]",sep=""), x$Description)
- x$Description <- factor(x$Description, levels = rev(unique(x$Description)))
- } else if (orderBy=="GeneRatio"){
- enrich.df %>% group_by(comparison) %>% arrange(p.adjust, .by_group = TRUE) -> x
- x %>% group_by(comparison) %>% arrange(p.adjust, .by_group = TRUE) %>% dplyr::top_n(n = show, wt = gene.ratio) %>% dplyr::pull(Description) -> terms
- x <- x[x$Description %in% terms,]
- x$Description <- ifelse(nchar(x$Description) > 80, paste(substr(x$Description, 1, 80),"[...]",sep=""), x$Description)
- x$Description <- factor(x$Description, levels = rev(unique(x$Description)))
- }else {
- "Please select orderBy='padj', orderBy='count'or orderBy='GeneRatio'."
- }
- ## coloring
- if(colorBy=="regulation" & scaleBy == "count"){
- p <- ggplot(data = x ,aes(x=comparison, y=Description, size=Count , fill=regulation)) +
- geom_point(pch=21) +
- scale_fill_manual(values = c(up = "firebrick4", down = "dodgerblue3")) +
- xlab("") +
- ylab("") +
- scale_radius() +
- theme_linedraw()+
- theme(axis.text.y = element_text(color = "black"),
- axis.text.x = element_text(angle=90, vjust=0.5,hjust=1, color = "black"),
- text = element_text(size = 12),
- panel.grid.major = element_line(colour = "grey70"))
- plot(p)
- } else if (colorBy=="regulation" & scaleBy == "GeneRatio"){
- p <- ggplot(data = x ,aes(x=comparison, y=Description, size=gene.ratio , fill=regulation)) +
- geom_point(pch=21) +
- scale_fill_manual(values = c(up = "firebrick4", down = "dodgerblue3")) +
- xlab("") +
- ylab("") +
- scale_radius() +
- theme_linedraw()+
- theme(axis.text.y = element_text(color = "black"),
- axis.text.x = element_text(angle=90, vjust=0.5,hjust=1, color = "black"),
- text = element_text(size = 12),
- panel.grid.major = element_line(colour = "grey70"))
- plot(p)
- } else if (colorBy=="padj" & scaleBy=="count"){
- p <- ggplot(data = x, aes(x=comparison, y=Description, size=Count, color=p.adjust)) +
- geom_point(pch=21) +
- scale_colour_gradientn(colours = c('red', 'orange', 'darkblue', 'darkblue'),
- limits = c(0, 1),
- values = c(0, 0.05, 0.2, 0.5, 1),
- breaks = c(0.05, 0.2, 1),
- labels = format(c(0.05, 0.2, 1))) +
- xlab("") +
- ylab("") +
- scale_radius() +
- theme_linedraw()+
- theme(axis.text.y = element_text(color = "black"),
- axis.text.x = element_text(angle=90, vjust=0.5, hjust=1, color = "black"),
- text = element_text(size = 12),
- panel.grid.major = element_line(colour = "grey70"))
- plot(p)
- } else if (colorBy=="padj" & scaleBy=="GeneRatio"){
- p <- ggplot(data = x, aes(x=comparison, y=Description, size=gene.ratio, color=p.adjust)) +
- geom_point(pch=21) +
- scale_colour_gradientn(colours = c('red', 'orange', 'darkblue', 'darkblue'),
- limits = c(0, 1),
- values = c(0, 0.05, 0.2, 0.5, 1),
- breaks = c(0.05, 0.2, 1),
- labels = format(c(0.05, 0.2, 1))) +
- xlab("") +
- ylab("") +
- scale_radius() +
- theme_linedraw()+
- theme(axis.text.y = element_text(color = "black"),
- axis.text.x = element_text(angle=90, vjust=0.5,hjust=1, color = "black"),
- text = element_text(size = 12),
- panel.grid.major = element_line(colour = "grey70"))
- plot(p)
- }else {
- "Please select colorBy='regulation' or colorBy='padj' and scaleBy='count' or scaleBy='GeneRatio'."
- }
- }
- }
- ```
- ### Volcano Plot
- ```{r}
- plotVolcano <- function(DEresults_obj = DEresults,
- comparison,
- labelnum=20,
- y.max = NULL,
- signature = NULL){
- # specify labeling
- upDE <- as.data.frame(DEresults_obj[[comparison]]@results[DEresults_obj[[comparison]]@results$regulation =="up",])
- if(!is.null(signature))
- upDE <- upDE %>% dplyr::filter(.,SYMBOL %in% signature)
- FClabel_up <- upDE[order(abs(upDE$log2FoldChange), decreasing = TRUE),]
- if(nrow(FClabel_up)>labelnum){
- FClabel_up <- as.character(FClabel_up[c(1:labelnum),"GENEID"])
- } else {
- FClabel_up <- as.character(FClabel_up$GENEID)}
- plabel_up <- upDE[order(upDE$padj, decreasing = FALSE),]
- if(nrow(plabel_up)>labelnum){
- plabel_up <- as.character(plabel_up[c(1:labelnum),"GENEID"])
- } else {
- plabel_up <- as.character(plabel_up$GENEID)}
- downDE <- as.data.frame(DEresults_obj[[comparison]]@results[DEresults_obj[[comparison]]@results$regulation =="down",])
- if(!is.null(signature))
- downDE <- downDE %>% dplyr::filter(SYMBOL %in% signature)
- FClabel_down <- downDE[order(abs(downDE$log2FoldChange), decreasing = TRUE),]
- if(nrow(FClabel_down)>labelnum){
- FClabel_down <- as.character(FClabel_down[c(1:labelnum),"GENEID"])
- } else {
- FClabel_down <- as.character(FClabel_down$GENEID)}
- plabel_down <- downDE[order(downDE$padj, decreasing = FALSE),]
- if(nrow(plabel_down)>labelnum){
- plabel_down <- as.character(plabel_down[c(1:labelnum),"GENEID"])
- } else {
- plabel_down <- as.character(plabel_down$GENEID)}
- label<- unique(c(FClabel_up, plabel_up, FClabel_down, plabel_down))
- data <- DEresults_obj[[comparison]]@results
- data$label<- ifelse(data$GENEID %in% label == "TRUE",as.character(data$SYMBOL), "")
- data <- data[,colnames(data) %in% c("label", "log2FoldChange", "padj", "regulation")]
- data$color <- apply(data, 1, function(x){
- if(x["label"] != "") "black"
- else x["regulation"]
- }) %>% unlist()
- limits <- ceiling(max(DEresults_obj[[comparison]]@results$log2FoldChange))
- # Volcano Plot
- volcano <- ggplot(data=na.omit(data), aes(x=log2FoldChange, y=-log10(padj), fill=regulation, color = color)) +
- geom_point(shape = 21, alpha=0.75, size=1.75) +
- scale_color_manual(values = c(c("down" = "dodgerblue3","n.s." = "grey","up" = "firebrick", "black" = "black"))) +
- scale_fill_manual(values=c("down" = "dodgerblue3", "n.s." = "grey", "up" = "firebrick"))+
- xlab("log2(FoldChange)") +
- ylab("-log10(padj)") +
- geom_vline(xintercept = c(-log(DEresults_obj$parameters$sigFC,2),log(DEresults_obj$parameters$sigFC,2)), colour="darkgrey", linetype = "dashed")+
- geom_hline(yintercept=-log(0.05,10),colour="darkgrey", linetype = "dashed")+
- geom_text_repel(data=na.omit(data[!data$label =="",]),aes(label=label), size=3)+
- scale_x_continuous(limits = c(-(limits), limits), breaks = seq(-(limits), limits, by=1))+
- guides(color="none") +
- ggtitle(paste("Volcano Plot of: ",comparison,sep="")) +
- theme_bw() +
- theme(panel.grid.minor = element_blank())
- if(!is.null(y.max))
- volcano <- volcano +
- scale_y_continuous(limits = c(0, y.max), breaks = seq(0, y.max, by=1))
- else
- volcano <- volcano +
- scale_y_continuous()
- volcano
- }
- ```
- # 2. Project information
- ```{r}
- organism = "mouse"
- ```
- # 3. Data Import
- ## 3.1 Load gene annotation
- ```{r gene annotation import}
- tx_annotation <- tx_import(file = "/data/references/mouse/mm10/ID2SYMBOL_gencode_vM25.txt",
- aligner = "STAR")
- ```
- ## 3.2 Load gene set annotation
- ```{r}
- GO_terms <- read.gmt("/data/analysis/m5.go.bp.v2024.1.Mm.symbols.gmt")
- ```
- ## 3.3 Load sample table
- ```{r sample table import}
- # Import your sample table
- sample_table <- read.xlsx("/data/analysis/sample_table_final.xlsx")
- rownames(sample_table) <- sample_table$ID
- sample_table
- ```
- ### Format sample table
- ```{r colour definitions}
- unique(sample_table$condition)
- ## Add columns with factors for comparisons in model
- sample_table$condition <- factor(sample_table$condition,
- levels = c("crtx_PBS","crtx_IgG","crtx_LON5","hippo_PBS","hippo_IgG","hippo_LON5"))
- sample_table$tissue <- factor(sample_table$tissue,
- levels = c("crtx", "hippo"))
- sample_table$treat<- factor(sample_table$treat,
- levels = c("PBS", "IgG", "LON5"))
- sample_table$donor <- factor(sample_table$donor,
- levels= c("14", "32", "33", "38", "74", "10", "11", "15", "37", "75", "8", "9", "16", "17"))
- # define factor for order of samples in plotting
- plot_order <- c("condition")
- ```
- ### Colour scheme customization
- ```{r}
- col_condition <- c("#C2E0EB", "#83C5BE","#006D77", "#FFDDD2","#E29578", "#CA582B")
- names(col_condition) <- c("crtx_PBS","crtx_IgG","crtx_LON5","hippo_PBS","hippo_IgG","hippo_LON5")
- col_tissue <- c("#006D77", "#CA582B")
- names(col_tissue) <- c("crtx", "hippo")
- col_treatment <- c("#fefae0", "#dda15e","#bc6c25" )
- names(col_treatment) <- c("PBS", "IgG", "LON5")
- col_donor <- c("#155289", "#95AAD3", "#B9DBF4", "#B8E2DE", "#94C47D", "#F0CF7F", "#F6BF93","#EDAEAE", "#E07F80", "#780000", "#C195C4", "#9B5C97", "#C43E96", "grey")
- names(col_donor) <- c("14", "32", "33", "38", "74", "10", "11", "15", "37", "75", "8", "9", "16", "17")
- # combine color code into list
- ann_colors <- list(condition= col_condition,
- tissue = col_tissue,
- treat = col_treatment,
- donor = col_donor
- )
- ```
- ```{r}
- alignstat <-sample_table[ , c("ID", "uniquely_mapped","total_reads")]
- alignstat <-gather(alignstat, "total_reads", "uniquely_mapped", key = "type", value = "reads")
- ggplot(alignstat, aes(x = reorder(ID,-reads), y = reads, fill = type)) +
- geom_bar(stat = "identity", position = "dodge", colour = "black") +
- scale_y_continuous(labels = scales::label_number(big.mark = ",")) +
- scale_fill_manual(name = "", values = c("white", "grey")) +
- ylab("Number of reads") +
- xlab("Sample IDs") +
- geom_hline(yintercept=5 * 10^6, linetype="dashed", color = "red") +
- ggtitle("Total reads and uniquely mapped reads") +
- theme(axis.text.x = element_text(angle = 90, size = 9, hjust = 1, vjust = .5),
- strip.background = element_rect(fill = "white"),
- panel.background = element_rect(fill = "white", colour = "black"),
- legend.position = "bottom")
- rm(alignstat)
- ```
- ### QC
- ```{r qc sample exclusion}
- # define read cutoff
- samples_to_keep <- sample_table[sample_table$uniquely_mapped > 5000000,]$ID
- length(samples_to_keep)
- nrow(sample_table) - length(samples_to_keep)
- sample_table <- sample_table[which(sample_table$ID %in% samples_to_keep),]
- rownames(sample_table) <- sample_table$ID
- ```
- # 4. Import of count files
- ```{r}
- star.count <- read.table(file = "/data/analysis/count_matrix.tsv",
- row.names = 1,
- header = T,
- stringsAsFactors = F,
- check.names = F)
- star.count <- star.count[, colnames(star.count) %in% sample_table$ID]
- ```
- # 5. Building the DESeqDataSet
- ```{r}
- identical(as.character(rownames(sample_table)), as.character(colnames(star.count)))
- # Reorder the rows of the sample_table matrix if necessary (based on Occam's razor [least number of moves for reordering])
- sample_table <- sample_table[match(colnames(star.count), rownames(sample_table)),]
- dds_txi <- DESeqDataSetFromMatrix(countData = star.count,
- colData = sample_table,
- design = ~condition)
- rm(star.count)
- ```
- ## 5.1 Pre-filtering
- ```{r pre-filtering}
- genes_to_keep <- rowSums(counts(dds_txi) >= 10) >= min(table(sample_table$condition)) #number of donors and number of different input amounts
- table(genes_to_keep)
- dds <- dds_txi[genes_to_keep,]
- ```
- **Number of genes after filtering is:** `r sum(genes_to_keep) `
- ## 5.2 DESeq calculations
- ```{r DESeq calculation}
- dds <- DESeq(dds)
- ```
- ## 5.3 Normalized counts
- ```{r gene annotation}
- norm_anno <- generate_norm_anno(dds_object = dds)
- ```
- Boxplot of normalized samples
- ```{r, fig.height=5, fig.width=8}
- boxplot_norm(norm_anno = norm_anno,
- col.by = "condition",
- col.use = col_condition)
- ```
- ## 5.4 Variance stabilizing transformation
- ```{r varStab}
- if (nrow(colData(dds)) < 30) {
- dds_vst <- rlog(dds, blind = TRUE)
- } else dds_vst <- vst(dds, blind = TRUE)
- ```
- ```{r vst matrix}
- vst <- generate_vst_anno(dds_object = dds_vst)
- vst_anno_log <- vst$log
- vst_anno <- vst$unlog
- ncol(vst_anno_log)
- nrow(sample_table)
- vst_anno_log[1:3,c(1:2, (ncol(vst_anno_log)-5):ncol(vst_anno_log))]
- vst_anno[1:3,c(1:2, (ncol(vst_anno)-5):ncol(vst_anno))]
- ```
- # 6. Exploratory Data Analysis
- ```{r}
- # choose columns from the sample table for the heatmap annotation
- plot_annotation <- sample_table[ , c("condition",
- "donor",
- "treat",
- "tissue"),
- drop = F]
- rownames(plot_annotation) <- sample_table$ID
- ```
- ## 6.2 Principle Component Analysis
- ### Supplementary Figure S3 i
- ```{r, fig.width=6, fig.height=5}
- plotPCA(ntop = "all",
- xPC = 1,
- yPC = 2,
- color = "condition",
- anno_colour = col_condition,
- shape = "input",
- point_size = 3,
- add_density = F,
- add_silhouette = F,
- label = NULL,
- title ="Condition")
- ```
- # 7. Differential Expression Analysis
- ```{r}
- comparison_table <- data.frame(control = c("crtx_PBS" ,"crtx_PBS" ,"crtx_IgG" , "hippo_PBS", "hippo_PBS", "hippo_IgG"),
- comparison = c("crtx_IgG" , "crtx_LON5", "crtx_LON5","hippo_IgG", "hippo_LON5", "hippo_LON5" ))
- ```
- ```{r}
- dds_dea <- dds
- DEresults_list <- list()
- for (i in unique(comparison_table$control)) {
- print(i)
- dds_dea$condition <- relevel(dds_dea$condition, i)
- dds_dea <- nbinomWaldTest(object = dds_dea)
- comparison_table_subset <- comparison_table[comparison_table$control == i, ]
- DEresults <- DEAnalysis(input = dds_dea,
- comparison_table = comparison_table_subset,
- condition = "condition",
- alpha = 0.05 ,
- lfcThreshold = 0,
- sigFC = 2,
- multiple_testing = "IHW",
- pAdjustMethod = "BH",
- shrinkage = TRUE,
- shrinkType = "apeglm")
- DEresults_list <- c(DEresults_list, DEresults)
- }
- DEresults <- DEresults_list[unique(names(DEresults_list))]
- ```
- ### Summary of DE genes
- #### Figure 3 j
- ```{r, fig.height=3, fig.width=6}
- DEcounts <- NULL
- for(i in 1:nrow(comparison_table)){
- tmp <- unlist(DEresults[[1+i]]@Number_DE_genes)
- DEcounts <- rbind(DEcounts, tmp)
- }
- rownames(DEcounts) <- names(DEresults)[-1]
- DEcounts
- DEcounts_melt <- reshape2::melt(DEcounts)
- # ggplot(DEcounts_melt, aes(x = Var1, fill = Var2)) +
- # geom_col(aes(y = value), position = "dodge", color = "black") +
- # geom_text(aes(label = value, y = value), position = position_dodge(.9), hjust=1) +
- # theme_bw()+
- # theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = .5)) +
- # scale_fill_manual(values = c("up_regulated_Genes" = "firebrick", "down_regulated_Genes" = "cornflowerblue")) +
- # guides(fill = guide_legend(title = "Mode of regulation")) +
- # xlab("Comparison") + ylab("Number of DEGs") + coord_flip()
- ggplot(DEcounts_melt[DEcounts_melt$Var1 %in% c("hippo_IgG_vs_hippo_PBS", "hippo_LON5_vs_hippo_PBS", "hippo_LON5_vs_hippo_IgG"),], aes(x = Var1, fill = Var2)) +
- geom_col(aes(y = value), position = "dodge", color = "black") +
- geom_text(aes(label = value, y = value), position = position_dodge(.9), hjust=1) +
- theme_bw()+
- theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = .5)) +
- scale_fill_manual(values = c("up_regulated_Genes" = "firebrick", "down_regulated_Genes" = "cornflowerblue")) +
- guides(fill = guide_legend(title = "Mode of regulation")) +
- xlab("Comparison") + ylab("Number of DEGs") + coord_flip()
- ```
- ### Upset Plot
- #### Supplementary Figure S3 k
- ```{r}
- list_up <- list()
- list_down <- list()
- for(i in 1:nrow(comparison_table)){
- comp <- paste0(comparison_table[i,2], "_vs_", comparison_table[i,1])
- list_up[[paste0(comp, "_up")]] <- DEresults[[comp]]@DE_genes[["up_regulated_Genes"]][["SYMBOL"]]
- list_down[[paste0(comp, "_down")]] <- DEresults[[comp]]@DE_genes[["down_regulated_Genes"]][["SYMBOL"]]
- }
- upset(fromList(list_up), nsets = 10,nintersects = 100, keep.order = F, sets.bar.color = "firebrick")
- upset(fromList(list_down), nsets = 10,nintersects = 100, keep.order = F, sets.bar.color = "dodgerblue")
- ```
- ## 7.2 General DE Gene analysis
- ### Venn diagrams
- #### Supplementary Figure S3 j
- ```{r, fig.height=6, fig.width=6}
- # plotVenn(comparisons = c("hippo_LON5_vs_hippo_IgG","hippo_LON5_vs_hippo_PBS", "crtx_LON5_vs_crtx_IgG", "crtx_LON5_vs_crtx_PBS"),
- # regulation ="up")
- plotVenn(comparisons = c("hippo_LON5_vs_hippo_IgG", "crtx_LON5_vs_crtx_IgG"),
- regulation ="up")
- plotVenn(comparisons = c("hippo_LON5_vs_hippo_PBS", "crtx_LON5_vs_crtx_PBS"),
- regulation ="up")
- ```
- ### Gene Set Enrichment of DE genes
- ```{r}
- # define universe
- universe <- unique(as.character(norm_anno$SYMBOL))
- ```
- ```{r, warnings=FALSE, message=FALSE}
- GSEA_results <- enrichGSEA(comparisons = "hippo_LON5_vs_hippo_IgG",
- DE_results = DEresults,
- universe = universe,
- GeneSets = c("GO"),#, "HALLMARK", "REACTOME"
- pCorrection = "bonferroni",
- pvalueCutoff = 0.05,
- qvalueCutoff = 0.05)
- ```
- ```{r}
- GSEA_results$GO$comparison <-
- factor(GSEA_results$GO$comparison,
- levels = c(unique(GSEA_results$GO$comparison)))
- ```
- Figure 3 l
- ```{r, fig.height=6, fig.width=15}
- dotplotGSEA(enrich.df = GSEA_results$GO, show = 20, orderBy = "padj", colorBy = "regulation", scaleBy = "count")
- ```
- ### Heatmaps of DE genes
- #### Figure 3 i
- ```{r}
- sample_anno <- sample_table[sample_table$tissue == "hippo",]
- input <- norm_anno[,c(sample_anno$ID,"GENEID", "SYMBOL", "GENETYPE" )]
- gene_anno <- tx_annotation
- geneset <- DEresults[["hippo_LON5_vs_hippo_IgG"]]@results[DEresults[["hippo_LON5_vs_hippo_IgG"]]@results$regulation %in% c("up","down"),"GENEID"]
- input <- input[input$GENEID %in% geneset,]
- input <- input[,colnames(input) %in% sample_anno$ID]
- input_scale <- t(scale(t(input)))
- input_scale<-as.data.frame(input_scale)
- input_scale$GENEID <- rownames(input_scale)
- gene_anno <- gene_anno[match(rownames(input_scale), gene_anno$GENEID),]
- input_scale <- merge(input_scale,
- gene_anno,
- by = "GENEID")
- rownames(input_scale) <- input_scale$SYMBOL
- title=paste("Heatmap of significant DE genes in: ","hippo_LON5_vs_hippo_IgG",sep="")
- print(plotHeatmap(input=input_scale,
- sample_annotation= sample_anno,
- geneset = geneset,
- title = title,
- keyType = "Ensembl",
- show_rownames = F,
- cluster_cols = F,
- gene_type="all",
- plot_mean = F))
- ```
- ### Volcano Plots
- #### Figure 3 k
- ```{r}
- # Plot Volcano Plot
- print(plotVolcano(DEresults_obj = DEresults, comparison = "hippo_LON5_vs_hippo_IgG", labelnum = 20))
- ```
- ```{r}
- sessionInfo()
- ```
250327_publication.Rmd at commit 39b95ee, under LGPL-3.0 · at the source
Overview
and 11 other authors
Elena De Domenico9,11, Peter Körtvelyessy3,15, Dirk Reinhold5, Anja Schneider11, Jonas J. Neher6,7,12, Thomas Ulas9,10,11, Stefan F. Lichtenthaler6,7,8, Benjamin R. Rost1, Dietmar Schmitz1,2,14,16, Harald Prüss1,2,3, Susanne Wegmann1,216 affiliations
- German Center for Neurodegenerative Diseases (DZNE), Berlin, Germany
- Einstein Center for Neurosciences (ECN), Charité – Universitätsmedizin Berlin, Berlin, Germany
- Department of Neurology and Experimental Neurology, Charité – Universitätsmedizin Berlin, Berlin, Germany
- Berlin Institute of Health (BIH) at Charité – Universitätsmedizin Berlin, Berlin, Germany
- Institute of Molecular and Clinical Immunology, Otto-von-Guericke-University, Magdeburg, Germany
- German Center for Neurodegenerative Diseases (DZNE), Munich, Germany
- Munich Cluster for Systems Neurology (SyNergy), Munich, Germany
- Neuroproteomics, School of Medicine and Health, Klinikum Rechts der Isar, Technical University of Munich, Munich, Germany
- Platform for Single Cell Genomics and Epigenomics (PRECISE) at the German Center for Neurodegenerative Diseases and the University of Bonn, Bonn, Germany
- Genomics and Immunoregulation, Life and Medical Sciences (LIMES) Institute, University of Bonn, Bonn, Germany
- German Center for Neurodegenerative Diseases (DZNE), Bonn, Germany
- Metabolic Biochemistry, Biomedical Center Munich (BMC), Faculty of Medicine, Ludwig Maximilian University, Munich, Germany
- Institute of Integrative Neuroanatomy, Charité, Berlin, Germany
- Institute of Cell Biology and Neurobiology, Charité – Universitätsmedizin Berlin, Berlin, Germany
- German Center for Neurodegenerative Diseases (DZNE), Magdeburg, Germany
- Neuroscience Research Center (NWFZ), Charité-Universitätsmedizin, Berlin, Germany
Abstract
Anti-IgLON5 disease is an autoimmune disease, in which autoantibodies (AABs) against the neuronal cell surface protein IgLON5 lead to profound brain dysfunction and Tau pathology. How α-IgLON5 AABs cause neuronal Tau protein pathology and neurodegeneration remains unclear. We find that patient-derived α-IgLON5 AABs cluster IgLON5 proteins with other cell surface proteins, leading to neuronal hyperactivity that triggers pathological Tau missorting and phosphorylation, typically observed early in Tau-related neurodegenerative diseases. In wild-type mice, α-IgLON5 AABs induce hippocampal Tau phosphorylation and neuroinflammatory responses. Our findings establish a causal link between the α-IgLON5 AABs and Tau pathology in anti-IgLON5 disease patients and highlight the role of neuronal hyperactivity as a disease-overarching driver of Tau pathology and provide a potential target for therapeutic intervention.
Reproduced under the paper's license (CC BY), from the paper cited above.
Repositories
Its files are read in the Code ↔ Paper reader above, with 1 match between paragraphs and lines of code.
gitlab.dzne.de/ag-ulas/iglon5-autoimmune-antibody-influence-on-neurons
39b95ee856d3cbf4189243e201bc7cf6be8bf980, 7 April 2026Availability: 1 check, the latest on 28 September 2026: the link answers
- 28 September 2026: the link answers
3 files
- 250327_publication.Rmd — R, 1,350 lines, 1 match
- LICENSE — License, 165 lines
- README.md — Text, 10 lines
Zenodo 19454006
Availability: 1 check, the latest on 28 September 2026: the link answers (HTTP 200)
- 28 September 2026: the link answers (HTTP 200)
3 files
- 250327_publication.Rmd — R, 1,350 lines
- LICENSE — License, 165 lines
- README.md — Text, 10 lines
gitlab.dzne.de/grundschoettelp/iglon5-autoimmune-antibody-influence-on-neurons
39b95ee856d3cbf4189243e201bc7cf6be8bf980, 7 April 2026Availability: 1 check, the latest on 28 September 2026: the link answers
- 28 September 2026: the link answers
3 files
- 250327_publication.Rmd — R, 1,350 lines
- LICENSE — License, 165 lines
- README.md — Text, 10 lines
The paper's code and data availability statement is in the Data section.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 3 repositories 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;
- 1 match 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
- geo:GSE298951 — at NCBI GEO; found in “Data, code, and materials availability:”
Data, code, and materials availability
All data and code needed to evaluate and reproduce the results in the paper are present in the paper and/
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, 28 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 31 authors, 10 MeSH terms, 6 funders, 115 references.
Cite
This paper
Askin, B., Kilic, C., Cordero Gómez, C., Duong, S. L.-L., Domingues-Baquero, A., Goihl, A., Nalbach, K., Petushi, J., Grundschöttel, P., Wagner, J., Thomas, V., Lamberty, J., Withers, E., Huber, H., Huebschmann, S., Semenova, E., Turko, P., Newman, A. G., Diez, L., . . . Wegmann, S. (2026). IgLON5 autoimmune antibodies activate Tau via neuronal hyperactivity. Science advances, 12(20), eaec2042. https://
BibTeX
@article{askin2026iglon5
author = {Askin, Bilge and Kilic, Cagla and Cordero Gómez, César and Duong, Sophie Lan-Linh and Domingues-Baquero, Alvaro and Goihl, Alexander and Nalbach, Karsten and Petushi, Joana and Grundschöttel, Pia and Wagner, Jessica and Thomas, Valentine and Lamberty, Janne and Withers, Emily and Huber, Hanna and Huebschmann, Sabrina and Semenova, Ekaterina and Turko, Paul and Newman, Andrew G. and Diez, Lisa and Beyer, Marc and De Domenico, Elena and Körtvelyessy, Peter and Reinhold, Dirk and Schneider, Anja and Neher, Jonas J. and Ulas, Thomas and Lichtenthaler, Stefan F. and Rost, Benjamin R. and Schmitz, Dietmar and Prüss, Harald and Wegmann, Susanne},
title = {{IgLON5 autoimmune antibodies activate Tau via neuronal hyperactivity}},
journal = {Science advances},
year = {2026},
month = may,
volume = {12},
number = {20},
pages = {eaec2042},
publisher = {American Association for the Advancement of Science},
issn = {2375-2548},
doi = {10.1126/
url = {https://
pmid = {42127169},
pmcid = {PMC13170660}
}
RIS
TY - JOUR
AU - Askin, Bilge
AU - Kilic, Cagla
AU - Cordero Gómez, César
AU - Duong, Sophie Lan-Linh
AU - Domingues-Baquero, Alvaro
AU - Goihl, Alexander
AU - Nalbach, Karsten
AU - Petushi, Joana
AU - Grundschöttel, Pia
AU - Wagner, Jessica
AU - Thomas, Valentine
AU - Lamberty, Janne
AU - Withers, Emily
AU - Huber, Hanna
AU - Huebschmann, Sabrina
AU - Semenova, Ekaterina
AU - Turko, Paul
AU - Newman, Andrew G.
AU - Diez, Lisa
AU - Beyer, Marc
AU - De Domenico, Elena
AU - Körtvelyessy, Peter
AU - Reinhold, Dirk
AU - Schneider, Anja
AU - Neher, Jonas J.
AU - Ulas, Thomas
AU - Lichtenthaler, Stefan F.
AU - Rost, Benjamin R.
AU - Schmitz, Dietmar
AU - Prüss, Harald
AU - Wegmann, Susanne
TI - IgLON5 autoimmune antibodies activate Tau via neuronal hyperactivity
T2 - Science advances
J2 - Sci Adv
PY - 2026
DA - 2026/
VL - 12
IS - 20
SP - eaec2042
SN - 2375-2548
PB - American Association for the Advancement of Science
DO - 10.1126/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1126/
"type": "article-journal",
"title": "IgLON5 autoimmune antibodies activate Tau via neuronal hyperactivity",
"container-title": "Science advances",
"author": [
{
"family": "Askin",
"given": "Bilge"
},
{
"family": "Kilic",
"given": "Cagla"
},
{
"family": "Cordero Gómez",
"given": "César"
},
{
"family": "Duong",
"given": "Sophie Lan-Linh"
},
{
"family": "Domingues-Baquero",
"given": "Alvaro"
},
{
"family": "Goihl",
"given": "Alexander"
},
{
"family": "Nalbach",
"given": "Karsten"
},
{
"family": "Petushi",
"given": "Joana"
},
{
"family": "Grundschöttel",
"given": "Pia"
},
{
"family": "Wagner",
"given": "Jessica"
},
{
"family": "Thomas",
"given": "Valentine"
},
{
"family": "Lamberty",
"given": "Janne"
},
{
"family": "Withers",
"given": "Emily"
},
{
"family": "Huber",
"given": "Hanna"
},
{
"family": "Huebschmann",
"given": "Sabrina"
},
{
"family": "Semenova",
"given": "Ekaterina"
},
{
"family": "Turko",
"given": "Paul"
},
{
"family": "Newman",
"given": "Andrew G."
},
{
"family": "Diez",
"given": "Lisa"
},
{
"family": "Beyer",
"given": "Marc"
},
{
"family": "De Domenico",
"given": "Elena"
},
{
"family": "Körtvelyessy",
"given": "Peter"
},
{
"family": "Reinhold",
"given": "Dirk"
},
{
"family": "Schneider",
"given": "Anja"
},
{
"family": "Neher",
"given": "Jonas J."
},
{
"family": "Ulas",
"given": "Thomas"
},
{
"family": "Lichtenthaler",
"given": "Stefan F."
},
{
"family": "Rost",
"given": "Benjamin R."
},
{
"family": "Schmitz",
"given": "Dietmar"
},
{
"family": "Prüss",
"given": "Harald"
},
{
"family": "Wegmann",
"given": "Susanne"
}
],
"container-title-short":
"volume": "12",
"issue": "20",
"page": "eaec2042",
"DOI": "10.1126/
"PMID": "42127169",
"PMCID": "PMC13170660",
"ISSN": "2375-2548",
"publisher": "American Association for the Advancement of Science",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
13
]
]
}
}
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/s41593-026-02367-0 [code]
- A reproducible three-dimensional model of human brain tissue to investigate physiological and disease-associated microglia phenotypes.Journal: Nature neuroscienceIn common: reshape2, tidyverse, cellular / molecular, 5 references, 3 authors
- [2] doi:10.1093/brain/awag015
- Brainstem pathology in anti-IgLON5 disease: new insights into early events and tau progression.Journal: Brain : a journal of neurologyIn common: other condition, cellular / molecular, 11 references
- [3] doi:10.1038/s41467-026-74961-6 [code]
- Spatial multi-omics identifies early synaptic pruning and context-specific dopaminergic vulnerability in synucleinopathies.Journal: Nature communicationsIn common: tidyverse, cellular / molecular, 2 authors
- [4] doi:10.3389/fnsyn.2026.1832103 [code]
- Automated ROI detection allows rapid quantification of synaptic activity across tens of thousands of synapses in cell culture.Journal: Frontiers in synaptic neuroscienceIn common: tidyverse, cellular / molecular, 3 references, author Paul Turko
- [5] doi:10.1186/s13073-026-01702-1
- Tandem repeat polymorphisms are associated with brain structure: results of two large population-based studies.Journal: Genome medicineIn common: 2 authors
- [6] doi:
- AMPAR immunization induces progressive autoimmune encephalitis with autoreactive B cells in the brainJournal: bioRxiv : the preprint server for biologyIn common: other condition, mouse, cellular / molecular, 5 references
- [7] doi:10.1186/s11689-026-09713-0 [code]
- DRP1 mutations associated with EMPF1 encephalopathy perturb the transcriptional profile and maturation of cortical neurons.Journal: Journal of neurodevelopmental disordersIn common: reshape2, tidyverse, other condition, 4 references
- [8] doi:10.1016/j.celrep.2026.117505 [code]
- Impaired spatial coding and neuronal hyperactivity in the medial entorhinal cortex of aged APP knock-in mice.Journal: Cell reportsIn common: reshape2, tidyverse, mouse, 3 references
- [9] doi:10.1038/s41467-026-74968-z [code]
- Activity-dependent ribosome profiling reveals the landscape of canonical and non-canonical translation in brain tissue.Journal: Nature communicationsIn common: tidyverse, mouse, cellular / molecular, 5 references
- [10] doi:10.1038/s41467-026-71831-z [code]
- Dysfunction of the episodic memory network in the Alzheimer's disease cascade.Journal: Nature communicationsIn common: 1 reference, author Anja Schneider
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.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 3 repositories of the authors' code, each at its verified commit and with its license, 3 scripts, and 1 match between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:7f3edf7cb7843138…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[.
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.
