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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: su_block_multiple_alignment.cpp,v $
  4.  * PRODUCTION Revision 1000.0  2004/06/01 18:14:28  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.9
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: su_block_multiple_alignment.cpp,v 1000.0 2004/06/01 18:14:28 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. *      Classes to hold alignment data
  38. *
  39. * ===========================================================================
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <corelib/ncbistd.hpp>
  43. #include <corelib/ncbi_limits.hpp>
  44. #include <util/tables/raw_scoremat.h>
  45. #include <objects/seqalign/Dense_diag.hpp>
  46. #include "su_block_multiple_alignment.hpp"
  47. #include "su_sequence_set.hpp"
  48. #include "su_private.hpp"
  49. // C-toolkit stuff for PSSM calculation
  50. #include <objalign.h>
  51. #include <blast.h>
  52. #include <blastkar.h>
  53. #include <cddutil.h>
  54. #include <thrdatd.h>
  55. #include <thrddecl.h>
  56. USING_NCBI_SCOPE;
  57. USING_SCOPE(objects);
  58. BEGIN_SCOPE(struct_util)
  59. // from su_sequence_set.cpp
  60. extern BioseqPtr GetOrCreateBioseq(const Sequence *sequence);
  61. extern void AddCSeqId(SeqIdPtr *sid, const ncbi::objects::CSeq_id& cppid);
  62. static const int SCALING_FACTOR = 1000000;
  63. static const string ThreaderResidues = "ARNDCQEGHILKMFPSTWYV";
  64. static const string BLASTResidues = "-ABCDEFGHIKLMNPQRSTVWXYZU*";
  65. BlockMultipleAlignment::BlockMultipleAlignment(const SequenceList& sequenceList)
  66. {
  67.     m_sequences = sequenceList;
  68.     m_pssm = NULL;
  69.     InitCache();
  70.     m_rowDoubles.resize(m_sequences.size(), 0.0);
  71.     m_rowStrings.resize(m_sequences.size());
  72. }
  73. void BlockMultipleAlignment::InitCache(void)
  74. {
  75.     m_cachePrevRow = eUndefined;
  76.     m_cachePrevBlock = NULL;
  77.     m_cacheBlockIterator = m_blocks.begin();
  78. }
  79. BlockMultipleAlignment::~BlockMultipleAlignment(void)
  80. {
  81.     RemovePSSM();
  82. }
  83. BlockMultipleAlignment * BlockMultipleAlignment::Clone(void) const
  84. {
  85.     BlockMultipleAlignment *copy = new BlockMultipleAlignment(m_sequences);
  86.     BlockList::const_iterator b, be = m_blocks.end();
  87.     for (b=m_blocks.begin(); b!=be; ++b)
  88.         copy->m_blocks.push_back(CRef<Block>((*b)->Clone(copy)));
  89.     copy->UpdateBlockMap();
  90.     copy->m_rowDoubles = m_rowDoubles;
  91.     copy->m_rowStrings = m_rowStrings;
  92.     return copy;
  93. }
  94. static inline unsigned int ScreenResidueCharacter(char original)
  95. {
  96.     char ch = toupper(original);
  97.     switch (ch) {
  98.         case 'A': case 'R': case 'N': case 'D': case 'C':
  99.         case 'Q': case 'E': case 'G': case 'H': case 'I':
  100.         case 'L': case 'K': case 'M': case 'F': case 'P':
  101.         case 'S': case 'T': case 'W': case 'Y': case 'V':
  102.         case 'B': case 'Z':
  103.             break;
  104.         default:
  105.             ch = 'X'; // make all but natural aa's just 'X'
  106.     }
  107.     return ch;
  108. }
  109. static int GetBLOSUM62Score(char a, char b)
  110. {
  111.     static SNCBIFullScoreMatrix Blosum62Matrix;
  112.     static bool unpacked = false;
  113.     if (!unpacked) {
  114.         NCBISM_Unpack(&NCBISM_Blosum62, &Blosum62Matrix);
  115.         unpacked = true;
  116.     }
  117.     return Blosum62Matrix.s[ScreenResidueCharacter(a)][ScreenResidueCharacter(b)];
  118. }
  119. // creates a SeqAlign from a BlockMultipleAlignment
  120. static SeqAlignPtr CreateCSeqAlign(const BlockMultipleAlignment& multiple)
  121. {
  122.     // one SeqAlign (chained into a linked list) for each slave row
  123.     SeqAlignPtr prevSap = NULL, firstSap = NULL;
  124.     for (unsigned int row=1; row<multiple.NRows(); ++row) {
  125.         SeqAlignPtr sap = SeqAlignNew();
  126.         if (prevSap) prevSap->next = sap;
  127.         prevSap = sap;
  128.         if (!firstSap) firstSap = sap;
  129.         sap->type = SAT_PARTIAL;
  130.         sap->dim = 2;
  131.         sap->segtype = SAS_DENDIAG;
  132.         DenseDiagPtr prevDd = NULL;
  133.         BlockMultipleAlignment::UngappedAlignedBlockList blocks;
  134.         multiple.GetUngappedAlignedBlocks(&blocks);
  135.         BlockMultipleAlignment::UngappedAlignedBlockList::const_iterator b, be = blocks.end();
  136.         for (b=blocks.begin(); b!=be; ++b) {
  137.             DenseDiagPtr dd = DenseDiagNew();
  138.             if (prevDd) prevDd->next = dd;
  139.             prevDd = dd;
  140.             if (b == blocks.begin()) sap->segs = dd;
  141.             dd->dim = 2;
  142.             AddCSeqId(&(dd->id), multiple.GetSequenceOfRow(0)->GetPreferredIdentifier());
  143.             AddCSeqId(&(dd->id), multiple.GetSequenceOfRow(row)->GetPreferredIdentifier());
  144.             dd->len = (*b)->m_width;
  145.             dd->starts = (Int4Ptr) MemNew(2 * sizeof(Int4));
  146.             const Block::Range *range = (*b)->GetRangeOfRow(0);
  147.             dd->starts[0] = range->from;
  148.             range = (*b)->GetRangeOfRow(row);
  149.             dd->starts[1] = range->from;
  150.         }
  151.     }
  152.     return firstSap;
  153. }
  154. static void CreateAllBioseqs(const BlockMultipleAlignment& multiple)
  155. {
  156.     for (unsigned int row=0; row<multiple.NRows(); ++row)
  157.         GetOrCreateBioseq(multiple.GetSequenceOfRow(row));
  158. }
  159. static Seq_Mtf * CreateSeqMtf(const BlockMultipleAlignment& multiple,
  160.     double weightPSSM, BLAST_KarlinBlkPtr karlinBlock)
  161. {
  162.     // special case for "PSSM" of single-row "alignment" - just use BLOSUM62 score
  163.     if (multiple.NRows() == 1) {
  164.         Seq_Mtf *seqMtf = NewSeqMtf(multiple.GetMaster()->Length(), ThreaderResidues.size());
  165.         for (unsigned int res=0; res<multiple.GetMaster()->Length(); ++res)
  166.             for (unsigned int aa=0; aa<ThreaderResidues.size(); ++aa)
  167.                 seqMtf->ww[res][aa] = ThrdRound(weightPSSM * SCALING_FACTOR *
  168.                     GetBLOSUM62Score(multiple.GetMaster()->m_sequenceString[res], ThreaderResidues[aa]));
  169.         WARNING_MESSAGE("Created Seq_Mtf (PSSM) from BLOSUM62 scores");
  170.         return seqMtf;
  171.     }
  172.     // convert all sequences to Bioseqs
  173.     CreateAllBioseqs(multiple);
  174.     // create SeqAlign from this BlockMultipleAlignment
  175.     SeqAlignPtr seqAlign = CreateCSeqAlign(multiple);
  176.     // "spread" unaligned residues between aligned blocks, for PSSM construction
  177.     CddDegapSeqAlign(seqAlign);
  178.     Seq_Mtf *seqMtf = NULL;
  179.     for (int i=11; i>=1; --i) {
  180.         // first try auto-determined pseudocount (-1); if fails, find higest <= 10 that works
  181.         int pseudocount = (i == 11) ? -1 : i;
  182.         seqMtf = CddDenDiagCposComp2KBP(
  183.             GetOrCreateBioseq(multiple.GetMaster()),
  184.             pseudocount,
  185.             seqAlign,
  186.             NULL,
  187.             NULL,
  188.             weightPSSM,
  189.             SCALING_FACTOR,
  190.             NULL,
  191.             karlinBlock
  192.         );
  193.         if (seqMtf)
  194.             break;
  195.         else
  196.             WARNING_MESSAGE("Cannot use " << ((pseudocount == -1) ? "(empirical) " : "")
  197.                 << "pseudocount of " << pseudocount);
  198.     }
  199.     if (seqMtf)
  200.         TRACE_MESSAGE("created Seq_Mtf (PSSM)");
  201.     else
  202.         ERROR_MESSAGE("Cannot find any pseudocount that yields an acceptable PSSM!");
  203.     SeqAlignSetFree(seqAlign);
  204.     return seqMtf;
  205. }
  206. // gives BLAST residue number for a character (or # for 'X' if char not found)
  207. int LookupBLASTResidueNumberFromCharacter(unsigned char r)
  208. {
  209.     typedef map < unsigned char, int > Char2Int;
  210.     static Char2Int charMap;
  211.     if (charMap.size() == 0) {
  212.         for (unsigned int i=0; i<BLASTResidues.size(); ++i)
  213.             charMap[BLASTResidues[i]] = i;
  214.     }
  215.     Char2Int::const_iterator n = charMap.find(toupper(r));
  216.     if (n != charMap.end())
  217.         return n->second;
  218.     else
  219.         return charMap.find('X')->second;
  220. }
  221. // gives BLAST residue number for a threader residue number (or # for 'X' if char == -1)
  222. static int LookupBLASTResidueNumberFromThreaderResidueNumber(unsigned char r)
  223. {
  224.     r = toupper(r);
  225.     return LookupBLASTResidueNumberFromCharacter(
  226.             (r < ThreaderResidues.size()) ? ThreaderResidues[r] : 'X');
  227. }
  228. static Int4 Round(double d)
  229. {
  230.     if (d >= 0.0)
  231.         return (Int4) (d + 0.5);
  232.     else
  233.         return (Int4) (d - 0.5);
  234. }
  235. const BLAST_Matrix * BlockMultipleAlignment::GetPSSM(void) const
  236. {
  237.     if (m_pssm) return m_pssm;
  238.     // for now, use threader's SeqMtf
  239.     BLAST_KarlinBlkPtr karlinBlock = BlastKarlinBlkCreate();
  240.     Seq_Mtf *seqMtf = CreateSeqMtf(*this, 1.0, karlinBlock);
  241.     m_pssm = (BLAST_Matrix *) MemNew(sizeof(BLAST_Matrix));
  242.     m_pssm->is_prot = TRUE;
  243.     m_pssm->name = StringSave("BLOSUM62");
  244.     m_pssm->karlinK = karlinBlock->K;
  245.     m_pssm->rows = seqMtf->n + 1;
  246.     m_pssm->columns = 26;
  247.     int i, j;
  248.     m_pssm->matrix = (Int4 **) MemNew(m_pssm->rows * sizeof(Int4 *));
  249.     for (i=0; i<m_pssm->rows; ++i) {
  250.         m_pssm->matrix[i] = (Int4 *) MemNew(m_pssm->columns * sizeof(Int4));
  251.         // set scores from threader matrix
  252.         if (i < seqMtf->n) {
  253.             // initialize all rows with custom score, or BLAST_SCORE_MIN; to match what Aron's function creates
  254.             for (j=0; j<m_pssm->columns; ++j)
  255.                 m_pssm->matrix[i][j] = (j == 21 ? -1 : (j == 25 ? -4 : BLAST_SCORE_MIN));
  256.             for (j=0; j<seqMtf->AlphabetSize; ++j) {
  257.                 m_pssm->matrix[i][LookupBLASTResidueNumberFromThreaderResidueNumber(j)] =
  258.                     Round(((double) seqMtf->ww[i][j]) / SCALING_FACTOR);
  259.             }
  260.         } else {
  261.             // initialize last row with BLAST_SCORE_MIN
  262.             for (j=0; j<m_pssm->columns; ++j)
  263.                 m_pssm->matrix[i][j] = BLAST_SCORE_MIN;
  264.         }
  265.     }
  266.     m_pssm->posFreqs = NULL;
  267.     FreeSeqMtf(seqMtf);
  268.     BlastKarlinBlkDestruct(karlinBlock);
  269.     return m_pssm;
  270. }
  271. void BlockMultipleAlignment::RemovePSSM(void) const
  272. {
  273.     if (m_pssm) {
  274.         BLAST_MatrixDestruct(m_pssm);
  275.         m_pssm = NULL;
  276.     }
  277. }
  278. bool BlockMultipleAlignment::CheckAlignedBlock(const Block *block) const
  279. {
  280.     if (!block || !block->IsAligned()) {
  281.         ERROR_MESSAGE("CheckAlignedBlock() - checks aligned blocks only");
  282.         return false;
  283.     }
  284.     if (block->NSequences() != m_sequences.size()) {
  285.         ERROR_MESSAGE("CheckAlignedBlock() - block size mismatch");
  286.         return false;
  287.     }
  288.     // make sure ranges are reasonable for each sequence
  289.     unsigned int row;
  290.     const Block
  291.         *prevBlock = GetBlockBefore(block),
  292.         *nextBlock = GetBlockAfter(block);
  293.     const Block::Range *range, *prevRange = NULL, *nextRange = NULL;
  294.     SequenceList::const_iterator sequence = m_sequences.begin();
  295.     for (row=0; row<block->NSequences(); ++row, ++sequence) {
  296.         range = block->GetRangeOfRow(row);
  297.         if (prevBlock) prevRange = prevBlock->GetRangeOfRow(row);
  298.         if (nextBlock) nextRange = nextBlock->GetRangeOfRow(row);
  299.         if (range->to - range->from + 1 != block->m_width ||       // check block m_width
  300.             (prevRange && range->from <= prevRange->to) ||          // check for range overlap
  301.             (nextRange && range->to >= nextRange->from) ||          // check for range overlap
  302.             range->from > range->to ||                              // check range values
  303.             range->to >= (*sequence)->Length())                     // check bounds of end
  304.         {
  305.             ERROR_MESSAGE("CheckAlignedBlock() - range error");
  306.             return false;
  307.         }
  308.     }
  309.     return true;
  310. }
  311. bool BlockMultipleAlignment::AddAlignedBlockAtEnd(UngappedAlignedBlock *newBlock)
  312. {
  313.     m_blocks.push_back(CRef<Block>(newBlock));
  314.     return CheckAlignedBlock(newBlock);
  315. }
  316. UnalignedBlock * BlockMultipleAlignment::
  317.     CreateNewUnalignedBlockBetween(const Block *leftBlock, const Block *rightBlock)
  318. {
  319.     if ((leftBlock && !leftBlock->IsAligned()) ||
  320.         (rightBlock && !rightBlock->IsAligned())) {
  321.         ERROR_MESSAGE("CreateNewUnalignedBlockBetween() - passed an unaligned block");
  322.         return NULL;
  323.     }
  324.     unsigned int row, from, to, length;
  325.     SequenceList::const_iterator s, se = m_sequences.end();
  326.     UnalignedBlock *newBlock = new UnalignedBlock(this);
  327.     newBlock->m_width = 0;
  328.     for (row=0, s=m_sequences.begin(); s!=se; ++row, ++s) {
  329.         if (leftBlock)
  330.             from = leftBlock->GetRangeOfRow(row)->to + 1;
  331.         else
  332.             from = 0;
  333.         if (rightBlock)
  334.             to = rightBlock->GetRangeOfRow(row)->from - 1;
  335.         else
  336.             to = (*s)->Length() - 1;
  337.         newBlock->SetRangeOfRow(row, from, to);
  338.         length = to - from + 1;
  339.         if ((to - from + 1) < 0) { // just to make sure...
  340.             ERROR_MESSAGE("CreateNewUnalignedBlockBetween() - unaligned length < 0");
  341.             return NULL;
  342.         }
  343.         if (length > newBlock->m_width)
  344.             newBlock->m_width = length;
  345.     }
  346.     if (newBlock->m_width == 0) {
  347.         delete newBlock;
  348.         return NULL;
  349.     } else
  350.         return newBlock;
  351. }
  352. bool BlockMultipleAlignment::AddUnalignedBlocks(void)
  353. {
  354.     BlockList::iterator a, ae = m_blocks.end();
  355.     const Block *alignedBlock = NULL, *prevAlignedBlock = NULL;
  356.     Block *newUnalignedBlock;
  357.     // unaligned m_blocks to the left of each aligned block
  358.     for (a=m_blocks.begin(); a!=ae; ++a) {
  359.         alignedBlock = *a;
  360.         newUnalignedBlock = CreateNewUnalignedBlockBetween(prevAlignedBlock, alignedBlock);
  361.         if (newUnalignedBlock)
  362.             m_blocks.insert(a, CRef<Block>(newUnalignedBlock));
  363.         prevAlignedBlock = alignedBlock;
  364.     }
  365.     // right tail
  366.     newUnalignedBlock = CreateNewUnalignedBlockBetween(alignedBlock, NULL);
  367.     if (newUnalignedBlock) {
  368.         m_blocks.insert(a, CRef<Block>(newUnalignedBlock));
  369.     }
  370.     return true;
  371. }
  372. bool BlockMultipleAlignment::UpdateBlockMap(bool clearRowInfo)
  373. {
  374.     unsigned int i = 0, j, n = 0;
  375.     BlockList::iterator b, be = m_blocks.end();
  376.     // reset old stuff, recalculate m_width
  377.     m_totalWidth = 0;
  378.     for (b=m_blocks.begin(); b!=be; ++b)
  379.         m_totalWidth += (*b)->m_width;
  380.     // fill out the block map
  381.     m_blockMap.resize(m_totalWidth);
  382.     UngappedAlignedBlock *aBlock;
  383.     for (b=m_blocks.begin(); b!=be; ++b) {
  384.         aBlock = dynamic_cast<UngappedAlignedBlock*>(b->GetPointer());
  385.         if (aBlock)
  386.             ++n;
  387.         for (j=0; j<(*b)->m_width; ++j, ++i) {
  388.             m_blockMap[i].block = *b;
  389.             m_blockMap[i].blockColumn = j;
  390.             m_blockMap[i].alignedBlockNum = aBlock ? n : eUndefined;
  391.         }
  392.     }
  393.     // if alignment changes, any pssm/scores/status become invalid
  394.     RemovePSSM();
  395.     if (clearRowInfo) ClearRowInfo();
  396.     return true;
  397. }
  398. bool BlockMultipleAlignment::GetCharacterAt(
  399.     unsigned int alignmentColumn, unsigned int row, eUnalignedJustification justification,
  400.     char *character) const
  401. {
  402.     const Sequence *sequence;
  403.     unsigned int seqIndex;
  404.     bool isAligned;
  405.     if (!GetSequenceAndIndexAt(alignmentColumn, row, justification, &sequence, &seqIndex, &isAligned))
  406.         return false;
  407.     *character = (seqIndex >= 0) ? sequence->m_sequenceString[seqIndex] : '~';
  408.     if (isAligned)
  409.         *character = toupper(*character);
  410.     else
  411.         *character = tolower(*character);
  412.     return true;
  413. }
  414. bool BlockMultipleAlignment::GetSequenceAndIndexAt(
  415.     unsigned int alignmentColumn, unsigned int row, eUnalignedJustification requestedJustification,
  416.     const Sequence **sequence, unsigned int *index, bool *isAligned) const
  417. {
  418.     if (sequence)
  419.         *sequence = m_sequences[row];
  420.     const BlockInfo& blockInfo = m_blockMap[alignmentColumn];
  421.     if (!blockInfo.block->IsAligned()) {
  422.         if (isAligned)
  423.             *isAligned = false;
  424.         // override requested justification for end m_blocks
  425.         if (blockInfo.block == m_blocks.back().GetPointer()) // also true if there's a single aligned block
  426.             requestedJustification = eLeft;
  427.         else if (blockInfo.block == m_blocks.front().GetPointer())
  428.             requestedJustification = eRight;
  429.     } else
  430.         if (isAligned)
  431.             *isAligned = true;
  432.     if (index)
  433.         *index = blockInfo.block->GetIndexAt(blockInfo.blockColumn, row, requestedJustification);
  434.     return true;
  435. }
  436. bool BlockMultipleAlignment::IsAligned(unsigned int row, unsigned int seqIndex) const
  437. {
  438.     const Block *block = GetBlock(row, seqIndex);
  439.     return (block && block->IsAligned());
  440. }
  441. const Block * BlockMultipleAlignment::GetBlock(unsigned int row, unsigned int seqIndex) const
  442. {
  443.     // make sure we're in range for this sequence
  444.     if (row < 0 || seqIndex < 0 || row >= NRows() || seqIndex >= m_sequences[row]->Length()) {
  445.         ERROR_MESSAGE("BlockMultipleAlignment::GetBlock() - coordinate out of range");
  446.         return NULL;
  447.     }
  448.     const Block::Range *range;
  449.     // first check to see if it's in the same block as last time.
  450.     if (m_cachePrevBlock) {
  451.         range = m_cachePrevBlock->GetRangeOfRow(row);
  452.         if (seqIndex >= range->from && seqIndex <= range->to)
  453.             return m_cachePrevBlock;
  454.         ++m_cacheBlockIterator; // start search at next block
  455.     } else {
  456.         m_cacheBlockIterator = m_blocks.begin();
  457.     }
  458.     // otherwise, perform block search. This search is most efficient when queries
  459.     // happen in order from left to right along a given row.
  460.     do {
  461.         if (m_cacheBlockIterator == m_blocks.end())
  462.             m_cacheBlockIterator = m_blocks.begin();
  463.         range = (*m_cacheBlockIterator)->GetRangeOfRow(row);
  464.         if (seqIndex >= range->from && seqIndex <= range->to) {
  465.             m_cachePrevBlock = *m_cacheBlockIterator; // cache this block
  466.             return m_cachePrevBlock;
  467.         }
  468.         ++m_cacheBlockIterator;
  469.     } while (1);
  470. }
  471. unsigned int BlockMultipleAlignment::GetFirstAlignedBlockPosition(void) const
  472. {
  473.     BlockList::const_iterator b = m_blocks.begin();
  474.     if (m_blocks.size() > 0 && (*b)->IsAligned()) // first block is aligned
  475.         return 0;
  476.     else if (m_blocks.size() >= 2 && (*(++b))->IsAligned()) // second block is aligned
  477.         return m_blocks.front()->m_width;
  478.     else
  479.         return eUndefined;
  480. }
  481. unsigned int BlockMultipleAlignment::GetAlignedSlaveIndex(unsigned int masterSeqIndex, unsigned int slaveRow) const
  482. {
  483.     const UngappedAlignedBlock
  484.         *aBlock = dynamic_cast<const UngappedAlignedBlock*>(GetBlock(0, masterSeqIndex));
  485.     if (!aBlock)
  486.         return eUndefined;
  487.     const Block::Range
  488.         *masterRange = aBlock->GetRangeOfRow(0),
  489.         *slaveRange = aBlock->GetRangeOfRow(slaveRow);
  490.     return (slaveRange->from + masterSeqIndex - masterRange->from);
  491. }
  492. void BlockMultipleAlignment::GetAlignedBlockPosition(unsigned int alignmentIndex,
  493.     unsigned int *blockColumn, unsigned int *blockWidth) const
  494. {
  495.     *blockColumn = *blockWidth = eUndefined;
  496.     const BlockInfo& info = m_blockMap[alignmentIndex];
  497.     if (info.block->IsAligned()) {
  498.         *blockColumn = info.blockColumn;
  499.         *blockWidth = info.block->m_width;
  500.     }
  501. }
  502. Block * BlockMultipleAlignment::GetBlockBefore(const Block *block)
  503. {
  504.     Block *prevBlock = NULL;
  505.     BlockList::iterator b, be = m_blocks.end();
  506.     for (b=m_blocks.begin(); b!=be; ++b) {
  507.         if (*b == block) break;
  508.         prevBlock = b->GetPointer();
  509.     }
  510.     return prevBlock;
  511. }
  512. const Block * BlockMultipleAlignment::GetBlockBefore(const Block *block) const
  513. {
  514.     const Block *prevBlock = NULL;
  515.     BlockList::const_iterator b, be = m_blocks.end();
  516.     for (b=m_blocks.begin(); b!=be; ++b) {
  517.         if (*b == block) break;
  518.         prevBlock = b->GetPointer();
  519.     }
  520.     return prevBlock;
  521. }
  522. Block * BlockMultipleAlignment::GetBlockAfter(const Block *block)
  523. {
  524.     BlockList::iterator b, be = m_blocks.end();
  525.     for (b=m_blocks.begin(); b!=be; ++b) {
  526.         if (*b == block) {
  527.             ++b;
  528.             if (b == be) break;
  529.             return *b;
  530.         }
  531.     }
  532.     return NULL;
  533. }
  534. const Block * BlockMultipleAlignment::GetBlockAfter(const Block *block) const
  535. {
  536.     BlockList::const_iterator b, be = m_blocks.end();
  537.     for (b=m_blocks.begin(); b!=be; ++b) {
  538.         if (*b == block) {
  539.             ++b;
  540.             if (b == be) break;
  541.             return *b;
  542.         }
  543.     }
  544.     return NULL;
  545. }
  546. const UnalignedBlock * BlockMultipleAlignment::GetUnalignedBlockBefore(
  547.     const UngappedAlignedBlock *aBlock) const
  548. {
  549.     const Block *prevBlock;
  550.     if (aBlock)
  551.         prevBlock = GetBlockBefore(aBlock);
  552.     else
  553.         prevBlock = m_blocks.back().GetPointer();
  554.     return dynamic_cast<const UnalignedBlock*>(prevBlock);
  555. }
  556. void BlockMultipleAlignment::InsertBlockBefore(Block *newBlock, const Block *insertAt)
  557. {
  558.     BlockList::iterator b, be = m_blocks.end();
  559.     for (b=m_blocks.begin(); b!=be; ++b) {
  560.         if (*b == insertAt) {
  561.             m_blocks.insert(b, CRef<Block>(newBlock));
  562.             return;
  563.         }
  564.     }
  565.     WARNING_MESSAGE("BlockMultipleAlignment::InsertBlockBefore() - couldn't find insertAt block");
  566. }
  567. void BlockMultipleAlignment::InsertBlockAfter(const Block *insertAt, Block *newBlock)
  568. {
  569.     BlockList::iterator b, be = m_blocks.end();
  570.     for (b=m_blocks.begin(); b!=be; ++b) {
  571.         if (*b == insertAt) {
  572.             ++b;
  573.             m_blocks.insert(b, CRef<Block>(newBlock));
  574.             return;
  575.         }
  576.     }
  577.     WARNING_MESSAGE("BlockMultipleAlignment::InsertBlockBefore() - couldn't find insertAt block");
  578. }
  579. void BlockMultipleAlignment::RemoveBlock(Block *block)
  580. {
  581.     BlockList::iterator b, be = m_blocks.end();
  582.     for (b=m_blocks.begin(); b!=be; ++b) {
  583.         if (*b == block) {
  584.             m_blocks.erase(b);
  585.             InitCache();
  586.             return;
  587.         }
  588.     }
  589.     WARNING_MESSAGE("BlockMultipleAlignment::RemoveBlock() - couldn't find block");
  590. }
  591. bool BlockMultipleAlignment::MoveBlockBoundary(unsigned int columnFrom, unsigned int columnTo)
  592. {
  593.     unsigned int blockColumn, blockWidth;
  594.     GetAlignedBlockPosition(columnFrom, &blockColumn, &blockWidth);
  595.     if (blockColumn == eUndefined || blockWidth == 0 || blockWidth == eUndefined) return false;
  596.     TRACE_MESSAGE("trying to move block boundary from " << columnFrom << " to " << columnTo);
  597.     const BlockInfo& info = m_blockMap[columnFrom];
  598.     unsigned int row;
  599.     int requestedShift = columnTo - columnFrom, actualShift = 0;
  600.     const Block::Range *range;
  601.     // shrink block from left
  602.     if (blockColumn == 0 && requestedShift > 0 && requestedShift < (int) info.block->m_width) {
  603.         actualShift = requestedShift;
  604.         TRACE_MESSAGE("shrinking block from left");
  605.         for (row=0; row<NRows(); ++row) {
  606.             range = info.block->GetRangeOfRow(row);
  607.             info.block->SetRangeOfRow(row, range->from + requestedShift, range->to);
  608.         }
  609.         info.block->m_width -= requestedShift;
  610.         Block *prevBlock = GetBlockBefore(info.block);
  611.         if (prevBlock && !prevBlock->IsAligned()) {
  612.             for (row=0; row<NRows(); ++row) {
  613.                 range = prevBlock->GetRangeOfRow(row);
  614.                 prevBlock->SetRangeOfRow(row, range->from, range->to + requestedShift);
  615.             }
  616.             prevBlock->m_width += requestedShift;
  617.         } else {
  618.             Block *newUnalignedBlock = CreateNewUnalignedBlockBetween(prevBlock, info.block);
  619.             if (newUnalignedBlock)
  620.                 InsertBlockBefore(newUnalignedBlock, info.block);
  621.             TRACE_MESSAGE("added new unaligned block");
  622.         }
  623.     }
  624.     // shrink block from right (requestedShift < 0)
  625.     else if (blockColumn == info.block->m_width - 1 &&
  626.                 requestedShift < 0 && ((unsigned int) -requestedShift) < info.block->m_width) {
  627.         actualShift = requestedShift;
  628.         TRACE_MESSAGE("shrinking block from right");
  629.         for (row=0; row<NRows(); ++row) {
  630.             range = info.block->GetRangeOfRow(row);
  631.             info.block->SetRangeOfRow(row, range->from, range->to + requestedShift);
  632.         }
  633.         info.block->m_width += requestedShift;
  634.         Block *nextBlock = GetBlockAfter(info.block);
  635.         if (nextBlock && !nextBlock->IsAligned()) {
  636.             for (row=0; row<NRows(); ++row) {
  637.                 range = nextBlock->GetRangeOfRow(row);
  638.                 nextBlock->SetRangeOfRow(row, range->from + requestedShift, range->to);
  639.             }
  640.             nextBlock->m_width -= requestedShift;
  641.         } else {
  642.             Block *newUnalignedBlock = CreateNewUnalignedBlockBetween(info.block, nextBlock);
  643.             if (newUnalignedBlock)
  644.                 InsertBlockAfter(info.block, newUnalignedBlock);
  645.             TRACE_MESSAGE("added new unaligned block");
  646.         }
  647.     }
  648.     // grow block to right
  649.     else if (blockColumn == info.block->m_width - 1 && requestedShift > 0) {
  650.         Block *nextBlock = GetBlockAfter(info.block);
  651.         if (nextBlock && !nextBlock->IsAligned()) {
  652.             int nRes;
  653.             actualShift = requestedShift;
  654.             for (row=0; row<NRows(); ++row) {
  655.                 range = nextBlock->GetRangeOfRow(row);
  656.                 nRes = range->to - range->from + 1;
  657.                 if (nRes < actualShift)
  658.                     actualShift = nRes;
  659.             }
  660.             if (actualShift) {
  661.                 TRACE_MESSAGE("growing block to right");
  662.                 for (row=0; row<NRows(); ++row) {
  663.                     range = info.block->GetRangeOfRow(row);
  664.                     info.block->SetRangeOfRow(row, range->from, range->to + actualShift);
  665.                     range = nextBlock->GetRangeOfRow(row);
  666.                     nextBlock->SetRangeOfRow(row, range->from + actualShift, range->to);
  667.                 }
  668.                 info.block->m_width += actualShift;
  669.                 nextBlock->m_width -= actualShift;
  670.                 if (nextBlock->m_width == 0) {
  671.                     RemoveBlock(nextBlock);
  672.                     TRACE_MESSAGE("removed empty block");
  673.                 }
  674.             }
  675.         }
  676.     }
  677.     // grow block to left (requestedShift < 0)
  678.     else if (blockColumn == 0 && requestedShift < 0) {
  679.         Block *prevBlock = GetBlockBefore(info.block);
  680.         if (prevBlock && !prevBlock->IsAligned()) {
  681.             int nRes;
  682.             actualShift = requestedShift;
  683.             for (row=0; row<NRows(); ++row) {
  684.                 range = prevBlock->GetRangeOfRow(row);
  685.                 nRes = range->to - range->from + 1;
  686.                 if (nRes < -actualShift) actualShift = -nRes;
  687.             }
  688.             if (actualShift) {
  689.                 TRACE_MESSAGE("growing block to left");
  690.                 for (row=0; row<NRows(); ++row) {
  691.                     range = info.block->GetRangeOfRow(row);
  692.                     info.block->SetRangeOfRow(row, range->from + actualShift, range->to);
  693.                     range = prevBlock->GetRangeOfRow(row);
  694.                     prevBlock->SetRangeOfRow(row, range->from, range->to + actualShift);
  695.                 }
  696.                 info.block->m_width -= actualShift;
  697.                 prevBlock->m_width += actualShift;
  698.                 if (prevBlock->m_width == 0) {
  699.                     RemoveBlock(prevBlock);
  700.                     TRACE_MESSAGE("removed empty block");
  701.                 }
  702.             }
  703.         }
  704.     }
  705.     if (actualShift != 0) {
  706.         UpdateBlockMap();
  707.         return true;
  708.     } else
  709.         return false;
  710. }
  711. bool BlockMultipleAlignment::ShiftRow(unsigned int row, unsigned int fromAlignmentIndex, unsigned int toAlignmentIndex,
  712.     eUnalignedJustification justification)
  713. {
  714.     if (fromAlignmentIndex == toAlignmentIndex)
  715.         return false;
  716.     Block
  717.         *blockFrom = m_blockMap[fromAlignmentIndex].block,
  718.         *blockTo = m_blockMap[toAlignmentIndex].block;
  719.     // at least one end of the drag must be in an aligned block
  720.     UngappedAlignedBlock *ABlock =
  721.         dynamic_cast<UngappedAlignedBlock*>(blockFrom);
  722.     if (ABlock) {
  723.         if (blockTo != blockFrom && blockTo->IsAligned())
  724.             return false;
  725.     } else {
  726.         ABlock = dynamic_cast<UngappedAlignedBlock*>(blockTo);
  727.         if (!ABlock)
  728.             return false;
  729.     }
  730.     // and the other must be in the same aligned block or an adjacent unaligned block
  731.     UnalignedBlock
  732.         *prevUABlock = dynamic_cast<UnalignedBlock*>(GetBlockBefore(ABlock)),
  733.         *nextUABlock = dynamic_cast<UnalignedBlock*>(GetBlockAfter(ABlock));
  734.     if (blockFrom != blockTo &&
  735.         ((ABlock == blockFrom && prevUABlock != blockTo && nextUABlock != blockTo) ||
  736.          (ABlock == blockTo && prevUABlock != blockFrom && nextUABlock != blockFrom)))
  737.         return false;
  738.     int requestedShift, actualShift = 0, width = 0;
  739.     // slightly different behaviour when dragging from unaligned to aligned...
  740.     if (!blockFrom->IsAligned()) {
  741.         unsigned int fromSeqIndex, toSeqIndex;
  742.         GetSequenceAndIndexAt(fromAlignmentIndex, row, justification, NULL, &fromSeqIndex, NULL);
  743.         GetSequenceAndIndexAt(toAlignmentIndex, row, justification, NULL, &toSeqIndex, NULL);
  744.         if (fromSeqIndex == eUndefined || toSeqIndex == eUndefined)
  745.             return false;
  746.         requestedShift = toSeqIndex - fromSeqIndex;
  747.     }
  748.     // vs. dragging from aligned
  749.     else {
  750.         requestedShift = toAlignmentIndex - fromAlignmentIndex;
  751.     }
  752.     const Block::Range *prevRange = NULL, *nextRange = NULL, *range = ABlock->GetRangeOfRow(row);
  753.     if (prevUABlock) prevRange = prevUABlock->GetRangeOfRow(row);
  754.     if (nextUABlock) nextRange = nextUABlock->GetRangeOfRow(row);
  755.     if (requestedShift > 0) {
  756.         if (prevUABlock)
  757.             width = prevRange->to - prevRange->from + 1;
  758.         actualShift = (width > requestedShift) ? requestedShift : width;
  759.     } else {
  760.         if (nextUABlock)
  761.             width = nextRange->to - nextRange->from + 1;
  762.         actualShift = (width > -requestedShift) ? requestedShift : -width;
  763.     }
  764.     if (actualShift == 0) return false;
  765.     TRACE_MESSAGE("shifting row " << row << " by " << actualShift);
  766.     ABlock->SetRangeOfRow(row, range->from - actualShift, range->to - actualShift);
  767.     if (prevUABlock) {
  768.         prevUABlock->SetRangeOfRow(row, prevRange->from, prevRange->to - actualShift);
  769.         prevUABlock->m_width = 0;
  770.         for (unsigned int i=0; i<NRows(); ++i) {
  771.             prevRange = prevUABlock->GetRangeOfRow(i);
  772.             width = prevRange->to - prevRange->from + 1;
  773.             if (width < 0)
  774.                 ERROR_MESSAGE("BlockMultipleAlignment::ShiftRow() - negative width on left");
  775.             if ((unsigned int) width > prevUABlock->m_width)
  776.                 prevUABlock->m_width = width;
  777.         }
  778.         if (prevUABlock->m_width == 0) {
  779.             TRACE_MESSAGE("removing zero-m_width unaligned block on left");
  780.             RemoveBlock(prevUABlock);
  781.         }
  782.     } else {
  783.         TRACE_MESSAGE("creating unaligned block on left");
  784.         prevUABlock = CreateNewUnalignedBlockBetween(GetBlockBefore(ABlock), ABlock);
  785.         InsertBlockBefore(prevUABlock, ABlock);
  786.     }
  787.     if (nextUABlock) {
  788.         nextUABlock->SetRangeOfRow(row, nextRange->from - actualShift, nextRange->to);
  789.         nextUABlock->m_width = 0;
  790.         for (unsigned int i=0; i<NRows(); ++i) {
  791.             nextRange = nextUABlock->GetRangeOfRow(i);
  792.             width = nextRange->to - nextRange->from + 1;
  793.             if (width < 0)
  794.                 ERROR_MESSAGE("BlockMultipleAlignment::ShiftRow() - negative width on right");
  795.             if ((unsigned int) width > nextUABlock->m_width)
  796.                 nextUABlock->m_width = width;
  797.         }
  798.         if (nextUABlock->m_width == 0) {
  799.             TRACE_MESSAGE("removing zero-m_width unaligned block on right");
  800.             RemoveBlock(nextUABlock);
  801.         }
  802.     } else {
  803.         TRACE_MESSAGE("creating unaligned block on right");
  804.         nextUABlock = CreateNewUnalignedBlockBetween(ABlock, GetBlockAfter(ABlock));
  805.         InsertBlockAfter(ABlock, nextUABlock);
  806.     }
  807.     if (!CheckAlignedBlock(ABlock))
  808.         ERROR_MESSAGE("BlockMultipleAlignment::ShiftRow() - shift failed to create valid aligned block");
  809.     UpdateBlockMap();
  810.     return true;
  811. }
  812. bool BlockMultipleAlignment::SplitBlock(unsigned int alignmentIndex)
  813. {
  814.     const BlockInfo& info = m_blockMap[alignmentIndex];
  815.     if (!info.block->IsAligned() || info.block->m_width < 2 || info.blockColumn == 0)
  816.         return false;
  817.     TRACE_MESSAGE("splitting block");
  818.     UngappedAlignedBlock *newAlignedBlock = new UngappedAlignedBlock(this);
  819.     newAlignedBlock->m_width = info.block->m_width - info.blockColumn;
  820.     info.block->m_width = info.blockColumn;
  821.     const Block::Range *range;
  822.     unsigned int oldTo;
  823.     for (unsigned int row=0; row<NRows(); ++row) {
  824.         range = info.block->GetRangeOfRow(row);
  825.         oldTo = range->to;
  826.         info.block->SetRangeOfRow(row, range->from, range->from + info.block->m_width - 1);
  827.         newAlignedBlock->SetRangeOfRow(row, oldTo - newAlignedBlock->m_width + 1, oldTo);
  828.     }
  829.     InsertBlockAfter(info.block, newAlignedBlock);
  830.     if (!CheckAlignedBlock(info.block) || !CheckAlignedBlock(newAlignedBlock))
  831.         ERROR_MESSAGE("BlockMultipleAlignment::SplitBlock() - split failed to create valid m_blocks");
  832.     UpdateBlockMap();
  833.     return true;
  834. }
  835. bool BlockMultipleAlignment::MergeBlocks(unsigned int fromAlignmentIndex, unsigned int toAlignmentIndex)
  836. {
  837.     Block
  838.         *expandedBlock = m_blockMap[fromAlignmentIndex].block,
  839.         *lastBlock = m_blockMap[toAlignmentIndex].block;
  840.     if (expandedBlock == lastBlock)
  841.         return false;
  842.     unsigned int i;
  843.     for (i=fromAlignmentIndex; i<=toAlignmentIndex; ++i)
  844.         if (!m_blockMap[i].block->IsAligned())
  845.             return false;
  846.     TRACE_MESSAGE("merging block(s)");
  847.     for (i=0; i<NRows(); ++i)
  848.         expandedBlock->SetRangeOfRow(i, expandedBlock->GetRangeOfRow(i)->from, lastBlock->GetRangeOfRow(i)->to);
  849.     expandedBlock->m_width = lastBlock->GetRangeOfRow(0)->to - expandedBlock->GetRangeOfRow(0)->from + 1;
  850.     Block *deletedBlock = NULL, *blockToDelete;
  851.     for (i=fromAlignmentIndex; i<=toAlignmentIndex; ++i) {
  852.         blockToDelete = m_blockMap[i].block;
  853.         if (blockToDelete == expandedBlock)
  854.             continue;
  855.         if (blockToDelete != deletedBlock) {
  856.             deletedBlock = blockToDelete;
  857.             RemoveBlock(blockToDelete);
  858.         }
  859.     }
  860.     if (!CheckAlignedBlock(expandedBlock))
  861.         ERROR_MESSAGE("BlockMultipleAlignment::MergeBlocks() - merge failed to create valid block");
  862.     UpdateBlockMap();
  863.     return true;
  864. }
  865. bool BlockMultipleAlignment::CreateBlock(unsigned int fromAlignmentIndex, unsigned int toAlignmentIndex,
  866.     eUnalignedJustification justification)
  867. {
  868.     const BlockInfo& info = m_blockMap[fromAlignmentIndex];
  869.     UnalignedBlock *prevUABlock = dynamic_cast<UnalignedBlock*>(info.block);
  870.     if (!prevUABlock || info.block != m_blockMap[toAlignmentIndex].block)
  871.         return false;
  872.     unsigned int row, seqIndexFrom, seqIndexTo,
  873.         newBlockWidth = toAlignmentIndex - fromAlignmentIndex + 1,
  874.         origWidth = prevUABlock->m_width;
  875.     vector < unsigned int > seqIndexesFrom(NRows()), seqIndexesTo(NRows());
  876.     const Sequence *seq;
  877. bool ignored;
  878.     for (row=0; row<NRows(); ++row) {
  879.         if (!GetSequenceAndIndexAt(fromAlignmentIndex, row, justification, &seq, &seqIndexFrom, &ignored) ||
  880.                 !GetSequenceAndIndexAt(toAlignmentIndex, row, justification, &seq, &seqIndexTo, &ignored) ||
  881.                 seqIndexFrom < 0 || seqIndexTo < 0 ||
  882.                 seqIndexTo - seqIndexFrom + 1 != newBlockWidth)
  883.             return false;
  884.         seqIndexesFrom[row] = seqIndexFrom;
  885.         seqIndexesTo[row] = seqIndexTo;
  886.     }
  887.     TRACE_MESSAGE("creating new aligned and unaligned blocks");
  888.     UnalignedBlock *nextUABlock = new UnalignedBlock(this);
  889.     UngappedAlignedBlock *ABlock = new UngappedAlignedBlock(this);
  890.     prevUABlock->m_width = nextUABlock->m_width = 0;
  891.     bool deletePrevUABlock = true, deleteNextUABlock = true;
  892.     const Block::Range *prevRange;
  893.     int rangeWidth;
  894.     for (row=0; row<NRows(); ++row) {
  895.         prevRange = prevUABlock->GetRangeOfRow(row);
  896.         nextUABlock->SetRangeOfRow(row, seqIndexesTo[row] + 1, prevRange->to);
  897.         rangeWidth = prevRange->to - seqIndexesTo[row];
  898.         if (rangeWidth < 0)
  899.             ERROR_MESSAGE("BlockMultipleAlignment::CreateBlock() - negative nextRange width");
  900.         else if (rangeWidth > 0) {
  901.             if ((unsigned int) rangeWidth > nextUABlock->m_width)
  902.                 nextUABlock->m_width = rangeWidth;
  903.             deleteNextUABlock = false;
  904.         }
  905.         prevUABlock->SetRangeOfRow(row, prevRange->from, seqIndexesFrom[row] - 1);
  906.         rangeWidth = seqIndexesFrom[row] - prevRange->from;
  907.         if (rangeWidth < 0)
  908.             ERROR_MESSAGE("BlockMultipleAlignment::CreateBlock() - negative prevRange width");
  909.         else if (rangeWidth > 0) {
  910.             if ((unsigned int) rangeWidth > prevUABlock->m_width)
  911.                 prevUABlock->m_width = rangeWidth;
  912.             deletePrevUABlock = false;
  913.         }
  914.         ABlock->SetRangeOfRow(row, seqIndexesFrom[row], seqIndexesTo[row]);
  915.     }
  916.     ABlock->m_width = newBlockWidth;
  917.     if (prevUABlock->m_width + ABlock->m_width + nextUABlock->m_width != origWidth)
  918.         ERROR_MESSAGE("BlockMultipleAlignment::CreateBlock() - bad block m_widths sum");
  919.     InsertBlockAfter(prevUABlock, ABlock);
  920.     InsertBlockAfter(ABlock, nextUABlock);
  921.     if (deletePrevUABlock) {
  922.         TRACE_MESSAGE("deleting zero-width unaligned block on left");
  923.         RemoveBlock(prevUABlock);
  924.     }
  925.     if (deleteNextUABlock) {
  926.         TRACE_MESSAGE("deleting zero-width unaligned block on right");
  927.         RemoveBlock(nextUABlock);
  928.     }
  929.     if (!CheckAlignedBlock(ABlock))
  930.         ERROR_MESSAGE("BlockMultipleAlignment::CreateBlock() - failed to create valid block");
  931.     UpdateBlockMap();
  932.     return true;
  933. }
  934. bool BlockMultipleAlignment::DeleteBlock(unsigned int alignmentIndex)
  935. {
  936.     Block *block = m_blockMap[alignmentIndex].block;
  937.     if (!block || !block->IsAligned())
  938.         return false;
  939.     TRACE_MESSAGE("deleting block");
  940.     Block
  941.         *prevBlock = GetBlockBefore(block),
  942.         *nextBlock = GetBlockAfter(block);
  943.     // unaligned m_blocks on both sides - note that total alignment m_width can change!
  944.     if (prevBlock && !prevBlock->IsAligned() && nextBlock && !nextBlock->IsAligned()) {
  945.         const Block::Range *prevRange, *nextRange;
  946.         unsigned int maxWidth = 0, width;
  947.         for (unsigned int row=0; row<NRows(); ++row) {
  948.             prevRange = prevBlock->GetRangeOfRow(row);
  949.             nextRange = nextBlock->GetRangeOfRow(row);
  950.             width = nextRange->to - prevRange->from + 1;
  951.             prevBlock->SetRangeOfRow(row, prevRange->from, nextRange->to);
  952.             if (width > maxWidth)
  953.                 maxWidth = width;
  954.         }
  955.         prevBlock->m_width = maxWidth;
  956.         TRACE_MESSAGE("removing extra unaligned block");
  957.         RemoveBlock(nextBlock);
  958.     }
  959.     // unaligned block on left only
  960.     else if (prevBlock && !prevBlock->IsAligned()) {
  961.         const Block::Range *prevRange, *range;
  962.         for (unsigned int row=0; row<NRows(); ++row) {
  963.             prevRange = prevBlock->GetRangeOfRow(row);
  964.             range = block->GetRangeOfRow(row);
  965.             prevBlock->SetRangeOfRow(row, prevRange->from, range->to);
  966.         }
  967.         prevBlock->m_width += block->m_width;
  968.     }
  969.     // unaligned block on right only
  970.     else if (nextBlock && !nextBlock->IsAligned()) {
  971.         const Block::Range *range, *nextRange;
  972.         for (unsigned int row=0; row<NRows(); ++row) {
  973.             range = block->GetRangeOfRow(row);
  974.             nextRange = nextBlock->GetRangeOfRow(row);
  975.             nextBlock->SetRangeOfRow(row, range->from, nextRange->to);
  976.         }
  977.         nextBlock->m_width += block->m_width;
  978.     }
  979.     // no adjacent unaligned m_blocks
  980.     else {
  981.         TRACE_MESSAGE("creating new unaligned block");
  982.         Block *newBlock = CreateNewUnalignedBlockBetween(prevBlock, nextBlock);
  983.         if (prevBlock)
  984.             InsertBlockAfter(prevBlock, newBlock);
  985.         else if (nextBlock)
  986.             InsertBlockBefore(newBlock, nextBlock);
  987.         else
  988.             m_blocks.push_back(CRef<Block>(newBlock));
  989.     }
  990.     RemoveBlock(block);
  991.     UpdateBlockMap();
  992.     return true;
  993. }
  994. bool BlockMultipleAlignment::DeleteAllBlocks(void)
  995. {
  996.     if (m_blocks.size() == 0)
  997.         return false;
  998.     m_blocks.clear();
  999.     InitCache();
  1000.     AddUnalignedBlocks();   // one single unaligned block for whole alignment
  1001.     UpdateBlockMap();
  1002.     return true;
  1003. }
  1004. bool BlockMultipleAlignment::DeleteRow(unsigned int row)
  1005. {
  1006.     if (row >= NRows()) {
  1007.         ERROR_MESSAGE("BlockMultipleAlignment::DeleteRow() - row out of range");
  1008.         return false;
  1009.     }
  1010.     // remove sequence from list
  1011.     SequenceList::iterator s = m_sequences.begin();
  1012.     for (unsigned int i=0; i<row; ++i)
  1013.         ++s;
  1014.     m_sequences.erase(s);
  1015.     // delete row from all m_blocks, removing any zero-m_width m_blocks
  1016.     BlockList::iterator b = m_blocks.begin(), br, be = m_blocks.end();
  1017.     while (b != be) {
  1018.         (*b)->DeleteRow(row);
  1019.         if ((*b)->m_width == 0) {
  1020.             br = b;
  1021.             ++b;
  1022.             TRACE_MESSAGE("deleting block resized to zero width");
  1023.             RemoveBlock(*br);
  1024.         } else
  1025.             ++b;
  1026.     }
  1027.     // update total alignment m_width
  1028.     UpdateBlockMap();
  1029.     InitCache();
  1030.     return true;
  1031. }
  1032. void BlockMultipleAlignment::GetUngappedAlignedBlocks(UngappedAlignedBlockList *uabs) const
  1033. {
  1034.     uabs->clear();
  1035.     uabs->reserve(m_blocks.size());
  1036.     BlockList::const_iterator b, be = m_blocks.end();
  1037.     for (b=m_blocks.begin(); b!=be; ++b) {
  1038.         const UngappedAlignedBlock *uab = dynamic_cast<const UngappedAlignedBlock*>(b->GetPointer());
  1039.         if (uab)
  1040.             uabs->push_back(uab);
  1041.     }
  1042.     uabs->resize(uabs->size());
  1043. }
  1044. void BlockMultipleAlignment::GetModifiableUngappedAlignedBlocks(ModifiableUngappedAlignedBlockList *uabs)
  1045. {
  1046.     uabs->clear();
  1047.     uabs->reserve(m_blocks.size());
  1048.     BlockList::iterator b, be = m_blocks.end();
  1049.     for (b=m_blocks.begin(); b!=be; ++b) {
  1050.         UngappedAlignedBlock *uab = dynamic_cast<UngappedAlignedBlock*>(b->GetPointer());
  1051.         if (uab)
  1052.             uabs->push_back(uab);
  1053.     }
  1054.     uabs->resize(uabs->size());
  1055. }
  1056. bool BlockMultipleAlignment::ExtractRows(
  1057.     const vector < unsigned int >& slavesToRemove, AlignmentList *pairwiseAlignments)
  1058. {
  1059.     if (slavesToRemove.size() == 0) return false;
  1060.     // make a bool list of rows to remove, also checking to make sure slave list items are in range
  1061.     unsigned int i;
  1062.     vector < bool > removeRows(NRows(), false);
  1063.     for (i=0; i<slavesToRemove.size(); ++i) {
  1064.         if (slavesToRemove[i] > 0 && slavesToRemove[i] < NRows()) {
  1065.             removeRows[slavesToRemove[i]] = true;
  1066.         } else {
  1067.             ERROR_MESSAGE("BlockMultipleAlignment::ExtractRows() - can't extract row "
  1068.                 << slavesToRemove[i]);
  1069.             return false;
  1070.         }
  1071.     }
  1072.     if (pairwiseAlignments) {
  1073.         TRACE_MESSAGE("creating new pairwise alignments");
  1074.         SetDiagPostLevel(eDiag_Warning);    // otherwise, info messages take a long time if lots of rows
  1075.         UngappedAlignedBlockList uaBlocks;
  1076.         GetUngappedAlignedBlocks(&uaBlocks);
  1077.         UngappedAlignedBlockList::const_iterator u, ue = uaBlocks.end();
  1078.         for (i=0; i<slavesToRemove.size(); ++i) {
  1079.             // create new pairwise alignment from each removed row
  1080.             SequenceList newSeqs(2);
  1081.             newSeqs[0] = m_sequences[0];
  1082.             newSeqs[1] = m_sequences[slavesToRemove[i]];
  1083.             BlockMultipleAlignment *newAlignment = new BlockMultipleAlignment(newSeqs);
  1084.             for (u=uaBlocks.begin(); u!=ue; ++u) {
  1085.                 UngappedAlignedBlock *newABlock = new UngappedAlignedBlock(newAlignment);
  1086.                 const Block::Range *range = (*u)->GetRangeOfRow(0);
  1087.                 newABlock->SetRangeOfRow(0, range->from, range->to);
  1088.                 range = (*u)->GetRangeOfRow(slavesToRemove[i]);
  1089.                 newABlock->SetRangeOfRow(1, range->from, range->to);
  1090.                 newABlock->m_width = range->to - range->from + 1;
  1091.                 newAlignment->AddAlignedBlockAtEnd(newABlock);
  1092.             }
  1093.             if (!newAlignment->AddUnalignedBlocks() ||
  1094.                 !newAlignment->UpdateBlockMap()) {
  1095.                 ERROR_MESSAGE("BlockMultipleAlignment::ExtractRows() - error creating new alignment");
  1096.                 return false;
  1097.             }
  1098.             pairwiseAlignments->push_back(newAlignment);
  1099.         }
  1100.         SetDiagPostLevel(eDiag_Info);
  1101.     }
  1102.     // remove sequences
  1103.     TRACE_MESSAGE("deleting sequences");
  1104.     VectorRemoveElements(m_sequences, removeRows, slavesToRemove.size());
  1105.     VectorRemoveElements(m_rowDoubles, removeRows, slavesToRemove.size());
  1106.     VectorRemoveElements(m_rowStrings, removeRows, slavesToRemove.size());
  1107.     // delete row from all blocks, removing any zero-width blocks
  1108.     TRACE_MESSAGE("deleting alignment rows from blocks");
  1109.     BlockList::iterator b = m_blocks.begin(), br, be = m_blocks.end();
  1110.     while (b != be) {
  1111.         (*b)->DeleteRows(removeRows, slavesToRemove.size());
  1112.         if ((*b)->m_width == 0) {
  1113.             br = b;
  1114.             ++b;
  1115.             TRACE_MESSAGE("deleting block resized to zero width");
  1116.             RemoveBlock(*br);
  1117.         } else
  1118.             ++b;
  1119.     }
  1120.     // update total alignment m_width
  1121.     UpdateBlockMap();
  1122.     InitCache();
  1123.     return true;
  1124. }
  1125. bool BlockMultipleAlignment::MergeAlignment(const BlockMultipleAlignment *newAlignment)
  1126. {
  1127.     // check to see if the alignment is compatible - must have same master sequence
  1128.     // and blocks of new alignment must contain m_blocks of this alignment; at same time,
  1129.     // build up map of aligned blocks in new alignment that correspond to aligned blocks
  1130.     // of this object, for convenient lookup later
  1131.     if (newAlignment->GetMaster() != GetMaster())
  1132.         return false;
  1133.     const Block::Range *newRange, *thisRange;
  1134.     BlockList::const_iterator nb, nbe = newAlignment->m_blocks.end();
  1135.     BlockList::iterator b, be = m_blocks.end();
  1136.     typedef map < UngappedAlignedBlock *, const UngappedAlignedBlock * > AlignedBlockMap;
  1137.     AlignedBlockMap correspondingNewBlocks;
  1138.     for (b=m_blocks.begin(); b!=be; ++b) {
  1139.         if (!(*b)->IsAligned())
  1140.             continue;
  1141.         for (nb=newAlignment->m_blocks.begin(); nb!=nbe; ++nb) {
  1142.             if (!(*nb)->IsAligned())
  1143.                 continue;
  1144.             newRange = (*nb)->GetRangeOfRow(0);
  1145.             thisRange = (*b)->GetRangeOfRow(0);
  1146.             if (newRange->from <= thisRange->from && newRange->to >= thisRange->to) {
  1147.                 correspondingNewBlocks[dynamic_cast<UngappedAlignedBlock*>(b->GetPointer())] =
  1148.                     dynamic_cast<const UngappedAlignedBlock*>(nb->GetPointer());
  1149.                 break;
  1150.             }
  1151.         }
  1152.         if (nb == nbe) return false;    // no corresponding block found
  1153.     }
  1154.     // add slave sequences from new alignment; also copy scores/status
  1155.     unsigned int i, nNewRows = newAlignment->m_sequences.size() - 1;
  1156.     m_sequences.resize(m_sequences.size() + nNewRows);
  1157.     m_rowDoubles.resize(m_rowDoubles.size() + nNewRows);
  1158.     m_rowStrings.resize(m_rowStrings.size() + nNewRows);
  1159.     for (i=0; i<nNewRows; ++i) {
  1160.         m_sequences[m_sequences.size() + i - nNewRows] = newAlignment->m_sequences[i + 1];
  1161.         SetRowDouble(NRows() + i - nNewRows, newAlignment->GetRowDouble(i + 1));
  1162.         SetRowStatusLine(NRows() + i - nNewRows, newAlignment->GetRowStatusLine(i + 1));
  1163.     }
  1164.     // now that we know blocks are compatible, add new rows at end of this alignment, containing
  1165.     // all rows (except master) from new alignment; only that part of the aligned blocks from
  1166.     // the new alignment that intersect with the aligned blocks from this object are added, so
  1167.     // that this object's block structure is unchanged
  1168.     // resize all aligned blocks
  1169.     for (b=m_blocks.begin(); b!=be; ++b)
  1170.         (*b)->AddRows(nNewRows);
  1171.     // set ranges of aligned blocks, and add them to the list
  1172.     AlignedBlockMap::const_iterator ab, abe = correspondingNewBlocks.end();
  1173.     const Block::Range *thisMaster, *newMaster;
  1174.     for (ab=correspondingNewBlocks.begin(); ab!=abe; ++ab) {
  1175.         thisMaster = ab->first->GetRangeOfRow(0);
  1176.         newMaster = ab->second->GetRangeOfRow(0);
  1177.         for (i=0; i<nNewRows; ++i) {
  1178.             newRange = ab->second->GetRangeOfRow(i + 1);
  1179.             ab->first->SetRangeOfRow(NRows() + i - nNewRows,
  1180.                 newRange->from + thisMaster->from - newMaster->from,
  1181.                 newRange->to + thisMaster->to - newMaster->to);
  1182.         }
  1183.     }
  1184.     // delete then recreate the unaligned blocks, in case a merge requires the
  1185.     // creation of a new unaligned block
  1186.     for (b=m_blocks.begin(); b!=be; ) {
  1187.         if (!(*b)->IsAligned()) {
  1188.             BlockList::iterator bb(b);
  1189.             ++bb;
  1190.             m_blocks.erase(b);
  1191.             b = bb;
  1192.         } else
  1193.             ++b;
  1194.     }
  1195.     InitCache();
  1196.     // update this alignment, but leave row scores/status alone
  1197.     if (!AddUnalignedBlocks() || !UpdateBlockMap(false)) {
  1198.         ERROR_MESSAGE("BlockMultipleAlignment::MergeAlignment() - internal update after merge failed");
  1199.         return false;
  1200.     }
  1201.     return true;
  1202. }
  1203. template < class T >
  1204. bool ReorderVector(T& v, const std::vector < unsigned int >& newOrder)
  1205. {
  1206.     // check validity of new ordering
  1207.     if (newOrder.size() != v.size()) {
  1208.         ERROR_MESSAGE("ReorderVector() - wrong size newOrder");
  1209.         return false;
  1210.     }
  1211.     vector < bool > isPresent(v.size(), false);
  1212.     unsigned int r;
  1213.     for (r=0; r<v.size(); r++) {
  1214.         if (isPresent[newOrder[r]]) {
  1215.             ERROR_MESSAGE("ReorderVector() - invalid newOrder: repeated/missing row");
  1216.             return false;
  1217.         }
  1218.         isPresent[newOrder[r]] = true;
  1219.     }
  1220.     // not terribly efficient - makes a whole new copy with the new order, then re-copies back
  1221.     T reordered(v.size());
  1222.     for (r=0; r<v.size(); r++)
  1223.         reordered[r] = v[newOrder[r]];
  1224.     v = reordered;
  1225.     return true;
  1226. }
  1227. bool BlockMultipleAlignment::ReorderRows(const std::vector < unsigned int >& newOrder)
  1228. {
  1229.     // can't reorder master
  1230.     if (newOrder[0] != 0) {
  1231.         ERROR_MESSAGE("ReorderRows() - can't move master row");
  1232.         return false;
  1233.     }
  1234.     bool okay =
  1235.         (ReorderVector(m_sequences, newOrder) &&
  1236.          ReorderVector(m_rowDoubles, newOrder) &&
  1237.          ReorderVector(m_rowStrings, newOrder));
  1238.     if (!okay) {
  1239.         ERROR_MESSAGE("reordering of sequences and status info failed");
  1240.         return false;
  1241.     }
  1242.     BlockList::iterator b, be = m_blocks.end();
  1243.     for (b=m_blocks.begin(); b!=be; ++b)
  1244.         okay = (okay && (*b)->ReorderRows(newOrder));
  1245.     if (!okay)
  1246.         ERROR_MESSAGE("reordering of block ranges failed");
  1247.     return okay;
  1248. }
  1249. CSeq_align * CreatePairwiseSeqAlignFromMultipleRow(const BlockMultipleAlignment *multiple,
  1250.     const BlockMultipleAlignment::UngappedAlignedBlockList& m_blocks, unsigned int slaveRow)
  1251. {
  1252.     if (!multiple || slaveRow >= multiple->NRows()) {
  1253.         ERROR_MESSAGE("CreatePairwiseSeqAlignFromMultipleRow() - bad parameters");
  1254.         return NULL;
  1255.     }
  1256.     CSeq_align *seqAlign = new CSeq_align();
  1257.     seqAlign->SetType(CSeq_align::eType_partial);
  1258.     seqAlign->SetDim(2);
  1259.     CSeq_align::C_Segs::TDendiag& denDiags = seqAlign->SetSegs().SetDendiag();
  1260.     denDiags.resize((m_blocks.size() > 0) ? m_blocks.size() : 1);
  1261.     CSeq_align::C_Segs::TDendiag::iterator d, de = denDiags.end();
  1262.     BlockMultipleAlignment::UngappedAlignedBlockList::const_iterator b = m_blocks.begin();
  1263.     const Block::Range *range;
  1264.     for (d=denDiags.begin(); d!=de; ++d, ++b) {
  1265.         CDense_diag *denDiag = new CDense_diag();
  1266.         d->Reset(denDiag);
  1267.         denDiag->SetDim(2);
  1268.         denDiag->SetIds().resize(2);
  1269.         // master row
  1270.         CRef < CSeq_id > id(new CSeq_id());
  1271.         id->Assign(multiple->GetSequenceOfRow(0)->GetPreferredIdentifier());
  1272.         denDiag->SetIds().front() = id;
  1273.         if (m_blocks.size() > 0) {
  1274.             range = (*b)->GetRangeOfRow(0);
  1275.             denDiag->SetStarts().push_back(range->from);
  1276.         } else
  1277.             denDiag->SetStarts().push_back(0);
  1278.         // slave row
  1279.         id.Reset(new CSeq_id());
  1280.         id->Assign(multiple->GetSequenceOfRow(slaveRow)->GetPreferredIdentifier());
  1281.         denDiag->SetIds().back() = id;
  1282.         if (m_blocks.size() > 0) {
  1283.             range = (*b)->GetRangeOfRow(slaveRow);
  1284.             denDiag->SetStarts().push_back(range->from);
  1285.         } else
  1286.             denDiag->SetStarts().push_back(0);
  1287.         // block m_width
  1288.         denDiag->SetLen((m_blocks.size() > 0) ? (*b)->m_width : 0);
  1289.     }
  1290.     return seqAlign;
  1291. }
  1292. unsigned int BlockMultipleAlignment::NAlignedBlocks(void) const
  1293. {
  1294.     unsigned int n = 0;
  1295.     BlockList::const_iterator b, be = m_blocks.end();
  1296.     for (b=m_blocks.begin(); b!=be; ++b)
  1297.         if ((*b)->IsAligned())
  1298.             ++n;
  1299.     return n;
  1300. }
  1301. unsigned int BlockMultipleAlignment::GetAlignmentIndex(unsigned int row, unsigned int seqIndex, eUnalignedJustification justification)
  1302. {
  1303.     if (row >= NRows() || seqIndex >= GetSequenceOfRow(row)->Length()) {
  1304.         ERROR_MESSAGE("BlockMultipleAlignment::GetAlignmentIndex() - coordinate out of range");
  1305.         return eUndefined;
  1306.     }
  1307.     unsigned int alignmentIndex, blockColumn;
  1308.     const Block *block = NULL;
  1309.     const Block::Range *range;
  1310.     for (alignmentIndex=0; alignmentIndex<m_totalWidth; ++alignmentIndex) {
  1311.         // check each block to see if index is in range
  1312.         if (block != m_blockMap[alignmentIndex].block) {
  1313.             block = m_blockMap[alignmentIndex].block;
  1314.             range = block->GetRangeOfRow(row);
  1315.             if (seqIndex >= range->from && seqIndex <= range->to) {
  1316.                 // override requested justification for end blocks
  1317.                 if (block == m_blocks.back()) // also true if there's a single aligned block
  1318.                     justification = eLeft;
  1319.                 else if (block == m_blocks.front())
  1320.                     justification = eRight;
  1321.                 // search block columns to find index (inefficient, but avoids having to write
  1322.                 // inverse functions of Block::GetIndexAt()
  1323.                 for (blockColumn=0; blockColumn<block->m_width; ++blockColumn) {
  1324.                     if (seqIndex == block->GetIndexAt(blockColumn, row, justification))
  1325.                         return alignmentIndex + blockColumn;
  1326.                 }
  1327.                 ERROR_MESSAGE("BlockMultipleAlignment::GetAlignmentIndex() - can't find index in block");
  1328.                 return eUndefined;
  1329.             }
  1330.         }
  1331.     }
  1332.     // should never get here...
  1333.     ERROR_MESSAGE("BlockMultipleAlignment::GetAlignmentIndex() - confused");
  1334.     return eUndefined;
  1335. }
  1336. bool Block::ReorderRows(const std::vector < unsigned int >& newOrder)
  1337. {
  1338.     return ReorderVector(m_ranges, newOrder);
  1339. }
  1340. ///// UngappedAlignedBlock methods /////
  1341. char UngappedAlignedBlock::GetCharacterAt(unsigned int blockColumn, unsigned int row) const
  1342. {
  1343.     return m_parentAlignment->GetSequenceOfRow(row)->m_sequenceString[GetIndexAt(blockColumn, row)];
  1344. }
  1345. Block * UngappedAlignedBlock::Clone(const BlockMultipleAlignment *newMultiple) const
  1346. {
  1347.     UngappedAlignedBlock *copy = new UngappedAlignedBlock(newMultiple);
  1348.     const Block::Range *range;
  1349.     for (unsigned int row=0; row<NSequences(); ++row) {
  1350.         range = GetRangeOfRow(row);
  1351.         copy->SetRangeOfRow(row, range->from, range->to);
  1352.     }
  1353.     copy->m_width = m_width;
  1354.     return copy;
  1355. }
  1356. void UngappedAlignedBlock::DeleteRow(unsigned int row)
  1357. {
  1358.     RangeList::iterator r = m_ranges.begin();
  1359.     for (unsigned int i=0; i<row; ++i)
  1360.         ++r;
  1361.     m_ranges.erase(r);
  1362. }
  1363. void UngappedAlignedBlock::DeleteRows(vector < bool >& removeRows, unsigned int nToRemove)
  1364. {
  1365.     VectorRemoveElements(m_ranges, removeRows, nToRemove);
  1366. }
  1367. ///// UnalignedBlock methods /////
  1368. unsigned int UnalignedBlock::GetIndexAt(unsigned int blockColumn, unsigned int row,
  1369.         BlockMultipleAlignment::eUnalignedJustification justification) const
  1370. {
  1371.     const Block::Range *range = GetRangeOfRow(row);
  1372.     unsigned int seqIndex = BlockMultipleAlignment::eUndefined, rangeWidth, rangeMiddle, extraSpace;
  1373.     switch (justification) {
  1374.         case BlockMultipleAlignment::eLeft:
  1375.             seqIndex = range->from + blockColumn;
  1376.             break;
  1377.         case BlockMultipleAlignment::eRight:
  1378.             seqIndex = range->to - m_width + blockColumn + 1;
  1379.             break;
  1380.         case BlockMultipleAlignment::eCenter:
  1381.             rangeWidth = (range->to - range->from + 1);
  1382.             extraSpace = (m_width - rangeWidth) / 2;
  1383.             if (blockColumn < extraSpace || blockColumn >= extraSpace + rangeWidth)
  1384.                 seqIndex = BlockMultipleAlignment::eUndefined;
  1385.             else
  1386.                 seqIndex = range->from + blockColumn - extraSpace;
  1387.             break;
  1388.         case BlockMultipleAlignment::eSplit:
  1389.             rangeWidth = (range->to - range->from + 1);
  1390.             rangeMiddle = (rangeWidth / 2) + (rangeWidth % 2);
  1391.             extraSpace = m_width - rangeWidth;
  1392.             if (blockColumn < rangeMiddle)
  1393.                 seqIndex = range->from + blockColumn;
  1394.             else if (blockColumn >= extraSpace + rangeMiddle)
  1395.                 seqIndex = range->to - m_width + blockColumn + 1;
  1396.             else
  1397.                 seqIndex = BlockMultipleAlignment::eUndefined;
  1398.             break;
  1399.     }
  1400.     if (seqIndex < range->from || seqIndex > range->to)
  1401.         seqIndex = BlockMultipleAlignment::eUndefined;
  1402.     return seqIndex;
  1403. }
  1404. void UnalignedBlock::Resize(void)
  1405. {
  1406.     m_width = 0;
  1407.     for (unsigned int i=0; i<NSequences(); ++i) {
  1408.         unsigned int blockWidth = m_ranges[i].to - m_ranges[i].from + 1;
  1409.         if (blockWidth > m_width)
  1410.             m_width = blockWidth;
  1411.     }
  1412. }
  1413. void UnalignedBlock::DeleteRow(unsigned int row)
  1414. {
  1415.     RangeList::iterator r = m_ranges.begin();
  1416.     for (unsigned int i=0; i<row; ++i)
  1417.         ++r;
  1418.     m_ranges.erase(r);
  1419.     Resize();
  1420. }
  1421. void UnalignedBlock::DeleteRows(vector < bool >& removeRows, unsigned int nToRemove)
  1422. {
  1423.     VectorRemoveElements(m_ranges, removeRows, nToRemove);
  1424.     Resize();
  1425. }
  1426. Block * UnalignedBlock::Clone(const BlockMultipleAlignment *newMultiple) const
  1427. {
  1428.     UnalignedBlock *copy = new UnalignedBlock(newMultiple);
  1429.     const Block::Range *range;
  1430.     for (unsigned int row=0; row<NSequences(); ++row) {
  1431.         range = GetRangeOfRow(row);
  1432.         copy->SetRangeOfRow(row, range->from, range->to);
  1433.     }
  1434.     copy->m_width = m_width;
  1435.     return copy;
  1436. }
  1437. END_SCOPE(struct_util)
  1438. /*
  1439. * ---------------------------------------------------------------------------
  1440. * $Log: su_block_multiple_alignment.cpp,v $
  1441. * Revision 1000.0  2004/06/01 18:14:28  gouriano
  1442. * PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.9
  1443. *
  1444. * Revision 1.9  2004/05/28 10:07:39  thiessen
  1445. * fix GCC warning
  1446. *
  1447. * Revision 1.8  2004/05/28 09:46:57  thiessen
  1448. * restructure C-toolkit header usage ; move C Bioseq storage into su_sequence_set
  1449. *
  1450. * Revision 1.7  2004/05/27 21:34:08  thiessen
  1451. * add PSSM calculation (requires C-toolkit)
  1452. *
  1453. * Revision 1.6  2004/05/26 14:49:59  thiessen
  1454. * UNDEFINED -> eUndefined
  1455. *
  1456. * Revision 1.5  2004/05/26 14:30:16  thiessen
  1457. * adjust handling of alingment data ; add row ordering
  1458. *
  1459. * Revision 1.4  2004/05/26 02:40:24  thiessen
  1460. * progress towards LOO - all but PSSM and row ordering
  1461. *
  1462. * Revision 1.3  2004/05/25 16:24:50  thiessen
  1463. * remove WorkShop warnings
  1464. *
  1465. * Revision 1.2  2004/05/25 16:12:30  thiessen
  1466. * fix GCC warnings
  1467. *
  1468. * Revision 1.1  2004/05/25 15:52:17  thiessen
  1469. * add BlockMultipleAlignment, IBM algorithm
  1470. *
  1471. */