block_align.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:38k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: block_align.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:11:09  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.20
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: block_align.cpp,v 1000.2 2004/06/01 18:11:09 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Authors:  Paul Thiessen
  35. *
  36. * File Description:
  37. *      Dynamic programming-based alignment algorithms: block aligner
  38. *
  39. * ===========================================================================
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <corelib/ncbistd.hpp>
  43. #include <corelib/ncbidiag.hpp>
  44. #include <corelib/ncbi_limits.h>
  45. #include <vector>
  46. #include <list>
  47. #include <algorithm>
  48. #include <algo/structure/struct_dp/struct_dp.h>
  49. USING_NCBI_SCOPE;
  50. const int DP_NEGATIVE_INFINITY = kMin_Int;
  51. const unsigned int DP_POSITIVE_INFINITY = kMax_UInt;
  52. const unsigned int DP_UNFROZEN_BLOCK = kMax_UInt;
  53. BEGIN_SCOPE(struct_dp)
  54. #define ERROR_MESSAGE(s) ERR_POST(Error << "block_align: " << s << '!')
  55. #define WARNING_MESSAGE(s) ERR_POST(Warning << "block_align: " << s)
  56. #define INFO_MESSAGE(s) ERR_POST(Info << "block_align: " << s)
  57. #define NO_TRACEBACK kMax_UInt
  58. class Cell
  59. {
  60. public:
  61.     int score;
  62.     unsigned int tracebackResidue;
  63.     Cell(void) : score(DP_NEGATIVE_INFINITY), tracebackResidue(NO_TRACEBACK) { }
  64. };
  65. class Matrix
  66. {
  67. public:
  68.     typedef vector < Cell > ResidueRow;
  69.     typedef vector < ResidueRow > Grid;
  70.     Grid grid;
  71.     Matrix(unsigned int nBlocks, unsigned int nResidues) : grid(nBlocks + 1)
  72.         { for (unsigned int i=0; i<nBlocks; ++i) grid[i].resize(nResidues + 1); }
  73.     ResidueRow& operator [] (unsigned int block) { return grid[block]; }
  74.     const ResidueRow& operator [] (unsigned int block) const { return grid[block]; }
  75. };
  76. // checks to make sure frozen block positions are legal (borrowing my own code from blockalign.c)
  77. int ValidateFrozenBlockPositions(const DP_BlockInfo *blocks,
  78.     unsigned int queryFrom, unsigned int queryTo, bool checkGapSum)
  79. {
  80.     static const unsigned int NONE = kMax_UInt;
  81.     unsigned int
  82.         block,
  83.         unfrozenBlocksLength = 0,
  84.         prevFrozenBlock = NONE,
  85.         maxGapsLength = 0;
  86.     for (block=0; block<blocks->nBlocks; ++block) {
  87.         /* keep track of max gap space between frozen blocks */
  88.         if (block > 0)
  89.             maxGapsLength += blocks->maxLoops[block - 1];
  90.         /* to allow room for unfrozen blocks between frozen ones */
  91.         if (blocks->freezeBlocks[block] == DP_UNFROZEN_BLOCK) {
  92.             unfrozenBlocksLength += blocks->blockSizes[block];
  93.             continue;
  94.         }
  95.         /* check absolute block end positions */
  96.         if (blocks->freezeBlocks[block] < queryFrom) {
  97.             ERROR_MESSAGE("Frozen block " << (block+1) << " can't start < " << (queryFrom+1));
  98.             return STRUCT_DP_PARAMETER_ERROR;
  99.         }
  100.         if (blocks->freezeBlocks[block] + blocks->blockSizes[block] - 1 > queryTo) {
  101.             ERROR_MESSAGE("Frozen block " << (block+1) << " can't end > " << (queryTo+1));
  102.             return STRUCT_DP_PARAMETER_ERROR;
  103.         }
  104.         /* checks for legal distances between frozen blocks */
  105.         if (prevFrozenBlock != NONE) {
  106.             unsigned int prevFrozenBlockEnd =
  107.                 blocks->freezeBlocks[prevFrozenBlock] + blocks->blockSizes[prevFrozenBlock] - 1;
  108.             /* check for adequate room for unfrozen blocks between frozen blocks */
  109.             if (blocks->freezeBlocks[block] <= (prevFrozenBlockEnd + unfrozenBlocksLength)) {
  110.                 ERROR_MESSAGE("Frozen block " << (block+1) << " starts before end of prior frozen block, "
  111.                     "or doesn't leave room for intervening unfrozen block(s)");
  112.                 return STRUCT_DP_PARAMETER_ERROR;
  113.             }
  114.             /* check for too much gap space since last frozen block,
  115.                but if frozen blocks are adjacent, issue warning only */
  116.             if (checkGapSum &&
  117.                 blocks->freezeBlocks[block] > prevFrozenBlockEnd + 1 + unfrozenBlocksLength + maxGapsLength)
  118.             {
  119.                 if (prevFrozenBlock == block - 1) {
  120.                     WARNING_MESSAGE("Frozen block " << (block+1) << " is further than allowed loop length"
  121.                         " from adjacent frozen block " << (prevFrozenBlock+1));
  122.                 } else {
  123.                     ERROR_MESSAGE("Frozen block " << (block+1) << " is too far away from prior frozen block"
  124.                         " given allowed intervening loop length(s) " << maxGapsLength
  125.                         << " plus unfrozen block length(s) " << unfrozenBlocksLength);
  126.                     return STRUCT_DP_PARAMETER_ERROR;
  127.                 }
  128.             }
  129.         }
  130.         /* reset counters after each frozen block */
  131.         prevFrozenBlock = block;
  132.         unfrozenBlocksLength = maxGapsLength = 0;
  133.     }
  134.     return STRUCT_DP_OKAY;
  135. }
  136. // fill matrix values; return true on success. Matrix must have only default values when passed in.
  137. int CalculateGlobalMatrix(Matrix& matrix,
  138.     const DP_BlockInfo *blocks, DP_BlockScoreFunction BlockScore,
  139.     unsigned int queryFrom, unsigned int queryTo)
  140. {
  141.     unsigned int block, residue, prevResidue, lastBlock = blocks->nBlocks - 1;
  142.     int score = 0, sum;
  143.     // find possible block positions, based purely on block lengths
  144.     vector < unsigned int > firstPos(blocks->nBlocks), lastPos(blocks->nBlocks);
  145.     for (block=0; block<=lastBlock; ++block) {
  146.         if (block == 0) {
  147.             firstPos[0] = queryFrom;
  148.             lastPos[lastBlock] = queryTo - blocks->blockSizes[lastBlock] + 1;
  149.         } else {
  150.             firstPos[block] = firstPos[block - 1] + blocks->blockSizes[block - 1];
  151.             lastPos[lastBlock - block] =
  152.                 lastPos[lastBlock - block + 1] - blocks->blockSizes[lastBlock - block];
  153.         }
  154.     }
  155.     // further restrict the search if blocks are frozen
  156.     for (block=0; block<=lastBlock; ++block) {
  157.         if (blocks->freezeBlocks[block] != DP_UNFROZEN_BLOCK) {
  158.             if (blocks->freezeBlocks[block] < firstPos[block] ||
  159.                 blocks->freezeBlocks[block] > lastPos[block])
  160.             {
  161.                 ERROR_MESSAGE("CalculateGlobalMatrix() - frozen block "
  162.                     << (block+1) << " does not leave room for unfrozen blocks");
  163.                 return STRUCT_DP_PARAMETER_ERROR;
  164.             }
  165.             firstPos[block] = lastPos[block] = blocks->freezeBlocks[block];
  166.         }
  167.     }
  168.     // fill in first row with scores of first block at all possible positions
  169.     for (residue=firstPos[0]; residue<=lastPos[0]; ++residue)
  170.         matrix[0][residue - queryFrom].score = BlockScore(0, residue);
  171.     // for each successive block, find the best allowed pairing of the block with the previous block
  172.     bool blockScoreCalculated;
  173.     for (block=1; block<=lastBlock; ++block) {
  174.         for (residue=firstPos[block]; residue<=lastPos[block]; ++residue) {
  175.             blockScoreCalculated = false;
  176.             for (prevResidue=firstPos[block - 1]; prevResidue<=lastPos[block - 1]; ++prevResidue) {
  177.                 // current block must come after the previous block
  178.                 if (residue < prevResidue + blocks->blockSizes[block - 1])
  179.                     break;
  180.                 // cut off at max loop length from previous block, but not if both blocks are frozen
  181.                 if (residue > prevResidue + blocks->blockSizes[block - 1] + blocks->maxLoops[block - 1] &&
  182.                         (blocks->freezeBlocks[block] == DP_UNFROZEN_BLOCK ||
  183.                          blocks->freezeBlocks[block - 1] == DP_UNFROZEN_BLOCK))
  184.                     continue;
  185.                 // make sure previous block is at an allowed position
  186.                 if (matrix[block - 1][prevResidue - queryFrom].score == DP_NEGATIVE_INFINITY)
  187.                     continue;
  188.                 // get score at this position
  189.                 if (!blockScoreCalculated) {
  190.                     score = BlockScore(block, residue);
  191.                     if (score == DP_NEGATIVE_INFINITY)
  192.                         break;
  193.                     blockScoreCalculated = true;
  194.                 }
  195.                 // find highest sum of scores for allowed pairing of this block with any previous
  196.                 sum = score + matrix[block - 1][prevResidue - queryFrom].score;
  197.                 if (sum > matrix[block][residue - queryFrom].score) {
  198.                     matrix[block][residue - queryFrom].score = sum;
  199.                     matrix[block][residue - queryFrom].tracebackResidue = prevResidue;
  200.                 }
  201.             }
  202.         }
  203.     }
  204.     return STRUCT_DP_OKAY;
  205. }
  206. // fill matrix values; return true on success. Matrix must have only default values when passed in.
  207. int CalculateGlobalMatrixGeneric(Matrix& matrix,
  208.     const DP_BlockInfo *blocks, DP_BlockScoreFunction BlockScore, DP_LoopPenaltyFunction LoopScore,
  209.     unsigned int queryFrom, unsigned int queryTo)
  210. {
  211.     unsigned int block, residue, prevResidue, lastBlock = blocks->nBlocks - 1;
  212.     int blockScore = 0, sum;
  213.     unsigned int loopPenalty;
  214.     // find possible block positions, based purely on block lengths
  215.     vector < unsigned int > firstPos(blocks->nBlocks), lastPos(blocks->nBlocks);
  216.     for (block=0; block<=lastBlock; ++block) {
  217.         if (block == 0) {
  218.             firstPos[0] = queryFrom;
  219.             lastPos[lastBlock] = queryTo - blocks->blockSizes[lastBlock] + 1;
  220.         } else {
  221.             firstPos[block] = firstPos[block - 1] + blocks->blockSizes[block - 1];
  222.             lastPos[lastBlock - block] =
  223.                 lastPos[lastBlock - block + 1] - blocks->blockSizes[lastBlock - block];
  224.         }
  225.     }
  226.     // further restrict the search if blocks are frozen
  227.     for (block=0; block<=lastBlock; ++block) {
  228.         if (blocks->freezeBlocks[block] != DP_UNFROZEN_BLOCK) {
  229.             if (blocks->freezeBlocks[block] < firstPos[block] ||
  230.                 blocks->freezeBlocks[block] > lastPos[block])
  231.             {
  232.                 ERROR_MESSAGE("CalculateGlobalMatrix() - frozen block "
  233.                     << (block+1) << " does not leave room for unfrozen blocks");
  234.                 return STRUCT_DP_PARAMETER_ERROR;
  235.             }
  236.             firstPos[block] = lastPos[block] = blocks->freezeBlocks[block];
  237.         }
  238.     }
  239.     // fill in first row with scores of first block at all possible positions
  240.     for (residue=firstPos[0]; residue<=lastPos[0]; ++residue)
  241.         matrix[0][residue - queryFrom].score = BlockScore(0, residue);
  242.     // for each successive block, find the best allowed pairing of the block with the previous block
  243.     bool blockScoreCalculated;
  244.     for (block=1; block<=lastBlock; ++block) {
  245.         for (residue=firstPos[block]; residue<=lastPos[block]; ++residue) {
  246.             blockScoreCalculated = false;
  247.             for (prevResidue=firstPos[block - 1]; prevResidue<=lastPos[block - 1]; ++prevResidue) {
  248.                 // current block must come after the previous block
  249.                 if (residue < prevResidue + blocks->blockSizes[block - 1])
  250.                     break;
  251.                 // make sure previous block is at an allowed position
  252.                 if (matrix[block - 1][prevResidue - queryFrom].score == DP_NEGATIVE_INFINITY)
  253.                     continue;
  254.                 // get loop score at this position; assume loop score zero if both frozen
  255.                 if (blocks->freezeBlocks[block] != DP_UNFROZEN_BLOCK &&
  256.                     blocks->freezeBlocks[block - 1] != DP_UNFROZEN_BLOCK)
  257.                 {
  258.                     loopPenalty = 0;
  259.                 } else {
  260.                     loopPenalty = LoopScore(block - 1, residue - prevResidue - blocks->blockSizes[block - 1]);
  261.                     if (loopPenalty == DP_POSITIVE_INFINITY)
  262.                         continue;
  263.                 }
  264.                 // get score at this position
  265.                 if (!blockScoreCalculated) {
  266.                     blockScore = BlockScore(block, residue);
  267.                     if (blockScore == DP_NEGATIVE_INFINITY)
  268.                         break;
  269.                     blockScoreCalculated = true;
  270.                 }
  271.                 // find highest sum of scores + loop score for allowed pairing of this block with previous
  272.                 sum = blockScore + matrix[block - 1][prevResidue - queryFrom].score - loopPenalty;
  273.                 if (sum > matrix[block][residue - queryFrom].score) {
  274.                     matrix[block][residue - queryFrom].score = sum;
  275.                     matrix[block][residue - queryFrom].tracebackResidue = prevResidue;
  276.                 }
  277.             }
  278.         }
  279.     }
  280.     return STRUCT_DP_OKAY;
  281. }
  282. // fill matrix values; return true on success. Matrix must have only default values when passed in.
  283. int CalculateLocalMatrix(Matrix& matrix,
  284.     const DP_BlockInfo *blocks, DP_BlockScoreFunction BlockScore,
  285.     unsigned int queryFrom, unsigned int queryTo)
  286. {
  287.     unsigned int block, residue, prevResidue, lastBlock = blocks->nBlocks - 1, tracebackResidue = 0;
  288.     int score, sum, bestPrevScore;
  289.     // find last possible block positions, based purely on block lengths
  290.     vector < unsigned int > lastPos(blocks->nBlocks);
  291.     for (block=0; block<=lastBlock; ++block) {
  292.         if (blocks->blockSizes[block] > queryTo - queryFrom + 1) {
  293.             ERROR_MESSAGE("Block " << (block+1) << " too large for this query range");
  294.             return STRUCT_DP_PARAMETER_ERROR;
  295.         }
  296.         lastPos[block] = queryTo - blocks->blockSizes[block] + 1;
  297.     }
  298.     // first row: positive scores of first block at all possible positions
  299.     for (residue=queryFrom; residue<=lastPos[0]; ++residue) {
  300.         score = BlockScore(0, residue);
  301.         matrix[0][residue - queryFrom].score = (score > 0) ? score : 0;
  302.     }
  303.     // first column: positive scores of all blocks at first positions
  304.     for (block=1; block<=lastBlock; ++block) {
  305.         score = BlockScore(block, queryFrom);
  306.         matrix[block][0].score = (score > 0) ? score : 0;
  307.     }
  308.     // for each successive block, find the best positive scoring with a previous block, if any
  309.     for (block=1; block<=lastBlock; ++block) {
  310.         for (residue=queryFrom+1; residue<=lastPos[block]; ++residue) {
  311.             // get score at this position
  312.             score = BlockScore(block, residue);
  313.             if (score == DP_NEGATIVE_INFINITY)
  314.                 continue;
  315.             // find max score of any allowed previous block
  316.             bestPrevScore = DP_NEGATIVE_INFINITY;
  317.             for (prevResidue=queryFrom; prevResidue<=lastPos[block - 1]; ++prevResidue) {
  318.                 // current block must come after the previous block
  319.                 if (residue < prevResidue + blocks->blockSizes[block - 1])
  320.                     break;
  321.                 // cut off at max loop length from previous block
  322.                 if (residue > prevResidue + blocks->blockSizes[block - 1] + blocks->maxLoops[block - 1])
  323.                     continue;
  324.                 // keep maximum score
  325.                 if (matrix[block - 1][prevResidue - queryFrom].score > bestPrevScore) {
  326.                     bestPrevScore = matrix[block - 1][prevResidue - queryFrom].score;
  327.                     tracebackResidue = prevResidue;
  328.                 }
  329.             }
  330.             // extend alignment if the sum of this block's + previous block's score is positive
  331.             if (bestPrevScore > 0 && (sum=bestPrevScore+score) > 0) {
  332.                 matrix[block][residue - queryFrom].score = sum;
  333.                 matrix[block][residue - queryFrom].tracebackResidue = tracebackResidue;
  334.             }
  335.             // otherwise, start new alignment if score is positive
  336.             else if (score > 0)
  337.                 matrix[block][residue - queryFrom].score = score;
  338.         }
  339.     }
  340.     return STRUCT_DP_OKAY;
  341. }
  342. // fill matrix values; return true on success. Matrix must have only default values when passed in.
  343. int CalculateLocalMatrixGeneric(Matrix& matrix,
  344.     const DP_BlockInfo *blocks, DP_BlockScoreFunction BlockScore, DP_LoopPenaltyFunction LoopScore,
  345.     unsigned int queryFrom, unsigned int queryTo)
  346. {
  347.     unsigned int block, residue, prevResidue, loopPenalty,
  348.         lastBlock = blocks->nBlocks - 1, tracebackResidue = 0;
  349.     int score, sum, bestPrevScore;
  350.     // find last possible block positions, based purely on block lengths
  351.     vector < unsigned int > lastPos(blocks->nBlocks);
  352.     for (block=0; block<=lastBlock; ++block) {
  353.         if (blocks->blockSizes[block] > queryTo - queryFrom + 1) {
  354.             ERROR_MESSAGE("Block " << (block+1) << " too large for this query range");
  355.             return STRUCT_DP_PARAMETER_ERROR;
  356.         }
  357.         lastPos[block] = queryTo - blocks->blockSizes[block] + 1;
  358.     }
  359.     // first row: positive scores of first block at all possible positions
  360.     for (residue=queryFrom; residue<=lastPos[0]; ++residue) {
  361.         score = BlockScore(0, residue);
  362.         matrix[0][residue - queryFrom].score = (score > 0) ? score : 0;
  363.     }
  364.     // first column: positive scores of all blocks at first positions
  365.     for (block=1; block<=lastBlock; ++block) {
  366.         score = BlockScore(block, queryFrom);
  367.         matrix[block][0].score = (score > 0) ? score : 0;
  368.     }
  369.     // for each successive block, find the best positive scoring with a previous block, if any
  370.     for (block=1; block<=lastBlock; ++block) {
  371.         for (residue=queryFrom+1; residue<=lastPos[block]; ++residue) {
  372.             // get score at this position
  373.             score = BlockScore(block, residue);
  374.             if (score == DP_NEGATIVE_INFINITY)
  375.                 continue;
  376.             // find max score of any allowed previous block
  377.             bestPrevScore = DP_NEGATIVE_INFINITY;
  378.             for (prevResidue=queryFrom; prevResidue<=lastPos[block - 1]; ++prevResidue) {
  379.                 // current block must come after the previous block
  380.                 if (residue < prevResidue + blocks->blockSizes[block - 1])
  381.                     break;
  382.                 // make sure previous block is at an allowed position
  383.                 if (matrix[block - 1][prevResidue - queryFrom].score == DP_NEGATIVE_INFINITY)
  384.                     continue;
  385.                 // get loop score
  386.                 loopPenalty = LoopScore(block - 1, residue - prevResidue - blocks->blockSizes[block - 1]);
  387.                 if (loopPenalty == DP_POSITIVE_INFINITY)
  388.                     continue;
  389.                 // keep maximum score
  390.                 sum = matrix[block - 1][prevResidue - queryFrom].score - loopPenalty;
  391.                 if (sum > bestPrevScore) {
  392.                     bestPrevScore = sum;
  393.                     tracebackResidue = prevResidue;
  394.                 }
  395.             }
  396.             // extend alignment if the sum of this block's + previous block's score is positive
  397.             if (bestPrevScore > 0 && (sum=bestPrevScore+score) > 0) {
  398.                 matrix[block][residue - queryFrom].score = sum;
  399.                 matrix[block][residue - queryFrom].tracebackResidue = tracebackResidue;
  400.             }
  401.             // otherwise, start new alignment if score is positive
  402.             else if (score > 0)
  403.                 matrix[block][residue - queryFrom].score = score;
  404.         }
  405.     }
  406.     return STRUCT_DP_OKAY;
  407. }
  408. int TracebackAlignment(const Matrix& matrix, unsigned int lastBlock, unsigned int lastBlockPos,
  409.     unsigned int queryFrom, DP_AlignmentResult *alignment)
  410. {
  411.     // trace backwards from last block/pos
  412.     vector < unsigned int > blockPositions;
  413.     unsigned int block = lastBlock, pos = lastBlockPos;
  414.     do {
  415.         blockPositions.push_back(pos);  // list is backwards after this...
  416.         pos = matrix[block][pos - queryFrom].tracebackResidue;
  417.         --block;
  418.     } while (pos != NO_TRACEBACK);
  419.     unsigned int firstBlock = block + 1; // last block traced to == first block of the alignment
  420.     // allocate and fill in alignment result structure
  421.     alignment->score = matrix[lastBlock][lastBlockPos - queryFrom].score;
  422.     alignment->firstBlock = firstBlock;
  423.     alignment->nBlocks = blockPositions.size();
  424.     alignment->blockPositions = new unsigned int[blockPositions.size()];
  425.     for (block=0; block<blockPositions.size(); ++block)
  426.         alignment->blockPositions[block] = blockPositions[lastBlock - firstBlock - block];
  427.     return STRUCT_DP_FOUND_ALIGNMENT;
  428. }
  429. int TracebackGlobalAlignment(const Matrix& matrix,
  430.     const DP_BlockInfo *blocks, unsigned int queryFrom, unsigned int queryTo,
  431.     DP_AlignmentResult **alignment)
  432. {
  433.     if (!alignment) {
  434.         ERROR_MESSAGE("TracebackGlobalAlignment() - NULL alignment handle");
  435.         return STRUCT_DP_PARAMETER_ERROR;
  436.     }
  437.     *alignment = NULL;
  438.     // find max score (e.g., best-scoring position of last block)
  439.     int score = DP_NEGATIVE_INFINITY;
  440.     unsigned int residue, lastBlockPos = 0;
  441.     for (residue=queryFrom; residue<=queryTo; ++residue) {
  442.         if (matrix[blocks->nBlocks - 1][residue - queryFrom].score > score) {
  443.             score = matrix[blocks->nBlocks - 1][residue - queryFrom].score;
  444.             lastBlockPos = residue;
  445.         }
  446.     }
  447.     if (score == DP_NEGATIVE_INFINITY) {
  448.         ERROR_MESSAGE("TracebackGlobalAlignment() - somehow failed to find any allowed global alignment");
  449.         return STRUCT_DP_ALGORITHM_ERROR;
  450.     }
  451. //    INFO_MESSAGE("Score of best global alignment: " << score);
  452.     *alignment = new DP_AlignmentResult;
  453.     return TracebackAlignment(matrix, blocks->nBlocks - 1, lastBlockPos, queryFrom, *alignment);
  454. }
  455. int TracebackLocalAlignment(const Matrix& matrix,
  456.     const DP_BlockInfo *blocks, unsigned int queryFrom, unsigned int queryTo,
  457.     DP_AlignmentResult **alignment)
  458. {
  459.     if (!alignment) {
  460.         ERROR_MESSAGE("TracebackLocalAlignment() - NULL alignment handle");
  461.         return STRUCT_DP_PARAMETER_ERROR;
  462.     }
  463.     *alignment = NULL;
  464.     // find max score (e.g., best-scoring position of any block)
  465.     int score = DP_NEGATIVE_INFINITY;
  466.     unsigned int block, residue, lastBlock = 0, lastBlockPos = 0;
  467.     for (block=0; block<blocks->nBlocks; ++block) {
  468.         for (residue=queryFrom; residue<=queryTo; ++residue) {
  469.             if (matrix[block][residue - queryFrom].score > score) {
  470.                 score = matrix[block][residue - queryFrom].score;
  471.                 lastBlock = block;
  472.                 lastBlockPos = residue;
  473.             }
  474.         }
  475.     }
  476.     if (score <= 0) {
  477. //        INFO_MESSAGE("No positive-scoring local alignment found.");
  478.         return STRUCT_DP_NO_ALIGNMENT;
  479.     }
  480. //    INFO_MESSAGE("Score of best local alignment: " << score);
  481.     *alignment = new DP_AlignmentResult;
  482.     return TracebackAlignment(matrix, lastBlock, lastBlockPos, queryFrom, *alignment);
  483. }
  484. typedef struct {
  485.     unsigned int block;
  486.     unsigned int residue;
  487. } Traceback;
  488. int TracebackMultipleLocalAlignments(const Matrix& matrix,
  489.     const DP_BlockInfo *blocks, unsigned int queryFrom, unsigned int queryTo,
  490.     DP_MultipleAlignmentResults **alignments, unsigned int maxAlignments)
  491. {
  492.     if (!alignments) {
  493.         ERROR_MESSAGE("TracebackMultipleLocalAlignments() - NULL alignments handle");
  494.         return STRUCT_DP_PARAMETER_ERROR;
  495.     }
  496.     *alignments = NULL;
  497.     unsigned int block, residue;
  498.     vector < vector < bool > > usedCells(blocks->nBlocks);
  499.     for (block=0; block<blocks->nBlocks; ++block)
  500.         usedCells[block].resize(queryTo - queryFrom + 1, false);
  501.     // find N max scores
  502.     list < Traceback > tracebacks;
  503.     while (maxAlignments == 0 || tracebacks.size() < maxAlignments) {
  504.         // find next best scoring cell that's not part of an alignment already reported
  505.         int score = DP_NEGATIVE_INFINITY;
  506.         unsigned int lastBlock = 0, lastBlockPos = 0;
  507.         for (block=0; block<blocks->nBlocks; ++block) {
  508.             for (residue=queryFrom; residue<=queryTo; ++residue) {
  509.                 if (!usedCells[block][residue - queryFrom] &&
  510.                     matrix[block][residue - queryFrom].score > score)
  511.                 {
  512.                     score = matrix[block][residue - queryFrom].score;
  513.                     lastBlock = block;
  514.                     lastBlockPos = residue;
  515.                 }
  516.             }
  517.         }
  518.         if (score <= 0)
  519.             break;
  520.         // mark cells of this alignment as used, and see if any part of this alignment
  521.         // has been reported before
  522.         block = lastBlock;
  523.         residue = lastBlockPos;
  524.         bool repeated = false;
  525.         do {
  526.             if (usedCells[block][residue - queryFrom]) {
  527.                 repeated = true;
  528.                 break;
  529.             } else {
  530.                 usedCells[block][residue - queryFrom] = true;
  531.             }
  532.             residue = matrix[block][residue - queryFrom].tracebackResidue;
  533.             --block;
  534.         } while (residue != NO_TRACEBACK);
  535.         if (repeated)
  536.             continue;
  537.         // add traceback start to list
  538.         tracebacks.resize(tracebacks.size() + 1);
  539.         tracebacks.back().block = lastBlock;
  540.         tracebacks.back().residue = lastBlockPos;
  541.     }
  542.     if (tracebacks.size() == 0) {
  543. //        INFO_MESSAGE("No positive-scoring local alignment found.");
  544.         return STRUCT_DP_NO_ALIGNMENT;
  545.     }
  546.     // allocate result structure
  547.     *alignments = new DP_MultipleAlignmentResults;
  548.     (*alignments)->nAlignments = 0;
  549.     (*alignments)->alignments = new DP_AlignmentResult[tracebacks.size()];
  550.     unsigned int a;
  551.     for (a=0; a<tracebacks.size(); ++a)
  552.         (*alignments)->alignments[a].blockPositions = NULL;
  553.     // fill in results from tracebacks
  554.     list < Traceback >::const_iterator t, te = tracebacks.end();
  555.     for (t=tracebacks.begin(), a=0; t!=te; ++t, ++a) {
  556.         if (TracebackAlignment(matrix, t->block, t->residue, queryFrom, &((*alignments)->alignments[a]))
  557.                 == STRUCT_DP_FOUND_ALIGNMENT)
  558.         {
  559.             ++((*alignments)->nAlignments);
  560. //            if (a == 0)
  561. //                INFO_MESSAGE("Score of best local alignment: " << (*alignments)->alignments[a].score);
  562. //            else
  563. //                INFO_MESSAGE("Score of next local alignment: " << (*alignments)->alignments[a].score);
  564.         } else
  565.             return STRUCT_DP_ALGORITHM_ERROR;
  566.     }
  567.     return STRUCT_DP_FOUND_ALIGNMENT;
  568. }
  569. END_SCOPE(struct_dp)
  570. // leave the C-called functions outside any namespace, just in case that might
  571. // cause any problems when linking to C code...
  572. USING_SCOPE(struct_dp);
  573. int DP_GlobalBlockAlign(
  574.     const DP_BlockInfo *blocks, DP_BlockScoreFunction BlockScore,
  575.     unsigned int queryFrom, unsigned int queryTo,
  576.     DP_AlignmentResult **alignment)
  577. {
  578.     if (!blocks || blocks->nBlocks < 1 || !blocks->blockSizes || !BlockScore || queryTo < queryFrom) {
  579.         ERROR_MESSAGE("DP_GlobalBlockAlign() - invalid parameters");
  580.         return STRUCT_DP_PARAMETER_ERROR;
  581.     }
  582.     unsigned int i, sumBlockLen = 0;
  583.     for (i=0; i<blocks->nBlocks; ++i)
  584.         sumBlockLen += blocks->blockSizes[i];
  585.     if (sumBlockLen > queryTo - queryFrom + 1) {
  586.         ERROR_MESSAGE("DP_GlobalBlockAlign() - sum of block lengths longer than query region");
  587.         return STRUCT_DP_PARAMETER_ERROR;
  588.     }
  589.     int status = ValidateFrozenBlockPositions(blocks, queryFrom, queryTo, true);
  590.     if (status != STRUCT_DP_OKAY) {
  591.         ERROR_MESSAGE("DP_GlobalBlockAlign() - ValidateFrozenBlockPositions() returned error");
  592.         return status;
  593.     }
  594.     Matrix matrix(blocks->nBlocks, queryTo - queryFrom + 1);
  595.     status = CalculateGlobalMatrix(matrix, blocks, BlockScore, queryFrom, queryTo);
  596.     if (status != STRUCT_DP_OKAY) {
  597.         ERROR_MESSAGE("DP_GlobalBlockAlign() - CalculateGlobalMatrix() failed");
  598.         return status;
  599.     }
  600.     return TracebackGlobalAlignment(matrix, blocks, queryFrom, queryTo, alignment);
  601. }
  602. int DP_GlobalBlockAlignGeneric(
  603.     const DP_BlockInfo *blocks,
  604.     DP_BlockScoreFunction BlockScore, DP_LoopPenaltyFunction LoopScore,
  605.     unsigned int queryFrom, unsigned int queryTo,
  606.     DP_AlignmentResult **alignment)
  607. {
  608.     if (!blocks || blocks->nBlocks < 1 || !blocks->blockSizes || queryTo < queryFrom ||
  609.             !BlockScore || !LoopScore) {
  610.         ERROR_MESSAGE("DP_GlobalBlockAlignGeneric() - invalid parameters");
  611.         return STRUCT_DP_PARAMETER_ERROR;
  612.     }
  613.     unsigned int i, sumBlockLen = 0;
  614.     for (i=0; i<blocks->nBlocks; ++i)
  615.         sumBlockLen += blocks->blockSizes[i];
  616.     if (sumBlockLen > queryTo - queryFrom + 1) {
  617.         ERROR_MESSAGE("DP_GlobalBlockAlignGeneric() - sum of block lengths longer than query region");
  618.         return STRUCT_DP_PARAMETER_ERROR;
  619.     }
  620.     int status = ValidateFrozenBlockPositions(blocks, queryFrom, queryTo, false);
  621.     if (status != STRUCT_DP_OKAY) {
  622.         ERROR_MESSAGE("DP_GlobalBlockAlignGeneric() - ValidateFrozenBlockPositions() returned error");
  623.         return status;
  624.     }
  625.     Matrix matrix(blocks->nBlocks, queryTo - queryFrom + 1);
  626.     status = CalculateGlobalMatrixGeneric(matrix, blocks, BlockScore, LoopScore, queryFrom, queryTo);
  627.     if (status != STRUCT_DP_OKAY) {
  628.         ERROR_MESSAGE("DP_GlobalBlockAlignGeneric() - CalculateGlobalMatrixGeneric() failed");
  629.         return status;
  630.     }
  631.     return TracebackGlobalAlignment(matrix, blocks, queryFrom, queryTo, alignment);
  632. }
  633. int DP_LocalBlockAlign(
  634.     const DP_BlockInfo *blocks, DP_BlockScoreFunction BlockScore,
  635.     unsigned int queryFrom, unsigned int queryTo,
  636.     DP_AlignmentResult **alignment)
  637. {
  638.     if (!blocks || blocks->nBlocks < 1 || !blocks->blockSizes || !BlockScore || queryTo < queryFrom) {
  639.         ERROR_MESSAGE("DP_LocalBlockAlign() - invalid parameters");
  640.         return STRUCT_DP_PARAMETER_ERROR;
  641.     }
  642.     for (unsigned int block=0; block<blocks->nBlocks; ++block) {
  643.         if (blocks->freezeBlocks[block] != DP_UNFROZEN_BLOCK) {
  644.             WARNING_MESSAGE("DP_LocalBlockAlign() - frozen block specifications are ignored...");
  645.             break;
  646.         }
  647.     }
  648.     Matrix matrix(blocks->nBlocks, queryTo - queryFrom + 1);
  649.     int status = CalculateLocalMatrix(matrix, blocks, BlockScore, queryFrom, queryTo);
  650.     if (status != STRUCT_DP_OKAY) {
  651.         ERROR_MESSAGE("DP_LocalBlockAlign() - CalculateLocalMatrix() failed");
  652.         return status;
  653.     }
  654.     return TracebackLocalAlignment(matrix, blocks, queryFrom, queryTo, alignment);
  655. }
  656. int DP_LocalBlockAlignGeneric(
  657.     const DP_BlockInfo *blocks, DP_BlockScoreFunction BlockScore, DP_LoopPenaltyFunction LoopScore,
  658.     unsigned int queryFrom, unsigned int queryTo,
  659.     DP_AlignmentResult **alignment)
  660. {
  661.     if (!blocks || blocks->nBlocks < 1 || !blocks->blockSizes || !BlockScore || queryTo < queryFrom) {
  662.         ERROR_MESSAGE("DP_LocalBlockAlignGeneric() - invalid parameters");
  663.         return STRUCT_DP_PARAMETER_ERROR;
  664.     }
  665.     for (unsigned int block=0; block<blocks->nBlocks; ++block) {
  666.         if (blocks->freezeBlocks[block] != DP_UNFROZEN_BLOCK) {
  667.             WARNING_MESSAGE("DP_LocalBlockAlignGeneric() - frozen block specifications are ignored...");
  668.             break;
  669.         }
  670.     }
  671.     Matrix matrix(blocks->nBlocks, queryTo - queryFrom + 1);
  672.     int status = CalculateLocalMatrixGeneric(matrix, blocks, BlockScore, LoopScore, queryFrom, queryTo);
  673.     if (status != STRUCT_DP_OKAY) {
  674.         ERROR_MESSAGE("DP_LocalBlockAlignGeneric() - CalculateLocalMatrixGeneric() failed");
  675.         return status;
  676.     }
  677.     return TracebackLocalAlignment(matrix, blocks, queryFrom, queryTo, alignment);
  678. }
  679. int DP_MultipleLocalBlockAlign(
  680.     const DP_BlockInfo *blocks, DP_BlockScoreFunction BlockScore,
  681.     unsigned int queryFrom, unsigned int queryTo,
  682.     DP_MultipleAlignmentResults **alignments, unsigned int maxAlignments)
  683. {
  684.     if (!blocks || blocks->nBlocks < 1 || !blocks->blockSizes || !BlockScore || queryTo < queryFrom) {
  685.         ERROR_MESSAGE("DP_MultipleLocalBlockAlign() - invalid parameters");
  686.         return STRUCT_DP_PARAMETER_ERROR;
  687.     }
  688.     for (unsigned int block=0; block<blocks->nBlocks; ++block) {
  689.         if (blocks->freezeBlocks[block] != DP_UNFROZEN_BLOCK) {
  690.             WARNING_MESSAGE("DP_MultipleLocalBlockAlign() - frozen block specifications are ignored...");
  691.             break;
  692.         }
  693.     }
  694.     Matrix matrix(blocks->nBlocks, queryTo - queryFrom + 1);
  695.     int status = CalculateLocalMatrix(matrix, blocks, BlockScore, queryFrom, queryTo);
  696.     if (status != STRUCT_DP_OKAY) {
  697.         ERROR_MESSAGE("DP_MultipleLocalBlockAlign() - CalculateLocalMatrix() failed");
  698.         return status;
  699.     }
  700.     return TracebackMultipleLocalAlignments(matrix, blocks, queryFrom, queryTo, alignments, maxAlignments);
  701. }
  702. int DP_MultipleLocalBlockAlignGeneric(
  703.     const DP_BlockInfo *blocks, DP_BlockScoreFunction BlockScore, DP_LoopPenaltyFunction LoopScore,
  704.     unsigned int queryFrom, unsigned int queryTo,
  705.     DP_MultipleAlignmentResults **alignments, unsigned int maxAlignments)
  706. {
  707.     if (!blocks || blocks->nBlocks < 1 || !blocks->blockSizes || !BlockScore || queryTo < queryFrom) {
  708.         ERROR_MESSAGE("DP_MultipleLocalBlockAlignGeneric() - invalid parameters");
  709.         return STRUCT_DP_PARAMETER_ERROR;
  710.     }
  711.     for (unsigned int block=0; block<blocks->nBlocks; ++block) {
  712.         if (blocks->freezeBlocks[block] != DP_UNFROZEN_BLOCK) {
  713.             WARNING_MESSAGE("DP_MultipleLocalBlockAlignGeneric() - frozen block specifications are ignored...");
  714.             break;
  715.         }
  716.     }
  717.     Matrix matrix(blocks->nBlocks, queryTo - queryFrom + 1);
  718.     int status = CalculateLocalMatrixGeneric(matrix, blocks, BlockScore, LoopScore, queryFrom, queryTo);
  719.     if (status != STRUCT_DP_OKAY) {
  720.         ERROR_MESSAGE("DP_MultipleLocalBlockAlignGeneric() - CalculateLocalMatrixGeneric() failed");
  721.         return status;
  722.     }
  723.     return TracebackMultipleLocalAlignments(matrix, blocks, queryFrom, queryTo, alignments, maxAlignments);
  724. }
  725. DP_BlockInfo * DP_CreateBlockInfo(unsigned int nBlocks)
  726. {
  727.     DP_BlockInfo *blocks = new DP_BlockInfo;
  728.     blocks->nBlocks = nBlocks;
  729.     blocks->blockPositions = new unsigned int[nBlocks];
  730.     blocks->blockSizes = new unsigned int[nBlocks];
  731.     blocks->maxLoops = new unsigned int[nBlocks - 1];
  732.     blocks->freezeBlocks = new unsigned int[nBlocks];
  733.     for (unsigned int i=0; i<nBlocks; ++i)
  734.         blocks->freezeBlocks[i] = DP_UNFROZEN_BLOCK;
  735.     return blocks;
  736. }
  737. void DP_DestroyBlockInfo(DP_BlockInfo *blocks)
  738. {
  739.     if (!blocks)
  740.         return;
  741.     delete[] blocks->blockPositions;
  742.     delete[] blocks->blockSizes;
  743.     delete[] blocks->maxLoops;
  744.     delete[] blocks->freezeBlocks;
  745.     delete blocks;
  746. }
  747. void DP_DestroyAlignmentResult(DP_AlignmentResult *alignment)
  748. {
  749.     if (!alignment)
  750.         return;
  751.     delete[] alignment->blockPositions;
  752.     delete alignment;
  753. }
  754. void DP_DestroyMultipleAlignmentResults(DP_MultipleAlignmentResults *alignments)
  755. {
  756.     if (!alignments) return;
  757.     for (unsigned int i=0; i<alignments->nAlignments; ++i)
  758.         if (alignments->alignments[i].blockPositions)
  759.             delete[] alignments->alignments[i].blockPositions;
  760.     delete[] alignments->alignments;
  761.     delete alignments;
  762. }
  763. unsigned int DP_CalculateMaxLoopLength(
  764.         unsigned int nLoops, const unsigned int *loops,
  765.         double percentile, unsigned int extension, unsigned int cutoff)
  766. {
  767.     vector < unsigned int > loopLengths(nLoops);
  768.     unsigned int index, max;
  769.     for (index=0; index<nLoops; ++index)
  770.         loopLengths[index] = loops[index];
  771.     stable_sort(loopLengths.begin(), loopLengths.end());
  772.     if (percentile < 1.0) {
  773.         index = (unsigned int)(percentile * (nLoops - 1) + 0.5);
  774.         max = loopLengths[index] + extension;
  775.     } else {  // percentile >= 1.0
  776.         max = ((unsigned int)(percentile * loopLengths[nLoops - 1] + 0.5)) + extension;
  777.     }
  778.     if (cutoff > 0 && max > cutoff)
  779.         max = cutoff;
  780.     return max;
  781. }
  782. /*
  783. * ---------------------------------------------------------------------------
  784. * $Log: block_align.cpp,v $
  785. * Revision 1000.2  2004/06/01 18:11:09  gouriano
  786. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.20
  787. *
  788. * Revision 1.20  2004/05/21 21:41:04  gorelenk
  789. * Added PCH ncbi_pch.hpp
  790. *
  791. * Revision 1.19  2004/03/15 18:54:57  thiessen
  792. * prefer prefix vs. postfix ++/-- operators
  793. *
  794. * Revision 1.18  2004/02/19 02:21:19  thiessen
  795. * fix struct_dp paths
  796. *
  797. * Revision 1.17  2003/12/19 14:37:50  thiessen
  798. * add local generic loop function alignment routines
  799. *
  800. * Revision 1.16  2003/12/08 16:33:58  thiessen
  801. * fix signed/unsigned mix
  802. *
  803. * Revision 1.15  2003/12/08 16:21:35  thiessen
  804. * add generic loop scoring function interface
  805. *
  806. * Revision 1.14  2003/09/07 01:11:25  thiessen
  807. * fix small memory leak
  808. *
  809. * Revision 1.13  2003/09/07 00:06:19  thiessen
  810. * add multiple tracebacks for local alignments
  811. *
  812. * Revision 1.12  2003/08/23 22:10:05  thiessen
  813. * fix local alignment block edge bug
  814. *
  815. * Revision 1.11  2003/08/22 14:28:49  thiessen
  816. * add standard loop calculating function
  817. *
  818. * Revision 1.10  2003/08/19 19:36:48  thiessen
  819. * avoid annoying 'might be used uninitialized' warnings
  820. *
  821. * Revision 1.9  2003/08/19 19:26:21  thiessen
  822. * error if block size > query range length
  823. *
  824. * Revision 1.8  2003/07/11 15:27:48  thiessen
  825. * add DP_ prefix to globals
  826. *
  827. * Revision 1.7  2003/06/22 12:18:16  thiessen
  828. * fixes for unsigned/signed comparison
  829. *
  830. * Revision 1.6  2003/06/22 12:11:37  thiessen
  831. * add local alignment
  832. *
  833. * Revision 1.5  2003/06/19 13:48:23  thiessen
  834. * cosmetic/typo fixes
  835. *
  836. * Revision 1.4  2003/06/18 21:55:15  thiessen
  837. * remove unused params
  838. *
  839. * Revision 1.3  2003/06/18 21:46:09  thiessen
  840. * add traceback, alignment return structure
  841. *
  842. * Revision 1.2  2003/06/18 19:10:17  thiessen
  843. * fix lf issues
  844. *
  845. * Revision 1.1  2003/06/18 16:54:12  thiessen
  846. * initial checkin; working global block aligner and demo app
  847. *
  848. */