Skip to content

Latest commit

 

History

History
551 lines (453 loc) · 18.1 KB

9.DEG.md

File metadata and controls

551 lines (453 loc) · 18.1 KB

Expresión Diferencial

En esta parte del curso vamos a realizar lo sigueinte:

  • Construcción de objetos necesarios para llevar a cabo la expresión diferencial
  • Ensayo de expresión diferencial
  • Obtener los genes diferencialmente expresados
  • Diversos métodos de visualización
  • Enriquecimiento de genes
    • Análisis de sobrerepresenctación (ORA)
    • GSEA

Para consultar la parte teórica revisar la explicación.

💡

La documentación aquí mostrada es una adapatación de información en línea y de cursos previos de la Dra. Alejandra Cervera y el Dr. Hugo Tovar. https://github.com/hachepunto/bioinformatics/blob/master/presentaciones/5-tximport.md

Paso 0

Entrar a la carpeta del drive, descarga el archivo salida_kallisto.zip descomprimirlo detro de datos.taller. Se encuentran 6 carpetas de salida de Kallisto en las dos condiciones, también se incluyen 4 archivos de texto donde se incluyen la información de la localización de las muestras y archivo de referencia del cromosoma 22, con tres columnas, el Id del gen, las diversas variantes de splicing y su símbolo.

Los datos de prueba consisten en dos muestras de ARN disponibles comercialmente: Referencia Humana Universal (UHR) y Referencia de Cerebro Humano (HBR). La UHR es ARN total aislado de un conjunto diverso de 10 líneas celulares cancerosas (mama, hígado, cuello uterino, testículo, cerebro, piel, tejido adiposo, histiocito, macrófago, célula T, célula B). La HBR es ARN total aislado de los cerebros de 23 caucásicos, hombres y mujeres, de diversas edades, pero en su mayoría de 60 a 80 años.

Archivos de texto

Para generar los diversos archivos de texto, mismos que ya están contenidos dentro de la Terminal de RStudio ejecutar

ls ./datos.taller/salida_kallisto_*/abundance.tsv | cut -d"/" -f3 | cut -d"_" -f3-4 > ./datos.taller/ids.txt ##### HBR_Rep1
ls ./datos.taller/salida_kallisto_*/abundance.tsv | cut -d"/" -f3 | cut -d"_" -f3 > ./datos.taller/condicion.txt #### HBR, UHR
ls ./datos.taller/salida_kallisto_*/abundance.tsv > ./datos.taller/rutas.txt ### paths

paste ids.txt condicion.txt rutas.txt > ./datos.taller/mis_muestras.tsv

Paso 1: Abrir Rstudio

Para empezar a crear un script con todos los pasos que vamos a ejecutar, abran en Rstudio un Rscript: File -> New File -> Rscript Es necesario y fundamental guardar el script, lo pueden hacer con CTRL+s o COMMAND+S, también dando con File -> Save. Asignen el nombre de DGEA.R

De manera inicial vamos a realizar todas las instalaciones necesario de las librerías a ocupar

### Instalaciones
if (!require("BiocManager", quietly = TRUE))
  install.packages("BiocManager")
BiocManager::install(version = "3.19")

BiocManager::install("S4Arrays")
BiocManager::install("tximport")
### DGEA
BiocManager::install("DESeq2")
### Volcano plots
BiocManager::install("EnhancedVolcano")
### GSEA
BiocManager::install("clusterProfiler")
### GSEA Plot
BiocManager::install("enrichplot",force = TRUE)
### GSEA Plot
BiocManager::install("DOSE",force = T)
### Gene reference
BiocManager::install("org.Hs.eg.db", character.only = TRUE)
### heatmaps, ORA
install.packages(c("pheatmap","ggplot2", "enrichR"))

💡 NOTA

Las instalaciones sólo es necesario hacerlo una vez, si corres nuevamente los comando no es necesario que vuelvas a cargar la instalación.

Paso 2

Definimos el directorio de trabajo

setwd("~")

Creamos dos carpetas, una donde guarderemos los datos generados y otra en donde guardaremos los gráficos.

path.Data = "./Results_Data"
if (!dir.exists(path.Data)) {dir.create(path.Data)}
path.plots = "./Results_plots"
if (!dir.exists(path.plots)) {dir.create(path.plots)}

Paso 3 Análisis de Expresión Diferencial

Cargamos las bibliotecas que vamos a utilizar:

####
library(tximport)
library(DESeq2)
###

tximport: Importa la abundancia a nivel de transcrito, los recuentos estimados y las longitudes de los transcritos, y los resume en matrices para su uso con paquetes de análisis a nivel de gen posteriores. Podemos consultar la ayuda

help(tximport)

#txi <- tximport(files, 
#                type = c("none", "salmon", "sailfish", "alevin", "piscem", "oarfish", "kallisto",
    "rsem", "stringtie"), 
#                tx2gene = tx2gene,
#                ignoreTxVersion = T,
#                dropInfReps=TRUE)

Paso 3.1 Argumentos de tximport

files

samples <- read.table("./datos.taller/mis_muestras.tsv",sep="\t",header=F)
samples
### Para tener mayor control vamos a ponerle nombre a las columnas
colnames(samples) <- c("Muestra","Condicion","Archivo")
samples

El argumentos sólo necesita la ruta de los archivos, por lo que seleccionando sólo la columna 1

files <- as.vector(samples$Archivo)
## Asociamos la ruta con la muestra, información en la columna 2
names(files) <- samples$Muestra 
files

Archivo de referencia (tx2gene)

refChr22 <- read.table("./datos.taller/geneId_transcriptId_geneName_chr22.txt", sep="\t", header=F)
### Asociamos el nombre a las columnas
colnames(refChr22) <- c("gene_id","transcript_id","gene_name")

Sólo requerimos de las columnas "transcript_id","gene_id" de acuerdo a tximport, creamos una nueva tabla

tx2gene <- refChr22[,c("transcript_id","gene_id")]
head(tx2gene)

Ejecutamos tximport, es importante que tengamos los objetos files y tx2gene

txi <- tximport(files, 
                type = "kallisto", 
                tx2gene = tx2gene,
                ignoreTxVersion = T,
                dropInfReps=TRUE)
str(txi)
head(txi$counts)
head(txi$abundance)

Creamos matriz de expresión normalizada(TPM)

table.out <- txi$abundance
head(table.out)
### Dimenciones del objeto table.out
dim(table.out)

Incluimos referencia de los nombre de los genes.

geneId_geneName <- unique(refChr22[,-2])
table.out.names <- merge(geneId_geneName,table.out,by.x='gene_id',by.y=0)
dim(table.out.names)
head(table.out.names)
### Guardamos la tabla asociada a los nombres
write.table(table.out.names, 
            file=paste0(path.Data,"/exprTable.tsv"), sep="\t", 
            quote=F, 
            col.names=T,
            row.names=F)

💡 NOTA

TPM (Transcripts per Millions)

  1. Divide los recuentos de lecturas por la longitud de cada gen en kilobases. Esto te da lecturas por kilobase (RPK).
  2. Suma todos los valores de RPK en una muestra y divide este número por 1,000,000. Este es tu factor de escalado "por millón".
  3. Divide los valores de RPK por el factor de escalado "por millón". Esto te da TPM.

Paso 4 Expresión Diferencial Deseq2

### Objeto para estructurar los datos y hacer el DGEA
?DESeqDataSetFromTximport
# DESeqDataSetFromTximport(txi, colData, design, ...)

El objeto txi ya lo tenemos, sólo falta considerar las condiciones.

## Condición
coldata <- data.frame(condition = samples$Condicion)
coldata$condition <- factor(coldata$condition)
## Nombre de filas
rownames(coldata) <- samples$Muestra
head(coldata)

## Expresión diferencial
dds <- DESeqDataSetFromTximport(txi, coldata, ~condition)


dds <- DESeq(dds)
resultsNames(dds)
### Objeto donde se encuentra información de análisis de expresión
res <- results(dds)
head(res)
plotMA(res)
## salvar el resultado de 
saveRDS(res, paste0(path.Data,"/res_dseq2.rds"))

Ejercicio para ver como se calcula el log2foldchange

cts <- counts(dds, normalized=T)
head(cts)
cts['ENSG00000008735',]
x.HBR <-cts['ENSG00000008735',1:3]
x.HBR
mh <- mean(x.HBR)
mh 

x.UHR<-cts['ENSG00000008735',4:6]
x.UHR
mu <- mean(x.UHR)
mu

h <- log2(mh)
h
u <- log2(mu)
u

lfc_u_h <- u - h
lfc_u_h

log2(mu/mh)
res['ENSG00000008735',]

Paso 4.1 Extraer los genes considerados como Diferencialmente expresados

degs<-subset(res, (!is.na(res$padj) & 
                     res$pvalue<0.05 & 
                     baseMean>=50 & res$padj < 0.05 & 
                     abs(res$log2FoldChange)>1))

Paso 4.2 Heatmaps

Vamos a extraer sólo los 10 genes con menor p_value

top <- degs[order(degs$pvalue),]
myTpm <- subset(table.out, rownames(table.out) %in% rownames(top[1:10,]) )
dim(myTpm)
log2mat <- log2(myTpm)

Hacemos el heatmap

library (pheatmap)
my_hmap <- pheatmap(log2mat,
                    main="DEGs UHR vs HBR",
                    filename= paste0(path.plots,"/heatmap_top10.png"))

cambiamor el nombre de los genes para mejor interpretación

myTpm <- subset(table.out.names, table.out.names$gene_id %in% rownames(top[1:10,]))
dim(myTpm)
head(myTpm)
mat <- myTpm[,-c(1:2)]
rownames(mat) <- myTpm$gene_name
log2mat <- log2(mat)
my_hmap <- pheatmap(log2mat,
                    main="DEGs UHR vs HBR")

Si queremos utilizar todos los genes diferencialmente expresados

myTpm <- subset(table.out.names, table.out.names$gene_id %in% rownames(top[,]))
dim(myTpm)
head(myTpm)
mat <- myTpm[,-c(1:2)] + 1 ### Quitar ceros
rownames(mat) <- myTpm$gene_name
log2mat <- log2(mat)
my_hmap <- pheatmap(log2mat,
                    main="DEGs UHR vs HBR",
                    filename= paste0(path.plots,"/heatmap_all.png"),
                    height = 10)

💡

No es tan clara la diferencia, probemos en la versión normalizada.

###
my_hmap <- pheatmap(log2mat,
                    main="DEGs UHR vs HBR",
                    scale = "row",
                    filename= paste0(path.plots,"/heatmap_all_scaled.png"),
                    height = 10)
dev.off()

Paso 4.3 Volcano Plots

Un "volcano plot" es una técnica de visualización utilizada en la bioinformática y en otras ciencias biológicas para identificar cambios significativos en grandes conjuntos de datos, como en estudios de expresión génica o proteómica.

Los puntos que están alejados del origen en ambas direcciones (tanto en términos de significancia como en términos de magnitud del cambio) son los que suelen ser de mayor interés biológico.

library(EnhancedVolcano)
library(ggplot2)

### Tabla de los resultados
degs.frame = as.data.frame(res)
### Le incluimos el símbolo del gen
degs.frame.1 = merge(geneId_geneName,degs.frame,by.x='gene_id',by.y=0)
### Vemos que columnas podemos graficar
colnames(degs.frame.1)
#[1] "gene_id"        "gene_name"      "baseMean"       "log2FoldChange"
# "lfcSE"          "stat"           "pvalue"         "padj" 

p1 <- EnhancedVolcano(degs.frame.1[,c("gene_name", "log2FoldChange", "padj")],
                      lab = degs.frame.1[,c("gene_name")],
                      x = 'log2FoldChange',
                      y = 'padj',
                      pCutoff = 0.05,
                      title = "UHR vs HBR")
p1
## Guardamos el gráfico
ggsave(paste0(path.plots,"/Volcano.png"))

Paso 5 Enriquecimiento

De acuerdo a la teoría, existen diversos tipos de enriquecimiento de genes nos centraremos en dos:

  1. ORA
  2. GSEA

ORA (Over representation Analysis)

Técnica utilizada en bioinformática para identificar categorías funcionales, rutas metabólicas, o grupos de genes que están sobrerrepresentados en un conjunto de genes de interés. Este método se usa comúnmente para interpretar resultados de experimentos de expresión génica, como microarrays o secuenciación de RNA (RNA-seq).

Se implementará mediante el uso de EnrichR. EnrichR es un programa que te permite consultar múltiples bases de datos a la vez donde puedes ver que vías de señalización o rutas metabólicas están sobrerepresentadas o enriquecidas en un conjunto de genes en particular.

https://maayanlab.cloud/Enrichr/

EnrichR no se puede descargar, es un programa que tiene sólo existe en su propio sitio web, pero existe un paquete de R que nos permite conectarnos a la página web de EnrichR y ejecutarlo desde nuestra computadora.

https://cran.r-project.org/web/packages/enrichR/vignettes/enrichR.html

# cargamos el paquete en nuestra sesión
library(enrichR)
### Verificamos que tengamos conexión con el servidor 
websiteLive <- getOption("enrichR.live")
#Welcome to enrichR
#Checking connection ... 
#Enrichr ... Connection is Live!** 
#FlyEnrichr ... Connection is Live!
#WormEnrichr ... Connection is Live!
#YeastEnrichr ... Connection is Live!
#FishEnrichr ... Connection is Live!
#OxEnrichr ... Connection is Live!

### seleccionamos sólo los datos para humano
if (websiteLive) {
  listEnrichrSites()
  setEnrichrSite("Enrichr") # Human genes
}
dbs <- listEnrichrDbs()

Veamos cuáles están actualizadas a 2023

grep("2023",dbs$libraryName,value=T)

Seleccionamos un par de bases de datos para nuestro ejercicio

misDBS <- c("GO_Biological_Process_2023","WikiPathway_2023_Human")

Vamos a hacer una prueba con unos genes de ejemplo

if (websiteLive) {
  enriched <- enrichr(c("Runx1", "Gfi1", "Gfi1b", "Spi1", "Gata1", "Kdr"), misDBS)
}

Para ver los resultados, podemos checar individualmente los resultados de cada base de datos:

if (websiteLive) head(enriched[["GO_Biological_Process_2023"]])
if (websiteLive) head(enriched[["WikiPathway_2023_Human"]])
plotEnrich(enriched[[2]], showTerms = 20, numChar = 40, y = "Count", orderBy = "P.value")
### Si quieren salvar el gráfico
#ggsave(paste0(path.plots,"/ORA.png"))

¿Cómo generarías el otro gráfico para la otra base de datos?

Para guardar nuestra tabla de resultados

write.table(enriched[["WikiPathway_2023_Human"]], 
            file=paste0(path.Data,"/enriched_WikiPathways_2023.tsv"), sep="\t", 
            quote=F, 
            col.names=T,
            row.names=F)

GSEA (Gene Set Enrichment Analysis)

Técnica estadística utilizada para determinar si un conjunto predefinido de genes muestra diferencias significativas en sus niveles de expresión entre dos condiciones biológicas (por ejemplo, muestras tratadas vs. no tratadas). A diferencia de ORA (Over-Representation Analysis), que se enfoca en categorías de genes que están sobrerrepresentadas en un subconjunto de genes significativamente expresados, GSEA analiza todos los genes de un experimento de expresión génica para identificar patrones globales de expresión.

library(clusterProfiler)
library(enrichplot)
library(ggplot2)
library("org.Hs.eg.db", character.only = TRUE)

Cargado de datos

original_gene_list <- res$log2FoldChange

En caso que cerraste sesión, no es necesario correr el análsiis de expresión diferencial

## línea 203 guardamos el objeto
res <- readRDS("./Results_Data/res_dseq2.rds")

Preparación

original_gene_list <- res$log2FoldChange

# Nombramos el vector

names(original_gene_list) <- rownames(res)

# eliminamos cualquier NA 

gene_list<-na.omit(original_gene_list)

# odernamos la lista en orden decreciente (requerido por clusterProfiler)

gene_list = sort(gene_list, decreasing = TRUE)
head(gene_list)

GSEA

Gene Ontology

?gseGO
  1. keyType El tipo de ids utilizados en nuestra lista. Receurden que los tipos permitidos se enlistan con el comado keytypes("org.Hs.eg.db"). Recueden que si usan algo distinto a Humano deben cambiar su anotación.
  2. ont Ontología. Alguno de "BP" (procesos biológicos), "MF" (función molecular), "CC" (componente celular) o "ALL" (todas) minGSSize tamaño mínimo de geneSet para analizar.
  3. maxGSSize tamaño máximo de genes anotados para probar. pvalueCutoff punto de corte del p-value.
  4. pAdjustMethod metodo para ajustar la p, puede ser uno de estos: "holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none"
gse <- gseGO(geneList=gene_list, 
             ont ="ALL", ##"BP"
             keyType = "ENSEMBL", 
             minGSSize = 3, 
             maxGSSize = 800, 
             pvalueCutoff = 0.05, 
             verbose = TRUE, 
             OrgDb = "org.Hs.eg.db", 
             pAdjustMethod = "BH")

Utilidad

Visualización

1. DotPlot

require(DOSE)
dotplot(gse, showCategory=10, split=".sign") + facet_grid(.~.sign)
geneset = 1

2. GSEA Plot

gseaplot(gse, by = "all", title = gse$Description[geneset], geneSetID = geneset)
goplot(gse)

3. Barplot

###barplot
dat  = data.frame("NES" = gse@result$enrichmentScore, 
                  "p_value" = gse@result$p.adjust,
                  "geneset" = gse@result$Description)

ggplot(dat, aes(x=geneset, y=NES, fill=p_value)) +
  geom_bar(stat="identity")+theme_minimal()+coord_flip()+
  scale_fill_gradient(low="red",high="blue")

KEGG

ids<-bitr(names(original_gene_list), fromType = "ENSEMBL", toType = "ENTREZID", OrgDb="org.Hs.eg.db")

# se elimnan ids duplicados (aquí usamos "ENSEMBL", pero debemos usar lo que hayamos empleado en el argumento "fromType")

dedup_ids <- ids[!duplicated(ids[c("ENSEMBL")]),]

# Creamos un nuevo dataframe res2 en cual solo contiene los genes que hicieron match usando ña función bitr

res2 <- res[rownames(res) %in% dedup_ids$ENSEMBL,]

# Creamos una nueva coñumna en degs2 con los correspondientes ENTREZ IDs

res2$Y <- dedup_ids$ENTREZID

# Creamos un vector con el universo de genes

kegg_gene_list <- res2$log2FoldChange

# Nombramos el vector con los ENTREZ ids

names(kegg_gene_list) <- res2$Y

# eliminamos NAs 

kegg_gene_list<-na.omit(kegg_gene_list)

# Ordenamos los datos en orden decreciente (requerido por clusterProfiler)

kegg_gene_list = sort(kegg_gene_list, decreasing = TRUE)

kk2 <- gseKEGG(geneList     = kegg_gene_list,
               organism     = "hsa",
               minGSSize    = 3,
               maxGSSize    = 800,
               pvalueCutoff = 0.05,
               pAdjustMethod = "none",
               keyType       = "ncbi-geneid")

Visualización

1. Dot Plot

dotplot(kk2, showCategory = 10, title = "Enriched Pathways" , split=".sign") + facet_grid(.~.sign)

2. Barplot

dat.kk2  = data.frame("NES" = kk2@result$enrichmentScore, 
                  "p_value" = kk2@result$p.adjust,
                  "geneset" = kk2@result$Description)

ggplot(dat.kk2, aes(x=geneset, y=NES, fill=p_value)) +
  geom_bar(stat="identity")+theme_minimal()+coord_flip()+
  scale_fill_gradient(low="red",high="blue")

3. GSE Plot

gseaplot(kk2, by = "all", title = kk2$Description[geneset], geneSetID = geneset)