Package bgu.bio.algorithms.alignment

Source Code of bgu.bio.algorithms.alignment.DiagonalSequenceAlignment$Job

package bgu.bio.algorithms.alignment;

import gnu.trove.list.array.TCharArrayList;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Date;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicInteger;

import bgu.bio.util.IdentityScoringMatrix;
import bgu.bio.util.ScoringMatrix;
import bgu.bio.util.alphabet.AlphabetUtils;
import bgu.bio.util.alphabet.RnaAlphabet;

/* Class DiagonalSequenceAlignment - representing the object which will create an optimal alignment of 2 strings */

public class DiagonalSequenceAlignment implements SequenceAlignment {

  /* Variables concerning the alignment algorithm */

  /**
   * The two input strings
   */
  private char[] str1, str2;

  private int b1 = 0, b2 = 0;

  /**
   * Lengths of the two strings
   */
  private int length1, length2;

  /**
   * The matrix the program will fill The true scores should be divided by the
   * normalization factor.
   */
  private volatile double[][] dpTable;

  /**
   * The score matrix which will donate the values of deletion, insertion,
   * substitution and matching
   */
  private ScoringMatrix scoringMatrix;

  /**
   * The normalization factor. To get the true score, divide the integer score
   * used in computation by the normalization factor.
   */
  private double normFactor = 1.0;

  private double score;

  /**
   * Constants of directions. Multiple directions are stored by bits. The zero
   * direction is the starting point.
   */
  private static final int DR_LEFT = 1; // 0001
  private static final int DR_UP = 2; // 0010
  private static final int DR_DIAG = 4; // 0100
  private static final int DR_ZERO = 8; // 1000

  /**
   * The directions pointing to the cells that give the maximum score at the
   * current cell. The first index is the row index. The second index is the
   * column index.
   */
  private int[][] prevCells;

  /**
   * The alphabet used for this program (DNA / RNA / any other kind)
   */
  private AlphabetUtils alphabet;

  private StringBuffer alignment;

  /**
   * Indicates whether or not the strings have been rotated to create a lying
   * rectangle
   */
  private boolean rotatedStrings = false;

  /* Variables concerning the concurrent execution of the program */

  /**
   * The lock on which the working threads will wait for the main thread to
   * inform them they can start work
   */
  private Object lock = new Object();

  /**
   * Cyclic barrier which will indicate when it's possible to start working on
   * a new diagonal (by indicating when all the workers are done working on a
   * certain diagonal)
   */
  // private CyclicBarrier barrier;

  /**
   *
   */
  private AtomicInteger finishedCounter;

  /**
   * A flag indicating when the program needs to shut itself down (when all
   * work on dpTable has ended). The value changes once the last cell in the
   * matrix was filled, so the threads won't continue working for nothing.
   */
  private boolean running = true;

  /**
   * A helping variable which causes the working threads to avoid entering the
   * "fill-in" part of the run function, and wait for the work to be given to
   * all threads. Its value is > 0 right before the main threads notifies all
   * of the working threads they can start, and each worker decreases its
   * value by 1.
   */
  // private volatile int condition = 0; //helps preventing the Worker to
  // start working before work was given to all threads

  /**
   * The maximal number of threads which can work simultaneously on the same
   * diagonal. Receives its value from the user.
   */
  private int numOfWorkers;

  /**
   * Array of workers who will be used to fill in dpTable when the program
   * runs on concurrent mode
   */
  private Worker[] workers;

  /**
   * The amount of cells each thread will do in its work. For any smaller
   * amount of cells the program will run on sequential mode and won't use
   * threads.
   */
  private int cells;

  private Object consumers = new Object();

  private Job[] jobsPool;

  private Queue<Job> jobs;

  /* DiagonalSequenceAlignment methods */

  /**
   * Constructor according to given strings
   *
   * @param str1
   *            the first input string
   * @param str2
   *            the second input string
   * @param alphabet
   *            the alphabet used for this program
   * @param matrix
   *            the scoring matrix
   * @param numWorkers
   *            the number of threads for this program
   * @param cells
   *            the job's size
   */
  public DiagonalSequenceAlignment(String str1, String str2,
      AlphabetUtils alphabet, ScoringMatrix matrix, int numWorkers,
      int cells) {
    // we will make sure in the next constructor that str1 will always be
    // the shorter string, so we'll create a lying down rectangle
    this(str1.length(), str2.length(), alphabet, matrix, numWorkers, cells,
        0, 0);
    this.setSequences(str1, str2);
    this.buildMatrix();
    this.getAlignment();
  }

  /**
   * Constructor according to given strings
   *
   * @param str1
   *            the first input string
   * @param b1
   *            beginning index on str1
   * @param e1
   *            ending index on str1
   * @param str2
   *            the second input string
   * @param b2
   *            beginning index on str2
   * @param e2
   *            ending index on str2
   * @param alphabet
   *            the alphabet used for this program
   * @param matrix
   *            the scoring matrix
   * @param numWorkers
   *            the number of threads for this program
   * @param cells
   *            the job's size
   */
  public DiagonalSequenceAlignment(String str1, int b1, int e1, String str2,
      int b2, int e2, AlphabetUtils alphabet, ScoringMatrix matrix,
      int numWorkers, int cells) {
    // we will make sure in the next constructor that str1 will always be
    // the shorter string, so we'll create a lying down rectangle
    this((e1 - b1 + 1), (e2 - b2 + 1), alphabet, matrix, numWorkers, cells,
        b1, b2);
    int l1 = e1 - b1 + 1;
    int l2 = e2 - b2 + 1;
    if (l1 > 0 && l2 > 0) {
      this.setSequences(str1.toCharArray(), l1, str2.toCharArray(), l2);
      this.buildMatrix();
      this.getAlignment();
    }
  }

  /**
   * Constructor according to given sizes. Will be used when we don't
   * necessarily need to create a specific matrix for specific strings, but a
   * general matrix which will fit most strings inputs.
   *
   * @param size1
   *            the length of the first input string
   * @param size2
   *            the length of the second input string
   * @param alphabet
   *            the alphabet used for this program
   * @param matrix
   *            the scoring matrix
   * @param numWorkers
   *            the maximum number of threads (which the user entered) to be
   *            used on the program
   */
  public DiagonalSequenceAlignment(int size1, int size2,
      AlphabetUtils alphabet, ScoringMatrix matrix, int numWorkers,
      int jobSize, int b1, int b2) {

    if (size1 <= 0 && size2 <= 0) { // two empty strings, therefore the
                    // alignment itself is also empty
      this.alignment = new StringBuffer("");
      this.score = 0;
    } else if (size1 <= 0) { // str1 is empty, therefore the alignment is
                  // constructed of insertions only
      char[] arr = new char[size2];
      for (int i = 0; i < size2; i++) {
        arr[i] = 'I';
      }
      this.alignment = new StringBuffer(new String(arr));
      this.score = 0;
    } else if (size2 <= 0) { // str2 is empty, therefore the alignment is
                  // constructed of deletions only
      char[] arr = new char[size1];
      for (int i = 0; i < size1; i++) {
        arr[i] = 'D';
      }
      this.alignment = new StringBuffer(new String(arr));
      this.score = 0;
    } else {
      this.scoringMatrix = matrix;
      this.alphabet = alphabet;
      if (size1 <= size2) {
        length1 = size1;
        length2 = size2;
        this.b1 = b1;
        this.b2 = b2;
      } else {
        length1 = size2;
        length2 = size1;
        rotatedStrings = true;
        this.b1 = b2;
        this.b2 = b1;
      }
      // initializing the tables we need to fill
      dpTable = new double[length1 + 1][length2 + 1];
      prevCells = new int[length1 + 1][length2 + 1];

      numOfWorkers = numWorkers;
      // barrier = new CyclicBarrier(numOfWorkers+1); //+1 for the main
      // thread

      score = 0;

      this.cells = jobSize;

      finishedCounter = new AtomicInteger(0);

      // creating the working objects which will fill in the table
      workers = new Worker[numOfWorkers];
      for (int i = 0; i < numOfWorkers; i++) {
        workers[i] = new Worker(i);
      }

      int capacity = (length1 / cells) + 1;
      jobs = new LinkedList<Job>(); // the maximal amount of jobs is the
                      // longest diagonal divided by the
                      // required cells

      jobsPool = new Job[capacity];
      for (int i = 0; i < capacity; i++) {
        jobsPool[i] = new Job();
      }
    }
  }

  /**
   * Given 2 strings - creates the suitable dpTable and prevCells arrays
   */
  @Override
  public void setSequences(String str1, String str2) {
    this.setSequences(str1.toCharArray(), str2.toCharArray());
  }

  @Override
  public void setSequences(char[] str1, char[] str2) {
    setSequences(str1, str1.length, str2, str2.length);
  }

  /**
   * Given 2 char arrays - creates the suitable dpTable and prevCells arrays
   */

  @Override
  public void setSequences(char[] s1, int size1, char[] s2, int size2) {

    // making sure that this.str1 will be the shorter string
    boolean init = false;
    if (size1 <= size2) {
      this.str1 = s1;
      this.str2 = s2;
      // if(dpTable!=null)
      init = size1 > dpTable.length || size2 > dpTable[0].length;
      length1 = size1;
      length2 = size2;
    } else {
      this.str1 = s2;
      this.str2 = s1;
      // if(dpTable!=null)
      init = size2 > dpTable.length || size1 > dpTable[0].length;
      length1 = size2;
      length2 = size1;
    }

    if (init) {
      dpTable = new double[length1 + 1][length2 + 1];
      prevCells = new int[length1 + 1][length2 + 1];
    }

  }

  // /?????????????????????????????????????????????????????????????????????
  /**
   * Given 2 TCharArrayList-s - creates the suitable dpTable and prevCells
   * arrays
   */
  @Override
  public void setSequences(TCharArrayList str1, TCharArrayList str2) {
    if (this.str1 == null || this.str1.length < str1.size()) {
      this.str1 = str1.toArray();
    } else {
      str1.toArray(this.str1);
    }
    if (this.str2 == null || this.str2.length < str2.size()) {
      this.str2 = str2.toArray();
    } else {
      str2.toArray(this.str2);
    }

    boolean init = str1.size() > dpTable.length
        || str2.size() > dpTable[0].length;
    length1 = str1.size();
    length2 = str2.size();

    if (init) {
      dpTable = new double[length1 + 1][length2 + 1];
      prevCells = new int[length1 + 1][length2 + 1];
    }
  }

  /**
   * Creates the dpTable matrix according to the scores in the scoring matrix
   */
  @Override
  public void buildMatrix() {

    int i; // length of prefix substring of str1
    int j; // length of prefix substring of str2

    // basic conditions: filling in row 0 and column 0

    // the cell [0][0]
    dpTable[0][0] = 0.0;

    prevCells[0][0] = DR_ZERO;

    // first row - the 0 row
    for (j = 1; j <= length2; j++) {
      dpTable[0][j] = this.scoringMatrix.score(alphabet.emptyLetter(),
          str2[j - 1]) + dpTable[0][j - 1];
      prevCells[0][j] = DR_LEFT; // marks that we arrived "from left" to
                    // 0,j
    }

    // first column - the 0 column
    for (i = 1; i <= length1; i++) {
      dpTable[i][0] = this.scoringMatrix.score(str1[i - 1],
          alphabet.emptyLetter())
          + dpTable[i - 1][0];
      prevCells[i][0] = DR_UP; // marks that we arrived "from above" to
                    // i,0
    }

    /*
     * 'sum' represents the sum of the indexes i & j of a certain cell [i,j]
     * in the matrix. 'j' will mark the column index of the first cell in
     * the diagonal
     */
    int sum;
    int numOfCellsInDiagonal = 1;

    // int threadsNeeded = 0;

    for (int k = 0; k < numOfWorkers; k++) {
      workers[k].start();
    }

    j = 1; // for the first 'for' loop the first cell in a diagonal will
        // always have the column index 1

    /* first part of the matrix alignment */
    for (sum = 2; sum < length1 + 1; sum++) {
      /*
       * //computing the needed amount of threads threadsNeeded =
       * neededThreads(numOfCellsInDiagonal);
       *
       * if(threadsNeeded >= 2){ //we will use the amount of threads
       * needed concurrent(threadsNeeded, sum, j, numOfCellsInDiagonal); }
       * else sequential(sum-j, j, numOfCellsInDiagonal);
       *
       *
       * System.out.println(
       * "main thread about to move to the next step in the loop");
       */
      diagonalComputation(numOfCellsInDiagonal, sum, j);
      numOfCellsInDiagonal++;
    }

    /* mid part of the matrix alignment */
    for (sum = length1 + 1; sum <= length2 + 1; sum++) {
      /*
       * //computing the needed amount of threads threadsNeeded =
       * neededThreads(numOfCellsInDiagonal);
       *
       * if(threadsNeeded >= 2){ //we will use the amount of threads
       * needed (not necessarily all of the workers)
       * concurrent(threadsNeeded, sum, j, numOfCellsInDiagonal); } else
       * //for under 2 threads it is unnecessary to operate on concurrent
       * mode sequential(sum-j, j, numOfCellsInDiagonal);
       */
      diagonalComputation(numOfCellsInDiagonal, sum, j);

      j++;
    }

    numOfCellsInDiagonal--;

    /* last part of the matrix alignment */
    for (sum = length2 + 2; sum <= (length1 + length2); sum++) {

      diagonalComputation(numOfCellsInDiagonal, sum, j);
      /*
       * //computing the needed amount of threads threadsNeeded =
       * neededThreads(numOfCellsInDiagonal);
       *
       *
       * if(threadsNeeded >= 2){ //we will use the amount of threads
       * needed concurrent(threadsNeeded, sum, j, numOfCellsInDiagonal); }
       * else sequential(sum-j, j, numOfCellsInDiagonal);
       */

      numOfCellsInDiagonal--;
      j++;
    }

    running = false;
    for (int k = 0; k < numOfWorkers; k++) {
      workers[k].interrupt();
    }

    this.score = dpTable[length1][length2];

    // System.out.println("finished DSA");
  }

  /**
   * Print the dynamic programming matrix
   */
  public void printDPMatrix() {
    System.out.print("   ");
    for (int j = 1; j <= length2; j++)
      System.out.print("   " + str2[j - 1]);
    System.out.println();
    for (int i = 0; i <= length1; i++) {
      if (i > 0)
        System.out.print(str1[i - 1] + " ");
      else
        System.out.print("  ");
      for (int j = 0; j <= length2; j++) {
        System.out.print(dpTable[i][j] / normFactor + " ");
      }
      System.out.println();
    }
  }

  /**
   * Set the normal factor
   */
  @Override
  public void setNormFactor(double factor) {
    this.normFactor = factor;
  }

  /**
   * Get the maximum value in the
   */
  @Override
  public double getAlignmentScore() {
    return getMaxScore() / normFactor;
  }

  /**
   * Get the maximum value (normalized) in the filled dynamic programming
   * table
   */
  private double getMaxScore() {
    return this.score;
  }

  /**
   * Determines the needed computation method for the current diagonal
   * (sequential or concurrent) and fills the diagonal using the selected
   * method.
   *
   * @param numOfCellsInDiagonal
   *            the number of cells in the current diagonal
   * @param sum
   *            the sum of the row and column indexes of a cell in the current
   *            diagonal
   * @param j
   *            the first column index in the current diagonal
   */
  private void diagonalComputation(int numOfCellsInDiagonal, int sum, int j) {

    // computing the needed amount of threads
    // int threadsNeeded = neededThreads(numOfCellsInDiagonal);

    if (numOfCellsInDiagonal >= cells) { // we will use the amount of
                        // threads needed (not
                        // necessarily all of the
                        // workers)
      // System.out.println("going to use threads");
      concurrent(sum, j, numOfCellsInDiagonal);
    } else
      // for under 2 threads it is unnecessary to operate on concurrent
      // mode
      sequential(sum - j, j, numOfCellsInDiagonal);
  }

  /**
   * The help function that will be called to work on a specific diagonal, if
   * NO use of threads is needed (on sequential mode)
   *
   * @param rowB
   *            the first row index of the diagonal
   * @param colB
   *            the first column index of the diagonal
   * @param numOfCells
   *            the amount of cells needed to be filled in this diagonal
   */
  private void sequential(int rowB, int colB, int numOfCells) {
    int k = 1; // counter for the number of filled cells
    int currRow = rowB;
    int currColumn = colB;
    while (k <= numOfCells) {
      // actually filling the table
      helpFill(currRow, currColumn);
      currRow--;
      currColumn++;
      k++;
    }
  }

  /**
   * The help function that will be called to work on a specific diagonal, if
   * use of threads is needed (on concurrent mode)
   *
   * @param threadsNeeded
   *            the amounts of threads needed to work on this diagonal
   * @param sum
   *            the sum of the row and column indexes of any cell in this
   *            diagonal
   * @param j
   *            the column index of the first cell in the given diagonal, from
   *            which the partition of work will start
   * @param numOfCellsInDiagonal
   *            the amount of cells in this diagonal
   */
  private void concurrent(int sum, int j, int numOfCellsInDiagonal) {

    finishedCounter.set(0);
    int i = 1;
    int columnIndex = j;
    // int rowIndex = 0;
    int res = numOfCellsInDiagonal / cells;
    int iterations = numOfCellsInDiagonal % cells == 0 ? res : res + 1;
    // long startTime5, endTime5;

    Job job;
    while (i <= iterations) {
      job = jobsPool[i - 1];
      job.beginningColumn = columnIndex;
      job.beginningRow = sum - columnIndex;
      // job.howMany = iterations;
      // job.c = c;
      if (i == iterations) // the last iteration - the last job will be
                  // the remaining amount of cells
        job.numOfCells = numOfCellsInDiagonal - (iterations - 1)
            * cells;
      else
        // in all iterations except the last one, the job will be the
        // regular number of cells to fill
        job.numOfCells = cells;
      // startTime5 = System.currentTimeMillis();
      jobs.add(job);
      // endTime5 = System.currentTimeMillis();
      // time5 += (double)(endTime5 - startTime5)/60000;

      columnIndex += cells;
      i++;
    }

    synchronized (consumers) {
      // System.out.println("releasing threads");
      // mainFinished = true;
      for (int t = 0; t < numOfWorkers; t++)
        workers[t].shouldWork = true;
      // System.out.println("main releasing threads");
      consumers.notifyAll();
      // System.out.println("main finished inserting to queue, notifying the workers...");
    }

    // long endTime1 = System.currentTimeMillis();

    // time1 += (double)(endTime1 - startTime1)/60000;

    synchronized (lock) {
      while (finishedCounter.get() != numOfWorkers) {
        try {
          lock.wait();
          // System.out.println("main was released by the workers - moving to the next diagonal");
        } catch (InterruptedException e) {
          System.out
              .println("this message should never be printed since no one interrupts main");
        }
      }
    }

    /*
     * barrier.reset(); //+1 for the main thread
     *
     * int i = 1; int columnIndex = j; int rowIndex = 0; int cells =
     * numOfCellsInDiagonal/threadsNeeded; while (i<=threadsNeeded){
     * rowIndex = sum - columnIndex; if(i!=threadsNeeded){ //in all
     * iterations except the last one, the thread will be given the minimum
     * number of cells to fill workers[i-1].setIndex(rowIndex, columnIndex,
     * cells); columnIndex = columnIndex + cells; } else{ //the last
     * iteration - the last thread will be given the "remains" of the
     * //diagonal (number of cells in this thread's work might be bigger
     * than the minimum workers[i-1].setIndex(rowIndex, columnIndex,
     * numOfCellsInDiagonal - ((i-1)*cells)); } i++; }
     *
     *
     *
     * //after giving work to each worker, the main thread releases the
     * workers to commit their job synchronized(lock){ condition =
     * numOfWorkers; //????????????????????????????????// lock.notifyAll();
     * }
     *
     *
     * //main thread counts down and will be released when all of the
     * workers will finish try { barrier.await(); } catch
     * (InterruptedException e){ e.printStackTrace(); } catch
     * (BrokenBarrierException e){ // TODO Auto-generated catch block
     * e.printStackTrace(); }
     */
  }

  /**
   * Fill in the cells of dpTable and prevCells according to the given indexes
   *
   * @param i
   *            - row index
   * @param j
   *            - column index
   */
  private double helpFill(int i, int j) {
    final double diagScore = dpTable[i - 1][j - 1] + similarity(i, j); // match
                                      // or
                                      // substitution
    final double leftScore = dpTable[i][j - 1] + similarity(0, j); // a
                                    // letter
                                    // was
                                    // read
                                    // from
                                    // str2
    final double upScore = dpTable[i - 1][j] + similarity(i, 0); // a letter
                                    // was
                                    // read
                                    // from
                                    // str1

    dpTable[i][j] = max(diagScore, max(upScore, leftScore)); // determines
                                  // which
                                  // option
                                  // will give
                                  // the
                                  // highest
                                  // score

    // find the directions that give the maximum scores.
    // the bitwise OR operator is used to record multiple
    // directions.
    prevCells[i][j] = 0;
    if (diagScore == dpTable[i][j]) { // match or substitution
      prevCells[i][j] |= DR_DIAG;
    }
    if (leftScore == dpTable[i][j]) { // a letter was read from str2
      prevCells[i][j] |= DR_LEFT;
    }
    if (upScore == dpTable[i][j]) { // a letter was read from str1
      prevCells[i][j] |= DR_UP;
    }

    return dpTable[i][j];
  }

  /**
   * Compute the similarity score of substitution: use a substitution matrix
   * if the cost model The position of the first character is 1. A position of
   * 0 represents a gap.
   *
   * @param i
   *            Position of the character in str1
   * @param j
   *            Position of the character in str2
   * @return cost of substitution of the character in str1 by the one in str2
   */
  private final double similarity(int i, int j) {
    final char c1 = i == 0 ? alphabet.emptyLetter() : str1[i - 1 + b1]; // if
                                      // i=0
                                      // than
                                      // no
                                      // letter
                                      // was
                                      // read
                                      // from
                                      // str1
    final char c2 = j == 0 ? alphabet.emptyLetter() : str2[j - 1 + b2]; // if
                                      // j=0
                                      // than
                                      // no
                                      // letter
                                      // was
                                      // read
                                      // from
                                      // str2
    return scoringMatrix.score(c1, c2);
  }

  /**
   * Returns the higher value: a or b
   */
  private final double max(double a, double b) {
    return a > b ? a : b;
  }

  /**
   *
   * @return
   */
  public StringBuffer getAlignmentInBuffer() {
    StringBuffer ans = new StringBuffer();
    int i = length1;
    int j = length2;
    int val = 0;
    while (!(i == 0 && j == 0)) {
      val = prevCells[i][j];
      if (val == 1) {
        ans.append('I');
        j--;
      } else if (val == 2) {
        ans.append('D');
        i--;
      } else if (val == 4) {
        if (str1[i - 1 + b1] == str2[j - 1 + b2])
          ans.append('M');
        else
          ans.append('R');
        i--;
        j--;
      } else if (val == 3) {
        if (Math.random() > 0.5) {
          ans.append('I');
          j--;
        } else {
          ans.append('D');
          i--;
        }
      } else if (val == 5) {
        if (Math.random() > 0.5) {
          ans.append('I');
          j--;
        } else {
          if (str1[i - 1 + b1] == str2[j - 1 + b2])
            ans.append('M');
          else
            ans.append('R');
          i--;
          j--;
        }
      } else if (val == 6) {
        if (Math.random() > 0.5) {
          ans.append('D');
          i--;
        } else {
          if (str1[i - 1 + b1] == str2[j - 1 + b2])
            ans.append('M');
          else
            ans.append('R');
          i--;
          j--;
        }
      } else { // val = 7 (M/R or I or D)
        double rand = Math.random();
        if (rand < 0.3) {
          ans.append('D');
          i--;
        } else if (rand >= 0.3 && rand < 0.6) {
          ans.append('I');
          j--;
        } else {
          if (str1[i - 1 + b1] == str2[j - 1 + b2])
            ans.append('M');
          else
            ans.append('R');
          i--;
          j--;
        }
      }
    }
    ans.reverse();
    if (rotatedStrings) { // the query was accepted as a standing rectangle,
                // so translate the alignment to the mirror
                // alignment
      char[] arr = ans.toString().toCharArray();
      for (int t = 0; t < arr.length; t++) {
        if (arr[t] == 'I')
          arr[t] = 'D';
        else if (arr[t] == 'D')
          arr[t] = 'I';
      }
      ans = new StringBuffer(new String(arr));
    }
    this.alignment = ans;
    return ans;
  }

  public StringBuffer getAlignmentString() {
    return this.alignment;
  }

  /**
   * Compute the needed amount of threads for the filling of a specific
   * diagonal
   *
   * @param cells
   *            the amount of cells in the diagonal
   * @return the amount of needed threads
   *
   *         private int neededThreads(int cells){ int ans = cells /
   *         minCellsPerWorker;
   *
   *         //insuring that the maximal number of threads won't be bigger
   *         than the given amount of threads if(ans > numOfWorkers){ ans =
   *         numOfWorkers; } return ans; }
   */

  /**
   * Main
   */
  public static void main(String[] args) {
    // int n = 24; //need to get this from the user?
    // int jobSize = 2000;
    FileReader input1 = null, input2 = null;

    // reading s1 from a file
    StringBuffer s1 = new StringBuffer();

    try {
      input1 = new FileReader(args[0]); // get the argument
    } catch (FileNotFoundException e) {
      System.out.println("where is file 1?");
      e.printStackTrace();
    }
    BufferedReader buf1 = new BufferedReader(input1);
    String lineFromF1;

    try {
      lineFromF1 = buf1.readLine();
      while (lineFromF1 != null) {
        s1.append(lineFromF1); // connects the string to the
                    // StringBuffer
        lineFromF1 = buf1.readLine();
      }
      buf1.close(); // close the buffered reader

    } catch (IOException e1) {
      System.out.println("IO problem in F1");
      e1.printStackTrace();
    }
    String str1 = s1.toString(); // cast the StringBuffer to string, so we
                    // could handle it in the
                    // DiagoalSequenceAlignment class

    // same process for s2...
    StringBuffer s2 = new StringBuffer();
    try {
      input2 = new FileReader(args[1]);
    } catch (FileNotFoundException e) {
      System.out.println("where is file 2?");
      e.printStackTrace();
    }

    BufferedReader buf2 = new BufferedReader(input2);
    String lineFromF2;

    try {
      lineFromF2 = buf2.readLine();
      while (lineFromF2 != null) {
        s2.append(lineFromF2); // connects the string to the
                    // StringBuffer
        lineFromF2 = buf2.readLine();
      }
      buf2.close(); // close the buffered reader

    } catch (IOException e1) {
      System.out.println("IO problem in F2");
      e1.printStackTrace();
    }
    String str2 = s2.toString(); // cast the StringBuffer to string, so we
                    // could handle it in the
                    // DiagoalSequenceAlignment class

    int n = Integer.parseInt(args[2]);

    int jobSize = Integer.parseInt(args[3]);

    /*
     * int b1 = Integer.parseInt(args[4]); int e1 =
     * Integer.parseInt(args[5]); int b2 = Integer.parseInt(args[6]); int e2
     * = Integer.parseInt(args[7]); /* String str2 =
     * "ACTTGAC";//"GGCTTGCACAGTGCTGACTACTGCCGTAGTGCAAATCGACTTCGAGAGGGTGAGA"
     * ; String str1 =
     * "CGACTAGCT";//"AGCTTGTGGCTGAAAGCTAGATTTCGGATCGCACAGGTCTGTGTCGACACTCTTC"
     * ; int n = 2; int jobSize = 3;
     */
    System.out.println(new Date());

    DiagonalSequenceAlignment alignment = new DiagonalSequenceAlignment(
        str2, 15412, 15917, str1, 15411, 16187,
        RnaAlphabet.getInstance(), new IdentityScoringMatrix(
            RnaAlphabet.getInstance()), n, jobSize);

    System.out.println("Score is: " + alignment.getAlignmentScore());
    System.out.println("alignment is:\n" + alignment.getAlignmentString());
    // System.out.println(alignment.getAlignmentScore());
    // alignment.printAlignments();
    // alignment.printDPMatrix();
    // alignment.printDPMatrixInLatexMatrix();
    System.out.println(new Date());
  }

  /*
   * Class Worker - representing the runnable object that will fill the tables
   */

  private class Worker extends Thread {

    /**
     * Beginning and ending indexes indicating the work borders, and the
     * amount of cells this worker will need to fill
     */
    // private volatile int rowB , colB, numOfCells;

    /**
     * The Worker's ID number (for debug)
     */
    private int id;

    /**
     * Flag which changes to 'true' only when a worker is given work to do,
     * and changes back to 'false' when the Worker is done working
     */
    boolean shouldWork = false;

    /**
     * Constructor
     *
     * @param id
     *            the unique ID number of the worker
     */
    public Worker(int id) {
      this.id = id;
    }

    /**
     * Set the beginning and ending indexes of the worker's job
     *
     * @param rowB
     *            the beginning point - row index
     * @param colB
     *            the beginning point - column index
     * @param numOfCells
     *            the number of cells the Worker will need to fill in a
     *            specific "round" of work
     *
     *            public void setIndex(int rowB, int colB, int numOfCells){
     *            this.rowB = rowB; this.colB = colB; this.numOfCells =
     *            numOfCells; shouldWork = true; }
     */

    /**
     * The Worker run function which actually computes and writes the
     * suiting values in dpTable and prevCells
     */
    @Override
    public void run() {

      while (running) { // the condition fails only when all of dpTable
                // was filled

        synchronized (consumers) {
          try {
            while (!shouldWork) {
              consumers.wait();
              // System.out.println("thread was released by main");
            }
            shouldWork = false;
          } catch (InterruptedException e) {
            return;
          }
        }
        // System.out.println("Size of queue= " + jobs.size());
        Job myJob = null;

        do {
          // long startTime2 = System.currentTimeMillis();
          synchronized (jobs) {
            myJob = jobs.poll();
          }
          if (myJob != null) {
            if (myJob.numOfCells == -1)
              return;
            // long endTime2 = System.currentTimeMillis();
            // time2 += (double)(endTime2 - startTime2)/60000;
            // synchronized(lock2){
            // fill the table
            int rowB = myJob.beginningRow; // row index of the first
                            // cell to be filled in
                            // the worker's job
            int colB = myJob.beginningColumn; // column index of the
                              // first cell to be
                              // filled in the
                              // worker's job
            int count = myJob.numOfCells; // counter for the number
                            // of unfilled cells
            // char c = myJob.c;
            int k = 0;
            int currRow = rowB;
            int currColumn = colB;
            // System.out.println("worker commiting job: from [" +
            // rowB + "][" + (colB) + "], filling up " + count +
            // " cells, on diagonal of sum " + (rowB+colB));
            while (k < count) {
              helpFill(currRow, currColumn);
              currRow--;
              currColumn++;
              k++;
            }

            /*
             * while(k <= numOfCells){ //actually filling the table
             * double d = helpFill(currRow, currColumn);
             * System.out.println("worker " + this.id +
             * " filled in [" + currRow + ", " + currColumn +
             * "] the value " + d); currRow--; currColumn++; k++; }
             */

            // }
            // long endJob = System.currentTimeMillis();
            // time3 += (double)(endJob - endTime2)/60000;

          }
        } while (myJob != null);

        int num = finishedCounter.incrementAndGet(); // indicates a job
                                // was done
        if (num == numOfWorkers) {
          // System.out.println("threads releasing main");
          synchronized (lock) {
            lock.notify();
            // System.out.println("last thread notified and released main");
          }
        }

      }

      /*
       * while(running){ //the condition fails only when all of dpTable
       * was filled System.out.println("worker started");
       * synchronized(lock){ //catches the lock try { while(condition==0){
       * // meant for the threads to wait for every worker to receive job
       * and only then start //(condition > 0 right before buildMatrix
       * function calls notifyAll) lock.wait(); } condition--; //each
       * worker that got work "informs" that it starts } catch
       * (InterruptedException e) { return; } }
       * System.out.println("worker " + this.id +
       * " finished waiting on the try / catch"); if(shouldWork){ //this
       * part of the function will be executed only by the workers who
       * were given work to do // fill the table int k=1; //counter for
       * the number of filled cells int currRow = rowB; int currColumn =
       * colB; while(k <= numOfCells){ //actually filling the table double
       * d = helpFill(currRow, currColumn); System.out.println("worker " +
       * this.id + " filled in [" + currRow + ", " + currColumn +
       * "] the value " + d); currRow--; currColumn++; k++; }
       * System.out.println("worker finished his part in the diagonal");
       * shouldWork = false; }
       *
       * //count down to mark the main thread that the worker is done
       * working and waits for a new job try { barrier.await(); } catch
       * (InterruptedException e){ return; }
       *
       * catch (BrokenBarrierException e){ // TODO Auto-generated catch
       * block e.printStackTrace(); } }
       */
    }

    /**
     * Fill in the cells of dpTable and prevCells according to the given
     * indexes
     *
     * @param i
     *            - row index
     * @param j
     *            - column index
     */
    private double helpFill(int i, int j) {
      final double diagScore = dpTable[i - 1][j - 1] + similarity(i, j); // match
                                        // or
                                        // substitution
      final double leftScore = dpTable[i][j - 1] + similarity(0, j); // a
                                      // letter
                                      // was
                                      // read
                                      // from
                                      // str2
      final double upScore = dpTable[i - 1][j] + similarity(i, 0); // a
                                      // letter
                                      // was
                                      // read
                                      // from
                                      // str1

      dpTable[i][j] = max(diagScore, max(upScore, leftScore)); // determines
                                    // which
                                    // option
                                    // will
                                    // give
                                    // the
                                    // highest
                                    // score

      // find the directions that give the maximum scores.
      // the bitwise OR operator is used to record multiple
      // directions.
      prevCells[i][j] = 0;
      if (diagScore == dpTable[i][j]) { // match or substitution
        prevCells[i][j] |= DR_DIAG;
      }
      if (leftScore == dpTable[i][j]) { // a letter was read from str2
        prevCells[i][j] |= DR_LEFT;
      }
      if (upScore == dpTable[i][j]) { // a letter was read from str1
        prevCells[i][j] |= DR_UP;
      }

      return dpTable[i][j];
    }

    /**
     * Compute the similarity score of substitution: use a substitution
     * matrix if the cost model The position of the first character is 1. A
     * position of 0 represents a gap.
     *
     * @param i
     *            Position of the character in str1
     * @param j
     *            Position of the character in str2
     * @return cost of substitution of the character in str1 by the one in
     *         str2
     */
    private final double similarity(int i, int j) {
      final char c1 = i == 0 ? alphabet.emptyLetter() : str1[i - 1 + b1]; // if
                                        // i=0
                                        // than
                                        // no
                                        // letter
                                        // was
                                        // read
                                        // from
                                        // str1
      final char c2 = j == 0 ? alphabet.emptyLetter() : str2[j - 1 + b2]; // if
                                        // j=0
                                        // than
                                        // no
                                        // letter
                                        // was
                                        // read
                                        // from
                                        // str2
      return scoringMatrix.score(c1, c2);
    }

    /**
     * Returns the higher value: a or b
     */
    private final double max(double a, double b) {
      return a > b ? a : b;
    }

  } // end of class Worker

  /*
   *
   * private class ReusableBarrier{
   *
   * int parties;
   *
   *
   * public ReusableBarrier(int parties){ this.parties = parties; }
   *
   *
   * public synchronized void reset(int i){ parties = i; }
   *
   * public synchronized void await() throws InterruptedException // throws
   * exception?? { parties--; if (parties==0){ this.notifyAll(); } else
   * this.wait();
   *
   * }
   *
   * } //end of class ReusableBarrier
   */

  /**
   * Class Job
   */
  private class Job {
    private volatile int beginningRow; // the row index of the first cell in
                      // this job
    private volatile int beginningColumn; // the column index of the first
                        // cell in this job
    private volatile int numOfCells; // the amount of cells needs to be
                      // filled in this job
    // private volatile int howMany; //this job is one of how many jobs?
    // private volatile char c; //state of filling
  } // end of class Job

  @Override
  public String[] getAlignment() {
    // TODO Auto-generated method stub
    throw new UnsupportedOperationException("Need to implement");
  }
 
  @Override
  public DiagonalSequenceAlignment cloneAligner() {
    throw new UnsupportedOperationException("Need to implement");
  }

}// end of class DiagonalSeuenceAlignment

TOP

Related Classes of bgu.bio.algorithms.alignment.DiagonalSequenceAlignment$Job

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.