MASA-Core
CPUBlockProcessor.cpp
Go to the documentation of this file.
00001 /*******************************************************************************
00002  *
00003  * Copyright (c) 2010-2015   Edans Sandes
00004  *
00005  * This file is part of MASA-Core.
00006  * 
00007  * MASA-Core is free software: you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation, either version 3 of the License, or
00010  * (at your option) any later version.
00011  * 
00012  * MASA-Core is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with MASA-Core.  If not, see <http://www.gnu.org/licenses/>.
00019  *
00020  ******************************************************************************/
00021 
00022 #include "CPUBlockProcessor.hpp"
00023 
00024 #include <stdio.h>
00025 
00026 /*
00027  * Some macros
00028  */
00029 #define MAX2(A,B) (((A)>(B))?(A):(B))
00030 #define MAX3(A,B,C) (MAX2(MAX2((A),(B)),(C)))
00031 #define MAX4(A,B,C,D) (MAX2(MAX2((A),(B)),MAX2((C),(D))))
00032 
00033 #define DEBUG (0)
00034 
00035 CPUBlockProcessor::CPUBlockProcessor() {
00036         this->seq0 = NULL;
00037         this->seq1 = NULL;
00038 }
00039 
00040 CPUBlockProcessor::~CPUBlockProcessor() {
00041         // TODO Auto-generated destructor stub
00042 }
00043 
00044 void CPUBlockProcessor::setSequences(const char* seq0, const char* seq1, int seq0_len, int seq1_len) {
00045         this->seq0 = seq0;
00046         this->seq1 = seq1;
00047 }
00048 
00049 void CPUBlockProcessor::unsetSequences() {
00050 
00051 }
00052 
00053 
00054 /**
00055  * Implements the smith waterman recurrence function.
00056  *
00057  * @param c0 char of sequence s0
00058  * @param c1 char of sequence s1
00059  * @param[in,out]       e00 Input E[i][j-1]; Output E[i][j]
00060  * @param[in,out]       f00 Input F[i-1][j]; Output F[i][j]
00061  * @param[in]           h01     Input H[i][j-1]
00062  * @param[in]           h11 Input H[i-1][j-1]
00063  * @param[in]           h10 Input H[i-1][j]
00064  * @param[out]          h00 Ouput H[i][j]
00065  */
00066 static void sw(const unsigned char c0, const unsigned char c1,
00067                         int *e00, int *f00, const int h01, const int h11, const int h10, int *h00) {
00068     *e00 = MAX2(h01-DNA_GAP_OPEN, *e00)-DNA_GAP_EXT; // Horizontal propagation
00069     *f00 = MAX2(h10-DNA_GAP_OPEN, *f00)-DNA_GAP_EXT; // Vertical propagation
00070     int v1 = h11+((c1!=c0)?DNA_MISMATCH:DNA_MATCH);
00071     *h00 = MAX4(0, v1, *e00, *f00);
00072 }
00073 
00074 /**
00075  * Implements the Needleman Wunsch recurrence function.
00076  *
00077  * @param c0 char of sequence s0
00078  * @param c1 char of sequence s1
00079  * @param[in,out]       e00 Input E[i][j-1]; Output E[i][j]
00080  * @param[in,out]       f00 Input F[i-1][j]; Output F[i][j]
00081  * @param[in]           h01     Input H[i][j-1]
00082  * @param[in]           h11 Input H[i-1][j-1]
00083  * @param[in]           h10 Input H[i-1][j]
00084  * @param[out]          h00 Ouput H[i][j]
00085  */
00086 static void nw(const unsigned char c0, const unsigned char c1,
00087                         int *e00, int *f00, const int h01, const int h11, const int h10, int *h00) {
00088 
00089     *e00 = MAX2(h01-DNA_GAP_OPEN, *e00)-DNA_GAP_EXT; // Horizontal propagation
00090     *f00 = MAX2(h10-DNA_GAP_OPEN, *f00)-DNA_GAP_EXT; // Vertical propagation
00091     int v1 = h11+((c1!=c0)?DNA_MISMATCH:DNA_MATCH);
00092     *h00 = MAX3(v1, *e00, *f00);
00093 }
00094 
00095 /**
00096  * Executes the SW/NW recurrence function for the given block.
00097  * @param[in,out]       row             Input: cells from the first row of the block, where
00098  *                                                                       row[k] represents cell (i0-1,j0+k);
00099  *                                                      Output: the same range is used for write, but the output represents the
00100  *                                                                      last row of the block;
00101  * @param[in,out]       col             Input: cells from the first column of the partition, where
00102  *                                                                      col[k] represents cell (i0-1+k,j0-1). Note that
00103  *                                                                      the col vector contains the diag cell (i0-1,j0-1).
00104  *                                                      Output: the same idea, but representing the last column of the partition.
00105  *                                                                      Note that col[0] represents the diag cell (i0-1,j0-1).
00106  *
00107  * @param[in]           i0      start row
00108  * @param[in]           j0      start column
00109  * @param[in]           i1      end row
00110  * @param[in]           j1      end column
00111  * @return
00112  */
00113 score_t CPUBlockProcessor::processBlock(cell_t *row, cell_t *col,
00114                 const int i0, const int j0, const int i1, const int j1,
00115                 const int recurrenceType) {
00116         /* Initializing the best score of this block */
00117         score_t block_best;
00118         block_best.i = -1;
00119         block_best.j = -1;
00120         block_best.score = -INF;
00121 
00122         /* sequence strings starting from the position i0 and j0. */
00123         const char* seq0 = this->seq0 + i0;
00124         const char* seq1 = this->seq1 + j0;
00125 
00126         int h11 = col[0].h; // diagonal cell H[i-1][j-1]
00127         //printf("[%d..%d][%d..%d] %d\n", i0, i1, j0, j1, h11);
00128 
00129         for (int i=0; i<i1-i0; i++) {
00130                 /* Reads cells from the previous left-block */
00131                 int h01 = col[i+1].h;   // H[i][j-1]
00132                 int e00 = col[i+1].e;   // E[i][j-1]
00133 
00134                 const unsigned char c = seq0[i];
00135                 for (int j=0; j<j1-j0; j++) {
00136                         int h10 = row[j].h; // H[i-1][j]
00137                         int f10 = row[j].f; // F[i-1][j]
00138 
00139                         /* Calculates H[i][j] */
00140                         int h00;
00141                         if (recurrenceType == SMITH_WATERMAN) {
00142                                 sw(c, seq1[j], &e00, &f10, h01, h11, h10, &h00);
00143                         } else {
00144                                 nw(c, seq1[j], &e00, &f10, h01, h11, h10, &h00);
00145                         }
00146 
00147                         /* Store the cells to be used in the next iteration */
00148                         h11 = h10;
00149                         h01 = h00;
00150                         row[j].h = h00;
00151                         row[j].f = f10;
00152 
00153                         /* Updates best score if necessary */
00154                         if (block_best.score < h00) {
00155                                 block_best.score = h00;
00156                                 block_best.i = i0+i;
00157                                 block_best.j = j0+j;
00158                         }
00159                 }
00160 
00161                 /* Store cells to the next right block */
00162                 if (i==0) {
00163                         col[0].h = h11; // Last diagonal cell H[i-1][j-1]
00164                 }
00165                 h11 = col[i+1].h;
00166                 col[i+1].h = h01;
00167                 col[i+1].e = e00;
00168         }
00169         //printf("[%d..%d][%d..%d] %d\n", i0, i1, j0, j1, h11);
00170 
00171         if (DEBUG) printf("ProcessBlock (%d,%d)-(%d,%d) - best:(%d,%d,%d)\n", i0, j0, i1, j1, block_best.score, block_best.i, block_best.j);
00172 
00173         return block_best;
00174 }
00175