以下の増分編集の概要:
これにより、コンパイルされたコードを使用してポイント座標を計算する際の速度が大幅に向上します ( 計算を除くと 50 倍shifts
) :
shifts = chars /. {"A" -> {0., 0.}, "T" -> {.5, 0.}, "G" -> {.5, .5}, "C" -> {0, .5}};
fun1d = Compile[{{a, _Real, 1}}, FoldList[#/2 + #2 &, .5, a], CompilationTarget -> "C"]
pts = Transpose[fun1d /@ Transpose[shifts]];
コードのボトルネックは、実際にグラフィックをレンダリングすることです。各ポイントをプロットする代わりに、ポイントの密度を視覚化します。
threshold = 1;
With[{size = 300},
Image[1 - UnitStep[BinCounts[pts, 1/size, 1/size] - threshold]]
]
threshold
少なくともポイントがある場合、リージョンは黒く表示されます。size
画像次元です。大きなサイズまたは大きなしきい値を選択することで、「黒い四角の問題」を回避できます。
詳細を含む私の元の回答:
私のかなり古いマシンでは、コードはそれほど遅くはありません。
chars = RandomChoice[{"A", "T", "C", "G"}, 800000];
f[x_, "A"] := x/2;
f[x_, "T"] := x/2 + {1/2, 0};
f[x_, "G"] := x/2 + {1/2, 1/2};
f[x_, "C"] := x/2 + {0, 1/2};
Timing[pts = FoldList[f, {0.5, 0.5}, chars];]
Graphics[{PointSize[Tiny], Point[pts]}]
6.8 秒のタイミングが得られました。これは、ループで何度も実行する必要がない限り使用できます (ユース ケースとマシンにとって十分に高速でない場合は、コメントを追加してください。高速化を試みます) )。
残念ながら、グラフィックのレンダリングにはこれよりもはるかに長い時間がかかります (36 秒)。プラットフォームによっては、アンチエイリアシングを無効にすると少しは役立つかもしれませStyle[Graphics[{PointSize[Tiny], Point[pts]}], Antialiasing -> False]
んが、あまり役に立ちません: (私にとってはそうではありません)。これは、私たちの多くにとって長年の悩みの種です。
グラフィック全体が黒くなっていることについては、マウスを使用してサイズを変更し、大きくすることができます。次に式を評価するときに、出力グラフィックはそのサイズを記憶しています。またはImageSize -> 800
、Graphics
オプションとして使用してください。画面のピクセル密度を考慮すると、私が考えることができる他の唯一の解決策 (グラフィックのサイズ変更を伴わない) は、グレーの色合いを使用してピクセル密度を表し、密度をプロットすることです。
編集:
これは、密度をプロットする方法です (これは、点プロットよりも計算とレンダリングがはるかに高速です!):
With[{resolution = 0.01},
ArrayPlot@BinCounts[pts, resolution, resolution]
]
解像度をいじって、プロットを素敵にします。
私のランダム シーケンスの例では、これは灰色のプロットのみを示します。あなたのゲノムデータについては、おそらくもっと興味深いパターンが得られるでしょう。
編集2:
コンパイルを使用して関数を高速化する簡単な方法を次に示します。
まず、文字をシフト ベクトルに置き換えます (データセットに対して 1 回だけ実行する必要があり、結果を保存できます)。
arr = chars /. {"A" -> {0., 0.}, "T" -> {.5, 0.}, "G" -> {.5, .5}, "C" -> {0, .5}};
次に、関数をコンパイルしましょう。
fun = Compile[{{a, _Real, 2}}, FoldList[#/2 + #2 &, {.5, .5}, a],
CompilationTarget -> "C"]
CompilationTarget
Mathematica のバージョンが 8 より前の場合、または C コンパイラがインストールされていない場合は削除してください。
fun[arr]; // Timing
0.6 秒が得られます。これは、瞬時に 10 倍のスピードアップになります。
編集3:
コンパイルされた関数でいくつかのカーネルコールバックを回避することにより、上記のコンパイルされたバージョンと比較して、さらに最大 5 倍のスピードアップが可能です (CompilePrint
このバージョンを作成するために使用してコンパイル出力を確認しました --- そうでなければ、なぜ高速なのかは明らかではありません)。
fun1d = Compile[{{a, _Real, 1}}, FoldList[#/2 + #2 &, .5, a],
CompilationTarget -> "C"]
arrt = Transpose[arr];
Timing[result = fun1d /@ arrt;]
pts = Transpose[result];
これは、私のマシンでは 0.11 秒で実行されます。最新のマシンでは、40 MB のデータセットでも数秒で終了するはずです。
この時点で の実行時間が の実行時間にfun1d
匹敵するようになるため、転置を別々の入力に分割しましたTranspose
。