Análisis evolutivo y funcional de genes asociados al complejo TORC1 en Saccharomyces cerevisiae mediante técnicas de inteligencia artificial

1. Introducción

La Saccharomyces cerevisiae es un hongo unicelular. En la industria, S. cerevisiae es fundamental para elaborar bebidas fermentadas como vino, cerveza, sidra y sake, además de productos de panadería y repostería. En S. cerevisiae, las quinasas TOR forman los complejos TORC1 y TORC2. El complejo TORC1 es crucial para la respuesta al nitrógeno, activándose en su presencia y promoviendo la biosíntesis de proteínas y ribosomas, esenciales para la fermentación. Esta activación es vital para la producción eficiente de productos fermentados, garantizando un crecimiento celular óptimo y mejorando la calidad de los productos. Sin embargo, aún no se comprenden completamente los mecanismos mediante los cuales TORC1 detecta y responde a los niveles de nitrógeno.

1.2 Objetivos

  1. Estudiar la historia evolutiva de estos genes mediante la construcción y análisis de un bosque filogenético utilizando técnicas de aprendizaje automático
  2. Identificar genes con historias evolutivas relacionadas y caracterizarlos funcionalmente mediante técnicas de enriquecimiento.

2. Selección de genes

Se inicia el trabajo con un listado de 6015 ORFs provenientes de cepas de la Saccharomyces cerevisiae, de las cuales se identifican 131 genes relevantes asociados al complejo TORC1 en levadura vínicas, siendo este análisis de la historia evolutiva de estos genes crucial para comprender su adaptación y funcionalidad.

3. Análisis de datos

3.1 Librerías a utilizar

#Librerías
library(stringr)
library(phangorn)
library(plotly)
library(reshape2)

3.2 Lectura de archivos

#Listado de ORFs: 6015
listado_ORFs = list.files("C:/Users/javie/OneDrive/Escritorio/Eduardo Kessi/2023/Secuencias_alineadas")
listado_ORFs = gsub(".fasta.phylip","",listado_ORFs)
#Leer archivo CSV que contiene los nombres de los ORFs para análisis y determinar la disponibilidad
BD_ORFS <- read.csv("C:/Users/javie/OneDrive/Escritorio/Eduardo Kessi/2024/Analisis Filogenético/BD/BD xls/BD_ORFS.csv", sep=";")

3.3 Selección de ORFS

ORFs_disponible <- intersect(BD_ORFS$ORF,listado_ORFs)
ORFs_nodisponible <- setdiff(BD_ORFS$ORF,listado_ORFs)
ORFs_outgroup <- setdiff(listado_ORFs,BD_ORFS$ORF)

3.4 Lectura de archivos cepas

#Leer archivo: cepas 1011
cepas_seleccionadas <- read.csv("C:/Users/javie/OneDrive/Escritorio/Eduardo Kessi/2024/Analisis Filogenético/BD/BD xls/BD_cepas.csv", sep=";")
#Seleccionar 270
cepas_seleccionadas <- cepas_seleccionadas[cepas_seleccionadas$Seleccionadas..270.!="","Seleccionadas..270."]

3.5 Construcción de árboles filogenéticos

#Inicialización de listas para almacenar árboles filogenéticos de todas las cepas y cepas seleccionadas
arboles_cepas <- list()
arboles_cepas_filtradas <- list()
matriz_distancia_cum <- matrix(0,0,ncol=1011,nrow=1011)
matriz_distancia_cum_filtrada <- matrix(0,0,ncol=270,nrow=270)
#Procesar cada ORF disponible y construir árboles filogenéticos
for (index in seq_along(ORFs_disponible)){
  message(sprintf("\t- Procesando árbol %d de %d...", index, length(ORFs_disponible)))
  
  #Leer las secuencias alineadas para todas las cepas y construir el árbol filogenético
  secuencias <- read.phyDat(paste("C:\\Users\\javie\\OneDrive\\Escritorio\\Eduardo Kessi\\2023\\Secuencias_alineadas\\", ORFs_disponible[index], ".fasta.phylip", sep=""))
  matriz_distancia_cum = matriz_distancia_cum + as.matrix(dist.hamming(secuencias))
  arbol <- NJ(dist.hamming(secuencias))
  arbol <- midpoint(multi2di(arbol))
  arboles_cepas[[index]] <- arbol
  
  #Filtrar secuencias según las cepas seleccionadas y reconstruir el árbol
  indice_cepas <- match(cepas_seleccionadas, names(secuencias))
  secuencias_filtradas <- secuencias[indice_cepas]
  
  matriz_distancia_cum_filtrada = matriz_distancia_cum_filtrada + as.matrix(dist.hamming(secuencias_filtradas))
  arboles_filtrados = NJ(dist.hamming(secuencias_filtradas))
  arboles_filtrados = midpoint(multi2di(arboles_filtrados))
  
  arboles_cepas_filtradas[[index]] <- arboles_filtrados
}

3.6 Cálculo del árbol de evidencia total.

#Calcular árbol de evidencia total (TE)
arbol_completos <- NJ(matriz_distancia_cum)
arboles_filtrados <- NJ(matriz_distancia_cum)

# Asignar nombres a los árboles basados en los ORFs disponibles
names(arboles_cepas) <- ORFs_disponible
names(arboles_cepas_filtradas) <- ORFs_disponible

3.7 Guardar archivos.

#Guardar árboles en archivo .tree
write.tree(arboles_cepas,"C:\\Users\\javie\\OneDrive\\Escritorio\\Eduardo Kessi\\2024\\Analisis Filogenético\\BD\\Arbol\\arboles_cepas.tree",tree.names = T)
write.tree(arboles_cepas_filtradas,"C:\\Users\\javie\\OneDrive\\Escritorio\\Eduardo Kessi\\2024\\Analisis Filogenético\\BD\\Arbol\\arboles_cepas_filtradas.tree",tree.names = T)
write.tree(arbol_completos, "C:\\Users\\javie\\OneDrive\\Escritorio\\Eduardo Kessi\\2024\\Analisis Filogenético\\BD\\Arbol\\TE_target_ORFS_all_strains.tree")
write.tree(arboles_filtrados,"C:\\Users\\javie\\OneDrive\\Escritorio\\Eduardo Kessi\\2024\\Analisis Filogenético\\BD\\Arbol\\TE_target_ORFS_filtered_strains.tree")

3.8 Visualización de la matriz de distancia

3.8.1 270 cepas

#Visualización de la matriz de distancia
#Calcular la matriz de distancia usando la distancia de Hamming
distancia_matriz = round(dist.hamming(secuencias_filtradas, ratio=T),3)

# Convertimos la matriz de distancia en un formato adecuado para el heatmap
dist_melted = melt(as.matrix(distancia_matriz))

# Creamos el mapa de calor con plot_ly
heatmap_plot = plot_ly(
  x = dist_melted$Var1,
  y = dist_melted$Var2,
  z = dist_melted$value,
  type = "heatmap",
  colorscale = list(c(0, "white"),
                    c(1, "#00A499"))  # Cambiamos la escala de colores de blanco a #00A499
)

# Agregamos un título al gráfico
heatmap_plot <- layout(
  heatmap_plot,
  title = list(text = "Secuencias seleccionadas - 270 cepas ", font = list(size = 12))
)

# Cambiamos la fuente de los ejes
heatmap_plot$x$axis$title = list(font = list(size = 12))
heatmap_plot$y$axis$title = list(font = list(size = 12))

# Mostramos el gráfico
heatmap_plot

3.8.2 1011 cepas

#Visualización de la matriz de distancia
#Calcular la matriz de distancia usando la distancia de Hamming
distancia_matriz = round(dist.hamming(secuencias, ratio=T),3)

# Convertimos la matriz de distancia en un formato adecuado para el heatmap
dist_melted = melt(as.matrix(distancia_matriz))

# Creamos el mapa de calor con plot_ly
heatmap_plot = plot_ly(
  x = dist_melted$Var1,
  y = dist_melted$Var2,
  z = dist_melted$value,
  type = "heatmap",
  colorscale = list(c(0, "white"),
                    c(1, "#00A499"))  # Cambiamos la escala de colores de blanco a #00A499
)

# Agregamos un título al gráfico
heatmap_plot <- layout(
  heatmap_plot,
  title = list(text = "Secuencias seleccionadas - 1011 cepas ", font = list(size = 12))
)

# Cambiamos la fuente de los ejes
heatmap_plot$x$axis$title = list(font = list(size = 12))
heatmap_plot$y$axis$title = list(font = list(size = 12))

# Mostramos el gráfico
heatmap_plot

4. Análisis de datos: outgroups

Se generan árboles aleatorios utilizando las ORFs que no pertenecen a los grupos principales (outgroups) para demostrar que el análisis no es producto del azar. Luego, se repite el proceso previamente realizado.

#OUTGROUPS: no modificado
#Generación de árboles al azar
# Procesar cada ORF que servirá de outgroup, seleccionando un subconjunto al azar
# Inicializar listas para almacenar árboles filogenéticos de todas las cepas y de las cepas filtradas
trees_all_strains <- list()
trees_filtered_strains <- list()
set.seed(1)
outgroups_seleccionados <- sample(ORFs_outgroup,100)

for (index in seq_along(outgroups_seleccionados)){
  message(sprintf("\t- Procesando árbol outgroup %d de %d...", index, length(outgroups_seleccionados)))
  
  #Leer y procesar las secuencias alineadas para cada ORF de outgroup
  sequences <- read.phyDat(paste("C:\\Users\\javie\\OneDrive\\Escritorio\\Eduardo Kessi\\2023\\Secuencias_alineadas\\", outgroups_seleccionados[index], ".fasta.phylip", sep=""))
  tree <- NJ(dist.hamming(sequences))
  tree <- midpoint(multi2di(tree))
  
  trees_all_strains[[index]] <- tree
  
  indice_cepas <- match(cepas_seleccionadas, names(secuencias))
  secuencias_filtradas <- secuencias[indice_cepas]
  
  tree_filtered <- NJ(dist.hamming(secuencias_filtradas))
  tree_filtered <- midpoint(multi2di(tree_filtered))
  
  trees_filtered_strains[[index]] <- tree_filtered
}

#Asignar nombres a los árboles basados en los ORFs de outgroup seleccionados
names(trees_all_strains) <- outgroups_seleccionados
names(trees_filtered_strains) <- outgroups_seleccionados

#Guardar los árboles de outgroup en archivos .tree
write.tree(trees_all_strains, "C:\\Users\\javie\\OneDrive\\Escritorio\\Eduardo Kessi\\2024\\Analisis Filogenético\\BD\\Arbol\\arboles_cepas_outgroups.tree",tree.names = T)
write.tree(trees_filtered_strains, "C:\\Users\\javie\\OneDrive\\Escritorio\\Eduardo Kessi\\2024\\Analisis Filogenético\\BD\\Arbol\\arboles_cepas_filtradas_outgroups.tree",tree.names = T)