Создание последовательности мотивов
#
MotifSequenceGenerator
— Module
MotifSequenceGenerator
Этот модуль генерирует случайные последовательности мотивов с тем условием, что последовательность имеет некоторую общую длину ℓ такую, что q - δq ≤ ℓ ≤ q + δq
. Основные функциональные возможности обеспечиваются функцией random_sequence
.
#
MotifSequenceGenerator.random_sequence
— Function
random_sequence(motifs::Vector{M}, q, limits, translate, δq = 0; kwargs...)
Создает случайную последовательность мотивов типа M
, с ограничением, что последовательность имеет «длину» ℓ
точно в пределах q - δq ≤ ℓ ≤ q + δq
. Возвращает саму последовательность, а также последовательность индексов мотивов motifs
, использованных для ее создания. В качестве аргумента ключевого слова может быть задан вектор вероятностей weights
, который определяет вероятность выборки для каждого элемента motifs
для созданной исходной последовательности.
Под «длиной» здесь понимается абстрактная длина, определяемая структурой M
на основе функций limits
и translate
. Она не связана с количеством элементов.
M
может быть любой структурой, к которой применимы две функции:
-
limits(motif)
: некоторая функция, которая для заданного мотиваmotif
возвращает(start, fine)
мотива в тех же единицах, что иq
. Эта функция определяет величину длины, которая просто равнаfine - start
. -
translate(motif, t)
: некоторая функция, которая для заданного мотиваmotif
возвращает новый мотив, преобразованный на величинуt
(отрицательную или положительную) в тех же единицах, что иq
.
Другие именованные аргументы
Полное описание алгоритма см. в исходном коде (используйте @which
).
-
tries = 5
: допустимое количество исходных случайных последовательностей. -
taulcut = 2
: максимальное количество исключений элемента из первоначального предположения. -
summands = 3
: максимальное количество мотивов, которые можно объединить для получения полной последовательности.
Простой пример
В этом примере показано, как модуль MotifSequenceGenerator
работает простой структурой struct
. Более приближенный к реальности и гораздо более сложный пример см. в разделе Пример с использованием музыкальных нот.
Предположим, что мы хотим создать случайную последовательность «возгласов», которые описываются структурой struct
.
struct Shout
shout::String
start::Int
end
Давайте сначала создадим вектор возгласов, который будет использоваться в качестве набора возможных мотивов для создания случайной последовательности:
using Random
shouts = [Shout(uppercase(randstring(rand(3:5))), rand(1:100)) for k in 1:5]
5-element Vector{Main.Shout}:
Main.Shout("0APP", 85)
Main.Shout("I4X", 100)
Main.Shout("FVZSV", 82)
Main.Shout("F6N", 77)
Main.Shout("PFOFW", 25)
Обратите внимание, что в данный момент значения поля .start
объекта Shout
не важны. MotifSequenceGenerator
преобразует все мотивы так, чтобы они начинались в точке 0.
Теперь, чтобы создать случайную последовательность, нужно определить две сущности:
shoutlimits(s::Shout) = (s.start, s.start + length(s.shout) + 1);
shouttranslate(s::Shout, n) = Shout(s.shout, s.start + n);
shouttranslate (generic function with 1 method)
Это означает, что мы принимаем тот факт, что временная длина Shout
равна length(s.shout) + 1
.
Теперь мы можем создавать случайные последовательности возгласов общей длиной ровно q
:
using MotifSequenceGenerator
q = 30
sequence, idxs = random_sequence(shouts, q, shoutlimits, shouttranslate)
sequence
6-element Vector{Main.Shout}:
Main.Shout("PFOFW", 0)
Main.Shout("F6N", 6)
Main.Shout("F6N", 10)
Main.Shout("PFOFW", 14)
Main.Shout("I4X", 20)
Main.Shout("FVZSV", 24)
sequence, idxs = random_sequence(shouts, q, shoutlimits, shouttranslate)
sequence
6-element Vector{Main.Shout}:
Main.Shout("PFOFW", 0)
Main.Shout("PFOFW", 6)
Main.Shout("0APP", 12)
Main.Shout("I4X", 17)
Main.Shout("I4X", 21)
Main.Shout("0APP", 25)
Обратите внимание, что на основе указанного выше набора невозможно создать последовательность длиной, например, 7
. Вызов random_sequence(shouts, 7, shoutlimits, shouttranslate)
приведет к ошибке.
Длины с плавающей запятой
Длины мотивов не обязательно должны быть целыми числами. При использовании мотивов с длиной с плавающей запятой рекомендуется указывать ненулевое значение δq
для random_sequence
. В следующем примере показано, как можно изменить структуру Shout
с использованием длины с плавающей запятой.
struct FloatShout
shout::String
dur::Float64
start::Float64
end
rs(x) = uppercase(randstring(x))
shouts = [FloatShout(rs(rand(3:5)), rand()+1, rand()) for k in 1:5]
shoutlimits(s::FloatShout) = (s.start, s.start + s.dur);
shouttranslate(s::FloatShout, n) = FloatShout(s.shout, s.dur, s.start + n);
q = 10.0
δq = 1.0
r, s = random_sequence(shouts, q, shoutlimits, shouttranslate, δq)
r
7-element Vector{Main.FloatShout}:
Main.FloatShout("HIIY", 1.2271063471583912, 0.0)
Main.FloatShout("HJA", 1.7413496261023735, 1.2271063471583914)
Main.FloatShout("PNCNX", 1.2683820201529303, 2.968455973260765)
Main.FloatShout("PNCNX", 1.2683820201529303, 4.236837993413696)
Main.FloatShout("OMGH", 1.1938851898812177, 5.5052200135666265)
Main.FloatShout("ONTJ", 1.8549771118240774, 6.699105203447845)
Main.FloatShout("PNCNX", 1.2683820201529303, 8.554082315271922)
s
7-element Vector{Int64}:
1
3
2
2
4
5
2