2016-08-13 3 views
-1

Ich habe eine DNA-Sequenz. Nennen wir es "ATCG". Ich habe 2 kleine Datenbanken von DNA-Sequenzen in 2 separaten Dateien, die wir "db1.txt" und "db2.txt" nennen. Beide Datenbanken sind wie folgt formatiert:Perl: Zuweisen einer Variablen einen von 3 möglichen Werten

>name of sequence 
EXAMPLESEQUENCEATCGATCG 
>name of another sequence 
ASECONDEXAMPLESEQUENCEATCGATCG 

Ich möchte wissen, ob meine DNA-Sequenz in einer der Datenbanken enthalten ist, und wenn ja, welche. Mein Ergebnis hat dann 3 mögliche Werte: Meine Sequenz befindet sich weder in der Datenbank, noch in db1 oder in db2. Hier ist mein Code:

use warnings; 
use strict; 
my $entry = 'ATCG'; 
my $returnval = "The sequence is from neither database"; 

#if in db1 
    my $name1; 
    my $seq1; 
    open (my $database1, "<", "db1.txt") or die "Can't find db1"; 
    while (<$database1>){ 
     chomp ($name1 = <$database1>); 
     chomp ($seq1 = <$database1>); 
     if (
      index($seq1, $entry) != -1 
      || index($entry, $seq1) != -1 
     ) { 
      $returnval = "The sequence is from db1: ". $name1; 
      last; 
     } 
    } 

#If in db2: 
    my $name2; 
    my $seq2; 
    open (my $database2, "<", "db2.txt") or die "Can't find db2"; 
    while (<$database2>){ 
     chomp ($name2 = <$database2>); 
     chomp ($seq2 = <$database2>); 
     if(
      index($seq2, $entry) != -1 
      || index($entry, $seq2) != -1 
     ) { 
      $returnval = "The sequence is from db2: ". $name2; 
      last; 
     } 

    } 
    print $returnval . "\n"; 

Es gibt ein paar Probleme mit diesem Code (wahrscheinlich mehr als ein paar). Egal was meine Sequenz ist, $ returnval = "Die Sequenz ist von db2:" ohne Namen am Ende. Darüber hinaus scheinen $ name2 und $ seq2 nicht initialisierte Werte zu sein, obwohl der Code identisch mit dem von db1 ist. Wenn ich den gesamten Abschnitt zum Testen für db2 entferne, gibt der Code nur "die Sequenz stammt von db1:" gefolgt von dem entsprechenden Namen für einige Sequenzen, die ich kopiert und aus der Datenbank eingefügt habe, zurück Datenbank "für andere.

Was mache ich falsch? Wie behebe ich die nicht initialisierten Werte und warum funktioniert der Code für db2 nicht?

EDIT: Ich habe vergessen zu erwähnen, dass die Ausgabe, dass die Sequenz in db2 ist, Vorrang vor der Ausgabe hat, dass es in db1 ist, sollte eine Sequenz in beiden sein.

+0

Das sollte nicht einmal kompilieren. '$ name' ist nicht deklariert. – melpomene

+0

Dies ist nicht der eigentliche Code.Ich habe die relevanten Teile herausgenommen und einige Variablen umbenannt, um das Lesen zu erleichtern. –

+1

Sie lesen eine Zeile mit dem 'while (<', zweite Zeile mit '$ nameX = <', dritte Zeile mit '$ seqX = <'. Sie müssen lese zwei Zeilen, nicht drei pro Wiederholung – choroba

Antwort

2

Das Hauptproblem ist in den Bedingungen der While-Schleifen, die eine Linie jede Iteration lesen und verwerfen und verhindern, die $name und $seq Variablen von einem Namen und Reihenfolge jedes Mal, enthält. Wenn Sie diese Bedingung entfernen und die Überprüfung für das Dateiende innerhalb der Schleife vornehmen, sollte das Problem behoben sein. Es ist auch möglich, die beiden Datenbanken zu durchlaufen und dieselbe Logik auf beide anzuwenden, so dass Sie nur eine Schleife benötigen, um den Inhalt jeder Datei zu untersuchen.

use warnings; 
use strict; 
my $entry = 'ATCG'; 
my $returnval = "The sequence is from neither database"; 
my @files = qw(db2 db1); 

FILE: 
for my $file (@files) { 
    open my $fh, '<', "$file.txt" or die "Error opening $file: $!"; 
    while (1) { 
     my $name = <$fh>; 
     my $seq = <$fh>; 
     if (not defined $seq) { 
      warn "Odd number of lines in $file" if defined $name; 
      last; # Reached end of file 
     } 
     chomp($name, $seq); 
     if (
      index($seq, $entry) != -1 
      or index($entry, $seq) != -1 
     ) { 
      $returnval = "The sequence is from $file: $name"; 
      last FILE; # No need to search the others 
     } 
    } 
} 

print "$returnval\n"; 
+0

Es gibt keine Notwendigkeit für die "PAIR" -Label. Ist das nur etwas, was du tust? – Borodin

+0

@Borodin Oh, das ist ein Versehen. Normalerweise beschrifte ich keine Schleifen, es sei denn, es ist notwendig. – Slade

+0

Danke! Habe es funktioniert. –

0

Ich würde den Vergleich in einem Unterprogramm wickeln, vor allem, da Sie die gleiche Sache mehrmals

Diese Lösung implementiert ein Unterprogramm matches, zu tun haben, die den Namen der passenden Reihenfolge in der Datei zurückgibt, oder ein falscher Wert, wenn es nicht gefunden wurde

ich habe die Datensatztrennzeichen $/ zum > Charakter verändert, so dass Sequenzen automatisch geteilt werden, wobei jeder Datensatz aus dem Namen auf den ersten bis ne wline-Zeichen und die Folge danach. Der tr/\n//d Anruf entfernt alle Zeilenumbrüche aus der Sequenz (so wird sie mit mehreren Leitungen Sequenzen handhaben, wie das FAST-Format unterstützt) und ein Vergleich wird für jede Sequenz

der aufrufende Code nur verwendet eine for Schleife nennen das Unterprogramm für die jeweils aus Dateiname. Die Schleife beendet, sobald eine Übereinstimmung gefunden wird, so dass $name und $file Satz auf die Details des Spiels

Die Nachricht erstellt wird und gedruckt je nachdem, ob $name endet wahre

use strict; 
use warnings 'all'; 
use feature 'say'; 

my $entry = 'ATCG'; 

my ($file, $name); 

for $file (qw/ db2 db1 /) { 
    last if $name = matches($entry, "$file.txt"); 
} 

say $name ? 
    "The sequence is from $file: $name" : 
    "The sequence is from neither database"; 


sub matches { 
    my ($seq, $file) = @_; 

    open my $fh, '<', $file or die qq{Unable to open "$file" for input: $!}; 

    local $/ = '>'; 

    while (<$fh>) { 
     chomp; 
     my ($name, $file_seq) = split /\n/, $_, 2; 
     $file_seq =~ tr/\n//d; 

     return $name if index($file_seq, $seq) >= 0 or index($seq, $file_seq) >= 0; 
    } 

    return; 
} 
Verwandte Themen