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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: sequence.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 19:25:30  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.82
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: sequence.cpp,v 1000.3 2004/06/01 19:25:30 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:  Clifford Clausen
  35. *
  36. * File Description:
  37. *   Sequence utilities requiring CScope
  38. */
  39. #include <ncbi_pch.hpp>
  40. #include <serial/iterator.hpp>
  41. #include <objmgr/object_manager.hpp>
  42. #include <objmgr/scope.hpp>
  43. #include <objmgr/seq_vector.hpp>
  44. #include <objmgr/seq_vector_ci.hpp>
  45. #include <objmgr/seqdesc_ci.hpp>
  46. #include <objmgr/feat_ci.hpp>
  47. #include <objmgr/impl/handle_range_map.hpp>
  48. #include <objmgr/impl/synonyms.hpp>
  49. #include <objects/general/Int_fuzz.hpp>
  50. #include <objects/seq/Bioseq.hpp>
  51. #include <objects/seq/Delta_ext.hpp>
  52. #include <objects/seq/Delta_seq.hpp>
  53. #include <objects/seq/MolInfo.hpp>
  54. #include <objects/seq/Seg_ext.hpp>
  55. #include <objects/seq/Seq_ext.hpp>
  56. #include <objects/seq/Seq_inst.hpp>
  57. #include <objects/seq/Seq_literal.hpp>
  58. #include <objects/seqloc/Packed_seqpnt.hpp>
  59. #include <objects/seqloc/Seq_bond.hpp>
  60. #include <objects/seqloc/Seq_id.hpp>
  61. #include <objects/seqloc/Seq_interval.hpp>
  62. #include <objects/seqloc/Seq_loc.hpp>
  63. #include <objects/seqloc/Seq_loc_equiv.hpp>
  64. #include <objects/seqloc/Seq_loc_mix.hpp>
  65. #include <objects/seqloc/Seq_point.hpp>
  66. #include <objects/seqset/Seq_entry.hpp>
  67. #include <objects/seqfeat/Org_ref.hpp>
  68. #include <objects/seqfeat/BioSource.hpp>
  69. #include <objects/seqfeat/Cdregion.hpp>
  70. #include <objects/seqfeat/Code_break.hpp>
  71. #include <objects/seqfeat/Genetic_code.hpp>
  72. #include <objects/seqfeat/Genetic_code_table.hpp>
  73. #include <objects/seqfeat/Seq_feat.hpp>
  74. #include <objmgr/util/sequence.hpp>
  75. #include <util/strsearch.hpp>
  76. #include <list>
  77. #include <algorithm>
  78. BEGIN_NCBI_SCOPE
  79. BEGIN_SCOPE(objects)
  80. BEGIN_SCOPE(sequence)
  81. const COrg_ref& GetOrg_ref(const CBioseq_Handle& handle)
  82. {
  83.     {{
  84.         CSeqdesc_CI desc(handle, CSeqdesc::e_Source);
  85.         if (desc) {
  86.             return desc->GetSource().GetOrg();
  87.         }
  88.     }}
  89.     {{
  90.         CSeqdesc_CI desc(handle, CSeqdesc::e_Org);
  91.         if (desc) {
  92.             return desc->GetOrg();
  93.         }
  94.     }}
  95.     NCBI_THROW(CException, eUnknown, "No organism set");
  96. }
  97. int GetTaxId(const CBioseq_Handle& handle)
  98. {
  99.     try {
  100.         return GetOrg_ref(handle).GetTaxId();
  101.     }
  102.     catch (...) {
  103.         return 0;
  104.     }
  105. }
  106. TSeqPos GetLength(const CSeq_id& id, CScope* scope)
  107. {
  108.     if ( !scope ) {
  109.         return numeric_limits<TSeqPos>::max();
  110.     }
  111.     CBioseq_Handle hnd = scope->GetBioseqHandle(id);
  112.     if ( !hnd ) {
  113.         return numeric_limits<TSeqPos>::max();
  114.     }
  115.     CBioseq_Handle::TBioseqCore core = hnd.GetBioseqCore();
  116.     return core->GetInst().IsSetLength() ? core->GetInst().GetLength() :
  117.         numeric_limits<TSeqPos>::max();
  118. }
  119. TSeqPos GetLength(const CSeq_loc& loc, CScope* scope)
  120.     THROWS((CNoLength))
  121. {
  122.     switch (loc.Which()) {
  123.     case CSeq_loc::e_Pnt:
  124.         return 1;
  125.     case CSeq_loc::e_Int:
  126.         return loc.GetInt().GetLength();
  127.     case CSeq_loc::e_Null:
  128.     case CSeq_loc::e_Empty:
  129.         return 0;
  130.     case CSeq_loc::e_Whole:
  131.         return GetLength(loc.GetWhole(), scope);
  132.     case CSeq_loc::e_Packed_int:
  133.         return loc.GetPacked_int().GetLength();
  134.     case CSeq_loc::e_Mix:
  135.         return GetLength(loc.GetMix(), scope);
  136.     case CSeq_loc::e_Packed_pnt:   // just a bunch of points
  137.         return loc.GetPacked_pnt().GetPoints().size();
  138.     case CSeq_loc::e_not_set:
  139.     case CSeq_loc::e_Bond:         //can't calculate length
  140.     case CSeq_loc::e_Feat:
  141.     case CSeq_loc::e_Equiv:        // unless actually the same length...
  142.     default:
  143.         THROW0_TRACE(CNoLength());
  144.     }
  145. }
  146. TSeqPos GetLength(const CSeq_loc_mix& mix, CScope* scope)
  147.     THROWS((CNoLength))
  148. {
  149.     TSeqPos length = 0;
  150.     ITERATE( CSeq_loc_mix::Tdata, i, mix.Get() ) {
  151.         TSeqPos ret = GetLength((**i), scope);
  152.         length += ret;
  153.     }
  154.     return length;
  155. }
  156. bool IsValid(const CSeq_point& pt, CScope* scope)
  157. {
  158.     if (static_cast<TSeqPos>(pt.GetPoint()) >=
  159.          GetLength(pt.GetId(), scope) )
  160.     {
  161.         return false;
  162.     }
  163.     return true;
  164. }
  165. bool IsValid(const CPacked_seqpnt& pts, CScope* scope)
  166. {
  167.     typedef CPacked_seqpnt::TPoints TPoints;
  168.     TSeqPos length = GetLength(pts.GetId(), scope);
  169.     ITERATE (TPoints, it, pts.GetPoints()) {
  170.         if (*it >= length) {
  171.             return false;
  172.         }
  173.     }
  174.     return true;
  175. }
  176. bool IsValid(const CSeq_interval& interval, CScope* scope)
  177. {
  178.     if (interval.GetFrom() > interval.GetTo() ||
  179.         interval.GetTo() >= GetLength(interval.GetId(), scope))
  180.     {
  181.         return false;
  182.     }
  183.     return true;
  184. }
  185. bool IsSameBioseq (const CSeq_id& id1, const CSeq_id& id2, CScope* scope)
  186. {
  187.     // Compare CSeq_ids directly
  188.     if (id1.Compare(id2) == CSeq_id::e_YES) {
  189.         return true;
  190.     }
  191.     // Compare handles
  192.     if ( scope ) {
  193.         try {
  194.             CBioseq_Handle hnd1 = scope->GetBioseqHandle(id1);
  195.             CBioseq_Handle hnd2 = scope->GetBioseqHandle(id2);
  196.             return hnd1  &&  hnd2  &&  (hnd1 == hnd2);
  197.         } catch (exception& e) {
  198.             ERR_POST(e.what() << ": CSeq_id1: " << id1.DumpAsFasta()
  199.                      << ": CSeq_id2: " << id2.DumpAsFasta());
  200.             return false;
  201.         }
  202.     }
  203.     return false;
  204. }
  205. bool IsOneBioseq(const CSeq_loc& loc, CScope* scope)
  206. {
  207.     try {
  208.         GetId(loc, scope);
  209.         return true;
  210.     } catch (CNotUnique&) {
  211.         return false;
  212.     }
  213. }
  214. class CSeqIdFromHandleException : EXCEPTION_VIRTUAL_BASE public CException
  215. {
  216. public:
  217.     // Enumerated list of document management errors
  218.     enum EErrCode {
  219.         eNoSynonyms,
  220.         eRequestedIdNotFound
  221.     };
  222.     // Translate the specific error code into a string representations of
  223.     // that error code.
  224.     virtual const char* GetErrCodeString(void) const
  225.     {
  226.         switch (GetErrCode()) {
  227.         case eNoSynonyms:           return "eNoSynonyms";
  228.         case eRequestedIdNotFound:  return "eRequestedIdNotFound";
  229.         default:                    return CException::GetErrCodeString();
  230.         }
  231.     }
  232.     NCBI_EXCEPTION_DEFAULT(CSeqIdFromHandleException, CException);
  233. };
  234. const CSeq_id& GetId(const CBioseq_Handle& handle,
  235.                      EGetIdType type)
  236. {
  237.     switch (type) {
  238.     case eGetId_HandleDefault:
  239.         return *handle.GetSeqId();
  240.     case eGetId_ForceGi:
  241.         if (handle.GetSeqId().GetPointer()  &&  handle.GetSeqId()->IsGi()) {
  242.             return *handle.GetSeqId();
  243.         }
  244.         {{
  245.             CConstRef<CSynonymsSet> syns =
  246.                 handle.GetScope().GetSynonyms(*handle.GetSeqId());
  247.             if ( !syns ) {
  248.                 string msg("No synonyms found for sequence ");
  249.                 handle.GetSeqId()->GetLabel(&msg);
  250.                 NCBI_THROW(CSeqIdFromHandleException, eNoSynonyms, msg);
  251.             }
  252.             ITERATE (CSynonymsSet, iter, *syns) {
  253.                 CSeq_id_Handle idh = CSynonymsSet::GetSeq_id_Handle(iter);
  254.                 if (idh.GetSeqId()->IsGi()) {
  255.                     return *idh.GetSeqId();
  256.                 }
  257.             }
  258.         }}
  259.         break;
  260.     case eGetId_Best:
  261.         {{
  262.             CConstRef<CSynonymsSet> syns =
  263.                 handle.GetScope().GetSynonyms(handle.GetSeq_id_Handle());
  264.             if ( !syns ) {
  265.                 string msg("No synonyms found for sequence ");
  266.                 handle.GetSeqId()->GetLabel(&msg);
  267.                 NCBI_THROW(CSeqIdFromHandleException, eNoSynonyms, msg);
  268.             }
  269.             list< CRef<CSeq_id> > ids;
  270.             ITERATE (CSynonymsSet, iter, *syns) {
  271.                 CSeq_id_Handle idh = CSynonymsSet::GetSeq_id_Handle(iter);
  272.                 ids.push_back
  273.                     (CRef<CSeq_id>(const_cast<CSeq_id*>(idh.GetSeqId().GetPointer())));
  274.             }
  275.             CConstRef<CSeq_id> best_id = FindBestChoice(ids, CSeq_id::Score);
  276.             if (best_id) {
  277.                 return *best_id;
  278.             }
  279.         }}
  280.         break;
  281.     default:
  282.         NCBI_THROW(CSeqIdFromHandleException, eRequestedIdNotFound,
  283.                    "Unhandled seq-id type");
  284.         break;
  285.     }
  286.     NCBI_THROW(CSeqIdFromHandleException, eRequestedIdNotFound,
  287.                "No best seq-id could be found");
  288. }
  289. const CSeq_id& GetId(const CSeq_loc& loc, CScope* scope)
  290.     THROWS((CNotUnique))
  291. {
  292.     CTypeConstIterator<CSeq_id> cur = ConstBegin(loc);
  293.     CTypeConstIterator<CSeq_id> first = ConstBegin(loc);
  294.     if (!first) {
  295.         THROW0_TRACE(CNotUnique());
  296.     }
  297.     for (++cur; cur; ++cur) {
  298.         if ( !IsSameBioseq(*cur, *first, scope) ) {
  299.             THROW0_TRACE(CNotUnique());
  300.         }
  301.     }
  302.     return *first;
  303. }
  304. inline
  305. static ENa_strand s_GetStrand(const CSeq_loc& loc)
  306. {
  307.     switch (loc.Which()) {
  308.     case CSeq_loc::e_Bond:
  309.         {
  310.             const CSeq_bond& bond = loc.GetBond();
  311.             ENa_strand a_strand = bond.GetA().IsSetStrand() ?
  312.                 bond.GetA().GetStrand() : eNa_strand_unknown;
  313.             ENa_strand b_strand = eNa_strand_unknown;
  314.             if ( bond.IsSetB() ) {
  315.                 b_strand = bond.GetB().IsSetStrand() ?
  316.                     bond.GetB().GetStrand() : eNa_strand_unknown;
  317.             }
  318.             if ( a_strand == eNa_strand_unknown  &&
  319.                  b_strand != eNa_strand_unknown ) {
  320.                 a_strand = b_strand;
  321.             } else if ( a_strand != eNa_strand_unknown  &&
  322.                         b_strand == eNa_strand_unknown ) {
  323.                 b_strand = a_strand;
  324.             }
  325.             return (a_strand != b_strand) ? eNa_strand_other : a_strand;
  326.         }
  327.     case CSeq_loc::e_Whole:
  328.         return eNa_strand_both;
  329.     case CSeq_loc::e_Int:
  330.         return loc.GetInt().IsSetStrand() ? loc.GetInt().GetStrand() :
  331.             eNa_strand_unknown;
  332.     case CSeq_loc::e_Pnt:
  333.         return loc.GetPnt().IsSetStrand() ? loc.GetPnt().GetStrand() :
  334.             eNa_strand_unknown;
  335.     case CSeq_loc::e_Packed_pnt:
  336.         return loc.GetPacked_pnt().IsSetStrand() ?
  337.             loc.GetPacked_pnt().GetStrand() : eNa_strand_unknown;
  338.     case CSeq_loc::e_Packed_int:
  339.     {
  340.         ENa_strand strand = eNa_strand_unknown;
  341.         bool strand_set = false;
  342.         ITERATE(CPacked_seqint::Tdata, i, loc.GetPacked_int().Get()) {
  343.             ENa_strand istrand = (*i)->IsSetStrand() ? (*i)->GetStrand() :
  344.                 eNa_strand_unknown;
  345.             if (strand == eNa_strand_unknown  &&  istrand == eNa_strand_plus) {
  346.                 strand = eNa_strand_plus;
  347.                 strand_set = true;
  348.             } else if (strand == eNa_strand_plus  &&
  349.                 istrand == eNa_strand_unknown) {
  350.                 istrand = eNa_strand_plus;
  351.                 strand_set = true;
  352.             } else if (!strand_set) {
  353.                 strand = istrand;
  354.                 strand_set = true;
  355.             } else if (istrand != strand) {
  356.                 return eNa_strand_other;
  357.             }
  358.         }
  359.         return strand;
  360.     }
  361.     case CSeq_loc::e_Mix:
  362.     {
  363.         ENa_strand strand = eNa_strand_unknown;
  364.         bool strand_set = false;
  365.         ITERATE(CSeq_loc_mix::Tdata, it, loc.GetMix().Get()) {
  366.             ENa_strand istrand = GetStrand(**it);
  367.             if (strand == eNa_strand_unknown  &&  istrand == eNa_strand_plus) {
  368.                 strand = eNa_strand_plus;
  369.                 strand_set = true;
  370.             } else if (strand == eNa_strand_plus  &&
  371.                 istrand == eNa_strand_unknown) {
  372.                 istrand = eNa_strand_plus;
  373.                 strand_set = true;
  374.             } else if (!strand_set) {
  375.                 strand = istrand;
  376.                 strand_set = true;
  377.             } else if (istrand != strand) {
  378.                 return eNa_strand_other;
  379.             }
  380.         }
  381.     }
  382.     default:
  383.         return eNa_strand_unknown;
  384.     }
  385. }
  386. ENa_strand GetStrand(const CSeq_loc& loc, CScope* scope)
  387. {
  388.     if (!IsOneBioseq(loc, scope)) {
  389.         return eNa_strand_unknown;  // multiple bioseqs
  390.     }
  391.     ENa_strand strand = eNa_strand_unknown, cstrand;
  392.     bool strand_set = false;
  393.     for (CSeq_loc_CI i(loc); i; ++i) {
  394.         switch (i.GetSeq_loc().Which()) {
  395.         case CSeq_loc::e_Equiv:
  396.             break;
  397.         default:
  398.             cstrand = s_GetStrand(i.GetSeq_loc());
  399.             if (strand == eNa_strand_unknown  &&  cstrand == eNa_strand_plus) {
  400.                 strand = eNa_strand_plus;
  401.                 strand_set = true;
  402.             } else if (strand == eNa_strand_plus  &&
  403.                 cstrand == eNa_strand_unknown) {
  404.                 cstrand = eNa_strand_plus;
  405.                 strand_set = true;
  406.             } else if (!strand_set) {
  407.                 strand = cstrand;
  408.                 strand_set = true;
  409.             } else if (cstrand != strand) {
  410.                 return eNa_strand_other;
  411.             }
  412.         }
  413.     }
  414.     return strand;
  415. }
  416. TSeqPos GetStart(const CSeq_loc& loc, CScope* scope)
  417.     THROWS((CNotUnique))
  418. {
  419.     // Throw CNotUnique if loc does not represent one CBioseq
  420.     GetId(loc, scope);
  421.     CSeq_loc::TRange rg = loc.GetTotalRange();
  422.     return rg.GetFrom();
  423. }
  424. TSeqPos GetStop(const CSeq_loc& loc, CScope* scope)
  425.     THROWS((CNotUnique))
  426. {
  427.     // Throw CNotUnique if loc does not represent one CBioseq
  428.     GetId(loc, scope);
  429.     CSeq_loc::TRange rg = loc.GetTotalRange();
  430.     return rg.GetTo();
  431. }
  432. /*
  433. *******************************************************************************
  434.                         Implementation of Compare()
  435. *******************************************************************************
  436. */
  437. ECompare s_Compare
  438. (const CSeq_loc&,
  439.  const CSeq_loc&,
  440.  CScope*);
  441. int s_RetA[5][5] = {
  442.     { 0, 4, 2, 2, 4 },
  443.     { 4, 1, 4, 1, 4 },
  444.     { 2, 4, 2, 2, 4 },
  445.     { 2, 1, 2, 3, 4 },
  446.     { 4, 4, 4, 4, 4 }
  447. };
  448. int s_RetB[5][5] = {
  449.     { 0, 1, 4, 1, 4 },
  450.     { 1, 1, 4, 1, 1 },
  451.     { 4, 4, 2, 2, 4 },
  452.     { 1, 1, 4, 3, 4 },
  453.     { 4, 1, 4, 4, 4 }
  454. };
  455. // Returns the complement of an ECompare value
  456. inline
  457. ECompare s_Complement(ECompare cmp)
  458. {
  459.     switch ( cmp ) {
  460.     case eContains:
  461.         return eContained;
  462.     case eContained:
  463.         return eContains;
  464.     default:
  465.         return cmp;
  466.     }
  467. }
  468. // Compare two Whole sequences
  469. inline
  470. ECompare s_Compare
  471. (const CSeq_id& id1,
  472.  const CSeq_id& id2,
  473.  CScope*        scope)
  474. {
  475.     // If both sequences from same CBioseq, they are the same
  476.     if ( IsSameBioseq(id1, id2, scope) ) {
  477.         return eSame;
  478.     } else {
  479.         return eNoOverlap;
  480.     }
  481. }
  482. // Compare Whole sequence with a Bond
  483. inline
  484. ECompare s_Compare
  485. (const CSeq_id&   id,
  486.  const CSeq_bond& bond,
  487.  CScope*          scope)
  488. {
  489.     unsigned int count = 0;
  490.     // Increment count if bond point A is from same CBioseq as id
  491.     if ( IsSameBioseq(id, bond.GetA().GetId(), scope) ) {
  492.         ++count;
  493.     }
  494.     // Increment count if second point in bond is set and is from
  495.     // same CBioseq as id.
  496.     if (bond.IsSetB()  &&  IsSameBioseq(id, bond.GetB().GetId(), scope)) {
  497.         ++count;
  498.     }
  499.     switch ( count ) {
  500.     case 1:
  501.         if ( bond.IsSetB() ) {
  502.             // One of two bond points are from same CBioseq as id --> overlap
  503.             return eOverlap;
  504.         } else {
  505.             // There is only one bond point set --> id contains bond
  506.             return eContains;
  507.         }
  508.     case 2:
  509.         // Both bond points are from same CBioseq as id --> id contains bond
  510.         return eContains;
  511.     default:
  512.         // id and bond do not overlap
  513.         return eNoOverlap;
  514.     }
  515. }
  516. // Compare Whole sequence with an interval
  517. inline
  518. ECompare s_Compare
  519. (const CSeq_id&       id,
  520.  const CSeq_interval& interval,
  521.  CScope*              scope)
  522. {
  523.     // If interval is from same CBioseq as id and interval is
  524.     // [0, length of id-1], then they are the same. If interval is from same
  525.     // CBioseq as id, but interval is not [0, length of id -1] then id
  526.     // contains seqloc.
  527.     if ( IsSameBioseq(id, interval.GetId(), scope) ) {
  528.         if (interval.GetFrom() == 0  &&
  529.             interval.GetTo()   == GetLength(id, scope) - 1) {
  530.             return eSame;
  531.         } else {
  532.             return eContains;
  533.         }
  534.     } else {
  535.         return eNoOverlap;
  536.     }
  537. }
  538. // Compare Whole sequence with a point
  539. inline
  540. ECompare s_Compare
  541. (const CSeq_id&     id,
  542.  const CSeq_point&  point,
  543.  CScope*            scope)
  544. {
  545.     // If point from the same CBioseq as id, then id contains point
  546.     if ( IsSameBioseq(id, point.GetId(), scope) ) {
  547.         return eContains;
  548.     } else {
  549.         return eNoOverlap;
  550.     }
  551. }
  552. // Compare Whole sequence with packed points
  553. inline
  554. ECompare s_Compare
  555. (const CSeq_id&        id,
  556.  const CPacked_seqpnt& packed,
  557.  CScope*               scope)
  558. {
  559.     // If packed from same CBioseq as id, then id contains packed
  560.     if ( IsSameBioseq(id, packed.GetId(), scope) ) {
  561.         return eContains;
  562.     } else {
  563.         return eNoOverlap;
  564.     }
  565. }
  566. // Compare an interval with a bond
  567. inline
  568. ECompare s_Compare
  569. (const CSeq_interval& interval,
  570.  const CSeq_bond&     bond,
  571.  CScope*              scope)
  572. {
  573.     unsigned int count = 0;
  574.     // Increment count if interval contains the first point of the bond
  575.     if (IsSameBioseq(interval.GetId(), bond.GetA().GetId(), scope)  &&
  576.         interval.GetFrom() <= bond.GetA().GetPoint()  &&
  577.         interval.GetTo()   >= bond.GetA().GetPoint()) {
  578.         ++count;
  579.     }
  580.     // Increment count if the second point of the bond is set and the
  581.     // interval contains the second point.
  582.     if (bond.IsSetB()  &&
  583.         IsSameBioseq(interval.GetId(), bond.GetB().GetId(), scope)  &&
  584.         interval.GetFrom() <= bond.GetB().GetPoint()  &&
  585.         interval.GetTo()   >= bond.GetB().GetPoint()) {
  586.         ++count;
  587.     }
  588.     switch ( count ) {
  589.     case 1:
  590.         if ( bond.IsSetB() ) {
  591.             // The 2nd point of the bond is set
  592.             return eOverlap;
  593.         } else {
  594.             // The 2nd point of the bond is not set
  595.             return eContains;
  596.         }
  597.     case 2:
  598.         // Both points of the bond are in the interval
  599.         return eContains;
  600.     default:
  601.         return eNoOverlap;
  602.     }
  603. }
  604. // Compare a bond with an interval
  605. inline
  606. ECompare s_Compare
  607. (const CSeq_bond&     bond,
  608.  const CSeq_interval& interval,
  609.  CScope*              scope)
  610. {
  611.     // Just return the complement of comparing an interval with a bond
  612.     return s_Complement(s_Compare(interval, bond, scope));
  613. }
  614. // Compare an interval to an interval
  615. inline
  616. ECompare s_Compare
  617. (const CSeq_interval& intA,
  618.  const CSeq_interval& intB,
  619.  CScope*              scope)
  620. {
  621.     // If the intervals are not on the same bioseq, then there is no overlap
  622.     if ( !IsSameBioseq(intA.GetId(), intB.GetId(), scope) ) {
  623.         return eNoOverlap;
  624.     }
  625.     // Compare two intervals
  626.     TSeqPos fromA = intA.GetFrom();
  627.     TSeqPos toA   = intA.GetTo();
  628.     TSeqPos fromB = intB.GetFrom();
  629.     TSeqPos toB   = intB.GetTo();
  630.     if (fromA == fromB  &&  toA == toB) {
  631.         // End points are the same --> the intervals are the same.
  632.         return eSame;
  633.     } else if (fromA <= fromB  &&  toA >= toB) {
  634.         // intA contains intB
  635.         return eContains;
  636.     } else if (fromA >= fromB  &&  toA <= toB) {
  637.         // intB contains intA
  638.         return eContained;
  639.     } else if (fromA > toB  ||  toA < fromB) {
  640.         // No overlap
  641.         return eNoOverlap;
  642.     } else {
  643.         // The only possibility left is overlap
  644.         return eOverlap;
  645.     }
  646. }
  647. // Compare an interval and a point
  648. inline
  649. ECompare s_Compare
  650. (const CSeq_interval& interval,
  651.  const CSeq_point&    point,
  652.  CScope*              scope)
  653. {
  654.     // If not from same CBioseq, then no overlap
  655.     if ( !IsSameBioseq(interval.GetId(), point.GetId(), scope) ) {
  656.         return eNoOverlap;
  657.     }
  658.     TSeqPos pnt = point.GetPoint();
  659.     // If the interval is of length 1 and contains the point, then they are
  660.     // identical
  661.     if (interval.GetFrom() == pnt  &&  interval.GetTo() == pnt ) {
  662.         return eSame;
  663.     }
  664.     // If point in interval, then interval contains point
  665.     if (interval.GetFrom() <= pnt  &&  interval.GetTo() >= pnt ) {
  666.         return eContains;
  667.     }
  668.     // Only other possibility
  669.     return eNoOverlap;
  670. }
  671. // Compare a point and an interval
  672. inline
  673. ECompare s_Compare
  674. (const CSeq_point&    point,
  675.  const CSeq_interval& interval,
  676.  CScope*              scope)
  677. {
  678.     // The complement of comparing an interval with a point.
  679.     return s_Complement(s_Compare(interval, point, scope));
  680. }
  681. // Compare a point with a point
  682. inline
  683. ECompare s_Compare
  684. (const CSeq_point& pntA,
  685.  const CSeq_point& pntB,
  686.  CScope*           scope)
  687. {
  688.     // If points are on same bioseq and coordinates are the same, then same.
  689.     if (IsSameBioseq(pntA.GetId(), pntB.GetId(), scope)  &&
  690.         pntA.GetPoint() == pntB.GetPoint() ) {
  691.         return eSame;
  692.     }
  693.     // Otherwise they don't overlap
  694.     return eNoOverlap;
  695. }
  696. // Compare a point with packed point
  697. inline
  698. ECompare s_Compare
  699. (const CSeq_point&     point,
  700.  const CPacked_seqpnt& points,
  701.  CScope*               scope)
  702. {
  703.     // If on the same bioseq, and any of the packed points are the
  704.     // same as point, then the point is contained in the packed point
  705.     if ( IsSameBioseq(point.GetId(), points.GetId(), scope) ) {
  706.         TSeqPos pnt = point.GetPoint();
  707.         // This loop will only be executed if points.GetPoints().size() > 0
  708.         ITERATE(CSeq_loc::TPoints, it, points.GetPoints()) {
  709.             if (pnt == *it) {
  710.                 return eContained;
  711.             }
  712.         }
  713.     }
  714.     // Otherwise, no overlap
  715.     return eNoOverlap;
  716. }
  717. // Compare a point with a bond
  718. inline
  719. ECompare s_Compare
  720. (const CSeq_point& point,
  721.  const CSeq_bond&  bond,
  722.  CScope*           scope)
  723. {
  724.     unsigned int count = 0;
  725.     // If the first point of the bond is on the same CBioseq as point
  726.     // and the point coordinates are the same, increment count by 1
  727.     if (IsSameBioseq(point.GetId(), bond.GetA().GetId(), scope)  &&
  728.         bond.GetA().GetPoint() == point.GetPoint()) {
  729.         ++count;
  730.     }
  731.     // If the second point of the bond is set, the points are from the
  732.     // same CBioseq, and the coordinates of the points are the same,
  733.     // increment the count by 1.
  734.     if (bond.IsSetB()  &&
  735.         IsSameBioseq(point.GetId(), bond.GetB().GetId(), scope)  &&
  736.         bond.GetB().GetPoint() == point.GetPoint()) {
  737.         ++count;
  738.     }
  739.     switch ( count ) {
  740.     case 1:
  741.         if ( bond.IsSetB() ) {
  742.             // The second point of the bond is set -- overlap
  743.             return eOverlap;
  744.             // The second point of the bond is not set -- same
  745.         } else {
  746.             return eSame;
  747.         }
  748.     case 2:
  749.         // Unlikely case -- can happen if both points of the bond are the same
  750.         return eSame;
  751.     default:
  752.         // All that's left is no overlap
  753.         return eNoOverlap;
  754.     }
  755. }
  756. // Compare packed point with an interval
  757. inline
  758. ECompare s_Compare
  759. (const CPacked_seqpnt& points,
  760.  const CSeq_interval&  interval,
  761.  CScope*               scope)
  762. {
  763.     // If points and interval are from same bioseq and some points are
  764.     // in interval, then overlap. If all points are in interval, then
  765.     // contained. Else, no overlap.
  766.     if ( IsSameBioseq(points.GetId(), interval.GetId(), scope) ) {
  767.         bool    got_one    = false;
  768.         bool    missed_one = false;
  769.         TSeqPos from = interval.GetFrom();
  770.         TSeqPos to   = interval.GetTo();
  771.         // This loop will only be executed if points.GetPoints().size() > 0
  772.         ITERATE(CSeq_loc::TPoints, it, points.GetPoints()) {
  773.             if (from <= *it  &&  to >= *it) {
  774.                 got_one = true;
  775.             } else {
  776.                 missed_one = true;
  777.             }
  778.             if (got_one  &&  missed_one) {
  779.                 break;
  780.             }
  781.         }
  782.         if ( !got_one ) {
  783.             return eNoOverlap;
  784.         } else if ( missed_one ) {
  785.             return eOverlap;
  786.         } else {
  787.             return eContained;
  788.         }
  789.     }
  790.     return eNoOverlap;
  791. }
  792. // Compare two packed points
  793. inline
  794. ECompare s_Compare
  795. (const CPacked_seqpnt& pntsA,
  796.  const CPacked_seqpnt& pntsB,
  797.  CScope*               scope)
  798. {
  799.     // If CPacked_seqpnts from different CBioseqs, then no overlap
  800.     if ( !IsSameBioseq(pntsA.GetId(), pntsB.GetId(), scope) ) {
  801.         return eNoOverlap;
  802.     }
  803.     const CSeq_loc::TPoints& pointsA = pntsA.GetPoints();
  804.     const CSeq_loc::TPoints& pointsB = pntsB.GetPoints();
  805.     // Check for equality. Note order of points is significant
  806.     if (pointsA.size() == pointsB.size()) {
  807.         CSeq_loc::TPoints::const_iterator iA = pointsA.begin();
  808.         CSeq_loc::TPoints::const_iterator iB = pointsB.begin();
  809.         bool check_containtment = false;
  810.         // This loop will only be executed if pointsA.size() > 0
  811.         while (iA != pointsA.end()) {
  812.             if (*iA != *iB) {
  813.                 check_containtment = true;
  814.                 break;
  815.             }
  816.             ++iA;
  817.             ++iB;
  818.         }
  819.         if ( !check_containtment ) {
  820.             return eSame;
  821.         }
  822.     }
  823.     // Check for containment
  824.     size_t hits = 0;
  825.     // This loop will only be executed if pointsA.size() > 0
  826.     ITERATE(CSeq_loc::TPoints, iA, pointsA) {
  827.         ITERATE(CSeq_loc::TPoints, iB, pointsB) {
  828.             hits += (*iA == *iB) ? 1 : 0;
  829.         }
  830.     }
  831.     if (hits == pointsA.size()) {
  832.         return eContained;
  833.     } else if (hits == pointsB.size()) {
  834.         return eContains;
  835.     } else if (hits == 0) {
  836.         return eNoOverlap;
  837.     } else {
  838.         return eOverlap;
  839.     }
  840. }
  841. // Compare packed point with bond
  842. inline
  843. ECompare s_Compare
  844. (const CPacked_seqpnt& points,
  845.  const CSeq_bond&      bond,
  846.  CScope*               scope)
  847. {
  848.     // If all set bond points (can be just 1) are in points, then contains. If
  849.     // one, but not all bond points in points, then overlap, else, no overlap
  850.     const CSeq_point& bondA = bond.GetA();
  851.     ECompare cmp = eNoOverlap;
  852.     // Check for containment of the first residue in the bond
  853.     if ( IsSameBioseq(points.GetId(), bondA.GetId(), scope) ) {
  854.         TSeqPos pntA = bondA.GetPoint();
  855.         // This loop will only be executed if points.GetPoints().size() > 0
  856.         ITERATE(CSeq_loc::TPoints, it, points.GetPoints()) {
  857.             if (pntA == *it) {
  858.                 cmp = eContains;
  859.                 break;
  860.             }
  861.         }
  862.     }
  863.     // Check for containment of the second residue of the bond if it exists
  864.     if ( !bond.IsSetB() ) {
  865.         return cmp;
  866.     }
  867.     const CSeq_point& bondB = bond.GetB();
  868.     if ( !IsSameBioseq(points.GetId(), bondB.GetId(), scope) ) {
  869.         return cmp;
  870.     }
  871.     TSeqPos pntB = bondB.GetPoint();
  872.     // This loop will only be executed if points.GetPoints().size() > 0
  873.     ITERATE(CSeq_loc::TPoints, it, points.GetPoints()) {
  874.         if (pntB == *it) {
  875.             if (cmp == eContains) {
  876.                 return eContains;
  877.             } else {
  878.                 return eOverlap;
  879.             }
  880.         }
  881.     }
  882.     return cmp == eContains ? eOverlap : cmp;
  883. }
  884. // Compare a bond with a bond
  885. inline
  886. ECompare s_Compare
  887. (const CSeq_bond& bndA,
  888.  const CSeq_bond& bndB,
  889.  CScope*          scope)
  890. {
  891.     // Performs two comparisons. First comparison is comparing the a points
  892.     // of each bond and the b points of each bond. The second comparison
  893.     // compares point a of bndA with point b of bndB and point b of bndA
  894.     // with point a of bndB. The best match is used.
  895.     ECompare cmp1, cmp2;
  896.     int div = static_cast<int> (eSame);
  897.     // Compare first points in each bond
  898.     cmp1 = s_Compare(bndA.GetA(), bndB.GetA(), scope);
  899.     // Compare second points in each bond if both exist
  900.     if (bndA.IsSetB()  &&  bndB.IsSetB() ) {
  901.         cmp2 = s_Compare(bndA.GetB(), bndB.GetB(), scope);
  902.     } else {
  903.         cmp2 = eNoOverlap;
  904.     }
  905.     int count1 = (static_cast<int> (cmp1) + static_cast<int> (cmp2)) / div;
  906.     // Compare point A of bndA with point B of bndB (if it exists)
  907.     if ( bndB.IsSetB() ) {
  908.         cmp1 = s_Compare(bndA.GetA(), bndB.GetB(), scope);
  909.     } else {
  910.         cmp1 = eNoOverlap;
  911.     }
  912.     // Compare point B of bndA (if it exists) with point A of bndB.
  913.     if ( bndA.IsSetB() ) {
  914.         cmp2 = s_Compare(bndA.GetB(), bndB.GetA(), scope);
  915.     } else {
  916.         cmp2 = eNoOverlap;
  917.     }
  918.     int count2 = (static_cast<int> (cmp1) + static_cast<int> (cmp2)) / div;
  919.     // Determine best match
  920.     int count = (count1 > count2) ? count1 : count2;
  921.     // Return based upon count in the obvious way
  922.     switch ( count ) {
  923.     case 1:
  924.         if (!bndA.IsSetB()  &&  !bndB.IsSetB()) {
  925.             return eSame;
  926.         } else if ( !bndB.IsSetB() ) {
  927.             return eContains;
  928.         } else if ( !bndA.IsSetB() ) {
  929.             return eContained;
  930.         } else {
  931.             return eOverlap;
  932.         }
  933.     case 2:
  934.         return eSame;
  935.     default:
  936.         return eNoOverlap;
  937.     }
  938. }
  939. // Compare an interval with a whole sequence
  940. inline
  941. ECompare s_Compare
  942. (const CSeq_interval& interval,
  943.  const CSeq_id&       id,
  944.  CScope*              scope)
  945. {
  946.     // Return the complement of comparing id with interval
  947.     return s_Complement(s_Compare(id, interval, scope));
  948. }
  949. // Compare an interval with a packed point
  950. inline
  951. ECompare s_Compare
  952. (const CSeq_interval&  interval,
  953.  const CPacked_seqpnt& packed,
  954.  CScope*               scope)
  955. {
  956.     // Return the complement of comparing packed points and an interval
  957.     return s_Complement(s_Compare(packed, interval, scope));
  958. }
  959. // Compare a Packed Interval with one of Whole, Interval, Point,
  960. // Packed Point, or Bond.
  961. template <class T>
  962. ECompare s_Compare
  963. (const CPacked_seqint& intervals,
  964.  const T&              slt,
  965.  CScope*               scope)
  966. {
  967.     // Check that intervals is not empty
  968.     if(intervals.Get().size() == 0) {
  969.         return eNoOverlap;
  970.     }
  971.     ECompare cmp1 , cmp2;
  972.     CSeq_loc::TIntervals::const_iterator it = intervals.Get().begin();
  973.     cmp1 = s_Compare(**it, slt, scope);
  974.     // This loop will be executed only if intervals.Get().size() > 1
  975.     for (++it;  it != intervals.Get().end();  ++it) {
  976.         cmp2 = s_Compare(**it, slt, scope);
  977.         cmp1 = static_cast<ECompare> (s_RetA[cmp1][cmp2]);
  978.     }
  979.     return cmp1;
  980. }
  981. // Compare one of Whole, Interval, Point, Packed Point, or Bond with a
  982. // Packed Interval.
  983. template <class T>
  984. ECompare s_Compare
  985. (const T&              slt,
  986.  const CPacked_seqint& intervals,
  987.  CScope*               scope)
  988. {
  989.     // Check that intervals is not empty
  990.     if(intervals.Get().size() == 0) {
  991.         return eNoOverlap;
  992.     }
  993.     ECompare cmp1 , cmp2;
  994.     CSeq_loc::TIntervals::const_iterator it = intervals.Get().begin();
  995.     cmp1 = s_Compare(slt, **it, scope);
  996.     // This loop will be executed only if intervals.Get().size() > 1
  997.     for (++it;  it != intervals.Get().end();  ++it) {
  998.         cmp2 = s_Compare(slt, **it, scope);
  999.         cmp1 = static_cast<ECompare> (s_RetB[cmp1][cmp2]);
  1000.     }
  1001.     return cmp1;
  1002. }
  1003. // Compare a CSeq_loc and a CSeq_interval. Used by s_Compare_Help below
  1004. // when comparing list<CRef<CSeq_loc>> with list<CRef<CSeq_interval>>.
  1005. // By wrapping the CSeq_interval in a CSeq_loc, s_Compare(const CSeq_loc&,
  1006. // const CSeq_loc&, CScope*) can be called. This permits CPacked_seqint type
  1007. // CSeq_locs to be treated the same as CSeq_loc_mix and CSeq_loc_equiv type
  1008. // CSeq_locs
  1009. inline
  1010. ECompare s_Compare
  1011. (const CSeq_loc&      sl,
  1012.  const CSeq_interval& si,
  1013.  CScope*              scope)
  1014. {
  1015.     CSeq_loc nsl;
  1016.     nsl.SetInt(const_cast<CSeq_interval&>(si));
  1017.     return s_Compare(sl, nsl, scope);
  1018. }
  1019. // Compare a CSeq_interval and a CSeq_loc. Used by s_Compare_Help below
  1020. // when comparing TLocations with TIntervals. By
  1021. // wrapping the CSeq_interval in a CSeq_loc, s_Compare(const CSeq_loc&,
  1022. // const CSeq_loc&, CScope*) can be called. This permits CPacked_seqint type
  1023. // CSeq_locs to be treated the same as CSeq_loc_mix and CSeq_loc_equiv type
  1024. // CSeq_locs
  1025. inline
  1026. ECompare s_Compare
  1027. (const CSeq_interval& si,
  1028.  const CSeq_loc&      sl,
  1029.  CScope*              scope)
  1030. {
  1031.     CSeq_loc nsl;
  1032.     nsl.SetInt(const_cast<CSeq_interval&>(si));
  1033.     return s_Compare(nsl, sl, scope);
  1034. }
  1035. // Called by s_Compare() below for <CSeq_loc, CSeq_loc>,
  1036. // <CSeq_loc, CSeq_interval>, <CSeq_interval, CSeq_loc>, and
  1037. // <CSeq_interval, CSeq_interval>
  1038. template <class T1, class T2>
  1039. ECompare s_Compare_Help
  1040. (const list<CRef<T1> >& mec,
  1041.  const list<CRef<T2> >& youc,
  1042.  const CSeq_loc&        you,
  1043.  CScope*                scope)
  1044. {
  1045.     // If either mec or youc is empty, return eNoOverlap
  1046.     if(mec.size() == 0  ||  youc.size() == 0) {
  1047.         return eNoOverlap;
  1048.     }
  1049.     typename list<CRef<T1> >::const_iterator mit = mec.begin();
  1050.     typename list<CRef<T2> >::const_iterator yit = youc.begin();
  1051.     ECompare cmp1, cmp2;
  1052.     // Check for equality of the lists. Note, order of the lists contents are
  1053.     // significant
  1054.     if (mec.size() == youc.size()) {
  1055.         bool check_contained = false;
  1056.         for ( ;  mit != mec.end()  &&  yit != youc.end();  ++mit, ++yit) {
  1057.             if (s_Compare(**mit, ** yit, scope) != eSame) {
  1058.                 check_contained = true;
  1059.                 break;
  1060.             }
  1061.         }
  1062.         if ( !check_contained ) {
  1063.             return eSame;
  1064.         }
  1065.     }
  1066.     // Check if mec contained in youc
  1067.     mit = mec.begin();
  1068.     yit = youc.begin();
  1069.     bool got_one = false;
  1070.     while (mit != mec.end()  &&  yit != youc.end()) {
  1071.         cmp1 = s_Compare(**mit, **yit, scope);
  1072.         switch ( cmp1 ) {
  1073.         case eNoOverlap:
  1074.             ++yit;
  1075.             break;
  1076.         case eSame:
  1077.             ++mit;
  1078.             ++yit;
  1079.             got_one = true;
  1080.             break;
  1081.         case eContained:
  1082.             ++mit;
  1083.             got_one = true;
  1084.             break;
  1085.         default:
  1086.             got_one = true;
  1087.             // artificial trick -- just to get out the loop "prematurely"
  1088.             yit = youc.end();
  1089.         }
  1090.     }
  1091.     if (mit == mec.end()) {
  1092.         return eContained;
  1093.     }
  1094.     // Check if mec contains youc
  1095.     mit = mec.begin();
  1096.     yit = youc.begin();
  1097.     while (mit != mec.end()  &&  yit != youc.end() ) {
  1098.         cmp1 = s_Compare(**yit, **mit, scope);
  1099.         switch ( cmp1 ) {
  1100.         case eNoOverlap:
  1101.             ++mit;
  1102.             break;
  1103.         case eSame:
  1104.             ++mit;
  1105.             ++yit;
  1106.             got_one = true;
  1107.             break;
  1108.         case eContained:
  1109.             ++yit;
  1110.             got_one = true;
  1111.             break;
  1112.         default:
  1113.             got_one = true;
  1114.             // artificial trick -- just to get out the loop "prematurely"
  1115.             mit = mec.end();
  1116.         }
  1117.     }
  1118.     if (yit == youc.end()) {
  1119.         return eContains;
  1120.     }
  1121.     // Check for overlap of mec and youc
  1122.     if ( got_one ) {
  1123.         return eOverlap;
  1124.     }
  1125.     mit = mec.begin();
  1126.     cmp1 = s_Compare(**mit, you, scope);
  1127.     for (++mit;  mit != mec.end();  ++mit) {
  1128.         cmp2 = s_Compare(**mit, you, scope);
  1129.         cmp1 = static_cast<ECompare> (s_RetA[cmp1][cmp2]);
  1130.     }
  1131.     return cmp1;
  1132. }
  1133. inline
  1134. const CSeq_loc::TLocations& s_GetLocations(const CSeq_loc& loc)
  1135. {
  1136.     switch (loc.Which()) {
  1137.         case CSeq_loc::e_Mix:    return loc.GetMix().Get();
  1138.         case CSeq_loc::e_Equiv:  return loc.GetEquiv().Get();
  1139.         default: // should never happen, but the compiler doesn't know that...
  1140.         NCBI_THROW(CObjmgrUtilException, eBadLocation,
  1141.                          "s_GetLocations: unsupported location type:"
  1142.                          + CSeq_loc::SelectionName(loc.Which()));
  1143.     }
  1144. }
  1145. // Compares two Seq-locs
  1146. ECompare s_Compare
  1147. (const CSeq_loc& me,
  1148.  const CSeq_loc& you,
  1149.  CScope*         scope)
  1150. {
  1151.     // Handle the case where me is one of e_Mix, e_Equiv, e_Packed_int
  1152.     switch ( me.Which() ) {
  1153.     case CSeq_loc::e_Mix:
  1154.     case CSeq_loc::e_Equiv: {
  1155.         const CSeq_loc::TLocations& pmc = s_GetLocations(me);
  1156.         switch ( you.Which() ) {
  1157.         case CSeq_loc::e_Mix:
  1158.         case CSeq_loc::e_Equiv: {
  1159.             const CSeq_loc::TLocations& pyc = s_GetLocations(you);
  1160.             return s_Compare_Help(pmc, pyc, you, scope);
  1161.         }
  1162.         case CSeq_loc::e_Packed_int: {
  1163.             const CSeq_loc::TIntervals& pyc = you.GetPacked_int().Get();
  1164.             return s_Compare_Help(pmc,pyc, you, scope);
  1165.         }
  1166.         case CSeq_loc::e_Null:
  1167.         case CSeq_loc::e_Empty:
  1168.         case CSeq_loc::e_Whole:
  1169.         case CSeq_loc::e_Int:
  1170.         case CSeq_loc::e_Pnt:
  1171.         case CSeq_loc::e_Packed_pnt:
  1172.         case CSeq_loc::e_Bond:
  1173.         case CSeq_loc::e_Feat: {
  1174.             //Check that pmc is not empty
  1175.             if(pmc.size() == 0) {
  1176.                 return eNoOverlap;
  1177.             }
  1178.             CSeq_loc::TLocations::const_iterator mit = pmc.begin();
  1179.             ECompare cmp1, cmp2;
  1180.             cmp1 = s_Compare(**mit, you, scope);
  1181.             // This loop will only be executed if pmc.size() > 1
  1182.             for (++mit;  mit != pmc.end();  ++mit) {
  1183.                 cmp2 = s_Compare(**mit, you, scope);
  1184.                 cmp1 = static_cast<ECompare> (s_RetA[cmp1][cmp2]);
  1185.             }
  1186.             return cmp1;
  1187.         }
  1188.         default:
  1189.             return eNoOverlap;
  1190.         }
  1191.     }
  1192.     case CSeq_loc::e_Packed_int: {
  1193.         switch ( you.Which() ) {
  1194.         case CSeq_loc::e_Mix:
  1195.         case CSeq_loc::e_Equiv: {
  1196.             const CSeq_loc::TLocations& pyc = s_GetLocations(you);
  1197.             const CSeq_loc::TIntervals& pmc = me.GetPacked_int().Get();
  1198.             return s_Compare_Help(pmc,pyc, you, scope);
  1199.         }
  1200.         case CSeq_loc::e_Packed_int: {
  1201.             const CSeq_loc::TIntervals& mc = me.GetPacked_int().Get();
  1202.             const CSeq_loc::TIntervals& yc = you.GetPacked_int().Get();
  1203.             return s_Compare_Help(mc, yc, you, scope);
  1204.         }
  1205.         default:
  1206.             // All other cases are handled below
  1207.             break;
  1208.         }
  1209.     }
  1210.     default:
  1211.         // All other cases are handled below
  1212.         break;
  1213.     }
  1214.     // Note, at this point, me is not one of e_Mix or e_Equiv
  1215.     switch ( you.Which() ) {
  1216.     case CSeq_loc::e_Mix:
  1217.     case CSeq_loc::e_Equiv: {
  1218.         const CSeq_loc::TLocations& pyouc = s_GetLocations(you);
  1219.         // Check that pyouc is not empty
  1220.         if(pyouc.size() == 0) {
  1221.             return eNoOverlap;
  1222.         }
  1223.         CSeq_loc::TLocations::const_iterator yit = pyouc.begin();
  1224.         ECompare cmp1, cmp2;
  1225.         cmp1 = s_Compare(me, **yit, scope);
  1226.         // This loop will only be executed if pyouc.size() > 1
  1227.         for (++yit;  yit != pyouc.end();  ++yit) {
  1228.             cmp2 = s_Compare(me, **yit, scope);
  1229.             cmp1 = static_cast<ECompare> (s_RetB[cmp1][cmp2]);
  1230.         }
  1231.         return cmp1;
  1232.     }
  1233.     // All other cases handled below
  1234.     default:
  1235.         break;
  1236.     }
  1237.     switch ( me.Which() ) {
  1238.     case CSeq_loc::e_Null: {
  1239.         switch ( you.Which() ) {
  1240.         case CSeq_loc::e_Null:
  1241.             return eSame;
  1242.         default:
  1243.             return eNoOverlap;
  1244.         }
  1245.     }
  1246.     case CSeq_loc::e_Empty: {
  1247.         switch ( you.Which() ) {
  1248.         case CSeq_loc::e_Empty:
  1249.             if ( IsSameBioseq(me.GetEmpty(), you.GetEmpty(), scope) ) {
  1250.                 return eSame;
  1251.             } else {
  1252.                 return eNoOverlap;
  1253.             }
  1254.         default:
  1255.             return eNoOverlap;
  1256.         }
  1257.     }
  1258.     case CSeq_loc::e_Packed_int: {
  1259.         // Comparison of two e_Packed_ints is handled above
  1260.         switch ( you.Which() ) {
  1261.         case CSeq_loc::e_Whole:
  1262.             return s_Compare(me.GetPacked_int(), you.GetWhole(), scope);
  1263.         case CSeq_loc::e_Int:
  1264.             return s_Compare(me.GetPacked_int(), you.GetInt(), scope);
  1265.         case CSeq_loc::e_Pnt:
  1266.             return s_Compare(me.GetPacked_int(), you.GetPnt(), scope);
  1267.         case CSeq_loc::e_Packed_pnt:
  1268.             return s_Compare(me.GetPacked_int(), you.GetPacked_pnt(), scope);
  1269.         case CSeq_loc::e_Bond:
  1270.             return s_Compare(me.GetPacked_int(), you.GetBond(), scope);
  1271.         default:
  1272.             return eNoOverlap;
  1273.         }
  1274.     }
  1275.     case CSeq_loc::e_Whole: {
  1276.         switch ( you.Which() ) {
  1277.         case CSeq_loc::e_Whole:
  1278.             return s_Compare(me.GetWhole(), you.GetWhole(), scope);
  1279.         case CSeq_loc::e_Bond:
  1280.             return s_Compare(me.GetWhole(), you.GetBond(), scope);
  1281.         case CSeq_loc::e_Int:
  1282.             return s_Compare(me.GetWhole(), you.GetInt(), scope);
  1283.         case CSeq_loc::e_Pnt:
  1284.             return s_Compare(me.GetWhole(), you.GetPnt(), scope);
  1285.         case CSeq_loc::e_Packed_pnt:
  1286.             return s_Compare(me.GetWhole(), you.GetPacked_pnt(), scope);
  1287.         case CSeq_loc::e_Packed_int:
  1288.             return s_Compare(me.GetWhole(), you.GetPacked_int(), scope);
  1289.         default:
  1290.             return eNoOverlap;
  1291.         }
  1292.     }
  1293.     case CSeq_loc::e_Int: {
  1294.         switch ( you.Which() ) {
  1295.         case CSeq_loc::e_Whole:
  1296.             return s_Compare(me.GetInt(), you.GetWhole(), scope);
  1297.         case CSeq_loc::e_Bond:
  1298.             return s_Compare(me.GetInt(), you.GetBond(), scope);
  1299.         case CSeq_loc::e_Int:
  1300.             return s_Compare(me.GetInt(), you.GetInt(), scope);
  1301.         case CSeq_loc::e_Pnt:
  1302.             return s_Compare(me.GetInt(), you.GetPnt(), scope);
  1303.         case CSeq_loc::e_Packed_pnt:
  1304.             return s_Compare(me.GetInt(), you.GetPacked_pnt(), scope);
  1305.         case CSeq_loc::e_Packed_int:
  1306.             return s_Compare(me.GetInt(), you.GetPacked_int(), scope);
  1307.         default:
  1308.             return eNoOverlap;
  1309.         }
  1310.     }
  1311.     case CSeq_loc::e_Pnt: {
  1312.         switch ( you.Which() ) {
  1313.         case CSeq_loc::e_Whole:
  1314.             return s_Complement(s_Compare(you.GetWhole(), me.GetPnt(), scope));
  1315.         case CSeq_loc::e_Int:
  1316.             return s_Compare(me.GetPnt(), you.GetInt(), scope);
  1317.         case CSeq_loc::e_Pnt:
  1318.             return s_Compare(me.GetPnt(), you.GetPnt(), scope);
  1319.         case CSeq_loc::e_Packed_pnt:
  1320.             return s_Compare(me.GetPnt(), you.GetPacked_pnt(), scope);
  1321.         case CSeq_loc::e_Bond:
  1322.             return s_Compare(me.GetPnt(), you.GetBond(), scope);
  1323.         case CSeq_loc::e_Packed_int:
  1324.             return s_Compare(me.GetPnt(), you.GetPacked_int(), scope);
  1325.         default:
  1326.             return eNoOverlap;
  1327.         }
  1328.     }
  1329.     case CSeq_loc::e_Packed_pnt: {
  1330.         const CPacked_seqpnt& packed = me.GetPacked_pnt();
  1331.         switch ( you.Which() ) {
  1332.         case CSeq_loc::e_Whole:
  1333.             return s_Complement(s_Compare(you.GetWhole(), packed, scope));
  1334.         case CSeq_loc::e_Int:
  1335.             return s_Compare(packed, you.GetInt(), scope);
  1336.         case CSeq_loc::e_Pnt:
  1337.             return s_Complement(s_Compare(you.GetPnt(), packed, scope));
  1338.         case CSeq_loc::e_Packed_pnt:
  1339.             return s_Compare(packed, you.GetPacked_pnt(),scope);
  1340.         case CSeq_loc::e_Bond:
  1341.             return s_Compare(packed, you.GetBond(), scope);
  1342.         case CSeq_loc::e_Packed_int:
  1343.             return s_Compare(me.GetPacked_pnt(), you.GetPacked_int(), scope);
  1344.         default:
  1345.             return eNoOverlap;
  1346.         }
  1347.     }
  1348.     case CSeq_loc::e_Bond: {
  1349.         const CSeq_bond& bnd = me.GetBond();
  1350.         switch ( you.Which() ) {
  1351.         case CSeq_loc::e_Whole:
  1352.             return s_Complement(s_Compare(you.GetWhole(), bnd, scope));
  1353.         case CSeq_loc::e_Bond:
  1354.             return s_Compare(bnd, you.GetBond(), scope);
  1355.         case CSeq_loc::e_Int:
  1356.             return s_Compare(bnd, you.GetInt(), scope);
  1357.         case CSeq_loc::e_Packed_pnt:
  1358.             return s_Complement(s_Compare(you.GetPacked_pnt(), bnd, scope));
  1359.         case CSeq_loc::e_Pnt:
  1360.             return s_Complement(s_Compare(you.GetPnt(), bnd, scope));
  1361.         case CSeq_loc::e_Packed_int:
  1362.             return s_Complement(s_Compare(you.GetPacked_int(), bnd, scope));
  1363.         default:
  1364.             return eNoOverlap;
  1365.         }
  1366.     }
  1367.     default:
  1368.         return eNoOverlap;
  1369.     }
  1370. }
  1371. ECompare Compare
  1372. (const CSeq_loc& loc1,
  1373.  const CSeq_loc& loc2,
  1374.  CScope*         scope)
  1375. {
  1376.     return s_Compare(loc1, loc2, scope);
  1377. }
  1378. void ChangeSeqId(CSeq_id* id, bool best, CScope* scope)
  1379. {
  1380.     // Return if no scope
  1381.     if (!scope) {
  1382.         return;
  1383.     }
  1384.     // Get CBioseq represented by *id
  1385.     CBioseq_Handle::TBioseqCore seq =
  1386.         scope->GetBioseqHandle(*id).GetBioseqCore();
  1387.     // Get pointer to the best/worst id of *seq
  1388.     const CSeq_id* tmp_id;
  1389.     if (!best) {
  1390.         tmp_id = FindBestChoice(seq->GetId(), CSeq_id::BestRank).GetPointer();
  1391.     } else {
  1392.         tmp_id = FindBestChoice(seq->GetId(), CSeq_id::WorstRank).GetPointer();
  1393.     }
  1394.     // Change the contents of *id to that of *tmp_id
  1395.     id->Reset();
  1396.     id->Assign(*tmp_id);
  1397. }
  1398. void ChangeSeqLocId(CSeq_loc* loc, bool best, CScope* scope)
  1399. {
  1400.     if (!scope) {
  1401.         return;
  1402.     }
  1403.     for (CTypeIterator<CSeq_id> id(Begin(*loc)); id; ++id) {
  1404.         ChangeSeqId(&(*id), best, scope);
  1405.     }
  1406. }
  1407. bool BadSeqLocSortOrder
  1408. (const CBioseq&, //  seq,
  1409.  const CSeq_loc& loc,
  1410.  CScope*         scope)
  1411. {
  1412.     ENa_strand strand = GetStrand(loc, scope);
  1413.     if (strand == eNa_strand_unknown  ||  strand == eNa_strand_other) {
  1414.         return false;
  1415.     }
  1416.     
  1417.     // Check that loc segments are in order
  1418.     CSeq_loc::TRange last_range;
  1419.     bool first = true;
  1420.     for (CSeq_loc_CI lit(loc); lit; ++lit) {
  1421.         if (first) {
  1422.             last_range = lit.GetRange();
  1423.             first = false;
  1424.             continue;
  1425.         }
  1426.         if (strand == eNa_strand_minus) {
  1427.             if (last_range.GetTo() < lit.GetRange().GetTo()) {
  1428.                 return true;
  1429.             }
  1430.         } else {
  1431.             if (last_range.GetFrom() > lit.GetRange().GetFrom()) {
  1432.                 return true;
  1433.             }
  1434.         }
  1435.         last_range = lit.GetRange();
  1436.     }
  1437.     return false;
  1438. }
  1439. ESeqLocCheck SeqLocCheck(const CSeq_loc& loc, CScope* scope)
  1440. {
  1441.     ESeqLocCheck rtn = eSeqLocCheck_ok;
  1442.     ENa_strand strand = GetStrand(loc, scope);
  1443.     if (strand == eNa_strand_unknown  ||  strand == eNa_strand_other) {
  1444.         rtn = eSeqLocCheck_warning;
  1445.     }
  1446.     CTypeConstIterator<CSeq_loc> lit(ConstBegin(loc));
  1447.     for (;lit; ++lit) {
  1448.         switch (lit->Which()) {
  1449.         case CSeq_loc::e_Int:
  1450.             if (!IsValid(lit->GetInt(), scope)) {
  1451.                 rtn = eSeqLocCheck_error;
  1452.             }
  1453.             break;
  1454.         case CSeq_loc::e_Packed_int:
  1455.         {
  1456.             CTypeConstIterator<CSeq_interval> sit(ConstBegin(*lit));
  1457.             for(;sit; ++sit) {
  1458.                 if (!IsValid(*sit, scope)) {
  1459.                     rtn = eSeqLocCheck_error;
  1460.                     break;
  1461.                 }
  1462.             }
  1463.             break;
  1464.         }
  1465.         case CSeq_loc::e_Pnt:
  1466.             if (!IsValid(lit->GetPnt(), scope)) {
  1467.                 rtn = eSeqLocCheck_error;
  1468.             }
  1469.             break;
  1470.         case CSeq_loc::e_Packed_pnt:
  1471.             if (!IsValid(lit->GetPacked_pnt(), scope)) {
  1472.                 rtn = eSeqLocCheck_error;
  1473.             }
  1474.             break;
  1475.         default:
  1476.             break;
  1477.         }
  1478.     }
  1479.     return rtn;
  1480. }
  1481. CRef<CSeq_loc> SourceToProduct(const CSeq_feat& feat,
  1482.                                const CSeq_loc& source_loc, TS2PFlags flags,
  1483.                                CScope* scope, int* frame)
  1484. {
  1485.     SRelLoc::TFlags rl_flags = 0;
  1486.     if (flags & fS2P_NoMerge) {
  1487.         rl_flags |= SRelLoc::fNoMerge;
  1488.     }
  1489.     SRelLoc rl(feat.GetLocation(), source_loc, scope, rl_flags);
  1490.     _ASSERT(!rl.m_Ranges.empty());
  1491.     rl.m_ParentLoc.Reset(&feat.GetProduct());
  1492.     if (feat.GetData().IsCdregion()) {
  1493.         // 3:1 ratio
  1494.         const CCdregion& cds         = feat.GetData().GetCdregion();
  1495.         int              base_frame  = cds.GetFrame();
  1496.         if (base_frame > 0) {
  1497.             --base_frame;
  1498.         }
  1499.         if (frame) {
  1500.             *frame = 3 - (rl.m_Ranges.front()->GetFrom() + 2 - base_frame) % 3;
  1501.         }
  1502.         TSeqPos prot_length;
  1503.         try {
  1504.             prot_length = GetLength(feat.GetProduct(), scope);
  1505.         } catch (CNoLength) {
  1506.             prot_length = numeric_limits<TSeqPos>::max();
  1507.         }
  1508.         NON_CONST_ITERATE (SRelLoc::TRanges, it, rl.m_Ranges) {
  1509.             if (IsReverse((*it)->GetStrand())) {
  1510.                 ERR_POST(Warning
  1511.                          << "SourceToProduct:"
  1512.                          " parent and child have opposite orientations");
  1513.             }
  1514.             (*it)->SetFrom(((*it)->GetFrom() - base_frame) / 3);
  1515.             (*it)->SetTo  (((*it)->GetTo()   - base_frame) / 3);
  1516.             if ((flags & fS2P_AllowTer)  &&  (*it)->GetTo() == prot_length) {
  1517.                 --(*it)->SetTo();
  1518.             }
  1519.         }
  1520.     } else {
  1521.         if (frame) {
  1522.             *frame = 0; // not applicable; explicitly zero
  1523.         }
  1524.     }
  1525.     return rl.Resolve(scope, rl_flags);
  1526. }
  1527. CRef<CSeq_loc> ProductToSource(const CSeq_feat& feat, const CSeq_loc& prod_loc,
  1528.                                TP2SFlags flags, CScope* scope)
  1529. {
  1530.     SRelLoc rl(feat.GetProduct(), prod_loc, scope);
  1531.     _ASSERT(!rl.m_Ranges.empty());
  1532.     rl.m_ParentLoc.Reset(&feat.GetLocation());
  1533.     if (feat.GetData().IsCdregion()) {
  1534.         // 3:1 ratio
  1535.         const CCdregion& cds        = feat.GetData().GetCdregion();
  1536.         int              base_frame = cds.GetFrame();
  1537.         if (base_frame > 0) {
  1538.             --base_frame;
  1539.         }
  1540.         TSeqPos nuc_length, prot_length;
  1541.         try {
  1542.             nuc_length = GetLength(feat.GetLocation(), scope);
  1543.         } catch (CNoLength) {
  1544.             nuc_length = numeric_limits<TSeqPos>::max();
  1545.         }
  1546.         try {
  1547.             prot_length = GetLength(feat.GetProduct(), scope);
  1548.         } catch (CNoLength) {
  1549.             prot_length = numeric_limits<TSeqPos>::max();
  1550.         }
  1551.         NON_CONST_ITERATE(SRelLoc::TRanges, it, rl.m_Ranges) {
  1552.             _ASSERT( !IsReverse((*it)->GetStrand()) );
  1553.             TSeqPos from, to;
  1554.             if ((flags & fP2S_Extend)  &&  (*it)->GetFrom() == 0) {
  1555.                 from = 0;
  1556.             } else {
  1557.                 from = (*it)->GetFrom() * 3 + base_frame;
  1558.             }
  1559.             if ((flags & fP2S_Extend)  &&  (*it)->GetTo() == prot_length - 1) {
  1560.                 to = nuc_length - 1;
  1561.             } else {
  1562.                 to = (*it)->GetTo() * 3 + base_frame + 2;
  1563.             }
  1564.             (*it)->SetFrom(from);
  1565.             (*it)->SetTo  (to);
  1566.         }
  1567.     }
  1568.     return rl.Resolve(scope);
  1569. }
  1570. TSeqPos LocationOffset(const CSeq_loc& outer, const CSeq_loc& inner,
  1571.                        EOffsetType how, CScope* scope)
  1572. {
  1573.     SRelLoc rl(outer, inner, scope);
  1574.     if (rl.m_Ranges.empty()) {
  1575.         return (TSeqPos)-1;
  1576.     }
  1577.     bool want_reverse = false;
  1578.     {{
  1579.         bool outer_is_reverse = IsReverse(GetStrand(outer, scope));
  1580.         switch (how) {
  1581.         case eOffset_FromStart:
  1582.             want_reverse = false;
  1583.             break;
  1584.         case eOffset_FromEnd:
  1585.             want_reverse = true;
  1586.             break;
  1587.         case eOffset_FromLeft:
  1588.             want_reverse = outer_is_reverse;
  1589.             break;
  1590.         case eOffset_FromRight:
  1591.             want_reverse = !outer_is_reverse;
  1592.             break;
  1593.         }
  1594.     }}
  1595.     if (want_reverse) {
  1596.         return GetLength(outer, scope) - rl.m_Ranges.back()->GetTo();
  1597.     } else {
  1598.         return rl.m_Ranges.front()->GetFrom();
  1599.     }
  1600. }
  1601. bool TestForStrands(ENa_strand strand1, ENa_strand strand2)
  1602. {
  1603.     // Check strands. Overlapping rules for strand:
  1604.     //   - equal strands overlap
  1605.     //   - "both" overlaps with any other
  1606.     //   - "unknown" overlaps with any other except "minus"
  1607.     return strand1 == strand2
  1608.         || strand1 == eNa_strand_both
  1609.         || strand2 == eNa_strand_both
  1610.         || (strand1 == eNa_strand_unknown  && strand2 != eNa_strand_minus)
  1611.         || (strand2 == eNa_strand_unknown  && strand1 != eNa_strand_minus);
  1612. }
  1613. bool TestForIntervals(CSeq_loc_CI it1, CSeq_loc_CI it2, bool minus_strand)
  1614. {
  1615.     // Check intervals one by one
  1616.     while ( it1  &&  it2 ) {
  1617.         if ( !TestForStrands(it1.GetStrand(), it2.GetStrand())  ||
  1618.              !it1.GetSeq_id().Equals(it2.GetSeq_id())) {
  1619.             return false;
  1620.         }
  1621.         if ( minus_strand ) {
  1622.             if (it1.GetRange().GetFrom()  !=  it2.GetRange().GetFrom() ) {
  1623.                 // The last interval from loc2 may be shorter than the
  1624.                 // current interval from loc1
  1625.                 if (it1.GetRange().GetFrom() > it2.GetRange().GetFrom()  ||
  1626.                     ++it2) {
  1627.                     return false;
  1628.                 }
  1629.                 break;
  1630.             }
  1631.         }
  1632.         else {
  1633.             if (it1.GetRange().GetTo()  !=  it2.GetRange().GetTo() ) {
  1634.                 // The last interval from loc2 may be shorter than the
  1635.                 // current interval from loc1
  1636.                 if (it1.GetRange().GetTo() < it2.GetRange().GetTo()  ||
  1637.                     ++it2) {
  1638.                     return false;
  1639.                 }
  1640.                 break;
  1641.             }
  1642.         }
  1643.         // Go to the next interval start
  1644.         if ( !(++it2) ) {
  1645.             break;
  1646.         }
  1647.         if ( !(++it1) ) {
  1648.             return false; // loc1 has not enough intervals
  1649.         }
  1650.         if ( minus_strand ) {
  1651.             if (it1.GetRange().GetTo() != it2.GetRange().GetTo()) {
  1652.                 return false;
  1653.             }
  1654.         }
  1655.         else {
  1656.             if (it1.GetRange().GetFrom() != it2.GetRange().GetFrom()) {
  1657.                 return false;
  1658.             }
  1659.         }
  1660.     }
  1661.     return true;
  1662. }
  1663. int x_TestForOverlap_MultiSeq(const CSeq_loc& loc1,
  1664.                               const CSeq_loc& loc2,
  1665.                               EOverlapType type)
  1666. {
  1667.     // Special case of TestForOverlap() - multi-sequences locations
  1668.     switch (type) {
  1669.     case eOverlap_Simple:
  1670.         {
  1671.             // Find all intersecting intervals
  1672.             int diff = 0;
  1673.             for (CSeq_loc_CI li1(loc1); li1; ++li1) {
  1674.                 for (CSeq_loc_CI li2(loc2); li2; ++li2) {
  1675.                     if ( !li1.GetSeq_id().Equals(li2.GetSeq_id()) ) {
  1676.                         continue;
  1677.                     }
  1678.                     CRange<TSeqPos> rg1 = li1.GetRange();
  1679.                     CRange<TSeqPos> rg2 = li2.GetRange();
  1680.                     if ( rg1.GetTo() >= rg2.GetFrom()  &&
  1681.                          rg1.GetFrom() <= rg2.GetTo() ) {
  1682.                         diff += abs(int(rg2.GetFrom() - rg1.GetFrom())) +
  1683.                             abs(int(rg1.GetTo() - rg2.GetTo()));
  1684.                     }
  1685.                 }
  1686.             }
  1687.             return diff ? diff : -1;
  1688.         }
  1689.     case eOverlap_Contained:
  1690.         {
  1691.             // loc2 is contained in loc1
  1692.             CHandleRangeMap rm1, rm2;
  1693.             rm1.AddLocation(loc1);
  1694.             rm2.AddLocation(loc2);
  1695.             int diff = 0;
  1696.             CHandleRangeMap::const_iterator it2 = rm2.begin();
  1697.             for ( ; it2 != rm2.end(); ++it2) {
  1698.                 CHandleRangeMap::const_iterator it1 =
  1699.                     rm1.GetMap().find(it2->first);
  1700.                 if (it1 == rm1.end()) {
  1701.                     // loc2 has region on a sequence not present in loc1
  1702.                     diff = -1;
  1703.                     break;
  1704.                 }
  1705.                 CRange<TSeqPos> rg1 = it1->second.GetOverlappingRange();
  1706.                 CRange<TSeqPos> rg2 = it2->second.GetOverlappingRange();
  1707.                 if ( rg1.GetFrom() <= rg2.GetFrom()  &&
  1708.                     rg1.GetTo() >= rg2.GetTo() ) {
  1709.                     diff += (rg2.GetFrom() - rg1.GetFrom()) +
  1710.                         (rg1.GetTo() - rg2.GetTo());
  1711.                 }
  1712.                 else {
  1713.                     // Found an interval on loc2 not contained in loc1
  1714.                     diff = -1;
  1715.                     break;
  1716.                 }
  1717.             }
  1718.             return diff;
  1719.         }
  1720.     case eOverlap_Contains:
  1721.         {
  1722.             // loc2 is contained in loc1
  1723.             CHandleRangeMap rm1, rm2;
  1724.             rm1.AddLocation(loc1);
  1725.             rm2.AddLocation(loc2);
  1726.             int diff = 0;
  1727.             CHandleRangeMap::const_iterator it1 = rm1.begin();
  1728.             for ( ; it1 != rm1.end(); ++it1) {
  1729.                 CHandleRangeMap::const_iterator it2 =
  1730.                     rm2.GetMap().find(it1->first);
  1731.                 if (it2 == rm2.end()) {
  1732.                     // loc1 has region on a sequence not present in loc2
  1733.                     diff = -1;
  1734.                     break;
  1735.                 }
  1736.                 CRange<TSeqPos> rg1 = it1->second.GetOverlappingRange();
  1737.                 CRange<TSeqPos> rg2 = it2->second.GetOverlappingRange();
  1738.                 if ( rg2.GetFrom() <= rg1.GetFrom()  &&
  1739.                     rg2.GetTo() >= rg1.GetTo() ) {
  1740.                     diff += (rg1.GetFrom() - rg2.GetFrom()) +
  1741.                         (rg2.GetTo() - rg1.GetTo());
  1742.                 }
  1743.                 else {
  1744.                     // Found an interval on loc1 not contained in loc2
  1745.                     diff = -1;
  1746.                     break;
  1747.                 }
  1748.             }
  1749.             return diff;
  1750.         }
  1751.     case eOverlap_Subset:
  1752.     case eOverlap_CheckIntervals:
  1753.     case eOverlap_Interval:
  1754.         {
  1755.             // For this types the function should not be called
  1756.             NCBI_THROW(CObjmgrUtilException, eNotImplemented,
  1757.                 "TestForOverlap() -- error processing multi-ID seq-loc");
  1758.         }
  1759.     }
  1760.     return -1;
  1761. }
  1762. int TestForOverlap(const CSeq_loc& loc1,
  1763.                    const CSeq_loc& loc2,
  1764.                    EOverlapType type,
  1765.                    TSeqPos circular_len)
  1766. {
  1767.     CRange<TSeqPos> rg1, rg2;
  1768.     bool multi_seq = false;
  1769.     try {
  1770.         rg1 = loc1.GetTotalRange();
  1771.         rg2 = loc2.GetTotalRange();
  1772.     }
  1773.     catch (exception&) {
  1774.         // Can not use total range for multi-sequence locations
  1775.         if (type == eOverlap_Simple  ||
  1776.             type == eOverlap_Contained  ||
  1777.             type == eOverlap_Contains) {
  1778.             // Can not process circular multi-id locations
  1779.             if (circular_len != 0  &&  circular_len != kInvalidSeqPos) {
  1780.                 throw;
  1781.             }
  1782.             return x_TestForOverlap_MultiSeq(loc1, loc2, type);
  1783.         }
  1784.         multi_seq = true;
  1785.     }
  1786.     ENa_strand strand1 = GetStrand(loc1);
  1787.     ENa_strand strand2 = GetStrand(loc2);
  1788.     if ( !TestForStrands(strand1, strand2) )
  1789.         return -1;
  1790.     switch (type) {
  1791.     case eOverlap_Simple:
  1792.         {
  1793.             if (circular_len != kInvalidSeqPos) {
  1794.                 TSeqPos from1 = loc1.GetStart(circular_len);
  1795.                 TSeqPos from2 = loc2.GetStart(circular_len);
  1796.                 TSeqPos to1 = loc1.GetEnd(circular_len);
  1797.                 TSeqPos to2 = loc2.GetEnd(circular_len);
  1798.                 if (from1 > to1) {
  1799.                     if (from2 > to2) {
  1800.                         // Both locations are circular and must intersect at 0
  1801.                         return abs(int(from2 - from1)) +
  1802.                             abs(int(to1 - to2));
  1803.                     }
  1804.                     else {
  1805.                         // Only the first location is circular, rg2 may be used
  1806.                         // for the second one.
  1807.                         int loc_len = rg2.GetLength() + loc1.GetCircularLength(circular_len);
  1808.                         if (from1 < rg2.GetFrom()  ||  to1 > rg2.GetTo()) {
  1809.                             // loc2 is completely in loc1
  1810.                             return loc_len - 2*rg2.GetLength();
  1811.                         }
  1812.                         if (from1 < rg2.GetTo()) {
  1813.                             return loc_len - (rg2.GetTo() - from1);
  1814.                         }
  1815.                         if (rg2.GetFrom() < to1) {
  1816.                             return loc_len - (to1 - rg2.GetFrom());
  1817.                         }
  1818.                         return -1;
  1819.                     }
  1820.                 }
  1821.                 else if (from2 > to2) {
  1822.                     // Only the second location is circular
  1823.                     int loc_len = rg1.GetLength() + loc2.GetCircularLength(circular_len);
  1824.                     if (from2 < rg1.GetFrom()  ||  to2 > rg1.GetTo()) {
  1825.                         // loc2 is completely in loc1
  1826.                         return loc_len - 2*rg1.GetLength();
  1827.                     }
  1828.                     if (from2 < rg1.GetTo()) {
  1829.                         return loc_len - (rg1.GetTo() - from2);
  1830.                     }
  1831.                     if (rg1.GetFrom() < to2) {
  1832.                         return loc_len - (to2 - rg1.GetFrom());
  1833.                     }
  1834.                     return -1;
  1835.                 }
  1836.                 // Locations are not circular, proceed to normal calculations
  1837.             }
  1838.             if ( rg1.GetTo() >= rg2.GetFrom()  &&
  1839.                 rg1.GetFrom() <= rg2.GetTo() ) {
  1840.                 return abs(int(rg2.GetFrom() - rg1.GetFrom())) +
  1841.                     abs(int(rg1.GetTo() - rg2.GetTo()));
  1842.             }
  1843.             return -1;
  1844.         }
  1845.     case eOverlap_Contained:
  1846.         {
  1847.             if (circular_len != kInvalidSeqPos) {
  1848.                 TSeqPos from1 = loc1.GetStart(circular_len);
  1849.                 TSeqPos from2 = loc2.GetStart(circular_len);
  1850.                 TSeqPos to1 = loc1.GetEnd(circular_len);
  1851.                 TSeqPos to2 = loc2.GetEnd(circular_len);
  1852.                 if (from1 > to1) {
  1853.                     if (from2 > to2) {
  1854.                         return (from1 <= from2  &&  to1 >= to2) ?
  1855.                             (from2 - from1) - (to1 - to2) : -1;
  1856.                     }
  1857.                     else {
  1858.                         if (rg2.GetFrom() >= from1  ||  rg2.GetTo() <= to1) {
  1859.                             return loc1.GetCircularLength(circular_len) -
  1860.                                 rg2.GetLength();
  1861.                         }
  1862.                         return -1;
  1863.                     }
  1864.                 }
  1865.                 else if (from2 > to2) {
  1866.                     // Non-circular location can not contain a circular one
  1867.                     return -1;
  1868.                 }
  1869.             }
  1870.             if ( rg1.GetFrom() <= rg2.GetFrom()  &&
  1871.                 rg1.GetTo() >= rg2.GetTo() ) {
  1872.                 return (rg2.GetFrom() - rg1.GetFrom()) +
  1873.                     (rg1.GetTo() - rg2.GetTo());
  1874.             }
  1875.             return -1;
  1876.         }
  1877.     case eOverlap_Contains:
  1878.         {
  1879.             if (circular_len != kInvalidSeqPos) {
  1880.                 TSeqPos from1 = loc1.GetStart(circular_len);
  1881.                 TSeqPos from2 = loc2.GetStart(circular_len);
  1882.                 TSeqPos to1 = loc1.GetEnd(circular_len);
  1883.                 TSeqPos to2 = loc2.GetEnd(circular_len);
  1884.                 if (from1 > to1) {
  1885.                     if (from2 > to2) {
  1886.                         return (from2 <= from1  &&  to2 >= to1) ?
  1887.                             (from1 - from2) - (to2 - to1) : -1;
  1888.                     }
  1889.                     else {
  1890.                         // Non-circular location can not contain a circular one
  1891.                         return -1;
  1892.                     }
  1893.                 }
  1894.                 else if (from2 > to2) {
  1895.                     if (rg1.GetFrom() >= from2  ||  rg1.GetTo() <= to2) {
  1896.                         return loc2.GetCircularLength(circular_len) -
  1897.                             rg1.GetLength();
  1898.                     }
  1899.                     return -1;
  1900.                 }
  1901.             }
  1902.             if ( rg2.GetFrom() <= rg1.GetFrom()  &&
  1903.                 rg2.GetTo() >= rg1.GetTo() ) {
  1904.                 return (rg1.GetFrom() - rg2.GetFrom()) +
  1905.                     (rg2.GetTo() - rg1.GetTo());
  1906.             }
  1907.             return -1;
  1908.         }
  1909.     case eOverlap_Subset:
  1910.         {
  1911.             // loc1 should contain loc2
  1912.             if ( Compare(loc1, loc2) != eContains ) {
  1913.                 return -1;
  1914.             }
  1915.             return GetLength(loc1) - GetLength(loc2);
  1916.         }
  1917.     case eOverlap_CheckIntervals:
  1918.         {
  1919.             if ( !multi_seq  &&
  1920.                 (rg1.GetFrom() > rg2.GetTo()  || rg1.GetTo() < rg2.GetTo()) ) {
  1921.                 return -1;
  1922.             }
  1923.             // Check intervals' boundaries
  1924.             CSeq_loc_CI it1(loc1);
  1925.             CSeq_loc_CI it2(loc2);
  1926.             if (!it1  ||  !it2) {
  1927.                 break;
  1928.             }
  1929.             // check case when strand is minus
  1930.             if (it2.GetStrand() == eNa_strand_minus) {
  1931.                 // The first interval should be treated as the last one
  1932.                 // for minuns strands.
  1933.                 TSeqPos loc2end = it2.GetRange().GetTo();
  1934.                 TSeqPos loc2start = it2.GetRange().GetFrom();
  1935.                 // Find the first interval in loc1 intersecting with loc2
  1936.                 for ( ; it1  &&  it1.GetRange().GetTo() >= loc2start; ++it1) {
  1937.                     if (it1.GetRange().GetTo() >= loc2end  &&
  1938.                         TestForIntervals(it1, it2, true)) {
  1939.                         return GetLength(loc1) - GetLength(loc2);
  1940.                     }
  1941.                 }
  1942.             }
  1943.             else {
  1944.                 TSeqPos loc2start = it2.GetRange().GetFrom();
  1945.                 TSeqPos loc2end = it2.GetRange().GetTo();
  1946.                 // Find the first interval in loc1 intersecting with loc2
  1947.                 for ( ; it1  /*&&  it1.GetRange().GetFrom() <= loc2end*/; ++it1) {
  1948.                     if (it1.GetSeq_id().Equals(it2.GetSeq_id())  &&
  1949.                         it1.GetRange().GetFrom() <= loc2start  &&
  1950.                         TestForIntervals(it1, it2, false)) {
  1951.                         return GetLength(loc1) - GetLength(loc2);
  1952.                     }
  1953.                 }
  1954.             }
  1955.             return -1;
  1956.         }
  1957.     case eOverlap_Interval:
  1958.         {
  1959.             return (Compare(loc1, loc2) == eNoOverlap) ? -1
  1960.                 : abs(int(rg2.GetFrom() - rg1.GetFrom())) +
  1961.                 abs(int(rg1.GetTo() - rg2.GetTo()));
  1962.         }
  1963.     }
  1964.     return -1;
  1965. }
  1966. CConstRef<CSeq_feat> x_GetBestOverlappingFeat(const CSeq_loc& loc,
  1967.                                               CSeqFeatData::E_Choice feat_type,
  1968.                                               CSeqFeatData::ESubtype feat_subtype,
  1969.                                               EOverlapType overlap_type,
  1970.                                               CScope& scope)
  1971. {
  1972.     bool revert_locations = false;
  1973.     SAnnotSelector::EOverlapType annot_overlap_type;
  1974.     switch (overlap_type) {
  1975.     case eOverlap_Simple:
  1976.     case eOverlap_Contained:
  1977.     case eOverlap_Contains:
  1978.         // Require total range overlap
  1979.         annot_overlap_type = SAnnotSelector::eOverlap_TotalRange;
  1980.         break;
  1981.     case eOverlap_Subset: