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

生物技术

开发平台:

C/C++

  1.     case eOverlap_CheckIntervals:
  2.     case eOverlap_Interval:
  3.         revert_locations = true;
  4.         // there's no break here - proceed to "default"
  5.     default:
  6.         // Require intervals overlap
  7.         annot_overlap_type = SAnnotSelector::eOverlap_Intervals;
  8.         break;
  9.     }
  10.     CConstRef<CSeq_feat> feat_ref;
  11.     int diff = -1;
  12.     CFeat_CI feat_it(scope, loc, SAnnotSelector()
  13.         .SetFeatType(feat_type)
  14.         .SetFeatSubtype(feat_subtype)
  15.         .SetOverlapType(annot_overlap_type)
  16.         .SetResolveTSE());
  17.     for ( ; feat_it; ++feat_it) {
  18.         // treat subset as a special case
  19.         int cur_diff = ( !revert_locations ) ?
  20.             TestForOverlap(loc, feat_it->GetLocation(), overlap_type) :
  21.             TestForOverlap(feat_it->GetLocation(), loc, overlap_type);
  22.         if (cur_diff < 0)
  23.             continue;
  24.         if ( cur_diff < diff  ||  diff < 0 ) {
  25.             diff = cur_diff;
  26.             feat_ref = &feat_it->GetMappedFeature();
  27.         }
  28.     }
  29.     return feat_ref;
  30. }
  31. CConstRef<CSeq_feat> GetBestOverlappingFeat(const CSeq_loc& loc,
  32.                                             CSeqFeatData::E_Choice feat_type,
  33.                                             EOverlapType overlap_type,
  34.                                             CScope& scope)
  35. {
  36.     return x_GetBestOverlappingFeat(loc,
  37.         feat_type, CSeqFeatData::eSubtype_any,
  38.         overlap_type, scope);
  39. }
  40. CConstRef<CSeq_feat> GetBestOverlappingFeat(const CSeq_loc& loc,
  41.                                             CSeqFeatData::ESubtype feat_type,
  42.                                             EOverlapType overlap_type,
  43.                                             CScope& scope)
  44. {
  45.     return x_GetBestOverlappingFeat(loc,
  46.         CSeqFeatData::GetTypeFromSubtype(feat_type), feat_type,
  47.         overlap_type, scope);
  48. }
  49. CConstRef<CSeq_feat> GetOverlappingGene(const CSeq_loc& loc, CScope& scope)
  50. {
  51.     return GetBestOverlappingFeat(loc, CSeqFeatData::eSubtype_gene,
  52.         eOverlap_Contains, scope);
  53. }
  54. CConstRef<CSeq_feat> GetOverlappingmRNA(const CSeq_loc& loc, CScope& scope)
  55. {
  56.     return GetBestOverlappingFeat(loc, CSeqFeatData::eSubtype_mRNA,
  57.         eOverlap_Contains, scope);
  58. }
  59. CConstRef<CSeq_feat> GetOverlappingCDS(const CSeq_loc& loc, CScope& scope)
  60. {
  61.     return GetBestOverlappingFeat(loc, CSeqFeatData::eSubtype_cdregion,
  62.         eOverlap_Contains, scope);
  63. }
  64. CConstRef<CSeq_feat> GetOverlappingPub(const CSeq_loc& loc, CScope& scope)
  65. {
  66.     return GetBestOverlappingFeat(loc, CSeqFeatData::eSubtype_pub,
  67.         eOverlap_Contains, scope);
  68. }
  69. CConstRef<CSeq_feat> GetOverlappingSource(const CSeq_loc& loc, CScope& scope)
  70. {
  71.     return GetBestOverlappingFeat(loc, CSeqFeatData::eSubtype_biosrc,
  72.         eOverlap_Contains, scope);
  73. }
  74. CConstRef<CSeq_feat> GetOverlappingOperon(const CSeq_loc& loc, CScope& scope)
  75. {
  76.     return GetBestOverlappingFeat(loc, CSeqFeatData::eSubtype_operon,
  77.         eOverlap_Contains, scope);
  78. }
  79. int SeqLocPartialCheck(const CSeq_loc& loc, CScope* scope)
  80. {
  81.     unsigned int retval = 0;
  82.     if (!scope) {
  83.         return retval;
  84.     }
  85.     // Find first and last Seq-loc
  86.     const CSeq_loc *first = 0, *last = 0;
  87.     for ( CSeq_loc_CI loc_iter(loc); loc_iter; ++loc_iter ) {
  88.         if ( first == 0 ) {
  89.             first = &(loc_iter.GetSeq_loc());
  90.         }
  91.         last = &(loc_iter.GetSeq_loc());
  92.     }
  93.     if (!first) {
  94.         return retval;
  95.     }
  96.     CSeq_loc_CI i2(loc, CSeq_loc_CI::eEmpty_Allow);
  97.     for ( ; i2; ++i2 ) {
  98.         const CSeq_loc* slp = &(i2.GetSeq_loc());
  99.         switch (slp->Which()) {
  100.         case CSeq_loc::e_Null:
  101.             if (slp == first) {
  102.                 retval |= eSeqlocPartial_Start;
  103.             } else if (slp == last) {
  104.                 retval |= eSeqlocPartial_Stop;
  105.             } else {
  106.                 retval |= eSeqlocPartial_Internal;
  107.             }
  108.             break;
  109.         case CSeq_loc::e_Int:
  110.             {
  111.                 const CSeq_interval& itv = slp->GetInt();
  112.                 if (itv.IsSetFuzz_from()) {
  113.                     const CInt_fuzz& fuzz = itv.GetFuzz_from();
  114.                     if (fuzz.Which() == CInt_fuzz::e_Lim) {
  115.                         CInt_fuzz::ELim lim = fuzz.GetLim();
  116.                         if (lim == CInt_fuzz::eLim_gt) {
  117.                             retval |= eSeqlocPartial_Limwrong;
  118.                         } else if (lim == CInt_fuzz::eLim_lt  ||
  119.                             lim == CInt_fuzz::eLim_unk) {
  120.                             if (itv.IsSetStrand()  &&
  121.                                 itv.GetStrand() == eNa_strand_minus) {
  122.                                 if (slp == last) {
  123.                                     retval |= eSeqlocPartial_Stop;
  124.                                 } else {
  125.                                     retval |= eSeqlocPartial_Internal;
  126.                                 }
  127.                                 if (itv.GetFrom() != 0) {
  128.                                     if (slp == last) {
  129.                                         retval |= eSeqlocPartial_Nostop;
  130.                                     } else {
  131.                                         retval |= eSeqlocPartial_Nointernal;
  132.                                     }
  133.                                 }
  134.                             } else {
  135.                                 if (slp == first) {
  136.                                     retval |= eSeqlocPartial_Start;
  137.                                 } else {
  138.                                     retval |= eSeqlocPartial_Internal;
  139.                                 }
  140.                                 if (itv.GetFrom() != 0) {
  141.                                     if (slp == first) {
  142.                                         retval |= eSeqlocPartial_Nostart;
  143.                                     } else {
  144.                                         retval |= eSeqlocPartial_Nointernal;
  145.                                     }
  146.                                 }
  147.                             }
  148.                         }
  149.                     }
  150.                 }
  151.                 
  152.                 if (itv.IsSetFuzz_to()) {
  153.                     const CInt_fuzz& fuzz = itv.GetFuzz_to();
  154.                     CInt_fuzz::ELim lim = fuzz.IsLim() ? 
  155.                         fuzz.GetLim() : CInt_fuzz::eLim_unk;
  156.                     if (lim == CInt_fuzz::eLim_lt) {
  157.                         retval |= eSeqlocPartial_Limwrong;
  158.                     } else if (lim == CInt_fuzz::eLim_gt  ||
  159.                         lim == CInt_fuzz::eLim_unk) {
  160.                         CBioseq_Handle hnd =
  161.                             scope->GetBioseqHandle(itv.GetId());
  162.                         bool miss_end = false;
  163.                         if ( hnd ) {
  164.                             CBioseq_Handle::TBioseqCore bc = hnd.GetBioseqCore();
  165.                             
  166.                             if (itv.GetTo() != bc->GetInst().GetLength() - 1) {
  167.                                 miss_end = true;
  168.                             }
  169.                         }
  170.                         if (itv.IsSetStrand()  &&
  171.                             itv.GetStrand() == eNa_strand_minus) {
  172.                             if (slp == first) {
  173.                                 retval |= eSeqlocPartial_Start;
  174.                             } else {
  175.                                 retval |= eSeqlocPartial_Internal;
  176.                             }
  177.                             if (miss_end) {
  178.                                 if (slp == first /* was last */) {
  179.                                     retval |= eSeqlocPartial_Nostart;
  180.                                 } else {
  181.                                     retval |= eSeqlocPartial_Nointernal;
  182.                                 }
  183.                             }
  184.                         } else {
  185.                             if (slp == last) {
  186.                                 retval |= eSeqlocPartial_Stop;
  187.                             } else {
  188.                                 retval |= eSeqlocPartial_Internal;
  189.                             }
  190.                             if (miss_end) {
  191.                                 if (slp == last) {
  192.                                     retval |= eSeqlocPartial_Nostop;
  193.                                 } else {
  194.                                     retval |= eSeqlocPartial_Nointernal;
  195.                                 }
  196.                             }
  197.                         }
  198.                     }
  199.                 }
  200.             }
  201.             break;
  202.         case CSeq_loc::e_Pnt:
  203.             if (slp->GetPnt().IsSetFuzz()) {
  204.                 const CInt_fuzz& fuzz = slp->GetPnt().GetFuzz();
  205.                 if (fuzz.Which() == CInt_fuzz::e_Lim) {
  206.                     CInt_fuzz::ELim lim = fuzz.GetLim();
  207.                     if (lim == CInt_fuzz::eLim_gt  ||
  208.                         lim == CInt_fuzz::eLim_lt  ||
  209.                         lim == CInt_fuzz::eLim_unk) {
  210.                         if (slp == first) {
  211.                             retval |= eSeqlocPartial_Start;
  212.                         } else if (slp == last) {
  213.                             retval |= eSeqlocPartial_Stop;
  214.                         } else {
  215.                             retval |= eSeqlocPartial_Internal;
  216.                         }
  217.                     }
  218.                 }
  219.             }
  220.             break;
  221.         case CSeq_loc::e_Packed_pnt:
  222.             if (slp->GetPacked_pnt().IsSetFuzz()) {
  223.                 const CInt_fuzz& fuzz = slp->GetPacked_pnt().GetFuzz();
  224.                 if (fuzz.Which() == CInt_fuzz::e_Lim) {
  225.                     CInt_fuzz::ELim lim = fuzz.GetLim();
  226.                     if (lim == CInt_fuzz::eLim_gt  ||
  227.                         lim == CInt_fuzz::eLim_lt  ||
  228.                         lim == CInt_fuzz::eLim_unk) {
  229.                         if (slp == first) {
  230.                             retval |= eSeqlocPartial_Start;
  231.                         } else if (slp == last) {
  232.                             retval |= eSeqlocPartial_Stop;
  233.                         } else {
  234.                             retval |= eSeqlocPartial_Internal;
  235.                         }
  236.                     }
  237.                 }
  238.             }
  239.             break;
  240.         case CSeq_loc::e_Whole:
  241.         {
  242.             // Get the Bioseq referred to by Whole
  243.             CBioseq_Handle bsh = scope->GetBioseqHandle(slp->GetWhole());
  244.             if ( !bsh ) {
  245.                 break;
  246.             }
  247.             // Check for CMolInfo on the biodseq
  248.             CSeqdesc_CI di( bsh, CSeqdesc::e_Molinfo );
  249.             if ( !di ) {
  250.                 // If no CSeq_descr, nothing can be done
  251.                 break;
  252.             }
  253.             // First try to loop through CMolInfo
  254.             const CMolInfo& mi = di->GetMolinfo();
  255.             if (!mi.IsSetCompleteness()) {
  256.                 continue;
  257.             }
  258.             switch (mi.GetCompleteness()) {
  259.             case CMolInfo::eCompleteness_no_left:
  260.                 if (slp == first) {
  261.                     retval |= eSeqlocPartial_Start;
  262.                 } else {
  263.                     retval |= eSeqlocPartial_Internal;
  264.                 }
  265.                 break;
  266.             case CMolInfo::eCompleteness_no_right:
  267.                 if (slp == last) {
  268.                     retval |= eSeqlocPartial_Stop;
  269.                 } else {
  270.                     retval |= eSeqlocPartial_Internal;
  271.                 }
  272.                 break;
  273.             case CMolInfo::eCompleteness_partial:
  274.                 retval |= eSeqlocPartial_Other;
  275.                 break;
  276.             case CMolInfo::eCompleteness_no_ends:
  277.                 retval |= eSeqlocPartial_Start;
  278.                 retval |= eSeqlocPartial_Stop;
  279.                 break;
  280.             default:
  281.                 break;
  282.             }
  283.             break;
  284.         }
  285.         default:
  286.             break;
  287.         }
  288.     }
  289.     return retval;
  290. }
  291. typedef CSeq_loc::TRange    TRange;
  292. typedef vector<TRange>      TRangeVec;
  293. CSeq_loc* SeqLocMerge
  294. (const CBioseq_Handle& target,
  295.  const CSeq_loc& loc1,
  296.  const CSeq_loc& loc2,
  297.  TSeqLocFlags flags)
  298. {
  299.     _ASSERT(target);
  300.     vector< CConstRef<CSeq_loc> > locs;
  301.     locs.push_back(CConstRef<CSeq_loc>(&loc1));
  302.     locs.push_back(CConstRef<CSeq_loc>(&loc2));
  303.     return SeqLocMerge(target, locs, flags);
  304. }
  305. static void s_CollectRanges(const CSeq_loc& loc, TRangeVec& ranges)
  306. {
  307.     // skipping empty / nulls
  308.     for ( CSeq_loc_CI li(loc); li; ++li ) {
  309.         ranges.push_back(li.GetRange());
  310.     }
  311. }
  312. static void s_MergeRanges(TRangeVec& ranges, TSeqLocFlags flags)
  313. {
  314.     bool merge = (flags & fMergeIntervals) != 0;
  315.     bool fuse  = (flags & fFuseAbutting) != 0;
  316.     if ( !merge  &&  !fuse ) {
  317.         return;
  318.     }
  319.     TRangeVec::iterator next = ranges.begin();
  320.     TRangeVec::iterator curr = next++;
  321.     bool advance = true;
  322.     while ( next != ranges.end() ) {
  323.         advance = true;
  324.         if ( (merge  &&  curr->GetTo() >= next->GetFrom())  ||
  325.              (fuse   &&  curr->GetTo() + 1 == next->GetFrom()) ) {
  326.             *curr += *next;
  327.             next = ranges.erase(next);
  328.             advance = false;
  329.         }
  330.         if ( advance ) {
  331.             curr = next++;
  332.         }
  333.     }
  334. }
  335. static CSeq_loc* s_CreateSeqLoc
  336. (CSeq_id& id,
  337.  const TRangeVec& ranges,
  338.  ENa_strand strand,
  339.  bool rearranged,
  340.  bool add_null)
  341. {
  342.     static const  CSeq_loc null_loc(CSeq_loc::e_Null);
  343.     bool has_pnt = false;
  344.     bool has_int = false;
  345.     if ( ranges.size() < 2 ) {
  346.         add_null = false;
  347.     }
  348.     if ( !add_null ) {
  349.         ITERATE(TRangeVec, it, ranges) {
  350.             if ( it->GetLength() == 1 ) {
  351.                 has_pnt = true;
  352.             } else {
  353.                 has_int = true;
  354.             }
  355.         }
  356.     }
  357.     
  358.     CSeq_loc::E_Choice loc_type = CSeq_loc::e_not_set;
  359.     if ( add_null ) {
  360.         loc_type = CSeq_loc::e_Mix;
  361.     } else if ( has_pnt  &&  has_int ) {  // points and intervals  => mix location
  362.         loc_type = CSeq_loc::e_Mix;
  363.     } else if ( has_pnt ) {  // only points
  364.         loc_type = ranges.size() == 1 ? CSeq_loc::e_Pnt : CSeq_loc::e_Packed_pnt;
  365.     } else if ( has_int ) {  // only intervals
  366.         loc_type = ranges.size() == 1 ? CSeq_loc::e_Int : CSeq_loc::e_Packed_int;
  367.     } else {
  368.         loc_type = CSeq_loc::e_Null;
  369.     }
  370.     CRef<CSeq_loc> result;
  371.     switch ( loc_type ) {
  372.     case CSeq_loc::e_Pnt:
  373.         {
  374.             result.Reset(new CSeq_loc(id, ranges.front().GetFrom(), strand));
  375.             break;
  376.         }
  377.     case CSeq_loc::e_Packed_pnt:
  378.         {
  379.             CPacked_seqpnt::TPoints points(ranges.size());;
  380.             ITERATE(TRangeVec, it, ranges) {
  381.                 points.push_back(it->GetFrom());
  382.             }
  383.             result.Reset(new CSeq_loc(id, points, strand));
  384.             
  385.             break;
  386.         }
  387.     case CSeq_loc::e_Int:
  388.         {
  389.             const TRange& r = ranges.front();
  390.             result.Reset(new CSeq_loc(id, r.GetFrom(), r.GetTo(), strand));
  391.             break;
  392.         }
  393.     case CSeq_loc::e_Packed_int:
  394.         {
  395.             result.Reset(new CSeq_loc(id, ranges, strand));
  396.             if ( rearranged ) {
  397.                 // the first 2 intervals span the origin
  398.                 CPacked_seqint::Tdata ivals = result->SetPacked_int().Set();
  399.                 CPacked_seqint::Tdata::iterator it = ivals.begin();
  400.                 if ( strand == eNa_strand_minus ) {
  401.                     (*it)->SetFuzz_from().SetLim(CInt_fuzz::eLim_circle);
  402.                     ++it;
  403.                     (*it)->SetFuzz_to().SetLim(CInt_fuzz::eLim_circle);
  404.                 } else {
  405.                     (*it)->SetFuzz_to().SetLim(CInt_fuzz::eLim_circle);
  406.                     ++it;
  407.                     (*it)->SetFuzz_from().SetLim(CInt_fuzz::eLim_circle);
  408.                 }
  409.             }
  410.             break;
  411.         }
  412.     case CSeq_loc::e_Mix:
  413.         {
  414.             result.Reset(new CSeq_loc);
  415.             CSeq_loc_mix& mix = result->SetMix();
  416.             TRangeVec::const_iterator last = ranges.end(); --last;
  417.             ITERATE(TRangeVec, it, ranges) {
  418.                 if ( it->GetLength() == 1 ) {
  419.                     mix.AddSeqLoc(*new CSeq_loc(id, it->GetFrom(), strand));
  420.                 } else {
  421.                     mix.AddSeqLoc(*new CSeq_loc(id, it->GetFrom(), it->GetTo(), strand));
  422.                 }
  423.                 if ( add_null  &&  it != last ) {
  424.                     mix.AddSeqLoc(null_loc);
  425.                 }
  426.             }
  427.             break;
  428.         }
  429.     case CSeq_loc::e_Null:
  430.         {
  431.             result.Reset(new CSeq_loc);
  432.             result->SetNull();
  433.             break;
  434.         }
  435.     default:
  436.         {
  437.             result.Reset();
  438.         }
  439.     };
  440.     return result.Release();
  441. }
  442. static void s_RearrangeRanges(TRangeVec& ranges)
  443. {
  444.     deque<TRange> temp(ranges.size());
  445.     copy(ranges.begin(), ranges.end(), temp.begin());
  446.     ranges.clear();
  447.     temp.push_front(temp.back());  
  448.     temp.pop_back();
  449.     copy(temp.begin(), temp.end(), back_inserter(ranges));
  450. }
  451. CSeq_loc* SeqLocMergeOne
  452. (const CBioseq_Handle& target,
  453.  const CSeq_loc& loc,
  454.  TSeqLocFlags flags)
  455. {
  456.     _ASSERT(target);
  457.     TRangeVec ranges;
  458.     CRef<CSeq_id> id(new CSeq_id);
  459.     id->Assign(GetId(target, eGetId_Best));
  460.     const CSeq_inst& inst = target.GetInst();
  461.     CSeq_inst::TTopology topology = inst.CanGetTopology() ?
  462.         inst.GetTopology() : CSeq_inst::eTopology_not_set;
  463.     bool circular = (topology == CSeq_inst::eTopology_circular);
  464.     if ( circular ) {  // circular topology overrides fSingleInterval flag
  465.         flags &= ~fSingleInterval;
  466.     }
  467.     TSeqPos seq_len = inst.IsSetLength() ? inst.GetLength() : 0;
  468.     // map the location to the target bioseq
  469.     CRef<CSeq_loc> mapped_loc(target.MapLocation(loc));
  470.     _ASSERT(IsOneBioseq(*mapped_loc));  // doesn't have multiple bioseqs
  471.     ENa_strand strand = GetStrand(*mapped_loc);
  472.     bool rearranged = false;
  473.     if ( (flags & fSingleInterval) != 0 ) {
  474.             ranges.push_back(mapped_loc->GetTotalRange());
  475.     } else {
  476.         if ( strand == eNa_strand_other ) {  // multiple strands in location
  477.             return mapped_loc.Release();
  478.         }
  479.     
  480.         s_CollectRanges(*mapped_loc, ranges);
  481.         sort(ranges.begin(), ranges.end());  // on the plus strand
  482.         s_MergeRanges(ranges, flags);
  483.         if ( strand == eNa_strand_minus ) {
  484.             reverse(ranges.begin(), ranges.end());
  485.         }
  486.         // if circular bioseq and ranges span the origin, rearrange
  487.         if ( circular ) {
  488.             if ( ((strand == eNa_strand_minus)             &&
  489.                   (ranges.front().GetTo() == seq_len - 1)  &&
  490.                   (ranges.back().GetFrom() == 0))           ||
  491.                  ((strand != eNa_strand_minus)             &&
  492.                   (ranges.front().GetFrom() == 0)          &&
  493.                   (ranges.back().GetTo() == seq_len - 1)) ) {
  494.                 rearranged = true;
  495.                 s_RearrangeRanges(ranges);
  496.             }
  497.         }
  498.     }   
  499.     return s_CreateSeqLoc(*id, ranges, strand, rearranged, (flags & fAddNulls) != 0);
  500. }
  501. static CSeq_interval* s_SeqIntRevCmp(const CSeq_interval& i, CScope* scope)
  502. {
  503.     CRef<CSeq_interval> rev_int(new CSeq_interval);
  504.     rev_int->Assign(i);
  505.     
  506.     ENa_strand s = i.CanGetStrand() ? i.GetStrand() : eNa_strand_unknown;
  507.     rev_int->SetStrand(Reverse(s));
  508.     return rev_int.Release();
  509. }
  510. static CSeq_point* s_SeqPntRevCmp(const CSeq_point& pnt, CScope* scope)
  511. {
  512.     CRef<CSeq_point> rev_pnt(new CSeq_point);
  513.     rev_pnt->Assign(pnt);
  514.     
  515.     ENa_strand s = pnt.CanGetStrand() ? pnt.GetStrand() : eNa_strand_unknown;
  516.     rev_pnt->SetStrand(Reverse(s));
  517.     return rev_pnt.Release();
  518. }
  519. CSeq_loc* SeqLocRevCmp(const CSeq_loc& loc, CScope* scope)
  520. {
  521.     CRef<CSeq_loc> rev_loc(new CSeq_loc);
  522.     switch ( loc.Which() ) {
  523.     // -- reverse is the same.
  524.     case CSeq_loc::e_Null:
  525.     case CSeq_loc::e_Empty:
  526.     case CSeq_loc::e_Whole:
  527.         rev_loc->Assign(loc);
  528.         break;
  529.     // -- just reverse the strand
  530.     case CSeq_loc::e_Int:
  531.         rev_loc->SetInt(*s_SeqIntRevCmp(loc.GetInt(), scope));
  532.         break;
  533.     case CSeq_loc::e_Pnt:
  534.         rev_loc->SetPnt(*s_SeqPntRevCmp(loc.GetPnt(), scope));
  535.         break;
  536.     case CSeq_loc::e_Packed_pnt:
  537.         rev_loc->SetPacked_pnt().Assign(loc.GetPacked_pnt());
  538.         rev_loc->SetPacked_pnt().SetStrand(Reverse(GetStrand(loc, scope)));
  539.         break;
  540.     // -- possibly more than one sequence
  541.     case CSeq_loc::e_Packed_int:
  542.     {
  543.         // reverse each interval and store them in reverse order
  544.         typedef CRef< CSeq_interval > TInt;
  545.         CPacked_seqint& pint = rev_loc->SetPacked_int();
  546.         ITERATE (CPacked_seqint::Tdata, it, loc.GetPacked_int().Get()) {
  547.             pint.Set().push_front(TInt(s_SeqIntRevCmp(**it, scope)));
  548.         }
  549.         break;
  550.     }
  551.     case CSeq_loc::e_Mix:
  552.     {
  553.         // reverse each location and store them in reverse order
  554.         typedef CRef< CSeq_loc > TLoc;
  555.         CSeq_loc_mix& mix = rev_loc->SetMix();
  556.         ITERATE (CSeq_loc_mix::Tdata, it, loc.GetMix().Get()) {
  557.             mix.Set().push_front(TLoc(SeqLocRevCmp(**it, scope)));
  558.         }
  559.         break;
  560.     }
  561.     case CSeq_loc::e_Equiv:
  562.     {
  563.         // reverse each location (no need to reverse order)
  564.         typedef CRef< CSeq_loc > TLoc;
  565.         CSeq_loc_equiv& e = rev_loc->SetEquiv();
  566.         ITERATE (CSeq_loc_equiv::Tdata, it, loc.GetEquiv().Get()) {
  567.             e.Set().push_back(TLoc(SeqLocRevCmp(**it, scope)));
  568.         }
  569.         break;
  570.     }
  571.     case CSeq_loc::e_Bond:
  572.     {
  573.         CSeq_bond& bond = rev_loc->SetBond();
  574.         bond.SetA(*s_SeqPntRevCmp(loc.GetBond().GetA(), scope));
  575.         if ( loc.GetBond().CanGetB() ) {
  576.             bond.SetA(*s_SeqPntRevCmp(loc.GetBond().GetB(), scope));
  577.         }
  578.     }
  579.         
  580.     // -- not supported
  581.     case CSeq_loc::e_Feat:
  582.     default:
  583.         NCBI_THROW(CException, eUnknown,
  584.             "CSeq_loc::SeqLocRevCmp -- unsupported location type");
  585.     }
  586.     return rev_loc.Release();
  587. }
  588. // Get the encoding CDS feature of a given protein sequence.
  589. const CSeq_feat* GetCDSForProduct(const CBioseq& product, CScope* scope)
  590. {
  591.     if ( scope == 0 ) {
  592.         return 0;
  593.     }
  594.     return GetCDSForProduct(scope->GetBioseqHandle(product));
  595. }
  596. const CSeq_feat* GetCDSForProduct(const CBioseq_Handle& bsh)
  597. {
  598.     if ( bsh ) {
  599.         CFeat_CI fi(bsh, 
  600.                     0, 0,
  601.                     CSeqFeatData::e_Cdregion,
  602.                     SAnnotSelector::eOverlap_Intervals,
  603.                     SAnnotSelector::eResolve_TSE,
  604.                     CFeat_CI::e_Product,
  605.                     0);
  606.         if ( fi ) {
  607.             // return the first one (should be the one packaged on the
  608.             // nuc-prot set).
  609.             return &(fi->GetOriginalFeature());
  610.         }
  611.     }
  612.     return 0;
  613. }
  614. // Get the mature peptide feature of a protein
  615. const CSeq_feat* GetPROTForProduct(const CBioseq& product, CScope* scope)
  616. {
  617.     if ( scope == 0 ) {
  618.         return 0;
  619.     }
  620.     return GetPROTForProduct(scope->GetBioseqHandle(product));
  621. }
  622. const CSeq_feat* GetPROTForProduct(const CBioseq_Handle& bsh)
  623. {
  624.     if ( bsh ) {
  625.         CFeat_CI fi(bsh, 
  626.                     0, 0,
  627.                     CSeqFeatData::e_Prot,
  628.                     SAnnotSelector::eOverlap_Intervals,
  629.                     SAnnotSelector::eResolve_TSE,
  630.                     CFeat_CI::e_Product,
  631.                     0);
  632.         if ( fi ) {
  633.             return &(fi->GetOriginalFeature());
  634.         }
  635.     }
  636.     return 0;
  637. }
  638. // Get the encoding mRNA feature of a given mRNA (cDNA) bioseq.
  639. const CSeq_feat* GetmRNAForProduct(const CBioseq& product, CScope* scope)
  640. {
  641.     if ( scope == 0 ) {
  642.         return 0;
  643.     }
  644.     return GetmRNAForProduct(scope->GetBioseqHandle(product));
  645. }
  646. const CSeq_feat* GetmRNAForProduct(const CBioseq_Handle& bsh)
  647. {
  648.     if ( bsh ) {
  649.         SAnnotSelector as;
  650.         as.SetFeatSubtype(CSeqFeatData::eSubtype_mRNA);
  651.         as.SetByProduct();
  652.         CFeat_CI fi(bsh, 0, 0, as);
  653.         if ( fi ) {
  654.             return &(fi->GetOriginalFeature());
  655.         }
  656.     }
  657.     return 0;
  658. }
  659. // Get the encoding sequence of a protein
  660. const CBioseq* GetNucleotideParent(const CBioseq& product, CScope* scope)
  661. {
  662.     if ( scope == 0 ) {
  663.         return 0;
  664.     }
  665.     CBioseq_Handle bsh = GetNucleotideParent(scope->GetBioseqHandle(product));
  666.     return bsh ? &(bsh.GetBioseq()) : 0;
  667. }
  668. CBioseq_Handle GetNucleotideParent(const CBioseq_Handle& bsh)
  669. {
  670.     // If protein use CDS to get to the encoding Nucleotide.
  671.     // if nucleotide (cDNA) use mRNA feature.
  672.     const CSeq_feat* sfp = bsh.GetBioseqMolType() == CSeq_inst::eMol_aa ?
  673.         GetCDSForProduct(bsh) : GetmRNAForProduct(bsh);
  674.     CBioseq_Handle ret;
  675.     if ( sfp ) {
  676.         ret = bsh.GetScope().GetBioseqHandle(sfp->GetLocation());
  677.     }
  678.     return ret;
  679. }
  680. END_SCOPE(sequence)
  681. void CFastaOstream::Write(const CBioseq_Handle& handle,
  682.                           const CSeq_loc* location)
  683. {
  684.     WriteTitle(handle);
  685.     WriteSequence(handle, location);
  686. }
  687. void CFastaOstream::WriteTitle(const CBioseq_Handle& handle)
  688. {
  689.     m_Out << '>' << CSeq_id::GetStringDescr(*handle.GetBioseqCore(),
  690.                                             CSeq_id::eFormat_FastA)
  691.           << ' ' << sequence::GetTitle(handle) << NcbiEndl;
  692. }
  693. // XXX - replace with SRelLoc?
  694. struct SGap {
  695.     SGap(TSeqPos start, TSeqPos length) : m_Start(start), m_Length(length) { }
  696.     TSeqPos GetEnd(void) const { return m_Start + m_Length - 1; }
  697.     TSeqPos m_Start, m_Length;
  698. };
  699. typedef list<SGap> TGaps;
  700. static bool s_IsGap(const CSeq_loc& loc, CScope& scope)
  701. {
  702.     if (loc.IsNull()) {
  703.         return true;
  704.     }
  705.     CTypeConstIterator<CSeq_id> id(loc);
  706.     CBioseq_Handle handle = scope.GetBioseqHandle(*id);
  707.     if (handle  &&  handle.GetBioseqCore()->GetInst().GetRepr()
  708.         == CSeq_inst::eRepr_virtual) {
  709.         return true;
  710.     }
  711.     return false; // default
  712. }
  713. static TGaps s_FindGaps(const CSeq_ext& ext, CScope& scope)
  714. {
  715.     TSeqPos pos = 0;
  716.     TGaps   gaps;
  717.     switch (ext.Which()) {
  718.     case CSeq_ext::e_Seg:
  719.         ITERATE (CSeg_ext::Tdata, it, ext.GetSeg().Get()) {
  720.             TSeqPos length = sequence::GetLength(**it, &scope);
  721.             if (s_IsGap(**it, scope)) {
  722.                 gaps.push_back(SGap(pos, length));
  723.             }
  724.             pos += length;
  725.         }
  726.         break;
  727.     case CSeq_ext::e_Delta:
  728.         ITERATE (CDelta_ext::Tdata, it, ext.GetDelta().Get()) {
  729.             switch ((*it)->Which()) {
  730.             case CDelta_seq::e_Loc:
  731.             {
  732.                 const CSeq_loc& loc = (*it)->GetLoc();
  733.                 TSeqPos length = sequence::GetLength(loc, &scope);
  734.                 if (s_IsGap(loc, scope)) {
  735.                     gaps.push_back(SGap(pos, length));
  736.                 }
  737.                 pos += length;
  738.                 break;
  739.             }
  740.             case CDelta_seq::e_Literal:
  741.             {
  742.                 const CSeq_literal& lit    = (*it)->GetLiteral();
  743.                 TSeqPos             length = lit.GetLength();
  744.                 if ( !lit.IsSetSeq_data() ) {
  745.                     gaps.push_back(SGap(pos, length));
  746.                 }
  747.                 pos += length;
  748.                 break;
  749.             }
  750.             default:
  751.                 ERR_POST(Warning << "CFastaOstream::WriteSequence: "
  752.                          "unsupported Delta-seq selection "
  753.                          << CDelta_seq::SelectionName((*it)->Which()));
  754.                 break;
  755.             }
  756.         }
  757.     default:
  758.         break;
  759.     }
  760.     return gaps;
  761. }
  762. static TGaps s_AdjustGaps(const TGaps& gaps, const CSeq_loc& location)
  763. {
  764.     // assume location matches handle
  765.     const TSeqPos         kMaxPos = numeric_limits<TSeqPos>::max();
  766.     TSeqPos               pos     = 0;
  767.     TGaps::const_iterator gap_it  = gaps.begin();
  768.     TGaps                 adjusted_gaps;
  769.     SGap                  new_gap(kMaxPos, 0);
  770.     for (CSeq_loc_CI loc_it(location);  loc_it  &&  gap_it != gaps.end();
  771.          pos += loc_it.GetRange().GetLength(), ++loc_it) {
  772.         CSeq_loc_CI::TRange range = loc_it.GetRange();
  773.         if (new_gap.m_Start != kMaxPos) {
  774.             // in progress
  775.             if (gap_it->GetEnd() < range.GetFrom()) {
  776.                 adjusted_gaps.push_back(new_gap);
  777.                 new_gap.m_Start = kMaxPos;
  778.                 ++gap_it;
  779.             } else if (gap_it->GetEnd() <= range.GetTo()) {
  780.                 new_gap.m_Length += gap_it->GetEnd() - range.GetFrom() + 1;
  781.                 adjusted_gaps.push_back(new_gap);
  782.                 new_gap.m_Start = kMaxPos;
  783.                 ++gap_it;
  784.             } else {
  785.                 new_gap.m_Length += range.GetLength();
  786.                 continue;
  787.             }
  788.         }
  789.         while (gap_it->GetEnd() < range.GetFrom()) {
  790.             ++gap_it; // skip
  791.         }
  792.         if (gap_it->m_Start <= range.GetFrom()) {
  793.             if (gap_it->GetEnd() <= range.GetTo()) {
  794.                 adjusted_gaps.push_back
  795.                     (SGap(pos, gap_it->GetEnd() - range.GetFrom() + 1));
  796.                 ++gap_it;
  797.             } else {
  798.                 new_gap.m_Start  = pos;
  799.                 new_gap.m_Length = range.GetLength();
  800.                 continue;
  801.             }
  802.         }
  803.         while (gap_it->m_Start <= range.GetTo()) {
  804.             TSeqPos pos2 = pos + gap_it->m_Start - range.GetFrom();
  805.             if (gap_it->GetEnd() <= range.GetTo()) {
  806.                 adjusted_gaps.push_back(SGap(pos2, gap_it->m_Length));
  807.                 ++gap_it;
  808.             } else {
  809.                 new_gap.m_Start  = pos2;
  810.                 new_gap.m_Length = range.GetTo() - gap_it->m_Start + 1;
  811.             }
  812.         }
  813.     }
  814.     if (new_gap.m_Start != kMaxPos) {
  815.         adjusted_gaps.push_back(new_gap);
  816.     }
  817.     return adjusted_gaps;
  818. }
  819. void CFastaOstream::WriteSequence(const CBioseq_Handle& handle,
  820.                                   const CSeq_loc* location)
  821. {
  822.     CConstRef<CBioseq> seq  = handle.GetCompleteBioseq();
  823.     const CSeq_inst& inst = seq->GetInst();
  824.     if ( !(m_Flags & eAssembleParts)  &&  !inst.IsSetSeq_data() ) {
  825.         return;
  826.     }
  827.     CSeqVector v = (location
  828.                     ? handle.GetSequenceView(*location,
  829.                                              CBioseq_Handle::eViewMerged,
  830.                                              CBioseq_Handle::eCoding_Iupac)
  831.                     : handle.GetSeqVector(CBioseq_Handle::eCoding_Iupac));
  832.     bool is_na = inst.GetMol() != CSeq_inst::eMol_aa;
  833.     // autodetection is sometimes broken (!)
  834.     v.SetCoding(is_na ? CSeq_data::e_Iupacna : CSeq_data::e_Iupacaa);
  835.     TSeqPos              size = v.size();
  836.     TSeqPos              pos  = 0;
  837.     CSeqVector::TResidue gap  = v.GetGapChar();
  838.     string               buffer;
  839.     TGaps                gaps;
  840.     CScope&              scope   = handle.GetScope();
  841.     const TSeqPos        kMaxPos = numeric_limits<TSeqPos>::max();
  842.     if ( !inst.IsSetSeq_data()  &&  inst.IsSetExt() ) {
  843.         gaps = s_FindGaps(inst.GetExt(), scope);
  844.         if (location) {
  845.             gaps = s_AdjustGaps(gaps, *location);
  846.         }
  847.     }
  848.     gaps.push_back(SGap(kMaxPos, 0));
  849.     while (pos < size) {
  850.         unsigned int limit = min(m_Width,
  851.                                  min(size, gaps.front().m_Start) - pos);
  852.         v.GetSeqData(pos, pos + limit, buffer);
  853.         pos += limit;
  854.         if (limit > 0) {
  855.             m_Out << buffer << 'n';
  856.         }
  857.         if (pos == gaps.front().m_Start) {
  858.             if (m_Flags & eInstantiateGaps) {
  859.                 for (TSeqPos l = gaps.front().m_Length; l > 0; l -= m_Width) {
  860.                     m_Out << string(min(l, m_Width), gap) << 'n';
  861.                 }
  862.             } else {
  863.                 m_Out << "-n";
  864.             }
  865.             pos += gaps.front().m_Length;
  866.             gaps.pop_front();
  867.         }
  868.     }
  869.     m_Out << NcbiFlush;
  870. }
  871. void CFastaOstream::Write(CSeq_entry& entry, const CSeq_loc* location)
  872. {
  873.     CObjectManager om;
  874.     CScope         scope(om);
  875.     scope.AddTopLevelSeqEntry(entry);
  876.     for (CTypeConstIterator<CBioseq> it(entry);  it;  ++it) {
  877.         if ( !SkipBioseq(*it) ) {
  878.             CBioseq_Handle h = scope.GetBioseqHandle(*it->GetId().front());
  879.             Write(h, location);
  880.         }
  881.     }
  882. }
  883. void CFastaOstream::Write(CBioseq& seq, const CSeq_loc* location)
  884. {
  885.     CSeq_entry entry;
  886.     entry.SetSeq(seq);
  887.     Write(entry, location);
  888. }
  889. /////////////////////////////////////////////////////////////////////////////
  890. //
  891. // sequence translation
  892. //
  893. template <class Container>
  894. void x_Translate(const Container& seq,
  895.                  string& prot,
  896.                  const CGenetic_code* code)
  897. {
  898.     // reserve our space
  899.     const size_t mod = seq.size() % 3;
  900.     prot.erase();
  901.     prot.reserve(seq.size() / 3 + (mod ? 1 : 0));
  902.     // get appropriate translation table
  903.     const CTrans_table & tbl =
  904.         (code ? CGen_code_table::GetTransTable(*code) :
  905.                 CGen_code_table::GetTransTable(1));
  906.     // main loop through bases
  907.     typename Container::const_iterator start = seq.begin();
  908.     size_t i;
  909.     size_t k;
  910.     size_t state = 0;
  911.     size_t length = seq.size() / 3;
  912.     for (i = 0;  i < length;  ++i) {
  913.         // loop through one codon at a time
  914.         for (k = 0;  k < 3;  ++k, ++start) {
  915.             state = tbl.NextCodonState(state, *start);
  916.         }
  917.         // save translated amino acid
  918.         prot.append(1, tbl.GetCodonResidue(state));
  919.     }
  920.     if (mod) {
  921.         LOG_POST(Warning <<
  922.                  "translation of sequence whose length "
  923.                  "is not an even number of codons");
  924.         for (k = 0;  k < mod;  ++k, ++start) {
  925.             state = tbl.NextCodonState(state, *start);
  926.         }
  927.         for ( ;  k < 3;  ++k) {
  928.             state = tbl.NextCodonState(state, 'N');
  929.         }
  930.         // save translated amino acid
  931.         prot.append(1, tbl.GetCodonResidue(state));
  932.     }
  933. }
  934. void CSeqTranslator::Translate(const string& seq, string& prot,
  935.                                const CGenetic_code* code,
  936.                                bool include_stop,
  937.                                bool remove_trailing_X)
  938. {
  939.     x_Translate(seq, prot, code);
  940. }
  941. void CSeqTranslator::Translate(const CSeqVector& seq, string& prot,
  942.                                const CGenetic_code* code,
  943.                                bool include_stop,
  944.                                bool remove_trailing_X)
  945. {
  946.     x_Translate(seq, prot, code);
  947. }
  948. void CSeqTranslator::Translate(const CSeq_loc& loc,
  949.                                const CBioseq_Handle& handle,
  950.                                string& prot,
  951.                                const CGenetic_code* code,
  952.                                bool include_stop,
  953.                                bool remove_trailing_X)
  954. {
  955.     CSeqVector seq =
  956.         handle.GetSequenceView(loc, CBioseq_Handle::eViewConstructed,
  957.                                CBioseq_Handle::eCoding_Iupac);
  958.     x_Translate(seq, prot, code);
  959. }
  960. void CCdregion_translate::ReadSequenceByLocation (string& seq,
  961.                                                   const CBioseq_Handle& bsh,
  962.                                                   const CSeq_loc& loc)
  963. {
  964.     // get vector of sequence under location
  965.     CSeqVector seqv = bsh.GetSequenceView (loc,
  966.                                            CBioseq_Handle::eViewConstructed,
  967.                                            CBioseq_Handle::eCoding_Iupac);
  968.     seqv.GetSeqData(0, seqv.size(), seq);
  969. }
  970. void CCdregion_translate::TranslateCdregion (string& prot,
  971.                                              const CBioseq_Handle& bsh,
  972.                                              const CSeq_loc& loc,
  973.                                              const CCdregion& cdr,
  974.                                              bool include_stop,
  975.                                              bool remove_trailing_X,
  976.                                              bool* alt_start)
  977. {
  978.     // clear contents of result string
  979.     prot.erase();
  980.     if ( alt_start != 0 ) {
  981.         *alt_start = false;
  982.     }
  983.     // copy bases from coding region location
  984.     string bases = "";
  985.     ReadSequenceByLocation (bases, bsh, loc);
  986.     // calculate offset from frame parameter
  987.     int offset = 0;
  988.     if (cdr.IsSetFrame ()) {
  989.         switch (cdr.GetFrame ()) {
  990.             case CCdregion::eFrame_two :
  991.                 offset = 1;
  992.                 break;
  993.             case CCdregion::eFrame_three :
  994.                 offset = 2;
  995.                 break;
  996.             default :
  997.                 break;
  998.         }
  999.     }
  1000.     int dnalen = bases.size () - offset;
  1001.     if (dnalen < 1) return;
  1002.     // pad bases string if last codon is incomplete
  1003.     bool incomplete_last_codon = false;
  1004.     int mod = dnalen % 3;
  1005.     if ( mod != 0 ) {
  1006.         incomplete_last_codon = true;
  1007.         bases += (mod == 1) ? "NN" : "N";
  1008.         dnalen += 3 - mod;
  1009.     }
  1010.     _ASSERT((dnalen >= 3)  &&  ((dnalen % 3) == 0));
  1011.     // resize output protein translation string
  1012.     prot.resize(dnalen / 3);
  1013.     // get appropriate translation table
  1014.     const CTrans_table& tbl = cdr.IsSetCode() ?
  1015.         CGen_code_table::GetTransTable(cdr.GetCode()) :
  1016.         CGen_code_table::GetTransTable(1);
  1017.     // main loop through bases
  1018.     string::const_iterator it = bases.begin();
  1019.     string::const_iterator end = bases.end();
  1020.     for ( int i = 0; i < offset; ++i ) {
  1021.         ++it;
  1022.     }
  1023.     unsigned int state = 0, j = 0;
  1024.     while ( it != end ) {
  1025.         // get one codon at a time
  1026.         state = tbl.NextCodonState(state, *it++);
  1027.         state = tbl.NextCodonState(state, *it++);
  1028.         state = tbl.NextCodonState(state, *it++);
  1029.         // save translated amino acid
  1030.         prot[j++] = tbl.GetCodonResidue(state);
  1031.     }
  1032.     // check for alternative start codon
  1033.     if ( alt_start != 0 ) {
  1034.         state = 0;
  1035.         state = tbl.NextCodonState (state, bases[0]);
  1036.         state = tbl.NextCodonState (state, bases[1]);
  1037.         state = tbl.NextCodonState (state, bases[2]);
  1038.         if ( tbl.IsAltStart(state) ) {
  1039.             *alt_start = true;
  1040.         }
  1041.     }
  1042.     // if complete at 5' end, require valid start codon
  1043.     if (offset == 0  &&  (! loc.IsPartialLeft ())) {
  1044.         state = tbl.SetCodonState (bases [offset], bases [offset + 1], bases [offset + 2]);
  1045.         prot [0] = tbl.GetStartResidue (state);
  1046.     }
  1047.     // code break substitution
  1048.     if (cdr.IsSetCode_break ()) {
  1049.         SIZE_TYPE protlen = prot.size ();
  1050.         ITERATE (CCdregion::TCode_break, code_break, cdr.GetCode_break ()) {
  1051.             const CRef <CCode_break> brk = *code_break;
  1052.             const CSeq_loc& cbk_loc = brk->GetLoc ();
  1053.             TSeqPos seq_pos = sequence::LocationOffset (loc, cbk_loc, sequence::eOffset_FromStart, &bsh.GetScope ());
  1054.             seq_pos -= offset;
  1055.             SIZE_TYPE i = seq_pos / 3;
  1056.             if (i >= 0 && i < protlen) {
  1057.               const CCode_break::C_Aa& c_aa = brk->GetAa ();
  1058.               if (c_aa.IsNcbieaa ()) {
  1059.                 prot [i] = c_aa.GetNcbieaa ();
  1060.               }
  1061.             }
  1062.         }
  1063.     }
  1064.     // optionally truncate at first terminator
  1065.     if (! include_stop) {
  1066.         SIZE_TYPE protlen = prot.size ();
  1067.         for (SIZE_TYPE i = 0; i < protlen; i++) {
  1068.             if (prot [i] == '*') {
  1069.                 prot.resize (i);
  1070.                 return;
  1071.             }
  1072.         }
  1073.     }
  1074.     // if padding was needed, trim ambiguous last residue
  1075.     if (incomplete_last_codon) {
  1076.         int protlen = prot.size ();
  1077.         if (protlen > 0 && prot [protlen - 1] == 'X') {
  1078.             protlen--;
  1079.             prot.resize (protlen);
  1080.         }
  1081.     }
  1082.     // optionally remove trailing X on 3' partial coding region
  1083.     if (remove_trailing_X) {
  1084.         int protlen = prot.size ();
  1085.         while (protlen > 0 && prot [protlen - 1] == 'X') {
  1086.             protlen--;
  1087.         }
  1088.         prot.resize (protlen);
  1089.     }
  1090. }
  1091. void CCdregion_translate::TranslateCdregion
  1092. (string& prot,
  1093.  const CSeq_feat& cds,
  1094.  CScope& scope,
  1095.  bool include_stop,
  1096.  bool remove_trailing_X,
  1097.  bool* alt_start)
  1098. {
  1099.     _ASSERT(cds.GetData().IsCdregion());
  1100.     prot.erase();
  1101.     CBioseq_Handle bsh = scope.GetBioseqHandle(cds.GetLocation());
  1102.     if ( !bsh ) {
  1103.         return;
  1104.     }
  1105.     CCdregion_translate::TranslateCdregion(
  1106.         prot,
  1107.         bsh,
  1108.         cds.GetLocation(),
  1109.         cds.GetData().GetCdregion(),
  1110.         include_stop,
  1111.         remove_trailing_X,
  1112.         alt_start);
  1113. }
  1114. SRelLoc::SRelLoc(const CSeq_loc& parent, const CSeq_loc& child, CScope* scope,
  1115.                  SRelLoc::TFlags flags)
  1116.     : m_ParentLoc(&parent)
  1117. {
  1118.     typedef CSeq_loc::TRange TRange0;
  1119.     for (CSeq_loc_CI cit(child);  cit;  ++cit) {
  1120.         const CSeq_id& cseqid  = cit.GetSeq_id();
  1121.         TRange0        crange  = cit.GetRange();
  1122.         if (crange.IsWholeTo()  &&  scope) {
  1123.             // determine actual end
  1124.             crange.SetToOpen(sequence::GetLength(cit.GetSeq_id(), scope));
  1125.         }
  1126.         ENa_strand     cstrand = cit.GetStrand();
  1127.         TSeqPos        pos     = 0;
  1128.         for (CSeq_loc_CI pit(parent);  pit;  ++pit) {
  1129.             ENa_strand pstrand = pit.GetStrand();
  1130.             TRange0    prange  = pit.GetRange();
  1131.             if (prange.IsWholeTo()  &&  scope) {
  1132.                 // determine actual end
  1133.                 prange.SetToOpen(sequence::GetLength(pit.GetSeq_id(), scope));
  1134.             }
  1135.             if ( !sequence::IsSameBioseq(cseqid, pit.GetSeq_id(), scope) ) {
  1136.                 pos += prange.GetLength();
  1137.                 continue;
  1138.             }
  1139.             CRef<TRange>         intersection(new TRange);
  1140.             TSeqPos              abs_from, abs_to;
  1141.             CConstRef<CInt_fuzz> fuzz_from, fuzz_to;
  1142.             if (crange.GetFrom() >= prange.GetFrom()) {
  1143.                 abs_from  = crange.GetFrom();
  1144.                 fuzz_from = cit.GetFuzzFrom();
  1145.                 if (abs_from == prange.GetFrom()) {
  1146.                     // subtract out parent fuzz, if any
  1147.                     const CInt_fuzz* pfuzz = pit.GetFuzzFrom();
  1148.                     if (pfuzz) {
  1149.                         if (fuzz_from) {
  1150.                             CRef<CInt_fuzz> f(new CInt_fuzz);
  1151.                             f->Assign(*fuzz_from);
  1152.                             f->Subtract(*pfuzz, abs_from, abs_from);
  1153.                             if (f->IsP_m()  &&  !f->GetP_m() ) {
  1154.                                 fuzz_from.Reset(); // cancelled
  1155.                             } else {
  1156.                                 fuzz_from = f;
  1157.                             }
  1158.                         } else {
  1159.                             fuzz_from = pfuzz->Negative(abs_from);
  1160.                         }
  1161.                     }
  1162.                 }
  1163.             } else {
  1164.                 abs_from  = prange.GetFrom();
  1165.                 // fuzz_from = pit.GetFuzzFrom();
  1166.                 CRef<CInt_fuzz> f(new CInt_fuzz);
  1167.                 f->SetLim(CInt_fuzz::eLim_lt);
  1168.                 fuzz_from = f;
  1169.             }
  1170.             if (crange.GetTo() <= prange.GetTo()) {
  1171.                 abs_to  = crange.GetTo();
  1172.                 fuzz_to = cit.GetFuzzTo();
  1173.                 if (abs_to == prange.GetTo()) {
  1174.                     // subtract out parent fuzz, if any
  1175.                     const CInt_fuzz* pfuzz = pit.GetFuzzTo();
  1176.                     if (pfuzz) {
  1177.                         if (fuzz_to) {
  1178.                             CRef<CInt_fuzz> f(new CInt_fuzz);
  1179.                             f->Assign(*fuzz_to);
  1180.                             f->Subtract(*pfuzz, abs_to, abs_to);
  1181.                             if (f->IsP_m()  &&  !f->GetP_m() ) {
  1182.                                 fuzz_to.Reset(); // cancelled
  1183.                             } else {
  1184.                                 fuzz_to = f;
  1185.                             }
  1186.                         } else {
  1187.                             fuzz_to = pfuzz->Negative(abs_to);
  1188.                         }
  1189.                     }
  1190.                 }
  1191.             } else {
  1192.                 abs_to  = prange.GetTo();
  1193.                 // fuzz_to = pit.GetFuzzTo();
  1194.                 CRef<CInt_fuzz> f(new CInt_fuzz);
  1195.                 f->SetLim(CInt_fuzz::eLim_gt);
  1196.                 fuzz_to = f;
  1197.             }
  1198.             if (abs_from <= abs_to) {
  1199.                 if (IsReverse(pstrand)) {
  1200.                     TSeqPos sigma = pos + prange.GetTo();
  1201.                     intersection->SetFrom(sigma - abs_to);
  1202.                     intersection->SetTo  (sigma - abs_from);
  1203.                     if (fuzz_from) {
  1204.                         intersection->SetFuzz_to().AssignTranslated
  1205.                             (*fuzz_from, intersection->GetTo(), abs_from);
  1206.                         intersection->SetFuzz_to().Negate
  1207.                             (intersection->GetTo());
  1208.                     }
  1209.                     if (fuzz_to) {
  1210.                         intersection->SetFuzz_from().AssignTranslated
  1211.                             (*fuzz_to, intersection->GetFrom(), abs_to);
  1212.                         intersection->SetFuzz_from().Negate
  1213.                             (intersection->GetFrom());
  1214.                     }
  1215.                     if (cstrand == eNa_strand_unknown) {
  1216.                         intersection->SetStrand(pstrand);
  1217.                     } else {
  1218.                         intersection->SetStrand(Reverse(cstrand));
  1219.                     }
  1220.                 } else {
  1221.                     TSignedSeqPos delta = pos - prange.GetFrom();
  1222.                     intersection->SetFrom(abs_from + delta);
  1223.                     intersection->SetTo  (abs_to   + delta);
  1224.                     if (fuzz_from) {
  1225.                         intersection->SetFuzz_from().AssignTranslated
  1226.                             (*fuzz_from, intersection->GetFrom(), abs_from);
  1227.                     }
  1228.                     if (fuzz_to) {
  1229.                         intersection->SetFuzz_to().AssignTranslated
  1230.                             (*fuzz_to, intersection->GetTo(), abs_to);
  1231.                     }
  1232.                     if (cstrand == eNa_strand_unknown) {
  1233.                         intersection->SetStrand(pstrand);
  1234.                     } else {
  1235.                         intersection->SetStrand(cstrand);
  1236.                     }
  1237.                 }
  1238.                 // add to m_Ranges, combining with the previous
  1239.                 // interval if possible
  1240.                 if ( !(flags & fNoMerge)  &&  !m_Ranges.empty()
  1241.                     &&  SameOrientation(intersection->GetStrand(),
  1242.                                         m_Ranges.back()->GetStrand()) ) {
  1243.                     if (m_Ranges.back()->GetTo() == intersection->GetFrom() - 1
  1244.                         &&  !IsReverse(intersection->GetStrand()) ) {
  1245.                         m_Ranges.back()->SetTo(intersection->GetTo());
  1246.                         if (intersection->IsSetFuzz_to()) {
  1247.                             m_Ranges.back()->SetFuzz_to
  1248.                                 (intersection->SetFuzz_to());
  1249.                         } else {
  1250.                             m_Ranges.back()->ResetFuzz_to();
  1251.                         }
  1252.                     } else if (m_Ranges.back()->GetFrom()
  1253.                                == intersection->GetTo() + 1
  1254.                                &&  IsReverse(intersection->GetStrand())) {
  1255.                         m_Ranges.back()->SetFrom(intersection->GetFrom());
  1256.                         if (intersection->IsSetFuzz_from()) {
  1257.                             m_Ranges.back()->SetFuzz_from
  1258.                                 (intersection->SetFuzz_from());
  1259.                         } else {
  1260.                             m_Ranges.back()->ResetFuzz_from();
  1261.                         }
  1262.                     } else {
  1263.                         m_Ranges.push_back(intersection);
  1264.                     }
  1265.                 } else {
  1266.                     m_Ranges.push_back(intersection);
  1267.                 }
  1268.             }
  1269.             pos += prange.GetLength();
  1270.         }
  1271.     }
  1272. }
  1273. // Bother trying to merge?
  1274. CRef<CSeq_loc> SRelLoc::Resolve(const CSeq_loc& new_parent, CScope* scope,
  1275.                                 SRelLoc::TFlags /* flags */)
  1276.     const
  1277. {
  1278.     typedef CSeq_loc::TRange TRange0;
  1279.     CRef<CSeq_loc> result(new CSeq_loc);
  1280.     CSeq_loc_mix&  mix = result->SetMix();
  1281.     ITERATE (TRanges, it, m_Ranges) {
  1282.         _ASSERT((*it)->GetFrom() <= (*it)->GetTo());
  1283.         TSeqPos pos = 0, start = (*it)->GetFrom();
  1284.         bool    keep_going = true;
  1285.         for (CSeq_loc_CI pit(new_parent);  pit;  ++pit) {
  1286.             TRange0 prange = pit.GetRange();
  1287.             if (prange.IsWholeTo()  &&  scope) {
  1288.                 // determine actual end
  1289.                 prange.SetToOpen(sequence::GetLength(pit.GetSeq_id(), scope));
  1290.             }
  1291.             TSeqPos length = prange.GetLength();
  1292.             if (start >= pos  &&  start < pos + length) {
  1293.                 TSeqPos              from, to;
  1294.                 CConstRef<CInt_fuzz> fuzz_from, fuzz_to;
  1295.                 ENa_strand           strand;
  1296.                 if (IsReverse(pit.GetStrand())) {
  1297.                     TSeqPos sigma = pos + prange.GetTo();
  1298.                     from = sigma - (*it)->GetTo();
  1299.                     to   = sigma - start;
  1300.                     if (from < prange.GetFrom()  ||  from > sigma) {
  1301.                         from = prange.GetFrom();
  1302.                         keep_going = true;
  1303.                     } else {
  1304.                         keep_going = false;
  1305.                     }
  1306.                     if ( !(*it)->IsSetStrand()
  1307.                         ||  (*it)->GetStrand() == eNa_strand_unknown) {
  1308.                         strand = pit.GetStrand();
  1309.                     } else {
  1310.                         strand = Reverse((*it)->GetStrand());
  1311.                     }
  1312.                     if (from == prange.GetFrom()) {
  1313.                         fuzz_from = pit.GetFuzzFrom();
  1314.                     }
  1315.                     if ( !keep_going  &&  (*it)->IsSetFuzz_to() ) {
  1316.                         CRef<CInt_fuzz> f(new CInt_fuzz);
  1317.                         if (fuzz_from) {
  1318.                             f->Assign(*fuzz_from);
  1319.                         } else {
  1320.                             f->SetP_m(0);
  1321.                         }
  1322.                         f->Subtract((*it)->GetFuzz_to(), from, (*it)->GetTo(),
  1323.                                     CInt_fuzz::eAmplify);
  1324.                         if (f->IsP_m()  &&  !f->GetP_m() ) {
  1325.                             fuzz_from.Reset(); // cancelled
  1326.                         } else {
  1327.                             fuzz_from = f;
  1328.                         }
  1329.                     }
  1330.                     if (to == prange.GetTo()) {
  1331.                         fuzz_to = pit.GetFuzzTo();
  1332.                     }
  1333.                     if (start == (*it)->GetFrom()
  1334.                         &&  (*it)->IsSetFuzz_from()) {
  1335.                         CRef<CInt_fuzz> f(new CInt_fuzz);
  1336.                         if (fuzz_to) {
  1337.                             f->Assign(*fuzz_to);
  1338.                         } else {
  1339.                             f->SetP_m(0);
  1340.                         }
  1341.                         f->Subtract((*it)->GetFuzz_from(), to,
  1342.                                     (*it)->GetFrom(), CInt_fuzz::eAmplify);
  1343.                         if (f->IsP_m()  &&  !f->GetP_m() ) {
  1344.                             fuzz_to.Reset(); // cancelled
  1345.                         } else {
  1346.                             fuzz_to = f;
  1347.                         }
  1348.                     }
  1349.                 } else {
  1350.                     TSignedSeqPos delta = prange.GetFrom() - pos;
  1351.                     from = start          + delta;
  1352.                     to   = (*it)->GetTo() + delta;
  1353.                     if (to > prange.GetTo()) {
  1354.                         to = prange.GetTo();
  1355.                         keep_going = true;
  1356.                     } else {
  1357.                         keep_going = false;
  1358.                     }
  1359.                     if ( !(*it)->IsSetStrand()
  1360.                         ||  (*it)->GetStrand() == eNa_strand_unknown) {
  1361.                         strand = pit.GetStrand();
  1362.                     } else {
  1363.                         strand = (*it)->GetStrand();
  1364.                     }
  1365.                     if (from == prange.GetFrom()) {
  1366.                         fuzz_from = pit.GetFuzzFrom();
  1367.                     }
  1368.                     if (start == (*it)->GetFrom()
  1369.                         &&  (*it)->IsSetFuzz_from()) {
  1370.                         CRef<CInt_fuzz> f(new CInt_fuzz);
  1371.                         if (fuzz_from) {
  1372.                             f->Assign(*fuzz_from);
  1373.                             f->Add((*it)->GetFuzz_from(), from,
  1374.                                    (*it)->GetFrom());
  1375.                         } else {
  1376.                             f->AssignTranslated((*it)->GetFuzz_from(), from,
  1377.                                                 (*it)->GetFrom());
  1378.                         }
  1379.                         if (f->IsP_m()  &&  !f->GetP_m() ) {
  1380.                             fuzz_from.Reset(); // cancelled
  1381.                         } else {
  1382.                             fuzz_from = f;
  1383.                         }
  1384.                     }
  1385.                     if (to == prange.GetTo()) {
  1386.                         fuzz_to = pit.GetFuzzTo();
  1387.                     }
  1388.                     if ( !keep_going  &&  (*it)->IsSetFuzz_to() ) {
  1389.                         CRef<CInt_fuzz> f(new CInt_fuzz);
  1390.                         if (fuzz_to) {
  1391.                             f->Assign(*fuzz_to);
  1392.                             f->Add((*it)->GetFuzz_to(), to, (*it)->GetTo());
  1393.                         } else {
  1394.                             f->AssignTranslated((*it)->GetFuzz_to(), to,
  1395.                                                 (*it)->GetTo());
  1396.                         }
  1397.                         if (f->IsP_m()  &&  !f->GetP_m() ) {
  1398.                             fuzz_to.Reset(); // cancelled
  1399.                         } else {
  1400.                             fuzz_to = f;
  1401.                         }
  1402.                     }
  1403.                 }
  1404.                 if (from == to
  1405.                     &&  (fuzz_from == fuzz_to
  1406.                          ||  (fuzz_from.GetPointer()  &&  fuzz_to.GetPointer()
  1407.                               &&  fuzz_from->Equals(*fuzz_to)))) {
  1408.                     // just a point
  1409.                     CRef<CSeq_loc> loc(new CSeq_loc);
  1410.                     CSeq_point& point = loc->SetPnt();
  1411.                     point.SetPoint(from);
  1412.                     if (strand != eNa_strand_unknown) {
  1413.                         point.SetStrand(strand);
  1414.                     }
  1415.                     if (fuzz_from) {
  1416.                         point.SetFuzz().Assign(*fuzz_from);
  1417.                     }
  1418.                     point.SetId().Assign(pit.GetSeq_id());
  1419.                     mix.Set().push_back(loc);
  1420.                 } else {
  1421.                     CRef<CSeq_loc> loc(new CSeq_loc);
  1422.                     CSeq_interval& ival = loc->SetInt();
  1423.                     ival.SetFrom(from);
  1424.                     ival.SetTo(to);
  1425.                     if (strand != eNa_strand_unknown) {
  1426.                         ival.SetStrand(strand);
  1427.                     }
  1428.                     if (fuzz_from) {
  1429.                         ival.SetFuzz_from().Assign(*fuzz_from);
  1430.                     }
  1431.                     if (fuzz_to) {
  1432.                         ival.SetFuzz_to().Assign(*fuzz_to);
  1433.                     }
  1434.                     ival.SetId().Assign(pit.GetSeq_id());
  1435.                     mix.Set().push_back(loc);
  1436.                 }
  1437.                 if (keep_going) {
  1438.                     start = pos + length;
  1439.                 } else {
  1440.                     break;
  1441.                 }
  1442.             }
  1443.             pos += length;
  1444.         }
  1445.         if (keep_going) {
  1446.             TSeqPos total_length;
  1447.             string  label;
  1448.             new_parent.GetLabel(&label);
  1449.             try {
  1450.                 total_length = sequence::GetLength(new_parent, scope);
  1451.                 ERR_POST(Warning << "SRelLoc::Resolve: Relative position "
  1452.                          << start << " exceeds length (" << total_length
  1453.                          << ") of parent location " << label);
  1454.             } catch (sequence::CNoLength) {
  1455.                 ERR_POST(Warning << "SRelLoc::Resolve: Relative position "
  1456.                          << start
  1457.                          << " exceeds length (???) of parent location "
  1458.                          << label);
  1459.             }            
  1460.         }
  1461.     }
  1462.     // clean up output
  1463.     switch (mix.Get().size()) {
  1464.     case 0:
  1465.         result->SetNull();
  1466.         break;
  1467.     case 1:
  1468.         result.Reset(mix.Set().front());
  1469.         break;
  1470.     default:
  1471.         break;
  1472.     }
  1473.     return result;
  1474. }
  1475. //============================================================================//
  1476. //                                 SeqSearch                                  //
  1477. //============================================================================//
  1478. // Public:
  1479. // =======
  1480. // Constructors and Destructors:
  1481. CSeqSearch::CSeqSearch(IClient *client, bool allow_mismatch) :
  1482.     m_AllowOneMismatch(allow_mismatch),
  1483.     m_MaxPatLen(0),
  1484.     m_Client(client)
  1485. {
  1486.     InitializeMaps();
  1487. }
  1488. CSeqSearch::~CSeqSearch(void) {}
  1489. // Add nucleotide pattern or restriction site to sequence search.
  1490. // Uses ambiguity codes, e.g., R = A and G, H = A, C and T
  1491. void CSeqSearch::AddNucleotidePattern
  1492. (const string& name,
  1493. const string& pat, 
  1494. int cut_site,
  1495. int overhang)
  1496. {
  1497.     string pattern = pat;
  1498.     NStr::TruncateSpaces(pattern);
  1499.     NStr::ToUpper(pattern);
  1500.     // reverse complement pattern to see if it is symetrical
  1501.     string rcomp = ReverseComplement(pattern);
  1502.     bool symmetric = (pattern == rcomp);
  1503.     ENa_strand strand = symmetric ? eNa_strand_both : eNa_strand_plus;
  1504.     AddNucleotidePattern(name, pat, cut_site, overhang, strand);
  1505.     if ( !symmetric ) {
  1506.         AddNucleotidePattern(name, rcomp, pat.length() - cut_site, 
  1507.                              overhang, eNa_strand_minus);
  1508.     }
  1509. }
  1510. // Program passes each character in turn to finite state machine.
  1511. int CSeqSearch::Search
  1512. (int current_state,
  1513.  char ch,
  1514.  int position,
  1515.  int length)
  1516. {
  1517.     if ( !m_Client ) return 0;
  1518.     // on first character, populate state transition table
  1519.     if ( !m_Fsa.IsPrimed() ) {
  1520.         m_Fsa.Prime();
  1521.     }
  1522.     
  1523.     int next_state = m_Fsa.GetNextState(current_state, ch);
  1524.     
  1525.     // report any matches at current state to the client object
  1526.     if ( m_Fsa.IsMatchFound(next_state) ) {
  1527.         ITERATE( vector<CMatchInfo>, it, m_Fsa.GetMatches(next_state) ) {
  1528.   //const CMatchInfo& match = *it;
  1529.             int start = position - it->GetPattern().length() + 1;    
  1530.             // prevent multiple reports of patterns for circular sequences.
  1531.             if ( start < length ) {
  1532.                 m_Client->MatchFound(*it, start);
  1533.             }
  1534.         }
  1535.     }
  1536.     return next_state;
  1537. }
  1538. // Search an entire bioseq.
  1539. void CSeqSearch::Search(const CBioseq_Handle& bsh)
  1540. {
  1541.     if ( !bsh ) return;
  1542.     if ( !m_Client ) return;  // no one to report to, so why search at all.
  1543.     CSeqVector seq_vec = bsh.GetSeqVector(CBioseq_Handle::eCoding_Iupac);
  1544.     size_t seq_len = seq_vec.size();
  1545.     size_t search_len = seq_len;
  1546.     CSeq_inst::ETopology topology =
  1547.         bsh.GetBioseqCore()->GetInst().GetTopology();    
  1548.     if ( topology == CSeq_inst::eTopology_circular ) {
  1549.         search_len += m_MaxPatLen - 1;
  1550.     }
  1551.     
  1552.     int state = m_Fsa.GetInitialState();
  1553.     for ( size_t i = 0; i < search_len; ++i ) {
  1554.         state = Search(state, seq_vec[i % seq_len], i, seq_len);
  1555.     }
  1556. }
  1557. // Private:
  1558. // ========
  1559. // translation finite state machine base codes - ncbi4na
  1560. enum EBaseCode {
  1561.     eBase_gap = 0,
  1562.         eBase_A,      /* A    */
  1563.         eBase_C,      /* C    */
  1564.         eBase_M,      /* AC   */
  1565.         eBase_G,      /* G    */
  1566.         eBase_R,      /* AG   */
  1567.         eBase_S,      /* CG   */
  1568.         eBase_V,      /* ACG  */
  1569.         eBase_T,      /* T    */
  1570.         eBase_W,      /* AT   */
  1571.         eBase_Y,      /* CT   */
  1572.         eBase_H,      /* ACT  */
  1573.         eBase_K,      /* GT   */
  1574.         eBase_D,      /* AGT  */
  1575.         eBase_B,      /* CGT  */
  1576.         eBase_N       /* ACGT */
  1577. };
  1578. map<unsigned char, int> CSeqSearch::sm_CharToEnum;
  1579. map<int, unsigned char> CSeqSearch::sm_EnumToChar;
  1580. map<char, char>         CSeqSearch::sm_Complement;
  1581. void CSeqSearch::InitializeMaps(void)
  1582. {
  1583.     int c, i;
  1584.     static const string iupacna_alphabet      = "-ACMGRSVTWYHKDBN";
  1585.     static const string comp_iupacna_alphabet = "-TGKCYSBAWRDMHVN";
  1586.     if ( sm_CharToEnum.empty() ) {
  1587.         // illegal characters map to eBase_gap (0)
  1588.         for ( c = 0; c < 256; ++c ) {
  1589.             sm_CharToEnum[c] = eBase_gap;
  1590.         }
  1591.         
  1592.         // map iupacna alphabet to EBaseCode
  1593.         for (i = eBase_gap; i <= eBase_N; ++i) {
  1594.             c = iupacna_alphabet[i];
  1595.             sm_CharToEnum[c] = (EBaseCode)i;
  1596.             c = tolower(c);
  1597.             sm_CharToEnum[c] = (EBaseCode)i;
  1598.         }
  1599.         sm_CharToEnum ['U'] = eBase_T;
  1600.         sm_CharToEnum ['u'] = eBase_T;
  1601.         sm_CharToEnum ['X'] = eBase_N;
  1602.         sm_CharToEnum ['x'] = eBase_N;
  1603.         
  1604.         // also map ncbi4na alphabet to EBaseCode
  1605.         for (c = eBase_gap; c <= eBase_N; ++c) {
  1606.             sm_CharToEnum[c] = (EBaseCode)c;
  1607.         }
  1608.     }
  1609.     
  1610.     // map EBaseCode to iupacna alphabet
  1611.     if ( sm_EnumToChar.empty() ) { 
  1612.         for (i = eBase_gap; i <= eBase_N; ++i) {
  1613.             sm_EnumToChar[i] = iupacna_alphabet[i];
  1614.         }
  1615.     }
  1616.     // initialize table to convert character to complement character
  1617.     if ( sm_Complement.empty() ) {
  1618.         int len = iupacna_alphabet.length();
  1619.         for ( i = 0; i < len; ++i ) {
  1620.             sm_Complement.insert(make_pair(iupacna_alphabet[i], comp_iupacna_alphabet[i]));
  1621.         }
  1622.     }
  1623. }
  1624. string CSeqSearch::ReverseComplement(const string& pattern) const
  1625. {
  1626.     size_t len = pattern.length();
  1627.     string rcomp = pattern;
  1628.     rcomp.resize(len);
  1629.     // calculate the complement
  1630.     for ( size_t i = 0; i < len; ++i ) {
  1631.         rcomp[i] = sm_Complement[pattern[i]];
  1632.     }
  1633.     // reverse the complement
  1634.     reverse(rcomp.begin(), rcomp.end());
  1635.     return rcomp;
  1636. }
  1637. void CSeqSearch::AddNucleotidePattern
  1638. (const string& name,
  1639. const string& pattern, 
  1640. int cut_site,
  1641. int overhang,
  1642. ENa_strand strand)
  1643. {
  1644.     size_t pat_len = pattern.length();
  1645.     string temp;
  1646.     temp.resize(pat_len);
  1647.     CMatchInfo info(name,
  1648.                     CNcbiEmptyString::Get(), 
  1649.                     cut_site, 
  1650.                     overhang, 
  1651.                     strand);
  1652.     if ( pat_len > m_MaxPatLen ) {
  1653.         m_MaxPatLen = pat_len;
  1654.     }
  1655.     ExpandPattern(pattern, temp, 0, pat_len, info);
  1656. }
  1657. void CSeqSearch::ExpandPattern
  1658. (const string& pattern,
  1659. string& temp,
  1660. int position,
  1661. int pat_len,
  1662. CMatchInfo& info)
  1663. {
  1664.     static EBaseCode expension[] = { eBase_A, eBase_C, eBase_G, eBase_T };
  1665.     if ( position < pat_len ) {
  1666.         int code = sm_CharToEnum[(int)pattern[position]];
  1667.         
  1668.         for ( int i = 0; i < 4; ++i ) {
  1669.             if ( code & expension[i] ) {
  1670.                 temp[position] = sm_EnumToChar[expension[i]];
  1671.                 ExpandPattern(pattern, temp, position + 1, pat_len, info);
  1672.             }
  1673.         }
  1674.     } else { // recursion base
  1675.         // when position reaches pattern length, store one expanded string.
  1676.         info.m_Pattern = temp;
  1677.         m_Fsa.AddWord(info.m_Pattern, info);
  1678.         if ( m_AllowOneMismatch ) {
  1679.             char ch;
  1680.             // put 'N' at every position if a single mismatch is allowed.
  1681.             for ( int i = 0; i < pat_len; ++i ) {
  1682.                 ch = temp[i];
  1683.                 temp[i] = 'N';
  1684.                 info.m_Pattern = temp;
  1685.                 m_Fsa.AddWord(pattern, info);
  1686.                 // restore proper character, go on to put N in next position.
  1687.                 temp[i] = ch;
  1688.             }
  1689.         }
  1690.     }
  1691. }
  1692. END_SCOPE(objects)
  1693. END_NCBI_SCOPE
  1694. /*
  1695. * ===========================================================================
  1696. * $Log: sequence.cpp,v $
  1697. * Revision 1000.3  2004/06/01 19:25:30  gouriano
  1698. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.82
  1699. *
  1700. * Revision 1.82  2004/05/27 13:48:24  jcherry
  1701. * Replaced some calls to deprecated CBioseq_Handle::GetBioseq() with
  1702. * GetCompleteBioseq() or GetBioseqCore()
  1703. *
  1704. * Revision 1.81  2004/05/25 21:06:34  johnson
  1705. * Bug fix in x_Translate
  1706. *
  1707. * Revision 1.80  2004/05/21 21:42:14  gorelenk
  1708. * Added PCH ncbi_pch.hpp
  1709. *
  1710. * Revision 1.79  2004/05/06 17:39:43  shomrat
  1711. * Fixes to SeqLocMerge
  1712. *
  1713. * Revision 1.78  2004/04/06 14:03:15  dicuccio
  1714. * Added API to extract the single Org-ref from a bioseq handle.  Added API to
  1715. * retrieve a single tax-id from a bioseq handle
  1716. *
  1717. * Revision 1.77  2004/04/05 15:56:14  grichenk
  1718. * Redesigned CAnnotTypes_CI: moved all data and data collecting
  1719. * functions to CAnnotDataCollector. CAnnotTypes_CI is no more
  1720. * inherited from SAnnotSelector.
  1721. *
  1722. * Revision 1.76  2004/03/25 20:02:30  vasilche
  1723. * Added several method variants with CBioseq_Handle as argument.
  1724. *
  1725. * Revision 1.75  2004/03/01 18:28:18  dicuccio
  1726. * Changed sequence::Compare() such that a seq-interval of length 1 and a
  1727. * corresponding seq-point compare as the same
  1728. *
  1729. * Revision 1.74  2004/03/01 18:24:22  shomrat
  1730. * Removed branching in the main cdregion translation loop; Added alternative start flag
  1731. *
  1732. * Revision 1.73  2004/02/19 18:16:48  shomrat
  1733. * Implemented SeqlocRevCmp
  1734. *
  1735. * Revision 1.72  2004/02/09 14:43:18  vasilche
  1736. * Added missing typename keyword.
  1737. *
  1738. * Revision 1.71  2004/02/05 19:41:46  shomrat
  1739. * Convenience functions for popular overlapping types
  1740. *
  1741. * Revision 1.70  2004/02/04 18:05:41  grichenk
  1742. * Added annotation filtering by set of types/subtypes.
  1743. * Renamed *Choice to *Type in SAnnotSelector.
  1744. *
  1745. * Revision 1.69  2004/01/30 17:49:29  ucko
  1746. * Add missing "typename"
  1747. *
  1748. * Revision 1.68  2004/01/30 17:22:53  dicuccio
  1749. * Added sequence::GetId(const CBioseq_Handle&) - returns a selected ID class
  1750. * (best, GI).  Added CSeqTranslator - utility class to translate raw sequence
  1751. * data
  1752. *
  1753. * Revision 1.67  2004/01/28 17:19:04  shomrat
  1754. * Implemented SeqLocMerge
  1755. *
  1756. * Revision 1.66  2003/12/16 19:37:43  shomrat
  1757. * Retrieve encoding feature and bioseq of a protein
  1758. *
  1759. * Revision 1.65  2003/11/19 22:18:05  grichenk
  1760. * All exceptions are now CException-derived. Catch "exception" rather
  1761. * than "runtime_error".
  1762. *
  1763. * Revision 1.64  2003/10/17 20:55:27  ucko
  1764. * SRelLoc::Resolve: fix a fuzz-handling paste-o.
  1765. *
  1766. * Revision 1.63  2003/10/16 11:55:19  dicuccio
  1767. * Fix for brain-dead MSVC and ambiguous operator&&
  1768. *
  1769. * Revision 1.62  2003/10/15 19:52:18  ucko
  1770. * More adjustments to SRelLoc: support fuzz, opposite-strand children,
  1771. * and resolving against an alternate parent.
  1772. *
  1773. * Revision 1.61  2003/10/08 21:08:38  ucko
  1774. * CCdregion_translate: take const Bioseq_Handles, since there's no need
  1775. * to modify them.
  1776. * TestForOverlap: don't consider sequences circular if
  1777. * circular_len == kInvalidSeqPos
  1778. *
  1779. * Revision 1.60  2003/09/22 18:38:14  grichenk
  1780. * Fixed circular seq-locs processing by TestForOverlap()
  1781. *
  1782. * Revision 1.59  2003/07/17 21:00:50  vasilche
  1783. * Added missing include <list>
  1784. *
  1785. * Revision 1.58  2003/06/19 17:11:43  ucko
  1786. * SRelLoc::SRelLoc: remember to update the base position when skipping
  1787. * parent ranges whose IDs don't match.
  1788. *
  1789. * Revision 1.57  2003/06/13 17:23:32  grichenk
  1790. * Added special processing of multi-ID seq-locs in TestForOverlap()
  1791. *
  1792. * Revision 1.56  2003/06/05 18:08:36  shomrat
  1793. * Allow empty location when computing SeqLocPartial; Adjust GetSeqData in cdregion translation
  1794. *
  1795. * Revision 1.55  2003/06/02 18:58:25  dicuccio
  1796. * Fixed #include directives
  1797. *
  1798. * Revision 1.54  2003/06/02 18:53:32  dicuccio
  1799. * Fixed bungled commit
  1800. *
  1801. * Revision 1.52  2003/05/27 19:44:10  grichenk
  1802. * Added CSeqVector_CI class
  1803. *
  1804. * Revision 1.51  2003/05/15 19:27:02  shomrat
  1805. * Compare handle only if both valid; Check IsLim before GetLim
  1806. *
  1807. * Revision 1.50  2003/05/09 15:37:00  ucko
  1808. * Take const CBioseq_Handle references in CFastaOstream::Write et al.
  1809. *
  1810. * Revision 1.49  2003/05/06 19:34:36  grichenk
  1811. * Fixed GetStrand() (worked fine only for plus and unknown strands)
  1812. *
  1813. * Revision 1.48  2003/05/01 17:55:17  ucko
  1814. * Fix GetLength(const CSeq_id&, CScope*) to return ...::max() rather
  1815. * than throwing if it can't resolve the ID to a handle.
  1816. *
  1817. * Revision 1.47  2003/04/24 16:15:58  vasilche
  1818. * Added missing includes and forward class declarations.
  1819. *
  1820. * Revision 1.46  2003/04/16 19:44:26  grichenk
  1821. * More fixes to TestForOverlap() and GetStrand()
  1822. *
  1823. * Revision 1.45  2003/04/15 20:11:21  grichenk
  1824. * Fixed strands problem in TestForOverlap(), replaced type
  1825. * iterator with container iterator in s_GetStrand().
  1826. *
  1827. * Revision 1.44  2003/04/03 19:03:17  grichenk
  1828. * Two more cases to revert locations in GetBestOverlappingFeat()
  1829. *
  1830. * Revision 1.43  2003/04/02 16:58:59  grichenk
  1831. * Change location and feature in GetBestOverlappingFeat()
  1832. * for eOverlap_Subset.
  1833. *
  1834. * Revision 1.42  2003/03/25 22:00:20  grichenk
  1835. * Added strand checking to TestForOverlap()
  1836. *
  1837. * Revision 1.41  2003/03/18 21:48:35  grichenk
  1838. * Removed obsolete class CAnnot_CI
  1839. *
  1840. * Revision 1.40  2003/03/11 16:00:58  kuznets
  1841. * iterate -> ITERATE
  1842. *
  1843. * Revision 1.39  2003/02/19 16:25:14  grichenk
  1844. * Check strands in GetBestOverlappingFeat()
  1845. *
  1846. * Revision 1.38  2003/02/14 15:41:00  shomrat
  1847. * Minor implementation changes in SeqLocPartialTest
  1848. *
  1849. * Revision 1.37  2003/02/13 14:35:40  grichenk
  1850. * + eOverlap_Contains
  1851. *
  1852. * Revision 1.36  2003/02/10 15:54:01  grichenk
  1853. * Use CFeat_CI->GetMappedFeature() and GetOriginalFeature()
  1854. *
  1855. * Revision 1.35  2003/02/06 22:26:27  vasilche
  1856. * Use CSeq_id::Assign().
  1857. *
  1858. * Revision 1.34  2003/02/06 20:59:16  shomrat
  1859. * Bug fix in SeqLocPartialCheck
  1860. *
  1861. * Revision 1.33  2003/01/22 21:02:23  ucko
  1862. * Fix stupid logic error in SRelLoc's constructor; change LocationOffset
  1863. * to return -1 rather than crashing if the locations don't intersect.
  1864. *
  1865. * Revision 1.32  2003/01/22 20:15:02  vasilche
  1866. * Removed compiler warning.
  1867. *
  1868. * Revision 1.31  2003/01/22 18:17:09  ucko
  1869. * SRelLoc::SRelLoc: change intersection to a CRef, so we don't have to
  1870. * worry about it going out of scope while still referenced (by m_Ranges).
  1871. *
  1872. * Revision 1.30  2003/01/08 20:43:10  ucko
  1873. * Adjust SRelLoc to use (ID-less) Seq-intervals for ranges, so that it
  1874. * will be possible to add support for fuzz and strandedness/orientation.
  1875. *
  1876. * Revision 1.29  2002/12/30 19:38:35  vasilche
  1877. * Optimized CGenbankWriter::WriteSequence.
  1878. * Implemented GetBestOverlappingFeat() with CSeqFeatData::ESubtype selector.
  1879. *
  1880. * Revision 1.28  2002/12/26 21:45:29  grichenk
  1881. * + GetBestOverlappingFeat()
  1882. *
  1883. * Revision 1.27  2002/12/26 21:17:06  dicuccio
  1884. * Minor tweaks to avoid compiler warnings in MSVC (remove unused variables)
  1885. *
  1886. * Revision 1.26  2002/12/20 17:14:18  kans
  1887. * added SeqLocPartialCheck
  1888. *
  1889. * Revision 1.25  2002/12/19 20:24:55  grichenk
  1890. * Updated usage of CRange<>
  1891. *
  1892. * Revision 1.24  2002/12/10 16:56:41  ucko
  1893. * CFastaOstream::WriteTitle: restore leading > accidentally dropped in R1.19.
  1894. *
  1895. * Revision 1.23  2002/12/10 16:34:45  kans
  1896. * implement code break processing in TranslateCdregion
  1897. *
  1898. * Revision 1.22  2002/12/09 20:38:41  ucko
  1899. * +sequence::LocationOffset
  1900. *
  1901. * Revision 1.21  2002/12/06 15:36:05  grichenk
  1902. * Added overlap type for annot-iterators
  1903. *
  1904. * Revision 1.20  2002/12/04 15:38:22  ucko
  1905. * SourceToProduct, ProductToSource: just check whether the feature is a coding
  1906. * region rather than attempting to determine molecule types; drop s_DeduceMol.
  1907. *
  1908. * Revision 1.19  2002/11/26 15:14:04  dicuccio
  1909. * Changed CFastaOStream::WriteTitle() to make use of CSeq_id::GetStringDescr().
  1910. *
  1911. * Revision 1.18  2002/11/25 21:24:46  grichenk
  1912. * Added TestForOverlap() function.
  1913. *
  1914. * Revision 1.17  2002/11/18 19:59:23  shomrat
  1915. * Add CSeqSearch - a nucleotide search utility
  1916. *
  1917. * Revision 1.16  2002/11/12 20:00:25  ucko
  1918. * +SourceToProduct, ProductToSource, SRelLoc
  1919. *
  1920. * Revision 1.15  2002/10/23 19:22:39  ucko
  1921. * Move the FASTA reader from objects/util/sequence.?pp to
  1922. * objects/seqset/Seq_entry.?pp because it doesn't need the OM.
  1923. *
  1924. * Revision 1.14  2002/10/23 18:23:59  ucko
  1925. * Clean up #includes.
  1926. * Add a FASTA reader (known to compile, but not otherwise tested -- take care)
  1927. *
  1928. * Revision 1.13  2002/10/23 16:41:12  clausen
  1929. * Fixed warning in WorkShop53
  1930. *
  1931. * Revision 1.12  2002/10/23 15:33:50  clausen
  1932. * Fixed local variable scope warnings
  1933. *
  1934. * Revision 1.11  2002/10/08 12:35:37  clausen
  1935. * Fixed bugs in GetStrand(), ChangeSeqId() & SeqLocCheck()
  1936. *
  1937. * Revision 1.10  2002/10/07 17:11:16  ucko
  1938. * Fix usage of ERR_POST (caught by KCC)
  1939. *
  1940. * Revision 1.9  2002/10/03 18:44:09  clausen
  1941. * Removed extra whitespace
  1942. *
  1943. * Revision 1.8  2002/10/03 16:33:55  clausen
  1944. * Added functions needed by validate
  1945. *
  1946. * Revision 1.7  2002/09/13 15:30:43  ucko
  1947. * Change resize(0) to erase() at Denis's suggestion.
  1948. *
  1949. * Revision 1.6  2002/09/13 14:28:34  ucko
  1950. * string::clear() doesn't exist under g++ 2.95, so use resize(0) instead. :-/
  1951. *
  1952. * Revision 1.5  2002/09/12 21:39:13  kans
  1953. * added CCdregion_translate and CCdregion_translate
  1954. *
  1955. * Revision 1.4  2002/09/03 21:27:04  grichenk
  1956. * Replaced bool arguments in CSeqVector constructor and getters
  1957. * with enums.
  1958. *
  1959. * Revision 1.3  2002/08/27 21:41:15  ucko
  1960. * Add CFastaOstream.
  1961. *
  1962. * Revision 1.2  2002/06/07 16:11:09  ucko
  1963. * Move everything into the "sequence" namespace.
  1964. * Drop the anonymous-namespace business; "sequence" should provide
  1965. * enough protection, and anonymous namespaces ironically interact poorly
  1966. * with WorkShop's caching when rebuilding shared libraries.
  1967. *
  1968. * Revision 1.1  2002/06/06 18:41:41  clausen
  1969. * Initial version
  1970. *
  1971. * ===========================================================================
  1972. */