Zeichnen von DNA-Chromatogramm-Spurendaten

7

Sanger - DNA - Sequenzierung erzeugt eine Chromatogramm Spur , die mit einer Reihe von Programmen sichtbar gemacht werden kann, einschließlich FinchTV oder ChromasLite. Die Rohdaten bestehen aus Koordinaten für jede der vier DNA-Basen (A, C, G und T). Diagramme werden jedoch als geglättete Peaks angezeigt, wie im vorherigen Bild gezeigt. In vielen Programmen kann die x- und y-Achse des Diagramms vergrößert oder verkleinert werden, um die Form des Diagramms zu ändern. Welche mathematische Methode wird verwendet, um solche glatten Kurven aus einer (kleinen) Anzahl von Rohdatenpunkten zu zeichnen?

Beispiel für eine Chromatogrammspur

SabreWolfy
quelle
1
Faltung? Was ist die geringe Anzahl von Rohdatenpunkten? Was sagt dir die Glätte? Ich bin verwirrt, obwohl das sanfte Signal aus dem Sequenzer kam und Sie an dem richtigen Buchstaben interessiert sind, der dem entspricht.
Henry Gomersall
@ HenryGomersall: Ja und Nein :) Was aus dem Sequenzer herauskommt, sind Punkte, die, wenn sie gezeichnet werden, auf dieser schönen geglätteten Linie liegen. Ich möchte die geglättete Linie zeichnen. Der Buchstabe, der dem Peak entspricht, ist ein anderes, aber verwandtes Problem, wie ich es verstehe.
SabreWolfy
1
Oh, Ihre Frage betrifft also die Interpolation für ein hübsches Rendering? Um klar zu sein, geht es hier nicht um die Verarbeitung der Daten an sich ?
Henry Gomersall
@HenryGomersall: Letztendlich wollte ich die Daten etwas verarbeiten, aber ich wollte zunächst herausfinden, wie die Kurven gezeichnet werden.
SabreWolfy

Antworten:

5

Implementierung

Angenommen, Sie haben bereits eine Strichzeichnungsroutine, müssen Sie diese nur durch eine Art Interpolation ergänzen. Die Kurven werden erstellt, indem genügend interpolierte kurze Linien gezeichnet werden, damit das Ergebnis glatt aussieht. Ein guter Ausgangspunkt wäre die Verwendung einer vorhandenen Interpolationsroutine, wie sie hier von Paul Bourke angegeben wurde .

Ich werde dies anhand der von ihm bereitgestellten kubischen Routinen veranschaulichen, da dies einige der einfachsten sind, die immer noch vernünftige Ergebnisse liefern. Hier ist der erste (übersetzt in Python) als Referenz:

def cubic(mu,y0,y1,y2,y3):
    mu2 = mu*mu
    a0 = y3 - y2 - y0 + y1
    a1 = y0 - y1 - a0
    a2 = y2 - y0
    a3 = y1
    return a0*mu*mu2 + a1*mu2 + a2*mu + a3

Jede Routine verfügt über einen Parameter, muder den Bruchteil des Index darstellt, den Sie interpolieren möchten. Abhängig von der Routine sind die anderen Parameter eine Anzahl von Stichproben, die den betreffenden Index umgeben. Im kubischen Fall benötigen Sie vier Proben. Zum Beispiel, wenn Sie Ihre Daten y[n], und Sie wollen den Wert an 10.3, muwäre .3, und man würde passieren in y[9], y[10], y[11], und y[12].

Anstatt dann eine einzelne Linie mit Endpunkten zu zeichnen, sagen wir: (10,y10)(11,y11)Mit den interpolierten Werten (z. B. würden Sie eine Reihe kürzerer Werte zeichnen. ). Offensichtlich müssten diese Punkte auf die und Dimensionen des zu rendernden Bildes skaliert werden.(10,y10)(10.1,cubic(.1,y9,y10,y11,y12))xy

Theorie

Da die Seite / Routine, auf die ich verwiesen habe, keine Quellen zitiert, lohnt es sich zu erklären, woher diese kubischen Routinen stammen (und wie sie funktionieren). Sowohl der oben reproduzierte als auch der sehr ähnliche Catmull-Rom-Spline, den er direkt darunter erwähnt, sind zwei spezielle Fälle für die Verwendung des folgenden kubischen Faltungskerns:

ψ(x)={(α+2)|x|3(α+3)|x|2+1, if 0|x|<1α|x|35α|x|2+8α|x|4α, if 1|x|<20, if 2|x|

Die oben aufgeführte Routine entspricht einem Wert von , und der Catmull-Rom-Spline entspricht . Ich werde nicht zu detailliert darauf eingehen, wie die allgemeine Form des Kernels abgeleitet wird, aber es beinhaltet verschiedene Einschränkungen, wie beispielsweise sicherzustellen, dass eins bei Null und null bei allen anderen ganzen Zahlen ist.α=1α=1/2ψ(x)

So sieht es aus:

Kubischer Faltungskern

Die beiden Auswahlmöglichkeiten für den Wert von sich aus Versuchen, verschiedene Aspekte der sinc-Funktion , dem idealen Rekonstruktionskern, abzugleichen. Wenn Sie stimmt die Ableitung von mit der Ableitung der sinc-Funktion bei überein , und wenn Sie sie gleich machen, erhalten Sie stattdessen die beste niederfrequente Näherung. In jedem Fall hat ein Wert von viel bessere Eigenschaften, daher ist er wahrscheinlich der beste Wert für die Praxis. Eine viel ausführlichere Diskussion finden Sie im folgenden Artikel ab Seite 328:αα=1ψx=1- -1/.2α=- -1/.2

Meijering, Erik. "Eine Chronologie der Interpolation: Von der alten Astronomie zur modernen Signal- und Bildverarbeitung." Verfahren des IEEE. vol. 90, nein. 3, S. 319-42. März 2002.

Einblick

Wenn man sich diesen Kernel nur in Bezug auf die tatsächliche Implementierung des Interpolationscodes ansieht, ist möglicherweise nicht klar, wie die beiden zusammenhängen. Grundsätzlich kann der Interpolationsprozess so betrachtet werden, dass verschobene Kopien des Kernels addiert werden, die durch die Stichproben der Daten wie folgt skaliert werden:

Kernelbasierte Rekonstruktion

Wenn Sie eine Implementierung des Kernels haben, können Sie diese direkt wie folgt für die Interpolation verwenden:

def kernel(x, a=-1.0):
    x = abs(x)
    if x >= 0.0 and x < 1.0:
        return (a + 2.0)*x**3.0 - (a + 3.0)*x**2.0 + 1
    elif x >= 1.0 and x < 2.0:
        return a*x**3.0 - 5.0*a*x**2.0 + 8.0*a*x - 4.0*a
    else:
        return 0.0

def cubic(mu,y0,y1,y2,y3):
    a = -1.0        
    result  = y0 * kernel(mu + 1, a)
    result += y1 * kernel(mu, a)     
    result += y2 * kernel(mu - 1, a)
    result += y3 * kernel(mu - 2, a)
    return result

Es ist jedoch viel weniger rechnerisch effizient, dies auf diese Weise zu tun. Betrachten Sie als Brücke vom direkten Kernel-Ansatz zum optimierten oben, dass mit ein wenig algebraischer Manipulation die erste Implementierung in der folgenden Form erfolgen kann:

def cubic(mu,y0,y1,y2,y3):
    mu2 = mu*mu
    mu3 = mu*mu2
    c0 = -mu3 + 2*mu2 - mu
    c1 =  mu3 - 2*mu2 + 1
    c2 = -mu3 + mu2 + mu
    c3 =  mu3 - mu2    
    return c0*y0 + c1*y1 + c2*y2 + c3*y3

In dieser Formulierung können die c0...c3Werte als die Koeffizienten eines FIR-Filters betrachtet werden, das auf die Abtastwerte angewendet wird. Jetzt ist es viel einfacher zu sehen, wie die Routine vom Kernel abgeleitet wird. Betrachten Sie den Kernel mit wie folgt:α=- -1

ψ(x)={|x|3- -2|x|2+1, wenn 0|x|<1- -|x|3+5|x|2- -8|x|+4, wenn 1|x|<20, wenn 2|x|

Bewerten Sie diesen Kernel nun symbolisch bei verschiedenen verschobenen Offsets, wobei Sie berücksichtigen, dass mu( ) von bis reicht :μ01

ψ(μ+1)=- -(μ+1)3+5(μ+1)2- -8(μ+1)+4=- -μ3+2μ2- -μ(c0)ψ(μ)=μ3- -2μ2+1=μ3- -2μ2+1(c1)ψ(μ- -1)=(1- -μ)3- -2(1- -μ)2+1=- -μ3+μ2+μ(c2)ψ(μ- -2)=- -(2- -μ)3+5(2- -μ)2- -8(2- -μ)+4=μ3- -μ2(c3)

Beachten Sie, dass aufgrund des Absolutwerts für in der Kerneldefinition auf "gespiegelt" wird . Jetzt haben wir die genauen Polynome, die in der "FIR-Version" der Interpolationsroutine verwendet werden. Die Bewertung dieser Polynome kann dann durch Standardtechniken (z. B. Horners Methode ) effizienter gestaltet werden . Ähnliche Dinge können mit anderen Kerneln durchgeführt werden, und es gibt auch andere Möglichkeiten, effiziente Implementierungen zu erstellen (vgl. Homepage für digitales Audio-Resampling ).μ- -1,μ- -21- -μ,2- -μx

Datageist
quelle