Jump to content

Bioinformatics/Sequence mutation: Difference between revisions

m
Comments and docs
m (Added weighted mutations)
m (Comments and docs)
Line 1,306:
 
// Utility functions
/**
* Return a shallow copy of an array
* @param {Array<*>} arr
* @returns {*[]}
*/
const copy = arr => [...arr];
 
/**
* Get a random int up to but excluding the the given number
* @param {number} max
* @returns {number}
*/
const randTo = max => (Math.random() * max) | 0;
 
/**
* Given an array return a random element and the index of that element from
* the array.
* @param {Array<*>} arr
* @returns {[*[], number]}
*/
const randSelect = arr => {
const at = randTo(arr.length);
return [arr[at], at];
};
 
/**
* Given a number or string, return a left padded string
* @param {string|number} v
* @returns {string}
*/
const pad = v => ('' + v).padStart(4, ' ');
 
/**
* Count the number of elements that match the given value in an array
* @param {Array<string>} arr
* @returns {function(string): number}
*/
const filterCount = arr => s => arr.filter(e => e === s).length;
 
/**
* Utility logging function
* @param {string|number} v
* @param {string|number} n
*/
const print = (v, n) => console.log(`${pad(v)}:\t${n}`)
 
/**
* Utility function to randomly select a new base, and an index in the given
* sequence.
* @param {Array<string>} seq
* @param {Array<string>} bases
* @returns {[string, string, number]}
*/
const getVars = (seq, bases) => {
const [newBase, _] = randSelect(bases);
const [extBase, randPos] = randSelect(seq);
return [newBase, extBase, randPos];
};
 
// Bias the operations
const leftPadN = n => v => {
/**
const arr = [...('' + v)];
* Given a map of function to ratio, return an array of those functions
const short = n - arr.length;
* appearing ratio number of times in the array.
return short ? [...(Array(short).fill(' ')), ...arr].join('') : arr.join('');
* @param weightMap
* @returns {Array<function>}
 
*/
const filterCount = arr => s => arr.filter(e => e === s).length;
const leftPadNweightedOps = n => vweightMap => {
return [...weightMap.entries()].reduce((p, [op, weight]) =>
[...p, ...(Array(weight).fill(op))], []);
};
 
// Pretty Print functions
const prettyPrint = seq => {
let idx = 0;
const pad = leftPadN(4);
const print = (v, s) => console.log(`${pad(v)}:\t${s}`)
const rem = seq.reduce((p, c) => {
const s = p + c;
Line 1,350 ⟶ 1,396:
const printBases = seq => {
const filterSeq = filterCount(seq);
const pad = leftPadN(4);
const print = (v, n) => console.log(`${pad(v)}:\t${n}`)
let tot = 0;
[...bases].forEach(e => {
const cnt = filterSeq(e);
print(e, cnt);
Line 1,361 ⟶ 1,405:
}
 
// MutationsMutation definitions
const swap = ([hist, seq]) => {
const arr = copy(seq);
Line 1,382 ⟶ 1,426:
return [[...hist, `Inserted ${newBase} at ${randPos}`], arr];
}
 
// Bias the operations
const weightMap = new Map();
weightMap.set(swap, 1);
weightMap.set(del, 2);
weightMap.set(insert, 3);
const weightedOps = weightMap => {
return [...weightMap.entries()].reduce((p, [op, weight]) =>
[...p, ...(Array(weight).fill(op))], []);
};
const operations = weightedOps(weightMap);
 
// Create the starting sequence
Line 1,398 ⟶ 1,431:
() => randSelect(bases)[0]);
 
// Create a weighted set of mutations
const weightMap = new Map();
weightMap .set(swap, 1);
weightMap .set(del, 21);
weightMap .set(insert, 31);
const operations = weightedOps(weightMap);
const mutations = Array(numMutations).fill(undefined).map(
() => randSelect(operations)[0]);
 
// Mutate the sequence
const [hist, mut] = mutations.reduce((p, c, i) => c(p), [[], seq]);
 
console.log('ORIGINAL SEQUENCE:')
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.