How to resolve the algorithm Bioinformatics/Sequence mutation step by step in the JavaScript programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Bioinformatics/Sequence mutation step by step in the JavaScript programming language

Table of Contents

Problem Statement

Given a string of characters A, C, G, and T representing a DNA sequence write a routine to mutate the sequence, (string) by:

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Bioinformatics/Sequence mutation step by step in the JavaScript programming language

Overview:

  • This code simulates mutations in a DNA sequence by randomly applying base swaps, deletions, and insertions.

Specific Breakdown:

Utility Functions:

  • copy: Creates a shallow copy of an array.
  • randTo: Returns a random integer up to but not including the given maximum.
  • randSelect: Selects a random element from an array and returns the element along with its index.
  • pad: Left-pads a string to a fixed length.
  • filterCount: Returns a function that counts the occurrences of a given value in an array.
  • print: Logs a value to the console with a label.
  • getVars: Randomly selects a new base, an existing base, and a random position in the sequence.

Sequence Manipulation Functions:

  • swap: Swaps a base at a random position in the sequence.
  • del: Deletes a base at a random position in the sequence.
  • insert: Inserts a new base at a random position in the sequence.

Mutation Definitions:

  • Several mutation definitions are provided: swap, del, and insert, each representing specific mutation types.

Main Sequence Manipulation:

  • An initial sequence of length numBases is created randomly.
  • A weighted set of mutations is created based on the weightMap, where each mutation has a specific occurrence probability.
  • numMutations mutations are randomly selected and applied to the sequence, recording the mutation history in hist.
  • The mutated sequence is then stored in mut.

Pretty Print Functions:

  • prettyPrint: Prints the sequence as multiple lines of 50 characters each.
  • printBases: Counts and prints the occurrences of each base in the sequence.

Execution:

  • The original sequence is generated and printed.
  • Base counts for the original sequence are printed.
  • The mutation history is printed.
  • The mutated sequence is printed.
  • Base counts for the mutated sequence are printed.

Results:

  • The program simulates mutations on a DNA sequence, tracking the changes made and the final mutated sequence.
  • The base counts before and after mutation showcase the changes introduced by the mutations.

Source code in the javascript programming language

// Basic set-up
const numBases = 250
const numMutations = 30
const bases = ['A', 'C', 'G', 'T'];

// 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
/**
 * Given a map of function to ratio, return an array of those functions
 * appearing ratio number of times in the array.
 * @param weightMap
 * @returns {Array<function>}
 */
const weightedOps = weightMap => {
  return [...weightMap.entries()].reduce((p, [op, weight]) =>
      [...p, ...(Array(weight).fill(op))], []);
};

// Pretty Print functions
const prettyPrint = seq => {
  let idx = 0;
  const rem = seq.reduce((p, c) => {
    const s = p + c;
    if (s.length === 50) {
      print(idx, s);
      idx = idx + 50;
      return '';
    }
    return s;
  }, '');
  if (rem !== '') {
    print(idx, rem);
  }
}

const printBases = seq => {
  const filterSeq = filterCount(seq);
  let tot = 0;
  [...bases].forEach(e => {
    const cnt = filterSeq(e);
    print(e, cnt);
    tot = tot + cnt;
  })
  print('Σ', tot);
}

// Mutation definitions
const swap = ([hist, seq]) => {
  const arr = copy(seq);
  const [newBase, extBase, randPos] = getVars(arr, bases);
  arr.splice(randPos, 1, newBase);
  return [[...hist, `Swapped ${extBase} for ${newBase} at ${randPos}`], arr];
};

const del = ([hist, seq]) => {
  const arr = copy(seq);
  const [newBase, extBase, randPos] = getVars(arr, bases);
  arr.splice(randPos, 1);
  return [[...hist, `Deleted ${extBase} at ${randPos}`], arr];
}

const insert = ([hist, seq]) => {
  const arr = copy(seq);
  const [newBase, extBase, randPos] = getVars(arr, bases);
  arr.splice(randPos, 0, newBase);
  return [[...hist, `Inserted ${newBase} at ${randPos}`], arr];
}

// Create the starting sequence
const seq = Array(numBases).fill(undefined).map(
    () => randSelect(bases)[0]);

// Create a weighted set of mutations
const weightMap = new Map()
    .set(swap, 1)
    .set(del, 1)
    .set(insert, 1);
const operations = weightedOps(weightMap);
const mutations = Array(numMutations).fill(undefined).map(
    () => randSelect(operations)[0]);

// Mutate the sequence
const [hist, mut] = mutations.reduce((p, c) => c(p), [[], seq]);

console.log('ORIGINAL SEQUENCE:')
prettyPrint(seq);

console.log('\nBASE COUNTS:')
printBases(seq);

console.log('\nMUTATION LOG:')
hist.forEach((e, i) => console.log(`${i}:\t${e}`));

console.log('\nMUTATED SEQUENCE:')
prettyPrint(mut);

console.log('\nMUTATED BASE COUNTS:')
printBases(mut);


  

You may also check:How to resolve the algorithm Partition function P step by step in the JavaScript programming language
You may also check:How to resolve the algorithm 15 puzzle game step by step in the JavaScript programming language
You may also check:How to resolve the algorithm Program termination step by step in the JavaScript programming language
You may also check:How to resolve the algorithm RPG attributes generator step by step in the JavaScript programming language
You may also check:How to resolve the algorithm Terminal control/Preserve screen step by step in the JavaScript programming language