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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: su_alignment_set.cpp,v $
  4.  * PRODUCTION Revision 1000.0  2004/06/01 18:14:18  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.6
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: su_alignment_set.cpp,v 1000.0 2004/06/01 18:14:18 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 sets of alignments
  38. *
  39. * ===========================================================================
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <corelib/ncbistl.hpp>
  43. #include <objects/seqalign/Dense_diag.hpp>
  44. #include <objects/seqalign/Dense_seg.hpp>
  45. #include <map>
  46. #include <memory>
  47. #include "su_alignment_set.hpp"
  48. #include "su_sequence_set.hpp"
  49. #include "su_block_multiple_alignment.hpp"
  50. #include "su_private.hpp"
  51. USING_NCBI_SCOPE;
  52. USING_SCOPE(objects);
  53. BEGIN_SCOPE(struct_util)
  54. AlignmentSet::AlignmentSet(const SeqAnnotList& seqAnnots, const SequenceSet& sequenceSet)
  55. {
  56.     // screen alignments to make sure they're a type we can handle
  57.     typedef list < CRef < CSeq_align > > SeqAlignList;
  58.     SeqAlignList seqAligns;
  59.     SeqAnnotList::const_iterator n, ne = seqAnnots.end();
  60.     for (n=seqAnnots.begin(); n!=ne; ++n) {
  61.         if (!n->GetObject().GetData().IsAlign())
  62.             THROW_MESSAGE("AlignmentSet::AlignmentSet() - confused by Seq-annot data format");
  63.         if (n != seqAnnots.begin())
  64.             TRACE_MESSAGE("multiple Seq-annots");
  65.         CSeq_annot::C_Data::TAlign::const_iterator
  66.             a, ae = n->GetObject().GetData().GetAlign().end();
  67.         for (a=n->GetObject().GetData().GetAlign().begin(); a!=ae; ++a) {
  68.             if (!(a->GetObject().GetType() != CSeq_align::eType_partial ||
  69.                     a->GetObject().GetType() != CSeq_align::eType_diags) ||
  70.                     !a->GetObject().IsSetDim() || a->GetObject().GetDim() != 2 ||
  71.                     (!a->GetObject().GetSegs().IsDendiag() && !a->GetObject().GetSegs().IsDenseg()))
  72.                 THROW_MESSAGE("AlignmentSet::AlignmentSet() - confused by alignment type");
  73.             seqAligns.push_back(*a);
  74.         }
  75.     }
  76.     if (seqAligns.size() == 0)
  77.         THROW_MESSAGE("AlignmentSet::AlignmentSet() - must have at least one Seq-align");
  78.     // we need to determine the identity of the master sequence; most rigorous way is to look
  79.     // for a Seq-id that is present in all pairwise alignments
  80.     m_master = NULL;
  81.     const Sequence *seq1 = NULL, *seq2 = NULL;
  82.     bool seq1PresentInAll = true, seq2PresentInAll = true;
  83.     // first, find sequences for first pairwise alignment
  84.     const CSeq_id& frontSid = seqAligns.front()->GetSegs().IsDendiag() ?
  85.         seqAligns.front()->GetSegs().GetDendiag().front()->GetIds().front().GetObject() :
  86.         seqAligns.front()->GetSegs().GetDenseg().GetIds().front().GetObject();
  87.     const CSeq_id& backSid = seqAligns.front()->GetSegs().IsDendiag() ?
  88.         seqAligns.front()->GetSegs().GetDendiag().front()->GetIds().back().GetObject() :
  89.         seqAligns.front()->GetSegs().GetDenseg().GetIds().back().GetObject();
  90.     SequenceSet::SequenceList::const_iterator s, se = sequenceSet.m_sequences.end();
  91.     for (s=sequenceSet.m_sequences.begin(); s!=se; ++s) {
  92.         if ((*s)->MatchesSeqId(frontSid)) seq1 = *s;
  93.         if ((*s)->MatchesSeqId(backSid)) seq2 = *s;
  94.         if (seq1 && seq2) break;
  95.     }
  96.     if (!(seq1 && seq2))
  97.         THROW_MESSAGE("AlignmentSet::AlignmentSet() - can't match first pair of Seq-ids to Sequences");
  98.     // now, make sure one of these sequences is present in all the other pairwise alignments
  99.     SeqAlignList::const_iterator a = seqAligns.begin(), ae = seqAligns.end();
  100.     for (++a; a!=ae; ++a) {
  101.         const CSeq_id& frontSid2 = (*a)->GetSegs().IsDendiag() ?
  102.             (*a)->GetSegs().GetDendiag().front()->GetIds().front().GetObject() :
  103.             (*a)->GetSegs().GetDenseg().GetIds().front().GetObject();
  104.         const CSeq_id& backSid2 = (*a)->GetSegs().IsDendiag() ?
  105.             (*a)->GetSegs().GetDendiag().front()->GetIds().back().GetObject() :
  106.             (*a)->GetSegs().GetDenseg().GetIds().back().GetObject();
  107.         if (!seq1->MatchesSeqId(frontSid2) && !seq1->MatchesSeqId(backSid2))
  108.             seq1PresentInAll = false;
  109.         if (!seq2->MatchesSeqId(frontSid2) && !seq2->MatchesSeqId(backSid2))
  110.             seq2PresentInAll = false;
  111.     }
  112.     if (!seq1PresentInAll && !seq2PresentInAll)
  113.         THROW_MESSAGE("AlignmentSet::AlignmentSet() - "
  114.             "all pairwise sequence alignments must have a common master sequence");
  115.     else if (seq1PresentInAll && !seq2PresentInAll)
  116.         m_master = seq1;
  117.     else if (seq2PresentInAll && !seq1PresentInAll)
  118.         m_master = seq2;
  119.     else if (seq1PresentInAll && seq2PresentInAll && seq1 == seq2)
  120.         m_master = seq1;
  121.     // if still ambiguous, just use the first one for now
  122.     if (!m_master) {
  123.         WARNING_MESSAGE("alignment master sequence is ambiguous - using the first one ("
  124.             << seq1->IdentifierString() << ')');
  125.         m_master = seq1;
  126.     }
  127.     TRACE_MESSAGE("determined master sequence: " << m_master->IdentifierString());
  128.     // parse the pairwise alignments
  129.     SeqAlignList::const_iterator l, le = seqAligns.end();
  130.     for (l=seqAligns.begin(); l!=le; ++l)
  131.         m_alignments.push_back(
  132.             CRef<MasterSlaveAlignment>(new MasterSlaveAlignment(**l, m_master, sequenceSet)));
  133.     TRACE_MESSAGE("number of alignments: " << m_alignments.size());
  134. }
  135. AlignmentSet * AlignmentSet::CreateFromMultiple(
  136.     const BlockMultipleAlignment *multiple, SeqAnnotList *newAsnAlignmentData,
  137.     const SequenceSet& sequenceSet, const vector < unsigned int > *rowOrder)
  138. {
  139.     newAsnAlignmentData->clear();
  140.     // sanity check on the row order map
  141.     if (rowOrder) {
  142.         map < unsigned int, unsigned int > rowCheck;
  143.         for (unsigned int i=0; i<rowOrder->size(); ++i)
  144.             rowCheck[(*rowOrder)[i]] = i;
  145.         if (rowOrder->size() != multiple->NRows() || rowCheck.size() != multiple->NRows() || (*rowOrder)[0] != 0) {
  146.             ERROR_MESSAGE("AlignmentSet::CreateFromMultiple() - bad row order vector");
  147.             return NULL;
  148.         }
  149.     }
  150.     // create a single Seq-annot, with 'align' data that holds one Seq-align per slave
  151.     SeqAnnotList newSeqAnnots;
  152.     CRef < CSeq_annot > seqAnnot(new CSeq_annot());
  153.     newSeqAnnots.push_back(seqAnnot);
  154.     CSeq_annot::C_Data::TAlign& seqAligns = seqAnnot->SetData().SetAlign();
  155.     seqAligns.resize((multiple->NRows() == 1) ? 1 : multiple->NRows() - 1);
  156.     CSeq_annot::C_Data::TAlign::iterator sa = seqAligns.begin();
  157.     BlockMultipleAlignment::UngappedAlignedBlockList blocks;
  158.     multiple->GetUngappedAlignedBlocks(&blocks);
  159.     // create Seq-aligns; if there's only one row (the master), then cheat and create an alignment
  160.     // of the master with itself, because asn data doesn't take well to single-row "alignment"
  161.     if (multiple->NRows() > 1) {
  162.         for (unsigned int row=1; row<multiple->NRows(); ++row, ++sa) {
  163.             sa->Reset(CreatePairwiseSeqAlignFromMultipleRow(multiple, blocks,
  164.                 (rowOrder ? (*rowOrder)[row] : row)));
  165.         }
  166.     } else
  167.         sa->Reset(CreatePairwiseSeqAlignFromMultipleRow(multiple, blocks, 0));
  168.     auto_ptr<AlignmentSet> newAlignmentSet;
  169.     try {
  170.         newAlignmentSet.reset(new AlignmentSet(newSeqAnnots, sequenceSet));
  171.     } catch (CException& e) {
  172.         ERROR_MESSAGE(
  173.             "AlignmentSet::CreateFromMultiple() - failed to create AlignmentSet from new asn object: "
  174.             << e.GetMsg());
  175.         return NULL;
  176.     }
  177.     *newAsnAlignmentData = newSeqAnnots;
  178.     return newAlignmentSet.release();
  179. }
  180. ///// MasterSlaveAlignment methods /////
  181. MasterSlaveAlignment::MasterSlaveAlignment(const ncbi::objects::CSeq_align& seqAlign,
  182.     const Sequence *masterSequence, const SequenceSet& sequenceSet) :
  183.         m_master(masterSequence), m_slave(NULL)
  184. {
  185.     // resize alignment and block vector
  186.     m_masterToSlave.resize(m_master->Length(), eUnaligned);
  187.     m_blockStructure.resize(m_master->Length(), eUnaligned);
  188.     // find slave sequence for this alignment, and order (master or slave first)
  189.     const CSeq_id& frontSeqId = seqAlign.GetSegs().IsDendiag() ?
  190.         seqAlign.GetSegs().GetDendiag().front()->GetIds().front().GetObject() :
  191.         seqAlign.GetSegs().GetDenseg().GetIds().front().GetObject();
  192.     const CSeq_id& backSeqId = seqAlign.GetSegs().IsDendiag() ?
  193.         seqAlign.GetSegs().GetDendiag().front()->GetIds().back().GetObject() :
  194.         seqAlign.GetSegs().GetDenseg().GetIds().back().GetObject();
  195.     bool masterFirst = true;
  196.     SequenceSet::SequenceList::const_iterator s, se = sequenceSet.m_sequences.end();
  197.     for (s=sequenceSet.m_sequences.begin(); s!=se; ++s) {
  198.         if (m_master->MatchesSeqId(frontSeqId) &&
  199.             (*s)->MatchesSeqId(backSeqId)) {
  200.             break;
  201.         } else if ((*s)->MatchesSeqId(frontSeqId) &&
  202.                    m_master->MatchesSeqId(backSeqId)) {
  203.             masterFirst = false;
  204.             break;
  205.         }
  206.     }
  207.     if (s == se) {
  208.         ERROR_MESSAGE("MasterSlaveAlignment::MasterSlaveAlignment() - couldn't find matching sequences; "
  209.             << "both " << frontSeqId.AsFastaString() << " and "
  210.             << backSeqId.AsFastaString() << " must be in the sequence list for this file!");
  211.         THROW_MESSAGE("couldn't find matching sequences");
  212.     } else {
  213.         m_slave = *s;
  214.     }
  215.     int masterRes, slaveRes, blockNum = 0;
  216. unsigned int i;
  217.     // unpack dendiag alignment
  218.     if (seqAlign.GetSegs().IsDendiag()) {
  219.         CSeq_align::C_Segs::TDendiag::const_iterator d , de = seqAlign.GetSegs().GetDendiag().end();
  220.         for (d=seqAlign.GetSegs().GetDendiag().begin(); d!=de; ++d, ++blockNum) {
  221.             const CDense_diag& block = d->GetObject();
  222.             if (block.GetDim() != 2 || block.GetIds().size() != 2 || block.GetStarts().size() != 2)
  223.                 THROW_MESSAGE("MasterSlaveAlignment::MasterSlaveAlignment() - incorrect dendiag block dimensions");
  224.             // make sure identities of master and slave sequences match in each block
  225.             if ((masterFirst &&
  226.                     (!m_master->MatchesSeqId(block.GetIds().front().GetObject()) ||
  227.                      !m_slave->MatchesSeqId(block.GetIds().back().GetObject()))) ||
  228.                 (!masterFirst &&
  229.                     (!m_master->MatchesSeqId(block.GetIds().back().GetObject()) ||
  230.                      !m_slave->MatchesSeqId(block.GetIds().front().GetObject()))))
  231.                 THROW_MESSAGE("MasterSlaveAlignment::MasterSlaveAlignment() - mismatched Seq-id in dendiag block");
  232.             // finally, actually unpack the data into the alignment vector
  233.             for (i=0; i<block.GetLen(); ++i) {
  234.                 if (masterFirst) {
  235.                     masterRes = block.GetStarts().front() + i;
  236.                     slaveRes = block.GetStarts().back() + i;
  237.                 } else {
  238.                     masterRes = block.GetStarts().back() + i;
  239.                     slaveRes = block.GetStarts().front() + i;
  240.                 }
  241.                 if ((unsigned) masterRes >= m_master->Length() || (unsigned) slaveRes >= m_slave->Length())
  242.                     THROW_MESSAGE("MasterSlaveAlignment::MasterSlaveAlignment() - seqloc in dendiag block > length of sequence!");
  243.                 m_masterToSlave[masterRes] = slaveRes;
  244.                 m_blockStructure[masterRes] = blockNum;
  245.             }
  246.         }
  247.     }
  248.     // unpack denseg alignment
  249.     else if (seqAlign.GetSegs().IsDenseg()) {
  250.         const CDense_seg& block = seqAlign.GetSegs().GetDenseg();
  251.         if (!block.IsSetDim() && block.GetDim() != 2 ||
  252.                 block.GetIds().size() != 2 ||
  253.                 block.GetStarts().size() != ((unsigned int) 2 * block.GetNumseg()) ||
  254.                 block.GetLens().size() != ((unsigned int) block.GetNumseg()))
  255.             THROW_MESSAGE("MasterSlaveAlignment::MasterSlaveAlignment() - incorrect denseg block dimension");
  256.         // make sure identities of master and slave sequences match in each block
  257.         if ((masterFirst &&
  258.                 (!m_master->MatchesSeqId(block.GetIds().front().GetObject()) ||
  259.                  !m_slave->MatchesSeqId(block.GetIds().back().GetObject()))) ||
  260.             (!masterFirst &&
  261.                 (!m_master->MatchesSeqId(block.GetIds().back().GetObject()) ||
  262.                  !m_slave->MatchesSeqId(block.GetIds().front().GetObject()))))
  263.             THROW_MESSAGE("MasterSlaveAlignment::MasterSlaveAlignment() - mismatched Seq-id in denseg block");
  264.         // finally, actually unpack the data into the alignment vector
  265.         CDense_seg::TStarts::const_iterator starts = block.GetStarts().begin();
  266.         CDense_seg::TLens::const_iterator lens, le = block.GetLens().end();
  267.         for (lens=block.GetLens().begin(); lens!=le; ++lens) {
  268.             if (masterFirst) {
  269.                 masterRes = *(starts++);
  270.                 slaveRes = *(starts++);
  271.             } else {
  272.                 slaveRes = *(starts++);
  273.                 masterRes = *(starts++);
  274.             }
  275.             if (masterRes != -1 && slaveRes != -1) { // skip gaps
  276.                 if ((masterRes + *lens - 1) >= m_master->Length() ||
  277.                         (slaveRes + *lens - 1) >= m_slave->Length())
  278.                     THROW_MESSAGE("MasterSlaveAlignment::MasterSlaveAlignment() - "
  279.                         "seqloc in denseg block > length of sequence!");
  280.                 for (i=0; i<*lens; ++i) {
  281.                     m_masterToSlave[masterRes + i] = slaveRes + i;
  282.                     m_blockStructure[masterRes + i] = blockNum;
  283.                 }
  284.                 ++blockNum; // a "block" of a denseg is an aligned (non-gap) segment
  285.             }
  286.         }
  287.     }
  288. }
  289. END_SCOPE(struct_util)
  290. /*
  291. * ---------------------------------------------------------------------------
  292. * $Log: su_alignment_set.cpp,v $
  293. * Revision 1000.0  2004/06/01 18:14:18  gouriano
  294. * PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.6
  295. *
  296. * Revision 1.6  2004/05/26 14:45:11  gorelenk
  297. * UNALIGNED->eUnaligned
  298. *
  299. * Revision 1.5  2004/05/26 01:58:05  ucko
  300. * Move #include <corelib/ncbi_limits.hpp> to su_alignment_set.hpp.
  301. *
  302. * Revision 1.4  2004/05/25 21:23:03  ucko
  303. * Remove definition of MasterSlaveAlignment::UNALIGNED (now part of an enum)
  304. *
  305. * Revision 1.3  2004/05/25 16:12:30  thiessen
  306. * fix GCC warnings
  307. *
  308. * Revision 1.2  2004/05/25 15:52:17  thiessen
  309. * add BlockMultipleAlignment, IBM algorithm
  310. *
  311. * Revision 1.1  2004/05/24 23:04:05  thiessen
  312. * initial checkin
  313. *
  314. */