Ausrichten mehrerer Sequenzen in einer heterogenen Gruppe

Ich habe eine Liste von ~200 DNA-Sequenzen, die wahrscheinlich 50 verschiedene Genomregionen darstellen, aber sie sind alle durcheinander. Wenn ich zum Beispiel habe seq1, seq2.... seq10, könnte es an und seq1ausgerichtet sein , aber völlig unabhängig von den anderen sein.seq3seq8

Es gibt auch einige Unterschiede in den abgetasteten Längen, sodass das obige Beispiel Folgendes darstellen könnte:

Seq1-------------------------------------------------

Seq3---------------------- seq8-----------------

So dass seq3und seq8nicht aufeinander ausgerichtet sind, sondern beide aufeinander ausgerichtet sindseq1

Was ich also tun möchte, ist, durchzugehen und irgendwie eine Liste von Gruppen von Sequenzen zu erstellen, die sich aneinander ausrichten, sowie die Ausrichtungen. z.B:

Gruppe 1

Seq1-------------------------------------------------

Seq3---------------------- seq8-----------------

Gruppe 2

seq2------------------------------------

. seq6-----------------------------

. seq7--------------------------xxxxxx

Gruppe 3 ... usw

ClustalW oder MUSSLE zu versuchen, alles auszurichten, funktioniert nicht (oder dauert unangemessen viel Zeit), ich vermute, weil es so viele Sequenzen gibt, die überhaupt nicht ausgerichtet sind. Ich habe versucht, eine benutzerdefinierte BLAST-Datenbank zu erstellen und dann jede Sequenz dagegen zu BLASTEN, aber dann erhalte ich mehrere Treffer für dieselbe Ausrichtung (mit dem Beispiel der Gruppe 2 oben, , , , , seq2:seq6und seq2:seq7alle seq6:seq2werden seq6:seq7als seq7:seq26 seq7:seq6eindeutige Treffer zurückgegeben, wenn sie es sein sollten zusammen gruppiert.

Meine aktuellen Programmierkenntnisse sind ziemlich einfach, aber ich bin bereit, Dokumente zu lesen und Dinge herauszufinden, ich möchte das Rad einfach nicht neu erfinden.

Edit2: Wirklich, die Gruppierung ist der wichtige Teil - sobald ich die Gruppen habe, kann ich die Ausrichtung mit wenig Aufwand separat vornehmen. Ich möchte nur Gruppen haben, in denen sich jede Sequenz in einer einzelnen Gruppe befindet.

Antworten (2)

Sie können dies versuchen:

  • BLAST jede Sequenz zu jeder anderen Sequenz (paarweise).
  • Jede Ausrichtung (mit einem definierten Cutoff) bezeichnet eine Verbindung.
  • Ordnen Sie alle Verbindungen zu.
  • Wenn eine Sequenz direkt oder indirekt mit einer anderen verbunden ist, fällt sie in eine Gruppe. Setzen Sie alle Sequenzen, die seq1ausgerichtet sind, in Gruppe-1 , und gehen Sie dann zu den Ausrichtungen dieser Sequenzen; fügen Sie alle Sequenzen, an denen diese ausgerichtet sind, erneut in Group-1 ein ; Bevölkern Sie die Gruppe also weiterhin so.

Methodik:

  • Installieren Sie eigenständiges Blast (wenn Sie nicht viele Sequenzen haben, können Sie BLAST auch online ausführen)
  • Erstellen Sie eine Explosionsdatenbank aus Ihren Sequenzen mitmakeblastdb
  • Gleichen Sie diese Sequenzen mit der Datenbank ab. Wenn Sie Online-BLAST verwenden, verwenden Sie BL2seq (zwei Sequenzen ausrichten). Es ist viel besser und bequemer, eigenständig zu verwenden. Sie können auch angeben, ob Sie Plus-Plus- oder Plus-Minus-Ausrichtungen oder beide Ausrichtungen wünschen. In einigen Fällen möchten Sie möglicherweise nur eines der beiden.
  • Im eigenständigen BLAST können Sie das Ausgabeformat angeben (welche Felder enthalten sein sollen usw. Das von Ihnen gewählte Format hängt nur von Ihren Anforderungen ab).

Ein tabellarisches Ausgabeformat sieht etwa so aus:

# BLASTN 2.2.27+
# Query: TCONS_00036712 gene=XLOC_017996
# Database: ../nt_db/nt
# Fields: query id, subject id, % identity, alignment length, mismatches, gap opens, q. start, q. end, s. start, s. end, evalue, bit score
# 1014 hits found
TCONS_00036712  gi|191174875|emb|CU655970.6|    95.54   202 9   0   423 624 16680   16479   8e-85    324
TCONS_00036712  gi|51491599|gb|AC144709.2|  95.02   201 10  0   424 624 28443   28243   1e-82    316

Ignorieren Sie die kommentierten ( #) Zeilen; das erste Feld ist die Abfrage-ID, das zweite die Betreff-ID und es gibt eine Ausrichtung zwischen den beiden; die anderen Felder geben Auskunft über die Ausrichtung (Sie können diese Felder auswählen).

Zum Parsen verwende ich eine schnelle und einfache Skriptsprache namens awk, die in allen UNIX-basierten Systemen enthalten ist. Es ist auch für Windows im GNUWin32-Paket verfügbar.

Was Sie tun müssen, ist die ersten beiden Felder zu überprüfen und die Gruppe zu aktualisieren.

# MakeGroups.awk

BEGIN{FS="\t"} # Feldtrenner als Tab deklarieren

!($1 in grp){ # Prüfe, ob seq eine übergeordnete Gruppe ist. Wenn nicht...
    k=1
    für(ich in grp){
        if($1 in grp[i]){ # Prüfe, ob seq Teil einer anderen Gruppe ist
            parentgrp[$1]=i
            if(!($2 in grp[i])) # Prüfe, ob das zweite Feld, dh Betreff, bereits in der Elterngruppe vorhanden ist
                grp[i][$2] # Wenn nicht, weisen Sie das zweite Feld der übergeordneten Gruppe zu
            k=0
            break # Hör auf, weiter zu suchen
        }
    }
    if(k==1) # Es gibt keine übergeordnete Gruppe mit diesem Label und die seq ist kein Teil einer anderen Gruppe
        grp[$1][$1] # Erstellen Sie eine Gruppe mit der Abfrage-ID als Bezeichnung und fügen Sie diese Abfrage dieser Gruppe hinzu.
}  

$1 in Grp{
    if(!($2 in grp[$1]))
        grp[$1][$2] # Wenn das zweite Feld kein Teil der Gruppe mit dem ersten Feld als Label ist, dann weisen Sie es diesem zu
}

ENDE{
    für(ich in grp){
        x++
        print "Gruppe-"x"\n----------"
        for(j in grp[i])
            drucke j
    }
    drucke "\n"
}

Führen Sie dieses Skript wie folgt im Terminal aus:
gawk -f MakeGroups.awk blastalignmentfile.txt

Hinweis: Dieses Skript enthält mehrdimensionale Arrays. Es funktioniert nicht mit allen Versionen von awk. Verwenden Siegawk version >4.0 .

Wie swarnbes in ihrer Antwort erwähnt, gibt es schnellere Algorithmen, die diese Art von Dingen erledigen und für die Sequenzzusammenstellung verwendet werden. Viele von ihnen erstellen einen Graphen (Netzwerke, die als deBruijn-Graphen bezeichnet werden), in denen jede Verbindung eine Ausrichtung ist, und berechnen einen Eulerschen Pfad. Siehe diese Rezension von Pavel Pevzner für Details. Überlappende Sequenzen bilden Contigs und Sie können leicht zurückverfolgen, welche Sequenz von welchem ​​Contig stammt (was Sie als Gruppe bezeichnen können). Jeder Contig/jede Gruppe ist ein disjunkter deBruijn-Untergraph.

Ja, aber wenn Sie mich auch nur in die richtige Richtung weisen könnten, wäre das großartig.
@kevbonham Dieses Skript sollte funktionieren. Wenn Sie eine andere Programmiersprache mögen, können Sie diese Logik darin implementieren.
Wow, vielen Dank! Das scheint so zu funktionieren ... Ich könnte versuchen, in Python neu zu schreiben (da ich damit am vertrautesten bin), aber die Logik ist leicht zu befolgen. Ich nehme an, ich würde eine weitere Schleife hinzufügen, um Übereinstimmungen zu ignorieren < eine bestimmte %-Übereinstimmung, oder würden Sie diese Parameter in den anfänglichen BLAST-Parametern angeben?
@kevbonham Sie können diese Bedingung hinzufügen und prüfen, ob sich das zweite Feld in einer Gruppe befindet oder nicht, ohne dass eine weitere Schleife hinzugefügt werden muss. Im Grunde sind all diese Kriterien hinsichtlich des Verhältnisses zwischen erstem und zweitem Feld streng. Die Sache mit awk ist, dass es Stream liest (nicht die gesamte Datei in den RAM lädt) und die Feldtrennung eine einfache Aufgabe ist. Gut für die Textanalyse.
Macht Sinn. Ist das Stream-Lesen gleichbedeutend mit etwas wie readline()explizit in Python deklariertem?
@kevbonham readline()liest die gesamte Datei Zeile für Zeile und speichert sie als Liste. Beim Stream-Lesen wird eine Zeile gelesen und der Code darauf implementiert, bevor mit der nächsten Zeile fortgefahren wird. Verwenden Sie zum Implementieren des Stream-Lesens in Python for line in file:. Siehe hier . Awk liest standardmäßig Streams. Awk hat auch eine gute Regex-Basis; In Python müssen Sie import re. Allerdings ist Awk nicht so vielseitig wie Python, aber gut für bestimmte Aufgaben.
@kevbonham in awk können Sie angeben, was das Datensatztrennzeichen ist (RS, was standardmäßig ein Zeilenumbruch ist). ">.*"Sie können stattdessen als RS für eine Fasta-Datei festlegen und jede Nukleotid-/Proteinsequenz wird in einem Stream gelesen.
@kevbonham Ein weiterer Punkt: Das Äquivalent zu assoziativen Arrays von awk (Hashtables) in Python ist ein Wörterbuch. Wörterbücher sind manchmal sehr praktisch und arbeiten viel schneller als Listen.
Ich habe es endlich geschafft, dies in Python zum Laufen zu bringen, indem ich Ihr Skript als Vorlage verwendet habe (zumindest das, was ich von der dahinter stehenden Logik verstanden habe). Es ist wahrscheinlich viel aufgeblähter als es sein muss, aber es war eine gute Lernübung. Ist es angebracht, meinen Code als Antwort auf diese Frage als Referenz zu posten? Ich bin mir immer noch nicht ganz sicher, was die Stackexchange-Etikette angeht.
@kevbonham Ja, Sie können es tun, aber hier sollte es nicht darum gehen, Codes im Allgemeinen zu schreiben, und dies ist nicht das richtige Forum, um sich mit Programmierdetails zu befassen. Code, der einen Algorithmus erklärt, ist in Ordnung. Pseudocode ist besser. Codewriting fällt unter die Domäne von StackOverflow.

Brauchen Sie BLAST wirklich? Das heißt, sind die Sequenzen so unterschiedlich, dass Sie einen Algorithmus benötigen, der nach großen Unterschieden zwischen ihnen sucht?

Vielleicht könnten Sie so etwas wie Phrap verwenden, das Contigs für Sie zusammenstellen sollte, wenn die Sequenzen, die zusammengehören sollen, sehr nahezu identisch sind.

Nun, nicht genau. Wo sich die Sequenzen überlappen, überlappen sie sich mit > 99 % Identität, aber es könnte flankierende Sequenzen geben, die sich nicht überlappen. Ich habe die Frage ein wenig geändert, um sie zu verdeutlichen (hoffe ich).
Ich bin mir nicht sicher, ob Phrap selbst funktionieren würde, weil es für die Sequenzmontage gebaut wurde, aber das verwandte cross_match oder SWAT könnte funktionieren ... werde sie ein bisschen genauer untersuchen