Сводная информация о приращениях, приведенных ниже:
Это значительно ускорит вычисление координат точек с использованием скомпилированного кода (в 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:
Вот простой способ ускорить функцию с помощью компиляции:
Сначала замените символы векторами сдвига (это нужно сделать только один раз для набора данных, затем вы можете сохранить результат):
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 МБ.
Я разделил транспонирование на отдельные входы, потому что в этот момент время выполнения fun1d
начинает сравниваться свремя работы Transpose
.