Anzeige:
Ergebnis 1 bis 13 von 13

Thema: Perl - Zeichenkette auftrennen und übersetzen

  1. #1
    Registrierter Benutzer
    Registriert seit
    17.01.2007
    Beiträge
    13

    Perl - Zeichenkette auftrennen und übersetzen

    Guten Abend zusammen,
    ich bin Perl-Anfänger und mit meinem Latein am Ende.

    Folgende Problemstellung: Ich habe eine Aneinanderreihung von Zeichenketten "ATGTGACTGGGTAAACCA" usw. in einem String vor mir liegen. Diese Zeichenkette soll nun nach jedem dritten Zeichen getrennt werden, wobei jede dreier Gruppe ein Element eines Arrays darstellen soll, so meine Überlegung.

    Ergebnis auf dem Bildschirm sollte so aussehen: "ATG TGA CTG GGT AAA CCA" usw. Jede Dreier Gruppe (Triplet), sollte nun anschließend übersetzt werden, mittels einem zu Beginn angelegten Hashes:

    Code:
    %hash = (
    "atg" => "F  ",
    "cca" => "M ",
    "tga" => "F  ",
    "ctg" => "L  ",
    "aaa" => "S  ",
    "ggt" => "L  ",
    );
    Die Werte sowie die Schlüssel habe ich in Arrays gespeichert und anschließend die Hashlänge bestimmt.
    Code:
    @triplets = keys %hash;
    @buchstabe = values %hash;
    
    $hashlaenge = scalar @buchstabe;
    Dadurch war es mir möglich die Zeichenfolge zu übersetzen, aber nur ungeordnet.
    Code:
    for ($i = 0; $i <= $hashlaenge; $i++) {
    
    $zeichenfolge =~ s/$triplets[$i]/$buchstabe[$i]/ig;
    }
    Mein Problem: Ich weiß nicht wie ich dreier Gruppen (Triplets) bilde (Vorrausetzung für eine geordnete Übersetzung) und die die dann nacheinander zu übersetzen. Folgende Schritte sollen ausgeführt werden:

    "ATGTGACTGGGTAAACCA" => "ATG TGA CTG GGT AAA CCA" => "F F L L S M"


    Weiß jmd. Rat? Hoffe ich hab mich, als Anfänger, verständlich genug ausgedrückt

    Edit: Ich kenne die Funktion "split", nur wie ich da nach jedem dritten Zeichen trenne?
    Geändert von SuiRIS (22-02-2007 um 21:18 Uhr)

  2. #2
    Registrierter Benutzer
    Registriert seit
    28.10.2006
    Beiträge
    34
    Hier ein ungetesteter Bauchschuss und darüber hinaus nicht sehr elegant.

    Code:
    my @tripplets;
    my @chars = split(//, $DEINSTRING);
    while (my $temp = @chars[0,1,2]){push (@tripplets,$temp);for($i=0;$i++,$i<3){shift (@chars);};}
    Grüße.
    craano.

  3. #3
    Registrierter Benutzer Avatar von Molaf
    Registriert seit
    15.11.2004
    Beiträge
    127
    Oder auch:

    Code:
    my $ein="ATGTGACTGGGTAAACCA";
    
    my @triplets;
    
    while($ein)
    	{push(@triplets,  substr($ein,0,3)  );
    	$ein= substr($ein,3);
    	}

  4. #4
    Registrierter Benutzer
    Registriert seit
    17.01.2007
    Beiträge
    13
    Morgen,
    vielen Dank ihr beiden
    @ craano: dein Vorschlag klappt nicht -> syntax-error
    Ist aber halb so schlimm, denn Molafs Idee funktioniert, fast einwandfrei.

    Das übersetzen der Triplets in einen Einbuchstabencode hab ich heut morgen auch hinbekommen. Seht selbst: *stolzbin*

    Code:
    my @seq_trip;
    
    # Auftrennen in Triplets
    while($sequenz_string)
    	{push(@seq_trip,  substr($sequenz_string,0,3)  );
    	$sequenz_string= substr($sequenz_string,3);
    	}
    
    $hashlaenge = scalar @as; # Anzahl der Elemente im Hash
    
    
    # Übersetzen der Triplets in Einbuchstabencode.
    @nukleotide = @seq_trip;
    
    for ($i = 0; $i <= $hashlaenge; $i++) {
    foreach $tri (@nukleotide){$tri =~ s/$triplets[$i]/$as[$i]/ig; # $triplets und $as sind jeweils Werte und Schlüssel des Hashs
    }}
    Jetzt hab ich noch ein Problem. Die Zeichenketten (Sequenzen) werden aus einer Text-Datei eingelesen, mit folgendem Format:
    Code:
    CTAACAAATTTGACTACAGGTATTTCTGCTGATAACGTAACACTTTTGGGTATATTTAAAACCATAAATA
    TTGGTATGAAAGGGGAATTTGATACCGACACGTATGCTCTATTTTCTACGTGGGTACAAAATATAGCTAC
    TACTCCTAAATCATATATGGGAAGGTATCTAACAGAAGCGGAAGAGGTCACGAAAGCGTTTGCTGATGCT
    CAAACACGTGTATTGACACAAGCAGGCAATGTAACTAGTAATTTAACTACTGGAATAACTGTTTCAATTA
    TTGCAATTGTAGTAATAGTTTTGGTTATGCTAATTATTTATTTAATTTTACGTTATCGACGAAAGAAAAA
    AATGAAGAAAAAACTCCAATATATAAAATTATTAAAGGAATAA
    Nur eine Zeile hat in diesem Fall 70 Zeichen und lässt sich somit nicht durch drei teilen. Wie stell ich es an, dass perl jede Zeile immer z.B. auf 72 Zeichen auffüllt, sodass sie durch drei teilbar wäre? Es sollen jeweils die ersten Buchstaben der nächsten Zeile ausgeschnitten und ans Ende der momentan Zeile eingefügt werden.

    substr, push, shift Funktion irgendwie in Schleife packen.. Nur wie?

    Wäre über jede Antwort dankbar

  5. #5
    Registrierter Benutzer
    Registriert seit
    28.10.2006
    Beiträge
    34
    Entferne doch mit chomp die eventuell vorhandenen Zeilenumbrüche und lege die gesamte Datei in einem String ab.

    Code:
    my $code;
    my @triplets
    while <IN>{chomp($_); $code = $code . $_;
    #Hier weiter mit dem code von Molaf
    #$code aufspalten und die einzelnen Trippletts in @triplets ablegen}
    Jetzt muss nur die Gesamtzahl Deiner Buchstaben durch 3 teilbar sein, aber das sollte ja der Fall sein.

    @ craano: dein Vorschlag klappt nicht -> syntax-error
    Wie gesagt, war nur eine spontane Idee, die ich nicht getestet habe. Werde ich mir aber bei Gelegenheit noch einmal genauer anschauen. Wo ist denn nur dieser verdammte syntax error?

    Was versuchst Du eigentlich gerade genau zu programmieren?
    Glaubst Du wirklich, dass das eine wirksame Verschlüssellung ist oder ist das nur eine kleine Spielerei von Dir?

    Grüße.
    craano.
    Geändert von craano (23-02-2007 um 12:13 Uhr)

  6. #6
    Registrierter Benutzer
    Registriert seit
    17.01.2007
    Beiträge
    13
    DANKE craano!

    Du hast mir die Erleuchtung gebracht. Man sollte nicht immer so kompliziert denken. Ich hab die Zeilenbrüche nun so entfernt:
    Code:
    $string =~ s/\n//g;
    Klappt 1A

    Was das werden soll?
    Naja.. ist eine Hausaufgabe, im Fach Bioinformatik, Klasse 13. Dabei soll eine eine mRNA translatiert, d.h. in eine Aminosäure-Sequenz umgewandelt werden.

    Grob gesagt: einen Genetischen Code in einem Protein-Code umwandeln.

    Ist jetzt etwas höhere Fachsprache, deswegen wollte ich das zu Beginn nicht mit reinbringen. Hätte wahrscheinlich eher zur Verwirrung beigetragen, als das es geholfen hätte.

  7. #7
    Registrierter Benutzer
    Registriert seit
    28.10.2006
    Beiträge
    34
    There is always more than one way...

  8. #8
    Registrierter Benutzer
    Registriert seit
    19.08.2004
    Beiträge
    404
    Zitat Zitat von SuiRIS Beitrag anzeigen
    Das übersetzen der Triplets in einen Einbuchstabencode hab ich heut morgen auch hinbekommen. Seht selbst: *stolzbin*

    Code:
    $hashlaenge = scalar @as; # Anzahl der Elemente im Hash
    
    # Übersetzen der Triplets in Einbuchstabencode.
    @nukleotide = @seq_trip;
    
    for ($i = 0; $i <= $hashlaenge; $i++) {
    foreach $tri (@nukleotide){$tri =~ s/$triplets[$i]/$as[$i]/ig; # $triplets und $as sind jeweils Werte und Schlüssel des Hashs
    }}
    Hi, ich habe zwar von Bioinformatik keine Ahnung, aber Deine Lösung bzgl. der Übersetzung fuinktioniert immer nur zufällig

    Zunächst mal musst Du wissen, dass ein Hash immer unsortiert ist.
    Legt man ein Hash also folgendermaßen an:
    Code:
    my %Hash = (
     'key1' => 'value1',
     'key2' => 'value2',
     'key3' => 'value3'
    );
    so kann es durchaus sein, dass bei einer Ausgabe die Reihenfolge abweicht:

    Code:
    foreach(keys(%Hash))
    {
      print $_;
    }
    
    1. Ausgabe:
    key2
    key1
    key3
    
    1. Ausgabe:
    key1
    key3
    key2
    Der erste grobe Fehler in Deinem Code ist dieser:

    Code:
    @triplets = keys %hash;
    @buchstabe = values %hash;
    Damit vernichtest Du unter Umständen die Zuordnung von keys und values, da beim Aufruf der Funktion keys() die Reihenfolge der Schlüssel-Wert-Paare von der beim Aufruf der Funktion values() abweichen kann. Das willst Du sicher nicht.

    Der zweite Fehler ist, dass Du Dich beim Übersetzen der Sequenz sicherlich an die Reihenfolge der Triplets in der Sequenz halten musst - nicht an die Reihenfolge, die das Hash vorgibt (da die ja sowieso zufällig ist).

    Ich würde daher die Sequenzen erstmal einlesen und alle \n entfernen, so wie Du es ja bereits gemacht hast.
    Anschließend würde ich den String in die Triplets auftrennen:

    Code:
    my @seq_trip = ($sequenz_string =~ m/.{3}/g);
    Ab jetzt hast Du in @seq_trip alle Triplets gespeichert - und zwar mit fester Reihenfolge.
    Nun fehlt nur noch die Übersetzung. Dabei richtest Du Dich natrülcih nach der Reihenfolge in @seq_trip - also so:

    Code:
    my @Nukleotide = ();
    foreach(@seq_trip)
    {
      push(@Nukleotide, $Hash{$_});
    }
    Das Array Nukleotide enthält ab jetzt die translatierte Sequenz.

    Zusammengefasst:

    Code:
    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    my $Sequenzen = 'dateiname.txt';
    my $sequenz_string='';
    my %Hash = (
      "ATG" => "F",
      "CCA" => "M",
      "TGA" => "F",
      "CTG" => "L",
      "AAA" => "S",
      "GGT" => "L"
    );
    
    
    open(my $fh,"<$Sequenzen");
    while(<$fh>)
    {
      chomp;
      $sequenz_string .= $_;
    }
    close($fh);
    
    my @seq_trip = ($sequenz_string =~ m/.{3}/g);
    my @Nukleotide = ();
    
    foreach(@seq_trip)
    {
      push(@Nukleotide, $Hash{$_});
    }
    print join(' ', @Nukleotide);
    hth, Michael

  9. #9
    Registrierter Benutzer
    Registriert seit
    05.02.2006
    Beiträge
    116
    Wie auf Perl-Community.de schon gesagt, gibt es auch Module, die einem das Einlesen von FASTA-Dateien erleichtern...

    Auch eine allgemeine Lösung wurde dort gepostet, aber der OP hat sich dort leider nicht mehr gemeldet...

  10. #10
    Registrierter Benutzer
    Registriert seit
    17.01.2007
    Beiträge
    13
    Danke ihr beiden.
    Werd mir das bei Gelegenheit mal zur Gemüte führen.
    Momentan bin ich leider kaum mit freier Zeit gesegnet...

  11. #11
    Registrierter Benutzer
    Registriert seit
    19.08.2004
    Beiträge
    404
    klar - wir wollen dir den code ja auch nicht aufzwängen. Nur bevor mutierte Säbelzahnkakerlaken aus den Gullideckeln kriechen, solltest Du den code vielleicht korrigieren
    Ich weiß ja nicht, was ihr Bioinformatiker so macht

  12. #12
    Registrierter Benutzer
    Registriert seit
    17.01.2007
    Beiträge
    13
    Hehe,
    nene, ich baue deinen Code ja nicht aus Sturheit, sondern momentan nur aus Zeitmangel nicht ein.

    Code:
    my @seq_trip = ($sequenz_string =~ m/.{3}/g);
    Das ist eingebaut und funktioniert prächtig.

    Dieser Abschnitt hapert bei mir jedoch noch:
    Code:
    my @Nukleotide = ();
    foreach(@seq_trip)
    {
      push(@Nukleotide, $Hash{$_});
    }
    Am Ende kommt einfach nichts...
    Nur Zeit zum Fehler suchen hab ich die nächsten zwei Tage nicht. Deswegen bleibt es momentan noch beim Alten.
    Geändert von SuiRIS (20-03-2007 um 17:59 Uhr)

  13. #13
    Registrierter Benutzer
    Registriert seit
    17.01.2007
    Beiträge
    13
    Hallo ich bins nochmal :-)

    @michael.sprick

    Könntest du diesen Abschnitt etwas genauer erklären?
    Ich versteh das ganze momentan so:
    es wird ein neuer leerer Array gebildet. Danach folgt die foreach-Schleife. Es wird zu Beginn auf das erste Element (Triplet) des Arrays @seq_trip zugegriffen. Mit dem zwischengespeicherte Triplet (Schlüssel) wird nun auf den dazugehörige Aminosäure (Wert) zugegriffen und an den Array @Nukleotide angehängt. Und das spiel beginnt von vorne, nun jedoch mit dem nächsten Element des Arrays @seq.

    Code:
    my @Nukleotide = ();
    foreach(@seq_trip)
    {
      push(@Nukleotide, $Hash{$_});
    }
    Ein
    Code:
    print "@Nukleotide\n";
    ergibt bei aktivierten warnings nur dies hier:
    Code:
    Use of uninitialized value in join or string at translate.pl line ....
    Keine einzige Sequenz wird ausgegeben..


    Edit: Was mich noch mehr verwirrt:
    Code:
    $anzahl_nukleotide = scalar @Nukleotide;
    print "$anzahl_nukleotide\n";
    Dieser Codeabschnitt funktioniert einwandfrei. Es wird die Anzahl der Elemente des Arrays ausgegeben! *verzweifel*


    Woran mag das liegen?

    PS: "use strict;" wurde nicht verwendet

    Edit2: Problem gefunden!! Liegt an der Groß/Kleinschreibung. Jippii!!
    Geändert von SuiRIS (21-03-2007 um 21:20 Uhr)

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •