NCBI C++ ToolKit
loc_edit.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

00001 /*  $Id: loc_edit.cpp 64337 2014-09-05 12:33:55Z asztalos $
00002 * ===========================================================================
00003 *
00004 *                            PUBLIC DOMAIN NOTICE
00005 *               National Center for Biotechnology Information
00006 *
00007 *  This software/database is a "United States Government Work" under the
00008 *  terms of the United States Copyright Act.  It was written as part of
00009 *  the author's official duties as a United States Government employee and
00010 *  thus cannot be copyrighted.  This software/database is freely available
00011 *  to the public for use. The National Library of Medicine and the U.S.
00012 *  Government have not placed any restriction on its use or reproduction.
00013 *
00014 *  Although all reasonable efforts have been taken to ensure the accuracy
00015 *  and reliability of the software and data, the NLM and the U.S.
00016 *  Government do not and cannot warrant the performance or results that
00017 *  may be obtained by using this software or data. The NLM and the U.S.
00018 *  Government disclaim all warranties, express or implied, including
00019 *  warranties of performance, merchantability or fitness for any particular
00020 *  purpose.
00021 *
00022 *  Please cite the author in any work or product based on this material.
00023 *
00024 * ===========================================================================
00025 *
00026 * Author: Colleen Bollin, NCBI
00027 *
00028 * File Description:
00029 *   functions for editing and working with locations
00030 */
00031 #include <ncbi_pch.hpp>
00032 #include <corelib/ncbistd.hpp>
00033 #include <corelib/ncbiobj.hpp>
00034 #include <objtools/edit/loc_edit.hpp>
00035 #include <objtools/edit/cds_fix.hpp>
00036 #include <objects/seq/Seq_descr.hpp>
00037 #include <objects/seq/Seqdesc.hpp>
00038 #include <objects/seqfeat/Code_break.hpp>
00039 #include <objects/seqfeat/Cdregion.hpp>
00040 #include <objects/seqfeat/RNA_ref.hpp>
00041 #include <objects/seqfeat/Trna_ext.hpp>
00042 #include <objects/seqloc/Packed_seqint.hpp>
00043 #include <objects/seqloc/Packed_seqpnt.hpp>
00044 #include <objects/seqloc/Seq_bond.hpp>
00045 #include <objects/seqloc/Seq_interval.hpp>
00046 #include <objects/seqloc/Seq_loc_equiv.hpp>
00047 #include <objects/seqloc/Seq_loc_mix.hpp>
00048 #include <objects/seqloc/Seq_point.hpp>
00049 #include <objects/general/Int_fuzz.hpp>
00050 #include <objmgr/bioseq_handle.hpp>
00051 #include <util/sequtil/sequtil_convert.hpp>
00052 #include <objmgr/util/sequence.hpp>
00053 #include <objmgr/seq_vector.hpp>
00054 
00055 BEGIN_NCBI_SCOPE
00056 BEGIN_SCOPE(objects)
00057 BEGIN_SCOPE(edit)
00058 
00059 string PrintBestSeqId(const CSeq_id& sid, CScope& scope) 
00060 {
00061    string best_id(kEmptyStr);
00062 
00063    // Best seq_id
00064    CSeq_id_Handle sid_hl = sequence::GetId(sid, scope, sequence::eGetId_Best);
00065    if (sid_hl) {
00066       CConstRef <CSeq_id> new_id = sid_hl.GetSeqId();
00067       if (new_id) {
00068         best_id = sid_hl.GetSeqId()->AsFastaString();
00069       }
00070    }
00071    else best_id = sid.AsFastaString();
00072 
00073    return best_id;
00074 };
00075 
00076 static const string strand_symbol[] = {"", "", "c","b", "r"};
00077 string PrintSeqIntUseBestID(const CSeq_interval& seq_int, CScope& scope, bool range_only)
00078 {
00079     string location(kEmptyStr);
00080 
00081     // Best seq_id
00082     if (!range_only) {
00083       location = PrintBestSeqId(seq_int.GetId(), scope) + ":";
00084     }
00085 
00086     // strand
00087     ENa_strand 
00088       this_strand 
00089          = (seq_int.CanGetStrand()) ? seq_int.GetStrand(): eNa_strand_unknown;
00090     location += strand_symbol[(int)this_strand];
00091     int from, to;
00092     string lab_from(kEmptyStr), lab_to(kEmptyStr);
00093     if (eNa_strand_minus == this_strand 
00094                                || eNa_strand_both_rev ==  this_strand) {
00095            to = seq_int.GetFrom();
00096            from = seq_int.GetTo();
00097            if (seq_int.CanGetFuzz_to()) {
00098                const CInt_fuzz& f_from = seq_int.GetFuzz_to();
00099                f_from.GetLabel(&lab_from, from, false); 
00100            }
00101            else lab_from = NStr::IntToString(++from);
00102            if (seq_int.CanGetFuzz_from()) {
00103                const CInt_fuzz& f_to = seq_int.GetFuzz_from();
00104                f_to.GetLabel(&lab_to, to); 
00105            }
00106            else lab_to = NStr::IntToString(++to);
00107     }
00108     else {
00109            to = seq_int.GetTo();
00110            from = seq_int.GetFrom();
00111            if (seq_int.CanGetFuzz_from()) {
00112                 const CInt_fuzz& f_from = seq_int.GetFuzz_from();
00113                 f_from.GetLabel(&lab_from, from, false);
00114            }
00115            else lab_from = NStr::IntToString(++from);
00116            if (seq_int.CanGetFuzz_to()) {
00117                const CInt_fuzz& f_to = seq_int.GetFuzz_to();
00118                f_to.GetLabel(&lab_to, to);
00119            }
00120            else lab_to = NStr::IntToString(++to);
00121     }
00122     location += lab_from + "-" + lab_to; 
00123     return location;
00124 };
00125 
00126 string PrintPntAndPntsUseBestID(const CSeq_loc& seq_loc, CScope& scope, bool range_only)
00127 {
00128   string location(kEmptyStr);
00129 
00130    // Best seq_id
00131   if (!range_only) {
00132      if (seq_loc.IsPnt()) {
00133        location = PrintBestSeqId(seq_loc.GetPnt().GetId(), scope) + ":";
00134      }
00135      else if (seq_loc.IsPacked_pnt()) {
00136        location = PrintBestSeqId(seq_loc.GetPacked_pnt().GetId(), scope) + ":";
00137      }
00138   }
00139 
00140   if (!location.empty()) {
00141      string strtmp;
00142      seq_loc.GetLabel(&strtmp);
00143      location += strtmp.substr(strtmp.find(":")+1);
00144   }
00145   return location;
00146 }
00147     
00148 string SeqLocPrintUseBestID(const CSeq_loc& seq_loc, CScope& scope, bool range_only)
00149 {
00150   string location(kEmptyStr);
00151   if (seq_loc.IsInt()) {
00152      location = PrintSeqIntUseBestID(seq_loc.GetInt(), scope, range_only);
00153   } 
00154   else if (seq_loc.IsMix() || seq_loc.IsEquiv()) {
00155      location = "(";
00156      const list <CRef <CSeq_loc> >* seq_loc_ls; 
00157      if (seq_loc.IsMix()) {
00158         seq_loc_ls = &(seq_loc.GetMix().Get());
00159      }
00160      else {
00161         seq_loc_ls = &(seq_loc.GetEquiv().Get());
00162      }
00163      ITERATE (list <CRef <CSeq_loc> >, it, *seq_loc_ls) {
00164         if (it == seq_loc.GetMix().Get().begin()) {
00165            location += SeqLocPrintUseBestID(**it, scope, range_only);
00166         }
00167         else location += SeqLocPrintUseBestID(**it, scope, true);
00168         location += ", ";
00169      }
00170      if (!location.empty()) {
00171         location = location.substr(0, location.size()-2);
00172      }
00173      location += ")"; 
00174   }
00175   else if (seq_loc.IsPacked_int()) {
00176      location = "(";
00177      ITERATE (list <CRef <CSeq_interval> >, it, seq_loc.GetPacked_int().Get()) {
00178         if (it == seq_loc.GetPacked_int().Get().begin()) {
00179            location += PrintSeqIntUseBestID(**it, scope, range_only);
00180         }
00181         else {
00182             location += PrintSeqIntUseBestID(**it, scope, true);
00183         }
00184         location += ", ";
00185      }
00186      if (!location.empty()) {
00187         location = location.substr(0, location.size()-2);
00188      }
00189      location += ")";
00190   }
00191   else if (seq_loc.IsPnt() || seq_loc.IsPacked_pnt()) {
00192      location = PrintPntAndPntsUseBestID(seq_loc, scope, range_only);
00193   }
00194   else if (seq_loc.IsBond()) {
00195      CSeq_loc tmp_loc;
00196      tmp_loc.SetBond().Assign(seq_loc.GetBond().GetA());
00197      location = PrintPntAndPntsUseBestID(tmp_loc, scope, range_only);
00198      if (seq_loc.GetBond().CanGetB()) {
00199        tmp_loc.SetBond().Assign(seq_loc.GetBond().GetB());
00200        location 
00201           += "=" + PrintPntAndPntsUseBestID(tmp_loc, scope, range_only);
00202      } 
00203   }
00204   else {
00205     seq_loc.GetLabel(&location);
00206   }
00207   return location;
00208 }
00209 
00210 
00211 bool s_Is5AtEndOfSeq(const CSeq_loc& loc, CBioseq_Handle bsh)
00212 {
00213     bool rval = false;
00214 
00215     ENa_strand strand = loc.GetStrand();
00216     if (strand == eNa_strand_minus) {
00217         if (bsh && loc.GetStart(eExtreme_Biological) == bsh.GetInst_Length() - 1) {
00218             rval = true;
00219         }
00220     } else {
00221         if (loc.GetStart(eExtreme_Biological) == 0) {
00222             rval = true;
00223         }
00224     }
00225     return rval;
00226 }
00227 
00228 
00229 bool s_Is3AtEndOfSeq(const CSeq_loc& loc, CBioseq_Handle bsh)
00230 {
00231     bool rval = false;
00232     ENa_strand strand = loc.GetStrand();
00233 
00234     if (strand == eNa_strand_minus) {
00235         if (loc.GetStop(eExtreme_Biological) == 0) {
00236             rval = true;
00237         }
00238     } else {
00239         if (bsh && loc.GetStop(eExtreme_Biological) == bsh.GetInst_Length() - 1) {                        
00240             rval = true;
00241         }
00242     }
00243     return rval;
00244 }
00245 
00246 
00247 bool s_Know5WithoutBsh(const CSeq_loc& loc)
00248 {
00249     ENa_strand strand = loc.GetStrand();
00250 
00251     if (strand == eNa_strand_minus) {
00252         return false;
00253     } else {
00254         return true;
00255     }
00256 }
00257 
00258 
00259 bool s_Know3WithoutBsh(const CSeq_loc& loc)
00260 {
00261     ENa_strand strand = loc.GetStrand();
00262 
00263     if (strand == eNa_strand_minus) {
00264         return true;
00265     } else {
00266         return false;
00267     }
00268 }
00269 
00270 
00271 bool CLocationEditPolicy::Interpret5Policy
00272 (const CSeq_feat& orig_feat, 
00273  CScope& scope, 
00274  bool& do_set_5_partial, 
00275  bool& do_clear_5_partial) const
00276 {
00277     do_set_5_partial = false;
00278     do_clear_5_partial = false;
00279     const CSeq_loc& loc = orig_feat.GetLocation();
00280     CBioseq_Handle bsh = scope.GetBioseqHandle(loc);
00281 
00282     switch (m_PartialPolicy5) {
00283         case ePartialPolicy_eNoChange:
00284             // do nothing
00285             break;
00286         case ePartialPolicy_eSet:
00287             if (!orig_feat.GetLocation().IsPartialStart(eExtreme_Biological)) {
00288                 do_set_5_partial = true;
00289             } else if (m_Extend5 && !s_Is5AtEndOfSeq(loc, bsh)
00290                        && (bsh || s_Know5WithoutBsh(loc))) {
00291                 do_set_5_partial = true;
00292             }
00293             break;
00294         case ePartialPolicy_eSetAtEnd:
00295             if (s_Is5AtEndOfSeq(loc, bsh) 
00296                 && !orig_feat.GetLocation().IsPartialStart(eExtreme_Biological)
00297                 && (bsh || s_Know5WithoutBsh(loc))) {
00298                 do_set_5_partial = true;
00299             }
00300             break;
00301         case ePartialPolicy_eSetForBadEnd:
00302             if (!orig_feat.GetLocation().IsPartialStart(eExtreme_Biological)
00303                 && orig_feat.GetData().IsCdregion()
00304                 && bsh) {
00305                 string transl_prot;
00306                 try {
00307                     CSeqTranslator::Translate(orig_feat, scope, transl_prot,
00308                                                 false,   // do not include stop codons
00309                                                 false);  // do not remove trailing X/B/Z
00310 
00311                 } catch ( const runtime_error& ) {
00312                 }
00313                 if (!NStr::StartsWith(transl_prot, "M", NStr::eNocase)) {
00314                     do_set_5_partial = true;
00315                 }
00316             }
00317             break;
00318         case ePartialPolicy_eSetForFrame:
00319             if (!orig_feat.GetLocation().IsPartialStart(eExtreme_Biological)
00320                 && orig_feat.GetData().IsCdregion()
00321                 && orig_feat.GetData().GetCdregion().IsSetFrame()
00322                 && orig_feat.GetData().GetCdregion().GetFrame() != CCdregion::eFrame_not_set
00323                 && orig_feat.GetData().GetCdregion().GetFrame() != CCdregion::eFrame_one) {
00324                 do_set_5_partial = true;
00325             }
00326             break;
00327         case ePartialPolicy_eClear:
00328             if (orig_feat.GetLocation().IsPartialStart(eExtreme_Biological)) {
00329                 do_clear_5_partial = true;
00330             }
00331             break;
00332         case ePartialPolicy_eClearNotAtEnd:
00333             if (orig_feat.GetLocation().IsPartialStart(eExtreme_Biological)
00334                 && !s_Is5AtEndOfSeq(orig_feat.GetLocation(), bsh)
00335                 && (bsh || s_Know5WithoutBsh(loc))) {
00336                 do_clear_5_partial = true;
00337             }
00338             break;
00339         case ePartialPolicy_eClearForGoodEnd:
00340             if (orig_feat.GetLocation().IsPartialStart(eExtreme_Biological)
00341                 && orig_feat.GetData().IsCdregion()
00342                 && bsh) {
00343                 string transl_prot;
00344                 try {
00345                     CSeqTranslator::Translate(orig_feat, scope, transl_prot,
00346                                                 false,   // do not include stop codons
00347                                                 false);  // do not remove trailing X/B/Z
00348 
00349                 } catch ( const runtime_error& ) {
00350                 }
00351                 if (NStr::StartsWith(transl_prot, "M", NStr::eNocase)) {
00352                     do_clear_5_partial = true;
00353                 }
00354             }
00355             break;
00356     }
00357     return do_set_5_partial || do_clear_5_partial;
00358 }
00359 
00360 
00361 bool CLocationEditPolicy::Interpret3Policy
00362 (const CSeq_feat& orig_feat,
00363  CScope& scope,
00364  bool& do_set_3_partial,
00365  bool& do_clear_3_partial) const
00366 {
00367     do_set_3_partial = false;
00368     do_clear_3_partial = false;
00369     
00370     const CSeq_loc& loc = orig_feat.GetLocation();
00371     CBioseq_Handle bsh = scope.GetBioseqHandle(loc);
00372 
00373     switch (m_PartialPolicy3) {
00374         case ePartialPolicy_eNoChange:
00375             // do nothing
00376             break;
00377         case ePartialPolicy_eSet:
00378             if (!orig_feat.GetLocation().IsPartialStop(eExtreme_Biological)) {
00379                 do_set_3_partial = true;
00380             } else if (m_Extend3 && !s_Is3AtEndOfSeq(loc, bsh) && (bsh || s_Know3WithoutBsh(loc))) {
00381                 do_set_3_partial = true;
00382             }
00383             break;
00384         case ePartialPolicy_eSetAtEnd:
00385             if (!orig_feat.GetLocation().IsPartialStop(eExtreme_Biological) 
00386                 && s_Is3AtEndOfSeq(orig_feat.GetLocation(), bsh)
00387                 && (bsh || s_Know3WithoutBsh(loc))) {
00388                 do_set_3_partial = true;
00389             }
00390             break;
00391         case ePartialPolicy_eSetForBadEnd:
00392             if (!orig_feat.GetLocation().IsPartialStop(eExtreme_Biological)
00393                 && orig_feat.GetData().IsCdregion()
00394                 && bsh) {
00395                 string transl_prot;
00396                 try {
00397                     CSeqTranslator::Translate(orig_feat, scope, transl_prot,
00398                                                 true,   // include stop codons
00399                                                 false);  // do not remove trailing X/B/Z
00400 
00401                 } catch ( const runtime_error& ) {
00402                 }
00403                 if (!NStr::EndsWith(transl_prot, "*", NStr::eNocase)) {
00404                     do_set_3_partial = true;
00405                 }
00406             }
00407             break;
00408         case ePartialPolicy_eSetForFrame:
00409             // not allowed for 3' end
00410             break;
00411         case ePartialPolicy_eClear:
00412             if (orig_feat.GetLocation().IsPartialStop(eExtreme_Biological)) {
00413                 do_clear_3_partial = true;
00414             }
00415             break;
00416         case ePartialPolicy_eClearNotAtEnd:
00417             if (orig_feat.GetLocation().IsPartialStop(eExtreme_Biological)
00418                 && !s_Is3AtEndOfSeq(orig_feat.GetLocation(), bsh)
00419                 && (bsh || s_Know3WithoutBsh(loc))) {
00420                 do_clear_3_partial = true;
00421             }
00422             break;
00423         case ePartialPolicy_eClearForGoodEnd:
00424             if (orig_feat.GetLocation().IsPartialStart(eExtreme_Biological)
00425                 && orig_feat.GetData().IsCdregion()
00426                 && bsh) {
00427                 string transl_prot;
00428                 try {
00429                     CSeqTranslator::Translate(orig_feat, scope, transl_prot,
00430                                                 true,   // include stop codons
00431                                                 false);  // do not remove trailing X/B/Z
00432 
00433                 } catch ( const runtime_error& ) {
00434                 }
00435                 if (NStr::EndsWith(transl_prot, "*", NStr::eNocase)) {
00436                     do_clear_3_partial = true;
00437                 }
00438             }
00439             break;
00440     }
00441     return do_set_3_partial || do_clear_3_partial;
00442 }
00443 
00444 
00445 CRef<CSeq_loc> SeqLocExtend(const CSeq_loc& loc, size_t pos, CScope* scope)
00446 {
00447     size_t loc_start = loc.GetStart(eExtreme_Positional);
00448     size_t loc_stop = loc.GetStop(eExtreme_Positional);
00449     bool partial_start = loc.IsPartialStart(eExtreme_Positional);
00450     bool partial_stop = loc.IsPartialStop(eExtreme_Positional);
00451     ENa_strand strand = loc.GetStrand();
00452     CRef<CSeq_loc> new_loc(NULL);
00453 
00454     if (pos < loc_start) {
00455         CRef<CSeq_id> id(new CSeq_id());
00456         id->Assign(*(loc.GetId()));
00457         CRef<CSeq_loc> add(new CSeq_loc(*id, pos, loc_start - 1, strand));
00458         add->SetPartialStart(partial_start, eExtreme_Positional);
00459         new_loc = sequence::Seq_loc_Add(loc, *add, CSeq_loc::fSort | CSeq_loc::fMerge_AbuttingOnly, scope);
00460     } else if (pos > loc_stop) {
00461         CRef<CSeq_id> id(new CSeq_id());
00462         id->Assign(*(loc.GetId()));
00463         CRef<CSeq_loc> add(new CSeq_loc(*id, loc_stop + 1, pos, strand));
00464         add->SetPartialStop(partial_stop, eExtreme_Positional);
00465         new_loc = sequence::Seq_loc_Add(loc, *add, CSeq_loc::fSort | CSeq_loc::fMerge_AbuttingOnly, scope);
00466     }
00467     return new_loc;
00468 }
00469 
00470 
00471 bool CLocationEditPolicy::ApplyPolicyToFeature(CSeq_feat& feat, CScope& scope) const
00472 {
00473     if (m_PartialPolicy5 == ePartialPolicy_eNoChange
00474         && m_PartialPolicy3 == ePartialPolicy_eNoChange
00475         && m_MergePolicy == eMergePolicy_NoChange) {
00476         return false;
00477     }
00478 
00479     bool any_change = false;
00480 
00481     // make changes to 5' end
00482     bool do_set_5_partial = false;
00483     bool do_clear_5_partial = false;
00484     any_change |= Interpret5Policy(feat, scope, do_set_5_partial, do_clear_5_partial);
00485     if (do_set_5_partial) {
00486         feat.SetLocation().SetPartialStart(true, eExtreme_Biological);
00487         if (m_Extend5) {
00488             // extend end
00489             Extend5(feat, scope);
00490         }
00491     } else if (do_clear_5_partial) {
00492         feat.SetLocation().SetPartialStart(false, eExtreme_Biological);
00493     }
00494 
00495     // make changes to 3' end
00496     bool do_set_3_partial = false;
00497     bool do_clear_3_partial = false;
00498     any_change |= Interpret3Policy(feat, scope, do_set_3_partial, do_clear_3_partial);
00499     if (do_set_3_partial) {
00500         feat.SetLocation().SetPartialStop(true, eExtreme_Biological);
00501         if (m_Extend3) {
00502             // extend end
00503             Extend3(feat, scope);
00504         }
00505     } else if (do_clear_3_partial) {
00506         feat.SetLocation().SetPartialStop(false, eExtreme_Biological);
00507     }
00508 
00509     // make merge changes
00510     switch (m_MergePolicy) {
00511         case CLocationEditPolicy::eMergePolicy_Join:
00512             {
00513                 // remove NULLS between, if present
00514                 bool changed = false;
00515                 CRef<CSeq_loc> new_loc = ConvertToJoin(feat.GetLocation(), changed);
00516                 if (changed) {
00517                     feat.SetLocation().Assign(*new_loc);
00518                     any_change = true;
00519                 }                
00520             }
00521             break;
00522         case CLocationEditPolicy::eMergePolicy_Order:
00523             {
00524                 // add NULLS between if not present
00525                 bool changed = false;
00526                 CRef<CSeq_loc> new_loc = ConvertToOrder(feat.GetLocation(), changed);
00527                 if (changed) {
00528                     feat.SetLocation().Assign(*new_loc);
00529                     any_change = true;
00530                 } 
00531             }
00532             break;
00533         case CLocationEditPolicy::eMergePolicy_SingleInterval:
00534             {
00535                 CRef<CSeq_loc> new_loc = sequence::Seq_loc_Merge(feat.GetLocation(), CSeq_loc::fMerge_SingleRange, &scope);
00536                 if (sequence::Compare(*new_loc, feat.GetLocation(), &scope) != sequence::eSame) {
00537                     feat.SetLocation().Assign(*new_loc);
00538                     any_change = true;
00539                 }
00540             }
00541             break;
00542         case CLocationEditPolicy::eMergePolicy_NoChange:
00543             break;
00544     }
00545 
00546     any_change |= AdjustFeaturePartialFlagForLocation(feat);
00547 
00548     return any_change;
00549 }
00550 
00551 
00552 bool CLocationEditPolicy::HasNulls(const CSeq_loc& orig_loc)
00553 {
00554     if (orig_loc.Which() == CSeq_loc::e_Mix) {
00555         ITERATE(CSeq_loc_mix::Tdata, it, orig_loc.GetMix().Get()) {
00556             if ((*it)->IsNull()) {
00557                 return true;
00558             }
00559         }
00560     }
00561     return false;
00562 }
00563 
00564 
00565 CRef<CSeq_loc> CLocationEditPolicy::ConvertToJoin(const CSeq_loc& orig_loc, bool &changed)
00566 {
00567     changed = false;
00568     CRef<CSeq_loc> new_loc(new CSeq_loc());
00569     if (!HasNulls(orig_loc)) {
00570         new_loc->Assign(orig_loc);
00571     } else {
00572         CSeq_loc_CI ci(orig_loc);
00573         new_loc->SetMix();
00574         while (ci) {
00575             CConstRef<CSeq_loc> subloc = ci.GetRangeAsSeq_loc();
00576             if (subloc && !subloc->IsNull()) {
00577                 CRef<CSeq_loc> add(new CSeq_loc());
00578                 add->Assign(*subloc);
00579                 new_loc->SetMix().Set().push_back(add);
00580             }
00581             ++ci;
00582         }
00583         changed = true;
00584     }
00585     return new_loc;
00586 }
00587 
00588 
00589 CRef<CSeq_loc> CLocationEditPolicy::ConvertToOrder(const CSeq_loc& orig_loc, bool &changed)
00590 {
00591     changed = false;
00592     CRef<CSeq_loc> new_loc(new CSeq_loc());
00593     if (HasNulls(orig_loc)) {
00594         new_loc->Assign(orig_loc);
00595         return new_loc;
00596     }
00597     switch(orig_loc.Which()) {
00598         case CSeq_loc::e_not_set:
00599         case CSeq_loc::e_Null:
00600         case CSeq_loc::e_Empty:
00601         case CSeq_loc::e_Whole:
00602         case CSeq_loc::e_Int:
00603         case CSeq_loc::e_Pnt:
00604         case CSeq_loc::e_Bond:
00605         case CSeq_loc::e_Feat:
00606         case CSeq_loc::e_Equiv:
00607             new_loc->Assign(orig_loc);
00608             break;
00609         case CSeq_loc::e_Packed_int:
00610         case CSeq_loc::e_Packed_pnt:
00611         case CSeq_loc::e_Mix:
00612             {
00613                 new_loc->SetMix();
00614                 CSeq_loc_CI ci(orig_loc);
00615                 CRef<CSeq_loc> first(new CSeq_loc());
00616                 first->Assign(*(ci.GetRangeAsSeq_loc()));
00617                 new_loc->SetMix().Set().push_back(first);
00618                 ++ci;
00619                 while (ci) {
00620                     CRef<CSeq_loc> null_loc(new CSeq_loc());
00621                     null_loc->SetNull();
00622                     new_loc->SetMix().Set().push_back(null_loc);
00623                     CRef<CSeq_loc> add(new CSeq_loc());
00624                     add->Assign(*(ci.GetRangeAsSeq_loc()));
00625                     new_loc->SetMix().Set().push_back(add);
00626                     ++ci;
00627                 }
00628                 changed = true;
00629             }
00630             break;
00631 
00632     }
00633     return new_loc;
00634 }
00635 
00636 bool CLocationEditPolicy::Extend5(CSeq_feat& feat, CScope& scope)
00637 {
00638     bool extend = false;
00639     CBioseq_Handle bsh = scope.GetBioseqHandle(feat.GetLocation());
00640     if (bsh || s_Know5WithoutBsh(feat.GetLocation())) {
00641         ENa_strand strand = feat.GetLocation().GetStrand();
00642         size_t start = feat.GetLocation().GetStart(eExtreme_Biological);
00643         int diff = 0;
00644         if (strand == eNa_strand_minus) {                
00645             if (start < bsh.GetInst_Length() - 1) {
00646                 diff = bsh.GetInst_Length() - feat.GetLocation().GetStart(eExtreme_Biological) - 1;
00647                 CRef<CSeq_loc> new_loc = SeqLocExtend(feat.GetLocation(), bsh.GetInst_Length() - 1, &scope);
00648                 if (new_loc) {
00649                     feat.SetLocation().Assign(*new_loc);
00650                     extend = true;
00651                 } else {
00652                     diff = 0;
00653                 }
00654             }
00655         } else  if (start > 0) {
00656             diff = start;
00657             CRef<CSeq_loc> new_loc = SeqLocExtend(feat.GetLocation(), 0, &scope);
00658             if (new_loc) {
00659                 feat.SetLocation().Assign(*new_loc);
00660                 extend = true;
00661             } else {
00662                 diff = 0;
00663             }
00664         }
00665         // adjust frame to maintain consistency
00666         if (diff % 3 > 0 && feat.GetData().IsCdregion()) {
00667             int orig_frame = 1;
00668             if (feat.GetData().GetCdregion().IsSetFrame()) {
00669                 if (feat.GetData().GetCdregion().GetFrame() == CCdregion::eFrame_two) {
00670                     orig_frame = 2;
00671                 } else if (feat.GetData().GetCdregion().GetFrame() == CCdregion::eFrame_three) {
00672                     orig_frame = 3;
00673                 }
00674             }
00675             CCdregion::EFrame new_frame = CCdregion::eFrame_not_set;
00676             switch ((orig_frame + diff % 3) % 3) {
00677                 case 1:
00678                     new_frame = CCdregion::eFrame_not_set;
00679                     break;
00680                 case 2:
00681                     new_frame = CCdregion::eFrame_two;
00682                     break;
00683                 case 0:
00684                     new_frame = CCdregion::eFrame_three;
00685                     break;
00686             }
00687             feat.SetData().SetCdregion().SetFrame(new_frame);
00688         }
00689     }
00690     return extend;
00691 }
00692 
00693 bool CLocationEditPolicy::Extend3(CSeq_feat& feat, CScope& scope)
00694 {
00695     bool extend = false;
00696     CBioseq_Handle bsh = scope.GetBioseqHandle(feat.GetLocation());
00697     if (bsh || s_Know3WithoutBsh(feat.GetLocation())) {
00698         ENa_strand strand = feat.GetLocation().GetStrand();
00699         size_t stop = feat.GetLocation().GetStop(eExtreme_Biological);
00700         if (strand == eNa_strand_minus) {                
00701             if (stop > 0) {
00702                 CRef<CSeq_loc> new_loc = SeqLocExtend(feat.GetLocation(), 0, &scope);
00703                 if (new_loc) {
00704                     feat.SetLocation().Assign(*new_loc);
00705                     extend = true;
00706                 }
00707             }
00708         } else  if (stop < bsh.GetInst_Length() - 1) {
00709             CRef<CSeq_loc> new_loc = SeqLocExtend(feat.GetLocation(), bsh.GetInst_Length() - 1, &scope);
00710             if (new_loc) {
00711                 feat.SetLocation().Assign(*new_loc);
00712                 extend = true;
00713             }
00714         }
00715     }
00716     return extend;
00717 }
00718 
00719 
00720 bool ApplyPolicyToFeature(const CLocationEditPolicy& policy, const CSeq_feat& orig_feat, 
00721     CScope& scope, bool adjust_gene, bool retranslate_cds)
00722 {
00723     CRef<CSeq_feat> new_feat(new CSeq_feat());
00724     new_feat->Assign(orig_feat);
00725 
00726     bool any_change = policy.ApplyPolicyToFeature(*new_feat, scope);
00727     
00728     if (any_change) {
00729         CSeq_feat_Handle fh = scope.GetSeq_featHandle(orig_feat);
00730         // This is necessary, to make sure that we are in "editing mode"
00731         const CSeq_annot_Handle& annot_handle = fh.GetAnnot();
00732         CSeq_entry_EditHandle eh = annot_handle.GetParentEntry().GetEditHandle();
00733         CSeq_feat_EditHandle feh(fh);
00734 
00735         // adjust gene feature
00736         if (adjust_gene) {
00737             CConstRef<CSeq_feat> old_gene = sequence::GetOverlappingGene(orig_feat.GetLocation(), scope);
00738             if (old_gene) {
00739                 size_t feat_start = new_feat->GetLocation().GetStart(eExtreme_Biological);
00740                 size_t feat_stop = new_feat->GetLocation().GetStop(eExtreme_Biological);
00741                 CRef<CSeq_feat> new_gene(new CSeq_feat());
00742                 new_gene->Assign(*old_gene);
00743                 bool gene_change = false;
00744                 // adjust ends of gene to match ends of feature
00745                 CRef<CSeq_loc> new_loc = SeqLocExtend(new_gene->GetLocation(), feat_start, &scope);
00746                 if (new_loc) {
00747                     new_gene->SetLocation().Assign(*new_loc);
00748                     gene_change = true;
00749                 }
00750                 new_loc = SeqLocExtend(new_gene->GetLocation(), feat_stop, &scope);
00751                 if (new_loc) {
00752                     new_gene->SetLocation().Assign(*new_loc);
00753                     gene_change = true;
00754                 }
00755                 if (gene_change) {
00756                     CSeq_feat_Handle gh = scope.GetSeq_featHandle(*old_gene);
00757                     // This is necessary, to make sure that we are in "editing mode"
00758                     const CSeq_annot_Handle& ah = gh.GetAnnot();
00759                     CSeq_entry_EditHandle egh = ah.GetParentEntry().GetEditHandle();
00760                     CSeq_feat_EditHandle geh(gh);
00761                     geh.Replace(*new_gene);                    
00762                 }
00763             }
00764         }
00765         feh.Replace(*new_feat);
00766 
00767         // retranslate or resynch if coding region
00768         if (new_feat->IsSetProduct() && new_feat->GetData().IsCdregion()) {
00769             if (!retranslate_cds || !RetranslateCDS(*new_feat, scope)) {
00770                 AdjustForCDSPartials(*new_feat, scope.GetBioseqHandle(new_feat->GetLocation()).GetSeq_entry_Handle());
00771             }
00772         }
00773     }
00774     return any_change;
00775 }
00776 
00777 
00778 void ReverseComplementLocation(CSeq_interval& interval, CScope& scope)
00779 {
00780     // flip strand
00781     interval.FlipStrand();
00782     if (interval.IsSetId()) {
00783         CBioseq_Handle bsh = scope.GetBioseqHandle(interval.GetId());
00784         if (bsh) {
00785             if (interval.IsSetFrom()) {
00786                 interval.SetFrom(bsh.GetInst_Length() - interval.GetFrom() - 1);
00787             }
00788             if (interval.IsSetTo()) {
00789                 interval.SetTo(bsh.GetInst_Length() - interval.GetTo() - 1);
00790             }
00791 
00792             // reverse from and to
00793             if (interval.IsSetFrom()) {
00794                 TSeqPos from = interval.GetFrom();
00795                 if (interval.IsSetTo()) {
00796                     interval.SetFrom(interval.GetTo());
00797                 } else {
00798                     interval.ResetFrom();
00799                 }
00800                 interval.SetTo(from);
00801             } else if (interval.IsSetTo()) {
00802                 interval.SetFrom(interval.GetTo());
00803                 interval.ResetTo();
00804             }
00805 
00806             if (interval.IsSetFuzz_from()) {
00807                 interval.SetFuzz_from().Negate(bsh.GetInst_Length());
00808             }
00809             if (interval.IsSetFuzz_to()) {
00810                 interval.SetFuzz_to().Negate(bsh.GetInst_Length());
00811             }
00812 
00813             // swap fuzz
00814             if (interval.IsSetFuzz_from()) {
00815                 CRef<CInt_fuzz> swap(new CInt_fuzz());
00816                 swap->Assign(interval.GetFuzz_from());
00817                 if (interval.IsSetFuzz_to()) {
00818                     interval.SetFuzz_from().Assign(interval.GetFuzz_to());
00819                 } else {
00820                     interval.ResetFuzz_from();
00821                 }
00822                 interval.SetFuzz_to(*swap);
00823             } else if (interval.IsSetFuzz_to()) {
00824                 interval.SetFuzz_from().Assign(interval.GetFuzz_to());
00825                 interval.ResetFuzz_to();
00826             }
00827         }
00828     }
00829 }
00830 
00831 
00832 void ReverseComplementLocation(CSeq_point& pnt, CScope& scope)
00833 {
00834     // flip strand
00835     pnt.FlipStrand();
00836     if (pnt.IsSetId()) {
00837         CBioseq_Handle bsh = scope.GetBioseqHandle(pnt.GetId());
00838         if (bsh) {
00839             if (pnt.IsSetPoint()) {
00840                 pnt.SetPoint(bsh.GetInst_Length() - pnt.GetPoint() - 1);
00841             }
00842             if (pnt.IsSetFuzz()) {
00843                 pnt.SetFuzz().Negate(bsh.GetInst_Length());
00844             }
00845         }
00846     }
00847 }
00848 
00849 
00850 void ReverseComplementLocation(CPacked_seqpnt& ppnt, CScope& scope)
00851 {
00852     // flip strand
00853     ppnt.FlipStrand();
00854     CBioseq_Handle bsh = scope.GetBioseqHandle(ppnt.GetId());
00855     if (bsh) {
00856         // flip fuzz
00857         if (ppnt.IsSetFuzz()) {
00858             ppnt.SetFuzz().Negate(bsh.GetInst_Length());
00859         }
00860         //complement points
00861         if (ppnt.IsSetPoints()) {
00862             vector<int> new_pnts;
00863             ITERATE(CPacked_seqpnt::TPoints, it, ppnt.SetPoints()) {
00864                 new_pnts.push_back(bsh.GetInst_Length() - *it - 1);
00865             }
00866             ppnt.ResetPoints();
00867             ITERATE(vector<int>, it, new_pnts) {
00868                 ppnt.SetPoints().push_back(*it);
00869             }
00870         }
00871     }
00872 
00873 }
00874 
00875 
00876 void ReverseComplementLocation(CSeq_loc& loc, CScope& scope)
00877 {
00878     switch (loc.Which()) {
00879         case CSeq_loc::e_Empty:
00880         case CSeq_loc::e_Whole:
00881         case CSeq_loc::e_Feat:
00882         case CSeq_loc::e_Null:
00883         case CSeq_loc::e_not_set:
00884             // do nothing
00885             break;
00886         case CSeq_loc::e_Int:
00887             ReverseComplementLocation(loc.SetInt(), scope);
00888             loc.InvalidateCache();
00889             break;
00890         case CSeq_loc::e_Pnt:
00891             ReverseComplementLocation(loc.SetPnt(), scope);
00892             loc.InvalidateCache();
00893             break;
00894         case CSeq_loc::e_Bond:
00895             if (loc.GetBond().IsSetA()) {
00896                 ReverseComplementLocation(loc.SetBond().SetA(), scope);
00897             }
00898             if (loc.GetBond().IsSetB()) {
00899                 ReverseComplementLocation(loc.SetBond().SetB(), scope);
00900             }
00901             loc.InvalidateCache();
00902             break;
00903         case CSeq_loc::e_Mix:
00904             // revcomp individual elements
00905             NON_CONST_ITERATE(CSeq_loc_mix::Tdata, it, loc.SetMix().Set()) {
00906                 ReverseComplementLocation(**it, scope);
00907             }
00908             loc.InvalidateCache();
00909             break;
00910         case CSeq_loc::e_Equiv:
00911             // revcomp individual elements
00912             NON_CONST_ITERATE(CSeq_loc_equiv::Tdata, it, loc.SetEquiv().Set()) {
00913                 ReverseComplementLocation(**it, scope);
00914             }
00915             loc.InvalidateCache();
00916             break;
00917         case CSeq_loc::e_Packed_int:
00918             // revcomp individual elements
00919             NON_CONST_ITERATE(CPacked_seqint::Tdata, it, loc.SetPacked_int().Set()) {
00920                 ReverseComplementLocation(**it, scope);
00921             }
00922             loc.InvalidateCache();
00923             break;
00924         case CSeq_loc::e_Packed_pnt:
00925             ReverseComplementLocation(loc.SetPacked_pnt(), scope);
00926             loc.InvalidateCache();
00927             break;
00928 
00929     }
00930 }
00931 
00932 
00933 void ReverseComplementCDRegion(CCdregion& cdr, CScope& scope)
00934 {
00935     if (cdr.IsSetCode_break()) {
00936         NON_CONST_ITERATE(CCdregion::TCode_break, it, cdr.SetCode_break()) {
00937             if ((*it)->IsSetLoc()) {
00938                 ReverseComplementLocation((*it)->SetLoc(), scope);
00939             }
00940         }
00941     }
00942 }
00943 
00944 
00945 void ReverseComplementTrna(CTrna_ext& trna, CScope& scope)
00946 {
00947     if (trna.IsSetAnticodon()) {
00948         ReverseComplementLocation(trna.SetAnticodon(), scope);
00949     }
00950 }
00951 
00952 
00953 void ReverseComplementFeature(CSeq_feat& feat, CScope& scope)
00954 {
00955     if (feat.IsSetLocation()) {
00956         ReverseComplementLocation(feat.SetLocation(), scope);
00957     }
00958     if (feat.IsSetData()) {
00959         switch (feat.GetData().GetSubtype()) {
00960             case CSeqFeatData::eSubtype_cdregion:
00961                 ReverseComplementCDRegion(feat.SetData().SetCdregion(), scope);
00962                 break;
00963             case CSeqFeatData::eSubtype_tRNA:
00964                 ReverseComplementTrna(feat.SetData().SetRna().SetExt().SetTRNA(), scope);
00965                 break;
00966             default:
00967                 break;
00968         }
00969     }
00970 }
00971 
00972 
00973 bool OkToAdjustLoc(const CSeq_interval& interval, const CSeq_id* seqid)
00974 {
00975     bool rval = true;
00976     if (seqid) {
00977         if (!interval.IsSetId() || interval.GetId().Compare(*seqid) != CSeq_id::e_YES) {
00978             rval = false;
00979         }
00980     }
00981     return rval;
00982 }
00983 
00984 
00985 bool OkToAdjustLoc(const CSeq_point& pnt, const CSeq_id* seqid)
00986 {
00987     bool rval = true;
00988     if (seqid) {
00989         if (!pnt.IsSetId() || pnt.GetId().Compare(*seqid) != CSeq_id::e_YES) {
00990             rval = false;
00991         }
00992     }
00993     return rval;
00994 }
00995 
00996 
00997 bool OkToAdjustLoc(const CPacked_seqpnt& pack, const CSeq_id* seqid)
00998 {
00999     bool rval = true;
01000     if (seqid) {
01001         if (!pack.IsSetId() || pack.GetId().Compare(*seqid) != CSeq_id::e_YES) {
01002             rval = false;
01003         }
01004     }
01005     return rval;
01006 }
01007 
01008 
01009 void NormalizeLoc(CSeq_loc& loc)
01010 {
01011     switch (loc.Which()) {
01012         case CSeq_loc::e_Equiv:
01013             {{
01014                 CSeq_loc::TEquiv::Tdata::iterator it = loc.SetEquiv().Set().begin();
01015                 while (it != loc.SetEquiv().Set().end()) {
01016                     NormalizeLoc(**it);
01017                     if (loc.Which() == CSeq_loc::e_not_set) {
01018                         it = loc.SetEquiv().Set().erase(it);
01019                     } else {
01020                         ++it;
01021                     }
01022                 }
01023 
01024                 // if only one, make regular loc
01025                 if (loc.GetEquiv().Get().size() == 1) {
01026                     CRef<CSeq_loc> sub(new CSeq_loc());
01027                     sub->Assign(*(loc.GetEquiv().Get().front()));
01028                     loc.Assign(*sub);
01029                 } else if (loc.GetEquiv().Get().size() == 0) {
01030                     // no sub intervals, reset
01031                     loc.Reset();
01032                 }                
01033             }}
01034             break;
01035         case CSeq_loc::e_Mix:
01036             {{
01037                 CSeq_loc::TMix::Tdata::iterator it = loc.SetMix().Set().begin();
01038                 while (it != loc.SetMix().Set().end()) {
01039                     NormalizeLoc(**it);
01040                     if (loc.Which() == CSeq_loc::e_not_set) {
01041                         it = loc.SetMix().Set().erase(it);
01042                     } else {
01043                         ++it;
01044                     }
01045                 }
01046 
01047                 // if only one, make regular loc
01048                 if (loc.GetMix().Get().size() == 1) {
01049                     CRef<CSeq_loc> sub(new CSeq_loc());
01050                     sub->Assign(*(loc.GetMix().Get().front()));
01051                     loc.Assign(*sub);
01052                 } else if (loc.GetMix().Get().size() == 0) {
01053                     // no sub intervals, reset
01054                     loc.Reset();
01055                 }                
01056             }}
01057             break;
01058         case CSeq_loc::e_Packed_int:
01059             if (loc.GetPacked_int().Get().size() == 0) {
01060                 loc.Reset();
01061             } else if (loc.GetPacked_int().Get().size() == 1) {
01062                 CRef<CSeq_interval> sub(new CSeq_interval());
01063                 sub->Assign(*(loc.GetPacked_int().Get().front()));
01064                 loc.SetInt().Assign(*sub);
01065             }
01066             break;
01067         case CSeq_loc::e_Packed_pnt:
01068             if (loc.GetPacked_pnt().GetPoints().size() == 0) {
01069                 loc.Reset();
01070             } else if (loc.GetPacked_pnt().GetPoints().size() == 1) {
01071                 CRef<CSeq_point> sub(new CSeq_point());
01072                 if (loc.GetPacked_pnt().IsSetStrand()) {
01073                     sub->SetStrand(loc.GetPacked_pnt().GetStrand());
01074                 }
01075                 if (loc.GetPacked_pnt().IsSetId()) {
01076                     sub->SetId().Assign(loc.GetPacked_pnt().GetId());
01077                 }
01078                 if (loc.GetPacked_pnt().IsSetFuzz()) {
01079                     sub->SetFuzz().Assign(loc.GetPacked_pnt().GetFuzz());
01080                 }
01081                 sub->SetPoint(loc.GetPacked_pnt().GetPoints()[0]);
01082                 loc.SetPnt().Assign(*sub);
01083             }
01084             break;
01085         default:
01086             // do nothing
01087             break;
01088     }
01089 }
01090 
01091 
01092 void SeqLocAdjustForTrim(CSeq_interval& interval, 
01093                          TSeqPos cut_from, TSeqPos cut_to,
01094                          const CSeq_id* seqid,
01095                          bool& bCompleteCut,
01096                          TSeqPos& trim5,
01097                          bool& bAdjusted)
01098 {
01099     if (!OkToAdjustLoc(interval, seqid)) {
01100         return;
01101     }
01102 
01103     // These are required fields
01104     if ( !(interval.CanGetFrom() && interval.CanGetTo()) )
01105     {
01106         return;
01107     }
01108 
01109     // Feature location
01110     TSeqPos feat_from = interval.GetFrom();
01111     TSeqPos feat_to = interval.GetTo();
01112 
01113     // Size of the cut
01114     TSeqPos cut_size = cut_to - cut_from + 1;
01115 
01116     // Case 1: feature is located completely before the cut
01117     if (feat_to < cut_from)
01118     {
01119         // Nothing needs to be done - cut does not affect feature
01120         return;
01121     }
01122 
01123     // Case 2: feature is completely within the cut
01124     if (feat_from >= cut_from && feat_to <= cut_to)
01125     {
01126         // Feature should be deleted
01127         bCompleteCut = true;
01128         trim5 += feat_from - feat_to + 1;
01129         return;
01130     }
01131 
01132     // Case 3: feature is completely past the cut
01133     if (feat_from > cut_to)
01134     {
01135         // Shift the feature by the cut_size
01136         feat_from -= cut_size;
01137         feat_to -= cut_size;
01138         interval.SetFrom(feat_from);
01139         interval.SetTo(feat_to);
01140         bAdjusted = true;
01141         return;
01142     }
01143 
01144     /***************************************************************************
01145      * Cases below are partial overlapping cases
01146     ***************************************************************************/
01147     // Case 4: Cut is completely inside the feature 
01148     //         OR
01149     //         Cut is to the "left" side of the feature (i.e., feat_from is 
01150     //         inside the cut)
01151     //         OR
01152     //         Cut is to the "right" side of the feature (i.e., feat_to is 
01153     //         inside the cut)
01154     if (feat_to > cut_to) {
01155         // Left side cut or cut is completely inside feature
01156         feat_to -= cut_size;
01157     }
01158     else {
01159         // Right side cut
01160         if (interval.IsSetStrand() && interval.GetStrand() == eNa_strand_minus) {
01161             TSeqPos diff = cut_from - 1 - feat_to;
01162             trim5 += diff;
01163         }
01164         feat_to = cut_from - 1;
01165     }
01166 
01167     // Take care of the feat_from from the left side cut case
01168     if (feat_from >= cut_from) {
01169         if (!interval.IsSetStrand() || interval.GetStrand() != eNa_strand_minus) {
01170             TSeqPos diff = cut_to + 1 - feat_from;
01171             trim5 += diff;
01172         }
01173         feat_from = cut_to + 1;
01174         feat_from -= cut_size;
01175     }
01176 
01177     interval.SetFrom(feat_from);
01178     interval.SetTo(feat_to);
01179     bAdjusted = true;
01180 }
01181 
01182 
01183 void SeqLocAdjustForTrim(CPacked_seqint& packint, 
01184                 TSeqPos from, TSeqPos to,
01185                 const CSeq_id* seqid,
01186                 bool& bCompleteCut,
01187                 TSeqPos& trim5,
01188                 bool& bAdjusted)
01189 {
01190     if (packint.IsSet()) {
01191         bool from5 = true;
01192         // Process each interval in the list
01193         CPacked_seqint::Tdata::iterator it;
01194         for (it = packint.Set().begin(); 
01195                 it != packint.Set().end(); ) 
01196         {
01197             bool bDeleted = false;
01198             TSeqPos this_trim = 0;
01199             SeqLocAdjustForTrim(**it, from, to, seqid, 
01200                                 bDeleted, this_trim, bAdjusted);
01201 
01202             if (from5) {
01203                 trim5 += this_trim;
01204             }
01205             // Should interval be deleted from list?
01206             if (bDeleted) {
01207                 it = packint.Set().erase(it);
01208             }
01209             else {
01210                 from5 = false;
01211                 ++it;
01212             }
01213         }
01214         if (packint.Get().empty()) {
01215             packint.Reset();
01216         }
01217     }    
01218     if (!packint.IsSet()) {
01219         bCompleteCut = true;
01220     }
01221 }
01222 
01223 
01224 void SeqLocAdjustForTrim(CSeq_loc_mix& mix, 
01225                 TSeqPos from, TSeqPos to,
01226                 const CSeq_id* seqid,
01227                 bool& bCompleteCut,
01228                 TSeqPos& trim5,
01229                 bool& bAdjusted)
01230 {
01231     if (mix.IsSet()) {
01232         bool from5 = true;
01233         // Process each seqloc in the list
01234         CSeq_loc_mix::Tdata::iterator it;
01235         for (it = mix.Set().begin(); 
01236                 it != mix.Set().end(); ) 
01237         {
01238             bool bDeleted = false;
01239             TSeqPos this_trim = 0;
01240             SeqLocAdjustForTrim(**it, from, to, seqid, bDeleted, this_trim, bAdjusted);
01241 
01242             if (from5) {
01243                 trim5 += this_trim;
01244             }
01245             // Should seqloc be deleted from list?
01246             if (bDeleted) {
01247                 it = mix.Set().erase(it);
01248             }
01249             else {
01250                 from5 = false;
01251                 ++it;
01252             }
01253         }
01254     }
01255     if (!mix.IsSet() || mix.Set().empty()) {
01256         bCompleteCut = true;
01257     }
01258 }
01259 
01260 
01261 void SeqLocAdjustForTrim(CSeq_point& pnt, 
01262                 TSeqPos from, TSeqPos to,
01263                 const CSeq_id* seqid,
01264                 bool& bCompleteCut,
01265                 TSeqPos& trim5,
01266                 bool& bAdjusted)
01267 {
01268     if (!OkToAdjustLoc(pnt, seqid)) {
01269         return;
01270     }
01271 
01272     if (to < pnt.GetPoint()) {
01273         size_t diff = to - from + 1;
01274         pnt.SetPoint(pnt.GetPoint() - diff);
01275         bAdjusted = true;
01276     } else if (from < pnt.GetPoint()) {
01277         bCompleteCut = true;
01278         trim5 += 1;
01279     }
01280 }
01281 
01282 
01283 void SeqLocAdjustForTrim(CPacked_seqpnt& pack, 
01284                 TSeqPos from, TSeqPos to,
01285                 const CSeq_id* seqid,
01286                 bool& bCompleteCut, TSeqPos& trim5, bool& bAdjusted)
01287 {
01288     if (!OkToAdjustLoc(pack, seqid)) {
01289         return;
01290     }
01291 
01292     if (pack.IsSetPoints()) {
01293         bool from5 = true;
01294         CPacked_seqpnt::TPoints::iterator it = pack.SetPoints().begin();
01295         while (it != pack.SetPoints().end()) {
01296             if (to < *it) {
01297                 size_t diff = to - from + 1;
01298                 *it -= diff;
01299                 it++;
01300                 bAdjusted = true;
01301                 from5 = false;
01302             } else if (from < *it) {
01303                 it = pack.SetPoints().erase(it);
01304                 bAdjusted = true;
01305                 if (from5) {
01306                     trim5 += 1;
01307                 }
01308             } else {
01309                 it++;
01310                 from5 = false;
01311             }
01312         }
01313     }
01314     if (pack.SetPoints().empty()) {
01315         bCompleteCut = true;
01316     }
01317 }
01318 
01319 
01320 void SeqLocAdjustForTrim(CSeq_bond& bond, 
01321                 TSeqPos from, TSeqPos to,
01322                 const CSeq_id* seqid,
01323                 bool& bCompleteCut,
01324                 TSeqPos& trim5,
01325                 bool& bAdjusted)
01326 {
01327     bool cutA = false, cutB = false;
01328     if (bond.IsSetA()) {
01329         SeqLocAdjustForTrim(bond.SetA(), from, to, seqid, cutA, trim5, bAdjusted);
01330     } else {
01331         cutA = true;
01332     }
01333 
01334     if (bond.IsSetB()) {
01335         SeqLocAdjustForTrim(bond.SetB(), from, to, seqid, cutB, trim5, bAdjusted);
01336     } else {
01337         cutB = true;
01338     }
01339     if (cutA && cutB) {
01340         bCompleteCut = true;
01341     }
01342 }
01343 
01344 
01345 void SeqLocAdjustForTrim(CSeq_loc_equiv& equiv, 
01346                 TSeqPos from, TSeqPos to,
01347                 const CSeq_id* seqid,                
01348                 bool& bCompleteCut,
01349                 TSeqPos& trim5,
01350                 bool& bAdjusted)
01351 {
01352     TSeqPos max_trim5 = 0;
01353     CSeq_loc_equiv::Tdata::iterator it = equiv.Set().begin();
01354     while (it != equiv.Set().end()) {
01355         bool cut = false;
01356         TSeqPos this_trim5 = 0;
01357         SeqLocAdjustForTrim(**it, from, to, seqid, cut, this_trim5, bAdjusted);
01358         if (this_trim5 > max_trim5) {
01359             max_trim5 = this_trim5;
01360         }
01361         if (cut) {
01362             it = equiv.Set().erase(it);
01363         } else {
01364             it++;
01365         }
01366     }
01367     if (equiv.Set().empty()) {
01368         bCompleteCut = true;
01369     }
01370     trim5 = max_trim5;
01371 }
01372 
01373 
01374 void SeqLocAdjustForTrim(CSeq_loc& loc, 
01375                 TSeqPos from, TSeqPos to,
01376                 const CSeq_id* seqid,
01377                 bool& bCompleteCut,
01378                 TSeqPos& trim5, bool& bAdjusted)
01379 {
01380     // Given a seqloc and a range, cut the seqloc
01381 
01382     switch(loc.Which())
01383     {
01384         // Single interval
01385         case CSeq_loc::e_Int:
01386             SeqLocAdjustForTrim(loc.SetInt(), from, to, seqid, 
01387                                 bCompleteCut, trim5, bAdjusted);
01388             break;
01389 
01390         // Multiple intervals
01391         case CSeq_loc::e_Packed_int:
01392             SeqLocAdjustForTrim(loc.SetPacked_int(), from, to, seqid, bCompleteCut, trim5, bAdjusted);
01393             break;
01394 
01395         // Multiple seqlocs
01396         case CSeq_loc::e_Mix:
01397             SeqLocAdjustForTrim(loc.SetMix(), from, to, seqid, bCompleteCut, trim5, bAdjusted);
01398             break;
01399         case CSeq_loc::e_Pnt:
01400             SeqLocAdjustForTrim(loc.SetPnt(), from, to , seqid, bCompleteCut, trim5, bAdjusted); 
01401             break;
01402         case CSeq_loc::e_Packed_pnt:
01403             SeqLocAdjustForTrim(loc.SetPacked_pnt(), from, to, seqid, bCompleteCut, trim5, bAdjusted);
01404             break;
01405         case CSeq_loc::e_Bond:
01406             SeqLocAdjustForTrim(loc.SetBond(), from, to, seqid, bCompleteCut, trim5, bAdjusted);
01407             break;
01408         case CSeq_loc::e_Equiv:
01409             SeqLocAdjustForTrim(loc.SetEquiv(), from, to, seqid, bCompleteCut, trim5, bAdjusted);
01410             break;
01411         case CSeq_loc::e_Empty:
01412         case CSeq_loc::e_Null:
01413         case CSeq_loc::e_not_set:
01414         case CSeq_loc::e_Whole:
01415         case CSeq_loc::e_Feat:
01416             // no adjustment needeed
01417             break;
01418     }
01419     if (!bCompleteCut) {
01420         NormalizeLoc(loc);
01421     }
01422 }
01423 
01424 
01425 void SeqLocAdjustForInsert(CSeq_interval& interval, 
01426                          TSeqPos insert_from, TSeqPos insert_to,
01427                          const CSeq_id* seqid)
01428 {
01429     if (!OkToAdjustLoc(interval, seqid)) {
01430         return;
01431     }
01432 
01433     // These are required fields
01434     if ( !(interval.CanGetFrom() && interval.CanGetTo()) )
01435     {
01436         return;
01437     }
01438 
01439     // Feature location
01440     TSeqPos feat_from = interval.GetFrom();
01441     TSeqPos feat_to = interval.GetTo();
01442 
01443     // Size of the insert
01444     TSeqPos insert_size = insert_to - insert_from + 1;
01445 
01446     // Case 1: feature is located before the insert
01447     if (feat_to < insert_from)
01448     {
01449         // Nothing needs to be done - cut does not affect feature
01450         return;
01451     }
01452 
01453     // Case 2: feature is located after the insert
01454     if (feat_from > insert_from) {
01455         feat_from += insert_size;
01456         feat_to += insert_size;
01457         interval.SetFrom(feat_from);
01458         interval.SetTo(feat_to);
01459         return;
01460     }
01461 
01462     // Case 3: insert occurs within interval
01463     if (feat_from <= insert_from && feat_to >= insert_from)
01464     {
01465         feat_to += insert_size;
01466         interval.SetTo(feat_to);
01467         return;
01468     }
01469 }
01470 
01471 
01472 void SeqLocAdjustForInsert(CPacked_seqint& packint, 
01473                          TSeqPos insert_from, TSeqPos insert_to,
01474                          const CSeq_id* seqid)
01475 {
01476     if (packint.IsSet()) {
01477         // Process each interval in the list
01478         CPacked_seqint::Tdata::iterator it;
01479         for (it = packint.Set().begin(); 
01480                 it != packint.Set().end(); it++) 
01481         {
01482             SeqLocAdjustForInsert(**it, insert_from, insert_to, seqid);
01483         }
01484     }
01485 }
01486 
01487 
01488 void SeqLocAdjustForInsert(CSeq_loc_mix& mix, 
01489                          TSeqPos insert_from, TSeqPos insert_to,
01490                          const CSeq_id* seqid)
01491 {
01492     if (mix.IsSet()) {
01493         // Process each seqloc in the list
01494         CSeq_loc_mix::Tdata::iterator it;
01495         for (it = mix.Set().begin(); 
01496                 it != mix.Set().end(); it++) 
01497         {
01498             SeqLocAdjustForInsert(**it, insert_from, insert_to, seqid);
01499         }
01500     }
01501 }
01502 
01503 
01504 void SeqLocAdjustForInsert(CSeq_point& pnt, 
01505                          TSeqPos insert_from, TSeqPos insert_to,
01506                          const CSeq_id* seqid)
01507 {
01508     if (!OkToAdjustLoc(pnt, seqid)) {
01509         return;
01510     }
01511     if (!pnt.IsSetPoint()) {
01512         return;
01513     }
01514 
01515     if (insert_from < pnt.GetPoint()) {
01516         size_t diff = insert_to - insert_from + 1;
01517         pnt.SetPoint(pnt.GetPoint() + diff);
01518     }
01519 }
01520 
01521 
01522 void SeqLocAdjustForInsert(CPacked_seqpnt& packpnt, 
01523                 TSeqPos from, TSeqPos to,
01524                 const CSeq_id* seqid)
01525 {
01526     if (!OkToAdjustLoc(packpnt, seqid)) {
01527         return;
01528     }
01529 
01530     CPacked_seqpnt::TPoints::iterator it = packpnt.SetPoints().begin();
01531     while (it != packpnt.SetPoints().end()) {
01532         if (from < *it) {
01533             size_t diff = to - from + 1;
01534             *it += diff;
01535         }
01536         it++;
01537     }
01538 }
01539 
01540 
01541 void SeqLocAdjustForInsert(CSeq_bond& bond, 
01542                 TSeqPos from, TSeqPos to,
01543                 const CSeq_id* seqid)
01544 {
01545     if (bond.IsSetA()) {
01546         SeqLocAdjustForInsert(bond.SetA(), from, to, seqid);
01547     }
01548 
01549     if (bond.IsSetB()) {
01550         SeqLocAdjustForInsert(bond.SetB(), from, to, seqid);
01551     }
01552 }
01553 
01554 
01555 void SeqLocAdjustForInsert(CSeq_loc_equiv& equiv, 
01556                 TSeqPos from, TSeqPos to,
01557                 const CSeq_id* seqid)
01558 {
01559     CSeq_loc_equiv::Tdata::iterator it = equiv.Set().begin();
01560     while (it != equiv.Set().end()) {
01561         SeqLocAdjustForInsert(**it, from, to, seqid);
01562         it++;
01563     }
01564 }
01565 
01566 
01567 void SeqLocAdjustForInsert(CSeq_loc& loc, 
01568                 TSeqPos from, TSeqPos to,
01569                 const CSeq_id* seqid)
01570 {
01571     // Given a seqloc and a range, insert into the seqloc
01572 
01573     switch(loc.Which())
01574     {
01575         // Single interval
01576         case CSeq_loc::e_Int:
01577             SeqLocAdjustForInsert(loc.SetInt(), from, to, seqid);
01578             break;
01579 
01580         // Multiple intervals
01581         case CSeq_loc::e_Packed_int:
01582             SeqLocAdjustForInsert(loc.SetPacked_int(), from, to, seqid);
01583             break;
01584 
01585         // Multiple seqlocs
01586         case CSeq_loc::e_Mix:
01587             SeqLocAdjustForInsert(loc.SetMix(), from, to, seqid);
01588             break;
01589         case CSeq_loc::e_Pnt:
01590             SeqLocAdjustForInsert(loc.SetPnt(), from, to, seqid);
01591             break;
01592 
01593         case CSeq_loc::e_Packed_pnt:
01594             SeqLocAdjustForInsert(loc.SetPacked_pnt(), from, to, seqid);
01595             break;
01596         case CSeq_loc::e_Bond:
01597             SeqLocAdjustForInsert(loc.SetBond(), from, to, seqid);
01598             break;
01599         case CSeq_loc::e_Equiv:
01600             SeqLocAdjustForInsert(loc.SetEquiv(), from, to, seqid);
01601             break;
01602         case CSeq_loc::e_Empty:
01603         case CSeq_loc::e_Null:
01604         case CSeq_loc::e_not_set:
01605         case CSeq_loc::e_Whole:
01606         case CSeq_loc::e_Feat:
01607             // no adjustment needeed
01608             break;
01609     }
01610 }
01611 
01612 
01613 CRef<CSeq_interval> SplitLocationForGap(CSeq_interval& before, 
01614                                         size_t start, size_t stop,
01615                                         const CSeq_id* seqid, bool& cut,
01616                                         unsigned int options)
01617 {
01618     cut = false;
01619     if (!OkToAdjustLoc(before, seqid)) {
01620         return CRef<CSeq_interval>(NULL);
01621     }
01622     // These are required fields
01623     if ( !(before.CanGetFrom() && before.CanGetTo()) )
01624     {
01625         return CRef<CSeq_interval>(NULL);
01626     }
01627 
01628     // Feature location
01629     TSeqPos feat_from = before.GetFrom();
01630     TSeqPos feat_to = before.GetTo();
01631 
01632     CRef<CSeq_interval> after(NULL);
01633     if (feat_to < start) {
01634         // gap completely after location
01635         return after;
01636     }
01637 
01638     if (feat_from > start && !(options & eSplitLocOption_split_in_intron)) {
01639         // if gap completely before location, but not splitting in introns,
01640         // no change
01641         return after;
01642     }
01643 
01644     if (feat_from < start && feat_to > stop) {
01645         // gap entirely in inteval
01646         if (!(options & eSplitLocOption_split_in_exon)) {
01647             return after;
01648         }
01649     }
01650 
01651     if (feat_to > stop) {
01652         after.Reset(new CSeq_interval());
01653         after->Assign(before);
01654         if (stop + 1 > feat_from) {
01655             after->SetFrom(stop + 1);
01656             if (options & eSplitLocOption_make_partial) {
01657                 after->SetFuzz_from().SetLim(CInt_fuzz::eLim_lt);
01658             }
01659         }
01660     } 
01661     if (feat_from < start) {
01662         before.SetTo(start - 1);
01663         if (options & eSplitLocOption_make_partial) {
01664             before.SetFuzz_to().SetLim(CInt_fuzz::eLim_gt);
01665         }
01666     } else {
01667         cut = true;
01668     }
01669     return after;
01670 }
01671 
01672 
01673 void SplitLocationForGap(CSeq_loc::TPacked_int& before_intervals,
01674                          CSeq_loc::TPacked_int& after_intervals,
01675                          size_t start, size_t stop, 
01676                          const CSeq_id* seqid, unsigned int options)
01677 {
01678     if (before_intervals.IsSet()) {
01679         // Process each interval in the list
01680         CPacked_seqint::Tdata::iterator it;
01681         for (it = before_intervals.Set().begin(); 
01682                 it != before_intervals.Set().end(); ) 
01683         {
01684             bool cut = false;
01685             CRef<CSeq_interval> after = SplitLocationForGap(**it, start, stop, seqid, cut, options);
01686 
01687             // Should interval be deleted from list?
01688             if (cut) {
01689                 it = before_intervals.Set().erase(it);
01690             }
01691             else {
01692                 ++it;
01693             }
01694             if (after) {
01695                 after_intervals.Set().push_back(after);
01696                 // from here on, always move intervals to the right to the other loc
01697                 options |= eSplitLocOption_split_in_intron;
01698             }
01699         }
01700     }
01701 }
01702 
01703 
01704 void SplitLocationForGap(CSeq_loc& loc1, CSeq_loc& loc2, 
01705                          size_t start, size_t stop, 
01706                          const CSeq_id* seqid, unsigned int options)
01707 {
01708     // Given a seqloc and a range, place the portion of the location before the range
01709     // into loc1 and the remainder of the location into loc2
01710 
01711     switch(loc1.Which())
01712     {
01713         // Single interval
01714         case CSeq_loc::e_Int:
01715             {{
01716                 bool cut = false;
01717                 CRef<CSeq_interval> after = SplitLocationForGap(loc1.SetInt(), start, stop,
01718                                                                 seqid, cut, options);
01719                 if (cut) {
01720                     loc1.Reset();
01721                 }
01722                 if (after) {
01723                     if (loc2.Which() == CSeq_loc::e_not_set) {
01724                         loc2.SetInt(*after);
01725                     } else {
01726                         CRef<CSeq_loc> add(new CSeq_loc());
01727                         add->SetInt(*after);
01728                         loc2.Add(*add);
01729                     }
01730                 }
01731             }}
01732             break;
01733         // Single point
01734         case CSeq_loc::e_Pnt:
01735             if (OkToAdjustLoc(loc1.GetPnt(), seqid)) {
01736                 if (stop < loc1.GetPnt().GetPoint()) {
01737                     if (loc2.Which() == CSeq_loc::e_not_set) {
01738                         loc2.SetPnt().Assign(loc1.GetPnt());
01739                     } else {
01740                         loc2.Add(loc1);
01741                     }
01742                     loc1.Reset();
01743                 }
01744             }
01745             break;
01746 
01747         // Multiple intervals
01748         case CSeq_loc::e_Packed_int:
01749             {{
01750                 CSeq_loc::TPacked_int& before_intervals = loc1.SetPacked_int();
01751                 CRef<CSeq_loc::TPacked_int> after_intervals(new CSeq_loc::TPacked_int);
01752                 SplitLocationForGap(before_intervals, *after_intervals,
01753                                     start, stop,
01754                                     seqid, options);
01755 
01756                 if (before_intervals.Set().empty()) {
01757                     loc1.Reset();
01758                 }
01759                 if (!after_intervals->Set().empty()) {
01760                     if (loc2.Which() == CSeq_loc::e_not_set) {
01761                         loc2.SetPacked_int().Assign(*after_intervals);
01762                     } else {
01763                         CRef<CSeq_loc> add(new CSeq_loc());
01764                         add->SetPacked_int().Assign(*after_intervals);
01765                         loc2.Add(*add);
01766                     }
01767                 }
01768             }}
01769             break;
01770 
01771         // Multiple seqlocs
01772         case CSeq_loc::e_Mix:
01773             {{
01774                 CSeq_loc_mix& before_mix = loc1.SetMix();
01775                 CRef<CSeq_loc_mix> after_mix(new CSeq_loc_mix);
01776                  if (before_mix.IsSet()) {
01777                     // Process each seqloc in the list
01778                     CSeq_loc_mix::Tdata::iterator it;
01779                     for (it = before_mix.Set().begin(); 
01780                          it != before_mix.Set().end(); ) 
01781                     {
01782                         CRef<CSeq_loc> after(new CSeq_loc());
01783                         SplitLocationForGap(**it, *after, start, stop, seqid, options);
01784                         // Should seqloc be deleted from list?
01785                         if ((*it)->Which() == CSeq_loc::e_not_set) {
01786                             it = before_mix.Set().erase(it);
01787                         }
01788                         else {
01789                             ++it;
01790                         }
01791                         if (after->Which() != CSeq_loc::e_not_set) {
01792                             after_mix->Set().push_back(after);
01793                             // from here on, always move intervals to the right to the other loc
01794                             options |= eSplitLocOption_split_in_intron;
01795                         }
01796                     }
01797 
01798                     // Update the original list
01799                     if (before_mix.Set().empty()) {
01800                         loc1.Reset();
01801                     }
01802                     if (!after_mix->Set().empty()) {
01803                         if (loc2.Which() == CSeq_loc::e_not_set) {
01804                             loc2.SetMix().Assign(*after_mix);
01805                         } else {
01806                             CRef<CSeq_loc> add(new CSeq_loc());
01807                             add->SetMix().Assign(*after_mix);
01808                             loc2.Add(*add);
01809                         }
01810                     }
01811                 }
01812             }}
01813             break;
01814         case CSeq_loc::e_Equiv:
01815              {{
01816                 CSeq_loc_equiv& before_equiv = loc1.SetEquiv();
01817                 CRef<CSeq_loc_equiv> after_equiv(new CSeq_loc_equiv);
01818                  if (before_equiv.IsSet()) {
01819                     // Process each seqloc in the list
01820                     CSeq_loc_equiv::Tdata::iterator it;
01821                     for (it = before_equiv.Set().begin(); 
01822                          it != before_equiv.Set().end(); ) 
01823                     {
01824                         CRef<CSeq_loc> after(new CSeq_loc());
01825                         SplitLocationForGap(**it, *after, start, stop, seqid, options);
01826                         // Should seqloc be deleted from list?
01827                         if ((*it)->Which() == CSeq_loc::e_not_set) {
01828                             it = before_equiv.Set().erase(it);
01829                         }
01830                         else {
01831                             ++it;
01832                         }
01833                         if (after->Which() != CSeq_loc::e_not_set) {
01834                             after_equiv->Set().push_back(after);
01835                         }
01836                     }
01837 
01838                     // Update the original list
01839                     if (before_equiv.Set().empty()) {
01840                         loc1.Reset();
01841                     }
01842                     if (!after_equiv->Set().empty()) {
01843                         if (loc2.Which() == CSeq_loc::e_not_set) {
01844                             loc2.SetMix().Assign(*after_equiv);
01845                         } else {
01846                             CRef<CSeq_loc> add(new CSeq_loc());
01847                             add->SetMix().Assign(*after_equiv);
01848                             loc2.Add(*add);
01849                         }
01850                     }
01851                 }
01852             }}
01853             break;
01854         case CSeq_loc::e_Packed_pnt:
01855             if (OkToAdjustLoc(loc1.GetPacked_pnt(), seqid)) {
01856                 CPacked_seqpnt::TPoints& before_points = loc1.SetPacked_pnt().SetPoints();
01857                 CPacked_seqpnt::TPoints after_points;
01858                 CPacked_seqpnt::TPoints::iterator it = loc1.SetPacked_pnt().SetPoints().begin();
01859                 while (it != loc1.SetPacked_pnt().SetPoints().end()) {
01860                     if (stop < *it) {
01861                         after_points.push_back(*it);
01862                     }
01863                     if (start >= *it) {
01864                         it = before_points.erase(it);
01865                     } else {
01866                         it++;
01867                     }
01868                 }
01869                 if (!after_points.empty()) {
01870                     CRef<CPacked_seqpnt> after(new CPacked_seqpnt());
01871                     after->Assign(loc1.GetPacked_pnt());
01872                     after->SetPoints().assign(after_points.begin(), after_points.end());
01873                     if (loc2.Which() == CSeq_loc::e_not_set) {
01874                         loc2.SetPacked_pnt().Assign(*after);
01875                     } else {
01876                         CRef<CSeq_loc> add(new CSeq_loc());
01877                         add->SetPacked_pnt().Assign(*after);
01878                         loc2.Add(*add);
01879                     }
01880                 }
01881                 if (before_points.empty()) {
01882                     loc1.Reset();
01883                 }
01884             }
01885             break;
01886         case CSeq_loc::e_Empty:
01887         case CSeq_loc::e_Null:
01888         case CSeq_loc::e_not_set:
01889         case CSeq_loc::e_Whole:
01890         case CSeq_loc::e_Feat:
01891         case CSeq_loc::e_Bond:
01892             // no adjustment needeed
01893             break;
01894     }
01895     NormalizeLoc(loc1);
01896     NormalizeLoc(loc2);
01897 }
01898 
01899 
01900 void CdregionAdjustForTrim(CCdregion& cdr,
01901                             TSeqPos from, TSeqPos to,
01902                             const CSeq_id* seqid)
01903 {
01904     CCdregion::TCode_break::iterator it = cdr.SetCode_break().begin();
01905     while (it != cdr.SetCode_break().end()) {
01906         if ((*it)->IsSetLoc()) {
01907             bool cut = false;
01908             bool adjusted = false;
01909             TSeqPos trim5 = 0;
01910             SeqLocAdjustForTrim((*it)->SetLoc(), from, to, seqid, cut, trim5, adjusted);
01911             if (cut) {
01912                 it = cdr.SetCode_break().erase(it);
01913             } else {
01914                 it++;
01915             }
01916         } else {
01917             it++;
01918         }
01919     }
01920     if (cdr.GetCode_break().empty()) {
01921         cdr.ResetCode_break();
01922     }
01923 }
01924 
01925 
01926 void TrnaAdjustForTrim(CTrna_ext& trna,
01927                         TSeqPos from, TSeqPos to,
01928                         const CSeq_id* seqid)
01929 {
01930     if (trna.IsSetAnticodon()) {
01931         bool cut = false;
01932         bool trimmed = false;
01933         TSeqPos trim5 = 0;
01934         SeqLocAdjustForTrim(trna.SetAnticodon(), from, to, seqid, cut, trim5, trimmed);
01935         if (cut) {
01936             trna.ResetAnticodon();
01937         } 
01938     }
01939 }
01940 
01941 
01942 void FeatureAdjustForTrim(CSeq_feat& feat, 
01943                             TSeqPos from, TSeqPos to,
01944                             const CSeq_id* seqid,
01945                             bool& bCompleteCut,
01946                             bool& bTrimmed)
01947 {
01948     TSeqPos trim5 = 0;
01949     SeqLocAdjustForTrim (feat.SetLocation(), from, to, seqid, bCompleteCut, trim5, bTrimmed);
01950     if (bCompleteCut) {
01951         return;
01952     }
01953 
01954     if (feat.IsSetData()) {
01955         switch (feat.GetData().Which()) {
01956             case CSeqFeatData::eSubtype_cdregion:
01957                 CdregionAdjustForTrim(feat.SetData().SetCdregion(), from, to, seqid);
01958                 break;
01959             case CSeqFeatData::eSubtype_tRNA:
01960                 TrnaAdjustForTrim(feat.SetData().SetRna().SetExt().SetTRNA(), from, to, seqid);
01961                 break;
01962             default:
01963                 break;
01964         }
01965     }
01966 }
01967 
01968 
01969 void CdregionAdjustForInsert(CCdregion& cdr,
01970                             TSeqPos from, TSeqPos to,
01971                             const CSeq_id* seqid)
01972 {
01973     CCdregion::TCode_break::iterator it = cdr.SetCode_break().begin();
01974     while (it != cdr.SetCode_break().end()) {
01975         if ((*it)->IsSetLoc()) {
01976             SeqLocAdjustForInsert((*it)->SetLoc(), from, to, seqid);
01977         }
01978         it++;
01979     }
01980     if (cdr.GetCode_break().empty()) {
01981         cdr.ResetCode_break();
01982     }
01983 }
01984 
01985 
01986 void TrnaAdjustForInsert(CTrna_ext& trna,
01987                         TSeqPos from, TSeqPos to,
01988                         const CSeq_id* seqid)
01989 {
01990     if (trna.IsSetAnticodon()) {
01991         SeqLocAdjustForInsert(trna.SetAnticodon(), from, to, seqid); 
01992     }
01993 }
01994 
01995 
01996 void FeatureAdjustForInsert(CSeq_feat& feat, 
01997                             TSeqPos from, TSeqPos to,
01998                             const CSeq_id* seqid)
01999 {
02000     SeqLocAdjustForInsert (feat.SetLocation(), from, to, seqid);
02001 
02002     if (feat.IsSetData()) {
02003         switch (feat.GetData().Which()) {
02004             case CSeqFeatData::eSubtype_cdregion:
02005                 CdregionAdjustForInsert(feat.SetData().SetCdregion(), from, to, seqid);
02006                 break;
02007             case CSeqFeatData::eSubtype_tRNA:
02008                 TrnaAdjustForInsert(feat.SetData().SetRna().SetExt().SetTRNA(), from, to, seqid);
02009                 break;
02010             default:
02011                 break;
02012         }
02013     }
02014 }
02015 
02016 
02017 END_SCOPE(edit)
02018 END_SCOPE(objects)
02019 END_NCBI_SCOPE
02020 
Modified on Fri Sep 19 19:28:16 2014 by modify_doxy.py rev. 426318