• Publicidad

Obtener el número de veces que aparecen las secuencias

Perl aplicado a la bioinformática

Obtener el número de veces que aparecen las secuencias

Notapor pubafra » 2014-12-20 19:18 @846

Buen día tengan todos en el foro.

Solicito de su amable ayuda. Estoy iniciando en esto del lenguaje de programación Perl con el objetivo de realizar tareas automatizadas y es por ese hecho que me cuesta trabajo entender algunos algoritmos.

En mi tiempo libre leo y complemento la lectura con algoritmos básicos. Aun así me falta mucho para llegar a donde quiero.

Dejando a un lado eso describo mi "problema": Necesito buscar secuencias cortas (alrededor de 20 caracteres) en un archivo plano (txt, fasta o fastq) el cual puede o no contener las secuencias que busco. Ya he realizado este trabajo usando textpad para lo cual en búsqueda pongo la secuencia que deseo buscar y selecciono el archivo donde la va a buscar. Cabe mencionar que son alrededor de 2000 secuencias que debo buscar. Aun así he avanzado en el trabajo en un 30 % o 40 %.

Me ayudaría mucho tener orientación en algoritmos o temas que me ayuden a lo siguiente: quiero que a partir de un archivo secuencias.txt (contiene las secuencias que deseo buscar separadas por saltos de línea) busque en el archivo bibliotecas.txt o .fast o .fastq (contiene información de la secuenciación) las veces que aparece cada una de las secuencias del archivo secuencias.txt y que el resultado lo almacene en un archivo resultado.txt con la misma información del archivo secuencias.txt solo que con el número de veces que aparece separada por espacio o tabulación.

Sé muy bien que es mucho lo que estoy pidiendo pero ya no quiero seguir con el método del textpad pero confío en su ayuda para orientarme a los temas que me ayudarán a resolver mi problema.

Espero haberme explicado bien lo que deseo. De antemano, gracias.

Este es parte del contenido del archivo secuencias.txt
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
TTGGACTGAAGGGAGCTCCCT
AGGCAGCTCTCCTCTGGCAGG
TGAAGTGTTTGGGGGAACTC
TGCAGTTGCTGCCTCAAGCTT
TTTGGAGTGAAGGGAGCTCTG
AATGGAGGCTGATCCAAGATC
GTGAAGTGTTTGGGGGAACTC
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Este es parte del contenido del archivo bibliotecas.txt
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
3:1:1619:956    CGGGGGCGCCCCCGCCCCCCCCCCCCCCCCCCCCCC    40 40 40 40 40 40 18 4 40 34 7 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40       N
3:1:1333:1700   GTTGTAGTATAGTGGTAAGTATTCCCGCTGTAGGCA    40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40     Y
3:1:1745:1406   ACCCCCCCCCCCCCCCCCCCACCCCAACAACCAACA    40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 10 40 3 40 40 40 40 33 40 40 40 40 40 40 40 40      N
3:1:1181:2030   GTCTTGAATCAAAATAATTTCTGTAGGCACCCTCCC    40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 10 18     Y
3:1:900:1829    GTGTTTTATCTTACCGTAGAAATTCTGTAGGCACCA    40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40     Y
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Este sería parte del contenido del archivo resultado.txt
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
TTGGACTGAAGGGAGCTCCCT 548
AGGCAGCTCTCCTCTGGCAGG 0
TGAAGTGTTTGGGGGAACTC 93652
TGCAGTTGCTGCCTCAAGCTT 26
TTTGGAGTGAAGGGAGCTCTG 166
AATGGAGGCTGATCCAAGATC 100033
GTGAAGTGTTTGGGGGAACTC 9745
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
pubafra
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2014-12-04 21:16 @927

Publicidad

Re: Obtener el número de veces que aparecen las secuencias

Notapor explorer » 2014-12-20 21:10 @923

Bienvenido a los foros de Perl en Español, pubafra.

No necesitas mucho de algoritmos para resolver un problema tan sencillo como este.

Te vale con leer el archivo secuencias.txt y meter las secuencias como claves de un hash.

Luego abres el archivo bibliotecas.txt, y por cada línea, la comparas con todas las claves del hash. Eso es un bucle por las claves, usando una expresión regular o, mucho mejor, usar la función index(), para saber si la secuencia está en la línea leída de la biblioteca. Por cada aparición de una secuencia, incrementas el valor asociado a ella en el hash.

Te queda abrir el archivo resultado.txt, recorrer las secuencias en el orden en que fueron leídas antes, y por cada una obtienes el número de veces que la has detectado (toda la información está en el hash).

Yo creo que en 20 líneas se puede resolver.

Una forma más óptima sería la confección de un patrón de alternancias con todas las secuencias a buscar, y por medio de una expresión regular, aplicar el patrón a cada línea de la biblioteca. La captura de la cadena encontrada nos sirve de clave dentro del hash para incrementar el número de apariciones. Esto reduce el código unas cinco o seis líneas, pero aumenta su velocidad.

Inténtalo. Si te atascas, te echamos una manita.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Obtener el número de veces que aparecen las secuencias

Notapor pubafra » 2015-02-06 03:15 @177

explorer, una disculpa de antemano por no haber respondido agradeciendo tu punto de vista para resolver mi problema. No me había reportado ya que me puse a estudiar para realizar al menos un script y presentarlo para corregir errores o mejorarlo por otra forma.

Te comento que resolví por esta vía el problema pero creo que podría mejorar para reducir el tiempo de respuesta. Te muestro el código y espero tus comentarios.

Gracias.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. use warnings;
  2.  
  3. open (INPUT, "mirnasNR.txt");
  4. @array = <INPUT>;
  5. chomp @array;
  6. close (INPUT);
  7.  
  8. %hash = map { $_ => 0 } @array;
  9.  
  10. foreach $llave(keys %hash){
  11.         open (FILE, "Drought_rice.txt");
  12.         while ($line = <FILE>){
  13.                 if ($line =~ m/$llave/g) {
  14.                 $hash{$llave}++;
  15.                 next;
  16.                 }
  17.         next;
  18.         }
  19.         close (FILE);
  20.         open (OUTPUT, ">>resultado.txt");
  21.         print OUTPUT "$llave - $hash{$llave}\n";
  22.         close (OUTPUT);
  23. }
  24.  
  25. exit;
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
pubafra
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2014-12-04 21:16 @927

Re: Obtener el número de veces que aparecen las secuencias

Notapor explorer » 2015-02-06 09:03 @419

Una forma de acelerarlo es metiendo todas las secuencias en una gigantesca expresión regular, para buscar por todas las secuencias, a la vez, por cada línea de la biblioteca. Y con un hash llevar la cuenta de aparición de cada secuencia.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.14;
  3. use strict;
  4. use warnings;
  5. use autodie;
  6.  
  7. # Leemos las secuencias
  8. open my $SECUENCIAS, '<', 'secuencias.txt';
  9. my @secuencias = <$SECUENCIAS>;
  10. chomp @secuencias;
  11. close $SECUENCIAS;
  12.  
  13. # Construimos la exp. reg.
  14. my $regex = join '|', @secuencias;
  15. $regex = qr/($regex)/;
  16.  
  17. # Recorrer el archivo de bibliotecas
  18. my %contador;
  19. open my $BIBLIOTECA, '<', 'bibliotecas.txt';
  20. while (my $linea = <$BIBLIOTECA>) {
  21.     while($linea =~ /$regex/g) {
  22.         $contador{$1}++;
  23.         pos($linea) = $-[0] +1;         # apuntamos a la posición inicial, siguiente, de la última coincidencia
  24.     }
  25. }
  26. close $BIBLIOTECA;
  27.  
  28. # Mostrar resultados
  29. open my $SALIDA,     '>', 'resultado.txt';
  30. while (my($secuencia,$veces) = each %contador) {
  31.     say $SALIDA "$secuencia $veces";
  32. }
  33. close $SALIDA;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Ajuste con pos() es necesario, para poder detectar secuencias que pudiesen estar dentro de otras secuencias en la misma línea.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Obtener el número de veces que aparecen las secuencias

Notapor pubafra » 2015-03-18 12:35 @566

Hola de nuevo, explorer.

Tengo una pregunta: ¿podría buscar las secuencias como líneas del archivo secuencias.txt sin pasar por algún array o hash? En otras palabras: Leer cada una de esas secuencias del archivo.txt y buscarla directamente en bibliotecas.txt y que muestre el mismo resultado.txt.

Ya he intentado varias formas. Una de ellas, que pienso que sería lo correcto, un while() que lea cada línea del secuencias.txt y la almacene en una variable. Después esa variable la paso a una subrutina para que abra el archivo bibliotecas.txt y busque cada variable dentro de la misma subrutina y que imprima en resultado.txt.

No me da resultado y no sé en qué estoy mal, agradecería si me orientas o me das ayuda, gracias.

Bueno, más tarde subo el intento de código.
pubafra
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2014-12-04 21:16 @927

Re: Obtener el número de veces que aparecen las secuencias

Notapor explorer » 2015-03-18 13:48 @617

La forma normal de resolverlo es como dices:

Leer el archivo donde vamos a buscar, línea por línea.
Por cada línea, comparamos esa línea con todas las secuencias, con una expresión regular.
Si el resultado de la comparación es positivo, pues sacamos el resultado.

La solución que te propuse "simplificaba" el segundo paso, construyendo una expresión regular que contuviese todas las secuencias a buscar, por lo que buscamos por todas a la vez. Quizás esta es la parte más oscura.

Aparte de expresiones regulares, otra opción es la de usar index(), que realiza la búsqueda de una cadena dentro de otra, y lo hace un poco más rápido que con exp. reg.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Obtener el número de veces que aparecen las secuencias

Notapor pubafra » 2015-03-18 20:52 @911

Gracias por tu respuesta, explorer, la voy a estudiar para replantear el programa pero aquí te dejo lo que intenté. Espero me ayudes a resolverlo por esta ruta, gracias.

use warnings;

open (FILE, "sequen5.txt");
open (FILE2, "biblioteca.txt");
open (FILE3, ">>", "resultado2.txt");

## el siguiente bloque extrae palabras en mayúsculas con un
## mínimo de diez letras

while (<FILE>){
while ($_ =~ m/([A-Z]{10,})/g){
$sec = $1;
chomp $sec;
ind_sec(); # le paso cada coincidencia a la subrutina
}
}

## tratando de buscar cada coincidencia en el archivo bibliotecas.txt

sub ind_sec{
$secb = $_;
print $secb;
$count = 0;
while ($sed = <FILE2>){
while ($sed =~ m/$secb/g){
$count += 1;
print;
}
}
print FILE3 "$secb - $count"; # imprime la secuencia y el número de veces que aparece
}

close (FILE);
close (FILE2);
close (FILE3);

exit;
pubafra
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2014-12-04 21:16 @927

Re: Obtener el número de veces que aparecen las secuencias

Notapor explorer » 2015-03-18 21:26 @934

Tienes que reiniciar la búsqueda en biblioteca.txt cada vez que llamas a ind_sec(). Es decir, que debes hacer el open() y el close de FILE2 dentro de esa subrutina.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Obtener el número de veces que aparecen las secuencias

Notapor pubafra » 2015-03-23 22:34 @982

¿Qué tal, explorer? Gracias por responder.

He avanzado con tu ayuda. Ya tengo este script pero no me sale exactamente el resultado que deseo.

¿Qué variable debo capturar en la expresión regular que se encuentra dentro de la subrutina? Porque $1 la ocupo en la primera expresión regular y al tratar de imprimir junto a $count me sale un error.

Aquí mi avance:
use warnings;

open (FILE, "unicas.txt");

while (<FILE>){
while ($_ =~ m/([A-Z]{10,})/g){
$sec = $1;
chomp $sec;
ind_sec();
}
}


sub ind_sec{
open (FILE2, "datos.txt");
$count = 0;
while ($sed = <FILE2>){
while ($sed =~ m/$sec/g){
$count += 1;
print "$count\n";
}
}
close (FILE2);
}

close (FILE);

exit;
Última edición por explorer el 2015-03-24 08:58 @415, editado 1 vez en total
Razón: que => ¿Qué; aqui => Aquí;
pubafra
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2014-12-04 21:16 @927

Re: Obtener el número de veces que aparecen las secuencias

Notapor explorer » 2015-03-24 15:07 @672

Hay que cambiar un par de cosas:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use warnings;
  3.  
  4. open( FILE, "secuencias.txt" );
  5.  
  6. while (<FILE>) {
  7.     while ( $_ =~ m/([A-Z]{10,})/g ) {
  8.         $sec = $1;
  9.         chomp $sec;
  10.         ind_sec();
  11.     }
  12. }
  13.  
  14. sub ind_sec {
  15.     open( FILE2, "bibliotecas.txt" );
  16.     $count = 0;
  17.     while ( $sed = <FILE2> ) {
  18.         while ( $sed =~ m/$sec/g ) {
  19.             $count += 1;
  20.         }
  21.     }
  22.     close(FILE2);
  23.     print "$sec $count\n";
  24. }
  25.  
  26. close(FILE);
  27.  
  28. exit;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Entonces, la salida es:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
TTGGACTGAAGGGAGCTCCCT 1
AGGCAGCTCTCCTCTGGCAGG 0
TGAAGTGTTTGGGGGAACTC 1
TGCAGTTGCTGCCTCAAGCTT 1
TTTGGAGTGAAGGGAGCTCTG 0
AATGGAGGCTGATCCAAGATC 1
GTGAAGTGTTTGGGGGAACTC 1
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Pero, repito, esto es tremendamente ineficiente. Además, no contemplas el caso de que una secuencia comience dentro de sí misma.

Por ejemplo, si tenemos una secuencia a buscar como

AATAATAATAATAATAAT

resulta que si la buscamos en

AATAATAATAATAATAATAATAATAATAATAATAAT

nos dará que la ha encontrado dos veces, que es lo correcto... ¿o quizás no? Realmente, la secuencia se repite siete veces:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
bibli: AATAATAATAATAATAATAATAATAATAATAATAAT
seq_1: AATAATAATAATAATAAT
seq_2:    AATAATAATAATAATAAT
seq_3:       AATAATAATAATAATAAT
seq_4:          AATAATAATAATAATAAT
seq_5:             AATAATAATAATAATAAT
seq_6:                AATAATAATAATAATAAT
seq_7:                   AATAATAATAATAATAAT
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
No nos dices si quieres contemplar este caso. Sí, ya sabemos que es casi imposible que se dé, pero...

Este caso es más real: Si buscamos esta secuencia:

GTGAAGTGTGTGAAGTGTG

dentro de

GTGAAGTGTGTGAAGTGTGTGAAGTGTGTGAAGTGTG

¿Cuál debe ser el resultado? Si lo hacemos con tu expresión regular (/$sec/g), nos dirá que solo aparece una vez. Pero... si la buscamos de forma exhaustiva, ¡aparece tres veces!

Esta es mi solución:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.14;
  3. use autodie;
  4.  
  5.  
  6. ## Leemos las secuencias
  7. my %secuencias;
  8.  
  9. open my $SECUENCIAS, '<', 'secuencias.txt';
  10.  
  11. while (my $sec = <$SECUENCIAS>) {               # Para todas las secuencias
  12.     chomp $sec;                                 # Quitamos el final de línea
  13.  
  14.     $secuencias{$sec} = 0;                      # Inicializar el contador de aparición
  15.                                                 # para cada secuencia
  16. }
  17.  
  18. close $SECUENCIAS;
  19.  
  20. ## Procesamos el archivo de bibliotecas
  21. open my $BIBLIO, '<', 'bibliotecas.txt';
  22.  
  23. while (my $linea = <$BIBLIO>) {
  24.  
  25.     my @columnas          = split " ", $linea;  # Partimos en columnas
  26.     my $secuencia_a_mirar = $columnas[1];       # Nos interesa la 2.ª columna
  27.    
  28.     for my $sec (keys %secuencias) {            # Para todas las secuencias a buscar
  29.    
  30.         while ($secuencia_a_mirar =~ /$sec/g) { # La buscamos
  31.        
  32.             $secuencias{$sec}++;                # Contamos una aparición más
  33.            
  34.                                                 # Reposicionamos (OPCIONAL)
  35.             pos($secuencia_a_mirar) = pos($secuencia_a_mirar) - length($sec) + 1;
  36.         }
  37.     }
  38. }
  39.  
  40. close $BIBLIO;
  41.  
  42. ## Salida de resultados
  43. while(my($sec, $veces) = each %secuencias) {
  44.     say "$sec => $veces";
  45. }
  46.  
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
La línea que dice OPCIONAL es la que permite hacer una búsqueda exhaustiva, como la del ejemplo que te he puesto. Si crees que no se va a dar ese caso, se puede quitar.

Con un archivo de secuencias como este:
Sintáxis: (secuencias.txt) [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
TTGGACTGAAGGGAGCTCCCT
AGGCAGCTCTCCTCTGGCAGG
TGAAGTGTTTGGGGGAACTC
TGCAGTTGCTGCCTCAAGCTT
TTTGGAGTGAAGGGAGCTCTG
AATGGAGGCTGATCCAAGATC
GTGAAGTGTTTGGGGGAACTC
GTGAAGTGTGTGAAGTGTG
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
Y con este archivo a analizar (la última línea es la "problemática" ;) )
Sintáxis: (bibliotecas.txt) [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
3:1:1619:956    CGGTTGGACTGAAGGGAGCTCCCTTTGGACTGAAGG    40 40 40 40 40 40 18 4 40 34 7 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40       N
3:1:1333:1700   GTTGTAGTATAGTGGTAAGTATTCCCGCTGTAGGCA    40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40     Y
3:1:1745:1406   AATGGAGGCTGATCCAAGATCGTGAAGTGTTTGGGG    40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 10 40 3 40 40 40 40 33 40 40 40 40 40 40 40 40      N
3:1:1181:2030   GTCGTCTGTCTTGAAGTGAAGTGTTTGGGGGAACTC    40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 10 18     Y
3:1:900:1829    GGTGTTGTGTGTTTTTGCAGTTGCTGCCTCAAGCTT    40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40     Y
3:1:900:1829    GTGAAGTGTGTGAAGTGTGTGAAGTGTGTGAAGTGTG   40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40     Y
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
El resultado es:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
AGGCAGCTCTCCTCTGGCAGG => 0
TTGGACTGAAGGGAGCTCCCT => 1
GTGAAGTGTTTGGGGGAACTC => 1
TTTGGAGTGAAGGGAGCTCTG => 0
AATGGAGGCTGATCCAAGATC => 1
TGCAGTTGCTGCCTCAAGCTT => 1
TGAAGTGTTTGGGGGAACTC => 1
GTGAAGTGTGTGAAGTGTG => 3
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Esta solución sigue las mismas ideas que la tuya. Pero sigue siendo menos eficiente que la primera solución que te di, en la que se construye una enorme exp. reg., con lo que se elimina el bucle más interno.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Siguiente

Volver a Bioinformática

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 4 invitados

cron