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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: struct_util.cpp,v $
  4.  * PRODUCTION Revision 1000.0  2004/06/01 18:14:13  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.9
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: struct_util.cpp,v 1000.0 2004/06/01 18:14:13 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. *      AlignmentUtility class
  38. *
  39. * ===========================================================================
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <corelib/ncbistd.hpp>
  43. #include <algo/structure/struct_dp/struct_dp.h>
  44. #include <algo/structure/struct_util/struct_util.hpp>
  45. #include "su_private.hpp"
  46. #include "su_sequence_set.hpp"
  47. #include "su_alignment_set.hpp"
  48. #include "su_block_multiple_alignment.hpp"
  49. // for PSSM (BLAST_Matrix)
  50. #include <blastkar.h>
  51. USING_NCBI_SCOPE;
  52. USING_SCOPE(objects);
  53. BEGIN_SCOPE(struct_util)
  54. AlignmentUtility::AlignmentUtility(const CSeq_entry& seqEntry, const SeqAnnotList& seqAnnots)
  55. {
  56.     CRef < CSeq_entry > seqEntryCopy(new CSeq_entry());
  57.     seqEntryCopy->Assign(seqEntry);
  58.     m_seqEntries.push_back(seqEntryCopy);
  59.     SeqAnnotList::const_iterator a, ae = seqAnnots.end();
  60.     for (a=seqAnnots.begin(); a!=ae; ++a) {
  61.         CRef < CSeq_annot > seqAnnotCopy(new CSeq_annot());
  62.         seqAnnotCopy->Assign(**a);
  63.         m_seqAnnots.push_back(seqAnnotCopy);
  64.     }
  65.     Init();
  66. }
  67. AlignmentUtility::AlignmentUtility(const SeqEntryList& seqEntries, const SeqAnnotList& seqAnnots)
  68. {
  69.     SeqEntryList::const_iterator s, se = seqEntries.end();
  70.     for (s=seqEntries.begin(); s!=se; s++) {
  71.         CRef < CSeq_entry > seqEntryCopy(new CSeq_entry());
  72.         seqEntryCopy->Assign(**s);
  73.         m_seqEntries.push_back(seqEntryCopy);
  74.     }
  75.     SeqAnnotList::const_iterator a, ae = seqAnnots.end();
  76.     for (a=seqAnnots.begin(); a!=ae; ++a) {
  77.         CRef < CSeq_annot > seqAnnotCopy(new CSeq_annot());
  78.         seqAnnotCopy->Assign(**a);
  79.         m_seqAnnots.push_back(seqAnnotCopy);
  80.     }
  81.     Init();
  82. }
  83. void AlignmentUtility::Init(void)
  84. {
  85.     m_sequenceSet = NULL;
  86.     m_alignmentSet = NULL;
  87.     m_okay = true;
  88.     m_currentMultiple = NULL;
  89.     bool prevState = CException::EnableBackgroundReporting(false);
  90.     try {
  91.         m_sequenceSet = new SequenceSet(m_seqEntries);
  92.         m_alignmentSet = new AlignmentSet(m_seqAnnots, *m_sequenceSet);
  93.     } catch (CException& e) {
  94.         ERROR_MESSAGE("exception during AlignmentUtility initialization: " << e.GetMsg());
  95.         m_okay = false;
  96.     }
  97.     CException::EnableBackgroundReporting(prevState);
  98. }
  99. AlignmentUtility::~AlignmentUtility()
  100. {
  101.     if (m_sequenceSet)
  102.         delete m_sequenceSet;
  103.     if (m_alignmentSet)
  104.         delete m_alignmentSet;
  105.     if (m_currentMultiple)
  106.         delete m_currentMultiple;
  107. }
  108. static bool AlignedToAllSlaves(unsigned int masterResidue, const AlignmentSet::AlignmentList& alignments)
  109. {
  110.     AlignmentSet::AlignmentList::const_iterator a, ae = alignments.end();
  111.     for (a=alignments.begin(); a!=ae; ++a) {
  112.         if ((*a)->m_masterToSlave[masterResidue] == MasterSlaveAlignment::eUnaligned)
  113.             return false;
  114.     }
  115.     return true;
  116. }
  117. static bool NoSlaveInsertionsBetween(unsigned int masterFrom, unsigned int masterTo,
  118.     const AlignmentSet::AlignmentList& alignments)
  119. {
  120.     AlignmentSet::AlignmentList::const_iterator a, ae = alignments.end();
  121.     for (a=alignments.begin(); a!=ae; ++a) {
  122.         if (((*a)->m_masterToSlave[masterTo] - (*a)->m_masterToSlave[masterFrom]) != (masterTo - masterFrom))
  123.             return false;
  124.     }
  125.     return true;
  126. }
  127. static bool NoBlockBoundariesBetween(unsigned int masterFrom, unsigned int masterTo,
  128.     const AlignmentSet::AlignmentList& alignments)
  129. {
  130.     AlignmentSet::AlignmentList::const_iterator a, ae = alignments.end();
  131.     for (a=alignments.begin(); a!=ae; ++a) {
  132.         if ((*a)->m_blockStructure[masterTo] != (*a)->m_blockStructure[masterFrom])
  133.             return false;
  134.     }
  135.     return true;
  136. }
  137. bool AlignmentUtility::DoIBM(void)
  138. {
  139.     if (m_currentMultiple) {
  140.         WARNING_MESSAGE("DoIBM() - already have a blocked alignment");
  141.         return true;
  142.     }
  143.     if (!m_alignmentSet || m_seqAnnots.size() == 0) {
  144.         ERROR_MESSAGE("DoIBM() - no alignment data present");
  145.         return false;
  146.     }
  147.     TRACE_MESSAGE("doing IBM");
  148.     const AlignmentSet::AlignmentList& alignments = m_alignmentSet->m_alignments;
  149.     AlignmentSet::AlignmentList::const_iterator a, ae = alignments.end();
  150.     // create sequence list; fill with sequences of master + slaves
  151.     BlockMultipleAlignment::SequenceList sequenceList(alignments.size() + 1);
  152.     BlockMultipleAlignment::SequenceList::iterator s = sequenceList.begin();
  153.     *(s++) = alignments.front()->m_master;
  154.     for (a=alignments.begin(); a!=ae; ++a) {
  155.         *(s++) = (*a)->m_slave;
  156.         if ((*a)->m_master != sequenceList.front()) {
  157.             ERROR_MESSAGE("AlignmentUtility::DoIBM() - all pairwise alignments must have the same master sequence");
  158.             return false;
  159.         }
  160.     }
  161.     CRef < BlockMultipleAlignment > multipleAlignment(new BlockMultipleAlignment(sequenceList));
  162.     // each block is a continuous region on the master, over which each master
  163.     // residue is aligned to a residue of each slave, and where there are no
  164.     // insertions relative to the master in any of the slaves
  165.     unsigned int masterFrom = 0, masterTo, row;
  166.     UngappedAlignedBlock *newBlock;
  167.     while (masterFrom < multipleAlignment->GetMaster()->Length()) {
  168.         // look for first all-aligned residue
  169.         if (!AlignedToAllSlaves(masterFrom, alignments)) {
  170.             ++masterFrom;
  171.             continue;
  172.         }
  173.         // find all next continuous all-aligned residues, but checking for
  174.         // block boundaries from the original master-slave pairs, so that
  175.         // blocks don't get merged
  176.         for (masterTo=masterFrom+1;
  177.                 masterTo < multipleAlignment->GetMaster()->Length() &&
  178.                 AlignedToAllSlaves(masterTo, alignments) &&
  179.                 NoSlaveInsertionsBetween(masterFrom, masterTo, alignments) &&
  180.                 NoBlockBoundariesBetween(masterFrom, masterTo, alignments);
  181.              ++masterTo) ;
  182.         --masterTo; // after loop, masterTo = first residue past block
  183.         // create new block with ranges from master and all slaves
  184.         newBlock = new UngappedAlignedBlock(multipleAlignment);
  185.         newBlock->SetRangeOfRow(0, masterFrom, masterTo);
  186.         newBlock->m_width = masterTo - masterFrom + 1;
  187.         for (a=alignments.begin(), row=1; a!=ae; ++a, ++row) {
  188.             newBlock->SetRangeOfRow(row,
  189.                 (*a)->m_masterToSlave[masterFrom],
  190.                 (*a)->m_masterToSlave[masterTo]);
  191.         }
  192.         // copy new block into alignment
  193.         multipleAlignment->AddAlignedBlockAtEnd(newBlock);
  194.         // start looking for next block
  195.         masterFrom = masterTo + 1;
  196.     }
  197.     if (!multipleAlignment->AddUnalignedBlocks() || !multipleAlignment->UpdateBlockMap()) {
  198.         ERROR_MESSAGE("AlignmentUtility::DoIBM() - error finalizing alignment");
  199.         return false;
  200.     }
  201.     // switch data to the new multiple alignment
  202.     m_currentMultiple = multipleAlignment.Release();
  203.     RemoveAlignAnnot();
  204.     return true;
  205. }
  206. // implemented in su_block_multiple_alignment.cpp
  207. extern int LookupBLASTResidueNumberFromCharacter(unsigned char r);
  208. // global stuff for DP block aligner score callback
  209. DP_BlockInfo *g_dpBlocks = NULL;
  210. const BLAST_Matrix *g_dpPSSM = NULL;
  211. const Sequence *g_dpQuery = NULL;
  212. // sum of scores for residue vs. PSSM
  213. extern "C" {
  214. int ScoreByPSSM(unsigned int block, unsigned int queryPos)
  215. {
  216.     if (!g_dpBlocks || !g_dpPSSM || !g_dpQuery || block >= g_dpBlocks->nBlocks ||
  217.         queryPos > g_dpQuery->Length() - g_dpBlocks->blockSizes[block])
  218.     {
  219.         ERROR_MESSAGE("ScoreByPSSM() - bad parameters");
  220.         return DP_NEGATIVE_INFINITY;
  221.     }
  222.     int masterPos = g_dpBlocks->blockPositions[block], score = 0;
  223.     for (unsigned i=0; i<g_dpBlocks->blockSizes[block]; ++i)
  224.         score += g_dpPSSM->matrix[masterPos + i]
  225.             [LookupBLASTResidueNumberFromCharacter(g_dpQuery->m_sequenceString[queryPos + i])];
  226.     return score;
  227. }
  228. }
  229. bool AlignmentUtility::DoLeaveOneOut(
  230.     unsigned int rowToRealign, const std::vector < unsigned int >& blocksToRealign, // what to realign
  231.     double percentile, unsigned int extension, unsigned int cutoff)                 // to calculate max loop lengths
  232. {
  233.     // first we need to do IBM -> BlockMultipleAlignment
  234.     if (!m_currentMultiple && !DoIBM())
  235.             return false;
  236.     BlockMultipleAlignment::UngappedAlignedBlockList blocks;
  237.     m_currentMultiple->GetUngappedAlignedBlocks(&blocks);
  238.     if (blocks.size() == 0) {
  239.         ERROR_MESSAGE("need at least one aligned block for LOO");
  240.         return false;
  241.     }
  242.     bool status = false;
  243.     DP_BlockInfo *dpBlocks = NULL;
  244.     DP_AlignmentResult *dpResult = NULL;
  245.     bool prevState = CException::EnableBackgroundReporting(false);
  246.     try {
  247.         // pull out the row we're realigning
  248.         if (rowToRealign < 1 || rowToRealign >= m_currentMultiple->NRows())
  249.             THROW_MESSAGE("invalid row number");
  250.         vector < unsigned int > rowsToRemove(1, rowToRealign);
  251.         BlockMultipleAlignment::AlignmentList toRealign;
  252.         TRACE_MESSAGE("extracting for realignment: "
  253.             << m_currentMultiple->GetSequenceOfRow(rowToRealign)->IdentifierString());
  254.         if (!m_currentMultiple->ExtractRows(rowsToRemove, &toRealign))
  255.             THROW_MESSAGE("ExtractRows() failed");
  256.         // fill out DP_BlockInfo structure
  257.         dpBlocks = DP_CreateBlockInfo(blocks.size());
  258.         unsigned int b, r;
  259.         const Block::Range *range, *nextRange;
  260.         unsigned int *loopLengths = new unsigned int[m_currentMultiple->NRows()];
  261.         for (b=0; b<blocks.size(); ++b) {
  262.             range = blocks[b]->GetRangeOfRow(0);
  263.             dpBlocks->blockPositions[b] = range->from;
  264.             dpBlocks->blockSizes[b] = range->to - range->from + 1;
  265.             // calculate max loop lengths for default square well scoring
  266.             if (b < blocks.size() - 1) {
  267.                 for (r=0; r<m_currentMultiple->NRows(); ++r) {
  268.                     range = blocks[b]->GetRangeOfRow(r);
  269.                     nextRange = blocks[b + 1]->GetRangeOfRow(r);
  270.                     loopLengths[r] = nextRange->from - range->to - 1;
  271.                 }
  272.                 dpBlocks->maxLoops[b] = DP_CalculateMaxLoopLength(
  273.                     m_currentMultiple->NRows(), loopLengths, percentile, extension, cutoff);
  274.             }
  275.         }
  276.         delete[] loopLengths;
  277.         // if we're not realigning, freeze blocks to original slave position
  278.         if (blocksToRealign.size() == 0)
  279.             THROW_MESSAGE("need at least one block to realign");
  280.         vector < bool > realignBlock(blocks.size(), false);
  281.         for (r=0; r<blocksToRealign.size(); ++r) {
  282.             if (blocksToRealign[r] >= 0 && blocksToRealign[r] < blocks.size())
  283.                 realignBlock[blocksToRealign[r]] = true;
  284.             else
  285.                 THROW_MESSAGE("block to realign is out of range");
  286.         }
  287.         toRealign.front()->GetUngappedAlignedBlocks(&blocks);
  288.         for (b=0; b<blocks.size(); b++) {
  289.             if (!realignBlock[b])
  290.                 dpBlocks->freezeBlocks[b] = blocks[b]->GetRangeOfRow(1)->from;
  291.             TRACE_MESSAGE("block " << (b+1) << " is " << (realignBlock[b] ? "to be realigned" : "frozen"));
  292.         }
  293.         // set up PSSM
  294.         g_dpPSSM = m_currentMultiple->GetPSSM();
  295.         g_dpBlocks = dpBlocks;
  296.         g_dpQuery = toRealign.front()->GetSequenceOfRow(1);
  297.         // call the block aligner
  298.         if (DP_GlobalBlockAlign(dpBlocks, ScoreByPSSM,
  299.                                 0, toRealign.front()->GetSequenceOfRow(1)->Length() - 1,    // realign on whole query
  300.                                 &dpResult)
  301.                     != STRUCT_DP_FOUND_ALIGNMENT ||
  302.                 dpResult->nBlocks != blocks.size() ||
  303.                 dpResult->firstBlock != 0)
  304.             THROW_MESSAGE("DP_GlobalBlockAlign() failed");
  305.         INFO_MESSAGE("score of new alignment of extracted row with PSSM: " << dpResult->score);
  306.         // adjust new alignment according to dp result
  307.         BlockMultipleAlignment::ModifiableUngappedAlignedBlockList modBlocks;
  308.         toRealign.front()->GetModifiableUngappedAlignedBlocks(&modBlocks);
  309.         for (b=0; b<modBlocks.size(); b++) {
  310.             if (realignBlock[b]) {
  311.                 modBlocks[b]->SetRangeOfRow(1,
  312.                     dpResult->blockPositions[b], dpResult->blockPositions[b] + dpBlocks->blockSizes[b] - 1);
  313.             } else {
  314.                 if (dpResult->blockPositions[b] != modBlocks[b]->GetRangeOfRow(1)->from)    // just to check...
  315.                     THROW_MESSAGE("dpResult block doesn't match frozen position on slave");
  316.             }
  317.         }
  318.         // merge realigned row back onto the end of the multiple alignment
  319.         TRACE_MESSAGE("merging DP results back into multiple alignment");
  320.         if (!m_currentMultiple->MergeAlignment(toRealign.front()))
  321.             THROW_MESSAGE("MergeAlignment() failed");
  322.         // move extracted row back to where it was
  323.         vector < unsigned int > rowOrder(m_currentMultiple->NRows());
  324.         for (r=0; r<m_currentMultiple->NRows(); r++) {
  325.             if (r < rowToRealign)
  326.                 rowOrder[r] = r;
  327.             else if (r == rowToRealign)
  328.                 rowOrder[r] = m_currentMultiple->NRows() - 1;
  329.             else
  330.                 rowOrder[r] = r - 1;
  331.         }
  332.         if (!m_currentMultiple->ReorderRows(rowOrder))
  333.             THROW_MESSAGE("ReorderRows() failed");
  334.         // remove other alignment data, since it no longer matches the multiple
  335.         RemoveAlignAnnot();
  336.         status = true;
  337.     } catch (CException& e) {
  338.         ERROR_MESSAGE("DoLeaveOneOut(): exception: " << e.GetMsg());
  339.     }
  340.     CException::EnableBackgroundReporting(prevState);
  341.     DP_DestroyBlockInfo(dpBlocks);
  342.     DP_DestroyAlignmentResult(dpResult);
  343.     g_dpPSSM = NULL;
  344.     g_dpBlocks = NULL;
  345.     g_dpQuery = NULL;
  346.     return status;
  347. }
  348. void AlignmentUtility::RemoveMultiple(void)
  349. {
  350.     if (m_currentMultiple) {
  351.         delete m_currentMultiple;
  352.         m_currentMultiple = NULL;
  353.     }
  354. }
  355. void AlignmentUtility::RemoveAlignAnnot(void)
  356. {
  357.     m_seqAnnots.clear();
  358.     if (m_alignmentSet) {
  359.         delete m_alignmentSet;
  360.         m_alignmentSet = NULL;
  361.     }
  362. }
  363. const AlignmentUtility::SeqAnnotList& AlignmentUtility::GetSeqAnnots(void)
  364. {
  365.     if (!m_alignmentSet || m_seqAnnots.size() == 0) {
  366.         if (m_alignmentSet)
  367.             ERROR_MESSAGE("ack - shouldn't have m_alignmentSet but empty m_seqAnnots");
  368.         m_alignmentSet = AlignmentSet::CreateFromMultiple(
  369.             m_currentMultiple, &m_seqAnnots, *m_sequenceSet);
  370.     }
  371.     return m_seqAnnots;
  372. }
  373. END_SCOPE(struct_util)
  374. /*
  375. * ---------------------------------------------------------------------------
  376. * $Log: struct_util.cpp,v $
  377. * Revision 1000.0  2004/06/01 18:14:13  gouriano
  378. * PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.9
  379. *
  380. * Revision 1.9  2004/05/28 10:22:13  thiessen
  381. * use delete[] for array
  382. *
  383. * Revision 1.8  2004/05/28 09:46:57  thiessen
  384. * restructure C-toolkit header usage ; move C Bioseq storage into su_sequence_set
  385. *
  386. * Revision 1.7  2004/05/27 21:34:08  thiessen
  387. * add PSSM calculation (requires C-toolkit)
  388. *
  389. * Revision 1.6  2004/05/26 14:49:59  thiessen
  390. * UNDEFINED -> eUndefined
  391. *
  392. * Revision 1.5  2004/05/26 14:45:11  gorelenk
  393. * UNALIGNED->eUnaligned
  394. *
  395. * Revision 1.4  2004/05/26 14:30:16  thiessen
  396. * adjust handling of alingment data ; add row ordering
  397. *
  398. * Revision 1.3  2004/05/26 02:40:24  thiessen
  399. * progress towards LOO - all but PSSM and row ordering
  400. *
  401. * Revision 1.2  2004/05/25 15:52:17  thiessen
  402. * add BlockMultipleAlignment, IBM algorithm
  403. *
  404. * Revision 1.1  2004/05/24 23:04:05  thiessen
  405. * initial checkin
  406. *
  407. */