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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: su_sequence_set.cpp,v $
  4.  * PRODUCTION Revision 1000.0  2004/06/01 18:14:43  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.3
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: su_sequence_set.cpp,v 1000.0 2004/06/01 18:14:43 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 sequences
  38. *
  39. * ===========================================================================
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <corelib/ncbistd.hpp>
  43. #include <corelib/ncbistre.hpp>
  44. #include <corelib/ncbistl.hpp>
  45. #include <vector>
  46. #include <map>
  47. #include <objects/seqloc/Seq_id.hpp>
  48. #include <objects/seqloc/PDB_seq_id.hpp>
  49. #include <objects/seqloc/PDB_mol_id.hpp>
  50. #include <objects/general/Object_id.hpp>
  51. #include <objects/seqset/Bioseq_set.hpp>
  52. #include <objects/seq/Seq_inst.hpp>
  53. #include <objects/seq/Seq_data.hpp>
  54. #include <objects/seq/NCBIeaa.hpp>
  55. #include <objects/seq/IUPACaa.hpp>
  56. #include <objects/seq/NCBIstdaa.hpp>
  57. #include <objects/seq/NCBI4na.hpp>
  58. #include <objects/seq/NCBI8na.hpp>
  59. #include <objects/seq/NCBI2na.hpp>
  60. #include <objects/seq/IUPACna.hpp>
  61. #include <objects/seq/Seq_annot.hpp>
  62. #include <objects/general/Dbtag.hpp>
  63. #include <objects/seqloc/Textseq_id.hpp>
  64. #include <objects/seq/Seq_descr.hpp>
  65. #include <objects/seq/Seqdesc.hpp>
  66. #include <objects/seqblock/PDB_block.hpp>
  67. #include <objects/seqfeat/BioSource.hpp>
  68. #include <objects/seqfeat/Org_ref.hpp>
  69. #include "su_sequence_set.hpp"
  70. #include "su_private.hpp"
  71. // borrow Cn3D's asn conversion functions
  72. #include "../src/app/cn3d/asn_converter.hpp"
  73. // C-toolkit stuff for BioseqPtr creation
  74. #include <objseq.h>
  75. #include <objalign.h>
  76. USING_NCBI_SCOPE;
  77. USING_SCOPE(objects);
  78. BEGIN_SCOPE(struct_util)
  79. // holds C Bioseqs associated with Sequences
  80. typedef map < const Sequence *, Bioseq * > BioseqMap;
  81. static BioseqMap bioseqs;
  82. void AddCSeqId(SeqIdPtr *sid, const ncbi::objects::CSeq_id& cppid)
  83. {
  84.     string err;
  85.     ValNode *vn = (SeqIdPtr) Cn3D::ConvertAsnFromCPPToC(cppid, (AsnReadFunc) SeqIdAsnRead, &err);
  86.     if (!vn || err.size() > 0) {
  87.         ERROR_MESSAGE("AddCSeqId() - ConvertAsnFromCPPToC() failed");
  88.         return;
  89.     }
  90.     ValNodeLink(sid, vn);
  91. }
  92. static void AddCSeqIdAll(SeqIdPtr *id, const Sequence& sequence)
  93. {
  94.     CBioseq::TId::const_iterator i, ie = sequence.GetAllIdentifiers().end();
  95.     for (i=sequence.GetAllIdentifiers().begin(); i!=ie; ++i)
  96.         AddCSeqId(id, **i);
  97. }
  98. BioseqPtr GetOrCreateBioseq(const Sequence *sequence)
  99. {
  100.     if (!sequence || !sequence->m_isProtein) {
  101.         ERROR_MESSAGE("GetOrCreateBioseq() - got non-protein or NULL Sequence");
  102.         return NULL;
  103.     }
  104.     // if already done
  105.     BioseqMap::const_iterator b = bioseqs.find(sequence);
  106.     if (b != bioseqs.end())
  107.         return b->second;
  108.     // create new Bioseq and fill it in from Sequence data
  109.     BioseqPtr bioseq = BioseqNew();
  110.     bioseq->mol = Seq_mol_aa;
  111.     bioseq->seq_data_type = Seq_code_ncbieaa;
  112.     bioseq->repr = Seq_repr_raw;
  113.     bioseq->length = sequence->Length();
  114.     bioseq->seq_data = BSNew(bioseq->length);
  115.     BSWrite(bioseq->seq_data, const_cast<char*>(sequence->m_sequenceString.c_str()), bioseq->length);
  116.     // create Seq-id
  117.     AddCSeqIdAll(&(bioseq->id), *sequence);
  118.     // store Bioseq
  119.     bioseqs[sequence] = bioseq;
  120.     return bioseq;
  121. }
  122. static void UnpackSeqSet(CBioseq_set& bss, SequenceSet::SequenceList& seqlist)
  123. {
  124.     CBioseq_set::TSeq_set::iterator q, qe = bss.SetSeq_set().end();
  125.     for (q=bss.SetSeq_set().begin(); q!=qe; ++q) {
  126.         if (q->GetObject().IsSeq()) {
  127.             // only store amino acid or nucleotide sequences
  128.             if (q->GetObject().GetSeq().GetInst().GetMol() != CSeq_inst::eMol_aa &&
  129.                 q->GetObject().GetSeq().GetInst().GetMol() != CSeq_inst::eMol_dna &&
  130.                 q->GetObject().GetSeq().GetInst().GetMol() != CSeq_inst::eMol_rna &&
  131.                 q->GetObject().GetSeq().GetInst().GetMol() != CSeq_inst::eMol_na)
  132.                 continue;
  133.             CRef < Sequence > sequence(new Sequence(q->GetObject().SetSeq()));
  134.             seqlist.push_back(sequence);
  135.         } else { // Bioseq-set
  136.             UnpackSeqSet(q->GetObject().SetSet(), seqlist);
  137.         }
  138.     }
  139. }
  140. static void UnpackSeqEntry(CSeq_entry& seqEntry, SequenceSet::SequenceList& seqlist)
  141. {
  142.     if (seqEntry.IsSeq()) {
  143.         CRef < Sequence > sequence(new Sequence(seqEntry.SetSeq()));
  144.         seqlist.push_back(sequence);
  145.     } else { // Bioseq-set
  146.         UnpackSeqSet(seqEntry.SetSet(), seqlist);
  147.     }
  148. }
  149. SequenceSet::SequenceSet(SeqEntryList& seqEntries)
  150. {
  151.     SeqEntryList::iterator s, se = seqEntries.end();
  152.     for (s=seqEntries.begin(); s!=se; ++s)
  153.         UnpackSeqEntry(s->GetObject(), m_sequences);
  154.     TRACE_MESSAGE("number of sequences: " << m_sequences.size());
  155. }
  156. #define FIRSTOF2(byte) (((byte) & 0xF0) >> 4)
  157. #define SECONDOF2(byte) ((byte) & 0x0F)
  158. static void StringFrom4na(const vector< char >& vec, string *str, bool isDNA)
  159. {
  160.     if (SECONDOF2(vec.back()) > 0)
  161.         str->resize(vec.size() * 2);
  162.     else
  163.         str->resize(vec.size() * 2 - 1);
  164.     // first, extract 4-bit values
  165.     unsigned int i;
  166.     for (i=0; i<vec.size(); ++i) {
  167.         str->at(2*i) = FIRSTOF2(vec[i]);
  168.         if (SECONDOF2(vec[i]) > 0) str->at(2*i + 1) = SECONDOF2(vec[i]);
  169.     }
  170.     // then convert 4-bit values to ascii characters
  171.     for (i=0; i<str->size(); ++i) {
  172.         switch (str->at(i)) {
  173.             case 1: str->at(i) = 'A'; break;
  174.             case 2: str->at(i) = 'C'; break;
  175.             case 4: str->at(i) = 'G'; break;
  176.             case 8: isDNA ? str->at(i) = 'T' : str->at(i) = 'U'; break;
  177.             default:
  178.                 str->at(i) = 'X';
  179.         }
  180.     }
  181. }
  182. #define FIRSTOF4(byte) (((byte) & 0xC0) >> 6)
  183. #define SECONDOF4(byte) (((byte) & 0x30) >> 4)
  184. #define THIRDOF4(byte) (((byte) & 0x0C) >> 2)
  185. #define FOURTHOF4(byte) ((byte) & 0x03)
  186. static void StringFrom2na(const vector< char >& vec, string *str, bool isDNA)
  187. {
  188.     str->resize(vec.size() * 4);
  189.     // first, extract 4-bit values
  190.     unsigned int i;
  191.     for (i=0; i<vec.size(); ++i) {
  192.         str->at(4*i) = FIRSTOF4(vec[i]);
  193.         str->at(4*i + 1) = SECONDOF4(vec[i]);
  194.         str->at(4*i + 2) = THIRDOF4(vec[i]);
  195.         str->at(4*i + 3) = FOURTHOF4(vec[i]);
  196.     }
  197.     // then convert 4-bit values to ascii characters
  198.     for (i=0; i<str->size(); ++i) {
  199.         switch (str->at(i)) {
  200.             case 0: str->at(i) = 'A'; break;
  201.             case 1: str->at(i) = 'C'; break;
  202.             case 2: str->at(i) = 'G'; break;
  203.             case 3: isDNA ? str->at(i) = 'T' : str->at(i) = 'U'; break;
  204.         }
  205.     }
  206. }
  207. static void StringFromStdaa(const vector < char >& vec, string *str)
  208. {
  209.     static const char *stdaaMap = "-ABCDEFGHIKLMNPQRSTVWXYZU*";
  210.     str->resize(vec.size());
  211.     for (unsigned int i=0; i<vec.size(); ++i)
  212.         str->at(i) = stdaaMap[vec[i]];
  213. }
  214. Sequence::Sequence(ncbi::objects::CBioseq& bioseq) :
  215.     m_bioseqASN(&bioseq), m_isProtein(false)
  216. {
  217.     // fill out description
  218.     if (bioseq.IsSetDescr()) {
  219.         string defline, taxid;
  220.         CSeq_descr::Tdata::const_iterator d, de = bioseq.GetDescr().Get().end();
  221.         for (d=bioseq.GetDescr().Get().begin(); d!=de; ++d) {
  222.             // get "defline" from title or compound
  223.             if ((*d)->IsTitle()) {              // prefer title over compound
  224.                 defline = (*d)->GetTitle();
  225.             } else if (defline.size() == 0 && (*d)->IsPdb() && (*d)->GetPdb().GetCompound().size() > 0) {
  226.                 defline = (*d)->GetPdb().GetCompound().front();
  227.             }
  228.             // get taxonomy
  229.             if ((*d)->IsSource()) {
  230.                 if ((*d)->GetSource().GetOrg().IsSetTaxname())
  231.                     taxid = (*d)->GetSource().GetOrg().GetTaxname();
  232.                 else if ((*d)->GetSource().GetOrg().IsSetCommon())
  233.                     taxid = (*d)->GetSource().GetOrg().GetCommon();
  234.             }
  235.         }
  236.         if (taxid.size() > 0)
  237.             m_description = string("[") + taxid + ']';
  238.         if (defline.size() > 0) {
  239.             if (taxid.size() > 0)
  240.                 m_description += ' ';
  241.             m_description += defline;
  242.         }
  243.     }
  244.     // get sequence string
  245.     if (bioseq.GetInst().GetRepr() == CSeq_inst::eRepr_raw && bioseq.GetInst().IsSetSeq_data()) {
  246.         // protein formats
  247.         if (bioseq.GetInst().GetSeq_data().IsNcbieaa()) {
  248.             m_sequenceString = bioseq.GetInst().GetSeq_data().GetNcbieaa().Get();
  249.             m_isProtein = true;
  250.         } else if (bioseq.GetInst().GetSeq_data().IsIupacaa()) {
  251.             m_sequenceString = bioseq.GetInst().GetSeq_data().GetIupacaa().Get();
  252.             m_isProtein = true;
  253.         } else if (bioseq.GetInst().GetSeq_data().IsNcbistdaa()) {
  254.             StringFromStdaa(bioseq.GetInst().GetSeq_data().GetNcbistdaa().Get(), &m_sequenceString);
  255.             m_isProtein = true;
  256.         }
  257.         // nucleotide formats
  258.         else if (bioseq.GetInst().GetSeq_data().IsIupacna()) {
  259.             m_sequenceString = bioseq.GetInst().GetSeq_data().GetIupacna().Get();
  260.             // convert 'T' to 'U' for RNA
  261.             if (bioseq.GetInst().GetMol() == CSeq_inst::eMol_rna) {
  262.                 for (unsigned int i=0; i<m_sequenceString.size(); ++i) {
  263.                     if (m_sequenceString[i] == 'T')
  264.                         m_sequenceString[i] = 'U';
  265.                 }
  266.             }
  267.         } else if (bioseq.GetInst().GetSeq_data().IsNcbi4na()) {
  268.             StringFrom4na(bioseq.GetInst().GetSeq_data().GetNcbi4na().Get(), &m_sequenceString,
  269.                 (bioseq.GetInst().GetMol() == CSeq_inst::eMol_dna));
  270.         } else if (bioseq.GetInst().GetSeq_data().IsNcbi8na()) {  // same repr. for non-X as 4na
  271.             StringFrom4na(bioseq.GetInst().GetSeq_data().GetNcbi8na().Get(), &m_sequenceString,
  272.                 (bioseq.GetInst().GetMol() == CSeq_inst::eMol_dna));
  273.         } else if (bioseq.GetInst().GetSeq_data().IsNcbi2na()) {
  274.             StringFrom2na(bioseq.GetInst().GetSeq_data().GetNcbi2na().Get(), &m_sequenceString,
  275.                 (bioseq.GetInst().GetMol() == CSeq_inst::eMol_dna));
  276.             if (bioseq.GetInst().IsSetLength() && bioseq.GetInst().GetLength() < m_sequenceString.length())
  277.                 m_sequenceString.resize(bioseq.GetInst().GetLength());
  278.         }
  279.         else
  280.             THROW_MESSAGE("Sequence::Sequence(): confused by sequence format");
  281.         // check length
  282.         if (bioseq.GetInst().IsSetLength() && bioseq.GetInst().GetLength() != m_sequenceString.length())
  283.             THROW_MESSAGE("Sequence::Sequence() - sequence string length mismatch");
  284.         // force uppercase
  285.         for (unsigned int i=0; i<m_sequenceString.size(); ++i)
  286.             m_sequenceString[i] = toupper(m_sequenceString[i]);
  287.     } else
  288.         THROW_MESSAGE("Sequence::Sequence(): confused by sequence representation");
  289. }
  290. Sequence::~Sequence(void)
  291. {
  292.     BioseqMap::iterator b = bioseqs.find(this);
  293.     if (b != bioseqs.end()) {
  294.         BioseqFree(b->second);
  295.         bioseqs.erase(b);
  296.     }
  297. }
  298. #define RETURN_FIRST_SEQID_THAT_(is) 
  299.     for (i=m_bioseqASN->GetId().begin(); i!=ie; ++i) 
  300.         if ((*i)->is()) 
  301.             return **i
  302. const CSeq_id& Sequence::GetPreferredIdentifier(void) const
  303. {
  304.     CBioseq::TId::const_iterator i, ie = m_bioseqASN->GetId().end();
  305.     // try to find one of these first
  306.     RETURN_FIRST_SEQID_THAT_(IsPdb);
  307.     RETURN_FIRST_SEQID_THAT_(IsGi);
  308.     // otherwise, just use the first one
  309.     return m_bioseqASN->GetId().front().GetObject();
  310. }
  311. bool Sequence::MatchesSeqId(const CSeq_id& seqID) const
  312. {
  313.     CBioseq::TId::const_iterator i, ie = m_bioseqASN->GetId().end();
  314.     for (i=m_bioseqASN->GetId().begin(); i!=ie; ++i) {
  315.         if (seqID.Match(**i))
  316.             return true;
  317.     }
  318.     return false;
  319. }
  320. string Sequence::IdentifierString(void) const
  321. {
  322.     return CSeq_id::GetStringDescr(*m_bioseqASN, CSeq_id::eFormat_FastA);
  323. }
  324. END_SCOPE(struct_util)
  325. /*
  326. * ---------------------------------------------------------------------------
  327. * $Log: su_sequence_set.cpp,v $
  328. * Revision 1000.0  2004/06/01 18:14:43  gouriano
  329. * PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.3
  330. *
  331. * Revision 1.3  2004/05/28 09:46:57  thiessen
  332. * restructure C-toolkit header usage ; move C Bioseq storage into su_sequence_set
  333. *
  334. * Revision 1.2  2004/05/25 15:52:18  thiessen
  335. * add BlockMultipleAlignment, IBM algorithm
  336. *
  337. * Revision 1.1  2004/05/24 23:04:05  thiessen
  338. * initial checkin
  339. *
  340. */