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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: utils.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:45:35  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: utils.cpp,v 1000.1 2004/06/01 19:45:35 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. * Author:  Mati Shomrat, NCBI
  35. *
  36. * File Description:
  37. *   shared utility functions
  38. *
  39. */
  40. #include <ncbi_pch.hpp>
  41. #include <corelib/ncbistd.hpp>
  42. #include <objects/general/Date.hpp>
  43. #include <objects/general/User_object.hpp>
  44. #include <objects/general/User_field.hpp>
  45. #include <objects/general/Object_id.hpp>
  46. #include <objects/seq/Bioseq.hpp>
  47. #include <objects/seq/Seq_inst.hpp>
  48. #include <objects/seq/Seq_ext.hpp>
  49. #include <objects/seq/Delta_ext.hpp>
  50. #include <objects/seq/Delta_seq.hpp>
  51. #include <objects/seq/Seq_literal.hpp>
  52. #include <objects/seq/MolInfo.hpp>
  53. #include <objects/seq/seqport_util.hpp>
  54. #include <objects/seqloc/Seq_loc.hpp>
  55. #include <objmgr/scope.hpp>
  56. #include <objmgr/bioseq_handle.hpp>
  57. #include <objmgr/seqdesc_ci.hpp>
  58. #include <objmgr/util/sequence.hpp>
  59. #include "utils.hpp"
  60. BEGIN_NCBI_SCOPE
  61. BEGIN_SCOPE(objects)
  62. string ExpandTildes(const string& s, ETildeStyle style)
  63. {
  64.     if ( style == eTilde_tilde ) {
  65.         return s;
  66.     }
  67.     SIZE_TYPE start = 0, tilde, length = s.length();
  68.     string result;
  69.     while ( (start < length)  &&  (tilde = s.find('~', start)) != NPOS ) {
  70.         result += s.substr(start, tilde - start);
  71.         char next = (tilde + 1) < length ? s[tilde + 1] : 0;
  72.         switch ( style ) {
  73.         case eTilde_space:
  74.             if ( (tilde + 1 < length  &&  isdigit(next) )  ||
  75.                  (tilde + 2 < length  &&  (next == ' '  ||  next == '(')  &&
  76.                   isdigit(s[tilde + 2]))) {
  77.                 result += '~';
  78.             } else {
  79.                 result += ' ';
  80.             }
  81.             start = tilde + 1;
  82.             break;
  83.             
  84.         case eTilde_newline:
  85.             if ( tilde + 1 < length  &&  s[tilde + 1] == '~' ) {
  86.                 result += '~';
  87.                 start = tilde + 2;
  88.             } else {
  89.                 result += 'n';
  90.                 start = tilde + 1;
  91.             }
  92.             break;
  93.             
  94.         default: // just keep it, for lack of better ideas
  95.             result += '~';
  96.             start = tilde + 1;
  97.             break;
  98.         }
  99.     }
  100.     result += s.substr(start);
  101.     return result;
  102. }
  103. void StripSpaces(string& str)
  104. {
  105.     if ( str.empty() ) {
  106.         return;
  107.     }
  108.     string::iterator new_str = str.begin();
  109.     NON_CONST_ITERATE(string, it, str) {
  110.         *new_str++ = *it;
  111.         if ( (*it == ' ')  ||  (*it == 't')  ||  (*it == '(') ) {
  112.             for (++it; *it == ' ' || *it == 't'; ++it) continue;
  113.             if (*it == ')' || *it == ',') {
  114.                 new_str--;
  115.             }
  116.         } else {
  117.             it++;
  118.         }
  119.     }
  120.     str.erase(new_str, str.end());
  121. }
  122. bool RemovePeriodFromEnd(string& str, bool keep_ellipsis)
  123. {
  124.     static const string period = ".";
  125.     static const string ellipsis = "...";
  126.     if ( NStr::EndsWith(str, period) ) {
  127.         if ( !keep_ellipsis  ||  !NStr::EndsWith(str, ellipsis) ) {
  128.             str.erase(str.length() - 1);
  129.             return true;
  130.         }
  131.     }
  132.     return false;
  133. }
  134. static bool s_IsWholeWord(const string& str, size_t pos, const string& word)
  135. {
  136.     // NB: To preserve the behavior of the C toolkit we only test on the left.
  137.     // This was an old bug in the C toolkit that was never fixed and by now
  138.     // has become the expected behavior.
  139.     return (pos > 0) ?
  140.         isspace(str[pos - 1])  ||  ispunct(str[pos - 1]) : true;
  141. }
  142. void JoinNoRedund(string& to, const string& prefix, const string& str)
  143. {
  144.     if ( str.empty() ) {
  145.         return;
  146.     }
  147.     if ( to.empty() ) {
  148.         to += str;
  149.         return;
  150.     }
  151.     
  152.     size_t pos = NPOS;
  153.     for ( pos = NStr::Find(to, str);
  154.           pos != NPOS  &&  !s_IsWholeWord(to, pos, str);
  155.           pos += str.length());
  156.     if ( pos == NPOS  ||  !s_IsWholeWord(to, pos, str) ) {
  157.         to += prefix;
  158.         to += str;
  159.     }
  160. }
  161. string JoinNoRedund(const list<string>& l, const string& delim)
  162. {
  163.     if ( l.empty() ) {
  164.         return kEmptyStr;
  165.     }
  166.     string result = l.front();
  167.     list<string>::const_iterator it = l.begin();
  168.     while ( ++it != l.end() ) {
  169.         JoinNoRedund(result, delim, *it);
  170.     }
  171.     return result;
  172. }
  173. // Validate the correct format of an accession string.
  174. bool ValidateAccession(const string& acc)
  175. {
  176.     if ( acc.empty() ) {
  177.         return false;
  178.     }
  179.     if ( acc.length() >= 16 ) {
  180.         return false;
  181.     }
  182.     // first character must be uppercase letter
  183.     if ( !(isalpha(acc[0])  &&  isupper(acc[0])) ) {
  184.         return false;
  185.     }
  186.     size_t num_alpha   = 0,
  187.            num_undersc = 0,
  188.            num_digits  = 0;
  189.     const char* ptr = acc.c_str();
  190.     if ( NStr::StartsWith(acc, "NZ_") ) {
  191.         ptr += 3;
  192.     }
  193.     for ( ; isalpha(*ptr); ++ptr, ++num_alpha );
  194.     for ( ; *ptr == '_'; ++ptr, ++num_undersc );
  195.     for ( ; isdigit(*ptr); ++ptr, ++num_digits );
  196.     if ( (*ptr != '')  &&  (*ptr != ' ')  &&  (*ptr != '.') ) {
  197.         return false;
  198.     }
  199.     switch ( num_undersc ) {
  200.     case 0:
  201.         {{
  202.             if ( (num_alpha == 1  &&  num_digits == 5)  ||
  203.                  (num_alpha == 2  &&  num_digits == 6)  ||
  204.                  (num_alpha == 3  &&  num_digits == 5)  || 
  205.                  (num_alpha == 4  &&  num_digits == 8) ) {
  206.                 return true;
  207.             }
  208.         }}
  209.         break;
  210.     case 1:
  211.         {{
  212.             // RefSeq accession
  213.             if ( (num_alpha != 2)  ||
  214.                  (num_digits != 6  &&  num_digits != 8  &&  num_digits != 9) ) {
  215.                 return false;
  216.             }
  217.             
  218.             char first_letter = acc[0];
  219.             char second_letter = acc[1];
  220.             if ( first_letter == 'N' ) {
  221.                 if ( second_letter == 'C'  ||  second_letter == 'G'  ||
  222.                      second_letter == 'M'  ||  second_letter == 'R'  ||
  223.                      second_letter == 'P'  ||  second_letter == 'W'  ||
  224.                      second_letter == 'T' ) {
  225.                     return true;
  226.                 }
  227.             } else if ( first_letter == 'X' ) {
  228.                 if ( second_letter == 'M'  ||  second_letter == 'R'  ||
  229.                      second_letter == 'P' ) {
  230.                     return true;
  231.                 }
  232.             } else if ( first_letter == 'Z' ) {
  233.                 if ( second_letter == 'P' ) {
  234.                     return true;
  235.                 }
  236.             }
  237.         }}
  238.         break;
  239.     default:
  240.         return false;
  241.     }
  242.     return false;
  243. }
  244. void DateToString(const CDate& date, string& str,  bool is_cit_sub)
  245. {
  246.     static const string regular_format  = "%{%2D%|01%}-%{%3N%|JUN%}-%Y";
  247.     static const string cit_sub_format = "%{%2D%|??%}-%{%3N%|???%}-%Y";
  248.     const string& format = is_cit_sub ? cit_sub_format : regular_format;
  249.     string date_str;
  250.     date.GetDate(&date_str, format);
  251.     NStr::ToUpper(date_str);
  252.     str.append(date_str);
  253. }
  254. void GetDeltaSeqSummary(const CBioseq_Handle& seq, SDeltaSeqSummary& summary)
  255. {
  256.     if ( !seq.IsSetInst()                                ||
  257.          !seq.IsSetInst_Repr()                           ||
  258.          !(seq.GetInst_Repr() == CSeq_inst::eRepr_delta) ||
  259.          !seq.IsSetInst_Ext()                            ||
  260.          !seq.GetInst_Ext().IsDelta() ) {
  261.         return;
  262.     }
  263.     SDeltaSeqSummary temp;
  264.     CScope& scope = seq.GetScope();
  265.     const CDelta_ext::Tdata& segs = seq.GetInst_Ext().GetDelta().Get();
  266.     temp.num_segs = segs.size();
  267.     
  268.     size_t len = 0;
  269.     CNcbiOstrstream text;
  270.     CDelta_ext::Tdata::const_iterator curr = segs.begin();
  271.     CDelta_ext::Tdata::const_iterator end = segs.end();
  272.     CDelta_ext::Tdata::const_iterator next;
  273.     for ( ; curr != end; curr = next ) {
  274.         {{
  275.             // set next to one after curr
  276.             next = curr; ++next;
  277.         }}
  278.         size_t from = len + 1;
  279.         switch ( (*curr)->Which() ) {
  280.         case CDelta_seq::e_Loc:
  281.             {{
  282.                 const CDelta_seq::TLoc& loc = (*curr)->GetLoc();
  283.                 if ( loc.IsNull() ) {  // gap
  284.                     ++temp.num_gaps;
  285.                     text << "* " << from << ' ' << len 
  286.                          << " gap of unknown length~";
  287.                 } else {
  288.                     size_t tlen = sequence::GetLength(loc, &scope);
  289.                     len += tlen;
  290.                     temp.residues += tlen;
  291.                     text << "* " << from << " " << len << ": contig of " 
  292.                         << tlen << " bp in length~";
  293.                 }
  294.             }}  
  295.             break;
  296.         case CDelta_seq::e_Literal:
  297.             {{
  298.                 const CDelta_seq::TLiteral& lit = (*curr)->GetLiteral();
  299.                 size_t lit_len = lit.CanGetLength() ? lit.GetLength() : 0;
  300.                 len += lit_len;
  301.                 if ( lit.CanGetSeq_data() ) {
  302.                     temp.residues += lit_len;
  303.                     while ( next != end  &&  (*next)->IsLiteral()  &&
  304.                         (*next)->GetLiteral().CanGetSeq_data() ) {
  305.                         const CDelta_seq::TLiteral& next_lit = (*next)->GetLiteral();
  306.                         size_t next_len = next_lit.CanGetLength() ?
  307.                             next_lit.GetLength() : 0;
  308.                         lit_len += next_len;
  309.                         len += next_len;
  310.                         temp.residues += next_len;
  311.                         ++next;
  312.                     }
  313.                     text << "* " << from << " " << len << ": contig of " 
  314.                          << lit_len << " bp in length~";
  315.                 } else {
  316.                     bool unk = false;
  317.                     ++temp.num_gaps;
  318.                     if ( lit.CanGetFuzz() ) {
  319.                         const CSeq_literal::TFuzz& fuzz = lit.GetFuzz();
  320.                         if ( fuzz.IsLim()  &&  
  321.                              fuzz.GetLim() == CInt_fuzz::eLim_unk ) {
  322.                             unk = true;
  323.                             ++temp.num_faked_gaps;
  324.                             if ( from > len ) {
  325.                                 text << "*                    gap of unknown length~";
  326.                             } else {
  327.                                 text << "* " << from << " " << len 
  328.                                      << ": gap of unknown length~";
  329.                             }
  330.                         }
  331.                     }
  332.                     if ( !unk ) {
  333.                         text << "* " << from << " " << len << ": gap of "
  334.                              << lit_len << " bp~";
  335.                     }
  336.                 }
  337.             }}
  338.             break;
  339.         default:
  340.             break;
  341.         }
  342.     }
  343.     summary = temp;
  344.     summary.text = CNcbiOstrstreamToString(text);
  345. }
  346. const string& GetTechString(int tech)
  347. {
  348.     static const string concept_trans_str = "conceptual translation";
  349.     static const string seq_pept_str = "direct peptide sequencing";
  350.     static const string both_str = "conceptual translation with partial peptide sequencing";
  351.     static const string seq_pept_overlap_str = "sequenced peptide, ordered by overlap";
  352.     static const string seq_pept_homol_str = "sequenced peptide, ordered by homology";
  353.     static const string concept_trans_a_str = "conceptual translation supplied by author";
  354.     
  355.     switch ( tech ) {
  356.     case CMolInfo::eTech_concept_trans:
  357.         return concept_trans_str;
  358.     case CMolInfo::eTech_seq_pept :
  359.         return seq_pept_str;
  360.     case CMolInfo::eTech_both:
  361.         return both_str;
  362.     case CMolInfo::eTech_seq_pept_overlap:
  363.         return seq_pept_overlap_str;
  364.     case CMolInfo::eTech_seq_pept_homol:
  365.         return seq_pept_homol_str;
  366.     case CMolInfo::eTech_concept_trans_a:
  367.         return concept_trans_a_str;
  368.     default:
  369.         return kEmptyStr;
  370.     }
  371.     return kEmptyStr;
  372. }
  373. bool s_IsModelEvidanceUop(const CUser_object& uo)
  374. {
  375.     return (uo.CanGetType()  &&  uo.GetType().IsStr()  &&
  376.         uo.GetType().GetStr() == "ModelEvidence");
  377. }
  378. const CUser_object* s_FindModelEvidanceUop(const CUser_object& uo)
  379. {
  380.     if ( s_IsModelEvidanceUop(uo) ) {
  381.         return &uo;
  382.     }
  383.     const CUser_object* temp = 0;
  384.     ITERATE (CUser_object::TData, ufi, uo.GetData()) {
  385.         const CUser_field& uf = **ufi;
  386.         if ( !uf.CanGetData() ) {
  387.             continue;
  388.         }
  389.         const CUser_field::TData& data = uf.GetData();
  390.         switch ( data.Which() ) {
  391.         case CUser_field::TData::e_Object:
  392.             temp = s_FindModelEvidanceUop(data.GetObject());
  393.             break;
  394.         case CUser_field::TData::e_Objects:
  395.             ITERATE (CUser_field::TData::TObjects, obj, data.GetObjects()) {
  396.                 temp = s_FindModelEvidanceUop(**obj);
  397.                 if ( temp != 0 ) {
  398.                     break;
  399.                 }
  400.             }
  401.             break;
  402.         default:
  403.             break;
  404.         }
  405.         if ( temp != 0 ) {
  406.             break;
  407.         }
  408.     }
  409.     return temp;
  410. }
  411. bool s_GetModelEvidance(const CBioseq_Handle& bsh, SModelEvidance& me)
  412. {
  413.     const CUser_object* moduop = 0;
  414.     bool result = false;
  415.     for (CSeqdesc_CI it(bsh, CSeqdesc::e_User);  it;  ++it) {
  416.         const CUser_object* modup = s_FindModelEvidanceUop(it->GetUser());
  417.         if ( modup != 0 ) {
  418.             result = true;
  419.             const CUser_field* ufp = 0;
  420.             if ( moduop->HasField("Contig Name") ) {
  421.                 ufp = &(moduop->GetField("Contig Name"));
  422.                 if ( ufp->CanGetData()  &&  ufp->GetData().IsStr() ) {
  423.                     me.name = ufp->GetData().GetStr();
  424.                 }
  425.             }
  426.             if ( moduop->HasField("Method") ) {
  427.                 ufp = &(moduop->GetField("Method"));
  428.                 if ( ufp->CanGetData()  &&  ufp->GetData().IsStr() ) {
  429.                     me.method = ufp->GetData().GetStr();
  430.                 }
  431.             }
  432.             if ( moduop->HasField("mRNA") ) {
  433.                 me.mrnaEv = true;
  434.             }
  435.             if ( moduop->HasField("EST") ) {
  436.                 me.estEv = true;
  437.             }
  438.         }
  439.     }
  440.     return result;
  441. }
  442. bool GetModelEvidance(const CBioseq_Handle& bsh, SModelEvidance& me)
  443. {
  444.     if ( s_GetModelEvidance(bsh, me) ) {
  445.         return true;
  446.     }
  447.     if ( CSeq_inst::IsAa(bsh.GetInst_Mol()) ) {
  448.         CBioseq_Handle nuc = sequence::GetNucleotideParent(bsh);
  449.         if ( nuc  ) {
  450.             return s_GetModelEvidance(nuc, me);
  451.         }
  452.     }
  453.     return false;
  454. }
  455. // in Ncbistdaa order
  456. static const char* kAANames[] = {
  457.     "---", "Ala", "Asx", "Cys", "Asp", "Glu", "Phe", "Gly", "His", "Ile",
  458.     "Lys", "Leu", "Met", "Asn", "Pro", "Glu", "Arg", "Ser", "Thr", "Val",
  459.     "Trp", "OTHER", "Tyr", "Glx", "Sec", "TERM"
  460. };
  461. const char* GetAAName(unsigned char aa, bool is_ascii)
  462. {
  463.     if (is_ascii) {
  464.         aa = CSeqportUtil::GetMapToIndex
  465.             (CSeq_data::e_Ncbieaa, CSeq_data::e_Ncbistdaa, aa);
  466.     }
  467.     return (aa < sizeof(kAANames)/sizeof(*kAANames)) ? kAANames[aa] : "OTHER";
  468. }
  469. END_SCOPE(objects)
  470. END_NCBI_SCOPE
  471. /*
  472. * ===========================================================================
  473. *
  474. * $Log: utils.cpp,v $
  475. * Revision 1000.1  2004/06/01 19:45:35  gouriano
  476. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
  477. *
  478. * Revision 1.10  2004/05/26 14:08:14  shomrat
  479. * ValidateAccession allow 2 letters + underscore + 9 digits
  480. *
  481. * Revision 1.9  2004/05/21 21:42:54  gorelenk
  482. * Added PCH ncbi_pch.hpp
  483. *
  484. * Revision 1.8  2004/05/07 15:23:14  shomrat
  485. * + RemovePeriodFromEnd
  486. *
  487. * Revision 1.7  2004/04/22 15:54:47  shomrat
  488. * Use CBioseq_Handle instead of CBioseq
  489. *
  490. * Revision 1.6  2004/04/07 14:29:16  shomrat
  491. * + GetAAName
  492. *
  493. * Revision 1.5  2004/03/25 20:47:26  shomrat
  494. * Use handles
  495. *
  496. * Revision 1.4  2004/03/18 15:35:17  shomrat
  497. * Fixes in JoinNoRedund
  498. *
  499. * Revision 1.3  2004/03/08 20:55:32  shomrat
  500. * Use case sensetive search when looking for redundent content
  501. *
  502. * Revision 1.2  2004/02/11 16:57:34  shomrat
  503. * added JoinNoRedund functions
  504. *
  505. * Revision 1.1  2003/12/17 20:25:01  shomrat
  506. * Initial Revision (adapted from flat lib)
  507. *
  508. *
  509. * ===========================================================================
  510. */