00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <ncbi_pch.hpp>
00040 #include <serial/enumvalues.hpp>
00041 #include <objects/general/Int_fuzz.hpp>
00042 #include <objects/seqloc/Seq_point.hpp>
00043 #include <objects/seqloc/Packed_seqint.hpp>
00044 #include <objects/seqloc/Packed_seqpnt.hpp>
00045 #include <objects/seqloc/Seq_loc_mix.hpp>
00046 #include <objects/seqloc/Seq_loc_equiv.hpp>
00047 #include <objects/seqloc/Seq_loc.hpp>
00048 #include <objects/seqfeat/Feat_id.hpp>
00049 #include <objects/misc/error_codes.hpp>
00050 #include <util/range_coll.hpp>
00051 #include <objects/seq/seq_id_handle.hpp>
00052 #include <algorithm>
00053
00054
00055 #define NCBI_USE_ERRCODE_X Objects_SeqLoc
00056
00057
00058 BEGIN_NCBI_SCOPE
00059 BEGIN_objects_SCOPE
00060
00061
00062
00063 CSeq_loc::CSeq_loc(E_Choice index)
00064 {
00065 x_InvalidateCache();
00066 switch ( index ) {
00067 case e_Null:
00068 {
00069 SetNull();
00070 break;
00071 }
00072 case e_Empty:
00073 {
00074 SetEmpty();
00075 break;
00076 }
00077 case e_Whole:
00078 {
00079 SetWhole();
00080 break;
00081 }
00082 case e_Int:
00083 {
00084 SetInt();
00085 break;
00086 }
00087 case e_Packed_int:
00088 {
00089 SetPacked_int();
00090 break;
00091 }
00092 case e_Pnt:
00093 {
00094 SetPnt();
00095 break;
00096 }
00097 case e_Packed_pnt:
00098 {
00099 SetPacked_pnt();
00100 break;
00101 }
00102 case e_Mix:
00103 {
00104 SetMix();
00105 break;
00106 }
00107 case e_Equiv:
00108 {
00109 SetEquiv();
00110 break;
00111 }
00112 case e_Bond:
00113 {
00114 SetBond();
00115 break;
00116 }
00117 case e_Feat:
00118 {
00119 SetFeat();
00120 break;
00121 }
00122 case e_not_set:
00123 default:
00124 break;
00125 }
00126 }
00127
00128
00129 CSeq_loc::CSeq_loc(TId& id, TPoint point, TStrand strand)
00130 {
00131 x_InvalidateCache();
00132 SetPnt(*new CSeq_point(id, point, strand));
00133 }
00134
00135
00136 CSeq_loc::CSeq_loc(TId& id, const TPoints& points, TStrand strand)
00137 {
00138 x_InvalidateCache();
00139 if ( points.size() == 1 ) {
00140 SetPnt(*new CSeq_point(id, points.front(), strand));
00141 } else {
00142 SetPacked_pnt(*new CPacked_seqpnt(id, points, strand));
00143 }
00144 }
00145
00146
00147 CSeq_loc::CSeq_loc(TId& id, TPoint from, TPoint to, TStrand strand)
00148 {
00149 x_InvalidateCache();
00150 SetInt(*new CSeq_interval(id, from, to, strand));
00151 }
00152
00153
00154 CSeq_loc::CSeq_loc(TId& id, TRanges ranges, TStrand strand)
00155 {
00156 x_InvalidateCache();
00157 if ( ranges.size() == 1 ) {
00158 SetInt(*new CSeq_interval(id,
00159 ranges.front().GetFrom(), ranges.front().GetTo(), strand));
00160 } else {
00161 SetPacked_int(*new CPacked_seqint(id, ranges, strand));
00162 }
00163 }
00164
00165
00166
00167 CSeq_loc::~CSeq_loc(void)
00168 {
00169 }
00170
00171
00172 inline
00173 void x_Assign(CInt_fuzz& dst, const CInt_fuzz& src)
00174 {
00175 switch ( src.Which() ) {
00176 case CInt_fuzz::e_not_set:
00177 dst.Reset();
00178 break;
00179 case CInt_fuzz::e_P_m:
00180 dst.SetP_m(src.GetP_m());
00181 break;
00182 case CInt_fuzz::e_Range:
00183 dst.SetRange().SetMin(src.GetRange().GetMin());
00184 dst.SetRange().SetMax(src.GetRange().GetMax());
00185 break;
00186 case CInt_fuzz::e_Pct:
00187 dst.SetPct(src.GetPct());
00188 break;
00189 case CInt_fuzz::e_Lim:
00190 dst.SetLim(src.GetLim());
00191 break;
00192 case CInt_fuzz::e_Alt:
00193 dst.SetAlt() = src.GetAlt();
00194 break;
00195 default:
00196 NCBI_THROW(CException, eUnknown,
00197 "Invalid Int-fuzz variant");
00198 }
00199 }
00200
00201
00202 inline
00203 void x_Assign(CSeq_interval& dst, const CSeq_interval& src)
00204 {
00205 dst.SetFrom(src.GetFrom());
00206 dst.SetTo(src.GetTo());
00207 if ( src.IsSetStrand() ) {
00208 dst.SetStrand(src.GetStrand());
00209 }
00210 else {
00211 dst.ResetStrand();
00212 }
00213 dst.SetId().Assign(src.GetId());
00214 if ( src.IsSetFuzz_from() ) {
00215 x_Assign(dst.SetFuzz_from(), src.GetFuzz_from());
00216 }
00217 else {
00218 dst.ResetFuzz_from();
00219 }
00220 if ( src.IsSetFuzz_to() ) {
00221 x_Assign(dst.SetFuzz_to(), src.GetFuzz_to());
00222 }
00223 else {
00224 dst.ResetFuzz_to();
00225 }
00226 }
00227
00228
00229 inline
00230 void x_Assign(CSeq_point& dst, const CSeq_point& src)
00231 {
00232 dst.SetPoint(src.GetPoint());
00233 if ( src.IsSetStrand() ) {
00234 dst.SetStrand(src.GetStrand());
00235 }
00236 else {
00237 dst.ResetStrand();
00238 }
00239 dst.SetId().Assign(src.GetId());
00240 if ( src.IsSetFuzz() ) {
00241 x_Assign(dst.SetFuzz(), src.GetFuzz());
00242 }
00243 else {
00244 dst.ResetFuzz();
00245 }
00246 }
00247
00248
00249 inline
00250 void x_Assign(CPacked_seqint& dst, const CPacked_seqint& src)
00251 {
00252 CPacked_seqint::Tdata& data = dst.Set();
00253 data.clear();
00254 ITERATE ( CPacked_seqint::Tdata, i, src.Get() ) {
00255 data.push_back(CRef<CSeq_interval>(new CSeq_interval));
00256 x_Assign(*data.back(), **i);
00257 }
00258 }
00259
00260
00261 inline
00262 void x_Assign(CPacked_seqpnt& dst, const CPacked_seqpnt& src)
00263 {
00264 if ( src.IsSetStrand() ) {
00265 dst.SetStrand(src.GetStrand());
00266 }
00267 else {
00268 dst.ResetStrand();
00269 }
00270 dst.SetId().Assign(src.GetId());
00271 if ( src.IsSetFuzz() ) {
00272 x_Assign(dst.SetFuzz(), src.GetFuzz());
00273 }
00274 else {
00275 dst.ResetFuzz();
00276 }
00277 dst.SetPoints() = src.GetPoints();
00278 }
00279
00280
00281 inline
00282 void x_Assign(CSeq_bond& dst, const CSeq_bond& src)
00283 {
00284 x_Assign(dst.SetA(), src.GetA());
00285 if ( src.IsSetB() ) {
00286 x_Assign(dst.SetB(), src.GetB());
00287 }
00288 else {
00289 dst.ResetB();
00290 }
00291 }
00292
00293
00294 inline
00295 void x_Assign(CSeq_loc_mix& dst, const CSeq_loc_mix& src)
00296 {
00297 CSeq_loc_mix::Tdata& data = dst.Set();
00298 data.clear();
00299 ITERATE ( CSeq_loc_mix::Tdata, i, src.Get() ) {
00300 data.push_back(CRef<CSeq_loc>(new CSeq_loc));
00301 data.back()->Assign(**i);
00302 }
00303 }
00304
00305
00306 inline
00307 void x_Assign(CSeq_loc_equiv& dst, const CSeq_loc_equiv& src)
00308 {
00309 CSeq_loc_equiv::Tdata& data = dst.Set();
00310 data.clear();
00311 ITERATE ( CSeq_loc_equiv::Tdata, i, src.Get() ) {
00312 data.push_back(CRef<CSeq_loc>(new CSeq_loc));
00313 data.back()->Assign(**i);
00314 }
00315 }
00316
00317
00318 void CSeq_loc::Assign(const CSerialObject& obj, ESerialRecursionMode how)
00319 {
00320 x_InvalidateCache();
00321 if ( GetTypeInfo() == obj.GetThisTypeInfo() ) {
00322 const CSeq_loc& loc = static_cast<const CSeq_loc&>(obj);
00323 switch ( loc.Which() ) {
00324 case e_not_set:
00325 Reset();
00326 return;
00327 case e_Null:
00328 SetNull();
00329 return;
00330 case e_Empty:
00331 SetEmpty().Assign(loc.GetEmpty());
00332 return;
00333 case e_Whole:
00334 SetWhole().Assign(loc.GetWhole());
00335 return;
00336 case e_Int:
00337 x_Assign(SetInt(), loc.GetInt());
00338 return;
00339 case e_Pnt:
00340 x_Assign(SetPnt(), loc.GetPnt());
00341 return;
00342 case e_Packed_int:
00343 x_Assign(SetPacked_int(), loc.GetPacked_int());
00344 return;
00345 case e_Packed_pnt:
00346 x_Assign(SetPacked_pnt(), loc.GetPacked_pnt());
00347 return;
00348 case e_Mix:
00349 x_Assign(SetMix(), loc.GetMix());
00350 return;
00351 case e_Equiv:
00352 x_Assign(SetEquiv(), loc.GetEquiv());
00353 return;
00354 case e_Bond:
00355 x_Assign(SetBond(), loc.GetBond());
00356 return;
00357 case e_Feat:
00358 SetFeat().Assign(loc.GetFeat());
00359 return;
00360 }
00361 }
00362 CSerialObject::Assign(obj, how);
00363 }
00364
00365
00366 CSeq_loc::TRange CSeq_loc::x_UpdateTotalRange(void) const
00367 {
00368 TRange range = m_TotalRangeCache;
00369 if ( range.GetFrom() == TSeqPos(kDirtyCache) ) {
00370 const CSeq_id* id = 0;
00371 range = x_CalculateTotalRangeCheckId(id);
00372 m_IdCache = id;
00373 m_TotalRangeCache.SetToOpen(range.GetToOpen());
00374 m_TotalRangeCache.SetFrom(range.GetFrom());
00375 }
00376 return range;
00377 }
00378
00379
00380 void CSeq_loc::x_UpdateId(const CSeq_id*& total_id, const CSeq_id* id) const
00381 {
00382 if ( total_id == id ) {
00383 return;
00384 }
00385
00386 if ( !total_id ) {
00387 total_id = id;
00388 } else if ( (id && !total_id->Equals(*id)) || !id ) {
00389 NCBI_THROW(CException, eUnknown, "CSeq_loc -- multiple seq-ids");
00390 }
00391 }
00392
00393
00394
00395
00396
00397
00398 CSeq_loc::TRange CSeq_loc::x_CalculateTotalRangeCheckId(const CSeq_id*& id) const
00399 {
00400 TRange total_range;
00401 switch ( Which() ) {
00402 case e_not_set:
00403 case e_Null:
00404 {
00405
00406 total_range = TRange::GetEmpty();
00407 break;
00408 }
00409 case e_Empty:
00410 {
00411 x_UpdateId(id, &GetEmpty());
00412 total_range = TRange::GetEmpty();
00413 break;
00414 }
00415 case e_Whole:
00416 {
00417 x_UpdateId(id, &GetWhole());
00418 total_range = TRange::GetWhole();
00419 break;
00420 }
00421 case e_Int:
00422 {
00423 const CSeq_interval& loc = GetInt();
00424 x_UpdateId(id, &loc.GetId());
00425 total_range.Set(loc.GetFrom(), loc.GetTo());
00426 break;
00427 }
00428 case e_Pnt:
00429 {
00430 const CSeq_point& pnt = GetPnt();
00431 x_UpdateId(id, &pnt.GetId());
00432 TSeqPos pos = pnt.GetPoint();
00433 total_range.Set(pos, pos);
00434 break;
00435 }
00436 case e_Packed_int:
00437 {
00438
00439 const CPacked_seqint& ints = GetPacked_int();
00440 total_range = TRange::GetEmpty();
00441 ITERATE ( CPacked_seqint::Tdata, ii, ints.Get() ) {
00442 const CSeq_interval& loc = **ii;
00443 x_UpdateId(id, &loc.GetId());
00444 total_range += TRange(loc.GetFrom(), loc.GetTo());
00445 }
00446 break;
00447 }
00448 case e_Packed_pnt:
00449 {
00450 const CPacked_seqpnt& pnts = GetPacked_pnt();
00451 x_UpdateId(id, &pnts.GetId());
00452 total_range = TRange::GetEmpty();
00453 ITERATE( CPacked_seqpnt::TPoints, pi, pnts.GetPoints() ) {
00454 TSeqPos pos = *pi;
00455 total_range += TRange(pos, pos);
00456 }
00457 break;
00458 }
00459 case e_Mix:
00460 {
00461
00462 const CSeq_loc_mix& mix = GetMix();
00463 total_range = TRange::GetEmpty();
00464 ITERATE( CSeq_loc_mix::Tdata, li, mix.Get() ) {
00465
00466 total_range += (*li)->x_CalculateTotalRangeCheckId(id);
00467 }
00468 break;
00469 }
00470 case e_Equiv:
00471 {
00472
00473 const CSeq_loc_equiv::Tdata& equiv = GetEquiv().Get();
00474 total_range = TRange::GetEmpty();
00475 ITERATE( CSeq_loc_equiv::Tdata, li, equiv ) {
00476 total_range += (*li)->x_CalculateTotalRangeCheckId(id);
00477 }
00478 break;
00479 }
00480 case e_Bond:
00481 {
00482
00483 const CSeq_bond& bond = GetBond();
00484 const CSeq_point& pointA = bond.GetA();
00485 x_UpdateId(id, &pointA.GetId());
00486 TSeqPos pos = pointA.GetPoint();
00487 total_range = TRange(pos, pos);
00488 if ( bond.IsSetB() ) {
00489 const CSeq_point& pointB = bond.GetB();
00490 x_UpdateId(id, &pointB.GetId());
00491 pos = pointB.GetPoint();
00492 total_range += TRange(pos, pos);
00493 }
00494 break;
00495 }
00496 case e_Feat:
00497 default:
00498 {
00499 NCBI_THROW(CException, eUnknown,
00500 "CSeq_loc::CalculateTotalRange -- "
00501 "unsupported location type");
00502 }
00503 }
00504
00505 return total_range;
00506 }
00507
00508
00509 bool CSeq_loc::IsSetStrand(EIsSetStrand flag) const
00510 {
00511 switch ( Which() ) {
00512 case e_Int:
00513 return GetInt().IsSetStrand();
00514 case e_Pnt:
00515 return GetPnt().IsSetStrand();
00516 case e_Packed_int:
00517 return GetPacked_int().IsSetStrand(flag);
00518 case e_Packed_pnt:
00519 return GetPacked_pnt().IsSetStrand();
00520 case e_Mix:
00521 return GetMix().IsSetStrand(flag);
00522 case e_Bond:
00523 return GetBond().IsSetStrand(flag);
00524
00525 case e_Equiv:
00526 case e_Feat:
00527 default:
00528 return false;
00529 }
00530 }
00531
00532
00533 ENa_strand CSeq_loc::GetStrand(void) const
00534 {
00535 switch ( Which() ) {
00536 case e_not_set:
00537 case e_Null:
00538 case e_Empty:
00539 return eNa_strand_unknown;
00540 case e_Whole:
00541 return eNa_strand_both;
00542 case e_Int:
00543 return GetInt().IsSetStrand() ? GetInt().GetStrand() : eNa_strand_unknown;
00544 case e_Pnt:
00545 return GetPnt().IsSetStrand() ? GetPnt().GetStrand() : eNa_strand_unknown;
00546 case e_Packed_int:
00547 return GetPacked_int().GetStrand();
00548 case e_Packed_pnt:
00549 return GetPacked_pnt().IsSetStrand() ?
00550 GetPacked_pnt().GetStrand() : eNa_strand_unknown;
00551 case e_Mix:
00552 return GetMix().GetStrand();
00553 case e_Bond:
00554 return GetBond().GetStrand();
00555
00556 case e_Equiv:
00557 case e_Feat:
00558 default:
00559 NCBI_THROW(CException, eUnknown,
00560 "CSeq_loc::GetStrand -- unsupported location type" +
00561 CSeq_loc::SelectionName(Which()));
00562 }
00563 }
00564
00565
00566 TSeqPos CSeq_loc::GetStart(ESeqLocExtremes ext) const
00567 {
00568 switch ( Which() ) {
00569 case e_not_set:
00570 case e_Null:
00571 case e_Empty:
00572 {
00573 return kInvalidSeqPos;
00574 }
00575 case e_Whole:
00576 {
00577 return TRange::GetWhole().GetFrom();
00578 }
00579 case e_Int:
00580 {
00581 return (ext == eExtreme_Biological && IsReverseStrand()) ?
00582 GetInt().GetTo() : GetInt().GetFrom();
00583 }
00584 case e_Pnt:
00585 {
00586 return GetPnt().GetPoint();
00587 }
00588 case e_Packed_int:
00589 {
00590 return GetPacked_int().GetStart(ext);
00591 }
00592 case e_Packed_pnt:
00593 {
00594 return GetPacked_pnt().GetStart(ext);
00595 }
00596 case e_Mix:
00597 {
00598 return GetMix().GetStart(ext);
00599 }
00600 case e_Bond:
00601 {
00602 return GetBond().GetStart(ext);
00603 }
00604
00605 case e_Equiv:
00606 case e_Feat:
00607 default:
00608 {
00609 NCBI_THROW(CException, eUnknown,
00610 "CSeq_loc::GetStart -- "
00611 "unsupported location type");
00612 }
00613 }
00614 }
00615
00616
00617 TSeqPos CSeq_loc::GetStop(ESeqLocExtremes ext) const
00618 {
00619 switch ( Which() ) {
00620 case e_not_set:
00621 case e_Null:
00622 case e_Empty:
00623 {
00624 return kInvalidSeqPos;
00625 }
00626 case e_Whole:
00627 {
00628 return TRange::GetWhole().GetTo();
00629 }
00630 case e_Int:
00631 {
00632 return (ext == eExtreme_Biological && IsReverseStrand()) ?
00633 GetInt().GetFrom() : GetInt().GetTo();
00634 }
00635 case e_Pnt:
00636 {
00637 return GetPnt().GetPoint();
00638 }
00639 case e_Packed_int:
00640 {
00641 return GetPacked_int().GetStop(ext);
00642 }
00643 case e_Packed_pnt:
00644 {
00645 return GetPacked_pnt().GetStop(ext);
00646 }
00647 case e_Mix:
00648 {
00649 return GetMix().GetStop(ext);
00650 }
00651 case e_Bond:
00652 {
00653 return GetBond().GetStop(ext);
00654 }
00655
00656 case e_Equiv:
00657 case e_Feat:
00658 default:
00659 {
00660 NCBI_THROW(CException, eUnknown,
00661 "CSeq_loc::GetStart -- "
00662 "unsupported location type");
00663 }
00664 }
00665 }
00666
00667
00668 TSeqPos CSeq_loc::GetCircularLength(TSeqPos seq_len) const
00669 {
00670 if (seq_len == kInvalidSeqPos) {
00671 return GetTotalRange().GetLength();
00672 }
00673 TSeqPos start = GetStart(eExtreme_Biological);
00674 TSeqPos stop = GetStop (eExtreme_Biological);
00675 bool minus = IsReverseStrand();
00676
00677 if (start < stop) {
00678 return minus ? (seq_len - stop + start + 1) : (stop - start - 1);
00679 } else {
00680 return minus ? (start - stop - 1) : (seq_len - start + stop + 1);
00681 }
00682 }
00683
00684
00685
00686
00687 CSeq_loc_CI::CSeq_loc_CI(void)
00688 : m_Location(0),
00689 m_EmptyFlag(eEmpty_Skip)
00690 {
00691 m_CurLoc = m_LocList.end();
00692 }
00693
00694
00695 CSeq_loc_CI::CSeq_loc_CI(const CSeq_loc& loc,
00696 EEmptyFlag empty_flag,
00697 ESeqLocOrder order)
00698 : m_Location(&loc),
00699 m_EmptyFlag(empty_flag)
00700 {
00701 x_ProcessLocation(loc);
00702 if ( order == eOrder_Biological && loc.IsReverseStrand() ) {
00703 m_LocList.reverse();
00704 }
00705 m_CurLoc = m_LocList.begin();
00706 }
00707
00708
00709 CSeq_loc_CI::CSeq_loc_CI(const CSeq_loc_CI& iter)
00710 {
00711 *this = iter;
00712 }
00713
00714
00715 CSeq_loc_CI::~CSeq_loc_CI()
00716 {
00717 }
00718
00719
00720 CSeq_loc_CI& CSeq_loc_CI::operator= (const CSeq_loc_CI& iter)
00721 {
00722 if (this == &iter)
00723 return *this;
00724 m_LocList.clear();
00725 m_Location = iter.m_Location;
00726 m_EmptyFlag = iter.m_EmptyFlag;
00727 m_CurLoc = m_LocList.end();
00728 ITERATE(TLocList, li, iter.m_LocList) {
00729 TLocList::iterator tmp = m_LocList.insert(m_LocList.end(), *li);
00730 if (iter.m_CurLoc == li)
00731 m_CurLoc = tmp;
00732 }
00733 return *this;
00734 }
00735
00736
00737 void CSeq_loc_CI::x_ThrowNotValid(const char* where) const
00738 {
00739 string msg;
00740 msg += "CSeq_loc_CI::";
00741 msg += where;
00742 msg += " -- iterator is not valid";
00743 NCBI_THROW(CException, eUnknown,
00744 msg);
00745 }
00746
00747 void CSeq_loc_CI::x_ProcessLocation(const CSeq_loc& loc)
00748 {
00749 switch ( loc.Which() ) {
00750 case CSeq_loc::e_not_set:
00751 case CSeq_loc::e_Null:
00752 case CSeq_loc::e_Empty:
00753 {
00754 if (m_EmptyFlag == eEmpty_Allow) {
00755 SLoc_Info info;
00756 if (loc.Which() == CSeq_loc::e_Empty) {
00757 info.m_Id = &loc.GetEmpty();
00758 }
00759 else {
00760 info.m_Id.Reset(new CSeq_id);
00761 }
00762 info.m_Range = TRange::GetEmpty();
00763 info.m_Loc = &loc;
00764 m_LocList.push_back(info);
00765 }
00766 return;
00767 }
00768 case CSeq_loc::e_Whole:
00769 {
00770 SLoc_Info info;
00771 info.m_Id = &loc.GetWhole();
00772 info.m_Range = TRange::GetWhole();
00773 info.m_Loc = &loc;
00774 m_LocList.push_back(info);
00775 return;
00776 }
00777 case CSeq_loc::e_Int:
00778 {
00779 SLoc_Info info;
00780 info.m_Id = &loc.GetInt().GetId();
00781 info.m_Range.Set(loc.GetInt().GetFrom(), loc.GetInt().GetTo());
00782 if ( loc.GetInt().IsSetStrand() ) {
00783 info.SetStrand(loc.GetInt().GetStrand());
00784 }
00785 info.m_Loc = &loc;
00786 if (loc.GetInt().IsSetFuzz_from()) {
00787 info.m_Fuzz.first = &loc.GetInt().GetFuzz_from();
00788 }
00789 if (loc.GetInt().IsSetFuzz_to()) {
00790 info.m_Fuzz.second = &loc.GetInt().GetFuzz_to();
00791 }
00792 m_LocList.push_back(info);
00793 return;
00794 }
00795 case CSeq_loc::e_Pnt:
00796 {
00797 SLoc_Info info;
00798 info.m_Id = &loc.GetPnt().GetId();
00799 info.m_Range.Set(loc.GetPnt().GetPoint(), loc.GetPnt().GetPoint());
00800 if ( loc.GetPnt().IsSetStrand() ) {
00801 info.SetStrand(loc.GetPnt().GetStrand());
00802 }
00803 info.m_Loc = &loc;
00804 if (loc.GetPnt().IsSetFuzz()) {
00805 info.m_Fuzz.first = info.m_Fuzz.second
00806 = &loc.GetPnt().GetFuzz();
00807 }
00808 m_LocList.push_back(info);
00809 return;
00810 }
00811 case CSeq_loc::e_Packed_int:
00812 {
00813 ITERATE ( CPacked_seqint::Tdata, ii, loc.GetPacked_int().Get() ) {
00814 SLoc_Info info;
00815 info.m_Id = &(*ii)->GetId();
00816 info.m_Range.Set((*ii)->GetFrom(), (*ii)->GetTo());
00817 if ( (*ii)->IsSetStrand() ) {
00818 info.SetStrand((*ii)->GetStrand());
00819 }
00820 info.m_Loc = &loc;
00821 if ((*ii)->IsSetFuzz_from()) {
00822 info.m_Fuzz.first = &(*ii)->GetFuzz_from();
00823 }
00824 if ((*ii)->IsSetFuzz_to()) {
00825 info.m_Fuzz.second = &(*ii)->GetFuzz_to();
00826 }
00827 m_LocList.push_back(info);
00828 }
00829 return;
00830 }
00831 case CSeq_loc::e_Packed_pnt:
00832 {
00833 ITERATE ( CPacked_seqpnt::TPoints, pi, loc.GetPacked_pnt().GetPoints() ) {
00834 SLoc_Info info;
00835 info.m_Id = &loc.GetPacked_pnt().GetId();
00836 info.m_Range.Set(*pi, *pi);
00837 if ( loc.GetPacked_pnt().IsSetStrand() ) {
00838 info.SetStrand(loc.GetPacked_pnt().GetStrand());
00839 }
00840 info.m_Loc = &loc;
00841 if (loc.GetPacked_pnt().IsSetFuzz()) {
00842 info.m_Fuzz.first = info.m_Fuzz.second
00843 = &loc.GetPacked_pnt().GetFuzz();
00844 }
00845 m_LocList.push_back(info);
00846 }
00847 return;
00848 }
00849 case CSeq_loc::e_Mix:
00850 {
00851 ITERATE(CSeq_loc_mix::Tdata, li, loc.GetMix().Get()) {
00852 x_ProcessLocation(**li);
00853 }
00854 return;
00855 }
00856 case CSeq_loc::e_Equiv:
00857 {
00858 ITERATE(CSeq_loc_equiv::Tdata, li, loc.GetEquiv().Get()) {
00859 x_ProcessLocation(**li);
00860 }
00861 return;
00862 }
00863 case CSeq_loc::e_Bond:
00864 {
00865 SLoc_Info infoA;
00866 infoA.m_Id = &loc.GetBond().GetA().GetId();
00867 infoA.m_Range.Set(loc.GetBond().GetA().GetPoint(),
00868 loc.GetBond().GetA().GetPoint());
00869 if ( loc.GetBond().GetA().IsSetStrand() ) {
00870 infoA.SetStrand(loc.GetBond().GetA().GetStrand());
00871 }
00872 infoA.m_Loc = &loc;
00873 if (loc.GetBond().GetA().IsSetFuzz()) {
00874 infoA.m_Fuzz.first = infoA.m_Fuzz.second
00875 = &loc.GetBond().GetA().GetFuzz();
00876 }
00877 m_LocList.push_back(infoA);
00878 if ( loc.GetBond().IsSetB() ) {
00879 SLoc_Info infoB;
00880 infoB.m_Id = &loc.GetBond().GetB().GetId();
00881 infoB.m_Range.Set(loc.GetBond().GetB().GetPoint(),
00882 loc.GetBond().GetB().GetPoint());
00883 if ( loc.GetBond().GetB().IsSetStrand() ) {
00884 infoB.SetStrand(loc.GetBond().GetB().GetStrand());
00885 }
00886 infoB.m_Loc = &loc;
00887 if (loc.GetBond().GetB().IsSetFuzz()) {
00888 infoB.m_Fuzz.first = infoB.m_Fuzz.second
00889 = &loc.GetBond().GetB().GetFuzz();
00890 }
00891 m_LocList.push_back(infoB);
00892 }
00893 return;
00894 }
00895 case CSeq_loc::e_Feat:
00896 default:
00897 {
00898 NCBI_THROW(CException, eUnknown,
00899 "CSeq_loc_CI -- unsupported location type");
00900 }
00901 }
00902 }
00903
00904
00905
00906 inline
00907 void s_GetLabel(const CSeq_id& id, string* label)
00908 {
00909 CNcbiOstrstream os;
00910 id.WriteAsFasta(os);
00911 *label += CNcbiOstrstreamToString(os);
00912 }
00913
00914
00915
00916 inline
00917 const CSeq_id* s_GetLabel
00918 (const CSeq_point& pnt,
00919 const CSeq_id* last_id,
00920 string* label)
00921 {
00922
00923 if ( !last_id || !last_id->Match(pnt.GetId()) ) {
00924 s_GetLabel(pnt.GetId(), label);
00925 *label += ":";
00926 }
00927
00928
00929 if (pnt.IsSetStrand()) {
00930 *label += GetTypeInfo_enum_ENa_strand()
00931 ->FindName(pnt.GetStrand(), true);
00932 }
00933
00934 if (pnt.IsSetFuzz()) {
00935
00936 pnt.GetFuzz().GetLabel(label, pnt.GetPoint());
00937 } else {
00938
00939 *label += NStr::IntToString(pnt.GetPoint()+1);
00940 }
00941
00942
00943 last_id = &pnt.GetId();
00944 return last_id;
00945 }
00946
00947
00948
00949 inline
00950 const CSeq_id* s_GetLabel
00951 (const CSeq_interval& itval,
00952 const CSeq_id* last_id,
00953 string* label)
00954 {
00955 if (!last_id || !last_id->Match(itval.GetId())) {
00956 s_GetLabel(itval.GetId(), label);
00957 *label += ":";
00958 }
00959 last_id = &itval.GetId();
00960 if (itval.IsSetStrand()) {
00961 *label += GetTypeInfo_enum_ENa_strand()
00962 ->FindName(itval.GetStrand(), true);
00963 }
00964 if (itval.IsSetStrand() &&
00965 (itval.GetStrand() == eNa_strand_minus ||
00966 itval.GetStrand() == eNa_strand_both_rev)) {
00967 if (itval.IsSetFuzz_to()) {
00968 itval.GetFuzz_to().GetLabel(label, itval.GetTo(), false);
00969 } else {
00970 *label += NStr::IntToString(itval.GetTo()+1);
00971 }
00972 *label += "-";
00973 if (itval.IsSetFuzz_from()) {
00974 itval.GetFuzz_from().GetLabel(label, itval.GetFrom());
00975 } else {
00976 *label += NStr::IntToString(itval.GetFrom()+1);
00977 }
00978 } else {
00979 if (itval.IsSetFuzz_from()) {
00980 itval.GetFuzz_from().GetLabel
00981 (label, itval.GetFrom(), false);
00982 } else {
00983 *label += NStr::IntToString(itval.GetFrom()+1);
00984 }
00985 *label += "-";
00986 if (itval.IsSetFuzz_to()) {
00987 itval.GetFuzz_to().GetLabel(label, itval.GetTo());
00988 } else {
00989 *label += NStr::IntToString(itval.GetTo()+1);
00990 }
00991 }
00992 return last_id;
00993 }
00994
00995
00996
00997 const CSeq_id* s_GetLabel
00998 (const CSeq_loc& loc,
00999 const CSeq_id* last_id,
01000 string* label,
01001 bool first = false);
01002
01003
01004
01005 inline
01006 const CSeq_id* s_GetLabel
01007 (const list<CRef<CSeq_loc> >& loc_list,
01008 const CSeq_id* last_id,
01009 string* label)
01010 {
01011 bool first = true;
01012 ITERATE (list<CRef<CSeq_loc> >, it, loc_list) {
01013
01014
01015 last_id = s_GetLabel(**it, last_id, label, first);
01016 first = false;
01017 }
01018
01019 return last_id;
01020 }
01021
01022
01023
01024 const CSeq_id* s_GetLabel
01025 (const CSeq_loc& loc,
01026 const CSeq_id* last_id,
01027 string* label,
01028 bool first)
01029 {
01030
01031 if (!label) {
01032 return last_id;
01033 }
01034
01035
01036 if (!first) {
01037 *label += ", ";
01038 }
01039
01040
01041
01042 switch (loc.Which()) {
01043 case CSeq_loc::e_Null:
01044 *label += "~";
01045 break;
01046 case CSeq_loc::e_Empty:
01047 *label += "{";
01048 s_GetLabel(loc.GetEmpty(), label);
01049 last_id = &loc.GetEmpty();
01050 *label += "}";
01051 break;
01052 case CSeq_loc::e_Whole:
01053 s_GetLabel(loc.GetWhole(), label);
01054 last_id = &loc.GetWhole();
01055 break;
01056 case CSeq_loc::e_Int:
01057 last_id = s_GetLabel(loc.GetInt(), last_id, label);
01058 break;
01059 case CSeq_loc::e_Packed_int:
01060 {
01061 *label += "(";
01062 bool frst = true;
01063 ITERATE(CPacked_seqint::Tdata, it, loc.GetPacked_int().Get()) {
01064 if (!frst) {
01065 *label += ", ";
01066 }
01067 frst = false;
01068 last_id = s_GetLabel(**it, last_id, label);
01069 }
01070 *label += ")";
01071 break;
01072 }
01073 case CSeq_loc::e_Pnt:
01074 last_id = s_GetLabel(loc.GetPnt(), last_id, label);
01075 break;
01076 case CSeq_loc::e_Packed_pnt:
01077 *label += "(" + loc.GetPacked_pnt().GetId().AsFastaString() + ":";
01078 {{
01079 string str;
01080 ITERATE (CPacked_seqpnt::TPoints, iter,
01081 loc.GetPacked_pnt().GetPoints()) {
01082 if ( !str.empty() ) {
01083 str += ", ";
01084 }
01085 str += NStr::IntToString(*iter);
01086 }
01087 *label += str;
01088 }}
01089 *label += ")";
01090 last_id = &loc.GetPacked_pnt().GetId();
01091 break;
01092 case CSeq_loc::e_Mix:
01093 *label += "[";
01094 last_id = s_GetLabel(loc.GetMix().Get(), last_id, label);
01095 *label += "]";
01096 break;
01097 case CSeq_loc::e_Equiv:
01098 *label += "[";
01099 last_id = s_GetLabel(loc.GetEquiv().Get(), last_id, label);
01100 *label += "]";
01101 break;
01102 case CSeq_loc::e_Bond:
01103 last_id = s_GetLabel(loc.GetBond().GetA(), last_id, label);
01104 *label += "=";
01105 if (loc.GetBond().IsSetB()) {
01106 last_id = s_GetLabel(loc.GetBond().GetB(), last_id, label);
01107 } else {
01108 *label += "?";
01109 }
01110 break;
01111 case CSeq_loc::e_Feat:
01112 *label += "(feat)";
01113 break;
01114 default:
01115 *label += "(?\?)";
01116 break;
01117 }
01118 return last_id;
01119 }
01120
01121
01122 bool CSeq_loc::IsPartialStart(ESeqLocExtremes ext) const
01123 {
01124 switch (Which ()) {
01125 case e_Null :
01126 return true;
01127
01128 case e_Int :
01129 return GetInt().IsPartialStart(ext);
01130
01131 case e_Packed_int :
01132 return GetPacked_int().IsPartialStart(ext);
01133
01134 case e_Pnt :
01135 return GetPnt().IsPartialStart(ext);
01136
01137 case e_Packed_pnt :
01138 return GetPacked_pnt().IsPartialStart(ext);
01139
01140 case e_Mix :
01141 return GetMix().IsPartialStart(ext);
01142
01143 default :
01144 break;
01145 }
01146
01147 return false;
01148 }
01149
01150
01151 bool CSeq_loc::IsPartialStop(ESeqLocExtremes ext) const
01152 {
01153 switch (Which ()) {
01154 case e_Null :
01155 return true;
01156
01157 case e_Int :
01158 return GetInt().IsPartialStop(ext);
01159
01160 case e_Packed_int :
01161 return GetPacked_int().IsPartialStop(ext);
01162
01163 case e_Pnt :
01164 return GetPnt().IsPartialStop(ext);
01165
01166 case e_Packed_pnt :
01167 return GetPacked_pnt().IsPartialStop(ext);
01168
01169 case e_Mix :
01170 return GetMix().IsPartialStop(ext);
01171
01172 default :
01173 break;
01174 }
01175
01176 return false;
01177 }
01178
01179
01180 void CSeq_loc::SetPartialStart(bool val, ESeqLocExtremes ext)
01181 {
01182 if (val == IsPartialStart(ext)) {
01183 return;
01184 }
01185
01186 switch (Which()) {
01187 case e_Int:
01188 SetInt().SetPartialStart(val, ext);
01189 break;
01190
01191 case e_Packed_int :
01192 SetPacked_int().SetPartialStart(val, ext);
01193 break;
01194
01195 case e_Pnt:
01196 SetPnt().SetPartialStart(val, ext);
01197 break;
01198
01199 case e_Packed_pnt:
01200 SetPacked_pnt().SetPartialStart(val, ext);
01201 break;
01202
01203 case e_Mix :
01204 SetMix().SetPartialStart(val, ext);
01205 break;
01206
01207 default :
01208 break;
01209 }
01210 }
01211
01212
01213 void CSeq_loc::SetPartialStop(bool val, ESeqLocExtremes ext)
01214 {
01215 if (val == IsPartialStop(ext)) {
01216 return;
01217 }
01218
01219 switch (Which()) {
01220 case e_Int:
01221 SetInt().SetPartialStop(val, ext);
01222 break;
01223
01224 case e_Packed_int :
01225 SetPacked_int().SetPartialStop(val, ext);
01226 break;
01227
01228 case e_Pnt:
01229 SetPnt().SetPartialStop(val, ext);
01230 break;
01231
01232 case e_Packed_pnt:
01233 SetPacked_pnt().SetPartialStop(val, ext);
01234 break;
01235
01236 case e_Mix:
01237 SetMix().SetPartialStop(val, ext);
01238 break;
01239
01240 default :
01241 break;
01242 }
01243 }
01244
01245
01246 bool CSeq_loc::IsTruncatedStart(ESeqLocExtremes ext) const
01247 {
01248 switch (Which ()) {
01249 case e_Int :
01250 return GetInt().IsTruncatedStart(ext);
01251
01252 case e_Packed_int :
01253 return GetPacked_int().IsTruncatedStart(ext);
01254
01255 case e_Pnt :
01256 return GetPnt().IsTruncatedStart(ext);
01257
01258 case e_Packed_pnt :
01259 return GetPacked_pnt().IsTruncatedStart(ext);
01260
01261 case e_Mix :
01262 return GetMix().IsTruncatedStart(ext);
01263
01264 default :
01265 break;
01266 }
01267
01268 return false;
01269 }
01270
01271
01272 bool CSeq_loc::IsTruncatedStop(ESeqLocExtremes ext) const
01273 {
01274 switch (Which ()) {
01275 case e_Int :
01276 return GetInt().IsTruncatedStop(ext);
01277
01278 case e_Packed_int :
01279 return GetPacked_int().IsTruncatedStop(ext);
01280
01281 case e_Pnt :
01282 return GetPnt().IsTruncatedStop(ext);
01283
01284 case e_Packed_pnt :
01285 return GetPacked_pnt().IsTruncatedStop(ext);
01286
01287 case e_Mix :
01288 return GetMix().IsTruncatedStop(ext);
01289
01290 default :
01291 break;
01292 }
01293
01294 return false;
01295 }
01296
01297
01298 void CSeq_loc::SetTruncatedStart(bool val, ESeqLocExtremes ext)
01299 {
01300 if (val == IsTruncatedStart(ext)) {
01301 return;
01302 }
01303
01304 switch (Which()) {
01305 case e_Int:
01306 SetInt().SetTruncatedStart(val, ext);
01307 break;
01308
01309 case e_Packed_int :
01310 SetPacked_int().SetTruncatedStart(val, ext);
01311 break;
01312
01313 case e_Pnt:
01314 SetPnt().SetTruncatedStart(val, ext);
01315 break;
01316
01317 case e_Packed_pnt:
01318 SetPacked_pnt().SetTruncatedStart(val, ext);
01319 break;
01320
01321 case e_Mix :
01322 SetMix().SetTruncatedStart(val, ext);
01323 break;
01324
01325 default :
01326 break;
01327 }
01328 }
01329
01330
01331 void CSeq_loc::SetTruncatedStop(bool val, ESeqLocExtremes ext)
01332 {
01333 if (val == IsTruncatedStop(ext)) {
01334 return;
01335 }
01336
01337 switch (Which()) {
01338 case e_Int:
01339 SetInt().SetTruncatedStop(val, ext);
01340 break;
01341
01342 case e_Packed_int :
01343 SetPacked_int().SetTruncatedStop(val, ext);
01344 break;
01345
01346 case e_Pnt:
01347 SetPnt().SetTruncatedStop(val, ext);
01348 break;
01349
01350 case e_Packed_pnt:
01351 SetPacked_pnt().SetTruncatedStop(val, ext);
01352 break;
01353
01354 case e_Mix:
01355 SetMix().SetTruncatedStop(val, ext);
01356 break;
01357
01358 default :
01359 break;
01360 }
01361 }
01362
01363
01364
01365
01366
01367 void CSeq_loc::GetLabel(string* label) const
01368 {
01369 s_GetLabel(*this, 0, label, true);
01370 }
01371
01372
01373
01374 void CSeq_loc::SetId(CSeq_id& id)
01375 {
01376 x_InvalidateCache();
01377 switch (Which()) {
01378 case e_Null:
01379 break;
01380
01381 case e_Int:
01382 SetInt().SetId(id);
01383 break;
01384
01385 case e_Pnt:
01386 SetPnt().SetId(id);
01387 break;
01388
01389 case e_Packed_int:
01390 NON_CONST_ITERATE (CPacked_seqint::Tdata, iter, SetPacked_int().Set()) {
01391 (*iter)->SetId(id);
01392 }
01393 break;
01394
01395 case e_Packed_pnt:
01396 SetPacked_pnt().SetId(id);
01397 break;
01398
01399 case e_Mix:
01400 NON_CONST_ITERATE (CSeq_loc_mix::Tdata, iter, SetMix().Set()) {
01401 (*iter)->SetId(id);
01402 }
01403 break;
01404
01405 case e_Whole:
01406 SetWhole(id);
01407 break;
01408
01409 case e_Empty:
01410 SetEmpty(id);
01411 break;
01412
01413 case e_Equiv:
01414 NON_CONST_ITERATE (CSeq_loc_equiv::Tdata, iter, SetEquiv().Set()) {
01415 (*iter)->SetId(id);
01416 }
01417 break;
01418
01419 case e_Bond:
01420 if (GetBond().IsSetA()) {
01421 SetBond().SetA().SetId(id);
01422 }
01423 if (GetBond().IsSetB()) {
01424 SetBond().SetB().SetId(id);
01425 }
01426 break;
01427
01428 case e_Feat:
01429 LOG_POST_X(1, Error
01430 << "unhandled loc type in CSeq_loc::SetId(): e_Feat");
01431 break;
01432
01433 default:
01434 LOG_POST_X(2, Error << "unhandled loc type in CSeq_loc::SetId(): "
01435 << Which());
01436 break;
01437 }
01438 }
01439
01440
01441 void CSeq_loc::x_CheckId(const CSeq_id*& id) const
01442 {
01443 switch ( Which() ) {
01444 case e_not_set:
01445 case e_Null:
01446 {
01447 x_UpdateId(id, 0);
01448 break;
01449 }
01450 case e_Empty:
01451 {
01452 x_UpdateId(id, &GetEmpty());
01453 break;
01454 }
01455 case e_Whole:
01456 {
01457 x_UpdateId(id, &GetWhole());
01458 break;
01459 }
01460 case e_Int:
01461 {
01462 const CSeq_interval& loc = GetInt();
01463 x_UpdateId(id, &loc.GetId());
01464 break;
01465 }
01466 case e_Pnt:
01467 {
01468 const CSeq_point& pnt = GetPnt();
01469 x_UpdateId(id, &pnt.GetId());
01470 break;
01471 }
01472 case e_Packed_int:
01473 {
01474
01475 const CPacked_seqint& ints = GetPacked_int();
01476 ITERATE ( CPacked_seqint::Tdata, ii, ints.Get() ) {
01477 const CSeq_interval& loc = **ii;
01478 x_UpdateId(id, &loc.GetId());
01479 }
01480 break;
01481 }
01482 case e_Packed_pnt:
01483 {
01484 const CPacked_seqpnt& pnts = GetPacked_pnt();
01485 x_UpdateId(id, &pnts.GetId());
01486 break;
01487 }
01488 case e_Mix:
01489 {
01490
01491 const CSeq_loc_mix& mix = GetMix();
01492 ITERATE( CSeq_loc_mix::Tdata, li, mix.Get() ) {
01493 (*li)->CheckId(id);
01494 }
01495 break;
01496 }
01497 case e_Bond:
01498 {
01499 const CSeq_bond& bond = GetBond();
01500 if ( bond.CanGetA() ) {
01501 x_UpdateId(id, &bond.GetA().GetId());
01502 }
01503 if ( bond.CanGetB() ) {
01504 x_UpdateId(id, &bond.GetB().GetId());
01505 }
01506 break;
01507 }
01508 case e_Equiv:
01509 {
01510
01511 ITERATE(CSeq_loc_equiv::Tdata, li, GetEquiv().Get()) {
01512 (*li)->CheckId(id);
01513 }
01514 break;
01515 }
01516 case e_Feat:
01517 default:
01518 {
01519 NCBI_THROW(CException, eUnknown,
01520 "CSeq_loc::CheckId -- "
01521 "unsupported location type");
01522 }
01523 }
01524 }
01525
01526
01527 void CSeq_loc::ChangeToMix(void)
01528 {
01529 switch ( Which() ) {
01530 case e_not_set:
01531 {
01532 SetMix();
01533 break;
01534 }
01535 case e_Mix:
01536 {
01537 break;
01538 }
01539 case e_Packed_int:
01540 {
01541
01542 CRef<CSeq_loc> self(new CSeq_loc);
01543 self->Assign(*this, eShallow);
01544
01545 CSeq_loc_mix& mix = SetMix();
01546 NON_CONST_ITERATE (CPacked_seqint::Tdata, it, self->SetPacked_int().Set()) {
01547 CRef<CSeq_loc> ival(new CSeq_loc);
01548 ival->SetInt(**it);
01549 mix.Set().push_back(ival);
01550 }
01551 break;
01552 }
01553 default:
01554 {
01555 CRef<CSeq_loc> self(new CSeq_loc);
01556 self->Assign(*this, eShallow);
01557 CSeq_loc_mix& mix = SetMix();
01558 mix.AddSeqLoc(*self);
01559 }
01560 }
01561 }
01562
01563
01564 void CSeq_loc::ChangeToPackedInt(void)
01565 {
01566 switch ( Which() ) {
01567 case e_not_set:
01568 {
01569 SetPacked_int();
01570 return;
01571 }
01572 case e_Packed_int:
01573 {
01574 return;
01575 }
01576 case e_Int:
01577 {
01578 CConstRef<CSeq_interval> self(&GetInt());
01579 SetPacked_int().AddInterval(*self);
01580 return;
01581 }
01582 case e_Pnt:
01583 {
01584
01585 CRef<CSeq_interval> new_int(new CSeq_interval);
01586 new_int->SetId().Assign(GetPnt().GetId());
01587 new_int->SetFrom(GetPnt().GetPoint());
01588 new_int->SetTo(GetPnt().GetPoint());
01589 if (GetPnt().IsSetStrand()) {
01590 new_int->SetStrand(GetPnt().GetStrand());
01591 }
01592 if (GetPnt().IsSetFuzz()) {
01593 new_int->SetFuzz_from().Assign(GetPnt().GetFuzz());
01594 new_int->SetFuzz_to().Assign(GetPnt().GetFuzz());
01595 }
01596 SetPacked_int().AddInterval(*new_int);
01597 return;
01598 }
01599 case e_Mix:
01600 {
01601
01602
01603
01604 vector<CRef<CSeq_loc> > sub_locs;
01605 sub_locs.reserve(GetMix().Get().size());
01606 ITERATE (CSeq_loc_mix::Tdata, orig_sub_loc, GetMix().Get()) {
01607 CRef<CSeq_loc> new_sub_loc(new CSeq_loc);
01608 new_sub_loc->Assign(**orig_sub_loc);
01609 new_sub_loc->ChangeToPackedInt();
01610 sub_locs.push_back(new_sub_loc);
01611 }
01612 SetPacked_int();
01613 ITERATE (vector<CRef<CSeq_loc> >, sub_loc, sub_locs) {
01614 copy((*sub_loc)->GetPacked_int().Get().begin(),
01615 (*sub_loc)->GetPacked_int().Get().end(),
01616 back_inserter(SetPacked_int().Set()));
01617 }
01618 return;
01619 }
01620 default:
01621 {
01622 NCBI_THROW(CException, eUnknown,
01623 "Can not convert location to packed-int");
01624 }
01625 }
01626 }
01627
01628
01629 void CSeq_loc::x_ChangeToMix(const CSeq_loc& other)
01630 {
01631 ChangeToMix();
01632 SetMix().AddSeqLoc(other);
01633 }
01634
01635
01636 void CSeq_loc::x_ChangeToPackedInt(const CSeq_interval& other)
01637 {
01638 _ASSERT(IsInt());
01639
01640 ChangeToPackedInt();
01641 SetPacked_int().AddInterval(other);
01642 }
01643
01644
01645 void CSeq_loc::x_ChangeToPackedInt(const CSeq_loc& other)
01646 {
01647 _ASSERT(IsInt());
01648 _ASSERT(other.IsInt() || other.IsPacked_int());
01649
01650 ChangeToPackedInt();
01651
01652 if ( other.IsInt() ) {
01653 SetPacked_int().AddInterval(other.GetInt());
01654 } else {
01655 SetPacked_int().AddIntervals(other.GetPacked_int());
01656 }
01657 }
01658
01659
01660 void CSeq_loc::x_ChangeToPackedPnt(const CSeq_loc& other)
01661 {
01662 _ASSERT(IsPnt());
01663 _ASSERT(other.IsPnt() || other.IsPacked_pnt());
01664
01665 CRef<CSeq_point> pnt(&SetPnt());
01666 CPacked_seqpnt& ppnt = SetPacked_pnt();
01667 if ( pnt->IsSetStrand() ) {
01668 ppnt.SetStrand(pnt->GetStrand());
01669 }
01670 if ( pnt->IsSetId() ) {
01671 ppnt.SetId(pnt->SetId());
01672 }
01673 if ( pnt->IsSetFuzz() ) {
01674 ppnt.SetFuzz(pnt->SetFuzz());
01675 }
01676 ppnt.AddPoint(pnt->GetPoint());
01677
01678 if ( other.IsPnt() ) {
01679 ppnt.AddPoint(other.GetPnt().GetPoint());
01680 } else {
01681 ppnt.AddPoints(other.GetPacked_pnt().GetPoints());
01682 }
01683 }
01684
01685
01686 template<typename T1, typename T2>
01687 bool s_CanAdd(const T1& obj1, const T2& obj2)
01688 {
01689
01690 {{
01691 ENa_strand s1 = obj1.CanGetStrand() ? obj1.GetStrand() : eNa_strand_unknown;
01692 ENa_strand s2 = obj2.CanGetStrand() ? obj2.GetStrand() : eNa_strand_unknown;
01693 if ( s1 != s2 ) {
01694 return false;
01695 }
01696 }}
01697
01698
01699 {{
01700 const CSeq_id* id1 = obj1.CanGetId() ? &obj1.GetId() : 0;
01701 const CSeq_id* id2 = obj2.CanGetId() ? &obj2.GetId() : 0;
01702 if ( ((id1 != id2) && (id1 == 0 || id2 == 0)) ||
01703 !id1->Match(*id2) ) {
01704 return false;
01705 }
01706 }}
01707
01708
01709 {{
01710 const CInt_fuzz* f1 = obj1.CanGetFuzz() ? &obj1.GetFuzz() : 0;
01711 const CInt_fuzz* f2 = obj2.CanGetFuzz() ? &obj2.GetFuzz() : 0;
01712 if ( ((f1 != f2) && (f1 == 0 || f2 == 0)) ||
01713 !f1->Equals(*f2) ) {
01714 return false;
01715 }
01716 }}
01717
01718 return true;
01719 }
01720
01721
01722 bool s_CanAdd(const CSeq_loc& loc1, const CSeq_loc& loc2)
01723 {
01724 switch ( loc1.Which() ) {
01725 case CSeq_loc::e_Pnt:
01726 {
01727 switch ( loc2.Which() ) {
01728 case CSeq_loc::e_Pnt:
01729 return s_CanAdd(loc1.GetPnt(), loc2.GetPnt());
01730 case CSeq_loc::e_Packed_pnt:
01731 return s_CanAdd(loc1.GetPnt(), loc2.GetPacked_pnt());
01732 default:
01733 break;
01734 }
01735 break;
01736 }
01737 case CSeq_loc::e_Packed_pnt:
01738 {
01739 switch ( loc2.Which() ) {
01740 case CSeq_loc::e_Pnt:
01741 return s_CanAdd(loc1.GetPacked_pnt(), loc2.GetPnt());
01742 case CSeq_loc::e_Packed_pnt:
01743 return s_CanAdd(loc1.GetPacked_pnt(), loc2.GetPacked_pnt());
01744 default:
01745 break;
01746 }
01747 break;
01748 }
01749 default:
01750 {
01751 return false;
01752 }
01753 }
01754
01755 return false;
01756 }
01757
01758
01759 void CSeq_loc::Add(const CSeq_loc& other)
01760 {
01761 x_InvalidateCache();
01762 switch ( Which() ) {
01763 case e_not_set:
01764 {
01765 Assign(other);
01766 break;
01767 }
01768 case e_Null:
01769 {
01770
01771 x_ChangeToMix(other);
01772 break;
01773 }
01774 case e_Empty:
01775 {
01776
01777 x_ChangeToMix(other);
01778 break;
01779 }
01780
01781 case e_Whole:
01782 {
01783 x_ChangeToMix(other);
01784 break;
01785 }
01786 case e_Int:
01787 {
01788 if ( other.IsInt() || other.IsPacked_int() ) {
01789 x_ChangeToPackedInt(other);
01790 } else {
01791 x_ChangeToMix(other);
01792 }
01793 }
01794 break;
01795 case e_Pnt:
01796 {
01797 if ( s_CanAdd(*this, other) ) {
01798 x_ChangeToPackedPnt(other);
01799 } else {
01800 x_ChangeToMix(other);
01801 }
01802 break;
01803 }
01804 case e_Packed_int:
01805 {
01806 if ( other.IsInt() ) {
01807 SetPacked_int().AddInterval(other.GetInt());
01808 } else if ( other.IsPacked_int() ) {
01809 SetPacked_int().AddIntervals(other.GetPacked_int());
01810 } else {
01811 x_ChangeToMix(other);
01812 }
01813 break;
01814 }
01815 case e_Packed_pnt:
01816 {
01817 if ( s_CanAdd(*this, other) ) {
01818 if ( other.IsPnt() ) {
01819 SetPacked_pnt().AddPoint(other.GetPnt().GetPoint());
01820 } else if ( other.IsPacked_pnt() ) {
01821 SetPacked_pnt().AddPoints(other.GetPacked_pnt().GetPoints());
01822 }
01823 } else {
01824 x_ChangeToMix(other);
01825 }
01826 break;
01827 }
01828 case e_Mix:
01829 {
01830 SetMix().AddSeqLoc(other);
01831 break;
01832 }
01833 case e_Equiv:
01834 {
01835 SetEquiv().Add(other);
01836 break;
01837 }
01838 case e_Bond:
01839 {
01840 x_ChangeToMix(other);
01841 break;
01842 }
01843 case e_Feat:
01844 default:
01845 {
01846 NCBI_THROW(CException, eUnknown,
01847 "CSeq_loc::Add -- "
01848 "unsupported location type");
01849 }
01850 }
01851 }
01852
01853
01854 void CSeq_loc::FlipStrand(void)
01855 {
01856 switch ( Which() ) {
01857 case e_Int:
01858 SetInt().FlipStrand();
01859 break;
01860 case e_Pnt:
01861 SetPnt().FlipStrand();
01862 break;
01863 case e_Packed_int:
01864 SetPacked_int().FlipStrand();
01865 break;
01866 case e_Packed_pnt:
01867 SetPacked_pnt().FlipStrand();
01868 break;
01869 case e_Mix:
01870 SetMix().FlipStrand();
01871 break;
01872
01873 default:
01874 break;
01875 }
01876 }
01877
01878
01879
01880
01881 class CRangeWithFuzz : public CSeq_loc::TRange
01882 {
01883 public:
01884 typedef CSeq_loc::TRange TParent;
01885 typedef CConstRef<CInt_fuzz> TFuzz;
01886
01887 CRangeWithFuzz(const TParent& rg)
01888 : TParent(rg)
01889 {
01890 }
01891 CRangeWithFuzz(const CSeq_loc_CI& it)
01892 : TParent(it.GetRange()),
01893 m_Fuzz_from(it.GetFuzzFrom()),
01894 m_Fuzz_to(it.GetFuzzTo())
01895 {
01896 }
01897 void ResetFuzzFrom(void) { m_Fuzz_from.Reset(); }
01898 void ResetFuzzTo(void) { m_Fuzz_to.Reset(); }
01899 TFuzz IsSetFuzzFrom(void) const { return m_Fuzz_from; }
01900 TFuzz IsSetFuzzTo(void) const { return m_Fuzz_to; }
01901 const CInt_fuzz& GetFuzzFrom(void) const { return *m_Fuzz_from; }
01902 const CInt_fuzz& GetFuzzTo(void) const { return *m_Fuzz_to; }
01903
01904 void CopyFrom(const CRangeWithFuzz& rg)
01905 {
01906 SetFrom(rg.GetFrom());
01907 m_Fuzz_from = rg.m_Fuzz_from;
01908 }
01909
01910 void CopyTo(const CRangeWithFuzz& rg)
01911 {
01912 SetTo(rg.GetTo());
01913 m_Fuzz_to = rg.m_Fuzz_to;
01914 }
01915
01916 CRangeWithFuzz& operator +=(const CRangeWithFuzz& rg)
01917 {
01918 TParent::position_type old_from = GetFrom();
01919 TParent::position_type old_to = GetTo();
01920 TParent::operator+=(rg);
01921 if (old_from != GetFrom()) {
01922 m_Fuzz_from.Reset(rg.m_Fuzz_from);
01923 }
01924 else if (old_from == rg.GetFrom()) {
01925 ResetFuzzFrom();
01926 }
01927 if (old_to != GetTo()) {
01928 m_Fuzz_to.Reset(rg.m_Fuzz_to);
01929 }
01930 else if (old_to == rg.GetTo()) {
01931 ResetFuzzTo();
01932 }
01933 return *this;
01934 }
01935
01936 CRangeWithFuzz& operator +=(const TParent& rg)
01937 {
01938 TParent::position_type old_from = GetFrom();
01939 TParent::position_type old_to = GetTo();
01940 TParent::operator+=(rg);
01941 if (old_from != GetFrom() || old_from == rg.GetFrom()) {
01942 ResetFuzzFrom();
01943 }
01944 if (old_to != GetTo() || old_to == rg.GetTo()) {
01945 ResetFuzzTo();
01946 }
01947 return *this;
01948 }
01949
01950 private:
01951 TFuzz m_Fuzz_from;
01952 TFuzz m_Fuzz_to;
01953 };
01954
01955
01956 typedef CRangeWithFuzz TRangeWithFuzz;
01957 typedef vector<TRangeWithFuzz> TRanges;
01958 typedef map<CSeq_id_Handle, TRanges> TIdToRangeMap;
01959 typedef CRangeCollection<TSeqPos> TRangeColl;
01960 typedef map<CSeq_id_Handle, TRangeColl> TIdToRangeColl;
01961
01962
01963 class CRange_Less
01964 {
01965 public:
01966 CRange_Less(void) {}
01967
01968 bool operator() (const TRangeWithFuzz& rg1, const TRangeWithFuzz& rg2) const
01969 {
01970 if ( rg1.IsWhole() ) {
01971 return !rg2.IsWhole();
01972 }
01973 if ( rg1.Empty() ) {
01974 return !rg2.Empty() && !rg2.IsWhole();
01975 }
01976 return !rg2.IsWhole() && !rg2.Empty() && rg1 < rg2;
01977 }
01978 };
01979
01980
01981 class CRange_ReverseLess
01982 {
01983 public:
01984 CRange_ReverseLess(void) {}
01985
01986 bool operator() (const TRangeWithFuzz& rg1, const TRangeWithFuzz& rg2) const
01987 {
01988 if ( rg1.IsWhole() ) {
01989 return !rg2.IsWhole();
01990 }
01991 if ( rg1.Empty() ) {
01992 return !rg2.Empty() && !rg2.IsWhole();
01993 }
01994 if ( rg2.IsWhole() || rg2.Empty() ) {
01995 return false;
01996 }
01997 if (rg1.GetTo() != rg2.GetTo()) {
01998 return rg1.GetTo() > rg2.GetTo();
01999 }
02000 return rg1.GetFrom() < rg2.GetFrom();
02001 }
02002 };
02003
02004
02005 inline
02006 bool x_MatchStrand(ENa_strand str1, ENa_strand str2, CSeq_loc::TOpFlags flags)
02007 {
02008 return (flags & CSeq_loc::fStrand_Ignore) != 0 ||
02009 IsReverse(str1) == IsReverse(str2);
02010 }
02011
02012
02013 bool x_MergeRanges(TRangeWithFuzz& rg1, ENa_strand str1,
02014 const TRangeWithFuzz& rg2, ENa_strand str2,
02015 CSeq_loc::TOpFlags flags)
02016 {
02017 if ( !x_MatchStrand(str1, str2, flags) ) {
02018 return false;
02019 }
02020
02021 if ( (flags & CSeq_loc::fMerge_Contained) != 0 ) {
02022 if (rg1.GetFrom() <= rg2.GetFrom() && rg1.GetTo() >= rg2.GetTo()) {
02023
02024 if (rg1.GetFrom() == rg2.GetFrom()) {
02025 rg1.ResetFuzzFrom();
02026 }
02027 if (rg1.GetTo() == rg2.GetTo()) {
02028 rg1.ResetFuzzTo();
02029 }
02030 return true;
02031 }
02032 if (rg1.GetFrom() >= rg2.GetFrom() && rg1.GetTo() <= rg2.GetTo()) {
02033
02034 bool reset_from = rg1.GetFrom() == rg2.GetFrom();
02035 bool reset_to = rg1.GetTo() == rg2.GetTo();
02036 rg1 = rg2;
02037 if (reset_from) {
02038 rg1.ResetFuzzFrom();
02039 }
02040 if (reset_to) {
02041 rg1.ResetFuzzTo();
02042 }
02043 return true;
02044 }
02045 }
02046
02047 if ( (flags & CSeq_loc::fMerge_OverlappingOnly) != 0 &&
02048 rg1.IntersectingWith(rg2) ) {
02049 rg1 += rg2;
02050 return true;
02051 }
02052
02053 if ((flags & CSeq_loc::fMerge_AbuttingOnly) != 0) {
02054 if ( !IsReverse(str1) ) {
02055 if ( rg1.GetToOpen() == rg2.GetFrom() ) {
02056 rg1.CopyTo(rg2);
02057 return true;
02058 }
02059 }
02060 else {
02061 if (rg1.GetFrom() == rg2.GetToOpen()) {
02062 rg1.CopyFrom(rg2);
02063 return true;
02064 }
02065 }
02066 }
02067 return false;
02068 }
02069
02070
02071 void x_PushRange(CSeq_loc& dst,
02072 CSeq_id_Handle idh,
02073 TRangeWithFuzz rg,
02074 ENa_strand strand)
02075 {
02076 if (dst.Which() != CSeq_loc::e_not_set) {
02077 if ( !dst.IsMix() ) {
02078 dst.ChangeToMix();
02079 }
02080 }
02081 if ( !idh ) {
02082
02083 if (dst.IsMix()) {
02084 CRef<CSeq_loc> null_loc(new CSeq_loc);
02085 null_loc->SetNull();
02086 dst.SetMix().Set().push_back(null_loc);
02087 }
02088 else {
02089 dst.SetNull();
02090 }
02091 }
02092 else if ( rg.IsWhole() ) {
02093 if (dst.IsMix()) {
02094 CRef<CSeq_loc> whole(new CSeq_loc);
02095 whole->SetWhole().Assign(*idh.GetSeqId());
02096 dst.SetMix().Set().push_back(whole);
02097 }
02098 else {
02099 dst.SetWhole().Assign(*idh.GetSeqId());
02100 }
02101 }
02102 else if ( rg.Empty() ) {
02103 if (dst.IsMix()) {
02104 CRef<CSeq_loc> empty(new CSeq_loc);
02105 empty->SetEmpty().Assign(*idh.GetSeqId());
02106 dst.SetMix().Set().push_back(empty);
02107 }
02108 else {
02109 dst.SetEmpty().Assign(*idh.GetSeqId());
02110 }
02111 }
02112 else if ( rg.GetLength() == 1 ) {
02113
02114 CRef<CSeq_id> id(new CSeq_id);
02115 id->Assign(*idh.GetSeqId());
02116 CRef<CSeq_point> pnt(new CSeq_point);
02117 pnt->SetId(*id);
02118 pnt->SetPoint(rg.GetFrom());
02119 if (strand != eNa_strand_unknown) {
02120 pnt->SetStrand(strand);
02121 }
02122 if ( rg.IsSetFuzzFrom() ) {
02123 pnt->SetFuzz().Assign(rg.GetFuzzFrom());
02124 }
02125 if (dst.IsMix()) {
02126 CRef<CSeq_loc> pnt_loc(new CSeq_loc);
02127 pnt_loc->SetPnt(*pnt);
02128 dst.SetMix().Set().push_back(pnt_loc);
02129 }
02130 else {
02131 dst.SetPnt(*pnt);
02132 }
02133 }
02134 else {
02135 CRef<CSeq_id> id(new CSeq_id);
02136 id->Assign(*idh.GetSeqId());
02137 if (dst.IsMix()) {
02138 dst.SetMix().AddInterval(*id,
02139 rg.GetFrom(),
02140 rg.GetTo(),
02141 strand);
02142 if ( rg.IsSetFuzzFrom() ) {
02143 dst.SetMix().Set().back()->SetInt().SetFuzz_from()
02144 .Assign(rg.GetFuzzFrom());
02145 }
02146 if ( rg.IsSetFuzzTo() ) {
02147 dst.SetMix().Set().back()->SetInt().SetFuzz_to()
02148 .Assign(rg.GetFuzzTo());
02149 }
02150 }
02151 else {
02152 CRef<CSeq_interval> interval(new CSeq_interval(*id,
02153 rg.GetFrom(),
02154 rg.GetTo(),
02155 strand));
02156 if ( rg.IsSetFuzzFrom() ) {
02157 interval->SetFuzz_from().Assign(rg.GetFuzzFrom());
02158 }
02159 if ( rg.IsSetFuzzTo() ) {
02160 interval->SetFuzz_to().Assign(rg.GetFuzzTo());
02161 }
02162 dst.SetInt(*interval);
02163 }
02164 }
02165 }
02166
02167
02168 void x_SingleRange(CSeq_loc& dst,
02169 const CSeq_loc& src,
02170 ISynonymMapper& syn_mapper)
02171 {
02172
02173 TRangeWithFuzz total_rg(TRangeWithFuzz::GetEmpty());
02174 CSeq_id_Handle first_id;
02175 ENa_strand first_strand = eNa_strand_unknown;
02176 for (CSeq_loc_CI it(src, CSeq_loc_CI::eEmpty_Allow); it; ++it) {
02177 CSeq_id_Handle next_id = syn_mapper.GetBestSynonym(it.GetSeq_id());
02178 if ( !next_id ) {
02179
02180 continue;
02181 }
02182 if ( first_id ) {
02183
02184 if (next_id && first_id != next_id) {
02185 NCBI_THROW(CException, eUnknown,
02186 "Can not merge multi-id seq-loc");
02187 }
02188 }
02189 else {
02190 first_id = next_id;
02191 first_strand = it.GetStrand();
02192 }
02193 total_rg += TRangeWithFuzz(it);
02194 }
02195 if ( first_id ) {
02196 CRef<CSeq_id> id(new CSeq_id);
02197 id->Assign(*first_id.GetSeqId());
02198 CRef<CSeq_interval> interval(new CSeq_interval(*id,
02199 total_rg.GetFrom(),
02200 total_rg.GetTo(),
02201 first_strand));
02202 if ( total_rg.IsSetFuzzFrom() ) {
02203 interval->SetFuzz_from().Assign(total_rg.GetFuzzFrom());
02204 }
02205 if ( total_rg.IsSetFuzzTo() ) {
02206 interval->SetFuzz_to().Assign(total_rg.GetFuzzTo());
02207 }
02208 dst.SetInt(*interval);
02209 }
02210 else {
02211
02212 dst.SetNull();
02213 }
02214 }
02215
02216
02217 void x_RangesToSeq_loc(CSeq_loc& dst,
02218 TIdToRangeMap& id_map,
02219 ENa_strand default_strand,
02220 CSeq_loc::TOpFlags flags)
02221 {
02222
02223 NON_CONST_ITERATE(TIdToRangeMap, id_it, id_map) {
02224 if ( !id_it->first ) {
02225
02226 x_PushRange(dst,
02227 id_it->first,
02228 TRangeWithFuzz(TRangeWithFuzz::GetEmpty()),
02229 eNa_strand_unknown);
02230 continue;
02231 }
02232 CRef<CSeq_id> id(new CSeq_id);
02233 id->Assign(*id_it->first.GetSeqId());
02234 TRanges& ranges = id_it->second;
02235 if ( (flags & CSeq_loc::fSort) != 0 ) {
02236 if ( !IsReverse(default_strand) ) {
02237 sort(ranges.begin(), ranges.end(), CRange_Less());
02238 }
02239 else {
02240 sort(ranges.begin(), ranges.end(), CRange_ReverseLess());
02241 }
02242 }
02243
02244 TRangeWithFuzz last_rg(TRangeWithFuzz::GetEmpty());
02245 bool have_range = false;
02246 ITERATE(TRanges, rg, ranges) {
02247 if (x_MergeRanges(last_rg, default_strand,
02248 *rg, default_strand,
02249 flags)) {
02250 have_range = true;
02251 continue;
02252 }
02253
02254 if (have_range) {
02255 x_PushRange(dst, id_it->first, last_rg, default_strand);
02256 }
02257 last_rg = *rg;
02258 have_range = true;
02259 }
02260 if (have_range) {
02261 x_PushRange(dst, id_it->first, last_rg, default_strand);
02262 }
02263 }
02264 }
02265
02266
02267 void x_MergeNoSort(CSeq_loc& dst,
02268 const CSeq_loc& src,
02269 CSeq_loc::TOpFlags flags,
02270 ISynonymMapper& syn_mapper)
02271 {
02272 _ASSERT((flags & CSeq_loc::fSort) == 0);
02273 CSeq_id_Handle last_id;
02274 TRangeWithFuzz last_rg(TRangeWithFuzz::GetEmpty());
02275 ENa_strand last_strand = eNa_strand_unknown;
02276 bool have_range = false;
02277 for (CSeq_loc_CI it(src, CSeq_loc_CI::eEmpty_Allow); it; ++it) {
02278 CSeq_id_Handle idh = syn_mapper.GetBestSynonym(it.GetSeq_id());
02279
02280 TRangeWithFuzz it_rg(it);
02281 if ( have_range && last_id == idh ) {
02282 if (x_MergeRanges(last_rg,
02283 last_strand,
02284 it_rg,
02285 it.GetStrand(),
02286 flags)) {
02287 have_range = true;
02288 continue;
02289 }
02290 }
02291
02292 if ( have_range ) {
02293 x_PushRange(dst, last_id, last_rg, last_strand);
02294 }
02295 last_id = idh;
02296 last_rg = it_rg;
02297 last_strand = it.GetStrand();
02298 have_range = true;
02299 }
02300 if ( have_range ) {
02301 x_PushRange(dst, last_id, last_rg, last_strand);
02302 }
02303 }
02304
02305
02306 void x_MergeAndSort(CSeq_loc& dst,
02307 const CSeq_loc& src,
02308 CSeq_loc::TOpFlags flags,
02309 ISynonymMapper& syn_mapper)
02310 {
02311 bool use_strand = (flags & CSeq_loc::fStrand_Ignore) == 0;
02312
02313 auto_ptr<TIdToRangeMap> pid_map_minus(use_strand ?
02314 new TIdToRangeMap : 0);
02315 TIdToRangeMap id_map_plus;
02316 TIdToRangeMap& id_map_minus = use_strand ?
02317 *pid_map_minus.get() : id_map_plus;
02318
02319
02320 ENa_strand default_plus = use_strand ?
02321 eNa_strand_plus : eNa_strand_unknown;
02322 ENa_strand default_minus = use_strand ?
02323 eNa_strand_minus : eNa_strand_unknown;
02324
02325
02326 for (CSeq_loc_CI it(src, CSeq_loc_CI::eEmpty_Allow); it; ++it) {
02327 CSeq_id_Handle idh = syn_mapper.GetBestSynonym(it.GetSeq_id());
02328 if ( IsReverse(it.GetStrand()) ) {
02329 id_map_minus[idh].push_back(TRangeWithFuzz(it));
02330 }
02331 else {
02332 id_map_plus[idh].push_back(TRangeWithFuzz(it));
02333 }
02334 }
02335
02336 x_RangesToSeq_loc(dst, id_map_plus, default_plus, flags);
02337 if ( use_strand ) {
02338 x_RangesToSeq_loc(dst, id_map_minus, default_minus, flags);
02339 }
02340 }
02341
02342
02343 void x_SingleRange(CSeq_loc& dst,
02344 const CSeq_loc& src,
02345 TIdToRangeColl& rg_coll_plus,
02346 TIdToRangeColl& rg_coll_minus,
02347 ISynonymMapper& syn_mapper,
02348 ILengthGetter& len_getter)
02349 {
02350 TRangeWithFuzz total_rg(TRangeWithFuzz::GetEmpty());
02351 CSeq_id_Handle first_id;
02352 ENa_strand first_strand = eNa_strand_unknown;
02353 for (CSeq_loc_CI it(src, CSeq_loc_CI::eEmpty_Allow); it; ++it) {
02354 CSeq_id_Handle next_id = syn_mapper.GetBestSynonym(it.GetSeq_id());
02355 if ( !next_id ) {
02356
02357 continue;
02358 }
02359 if ( first_id ) {
02360
02361 if (next_id && first_id != next_id) {
02362 NCBI_THROW(CException, eUnknown,
02363 "Can not merge multi-id seq-loc");
02364 }
02365 }
02366 else {
02367 first_id = next_id;
02368 first_strand = it.GetStrand();
02369 }
02370 TRangeWithFuzz it_range = TRangeWithFuzz(it);
02371 if (it_range.GetFrom() >= total_rg.GetFrom() &&
02372 it_range.GetTo() <= total_rg.GetTo()) {
02373
02374 continue;
02375 }
02376 if ( it_range.IsWhole() ) {
02377 it_range.SetOpen(0, len_getter.GetLength(it.GetSeq_id()));
02378 it_range.ResetFuzzFrom();
02379 it_range.ResetFuzzTo();
02380 }
02381 TRangeColl it_rg_coll(it_range);
02382 TIdToRangeColl& rg_coll = IsReverse(it.GetStrand()) ?
02383 rg_coll_minus : rg_coll_plus;
02384 TIdToRangeColl::const_iterator id_it = rg_coll.find(next_id);
02385 if (id_it != rg_coll.end()) {
02386 it_rg_coll -= id_it->second;
02387 }
02388 total_rg += it_rg_coll.GetLimits();
02389 }
02390
02391 if ( first_id ) {
02392 CRef<CSeq_id> id(new CSeq_id);
02393 id->Assign(*first_id.GetSeqId());
02394 CRef<CSeq_interval> interval(new CSeq_interval(*id,
02395 total_rg.GetFrom(),
02396 total_rg.GetTo(),
02397 first_strand));
02398 dst.SetInt(*interval);
02399 }
02400 else {
02401
02402 dst.SetNull();
02403 }
02404 }
02405
02406
02407 void x_SubNoSort(CSeq_loc& dst,
02408 const CSeq_loc& src,
02409 TIdToRangeColl& rg_coll_plus,
02410 TIdToRangeColl& rg_coll_minus,
02411 ISynonymMapper& syn_mapper,
02412 ILengthGetter& len_getter,
02413 CSeq_loc::TOpFlags flags)
02414 {
02415 _ASSERT((flags & CSeq_loc::fSort) == 0);
02416 CSeq_id_Handle last_id;
02417 TRangeWithFuzz last_rg(TRangeWithFuzz::GetEmpty());
02418 ENa_strand last_strand = eNa_strand_unknown;
02419 bool have_range = false;
02420 for (CSeq_loc_CI it(src, CSeq_loc_CI::eEmpty_Allow); it; ++it) {
02421 CSeq_id_Handle idh = syn_mapper.GetBestSynonym(it.GetSeq_id());
02422 TRangeWithFuzz it_range = TRangeWithFuzz(it);
02423 if ( it_range.IsWhole() ) {
02424 it_range.SetOpen(0, len_getter.GetLength(it.GetSeq_id()));
02425 }
02426 TRangeColl it_rg_coll(it_range);
02427 TIdToRangeColl& rg_coll = IsReverse(it.GetStrand()) ?
02428 rg_coll_minus : rg_coll_plus;
02429 TIdToRangeColl::const_iterator id_it = rg_coll.find(idh);
02430 if (id_it != rg_coll.end()) {
02431 it_rg_coll -= id_it->second;
02432 }
02433 ITERATE(TRangeColl, rg_it, it_rg_coll) {
02434 if ( have_range && last_id == idh ) {
02435 if (x_MergeRanges(last_rg,
02436 last_strand,
02437 *rg_it,
02438 it.GetStrand(),
02439 flags)) {
02440 have_range = true;
02441 continue;
02442 }
02443 }
02444
02445 if ( have_range ) {
02446 x_PushRange(dst, last_id, last_rg, last_strand);
02447 }
02448 last_id = idh;
02449 last_rg = *rg_it;
02450 last_strand = it.GetStrand();
02451 have_range = true;
02452 }
02453 }
02454 if ( have_range ) {
02455 x_PushRange(dst, last_id, last_rg, last_strand);
02456 }
02457 }
02458
02459
02460 void x_SubAndSort(CSeq_loc& dst,
02461 const CSeq_loc& src,
02462 TIdToRangeColl& rg_coll_plus,
02463 TIdToRangeColl& rg_coll_minus,
02464 ISynonymMapper& syn_mapper,
02465 ILengthGetter& len_getter,
02466 CSeq_loc::TOpFlags flags)
02467 {
02468 bool use_strand = (flags & CSeq_loc::fStrand_Ignore) == 0;
02469
02470
02471 auto_ptr<TIdToRangeMap> p_id_map_minus(use_strand ?
02472 new TIdToRangeMap : 0);
02473 TIdToRangeMap id_map_plus;
02474 TIdToRangeMap& id_map_minus = use_strand ?
02475 *p_id_map_minus.get() : id_map_plus;
02476
02477
02478 ENa_strand default_plus = use_strand ?
02479 eNa_strand_plus : eNa_strand_unknown;
02480 ENa_strand default_minus = use_strand ?
02481 eNa_strand_minus : eNa_strand_unknown;
02482
02483 for (CSeq_loc_CI it(src, CSeq_loc_CI::eEmpty_Allow); it; ++it) {
02484 CSeq_id_Handle idh = syn_mapper.GetBestSynonym(it.GetSeq_id());
02485 TRangeWithFuzz it_range = it.GetRange();
02486 if ( it_range.IsWhole() ) {
02487 it_range.SetOpen(0, len_getter.GetLength(it.GetSeq_id()));
02488 it_range.ResetFuzzFrom();
02489 it_range.ResetFuzzTo();
02490 }
02491 TRangeColl it_rg_coll(it_range);
02492 TRanges& rg_map = IsReverse(it.GetStrand()) ?
02493 id_map_minus[idh] : id_map_plus[idh];
02494 TIdToRangeColl& rg_coll = IsReverse(it.GetStrand()) ?
02495 rg_coll_minus : rg_coll_plus;
02496 TIdToRangeColl::const_iterator id_it = rg_coll.find(idh);
02497 if (id_it != rg_coll.end()) {
02498 it_rg_coll -= id_it->second;
02499 }
02500 ITERATE(TRangeColl, rg_it, it_rg_coll) {
02501 rg_map.push_back(*rg_it);
02502 }
02503 }
02504
02505 x_RangesToSeq_loc(dst, id_map_plus, default_plus, flags);
02506 if ( use_strand ) {
02507 x_RangesToSeq_loc(dst, id_map_minus, default_minus, flags);
02508 }
02509 }
02510
02511
02512 class CDummySynonymMapper : public ISynonymMapper
02513 {
02514 public:
02515 CDummySynonymMapper(void) {}
02516 virtual ~CDummySynonymMapper(void) {}
02517
02518 virtual CSeq_id_Handle GetBestSynonym(const CSeq_id& id)
02519 {
02520 return CSeq_id_Handle::GetHandle(id);
02521 }
02522 };
02523
02524
02525 class CDummyLengthGetter : public ILengthGetter
02526 {
02527 public:
02528 CDummyLengthGetter(void) {}
02529 virtual ~CDummyLengthGetter(void) {}
02530
02531 virtual TSeqPos GetLength(const CSeq_id& id)
02532 {
02533 return CSeq_loc::TRange::GetWholeToOpen();
02534 }
02535 };
02536
02537
02538 CRef<CSeq_loc> CSeq_loc::Merge(TOpFlags flags,
02539 ISynonymMapper* syn_mapper) const
02540 {
02541 auto_ptr<CDummySynonymMapper> p_mapper;
02542 if ( !syn_mapper ) {
02543 p_mapper.reset(new CDummySynonymMapper);
02544 syn_mapper = p_mapper.get();
02545 }
02546
02547 CRef<CSeq_loc> ret(new CSeq_loc);
02548 if ( (flags & CSeq_loc::fMerge_SingleRange) != 0 ) {
02549 x_SingleRange(*ret, *this, *syn_mapper);
02550 }
02551 else if ( (flags & CSeq_loc::fSort) == 0 ) {
02552 x_MergeNoSort(*ret, *this, flags, *syn_mapper);
02553 }
02554 else {
02555 x_MergeAndSort(*ret, *this, flags, *syn_mapper);
02556 }
02557 return ret;
02558 }
02559
02560
02561 CRef<CSeq_loc> CSeq_loc::Add(const CSeq_loc& other,
02562 TOpFlags flags,
02563 ISynonymMapper* syn_mapper) const
02564 {
02565 auto_ptr<CDummySynonymMapper> p_mapper;
02566 if ( !syn_mapper ) {
02567 p_mapper.reset(new CDummySynonymMapper);
02568 syn_mapper = p_mapper.get();
02569 }
02570
02571 CRef<CSeq_loc> ret(new CSeq_loc);
02572 CSeq_loc tmp;
02573 tmp.SetMix().AddSeqLoc(const_cast<CSeq_loc&>(*this));
02574 tmp.SetMix().AddSeqLoc(const_cast<CSeq_loc&>(other));
02575 if ( (flags & CSeq_loc::fMerge_SingleRange) != 0 ) {
02576 x_SingleRange(*ret, tmp, *syn_mapper);
02577 }
02578 else if ( (flags & CSeq_loc::fSort) == 0 ) {
02579 x_MergeNoSort(*ret, tmp, flags, *syn_mapper);
02580 }
02581 else {
02582 x_MergeAndSort(*ret, tmp, flags, *syn_mapper);
02583 }
02584 return ret;
02585 }
02586
02587
02588 CRef<CSeq_loc> CSeq_loc::Subtract(const CSeq_loc& other,
02589 TOpFlags flags,
02590 ISynonymMapper* syn_mapper,
02591 ILengthGetter* len_getter) const
02592 {
02593 auto_ptr<CDummySynonymMapper> p_mapper;
02594 if ( !syn_mapper ) {
02595 p_mapper.reset(new CDummySynonymMapper);
02596 syn_mapper = p_mapper.get();
02597 }
02598 auto_ptr<CDummyLengthGetter> p_getter;
02599 if ( !len_getter ) {
02600 p_getter.reset(new CDummyLengthGetter);
02601 len_getter = p_getter.get();
02602 }
02603
02604 CRef<CSeq_loc> ret(new CSeq_loc);
02605
02606 bool use_strand = (flags & CSeq_loc::fStrand_Ignore) == 0;
02607
02608
02609 auto_ptr<TIdToRangeColl> p_rg_coll_minus(use_strand ?
02610 new TIdToRangeColl : 0);
02611 TIdToRangeColl rg_coll_plus;
02612 TIdToRangeColl& rg_coll_minus = use_strand ?
02613 *p_rg_coll_minus.get() : rg_coll_plus;
02614
02615
02616 for (CSeq_loc_CI it(other); it; ++it) {
02617 if ( it.IsEmpty() ) {
02618 continue;
02619 }
02620 CSeq_id_Handle idh = syn_mapper->GetBestSynonym(it.GetSeq_id());
02621 TRangeColl& rmap = IsReverse(it.GetStrand()) ?
02622 rg_coll_minus[idh] : rg_coll_plus[idh];
02623 rmap += TRangeWithFuzz(it);
02624 }
02625
02626 if ( (flags & CSeq_loc::fMerge_SingleRange) != 0 ) {
02627 x_SingleRange(*ret,
02628 *this,
02629 rg_coll_plus,
02630 rg_coll_minus,
02631 *syn_mapper,
02632 *len_getter);
02633 }
02634 else if ( (flags & CSeq_loc::fSort) == 0 ) {
02635 x_SubNoSort(*ret,
02636 *this,
02637 rg_coll_plus,
02638 rg_coll_minus,
02639 *syn_mapper,
02640 *len_getter,
02641 flags);
02642 }
02643 else {
02644 x_SubAndSort(*ret,
02645 *this,
02646 rg_coll_plus,
02647 rg_coll_minus,
02648 *syn_mapper,
02649 *len_getter,
02650 flags);
02651 }
02652
02653 return ret;
02654 }
02655
02656
02657 CRef<CSeq_loc> CSeq_loc::Intersect(const CSeq_loc& other,
02658 TOpFlags flags,
02659 ISynonymMapper* syn_mapper) const
02660 {
02661 auto_ptr<CDummyLengthGetter> len_getter(new CDummyLengthGetter);
02662 CRef<CSeq_loc> tmp = Subtract(other,
02663
02664 flags & ~fMerge_SingleRange,
02665 syn_mapper, len_getter.get());
02666 return Subtract(*tmp, flags, syn_mapper, len_getter.get());
02667 }
02668
02669
02670 void CSeq_loc::SetStrand(ENa_strand strand)
02671 {
02672 switch ( Which() ) {
02673 case e_Int:
02674 SetInt().SetStrand(strand);
02675 break;
02676 case e_Pnt:
02677 SetPnt().SetStrand(strand);
02678 break;
02679 case e_Packed_int:
02680 SetPacked_int().SetStrand(strand);
02681 break;
02682 case e_Packed_pnt:
02683 SetPacked_pnt().SetStrand(strand);
02684 break;
02685 case e_Mix:
02686 SetMix().SetStrand(strand);
02687 break;
02688
02689 default:
02690 break;
02691 }
02692 }
02693
02694
02695 void CSeq_loc::ResetStrand(void)
02696 {
02697 switch ( Which() ) {
02698 case e_Int:
02699 SetInt().ResetStrand();
02700 break;
02701 case e_Pnt:
02702 SetPnt().ResetStrand();
02703 break;
02704 case e_Packed_int:
02705 SetPacked_int().ResetStrand();
02706 break;
02707 case e_Packed_pnt:
02708 SetPacked_pnt().ResetStrand();
02709 break;
02710 case e_Mix:
02711 SetMix().ResetStrand();
02712 break;
02713
02714 default:
02715 break;
02716 }
02717 }
02718
02719
02720 END_objects_SCOPE
02721 END_NCBI_SCOPE
02722
02723 #undef NCBI_USE_ERRCODE_X
02724
02725