• Publicidad

Conteo de líneas donde la variable asuma igual valor :S

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Conteo de líneas donde la variable asuma igual valor :S

Notapor andrea » 2009-01-27 20:14 @885

Hola,
Por favor, requiero su ayuda con esto de Perl, esta es mi duda:

Mi script debe básicamente rescatar algunas partes de este archivo de entrada y ponerlos en uno nuevo con un orden especifico, lo que ya conseguí =D. Mi problema empieza cuando requiero contar el número de veces que una variable tiene el mismo valor o significado, o sea, que el número de átomos (líneas) que tiene cada aminoácido ($temp).

Debo considerar solo las líneas que empiezan con ATOM, luego debería contar hasta que el número del aminoácido cambiara al siguiente. Por ejemplo, el aminoácido 84 (corresponde a la 5ª columna) debería tener 7 átomos (el 84 aparece 7 veces), el aminoácido 86 debería tener 8, etc. Lo que hice fue asignar una variable al número del aminoácido ($temp), entonces la idea es que cuando este número cambie, la cuenta pare y empiece otra vez con el siguiente aminoácido.

Intenté poner en un hash todos los números de los aminoácidos, o sea la variable $temp, pero en los ejemplos que encontré el hash era definido solo con elementos, o sea : 84, 85, 86, etc. y no me servía porque tengo como 300 aminoácidos. Mi otro problema es que los ejemplos que vi siempre indicaban que el conteo paraba cuando la variable (en mi caso $temp) fuera mayor o menor a un número, y en mi caso requiero que el número de aminoácidos sea considerado como una palabra y el conteo pare cuando la palabra sea cambiada por otra.

Ojalá no este muy enredado para entender.

Este es parte de mi input:
Código: Seleccionar todo
HEADER    VIRAL PROTEIN/IMMUNE SYSTEM             23-SEP-05   2B4C
TITLE     CRYSTAL STRUCTURE OF HIV-1 JR-FL GP120 CORE PROTEIN
TITLE    2 CONTAINING THE THIRD VARIABLE REGION (V3) COMPLEXED WITH
TITLE    3 CD4 AND THE X5 ANTIBODY
COMPND    MOL_ID: 1;
COMPND   2 MOLECULE: ENVELOPE GLYCOPROTEIN;
ATOM      1  N   VAL G  84      83.090-158.764  98.727  1.00133.29           N
ATOM      2  CA  VAL G  84      84.569-158.842  98.897  1.00133.95           C
ATOM      3  C   VAL G  84      85.258-158.165  97.714  1.00134.16           C
ATOM      4  O   VAL G  84      85.855-158.828  96.866  1.00134.41           O
ATOM      5  CB  VAL G  84      85.039-160.312  98.978  1.00134.07           C
ATOM      6  CG1 VAL G  84      86.507-160.372  99.373  1.00134.72           C
ATOM      7  CG2 VAL G  84      84.181-161.078  99.974  1.00132.76           C
ATOM      8  N   VAL G  85      85.169-156.839  97.667  1.00134.17           N
ATOM      9  CA  VAL G  85      85.767-156.061  96.587  1.00133.97           C
ATOM     10  C   VAL G  85      87.243-155.768  96.832  1.00134.16           C
ATOM     11  O   VAL G  85      87.711-155.788  97.971  1.00134.47           O
ATOM     12  CB  VAL G  85      85.026-154.715  96.401  1.00133.69           C
ATOM     13  CG1 VAL G  85      85.141-153.883  97.666  1.00133.08           C
ATOM     14  CG2 VAL G  85      85.601-153.958  95.213  1.00133.51           C
ATOM     15  N   LEU G  86      87.971-155.505  95.751  1.00134.10           N
ATOM     16  CA  LEU G  86      89.392-155.192  95.827  1.00134.30           C
ATOM     17  C   LEU G  86      89.724-154.045  94.874  1.00134.27           C
ATOM     18  O   LEU G  86      90.077-154.264  93.714  1.00134.21           O
ATOM     19  CB  LEU G  86      90.235-156.426  95.483  1.00134.49           C
ATOM     20  CG  LEU G  86      90.134-157.616  96.446  1.00134.44           C
ATOM     21  CD1 LEU G  86      88.803-158.331  96.264  1.00134.35           C
ATOM     22  CD2 LEU G  86      91.277-158.581  96.183  1.00134.28           C
ATOM     23  N   GLU G  87      89.663-152.780  95.269  1.00136.00           N
ATOM     24  CA  GLU G  87      89.975-151.658  94.374  1.00136.69           C
ATOM     25  C   GLU G  87      91.472-151.398  94.342  1.00137.59           C


Acá va mi script:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
print "Enter PDB file name :";
$filename = <STDIN>;
chomp $filename;
unless(open (FILE,$filename)){ print "\n\nFile non found!!!\n\n";}

#open (FILE2,">out");
$i=0;
$count=0;
@pdb=<FILE>;
close FILE;

        foreach $line (@pdb){
        if ($line=~/^TITLE/){
        chomp $line;
        print "$line\n";    }

        if ($line=~/^.*\ 2 RESOLUTION\.*/){
        #print "$line";
                $res=substr($line,11,25);
                print "\n$res\n";
                                          }
        if ($line=~/^HEADER/){
        chomp $line;
                $date=substr($line,50,10);
                print "\nDEPOSIT DATE: $date\n\n";
                             }

        if ($line=~/^ATOM.*\  CA  \.*/){
#               print "$line";
                chomp $line;

                $chain=substr($line,20,3);
        #       print "\n$chain";
                $aa=substr($line,17,4);
                $naa=substr($line,23,3);
                                       }
  #Aca viene la parte del conteo de atomos por aminoacido donde ando perdida

        if ($line=~/^ATOM/){
       
        $temp=substr($line,23,3);        
    while($temp==$temp[$i]){        #quise decir que mientras $temp sea la misma que aumente el conteo
        $count{$temp}++;

         #print "$count"}
}


$col=("$chain"  .  "$aa"  .  "$naa" .  "$count\n");    #mi output deberia ser asi, de manera que lo que me ha tomado todo el dia es el valor de la ultima columna
print "$col\n";
                       }
          exit;
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Mi ouput debería ser algo así:

Código: Seleccionar todo
TITLE    CRYSTAL STRUCTURE OF HIV-1 JR-FL GP120 CORE PROTEIN                  
TITLE    2 CONTAINING THE THIRD VARIABLE REGION (V3) COMPLEXED WITH            
TITLE    3 CD4 AND THE X5 ANTIBODY

RESOLUTION. 3.30 ANGSTROMS

DEPOSIT DATE 23 SEP 05

G       VAL-84  7
G       VAL-85  7
G       LEU-86  8



Por favor, alguna idea que me ayude será muy agradecida,

Andrea
andrea
Perlero nuevo
Perlero nuevo
 
Mensajes: 15
Registrado: 2007-07-27 16:29 @728

Publicidad

Notapor explorer » 2009-01-28 10:55 @496

Esta es una solución:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;

## Abrimos el fichero pasado por el usuario
print "Enter PDB file name :";
my $filename = <STDIN>;
chomp $filename;

open FILE, "<$filename" or die "ERROR: $!\n";

## Leemos el fichero de entrada
my %fichero;
while (my $line = <FILE>) {
    chomp $line;

    if    ($line =~ /^HEADER.+(..)-(...)-(..)/) {       # De la cabecera nos interesa la fecha
        $fichero{HEADER} = "DEPOSIT DATE $1 $2 $3";
    }
    elsif ($line =~ /^TITLE/) {                         # Guardamos todos los títulos en una pila
        push @{$fichero{TITLE}}, $line;
    }
    elsif ($line =~ / 2 RESOLUTION/) {                  # Resolución
        $fichero{RESOLUTION} = 'RESOLUTION ' . substr $line, 11, 25;
    }
    elsif ($line =~ /^ATOM/) {                          # Átomos
        my @atom = split " ", $line;
        my ($chain, $aa, $naa) = @atom[4,3,5];
        $fichero{ATOM}[$naa]{"$chain\t$aa"}++ ;             # Incrementamos en uno
    }
}

close FILE;

## Mostrar los resultados
# Títulos
if (@{$fichero{TITLE}}) {
    for my $title (@{$fichero{TITLE}}) {
        print "$title\n";
    }
    print "\n";
}

# Resolución
if ($fichero{RESOLUTION}) {
    print "$fichero{RESOLUTION}\n\n";
}

# Cabecera
if ($fichero{HEADER}) {
    print "$fichero{HEADER}\n\n";
}

# Átomos
if ($fichero{ATOM}) {
    for my $naa (0 .. $#{$fichero{ATOM}}) {
        next if ! exists $fichero{ATOM}[$naa];
        for my $amino (keys %{$fichero{ATOM}[$naa]}) {
            print "$amino-$naa\t$fichero{ATOM}[$naa]{$amino}\n";
        }
    }
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

Como faltan detalles de los rangos de valores que pueden aparecer en el fichero, hay que tomar una serie de precauciones, que hace el programa más largo y complicado.

La estrategia que usamos es la de leer todo el fichero y luego pintar la salida en el orden que deseamos.

En cambio, si sabemos que por cada $naa solo existe una combinación de $chain y $aa entonces se puede simplificar un poco más:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;

## Abrimos el fichero pasado por el usuario
print "Enter PDB file name :";
my $filename = <STDIN>;
chomp $filename;

open FILE, "<$filename" or die "ERROR: $!\n";

## Leemos el fichero de entrada
my %fichero;
while (my $line = <FILE>) {
    chomp $line;

    if    ($line =~ /^HEADER.+(..)-(...)-(..)/) {       # De la cabecera nos interesa la fecha
        $fichero{HEADER} = "DEPOSIT DATE $1 $2 $3";
    }
    elsif ($line =~ /^TITLE/) {                         # Guardamos todos los títulos en una pila
        push @{$fichero{TITLE}}, $line;
    }
    elsif ($line =~ / 2 RESOLUTION/) {                  # Resolución
        $fichero{RESOLUTION} = 'RESOLUTION ' . substr $line, 11, 25;
    }
    elsif ($line =~ /^ATOM/) {                          # Átomos
        my @atom = split " ", $line;
        my ($chain, $aa, $naa) = @atom[4,3,5];
        $fichero{ATOM}{$naa}{COUNT}++ ;                     # Incrementamos en uno
        $fichero{ATOM}{$naa}{CHAIN} = "$chain\t$aa";        # Cadena previa
    }
}

close FILE;

## Mostrar los resultados
# Títulos
if (@{$fichero{TITLE}}) {
    for my $title (@{$fichero{TITLE}}) {
        print "$title\n";
    }
    print "\n";
}

# Resolución
if ($fichero{RESOLUTION}) {
    print "$fichero{RESOLUTION}\n\n";
}

# Cabecera
if ($fichero{HEADER}) {
    print "$fichero{HEADER}\n\n";
}

# Átomos
if ($fichero{ATOM}) {
    for my $naa (sort {$a <=> $b } keys %{$fichero{ATOM}}) {    # Salida por orden numérico creciente
        print "$fichero{ATOM}{$naa}{CHAIN}-$naa\t$fichero{ATOM}{$naa}{COUNT}\n";
    }
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

En esta segunda variante, guardamos, por cada ATOM, por un lado, la cadena (CHAIN) que acompaña a cada $naa, y por otro, el número de veces que aparece $naa.

Con lo que al final sale:
Código: Seleccionar todo
TITLE     CRYSTAL STRUCTURE OF HIV-1 JR-FL GP120 CORE PROTEIN
TITLE    2 CONTAINING THE THIRD VARIABLE REGION (V3) COMPLEXED WITH
TITLE    3 CD4 AND THE X5 ANTIBODY

DEPOSIT DATE 23 SEP 05


G       VAL-84  7
G       VAL-85  7
G       LEU-86  8
G       GLU-87  3

Si queremos verlo más claro cómo organizamos la información, podemos agregar estas dos líneas al final:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use Data::Dumper;
print Dumper \%fichero;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
con lo que vemos el aspecto de %ficheros:
Código: Seleccionar todo
$VAR1 = {
          'TITLE' => [
                       'TITLE     CRYSTAL STRUCTURE OF HIV-1 JR-FL GP120 CORE PROTEIN',
                       'TITLE    2 CONTAINING THE THIRD VARIABLE REGION (V3) COMPLEXED WITH',
                       'TITLE    3 CD4 AND THE X5 ANTIBODY'
                     ],
          'ATOM' => {
                      '84' => {
                                'CHAIN' => 'G   VAL',
                                'COUNT' => 7
                              },
                      '87' => {
                                'CHAIN' => 'G   GLU',
                                'COUNT' => 3
                              },
                      '85' => {
                                'CHAIN' => 'G   VAL',
                                'COUNT' => 7
                              },
                      '86' => {
                                'CHAIN' => 'G   LEU',
                                'COUNT' => 8
                              }
                    },
          'HEADER' => 'DEPOSIT DATE 23 SEP 05'
        };
Última edición por explorer el 2009-01-28 16:57 @748, editado 1 vez en total
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

Notapor andrea » 2009-01-28 15:53 @704

¡Hola! Gracias por responder tan rápido... la verdad es que el output que obtengo no es el que requiero... obtengo esto:

Código: Seleccionar todo
TITLE     CRYSTAL STRUCTURE OF HIV-1 JR-FL GP120 CORE PROTEIN
TITLE    2 CONTAINING THE THIRD VARIABLE REGION (V3) COMPLEXED WITH
TITLE    3 CD4 AND THE X5 ANTIBODY

DEPOSIT DATE 23 SEP 05

G       VAL-1  7
G       VAL-2  7
G       LEU-3  8
G       GLU-4  3


y requiero que se mantenga el 84, 85, 86 ...

Y lo otro es que no requiero que estén en orden creciente, sino solo como aparecen en el input.

Intenté con esto, pero no me resulta...

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  if ($line=~/^ATOM/){
#               print "$line";
                chomp $line;

                $chain=substr($line,20,3);
        #       print "\n$chain";
                $aa=substr($line,17,4);
                $naa=substr($line,23,3)+0;

                $count[$naa]++;

                $col= " $chain" . "$aa" . "$naa" . "$count[$naa]";

                print "$col\n";
  }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


por favor, una ayudita...
andrea
Perlero nuevo
Perlero nuevo
 
Mensajes: 15
Registrado: 2007-07-27 16:29 @728

Notapor explorer » 2009-01-28 18:46 @823

He probado mis dos códigos anteriores y a mí me sale perfecto. No me sale lo que me muestras.

En cuanto a que no quieres que no sea en orden creciente, sino en el orden en que salen, según el ejemplo que pusiste, es lo mismo (aparecen en orden creciente). Pero bueno, supongamos que podrían aparecer en otro orden, así que tenemos que almacenar de alguna manera ese orden.

Lo normal es guardarlo usando un array: a medida de que vamos encontrando elementos distintos de ATOM, los vamos guardando en una pila.

Y, por cada elemento, necesitamos guardar: las veces que aparece y la cadena que precede a ese dato.

Entonces haremos eso: un array en el que cada elemento será una referencia a otro array que tendrá 3 elementos: el ATOM leído, cuántas veces aparece y la cadena que le precede.

Lo guardaremos en una nueva estructura, llamada @atoms.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;

## Abrimos el fichero pasado por el usuario
print "Enter PDB file name :";
my $filename = <STDIN>;
chomp $filename;

open FILE, "<$filename" or die "ERROR: $!\n";

## Leemos el fichero de entrada
my %fichero;
my @atoms;

while (my $line = <FILE>) {
    chomp $line;

    if ($line =~ /^ATOM/) {                             # Átomos
        my @atom               = split " ", $line;
        my ($chain, $aa, $naa) = @atom[4,3,5];

        if (@atoms and                                      # Si tenemos algún atom anterior, y
            $atoms[-1][0] eq $naa) {                        # si es el igual que el último leído
            $atoms[-1][1]++;                                # entonces incrementamos su contador
        }
        else {                                              # si es distinto, es que un atom nuevo
            push @atoms, [ $naa, 1, "$chain\t$aa" ];        # creamos una entrada en @atoms
        }
    }
    elsif ($line =~ /^HEADER.+(..)-(...)-(..)/) {       # De la cabecera nos interesa la fecha
        $fichero{HEADER} = "DEPOSIT DATE $1 $2 $3";
    }
    elsif ($line =~ /^TITLE/) {                         # Guardamos todos los títulos en una pila
        push @{$fichero{TITLE}}, $line;
    }
    elsif ($line =~ / 2 RESOLUTION/) {                  # Resolución
        $fichero{RESOLUTION} = 'RESOLUTION ' . substr $line, 11, 25;
    }
}

close FILE;

## Mostrar los resultados
# Títulos
if (@{$fichero{TITLE}}) {
    for my $title (@{$fichero{TITLE}}) {
        print "$title\n";
    }
    print "\n";
}

# Resolución
if ($fichero{RESOLUTION}) {
    print "$fichero{RESOLUTION}\n\n";
}

# Cabecera
if ($fichero{HEADER}) {
    print "$fichero{HEADER}\n\n";
}

# Átomos
for my $atom (@atoms) {
    print "$atom->[2]-$atom->[0]\t$atom->[1]\n";
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
Última edición por explorer el 2009-01-28 20:54 @912, editado 1 vez en total
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

Notapor andrea » 2009-01-28 20:04 @878

Wow... miles de gracias... me quedó absolutamente claro con tus explicaciones, pero una pregunta más: no entendí bien la última línea
print "$atom->[2]-$atom->[0]\t$atom->[1]\n";

¡Gracias de nuevo!
andrea
Perlero nuevo
Perlero nuevo
 
Mensajes: 15
Registrado: 2007-07-27 16:29 @728

Notapor explorer » 2009-01-28 20:48 @908

Si agregas estas dos líneas al final del programa
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use Data::Dumper;
print Dumper \@atoms;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

sale
Código: Seleccionar todo
$VAR1 = [
          [
            '84',
            7,
            'G  VAL'
          ],
          [
            '85',
            7,
            'G  VAL'
          ],
          [
            '86',
            8,
            'G  LEU'
          ],
          [
            '87',
            3,
            'G  GLU'
          ]
        ];
que es el contenido de @atoms. Ves que es un arreglo, y cada elemento de ese arreglo es una referencia a otro arreglo, que tiene 3 elementos cada uno.

Dentro del bucle for my $atom (@atoms) estamos recorriendo todo el arreglo @atoms, y guardando cada elemento (la referencia a cada arreglo pequeño) dentro de $atom.

Como lo que tenemos en $atom es una referencia a un arreglo, para acceder a los elementos del arreglo que referencia (esto se parece cada vez más a un juego de palabras), necesitamos desreferenciarlo con '->'. Así, para obtener el primer elemento del arreglo, será: $atom->[0].

El print() muestra los tres elementos de cada arreglo, añadiendo un '-' por aquí, un tabulador por allá, y un "\n" por acullá.

Quizás queda más claro así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
for my $atom (@atoms) {
    my @atomos = @$atom;
    print "$atomos[2]-$atomos[0]\t$atomos[1]\n";
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

En este caso, como $atom es una referencia a un arreglo, lo desreferenciamos con un '@' delante (y ya tenemos el arreglo en nuestras manos) y se lo metemos a @atomos. Y lo que sigue es fácil.
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


Volver a Básico

¿Quién está conectado?

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

cron