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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: splign_hitparser.cpp,v $
  4.  * PRODUCTION Revision 1000.0  2004/06/01 18:12:53  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.7
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: splign_hitparser.cpp,v 1000.0 2004/06/01 18:12:53 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:  Yuri Kapustin
  35. *
  36. * File Description:
  37. *   Temporary code - will be part of the hit filtering library
  38. *
  39. */
  40. #include <ncbi_pch.hpp>
  41. #include "splign_hitparser.hpp"
  42. #include <algo/align/align_exception.hpp>
  43. #include <corelib/ncbi_limits.hpp>
  44. #include <corelib/ncbistre.hpp>
  45. #include <algorithm>
  46. #include <numeric>
  47. BEGIN_NCBI_SCOPE
  48. // auxiliary structure utilized in calculation of collisions and other routines
  49. struct SNode {
  50.     int x; // coordinate
  51.     bool type; // true = open, false = close
  52.     vector<CHit>::const_iterator pHit; // owner
  53.     SNode(int n, bool b, vector<CHit>::const_iterator ph):
  54.         x(n), type(b), pHit(ph) {};
  55.     bool operator>(const SNode& rhs) const { return x > rhs.x; }
  56.     bool operator==(const SNode& rhs) const { return x == rhs.x; }
  57.     bool operator<(const SNode& rhs) const { return x < rhs.x; }
  58. };
  59. //
  60. // general single-linkage clustering (SLC) algorithm 
  61. //
  62. struct SNodePair
  63. {
  64.     SNodePair(int i, int j): n1(i), n2(j) {}
  65.     int n1, n2;
  66. };
  67. template<class T, class PClustCrit, class CClustID_Set, class CClustID_Get>
  68. void DoSingleLinkageClustering (
  69.    vector<T>& vt,          // vector of objects to be clustered
  70.    const PClustCrit& pr2,        // clustering criterion (two-argument predicate)
  71.    const CClustID_Set& CID_Set,  // function that assigns ClustID to objects
  72.    const CClustID_Get& CID_Get   // function that retrieves ClustID from objects
  73. )
  74. {
  75.     vector<SNodePair> vnodes;    // auxiliary vector
  76.     size_t nSize = vt.size(), j = 0, i;
  77.     for( j = 0; j < nSize; ++j ) {
  78.         CID_Set( vt[j], j );
  79.         for( i = 0; i < j; ++i ) {
  80.             if( pr2(vt[i], vt[j] ) )
  81.                 vnodes.push_back( SNodePair( i, j ) );
  82.          }
  83.     }
  84.  
  85.     vector<SNodePair>::const_iterator kk, kend;
  86.     for( kk = vnodes.begin(), kend = vnodes.end(); kk != kend; ++kk ) {
  87.         int n1 = CID_Get( vt[kk->n1] ), n2 = CID_Get( vt[kk->n2] );
  88.         if( n1 != n2 ) {
  89.             NON_CONST_ITERATE (typename vector<T>, jj, vt) {
  90.                 if( CID_Get( *jj ) == n1 )
  91.                     CID_Set( *jj, n2 );
  92.             }
  93.         }
  94.     }
  95. }
  96. CHitParser::CHitParser()
  97. {
  98.     x_Set2Defaults();
  99. }
  100. CHitParser::CHitParser(const vector<CHit>& vh, int& nGroupID)
  101. {
  102.     Init(vh, nGroupID);
  103. }
  104. void CHitParser::Init(const vector<CHit>& vh, int& nGroupID)
  105. {
  106.     m_Out = vh;
  107.     x_RemoveEqual();
  108.     x_Set2Defaults();
  109.     nGroupID++;
  110.     m_GroupID = &nGroupID;
  111. }
  112. void CHitParser::x_Set2Defaults()
  113. {
  114.     m_SameOrder = true;
  115.     m_Strand = eStrand_Auto;
  116.     m_MaxHitDistQ = kMax_Int;
  117.     m_MaxHitDistS = kMax_Int;
  118.     m_Method = eMethod_MaxScore;
  119.     m_SplitQuery   = eSplitMode_MaxScore;
  120.     m_SplitSubject = eSplitMode_MaxScore;
  121.     m_Prot2Nucl = false;
  122.     m_CombinationProximity_pre = m_CombinationProximity_post = -1.;
  123.     m_group_identification_method = eNone;
  124.     m_CovStep = 90.;
  125.     m_MinQueryCoverage = 0.;
  126.     m_MinSubjCoverage = 0.;
  127.     m_OutputAllGroups = false;
  128.     m_Query = m_Subj = "";
  129.     m_GroupID = 0;
  130.     
  131.     x_CalcGlobalEnvelop();
  132. }
  133. void CHitParser::x_CalcGlobalEnvelop()
  134. {
  135.     const size_t dim = m_Out.size();
  136.     if(dim == 0) {
  137.         m_ange[0] = m_ange[1] = m_ange[2] = m_ange[3] = 0;
  138.         return;
  139.     }
  140.     m_ange[0] = m_ange[2] = kMax_Int;
  141.     m_ange[1] = m_ange[3] = kMin_Int;
  142.     vector<CHit>::iterator ii, iend;
  143.     for(ii = m_Out.begin(), iend = m_Out.end(); ii != iend; ii++)
  144.     {
  145.         if(m_ange[0] > ii->m_ai[0]) m_ange[0] = ii->m_ai[0];
  146.         if(m_ange[2] > ii->m_ai[2]) m_ange[2] = ii->m_ai[2];
  147.         if(m_ange[1] < ii->m_ai[1]) m_ange[1] = ii->m_ai[1];
  148.         if(m_ange[3] < ii->m_ai[3]) m_ange[3] = ii->m_ai[3];
  149.     }
  150. }
  151. CHitParser::~CHitParser()
  152. {
  153. }
  154. bool  CHitParser::x_DetectInclusion(const CHit& h1, const CHit& h2) const
  155. {
  156.   if( h2.m_ai[0] <= h1.m_ai[0] && h1.m_ai[1] <= h2.m_ai[1]) {
  157.     return true;
  158.   }
  159.   if( h2.m_ai[2] <= h1.m_ai[2] && h1.m_ai[3] <= h2.m_ai[3]) {
  160.     return true;
  161.   }
  162.   if( h1.m_ai[0] <= h2.m_ai[0] && h2.m_ai[1] <= h1.m_ai[1]) {
  163.     return true;
  164.   }
  165.   if( h1.m_ai[2] <= h2.m_ai[2] && h2.m_ai[3] <= h1.m_ai[3]) {
  166.     return true;
  167.   }
  168.   return false;
  169. }
  170. // implements half splitmode
  171. bool CHitParser::x_RunAltSplitMode(char cSide, CHit& hit1, CHit& hit2)
  172. {
  173.     int nb = cSide*2;
  174.     // detect intersection
  175.     if(hit1.m_ai[nb] <= hit2.m_ai[nb] && hit2.m_ai[nb] <= hit1.m_ai[nb+1])
  176.     {
  177.         int n1 = hit1.m_ai[nb + 1] + 1;
  178.         int n2 = hit2.m_ai[nb] - 1;
  179.         if(m_Prot2Nucl)
  180.         {  // frame must be preserved
  181.             int nShift = n1 - hit2.m_ai[nb];
  182.             while(nShift % 3) { nShift++; n1++; }
  183.             nShift = hit1.m_ai[nb + 1] - n2;
  184.             while(nShift % 3) { nShift++; n2--; }
  185.         }
  186.         hit1.Move(nb + 1, n2, m_Prot2Nucl);
  187.         hit2.Move(nb, n1, m_Prot2Nucl);
  188.         hit1.UpdateAttributes();
  189.         hit2.UpdateAttributes();
  190.     }
  191.     else
  192.     if(hit2.m_ai[nb] <= hit1.m_ai[nb] && hit1.m_ai[nb] <= hit2.m_ai[nb+1])
  193.     {
  194.         int n1 = hit1.m_ai[nb] - 1;
  195.         int n2 = hit2.m_ai[nb + 1] + 1;
  196.         if(m_Prot2Nucl)
  197.         {  // frame must be preserved
  198.             int nShift = hit2.m_ai[nb + 1] - n1;
  199.             while(nShift % 3) { nShift++; n1--; }
  200.             nShift = n2 - hit1.m_ai[nb];
  201.             while(nShift % 3) { nShift++; n2++; }
  202.         }
  203.         hit1.Move(nb, n2, m_Prot2Nucl);
  204.         hit2.Move(nb + 1, n1, m_Prot2Nucl);
  205.         hit1.UpdateAttributes();
  206.         hit2.UpdateAttributes();
  207.     }
  208.     return true;
  209. }
  210. int GetIntersectionSize (int a0, int b0, int c0, int d0) {
  211.     int a = min(a0, b0), b = max(a0, b0), c = min(c0, d0), d = max(c0, d0);
  212.     int an1[] = {a, b};
  213.     int an2[] = {c, d};
  214.     int* apn[] = {an1, an2};
  215.     if(c <= a) {
  216.         apn[0] = an2; apn[1] = an1;
  217.     }
  218.     int n = (apn[0][1] - apn[1][0]) + 1;
  219.     return n > 0? n: 0;
  220. }
  221. // accumulate coverage on query or subject
  222. class AcmCvg: public binary_function<int, const CHit*, int>
  223. {
  224. public:
  225.     AcmCvg(char where): m_where(where), m_nFinish(-1) {
  226.         m_i1 = m_where == 'q'? 0: 2;
  227.         m_i2 = m_where == 'q'? 1: 3;
  228.     }
  229.     int operator() (int iVal, const CHit* ph)
  230.     {
  231.         const CHit& h = *ph;
  232.         if(h.m_ai[m_i1] > m_nFinish)
  233.             return iVal + (m_nFinish = h.m_ai[m_i2]) - h.m_ai[m_i1] + 1;
  234.         else
  235.         {
  236.             int nFinish0 = m_nFinish;
  237.             return (h.m_ai[m_i2] > nFinish0)?
  238.                 (iVal + (m_nFinish = h.m_ai[m_i2]) - nFinish0): iVal;
  239.         }
  240.     }
  241. private:
  242.     char m_where;
  243.     int  m_nFinish;
  244.     unsigned char m_i1, m_i2;
  245. };
  246. int CHitParser::CalcCoverage(vector<CHit>::const_iterator ib,
  247.                              vector<CHit>::const_iterator ie,
  248.                              char where)
  249. {
  250.     vector<const CHit*> vh (ie - ib, (const CHit*)0);
  251.     for(int i = 0; i < ie - ib; ++i)  vh[i] = &(*ib) + i;
  252.     if(where == 'q') {
  253.         stable_sort(vh.begin(), vh.end(), CHit::PPrecedeQ_ptr);
  254.     }
  255.     else {
  256.         stable_sort(vh.begin(), vh.end(), CHit::PPrecedeS_ptr);
  257.     }
  258.     int s = accumulate(vh.begin(), vh.end(), 0, AcmCvg(where));
  259.     return s;
  260. }
  261. //////// Maximum Score method:
  262. // 1. Sort the vector in desc order starting from the current hit
  263. // 2. Consider max score hit (the current)
  264. // 3. Process the other hits, so the current hit remains intact
  265. //    and overlapping free
  266. // 4. Go to step 1.
  267. int CHitParser::x_RunMaxScore()
  268. {
  269.     // special pre-processing for prot2nucl mode:
  270.     // remove those hits that intersect on the genomic
  271.     // side having different reading frame
  272.     if(m_Prot2Nucl && false)  // -- currently disabled
  273.     {
  274.         list<vector<CHit>::iterator > l0;
  275.         vector<CHit>::iterator ivh;
  276.         for(ivh = m_Out.begin(); ivh != m_Out.end(); ivh++)
  277.             l0.push_back(ivh);
  278.         list<vector<CHit>::iterator >::iterator ii;
  279.         bool bDel = false;
  280.         for(ii = l0.begin(); ii != l0.end(); )
  281.         {
  282.             list<vector<CHit>::iterator >::iterator jj = ii;
  283.             for(++jj; jj != l0.end(); jj++)
  284.             {
  285.                 int& a = (*ii)->m_ai[2];
  286.                 int& b = (*ii)->m_ai[3];                
  287.                 int& c = (*jj)->m_ai[2];
  288.                 int& d = (*jj)->m_ai[3];
  289.                 bool bSameFrame = a%3 == c%3;
  290.                 if( !bSameFrame && GetIntersectionSize(a, b, c, d) > 0)
  291.                 {
  292.                     l0.erase(jj);
  293.                     bDel = true;
  294.                     break;
  295.                 }
  296.             }
  297.             if(bDel)
  298.             {
  299.                 list<vector<CHit>::iterator >::iterator jj0 = ii; jj0++;
  300.                 l0.erase(ii);
  301.                 ii = jj0;
  302.                 bDel = false;
  303.             }
  304.             else
  305.                 ii++;
  306.         }
  307.         vector<CHit> vh1;
  308.         for(ii = l0.begin(); ii != l0.end(); ii++)
  309.             vh1.push_back(**ii);
  310.         m_Out = vh1;
  311.     }
  312.     size_t nQuerySize = 0;
  313.     if(m_MinQueryCoverage > 0.) {
  314.         NCBI_THROW( CAlgoAlignException,
  315.                     eInternal,
  316.                     "Query coverage filtering not supported" );
  317.     }
  318.     size_t nSubjSize = 0;
  319.     if(m_MinSubjCoverage > 0.) {
  320.         NCBI_THROW( CAlgoAlignException,
  321.                     eInternal,
  322.                     "Subj coverage filtering not supported" );
  323.     }
  324.     // main processing
  325.     int i0 = 0;
  326.     bool bRestart = true;
  327.     while(bRestart) {
  328.         bRestart = false;
  329.         for(i0 = 0; i0 < int(m_Out.size())-1; ++i0) {
  330.             vector<CHit>::iterator ii = m_Out.begin() + i0;
  331.             // Sort by score (& priority) starting from the current hit
  332.             sort(ii, m_Out.end(), hit_greater());
  333.             // Consider max score hit (the current)
  334.             CHit& hit = *ii;
  335.             // Process the other hits, so the current hit
  336.             // remains intact and overlapping free
  337.             int j0 = 0;
  338.             for(j0 = int(m_Out.size())-1; j0 > i0; --j0) {
  339.                 vector<CHit>::iterator jj = m_Out.begin() + j0;
  340. if(m_SplitQuery == eSplitMode_Clear
  341.    || m_SplitSubject == eSplitMode_Clear) {
  342.   if(x_DetectInclusion(hit, *jj)) {
  343.     m_Out.erase(jj);
  344.     continue;
  345.   }
  346. }
  347.                 if(m_SplitQuery == eSplitMode_Clear) {
  348.                     if(x_RunAltSplitMode(0, hit, *jj) == false) {
  349.                         m_Out.erase(jj);
  350.                         continue;
  351.                     }
  352.                 }
  353.                 if(m_SplitSubject == eSplitMode_Clear) {
  354.                     if(x_RunAltSplitMode(1, hit, *jj) == false) {
  355.                         m_Out.erase(jj);
  356.                         continue;
  357.                     }
  358.                 }
  359.                 // We have two possibilities:
  360.                 // (1) there is at least one end of *jj inside the current hit;
  361.                 // (2) when *jj "embraces" the current hit;
  362.                 // (1) - proceed it in cyclic manner
  363.                 bool b [4];
  364.                 bool bFirstLoop = true;
  365.                 bool bContinue = false;
  366.                 do {
  367.                     if(!bFirstLoop) {
  368.                         size_t i = 0;
  369.                         for(i = 0; i < 4; ++i) {
  370.                             if(b[i]) {
  371.                                 switch(i) {
  372.                                 case 0: {
  373.                                     jj->Move(0,
  374.                                              hit.m_ai[1] + 1,
  375.                                              m_Prot2Nucl);
  376.                                     for(size_t d = 2; d < 4; ++d) {
  377.                                         b[d] = hit.m_ai[2] <= jj->m_ai[d] &&
  378.                                                jj->m_ai[d] <= hit.m_ai[3];
  379.                                     }
  380.                                 }
  381.                                 break;
  382.                                 case 1: {
  383.                                     jj->Move(1,
  384.                                              hit.m_ai[0] - 1,
  385.                                              m_Prot2Nucl);
  386.                                     for(size_t d = 2; d < 4; ++d) {
  387.                                         b[d] = hit.m_ai[2] <= jj->m_ai[d] &&
  388.                                                jj->m_ai[d] <= hit.m_ai[3];
  389.                                     }
  390.                                 }
  391.                                 break;
  392.                                 case 2: {
  393.                                     jj->Move(2,
  394.                                              hit.m_ai[3] + 1,
  395.                                              m_Prot2Nucl);
  396.                                     for(size_t d = 0; d < 2; ++d) {
  397.                                         b[d] = hit.m_ai[0] <= jj->m_ai[d] &&
  398.                                                jj->m_ai[d] <= hit.m_ai[1];
  399.                                     }
  400.                                 }
  401.                                 break;
  402.                                 case 3: {
  403.                                     jj->Move(3,
  404.                                              hit.m_ai[2] - 1,
  405.                                              m_Prot2Nucl);
  406.                                     for(size_t d = 0; d < 2; ++d) {
  407.                                         b[d] = hit.m_ai[0] <= jj->m_ai[d] &&
  408.                                                jj->m_ai[d] <= hit.m_ai[1];
  409.                                     }
  410.                                 }
  411.                                 break;
  412.                                 }
  413.                             }
  414.                             
  415.                             // check if *jj still exists
  416.                             if(!jj->IsConsistent())
  417.                             {
  418.                                 m_Out.erase(jj);
  419.                                 bContinue = true;
  420.                                 break;
  421.                             }
  422.                         }
  423.                         if(bContinue) break;
  424.                     }
  425.                     else
  426.                         bFirstLoop = false;
  427.                     size_t i = 0;
  428.                     for(i = 0; i < 2; ++i) {
  429.                         b[i] = hit.m_ai[0] <= jj->m_ai[i] &&
  430.                             jj->m_ai[i] <= hit.m_ai[1];
  431.                     }
  432.                     for(i = 2; i < 4; ++i) {
  433.                         b[i] = hit.m_ai[2] <= jj->m_ai[i] &&
  434.                             jj->m_ai[i] <= hit.m_ai[3];
  435.                     }
  436.                     if(b[0] && b[1] || b[2] && b[3]) {
  437.                         m_Out.erase(jj);
  438.                         bContinue = true;
  439.                         break;
  440.                     }
  441.                 }
  442.                 while(b[0] || b[1] || b[2] || b[3]);
  443.             
  444.                 if(bContinue)
  445.                     continue;    // the hit has dissapeared
  446.                 // (2)
  447.                 double ad[] = {
  448.                     hit.m_ai[0] - jj->m_ai[0], jj->m_ai[1] - hit.m_ai[1],
  449.                     hit.m_ai[2] - jj->m_ai[2], jj->m_ai[3] - hit.m_ai[3] };
  450.                 bool ab[] = {ad[0] > 0, ad[1] > 0, ad[2] > 0, ad[3] > 0 };
  451.                 bool bNewHit = false;
  452.                 CHit hit2;
  453.                 if(ab[0] && ab[1] || ab[2] && ab[3]) { // split *jj
  454.                     int n1, n2, n1x, n2x;
  455.                     if(jj->IsStraight()) {
  456.                         if(!(ab[2] && ab[3])) {
  457.                             n1 = 1; n2 = 0;
  458.                             n1x = hit.m_ai[0] - 1;
  459.                             n2x = hit.m_ai[1] + 1;
  460.                         }
  461.                         else if(!(ab[0] && ab[1])) {
  462.                             n1 = 3; n2 = 2;
  463.                             n1x = hit.m_ai[2] - 1;
  464.                             n2x = hit.m_ai[3] + 1;
  465.                         }
  466.                         else {
  467.                             n1 = (ad[0] < ad[2])? 1: 3;
  468.                             n2 = (ad[1] < ad[3])? 0: 2;
  469.                             n1x = (ad[0] < ad[2])?
  470.                                 hit.m_ai[0] - 1: hit.m_ai[2] - 1;
  471.                             n2x = (ad[1] < ad[3])?
  472.                                 hit.m_ai[1] + 1: hit.m_ai[3] + 1;
  473.                         }
  474.                     }
  475.                     else {
  476.                         if(!(ab[2] && ab[3])) {
  477.                             n1 = 1; n2 = 0;
  478.                             n1x = hit.m_ai[0] - 1; n2x = hit.m_ai[1] + 1;
  479.                         }
  480.                         else if(!(ab[0] && ab[1])) {
  481.                             n1 = 2; n2 = 3;
  482.                             n1x = hit.m_ai[3] + 1; n2x = hit.m_ai[2] - 1;
  483.                         }
  484.                         else {
  485.                             n1 = (ad[0] < ad[3])? 1: 2;
  486.                             n2 = (ad[1] < ad[2])? 0: 3;
  487.                             n1x = (ad[0] < ad[3])?
  488.                                 hit.m_ai[0] - 1: hit.m_ai[3] + 1;
  489.                             n2x = (ad[1] < ad[2])?
  490.                                 hit.m_ai[1] + 1: hit.m_ai[2] - 1;
  491.                         }
  492.                     }
  493.                     hit2 = *jj;
  494.                     bNewHit = true;
  495.                     jj->Move(n1, n1x, m_Prot2Nucl);
  496.                     if(!jj->IsConsistent()) {
  497.                         m_Out.erase(jj);
  498.                     }
  499.                     else { // some trapezoidal hits may still overlap
  500.                         bRestart = true;
  501.                     }
  502.                     hit2.Move(n2, n2x, m_Prot2Nucl);
  503.                     if(hit2.IsConsistent()) {
  504.                         // some trapezoidal hits may still overlap
  505.                         hit2.UpdateAttributes();
  506.                         bRestart = true;
  507.                     }
  508.                     else {
  509.                         bNewHit = false;
  510.                     }
  511.                 }
  512.                 jj->UpdateAttributes();
  513.                 if(bNewHit) {
  514.                     m_Out.push_back(hit2);
  515.                 }
  516.                 if(bRestart) break;
  517.             }
  518.             if(m_SameOrder) {
  519.                 x_FilterByOrder(i0, false);
  520.             }
  521.             // step 4: re-assess groups and continue the cycle
  522.             if(bRestart) break;
  523.         }
  524.     }
  525.     if(m_MinQueryCoverage > 0.) {
  526.         // calculate query coverage
  527.         double dQCov = CalcCoverage(m_Out.begin(), m_Out.end(), 'q');
  528.         if(dQCov < m_MinQueryCoverage* nQuerySize)
  529.             m_Out.clear();
  530.     }
  531.     if(m_MinSubjCoverage > 0.) {
  532.         // calculate subj coverage
  533.         double dSCov = CalcCoverage(m_Out.begin(), m_Out.end(), 's');
  534.         if(dSCov < m_MinSubjCoverage* nSubjSize)
  535.             m_Out.clear();
  536.     }
  537.     return 0;
  538. }
  539. void CHitParser::x_FilterByOrder(size_t offset, bool use_chainfilter)
  540. {
  541.     size_t dim = m_Out.size();
  542.     if(offset >= dim) return;
  543.     vector<CHit>::iterator ii_beg = m_Out.begin() + offset;
  544.     if(use_chainfilter) {  // groupwise chain filtering
  545.       /*
  546.         sort(ii_beg, m_Out.end(), hit_groupid_less());
  547.         int nGroupID = m_Out[0].m_GroupID;
  548.         size_t start = 0, fin = 0, target = 0;
  549.         while(fin < dim) {
  550.             for(; fin < dim && nGroupID == m_Out[fin].m_GroupID; ++fin);
  551.             start = fin;
  552.             nGroupID = m_Out[fin].m_GroupID;
  553.             vector<CHit> vh (ii_beg + start, ii_beg + fin);
  554.             CChainFilter cf (vh);
  555.             cf.Run();
  556.             copy(vh.begin(), vh.end(), ii_beg + target);
  557.             target += vh.size();
  558.         }
  559.         m_Out.resize(target);
  560.       */
  561.     }
  562.     else { // greedy filtering
  563.         vector<CHit>::iterator ii2 = ii_beg, iend2;
  564.         //for(iend2 = m_Out.end(); ii2 < iend2; ++ii2) {
  565.         //    iend2 = remove_if(ii2 + 1, iend2,
  566.         //                     bind1st(hit_not_same_order(), *ii2));
  567.         //}
  568.         iend2 = remove_if(ii2 + 1, m_Out.end(),
  569.                              bind1st(hit_not_same_order(), *ii2));
  570.         m_Out.erase(iend2, m_Out.end());
  571.     }
  572. }
  573. // Calculates proximity btw any two hits.
  574. // Return value can range from 0 (similar) to 1 (different)
  575. double CHitParser::x_CalculateProximity(const CHit& h1, const CHit& h2) const
  576. {
  577.     //    if(m_SameOrder)
  578.     //    {
  579.     //        hit_not_same_order hnso;
  580.     //        if(hnso(h1,h2)) return 1.;
  581.     //    }
  582.     double adm [] = { m_ange[1] - m_ange[0] + 1, m_ange[3] - m_ange[2] + 1};
  583.     double dm = max(adm[0], adm[1]);
  584.     double ad [2];
  585.     for(int i = 0; i < 4; i += 2) {
  586.         int i0 = i, i1 = i + 1;
  587.         if(h1.m_ai[i1] <= h2.m_ai[i0])  // no intersection
  588.             ad[i/2] = double(h2.m_ai[i0] - h1.m_ai[i1] - 1) / dm;// adm[i/2];
  589.         else
  590.         if(h2.m_ai[i1] <= h1.m_ai[i0])  // no intersection
  591.             ad[i/2] = double(h1.m_ai[i0] - h2.m_ai[i1] - 1) / dm;//adm[i/2];
  592.         else // inclusion
  593.         if(h1.m_ai[i0] <= h2.m_ai[i0] && h2.m_ai[i1] <= h1.m_ai[i1] ||
  594.              h2.m_ai[i0] <= h1.m_ai[i0] && h1.m_ai[i1] <= h2.m_ai[i1] )
  595.             ad[i/2] = 1.0;
  596.         else // intersection
  597.         if(h2.m_ai[i0] <= h1.m_ai[i0] && h1.m_ai[i0] <= h2.m_ai[i1])
  598.             ad[i/2] = double(h2.m_ai[i1] - h1.m_ai[i0] + 1) /
  599.                 (h1.m_ai[i1] - h2.m_ai[i0] + 1);
  600.         else
  601.             ad[i/2] = double(h1.m_ai[i1] - h2.m_ai[i0] + 1) /
  602.                 (h2.m_ai[i1] - h1.m_ai[i0] + 1);
  603.     }
  604.     return max(ad[0],ad[1]);
  605. }
  606. int CHitParser::x_RunMSGS(bool bSelectGroupsOnly, int& nGroupId)
  607. {
  608.     if( m_group_identification_method != eNone || bSelectGroupsOnly )
  609.     {
  610.         if(m_group_identification_method == eQueryCoverage) {
  611.             x_GroupsIdentifyByCoverage(0, m_Out.size(), nGroupId, 0, 'q');
  612.         }
  613.         else {
  614.             x_GroupsIdentifyByCoverage(0, m_Out.size(), nGroupId, 0, 's');
  615.         }
  616.         x_SyncGroupsByMaxDist(nGroupId);
  617.     }
  618.     if(m_OutputAllGroups && !bSelectGroupsOnly && m_Out.size())
  619.     {
  620.         // make copies to m_Out here
  621.         // new subj string must reflect both number and strand
  622.         // like [s4], [i8]
  623.         // first we count the number of groups
  624.         size_t nGroupCount = 1;
  625.         {{
  626.         sort(m_Out.begin(), m_Out.end(), hit_groupid_less());
  627.         vector<CHit>::iterator ibegin = m_Out.begin(), iend = m_Out.end(),
  628.             ii = ibegin;
  629.         int ngid = ii->m_GroupID;
  630.         for(++ii; ii != iend; ++ii)
  631.         {
  632.             if(ii->m_GroupID != ngid)
  633.             {
  634.                 ngid = ii->m_GroupID;
  635.                 ++nGroupCount;
  636.             }
  637.         }
  638.         }}
  639.         {{
  640.             // determine strands of the groups
  641.             // 1 = straight, 0 = inverse, -1 = both / undefined
  642.             vector<char> vStrands (nGroupCount, -1);
  643.             vector<CHit>::iterator ibegin = m_Out.begin(),
  644.                 ii = ibegin, iend = m_Out.end();
  645.             for(size_t ig = 0; ig < nGroupCount; ++ig)
  646.             {
  647.                 vStrands[ig] = ii->IsStraight()? 1: 0;
  648.                 int ngid = ii->m_GroupID;
  649.                 for(; ii != iend; ii++)
  650.                 {
  651.                     if(ii->m_GroupID != ngid) break;
  652.                     char cs = ii->IsStraight()? 1: 0;
  653.                     if(cs != vStrands[ig]) vStrands[ig] = -1;
  654.                 }
  655.             }
  656.             
  657.             // now separate the groups
  658.             ii = ibegin;
  659.             string strSubject0 = ii->m_Subj;
  660.             int ngc_s = 0, ngc_i = 0;
  661.             for(size_t ig = 0; ig < nGroupCount; ig++)
  662.             {
  663.                 int ngid = ii->m_GroupID;
  664. CNcbiOstrstream oss; // new subject
  665.                 char c0 = (vStrands[ig] == -1)? 'x':
  666.                     (vStrands[ig] == 0)? 'm': 'p';
  667.                 int ngc = (c0 == 'i')? ++ngc_i: ++ngc_s;
  668. oss << strSubject0 << "_[" << c0 << ngc << ']';
  669. const string new_subj = CNcbiOstrstreamToString(oss);
  670.                 for(; ii != iend; ++ii)
  671.                 {
  672.                     if(ii->m_GroupID != ngid) break;
  673.                     ii->m_Subj = new_subj;
  674.                 }
  675.             }
  676.         }}
  677.         return 0; // we don't resolve ambiguities in this mode
  678.     }
  679.     if(bSelectGroupsOnly) return 0;
  680.     vector<CHit> vh (m_Out);
  681.     vector<CHit> vh_out;
  682.     double max_group_score = 0;
  683.     size_t i = 0, dim = vh.size();
  684.     while(i < dim) {
  685.         int groupid0 = vh[i].m_GroupID;
  686.         int istart = i;
  687.         for(; i < dim && groupid0 == vh[i].m_GroupID; ++i);
  688.         int ifin = i;
  689.         m_Out.resize(ifin - istart);
  690.         copy(vh.begin() + istart, vh.begin() + ifin, m_Out.begin());
  691.         x_RunMaxScore();
  692.         double group_score = 0;
  693.         size_t dim_group = m_Out.size();
  694.         for(size_t k = 0; k < dim_group; ++k) group_score += m_Out[k].m_Score;
  695.         
  696.         if(m_OutputAllGroups) {
  697.             copy(m_Out.begin(), m_Out.end(), back_inserter(vh_out));
  698.         }
  699.         else if(group_score > max_group_score) {
  700.             max_group_score = group_score;
  701.             vh_out.clear();
  702.             copy(m_Out.begin(), m_Out.end(), back_inserter(vh_out));
  703.         }
  704.     }
  705.     m_Out = vh_out;
  706.     return 0;
  707. }
  708. void CHitParser::x_GroupsIdentifyByCoverage(int iStart, int iStop, int& iGroupId,
  709.                                           double dTotalCoverage, char where)
  710. {
  711.     bool bTopLevelCall = (iStart == 0) && (size_t(iStop) == m_Out.size());
  712.     if(bTopLevelCall) { // top-level call
  713.         x_CalcGlobalEnvelop();
  714.         if(where == 'q') {
  715.             stable_sort(m_Out.begin() + iStart, m_Out.begin() + iStop,
  716.                         CHit::PPrecedeS);
  717.         }
  718.         else {
  719.             stable_sort(m_Out.begin() + iStart, m_Out.begin() + iStop,
  720.                         CHit::PPrecedeQ);
  721.         }
  722.         dTotalCoverage = CalcCoverage(m_Out.begin() + iStart,
  723.                                       m_Out.begin() + iStop, where);
  724.     }
  725.     // assign new groupid
  726.     {{
  727.         ++iGroupId;
  728.         for(int i = iStart; i < iStop; ++i)
  729.             m_Out[i].m_GroupID = iGroupId;
  730.     }}
  731.     if(iStop - iStart <= 1) return;
  732.     // choose the best location
  733.     double dMax = dTotalCoverage;
  734.     int iMax = iStop;
  735.     unsigned char idx1, idx2;
  736.     if(where == 'q') {
  737.         idx1 = 2;
  738.         idx2 = 3;
  739.     }
  740.     else {
  741.         idx1 = 0;
  742.         idx2 = 1;
  743.     }
  744.     // find all gaps, sort them by size, then 
  745.     // proceed from larger to lower
  746.     typedef multimap<int, int> mm_t;
  747.     mm_t mm_gapsize2index;
  748.     for(int i = iStart; i < iStop - 1; i++)
  749.     {
  750.         int gap = m_Out[i+1].m_ai[idx1] - m_Out[i].m_ai[idx2];
  751.         if(gap > 0) {
  752.             mm_gapsize2index.insert(mm_t::value_type(gap, i));
  753.         }
  754.     }
  755.     mm_t::reverse_iterator mmirb = mm_gapsize2index.rbegin();
  756.     mm_t::reverse_iterator mmire = mm_gapsize2index.rend();
  757.     mm_t::reverse_iterator mmir;
  758.     bool match = false;
  759.     for(mmir = mmirb; mmir != mmire; ++mmir) {
  760.         int i = mmir->second;
  761.         int n1 = CalcCoverage(m_Out.begin() + iStart,
  762.                               m_Out.begin() + i + 1, where);
  763.         int n2 = CalcCoverage(m_Out.begin() + i + 1,
  764.                               m_Out.begin() + iStop, where);
  765.         double d = (n1 + n2);
  766.         match = (d - dTotalCoverage) / dTotalCoverage  >= m_CovStep;
  767.         if(match) {
  768.              dMax = d;
  769.              iMax = i;
  770.              break;
  771.          }
  772.     }
  773.     if(match)
  774.     {
  775.         x_GroupsIdentifyByCoverage(iStart, iMax + 1, iGroupId,
  776.    dTotalCoverage, where);
  777.         x_GroupsIdentifyByCoverage(iMax + 1, iStop, iGroupId,
  778.    dTotalCoverage, where);
  779.     }
  780. }
  781. size_t CHitParser::x_RemoveEqual()
  782. {
  783.     typedef map<size_t, vector<size_t> > map_t;
  784.     map_t m;  // hit checksum to hits
  785.     vector<size_t> vhd;  // hits to delete
  786.     size_t dim = m_Out.size();
  787.     for(size_t i = 0; i < dim ; ++i) {
  788.         const CHit& h = m_Out[i];
  789.         size_t checksum = ( h.m_an[0] + h.m_an[1] + h.m_an[2] + h.m_an[3] )
  790.                           % 1000;
  791.         map_t::iterator mi = m.find(checksum);
  792.         if(mi == m.end()) {
  793.             m[checksum].push_back(i);
  794.         }
  795.         else {
  796.             vector<size_t>& vph = mi->second;
  797.             size_t dim_hits = vph.size(), k = 0;
  798.             for(; k < dim_hits; ++k) {
  799.                 const CHit& h2 = m_Out[vph[k]];
  800.                 if( h.m_an[0] == h2.m_an[0] && h.m_an[1] == h2.m_an[1] &&
  801.                     h.m_an[2] == h2.m_an[2] && h.m_an[3] == h2.m_an[3]    ) {
  802.                     vhd.push_back(i);
  803.                     break;
  804.                 }
  805.             }
  806.             if(k == dim_hits) {
  807.                     m[checksum].push_back(i);
  808.             }
  809.         }
  810.     }
  811.     size_t del_count = 0;
  812.     if(vhd.size()) {
  813.         sort(vhd.begin(), vhd.end());
  814.         size_t dim_vhd = vhd.size();
  815.         size_t vhd_i = 0;
  816.         for(size_t k = vhd[vhd_i]; k < dim - del_count; ++k) {
  817.             bool b = false;
  818.             if(vhd_i < dim_vhd && k == vhd[vhd_i] - del_count) {
  819.                 ++del_count;
  820.                 ++vhd_i;
  821.                 b = true;
  822.             }
  823.             size_t k1 = k + del_count;
  824.             if(k1 < dim) {
  825.                 m_Out[k] = m_Out[k1];
  826.             }
  827.             else  break;
  828.             if(b) --k;
  829.         }
  830.         m_Out.resize(dim - del_count);
  831.     }
  832.     return del_count;
  833. }
  834. int CHitParser::Run(EMode erm)
  835. {
  836.     int nCode = x_CheckParameters();
  837.     if(nCode) return nCode;
  838.     vector<CHit> vhInvStrand;      // used only if strand mode = auto
  839.     int& nGroupId = *m_GroupID;  // auxiliary variable
  840.     size_t dim = m_Out.size();
  841.     if(dim)
  842.     {
  843.         x_TransformCoordinates(true);
  844.         x_Combine(m_CombinationProximity_pre);
  845.         {{
  846.         // filter by strand or separate strands, if applicable
  847.         if(m_Strand == eStrand_Plus || m_Strand == eStrand_Minus ||
  848.            m_Strand == eStrand_Auto)
  849.         {
  850.             vector<CHit>::iterator ii;
  851.             for(ii = m_Out.end()-1; ii >= m_Out.begin(); ii--)
  852.             {
  853.                 bool bStraight = ii->IsStraight();
  854.                 switch(m_Strand)
  855.                 {
  856.                     case eStrand_Plus:
  857.                         if (bStraight) continue; else m_Out.erase(ii);
  858.                         break;
  859.                     case eStrand_Minus:
  860.                         if (!bStraight) continue; else m_Out.erase(ii);
  861.                         break;
  862.                     case eStrand_Auto: //  separate strands before processing
  863.                         if (bStraight) continue;
  864.                         else
  865.                         {
  866.                             vhInvStrand.push_back(*ii);
  867.                             m_Out.erase(ii);
  868.                         }
  869.                         break;
  870.                 }
  871.             }
  872.         }
  873.         x_CalcGlobalEnvelop();
  874.         switch(erm)
  875.         {
  876.             case eMode_Combine: // already combined
  877.                 break;
  878.             case eMode_GroupSelect:
  879.                 x_RunMSGS(true, nGroupId);
  880.                 break;
  881.             case eMode_Normal:
  882.                 x_IdentifyMaxDistGroups();
  883.                 switch(m_Method)
  884.                 {
  885.                     case eMethod_MaxScore:
  886.                         x_RunMaxScore(); break;
  887.                     case eMethod_MaxScore_GroupSelect:
  888.                         x_RunMSGS(false, nGroupId); break;
  889.                     default: return 1; //  not supported
  890.                 }
  891.                 if(!m_OutputAllGroups) {
  892.                     // we need to identify again because "connecting"
  893.                     // hits might might have perished
  894.                     x_IdentifyMaxDistGroups();  
  895.                     x_FilterByMaxDist();
  896.                 }
  897.                 break;
  898.         }
  899.         // if strand mode is auto then we run it again for inverse strand
  900.         // and then compare the strands
  901.         if(m_Strand == 3)
  902.         {
  903.             vector<CHit> vh0 = m_Out;
  904.             m_Out = vhInvStrand;
  905.             x_CalcGlobalEnvelop();
  906.             switch(erm)
  907.             {
  908.                 case eMode_Combine:
  909.                     break;
  910.                 case eMode_GroupSelect:
  911.                     x_RunMSGS(true, nGroupId);
  912.                     break;
  913.                 case eMode_Normal:
  914.                     x_IdentifyMaxDistGroups();
  915.                     switch(m_Method)
  916.                     {
  917.                         case eMethod_MaxScore:
  918.                             x_RunMaxScore(); break;
  919.                         case eMethod_MaxScore_GroupSelect:
  920.                             x_RunMSGS(false, nGroupId); break;
  921.                         default: return 1; //  not supported
  922.                     }
  923.                     x_IdentifyMaxDistGroups();
  924.                     x_FilterByMaxDist();
  925.                     break;
  926.             }
  927.             if(erm == eMode_Normal && !m_OutputAllGroups)
  928.             { // leave only the best strand
  929.                 double dScoreStraight = 0., dScoreInverse = 0.;
  930.                 vector<CHit>::iterator ii = vh0.begin(), iend = vh0.end();
  931.                 for(; ii != iend; ii++) dScoreStraight += ii->m_Score;
  932.                 ii = m_Out.begin(); iend = m_Out.end();
  933.                 for(; ii != iend; ii++) dScoreInverse += ii->m_Score;
  934.                 if(dScoreStraight > dScoreInverse) m_Out = vh0;
  935.             }
  936.             else
  937.             { // merge the strands since we don't actually want to
  938.               // eliminate ambiguities here
  939.               copy(vh0.begin(), vh0.end(), back_inserter(m_Out));
  940.             }
  941.         }
  942.         x_Combine(m_CombinationProximity_post);
  943.         }}
  944.         x_TransformCoordinates(false);
  945.     }
  946.     return nCode;
  947. }
  948. int CHitParser::x_CheckParameters() const
  949. {
  950.     switch (m_Method)
  951.     {
  952.         case eMethod_MaxScore:
  953.         case eMethod_MaxScore_GroupSelect:
  954.         break;
  955.         default: return 1; // unsupported
  956.     };
  957.     switch (m_Strand)
  958.     {
  959.         case 0: case 1: case 3: break;
  960.             // same order and different strands are incompatible
  961.         case 2: if(m_SameOrder) return 3;
  962.                         else break;
  963.         default: return 2; // unsupported
  964.     };
  965.     return 0;
  966. }
  967. // counts the number of collisions
  968. // pvh0== 0 => count at m_Out
  969. int CHitParser::GetCollisionCount (int& nq, int& ns, const vector<CHit>& vh)
  970. {
  971.     nq = ns = 0;
  972.     vector<SNode> vi_q, vi_s;
  973.     vector<CHit>::const_iterator phi0 = vh.begin(),
  974.       phi1 = vh.end(), phi = phi0;
  975.     for(phi = phi0; phi != phi1; ++phi)
  976.     {
  977.         SNode Nodes [] = {
  978.             SNode(phi->m_ai[0],true,phi), SNode(phi->m_ai[1],false,phi),
  979.             SNode(phi->m_ai[2],true,phi), SNode(phi->m_ai[3],false,phi)
  980.         };
  981.         vi_q.push_back(Nodes[0]); vi_q.push_back(Nodes[1]);
  982.         vi_s.push_back(Nodes[2]); vi_s.push_back(Nodes[3]);
  983.     }
  984.     sort(vi_q.begin(),vi_q.end());
  985.     sort(vi_s.begin(),vi_s.end());
  986.     int nLevel = 0;
  987.     vector<SNode>::iterator ii;
  988.     for(ii = vi_q.begin(); ii != vi_q.end(); ii++)
  989.         if(ii->type) { if(++nLevel == 2) nq++; } else nLevel--;
  990.     nLevel = 0;
  991.     vector<SNode>::iterator jj;
  992.     for(jj = vi_s.begin(); jj != vi_s.end(); jj++)
  993.         if(jj->type) { if(++nLevel == 2) ns++; } else nLevel--;
  994.     return nq + ns;
  995. }
  996. void CHitParser::x_TransformCoordinates(bool bDir)
  997. {
  998.     if(bDir)
  999.     {
  1000.         // transform hits
  1001.         m_Origin[0] = m_ange[0];
  1002.         m_Origin[1] = m_ange[2];
  1003.         vector<CHit>::iterator ii, iend;
  1004.         for(ii = m_Out.begin(), iend = m_Out.end(); ii != iend; ii++)
  1005.         {
  1006.             for(int k=0; k<4; k++)
  1007.             {
  1008.                 ii->m_an[k] -= m_Origin[k/2];
  1009.                 ii->m_ai[k] -= m_Origin[k/2];
  1010.             }
  1011.         }
  1012.     }
  1013.     else
  1014.     {
  1015.         vector<CHit>::iterator ii, iend;
  1016.         vector<vector<CHit>::iterator> vhi_del;
  1017.         for(ii = m_Out.begin(), iend = m_Out.end(); ii != iend; ii++)
  1018.         {
  1019.             for(int k=0; k<4; k++)
  1020.             {
  1021.                 ii->m_an[k] += m_Origin[k/2];
  1022.                 ii->m_ai[k] += m_Origin[k/2];
  1023.             }
  1024.             if(ii->m_ai[1] == ii->m_ai[0] || ii->m_ai[3] == ii->m_ai[2])
  1025.                 vhi_del.push_back(ii);
  1026.         }
  1027.         // delete the slack
  1028.         vector<vector<CHit>::iterator>::reverse_iterator i1, i1e;
  1029.         for(i1 = vhi_del.rbegin(), i1e = vhi_del.rend(); i1 != i1e; i1++)
  1030.             m_Out.erase(*i1);
  1031.     }
  1032.     x_CalcGlobalEnvelop();
  1033. }
  1034. void CHitParser::x_FilterByMaxDist()
  1035. {
  1036.     //  sum and compare the scores
  1037.     map<int,double> mgr2sc;
  1038.     int nSize = m_Out.size();
  1039.     for(int j = 0; j < nSize; j++)
  1040.     {
  1041.         const int nClustID = CMaxDistClIdGet()(m_Out[j]);
  1042.         mgr2sc[nClustID] += m_Out[j].m_Score;
  1043.     }
  1044.     double dmax = -1e38;
  1045.     map<int,double>::iterator im, im1;
  1046.     for(im1 = im = mgr2sc.begin(); im != mgr2sc.end(); im++)
  1047.     {
  1048.         if(im->second > dmax)
  1049.         {
  1050.             dmax = im->second;
  1051.             im1 = im;
  1052.         }
  1053.     }
  1054.     // leave only the top-score max dist group
  1055.     vector<CHit>::iterator ie = remove_if(
  1056.         m_Out.begin(), m_Out.end(), bind2nd(hit_out_of_group(),im1->first));
  1057.     m_Out.erase(ie,m_Out.end());
  1058. }
  1059. void CHitParser::x_IdentifyMaxDistGroups()
  1060. {
  1061.     DoSingleLinkageClustering ( m_Out,
  1062.         CMaxDistClustPred(m_MaxHitDistQ, m_MaxHitDistS),
  1063.         CMaxDistClIdSet(),
  1064.         CMaxDistClIdGet() );
  1065. }
  1066. void CHitParser::x_SyncGroupsByMaxDist(int& nGroupID)
  1067. {
  1068.     if(m_Out.size() == 0) return;
  1069.     // order by GroupID
  1070.     stable_sort(m_Out.begin(), m_Out.end(), hit_groupid_less());
  1071.     // renumber the groups to make sure that
  1072.     // we have same nClustID throughout the group
  1073.     vector<CHit>::iterator ibegin = m_Out.begin(), iend = m_Out.end(),
  1074.         ii = ibegin;
  1075.     int ngid = ii->m_GroupID, nmdcid = ii->m_MaxDistClustID;
  1076.     ii->m_GroupID = ++nGroupID;
  1077.     for(++ii; ii != iend; ++ii)
  1078.     {
  1079.         if(ngid == ii->m_GroupID && nmdcid != ii->m_MaxDistClustID)
  1080.         {
  1081.             ++nGroupID;
  1082.             nmdcid = ii->m_MaxDistClustID;
  1083.         }
  1084.         if(ngid != ii->m_GroupID)
  1085.         {
  1086.             ++nGroupID;
  1087.             ngid = ii->m_GroupID;
  1088.         }
  1089.         ii->m_GroupID = nGroupID;
  1090.     }
  1091. }
  1092. size_t CHitParser::GetSeqLength(const string& accession)
  1093. {
  1094.     return 0;
  1095.     /*
  1096.   using namespace objects;
  1097.   map<string, size_t>::const_iterator i1 = m_seqsizes.find(accession),
  1098.     i2 = m_seqsizes.end();
  1099.   if(i1 != i2) {
  1100.     size_t s = i1->second;
  1101.     return s;
  1102.   }
  1103.   
  1104.   CObjectManager om;
  1105.   om.RegisterDataLoader ( *new CGBDataLoader("ID", new CId1Reader, 2),
  1106.   CObjectManager::eDefault );
  1107.   CScope scope(om);
  1108.   scope.AddDefaults();
  1109.     
  1110.   CSeq_id seq_id (accession);
  1111.   
  1112.   CBioseq_Handle bioseq_handle = scope.GetBioseqHandle(seq_id);
  1113.   
  1114.   if ( bioseq_handle ) {
  1115.     const CBioseq& bioseq = bioseq_handle.GetBioseq();
  1116.     const CSeq_inst& inst = bioseq.GetInst();
  1117.     if(inst.IsSetLength()) {
  1118.       size_t s = inst.GetLength();
  1119.       m_seqsizes[accession] = s;
  1120.       return s;
  1121.     }
  1122.   }
  1123.   return 0;
  1124.     */
  1125. }
  1126. bool CHitGroup::CheckSameOrder()
  1127. {
  1128.     if(m_vHits.size() == 0) return true;
  1129.     vector<int>::const_iterator ivh0 = m_vHits.begin(),
  1130.         ivh1 = m_vHits.end(), ii, jj;
  1131.     hit_not_same_order hnso;
  1132.     for(ii = ivh0; ii < ivh1; ++ii) {
  1133.         for(jj = ivh0; jj < ii; ++jj) {
  1134.             if(hnso( (*m_pHits)[*ii], (*m_pHits)[*jj] ))
  1135.                 return false;
  1136.         }
  1137.     }
  1138.     return true;
  1139. }
  1140. void CHitParser::x_Combine(double dProximity)
  1141. {
  1142.     if(dProximity < 0 || m_Out.size() == 0) {
  1143.         return;
  1144.     }
  1145.     x_CalcGlobalEnvelop();
  1146.     size_t total_hits = m_Out.size();
  1147.     vector<CHit*> vh (total_hits);
  1148.     CHit* phit = &(m_Out[0]);
  1149.     for(size_t i = 0; i < total_hits; ++i) {
  1150.         vh[i] = phit++;
  1151.     }
  1152.     typedef vector<CHit*>::iterator TVHitPtrI;
  1153.     // separate strands
  1154.     sort(vh.begin(), vh.end(),  CHit::PPrecedeStrand_ptr);
  1155.     TVHitPtrI strand_minus_start = 
  1156.         find_if(vh.begin(), vh.end(), bind2nd(hit_ptr_strand_is(), true));
  1157.     typedef pair<TVHitPtrI, TVHitPtrI> THitRange;
  1158.     THitRange strands [2];
  1159.     strands[0].first = vh.begin();
  1160.     strands[0].second = strands[1].first = strand_minus_start;
  1161.     strands[1].second = strands[0].first + total_hits;
  1162.  
  1163.     for(size_t strand = 0; strand < 2; ++strand) {
  1164.         TVHitPtrI start  = strands[strand].first;
  1165.         TVHitPtrI finish = strands[strand].second;
  1166.         
  1167.         size_t dim = finish - start;
  1168.         if(dim < 2) continue;
  1169.         size_t count;
  1170.         do {
  1171.             count = 0;
  1172.             stable_sort(start, finish, CHit::PGreaterScore_ptr);
  1173.             for(TVHitPtrI i1 = start; i1 < finish - 1; ++i1) {
  1174.                 if(*i1 == 0) continue;
  1175.                 for(TVHitPtrI j1 = i1 + 1; j1 < finish; ++j1) {
  1176.                     if(*j1 == 0) continue;
  1177.                     double d = x_CalculateProximity(**i1, **j1);
  1178.                     if(d <= dProximity) {
  1179.                         CHit hc (**i1, **j1);
  1180.                         **i1 = hc;
  1181.                         *j1 = 0;
  1182.                         ++count;
  1183.                     }
  1184.                 }
  1185.             }
  1186.         }
  1187.         while(count);
  1188.     }
  1189.     // flush deletions, compress pointers vector, fill original hit vector
  1190.     TVHitPtrI iv = remove(vh.begin(), vh.end(), (CHit*) 0);
  1191.     vh.erase(iv, vh.end());
  1192.     TVHitPtrI ib = vh.begin(), ie = vh.end();
  1193.     sort(ib, ie, CHit::PGreaterScore_ptr);
  1194.     vector<CHit> vout (vh.size());
  1195.     for(iv = ib; iv != ie; ++iv) {
  1196.         vout[iv - ib] = **iv;
  1197.     }
  1198.     m_Out = vout;
  1199.     return;
  1200. }
  1201. END_NCBI_SCOPE
  1202. /*
  1203. * ===========================================================================
  1204. *
  1205. * $Log: splign_hitparser.cpp,v $
  1206. * Revision 1000.0  2004/06/01 18:12:53  gouriano
  1207. * PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.7
  1208. *
  1209. * Revision 1.7  2004/05/24 16:13:57  gorelenk
  1210. * Added PCH ncbi_pch.hpp
  1211. *
  1212. * Revision 1.6  2004/05/18 21:43:40  kapustin
  1213. * Code cleanup
  1214. *
  1215. * Revision 1.5  2004/05/03 21:53:57  kapustin
  1216. * Eliminate OM-dependant code
  1217. *
  1218. * Revision 1.4  2004/04/26 16:52:44  ucko
  1219. * Add an explicit "typename" annotation required by GCC 3.4, and adjust
  1220. * the code to take advantage of the ITERATE macro.
  1221. *
  1222. * Revision 1.3  2004/04/23 14:37:44  kapustin
  1223. * *** empty log message ***
  1224. *
  1225. * ===========================================================================
  1226. */