• Publicidad

Procesamiento básico de textos

Perl aplicado a la bioinformática

Re: Procesamiento básico de textos

Notapor alexclipse » 2012-04-26 04:12 @216

Voy avanzando aunque sigo sin acabar. Con lo que tengo ahora, para el primer gen imprimo en el archivo express (y en prueba para comprobar) la lista de tejidos sin ';'. Sin embargo para el resto de genes me da error al ejecutar pero no consigo identificarlo. A ver si consigues ver el fallo, porque tengo lo mismo que para el primer gen.

use warnings;
use diagnostics;
my $a = "ADH2.txt"; #Archivo de entrada del primer gen
my $a1 = "ADH2.express"; #Archivo de salida del primer gen
my $a2 = "prueba.txt"; #compruebo que se escriben los datos en un txt
my $b = "CEACAM4.txt"; #Archivo de entrada del segundo gen
my $b1 = "CEACAM4.express"; #Archivo de salida del segundo gen
my $b2 = "prueba2.txt";
my $c = "GLDC.txt"; #Archivo de entrada del tercer gen
my $c1 = "GLDC.express"; #Archivo de salida del tercer gen
my $c2 = "prueba3.txt";
my $d = "TGM1.txt"; #Archivo de entrada del cuarto gen
my $d1 = "TGM1.express"; #Archivo de salida del cuarto gen
my $d2 = "prueba4.txt";
print "Introduzca el nombre del gen:";
my $gen = <STDIN>;
chomp ($gen);
if ($gen eq "adh2") {
open (ADH2, $a) || die "No se pudo abrir el archivo \"$infile\": $!"; #Este proceso lo repito
open (FINADH2, ">$a1") || die "No se pudo abrir el archivo \"$infile\": $!"; #con los otros 3 genes
open (PRUEBA, ">$a2") || die "No se pudo abrir el archivo \"$infile\": $!";
while ($a = <ADH2>) {
if ($a =~ EXPRESS) {
my $tejidos = substr ($a, 12);
my @tejidos2 = split (/;/, $tejidos);
print FINADH2 "@tejidos2";
print PRUEBA "@tejidos2";
}}
close (ADH2);
close (FINADH2);
}
elsif ($gen eq "ceacam4") {
open (CEACAM4, $b) || die "No se pudo abrir el archivo \"$infile\": $!";
open (FINCEACAM4, ">$b1") || die "No se pudo abrir el archivo \"$infile\": $!";
open (PRUEBA2, ">$b2") || die "No se pudo abrir el archivo \"$infile\": $!";
while ($b = <CEACAM4>) {
my $tejidos = substr ($b, 12);
my @tejidos2 = split (/;/, $tejidos);
print FINCEACAM4 "@tejidos2";
print PRUEBA2 "@tejidos2";
}
close (CEACAM4);
close (FINCEACAM4);
}
elsif ($gen eq "gldc") {
open (GLDC, $c) || die "No se pudo abrir el archivo \"$infile\": $!";
open (FINGLDC, ">$c1") || die "No se pudo abrir el archivo \"$infile\": $!";
open (PRUEBA3, ">$c2") || die "No se pudo abrir el archivo \"$infile\": $!";
while ($c = <GLDC>) {
my $tejidos = substr ($c, 12);
my @tejidos2 = split (/;/, $tejidos);
print FINGLDC "@tejidos2";
print PRUEBA3 "@tejidos2";
}
close (GLDC);
close (FINGLDC);
}
elsif ($gen eq "tgm1") {
open (TGM1, $d) || die "No se pudo abrir el archivo \"$infile\": $!";
open (FINTGM1, ">$d1") || die "No se pudo abrir el archivo \"$infile\": $!";
open (PRUEBA4, ">$d2") || die "No se pudo abrir el archivo \"$infile\": $!";
while ($d = <TGM1>) {
my $tejidos = substr ($d, 12);
my @tejidos2 = split (/;/, $tejidos);
print FINTGM1 "@tejidos2";
print PRUEBA4 "@tejidos2";
}
close (TGM1);
close (FINTGM1);
}
else { #si no introduzco el nombre de ninguno de los 3 genes haz...
print "Gen incorrecto\n";
}
alexclipse
Perlero nuevo
Perlero nuevo
 
Mensajes: 43
Registrado: 2012-03-27 11:17 @511

Publicidad

Re: Procesamiento básico de textos

Notapor explorer » 2012-04-26 05:40 @278

Claro... no has puesto el filtrado de la palabra EXPRESS en el resto de genes.

Eso es lo que pasa cuando repites lo mismo cuatro veces... que crees que lo has hecho, pero no... :)

A ver... la solución no está tan lejos... solo es cuestión de fijarse: las cuatro partes son idénticas porque puedes reproducir los cuatro comportamientos con solo el valor del gen que el usuario nos ingresa por el teclado...
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Procesamiento básico de textos

Notapor alexclipse » 2012-04-26 06:00 @292

Vale, no sé copiar y pegar... xD Ahora tengo en los archivos de salida los tejidos sin los puntos y coma. Solo me falta ponerlos en columna con los números delante. Aquí sí que no tengo ni idea de cómo hacerlo.
alexclipse
Perlero nuevo
Perlero nuevo
 
Mensajes: 43
Registrado: 2012-03-27 11:17 @511

Re: Procesamiento básico de textos

Notapor explorer » 2012-04-26 07:44 @363

Inicializa una variable a 1.
Entra en el bucle que recorra los tejidos.
Por cada uno, pintas la variable contador y un tejido.
Incrementas la variable contador.
Y repites el bucle hasta que se agoten todos los tejidos.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Procesamiento básico de textos

Notapor alexclipse » 2012-04-27 04:23 @224

Ya casi está. Tengo 2 problemillas. El primero es que si, por ejemplo, tengo 15 tejidos en ese gen, me imprime los 15 correspondientes en orden con su número y después me imprime también el 16, sin nada detrás. he probado al igual que con el gen 2 (ceacam4) a poner en el índice del array $contador-1, pero entonces el primero queda en blanco.
El otro problema es cómo hacer lo que me dijiste en otro comentario, que es escribir el código solo una vez y no cuatro. Gracias por adelantado. :D

Este es el código:

use warnings;
use diagnostics;
my $a = "ADH2.txt"; #Archivo de entrada del primer gen
my $a1 = "ADH2.express"; #Archivo de salida del primer gen
my $a2 = "prueba.txt"; #compruebo que se escriben los datos en un txt
my $b = "CEACAM4.txt"; #Archivo de entrada del segundo gen
my $b1 = "CEACAM4.express"; #Archivo de salida del segundo gen
my $b2 = "prueba2.txt";
my $c = "GLDC.txt"; #Archivo de entrada del tercer gen
my $c1 = "GLDC.express"; #Archivo de salida del tercer gen
my $c2 = "prueba3.txt";
my $d = "TGM1.txt"; #Archivo de entrada del cuarto gen
my $d1 = "TGM1.express"; #Archivo de salida del cuarto gen
my $d2 = "prueba4.txt";
print "Introduzca el nombre del gen:";
my $gen = <STDIN>;
chomp ($gen);
if ($gen eq "adh2") {
open (ADH2, $a) || die "No se pudo abrir el archivo \"$infile\": $!"; #Este proceso lo repito
open (FINADH2, ">$a1") || die "No se pudo abrir el archivo \"$infile\": $!"; #con los otros 3 genes
open (PRUEBA, ">$a2") || die "No se pudo abrir el archivo \"$infile\": $!";
while ($a = <ADH2>) {
if ($a =~ EXPRESS) {
my $tejidos = substr ($a, 12);
my @tejidos2 = split (/;/, $tejidos);
my $contador = 1;
foreach $valor (@tejidos2) {
print FINADH2 "$contador. $tejidos2[$contador]\n";
print PRUEBA "$contador. $tejidos2[$contador]\n";
$contador ++;
}
print "Hecho\n";
}}
close (ADH2);
close (FINADH2);
close (PRUEBA);
}
elsif ($gen eq "ceacam4") {
open (CEACAM4, $b) || die "No se pudo abrir el archivo \"$infile\": $!";
open (FINCEACAM4, ">$b1") || die "No se pudo abrir el archivo \"$infile\": $!";
open (PRUEBA2, ">$b2") || die "No se pudo abrir el archivo \"$infile\": $!";
while ($b = <CEACAM4>) {
if ($b =~ EXPRESS) {
my $tejidos = substr ($b, 12);
my @tejidos2 = split (/;/, $tejidos);
my $contador = 1;
foreach $valor (@tejidos2) {
print FINCEACAM4 "$contador. $tejidos2[$contador-1]\n";
print PRUEBA2 "$contador. $tejidos2[$contador-1]\n";
$contador ++;
}
print "Hecho\n";
}}
close (CEACAM4);
close (FINCEACAM4);
close (PRUEBA2);
}
elsif ($gen eq "gldc") {
open (GLDC, $c) || die "No se pudo abrir el archivo \"$infile\": $!";
open (FINGLDC, ">$c1") || die "No se pudo abrir el archivo \"$infile\": $!";
open (PRUEBA3, ">$c2") || die "No se pudo abrir el archivo \"$infile\": $!";
while ($c = <GLDC>) {
if ($c =~ EXPRESS) {
my $tejidos = substr ($c, 12);
my @tejidos2 = split (/;/, $tejidos);
my $contador = 1;
foreach $valor (@tejidos2) {
print FINGLDC "$contador. $tejidos2[$contador]\n";
print PRUEBA3 "$contador. $tejidos2[$contador]\n";
$contador ++;
}
print "Hecho\n";
}}
close (GLDC);
close (FINGLDC);
close (PRUEBA3);
}
elsif ($gen eq "tgm1") {
open (TGM1, $d) || die "No se pudo abrir el archivo \"$infile\": $!";
open (FINTGM1, ">$d1") || die "No se pudo abrir el archivo \"$infile\": $!";
open (PRUEBA4, ">$d2") || die "No se pudo abrir el archivo \"$infile\": $!";
while ($d = <TGM1>) {
if ($d =~ EXPRESS) {
my $tejidos = substr ($d, 12);
my @tejidos2 = split (/;/, $tejidos);
my $contador = 1;
foreach $valor (@tejidos2) {
print FINTGM1 "$contador. $tejidos2[$contador]\n";
print PRUEBA4 "$contador. $tejidos2[$contador]\n";
$contador ++;
}
print "Hecho\n";
}}
close (TGM1);
close (FINTGM1);
close (PRUEBA4);
}
else { #si no introduzco el nombre de ninguno de los 3 genes haz...
print "Gen incorrecto\n";
}
alexclipse
Perlero nuevo
Perlero nuevo
 
Mensajes: 43
Registrado: 2012-03-27 11:17 @511

Re: Procesamiento básico de textos

Notapor explorer » 2012-04-27 05:51 @286

Los problemas uno y dos, son el mismo, debido a que estás imprimiendo valores del array de tejidos con un índice con un valor superior en uno, porque estás usando la variable contador a partir de 1, cuando los arrays siempre empiezan en 0.

Así lo estás haciendo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $contador = 1;                                        # inicializamos $contador en 1
  2. foreach $valor (@tejidos2) {                             # para cada $valor de los @tejidos
  3.     print FINADH2 "$contador. $tejidos2[$contador]\n";   # lo sacamos fuera
  4.     print PRUEBA "$contador. $tejidos2[$contador]\n";
  5.  
  6.     $contador++;                                         # incrementamos $contador
  7. }
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4
El problema está en $tejidos2[$contador]. ¿Cuál es el primer valor que se imprime? Este: $tejidos2[1]. ¿Y qué ha pasado con el $tejidos2[0]? Pues que nunca lo imprimes.

Ahora bien... tu no notas el problema porque ves que el primer tejido sí que sale en el listado.

Eso es porque la línea de tejidos contiene un ';' inicial, por lo que el split() almacena un 'undef' en el $tejidos2[0].

Y ahora viene el problema 1: estás imprimiendo con un índice más allá del límite del array, y por eso sale vacía la última entrada. Si @tejidos2 contiene, por ejemplo, 6 valores, $contador recorre los valores de 1 a 6, pero $tejidos2[6] no existe.

Y el problema 2 ocurre porque en los casos que solo hay un tejido, no llevan ningún carácter ';'. En ese caso, el tejido se almacena en $tejidos[0], pero $contador empieza en 1... y no lo vemos.

La solución es vigilar cada $valor, para ver si contiene algo o no.

Mejor lo escribes así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $contador = 1;                                        # inicializamos $contador en 1
  2. for $valor (@tejidos2) {                                 # para cada $valor de los @tejidos
  3.     next if not $valor;                                  # saltamos al siguiente $valor, si éste está vacío
  4.  
  5.     print FINADH2 "$contador. $valor\n";                 # lo sacamos fuera
  6.     print PRUEBA  "$contador. $valor\n";
  7.     $contador++;                                         # incrementamos $contador
  8. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Y ya está: es el propio for() el que nos da cada elemento del array, así que ese es justo el valor a imprimir.

Para el tercer problema... Todo tu programa queda reducido a esto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;                                             # Programación estricta, lo prometemos
  3. use warnings;                                           # Avísanos de cualquier cosa rara
  4. use diagnostics;                                        # pero... con detalles...
  5.  
  6. # Lista de genes a procesar
  7. my @genes = qw(
  8.     ADH2 CEACAM4 GLDC TGM1
  9. );
  10. my $genes = join '|', @genes;                           # Lo mismo, unidos por '|'
  11.  
  12. print "Introduzca el nombre del gen [$genes]: ";
  13. my $gen = <>;
  14. chomp $gen;                                             # Quitamos fin de línea
  15. $gen = uc $gen;                                         # y lo pasamos a mayúsculas (por si acaso)
  16.  
  17. if ($gen =~ /^($genes)$/) {                             # Si es un gen conocido...
  18.  
  19.     print "Procesando gen [$gen]\n";
  20.  
  21.     open my $GEN, '<', "$gen.txt"     or  die "ERROR: No se pudo abrir el archivo [$gen.txt]: $!\n";
  22.     open my $EXP, '>', "$gen.express" or  die "ERROR: No se pudo escribir en el archivo [$gen.express]: $!\n";
  23.  
  24.     print $EXP "$gen\n\n";
  25.  
  26.     while (my $linea = <$GEN>) {                        # Mientras leamos líneas desde el archivo...
  27.         if ($linea =~ /^EXPRESS/) {                     # Si la $linea comienza por EXPRESS
  28.             chomp $linea;
  29.             my @tejidos  = split /;/, substr $linea, 12;
  30.             my $contador = 1;                           # inicializamos $contador en 1
  31.  
  32.             for my $valor (@tejidos) {                  # para cada $valor de los @tejidos
  33.                 next if not $valor;                     # saltamos al siguiente $valor, si éste está vacío
  34.  
  35.                 print $EXP "$contador. $valor\n";
  36.  
  37.                 $contador++;                            # incrementamos $contador
  38.             }
  39.  
  40.             print "Hecho\n";
  41.  
  42.             last;                                       # No hace falta seguir leyendo más líneas
  43.         }
  44.     }
  45.  
  46.     close $EXP;
  47.     close $GEN;
  48. }
  49. else {                                  # Error: no metió ningún gen conocido
  50.     print "Gen incorrecto\n";
  51. }
  52.  
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
El truco está en la confección de $genes.

Primero tenemos @genes, escrito en forma de palabras sueltas, para que sea fácil editar el programa y poder añadir, cambiar o quitar genes. A partir de él creamos $genes, que son todos los @genes, unidos con '|'. Y lo usamos para dos cosas radicalmente distintas:
  • En la línea 12 sacamos toda la lista de genes. Con el separador '|', el usuario distingue cada gen: Introduzca el nombre del gen [ADH2|CEACAM4|GLDC|TGM1]:
  • En la línea 17, usamos $genes como una expresión regular. Aquí, el carácter '|' significa 'o', así que estamos comprobando si todo el $gen (de principio (^) a fin ($)) coincide con alguno de los que tenemos en la lista de @genes. Es lo mismo que si hubiéramos escrito /^(ADH2|CEACAM4|GLDC|TGM1)$/

Una vez que sabemos qué $gen es, solo queda abrir su archivo, crear el archivo de salida, recorrer las líneas, identificar la línea EXPRESS, etcétera, etcétera.

No hace falta hacer cuatro códigos para lo mismo, porque $gen contiene el gen a tratar, y con él podemos acceder a todos los archivos.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Procesamiento básico de textos

Notapor alexclipse » 2012-04-27 09:00 @417

Entiendo lo que me dices y sería sencillo hacerlo así pero no hemos estudiado aún la mayoría de expresiones que me sugieres como next if not, for, etc. Son sencillas pero ya me bajó la calificación en otro programa por usar for.

El problema de los 4 genes es lo de menos, se queda el código cuatro veces (es más feo pero sigue siendo válido).

En cuanto al de qué valores imprimir del array, cómo puedo solucionarlo sin el next if not?
alexclipse
Perlero nuevo
Perlero nuevo
 
Mensajes: 43
Registrado: 2012-03-27 11:17 @511

Re: Procesamiento básico de textos

Notapor explorer » 2012-04-27 09:16 @428

Los bucles for() los puedes sustituir por bucles hechos en while().

Y en next if not, quiere decir: «salta a la siguiente vuelta del bucle si no se cumple una condición».

Eso quiere decir que puedes sustituir toda la línea por un simple if() de la condición contraria que abarque todo el cuerpo del bucle.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Procesamiento básico de textos

Notapor alexclipse » 2012-04-27 09:21 @431

Entiendo bien para qué sirve el next if not, es sencillo. Pero, ¿cómo sustituyo el for() por un while()? ¿Y el next if not por un if?
alexclipse
Perlero nuevo
Perlero nuevo
 
Mensajes: 43
Registrado: 2012-03-27 11:17 @511

Re: Procesamiento básico de textos

Notapor explorer » 2012-04-27 09:31 @438

Por ejemplo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $i = 0;
  2. while($i < @tejidos) {
  3.     my $valor = $tejidos[$i];
  4.  
  5.     ...;
  6.  
  7.     $i++;
  8. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Para el next if not, dices que lo entiendes, y te he indicado lo que tienes que hacer: cambiarlo por un if(), pero con la condición contraria y que abarque todas las sentencias que forman el resto del cuerpo del for()...

Solo tienes que entender lo que hace cada sentencia, y verás cuándo se tiene que ejecutar y cuándo no...
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

AnteriorSiguiente

Volver a Bioinformática

¿Quién está conectado?

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