• Publicidad

Contar número de veces de aparición

Perl aplicado a la bioinformática

Contar número de veces de aparición

Notapor danusol » 2010-10-13 04:14 @218

Hola perleros,

estoy interesado en crear un programa que me lea un archivo de secuencias cortas en formato FASTA y que me cuente el número de apariciones de cada secuencia. Me imagino que para ello tengo que crear un hash. La cuestión es que el archivo es muy grande y en pruebas con otro software he visto que puedo tener hasta 1 millón de secuencias únicas algunas repetidas más de una vez. Me gustaría luego poder crear un archivo de salida también en formato FASTA con los encabezados originales sólo para aquellas secuencias que aparecen al menos un número determinado de veces, especificado en los parámetros del programa. ¿Cómo puedo diseñar este programa? Me imagino que luego vendré con preguntas específicas, pero para empezar...

Primero, he pensado en crear un hash, meter la primera secuencia del archivo de entrada y luego empezar a comparar la siguiente. Si es igual, sumar uno al valor del key, si no, añadir otro key e inicializar su valor.

Después, he pensado eliminar todas aquellas entradas del hash que tengan un valor menor al especificado en los parámetros del programa.

La duda que me queda es cómo recuperar el encabezado original de cada uno de los keys que no se han eliminado y escribirlo a un archivo de salida.

Os incluyo un ejemplo de entrada:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
>19981#0/1
GTTGACTATTGCATCTGGAC
>2276#0/1
GTTGACTATTGCATCTGGAC
>16286#0/1
AGCGGATCTGTAAAGGCTTTC
>16971#0/1
AGCGGATCTGTAAAGGCTTTC
>5253#0/1
AGCGGATCTGTAAAGGCTTTC
>16494#0/1
AGCGGATCTGTAAAGGCTTTC
>19730#0/1
AGCGGATCTGTAAAGGCTTTC
>10089#0/1
GCAAGTTTGTGAACATGTA
>15513#0/1
TGCATTTACACCTGCACCTC
>18793#0/1
ATTATGATGTCACAGATG
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Como veis, las secuencias 1 y 2 son iguales y las secuencias 3,4,5,6 y 7 también. Las tres últimas secuencias no se repiten.

La salida del programa, seleccionando un criterio de al menos 3 repeticiones debería ser:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
>16286#0/1
AGCGGATCTGTAAAGGCTTTC
>16971#0/1
AGCGGATCTGTAAAGGCTTTC
>5253#0/1
AGCGGATCTGTAAAGGCTTTC
>16494#0/1
AGCGGATCTGTAAAGGCTTTC
>19730#0/1
AGCGGATCTGTAAAGGCTTTC
 
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


¡Mil gracias!

D.
danusol
Perlero nuevo
Perlero nuevo
 
Mensajes: 46
Registrado: 2010-04-22 07:08 @339

Publicidad

Re: Contar número de veces de aparición

Notapor explorer » 2010-10-13 04:47 @240

danusol escribiste:Primero, he pensado en crear un hash, meter la primera secuencia del archivo de entrada y luego empezar a comparar la siguiente. Si es igual, sumar uno al valor del key, si no, añadir otro key e inicializar su valor.

Después, he pensado eliminar todas aquellas entradas del hash que tengan un valor menor al especificado en los parámetros del programa.

Con los hash, no te hace falta "buscar" claves: es implícito en un hash.

La siguiente solución da la salida que pides. Observa que solo se trata de guardar las secuencias como las claves del hash, como indicabas, pero, en lugar de contar el número de veces que se repiten, guardamos, como valor de ellas, los nombres de las secuencias que las referencian. Tenemos entonces un hash que contiene arrays, y cada uno, es una lista de esos nombres.

Luego, a la hora de imprimir, deshacemos la madeja, quedándonos solo con los que cumplan la condición que buscamos.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. #use strict;
  3. #use warnings;
  4. #use diagnostics;
  5.  
  6. use autodie;
  7.  
  8. my $nombre_secuencia;
  9. my $secuencia;
  10. my %secuencias;
  11.  
  12. ### Parámetros
  13. @ARGV == 2  or  die "Uso: $0 <fichero secuencias> <número repeticiones mínimo>\n";
  14.  
  15. my ($fichero_secuencias, $minimo) = @ARGV;
  16.  
  17.  
  18. ### Lectura del fichero de secuencias
  19. open my $fh_secuencias, q[<], $fichero_secuencias;
  20.  
  21. while (<$fh_secuencias>) {
  22.     if (/^ > (.+)/x) {
  23.         $nombre_secuencia = $1;         # leemos el nombre de la secuencia
  24.         $secuencia = <$fh_secuencias>;  # leemos la secuencia que le sigue
  25.  
  26.         # guardamos el nombre asociado a la secuencia en el array asociado a la secuencia
  27.         push @{ $secuencias{$secuencia} }, $nombre_secuencia;
  28.     }
  29. }
  30.  
  31. close $fh_secuencias;
  32.  
  33.  
  34. ### Salida
  35. for my $seq ( keys %secuencias ) {   # recorremos todas las secuencias encontradas
  36.  
  37.     # nombres de las secuencias que tienen esa misma secuencia
  38.     my @nombres = @{$secuencias{$seq}};
  39.  
  40.     # si la secuencia se repite menos del mínimo, pasamos a la siguiente
  41.     next if @nombres < $minimo;
  42.  
  43.     for my $nombre ( @nombres ) {    # impresión
  44.         print ">$nombre\n";
  45.         print "$seq";
  46.     }
  47. }
  48.  
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4

La línea 24 es especial: este programa sólo funcionará si la secuencia está contenido en una sola línea, y que además sea la línea que sigue a la línea del nombre de la secuencia.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Contar número de veces de aparición

Notapor danusol » 2010-10-13 05:41 @279

Explorer, muchísimas gracias por tu rápida respuesta. Ni se me había pasado por la cabeza la posibilidad de meter como valor un array, ¡increíble! (para un novato, claro). Es una solución muy inteligente. El problema que veo (y eso me pasa por no contar toda la historia) es que tengo en mente una modificación de este programa para que funcione con un formato similar, formato que en vez de dos líneas por secuencia, tiene cuatro, y ahora el indicador de nuevo bloque (cuatro líneas) es un "@", como sigue:

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
@ILLUMINA-GA_0001:1:14:1187:19981#0/1
GTTGACTATTGCATCTGGACC
+ILLUMINA-GA_0001:1:14:1187:19981#0/1
\dedeaee`Lac\^\d^YT^^
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


y entonces en este caso no se podría meter la primera, tercera y cuarta líneas dentro del valor de la clave en un array, ¿no?.

Por otro lado, ¿podrías explicarme un poco la expresión regular que usas para el encabezado? La primera parte la entiendo pero no me queda claro el significado de /x al final de la expresión en la línea 22.
danusol
Perlero nuevo
Perlero nuevo
 
Mensajes: 46
Registrado: 2010-04-22 07:08 @339

Re: Contar número de veces de aparición

Notapor explorer » 2010-10-13 06:29 @312

Es normal, en Perl, pensar en "más de una dimensión" :) Pero solo hasta cierto punto, el suficiente para organizar la información que recibimos. Ideal, también, haber estudiado/leído algo de Estructuras de datos.

En lo referente al cambio de formato, pues entonces, hay que describirlo con detalle, cada una de sus partes. Por ejemplo, no sé la importancia de la línea que comienza por '+'. Es la secuencia la que hace de clave del hash, pero, como valor, puedes componer lo que quieras (la primera, la tercera y cuarta) en un solo escalar, que ese será el valor que meterás en el array (una posible solución).

Algo así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. ### Leemos el registro (después de haber leído la línea de cabecera)
  2. $secuencia  = <$fh>;
  3. my $tercera = <$fh>;
  4. my $cuarta  = <$fh>;
  5. ## Composición del nombre
  6. $nombre_secuencia =  $1 . $tercera . $cuarta; # $1 viene de la exp. reg.
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Así, estamos metiendo las tres líneas en un solo valor escalar (con '.' concatenamos cadenas de caracteres).

El '/x' sirve para escribir la expresión regular con espacios en blanco, para que sea un poco más clara. Así, es lo mismo escribir

/^ > (.+)/x

que

/^>(.+)/

pero, un poco menos "apretado". Más información en perldoc perlre.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Contar número de veces de aparición

Notapor danusol » 2010-10-13 07:10 @340

Muchísimas gracias de nuevo,

este es un formato de secuenciación masiva y las cuatro líneas son importantes: la primera es el encabezado del bloque; la segunda, la secuencia; la tercera, el encabezado de calidad de dicha secuencia; y la cuarta, la calidad de cada base en formato ASCII. La solución de concatenar las líneas 1, 3 y 4 me parece buena, pero tendré que añadir un guión bajo '_' o algo si quiero al final deconcatenar y poder recuperarlas y generar el archivo de resultados con el mismo formato de inicio.

Por cierto, efectivamente hablaba del valor de la clave para guardar el array y no de la clave en sí.

D.
danusol
Perlero nuevo
Perlero nuevo
 
Mensajes: 46
Registrado: 2010-04-22 07:08 @339

Re: Contar número de veces de aparición

Notapor explorer » 2010-10-13 10:40 @486

No te hace falta unirlas con '_'... ya están separadas entre sí con el carácter "\n" que traen del mismo fichero del que fueron leídas.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Contar número de veces de aparición:RESUELTO

Notapor danusol » 2010-10-15 04:18 @220

Muchas gracias explorer, me pongo a ello. Aprendo muchísimo con el foro.

D.
danusol
Perlero nuevo
Perlero nuevo
 
Mensajes: 46
Registrado: 2010-04-22 07:08 @339

Re: Contar número de veces de aparición

Notapor danusol » 2012-06-06 10:14 @468

Hola de nuevo.

Reactivo esta viejo hilo por estar muy relacionado con mi problema actual.

Tengo un archivo de texto con dos columnas separadas por espacio, de tal manera que la primera es un Transcript ID y la segunda es una proteína. El mismo Transcript ID puede corresponder a varias proteínas pero también puede haber el mismo Transcript ID con la misma proteína, por lo que existe redundancia, de la siguiente manera:

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Locus_3_Transcript_3/4_Confidence_0.714_Length_1364 sp|Q924L1|LTMD1_MOUSE
Locus_3_Transcript_3/4_Confidence_0.714_Length_1364 sp|Q924L1|LTMD1_MOUSE
Locus_3_Transcript_3/4_Confidence_0.714_Length_1364 sp|Q28EM8|LTMD1_XENTR
Locus_3_Transcript_3/4_Confidence_0.714_Length_1364 sp|Q6P1Q0|LTMD1_HUMAN
Locus_3_Transcript_3/4_Confidence_0.714_Length_1364 sp|Q6P1Q0|LTMD1_HUMAN
Locus_3_Transcript_4/4_Confidence_0.929_Length_1250 sp|Q924L1|LTMD1_MOUSE
Locus_3_Transcript_4/4_Confidence_0.929_Length_1250 sp|Q924L1|LTMD1_MOUSE
Locus_3_Transcript_4/4_Confidence_0.929_Length_1250 sp|Q924L1|LTMD1_MOUSE
Locus_3_Transcript_4/4_Confidence_0.929_Length_1250 sp|Q6P1Q0|LTMD1_HUMAN
Locus_3_Transcript_4/4_Confidence_0.929_Length_1250 sp|Q6P1Q0|LTMD1_HUMAN
Locus_3_Transcript_4/4_Confidence_0.929_Length_1250 sp|Q6P1Q0|LTMD1_HUMAN
Locus_3_Transcript_4/4_Confidence_0.929_Length_1250 sp|Q28EM8|LTMD1_XENTR
Locus_3_Transcript_4/4_Confidence_0.929_Length_1250 sp|Q28EM8|LTMD1_XENTR
Locus_4_Transcript_15/24_Confidence_0.582_Length_3109 sp|Q2KIR8|TDH_BOVIN
Locus_4_Transcript_15/24_Confidence_0.582_Length_3109 sp|Q2KIR8|TDH_BOVIN
Locus_4_Transcript_15/24_Confidence_0.582_Length_3109 sp|Q2KIR8|TDH_BOVIN
Locus_4_Transcript_15/24_Confidence_0.582_Length_3109 sp|Q8MIR0|TDH_PIG
 
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Lo que quiero hacer es ver cuántos Transcript ID representan cada proteína, pero sin redundancia, es decir si un mismo Transcript ID representa la misma proteína dos veces, entonces solo cuenta como uno.

Así, en el ejemplo de arriba, el resultado sería
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
sp|Q924L1|LTMD1_MOUSE 2
sp|Q28EM8|LTMD1_XENTR 2
sp|Q6P1Q0|LTMD1_HUMAN 2
sp|Q2KIR8|TDH_BOVIN 1
sp|Q8MIR0|TDH_PIG 1
 
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Para ello, estoy intentando leer cada línea para formar un hash de array, de tal manera que cada clave sea una proteína y su valor sea el array de Transcript ID. Por último, quiero crear un array que me guarde los Transcript ID únicos en cada valor/array con la función 'uniq' y al final imprimir cada clave con la longitud de su correspondiente array único.

El resultado que obtengo no es el esperado, porque todos me da como resultado que tienen una única aparición.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. #use strict;
  3. #use warnings;
  4. #use diagnostics;
  5. use List::MoreUtils qw/ uniq /;
  6.  
  7. use autodie;
  8.  
  9. my $transcript; #transcript ID
  10. my $protein; #nombre proteina asociada
  11. my %HashOfArrays;
  12.  
  13. ### Parámetros
  14. @ARGV == 1  or  die "Uso: $0 <fichero_transcritos>\n";
  15.  
  16. my ($fichero_transcritos) = @ARGV[0];
  17.  
  18.  
  19. ### Lectura del fichero de secuencias
  20. open my $fh_input, q[<], $fichero_transcritos;
  21. open (OUT,">output.txt") or die "can't open OUT file";
  22. while (<$fh_input>) {
  23.         chomp;
  24.         ($transcript,$protein) = split(/ /);#separar las dos columnas por espacio
  25.  
  26.         # guardamos el transcript ID en el array asociado a la proteina
  27.         push @{ $HashOfArrays{$protein} }, $transcript; #tenemos un hash con claves "proteinas" y valores arrays de "transcript ID"
  28.     }
  29.  
  30.  
  31. close $fh_input;
  32.  
  33.  
  34. ### Salida
  35. for my $family ( keys %HashOfArrays ) {   # recorremos todas las proteinas encontradas
  36.        
  37.         my @unique = uniq $HashOfArrays{$family}; #utilizando la libreria MoreUtils creo un array con los transcript IDs unicos para cada clave-proteina.
  38.         print OUT "$family\t", @unique."\n"; #imprimo el nombre de la proteina junto con la longitud del array de nombres únicos.
  39.  
  40.     }
  41.  
  42.  
  43. close(OUT);
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


¿Dónde fallo?

Gracias,

D.
danusol
Perlero nuevo
Perlero nuevo
 
Mensajes: 46
Registrado: 2010-04-22 07:08 @339

Re: Contar número de veces de aparición

Notapor explorer » 2012-06-06 10:49 @492

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.         my @unique = uniq @{ $HashOfArrays{$family} };
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Contar número de veces de aparición

Notapor danusol » 2012-06-06 10:55 @496

¡ayyyy!

¡Mil gracias, ahora sí!

D.
danusol
Perlero nuevo
Perlero nuevo
 
Mensajes: 46
Registrado: 2010-04-22 07:08 @339


Volver a Bioinformática

¿Quién está conectado?

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

cron