サンガーDNA シーケンスはクロマトグラムトレースを生成し、FinchTVやChromasLiteなどの多くのプログラムで視覚化できます。生データは、4つのDNA塩基(A、C、G、T)のそれぞれの座標で構成されます。ただし、プロットは、前の図に示すように、平滑化されたピークとして表示されます。多くのプログラムでは、プロットのx軸とy軸を拡大または縮小して、プロットの形状を変更できます。(少数の)生データポイントからこれらのような滑らかな曲線をプロットするために使用される数学的な方法は何ですか?
サンガーDNA シーケンスはクロマトグラムトレースを生成し、FinchTVやChromasLiteなどの多くのプログラムで視覚化できます。生データは、4つのDNA塩基(A、C、G、T)のそれぞれの座標で構成されます。ただし、プロットは、前の図に示すように、平滑化されたピークとして表示されます。多くのプログラムでは、プロットのx軸とy軸を拡大または縮小して、プロットの形状を変更できます。(少数の)生データポイントからこれらのような滑らかな曲線をプロットするために使用される数学的な方法は何ですか?
回答:
実装
あなたがすでに線画ルーチンを持っていると仮定すると、何らかの補間でそれを補足する必要があるだけです。曲線は、結果が滑らかに見えるように十分な補間された短い線を描くことによって作成されます。ここからPaul Bourkeが提供するものなど、既存の補間ルーチンを使用することをお勧めします。
彼が提供する3次ルーチンを使用してこれを説明します。これは、合理的な結果が得られる最も単純なルーチンの一部であるためです。参考のために、最初のコードを(pythonに翻訳して)示します。
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
各ルーチンには、mu
補間するインデックスの小数部分を表すパラメーターがあります。ルーチンに応じて、他のパラメーターは、問題のインデックスを囲むいくつかのサンプルになります。キュービックの場合、4つのサンプルが必要になります。たとえば、あなたのデータがあれば、y[n]
とあなたはでの値をしたい10.3
、mu
となり.3
、あなたは渡すだろうy[9]
、y[10]
、y[11]
、とy[12]
。
次に、たとえば、端点のある単一の線を描く代わりに、補間された値(たとえば)明らかに、これらのポイントは、レンダリングされるイメージのと次元に合わせてスケーリングする必要があります。
理論
さて、私が参照したページ/ルーチンはソースを引用していないので、それらの3次ルーチンがどこから来たのか(そしてそれらがどのように機能するのか)を説明する価値があります。上記で再現したものと、そのすぐ下で彼が言及している非常に類似したCatmull-Romスプラインは、次の3次畳み込みカーネルを使用する2つの特定のケースです。
上記のルーチンは値に対応し、Catmull-Romスプラインは対応します。カーネルの一般的な形式の導出方法についてはあまり詳しく説明しませんが、がゼロで1、他のすべての整数でゼロであることを確認するなど、さまざまな制約が関係しています。
これは次のようになります。
の値の2つの選択肢は、理想的な再構築カーネルであるsinc関数のさまざまな側面を一致させる試みから来ています。を設定すると、の導関数がでのsinc関数の導関数に一致し、に等しくすると、代わりに最適な低周波近似が提供されます。すべてのアカウントで、値は全体的にはるかに優れたプロパティを持っているので、実際に使用するのにおそらく最良の値です。はるかに広範な議論は、328ページから始まる次の論文にあります。
メイリング、エリック。 「補間の年代学:古代の天文学から現代の信号および画像処理まで」 IEEEの議事録。巻。90、いいえ。3、319-42ページ。2002年3月。
洞察力
さて、補間コードの実際の実装に関連してそのカーネルを見るだけで、2つがどのように関連しているかは明確ではないかもしれません。基本的に、補間プロセスは、次のように、データのサンプルによってスケーリングされるカーネルのシフトされたコピーを一緒に追加すると考えることができます。
実際、カーネルの実装がある場合、次のように、それを直接使用して補間を行うことができます。
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
ただし、この方法で行うと、計算効率が大幅に低下します。ダイレクトカーネルアプローチから上記のより合理化されたアプローチへの架け橋として、少しの代数操作を使用して、最初の実装を次の形式にすることができます。
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
この定式化では、c0...c3
値はサンプル値に適用されるFIRフィルターの係数と考えることができます。これで、ルーチンをカーネルから派生させる方法がはるかに簡単になりました。次のように、カーネルについて考えます。
今すぐことを念頭に置いて、様々なシフトオフセットで象徴的にそのカーネルを評価するmu
(の範囲)に:0
1
カーネル定義のの絶対値のため、はそれぞれ「反転」することに注意してください。これで、補間ルーチンの「FIRバージョン」で使用される正確な多項式が得られました。これらの多項式の評価は、標準的な手法(Hornerの方法など)を使用してより効率的に行うことができます。他のカーネルでも同様のことができ、効率的な実装を構築する他の方法もあります(デジタルオーディオリサンプリングホームページを参照)。