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

Go to the SVN repository for this file.

1 /* $Id: visible_range.cpp 40878 2018-04-25 19:54:29Z katargir $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Vladimir Tereshkov, Andrey Yazhuk, Mike Dicuccio
27  *
28  * File Description:
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 
34 #include <objmgr/util/sequence.hpp>
35 #include <gui/objutils/utils.hpp>
36 
38 
41 
44 
45 CVisibleRange::CVisibleRange(objects::CScope& scope)
46  : m_Scope(&scope)
47  , m_Policy(sm_DefaultPolicy)
48 {
49 }
50 
52 {
53 }
54 
55 void CVisibleRange::AddLocation(const objects::CSeq_loc& loc)
56 {
57  m_Locs.push_back(CConstRef<CSeq_loc>(&loc));
58 }
59 
61 {
62  return m_Locs;
63 }
64 
65 bool CVisibleRange::Match(const CSeq_id& other_id) const
66 {
67  try {
68  CRef<CScope> scope = m_Scope;
69 
70  ITERATE (TLocations, iter, m_Locs) {
71  const CSeq_id& id = sequence::GetId(**iter, scope);
72  if (CSeqUtils::Match(id, other_id, scope)) {
73  return true;
74  }
75  }
76  }
77  catch (CException& e) {
78  LOG_POST(Error << "CVisibleRange::Match(): error: " << e.GetMsg());
79  }
80  return false;
81 }
82 
83 /// Alter the supplied range according to the rules provided in the
84 /// policy and the supplied new location
85 bool CVisibleRange::Clamp(const CBioseq_Handle& handle,
86  TSeqRange& range) const
87 {
88  try {
89  CRef<CScope> scope = m_Scope;
90  ITERATE (TLocations, iter, m_Locs) {
91  const CSeq_id& id = sequence::GetId(**iter, scope);
92  if (CSeqUtils::Match(id, *handle.GetSeqId(), scope)) {
93  return x_Clamp(**iter, handle, range);
94  }
95  }
96  }
97  catch (CException& e) {
98  LOG_POST(Error << "CVisibleRange::Clamp(): error: " << e.GetMsg());
99  }
100  return false;
101 }
102 
104 {
105  switch (m_Policy) {
106  case eBasic_TrackCenter :
107  return eVisible_TrackCenter;
108  case eBasic_TrackExpand :
109  return eVisible_TrackExpand;
110  case eBasic_TrackContract :
111  return eVisible_TrackContract;
112  case eBasic_Slave :
113  return eVisible_Slave;
114  case eBasic_Ignore :
115  return eVisible_Ignore;
116  default :
117  return eVisible_Track;
118  }
119 }
120 
121 bool CVisibleRange::x_Clamp(const objects::CSeq_loc& loc,
122  const objects::CBioseq_Handle& handle,
123  TSeqRange& range) const
124 {
125  int mode = x_GetPolicy();
126  if (mode == eVisible_Ignore)
127  return false;
128 
129  TSeqRange this_range(range);
130  if (this_range.IsWhole()) {
131  this_range.SetTo(handle.GetBioseqLength());
132  }
133  TSeqRange other_range = loc.GetTotalRange();
134  if (other_range.IsWhole()) {
135  other_range.SetTo(handle.GetBioseqLength());
136  }
137 
138  if (mode == eDefault) {
140  }
141 
142  if (mode == eVisible_Slave) {
143  this_range = other_range;
144  } else {
145  if ( (mode & eScaleMask) == eScale_Expand) {
146  if (other_range.GetLength() > this_range.GetLength()) {
147  this_range = other_range;
148  }
149  } else if ((mode & eScaleMask) == eScale_Contract) {
150  if (other_range.GetLength() < this_range.GetLength()) {
151  this_range = other_range;
152  }
153  } else if ((mode & eScaleMask) == eScale_TrackScale) {
154  TSeqPos other_diff = other_range.GetTo() - other_range.GetFrom();
155  TSeqPos this_diff = this_range.GetTo() - this_range.GetFrom();
156  TSignedSeqPos diff = (other_diff - this_diff) / 2;
157  this_range.SetFrom(this_range.GetFrom() + diff);
158  this_range.SetTo (this_range.GetTo() + diff);
159  }
160 
161  if ((mode & ePositionMask) == ePosition_Track ||
163  if (this_range.GetLength() == other_range.GetLength()) {
164  this_range = other_range;
165  } else {
166  TSeqRange r(this_range);
167  r += other_range;
168  if (this_range.GetLength() > other_range.GetLength() && this_range != r) {
169  if (other_range.GetFrom() < this_range.GetFrom()) {
170  size_t diff = this_range.GetFrom() - other_range.GetFrom();
171  this_range.SetFrom((unsigned)(this_range.GetFrom() - diff));
172  this_range.SetTo ((unsigned)(this_range.GetTo() - diff));
173  } else if (other_range.GetTo() > this_range.GetTo()) {
174  size_t diff = other_range.GetTo() - this_range.GetTo();
175  this_range.SetFrom((unsigned)(this_range.GetFrom() + diff));
176  this_range.SetTo ((unsigned)(this_range.GetTo() + diff));
177  }
178  } else if (this_range.GetLength() < other_range.GetLength() && other_range != r) {
179  if (this_range.GetFrom() < other_range.GetFrom()) {
180  size_t diff = other_range.GetFrom() - this_range.GetFrom();
181  this_range.SetFrom((unsigned)(this_range.GetFrom() + diff));
182  this_range.SetTo ((unsigned)(this_range.GetTo() + diff));
183  } else if (this_range.GetTo() > other_range.GetTo()) {
184  size_t diff = this_range.GetTo() - other_range.GetTo();
185  this_range.SetFrom((unsigned)(this_range.GetFrom() - diff));
186  this_range.SetTo ((unsigned)(this_range.GetTo() - diff));
187  }
188  }
189  }
191  TSeqPos this_center =
192  (this_range.GetTo() + this_range.GetFrom()) / 2;
193  TSeqPos other_center =
194  (other_range.GetTo() + other_range.GetFrom()) / 2;
195  TSignedSeqPos diff = other_center - this_center;
196  TSignedSeqPos new_from = this_range.GetFrom() + diff;
197  TSeqPos new_to = this_range.GetTo() + diff;
198  if (new_from < 0) {
199  new_to += -new_from;
200  new_from = 0;
201  } else if (new_to > handle.GetBioseqLength()) {
202  new_from -= new_to - handle.GetBioseqLength();
203  new_to = handle.GetBioseqLength();
204  }
205 
206  this_range.SetFrom(new_from);
207  this_range.SetTo(new_to);
208  }
209  }
210  }
211 
212  bool ret_val = (this_range != range);
213  range = this_range;
214  return ret_val;
215 }
216 
217 /// Alter the supplied location according to the rules provided in the
218 /// policy and the supplied new location
219 bool CVisibleRange::Clamp(objects::CSeq_loc& loc) const
220 {
221  try {
222  CRef<CScope> scope = m_Scope;
223 
224  CBioseq_Handle bsh = scope->GetBioseqHandle(loc);
225  TSeqRange total_range = loc.GetTotalRange();
226  if (total_range.IsWhole()) {
227  total_range.SetTo(bsh.GetBioseqLength());
228  }
229  CSeq_id_Handle idh = sequence::GetIdHandle(loc, scope);
230 
231  bool clamped = false;
232  ITERATE (TLocations, iter, m_Locs) {
233  const CSeq_id& id = sequence::GetId(**iter, scope);
234  if (CSeqUtils::Match(id, *idh.GetSeqId(), scope)) {
235  CBioseq_Handle bsh2 = scope->GetBioseqHandle(id);
236  if (x_Clamp(**iter, bsh2, total_range)) {
237  clamped = true;
238  break;
239  }
240  }
241 
242  if (clamped) {
243  break;
244  }
245  }
246 
247  if (clamped) {
248  /// now, all we need to do is clamp the current
249  /// seq-loc to this specific range
250  return x_Clamp(loc, total_range);
251  }
252  }
253  catch (CException& e) {
254  LOG_POST(Error << "CVisibleRange::Clamp(): error: " << e.GetMsg());
255  }
256  return false;
257 }
258 
259 
260 bool CVisibleRange::x_Clamp(CSeq_loc& loc, const TSeqRange& range) const
261 {
262  switch (loc.Which()) {
263  case CSeq_loc::e_Whole:
264  {{
265  CRef<CSeq_id> id(&loc.SetWhole());
266  loc.SetInt().SetFrom(range.GetFrom());
267  loc.SetInt().SetTo (range.GetTo());
268  loc.SetId(*id);
269  }}
270  return true;
271 
272  case CSeq_loc::e_Int:
273  loc.SetInt().SetFrom(range.GetFrom());
274  loc.SetInt().SetTo (range.GetTo());
275  return true;
276 
278  {{
279  CSeq_loc::TPacked_int::Tdata::iterator iter = loc.SetPacked_int().Set().begin();
280  CSeq_loc::TPacked_int::Tdata::iterator end = loc.SetPacked_int().Set().end();
281  for ( ; iter != end; ++iter) {
282  CSeq_interval& ival = **iter;
283  if (ival.GetTo() < range.GetFrom() ||
284  ival.GetFrom() > range.GetTo()) {
285  /// spike the whole interval
286  loc.SetPacked_int().Set().erase(iter++);
287  /// ival is now dead!
288  } else {
289  ival.SetFrom(max(ival.GetFrom(), range.GetFrom()));
290  ival.SetTo (min(ival.GetTo(), range.GetTo()));
291  }
292  }
293  }}
294  return true;
295 
296  case CSeq_loc::e_Mix:
297  {{
298  CSeq_loc::TMix::Tdata::iterator iter = loc.SetMix().Set().begin();
299  CSeq_loc::TMix::Tdata::iterator end = loc.SetMix().Set().end();
300  for ( ; iter != end; ++iter) {
301  CSeq_loc& this_loc = **iter;
302  TSeqRange this_range = this_loc.GetTotalRange();
303  if (this_range.GetTo() < range.GetFrom() ||
304  this_range.GetFrom() > range.GetTo()) {
305  /// spike the whole sublocation
306  loc.SetMix().Set().erase(iter++);
307  /// this_loc is now dead!
308  } else {
309  x_Clamp(this_loc, range);
310  }
311  }
312  }}
313  return true;
314 
315  default:
316  LOG_POST(Error << "CVisibleRange::x_Clamp(): unhandled loc type");
317  return false;
318  }
319 }
320 
static CRef< CScope > m_Scope
CBioseq_Handle –.
EBasicPolicy m_Policy
@ eVisible_Ignore
combination options
@ ePositionMask
position tracking options
@ eScaleMask
location scale tracking options
static EBasicPolicy GetDefaultVisibleRangePolicy()
CVisibleRange(objects::CScope &scope)
static EBasicPolicy sm_DefaultPolicy
static bool sm_AutoBroadcast
int x_GetPolicy() const
CRef< objects::CScope > m_Scope
TLocations m_Locs
list< CConstRef< objects::CSeq_loc > > TLocations
const TLocations & GetLocations() const
bool Clamp(const objects::CBioseq_Handle &handle, TSeqRange &range) const
Alter the supplied range according to the rules provided in the policy and the supplied new location.
bool Match(const objects::CSeq_id &id) const
See if we can match the supplied range.
bool x_Clamp(const objects::CSeq_loc &loc, const objects::CBioseq_Handle &handle, TSeqRange &range) const
internal clamping function to clamp a total range based on a location
void AddLocation(const objects::CSeq_loc &loc)
constexpr auto end(const ct_const_array< T, N > &in) noexcept
unsigned int TSeqPos
Type for sequence locations and lengths.
Definition: ncbimisc.hpp:875
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
int TSignedSeqPos
Type for signed sequence position.
Definition: ncbimisc.hpp:887
#define LOG_POST(message)
This macro is deprecated and it's strongly recomended to move in all projects (except tests) to macro...
Definition: ncbidiag.hpp:226
void Error(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1197
const string & GetMsg(void) const
Get message string.
Definition: ncbiexpt.cpp:461
static bool Match(const objects::CSeq_id &id1, const objects::CSeq_id &id2, objects::CScope *scope=NULL)
check to see if two seq-ids are identical.
CConstRef< CSeq_id > GetSeqId(void) const
void SetPacked_int(TPacked_int &v)
Definition: Seq_loc.hpp:984
void SetMix(TMix &v)
Definition: Seq_loc.hpp:987
void SetWhole(TWhole &v)
Definition: Seq_loc.hpp:982
void SetId(CSeq_id &id)
set the 'id' field in all parts of this location
Definition: Seq_loc.cpp:3474
TRange GetTotalRange(void) const
Definition: Seq_loc.hpp:913
void SetInt(TInt &v)
Definition: Seq_loc.hpp:983
const CSeq_id & GetId(const CSeq_loc &loc, CScope *scope)
If all CSeq_ids embedded in CSeq_loc refer to the same CBioseq, returns the first CSeq_id found,...
CSeq_id_Handle GetIdHandle(const CSeq_loc &loc, CScope *scope)
CBioseq_Handle GetBioseqHandle(const CSeq_id &id)
Get bioseq handle by seq-id.
Definition: scope.cpp:95
TSeqPos GetBioseqLength(void) const
CConstRef< CSeq_id > GetSeqId(void) const
Get id which can be used to access this bioseq handle Throws an exception if none is available.
position_type GetLength(void) const
Definition: range.hpp:158
bool IsWhole(void) const
Definition: range.hpp:284
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
void SetFrom(TFrom value)
Assign a value to From data member.
Definition: Range_.hpp:231
TTo GetTo(void) const
Get the To member data.
Definition: Range_.hpp:269
TFrom GetFrom(void) const
Get the From member data.
Definition: Range_.hpp:222
void SetTo(TTo value)
Assign a value to To data member.
Definition: Range_.hpp:278
void SetTo(TTo value)
Assign a value to To data member.
TFrom GetFrom(void) const
Get the From member data.
E_Choice Which(void) const
Which variant is currently selected.
Definition: Seq_loc_.hpp:475
void SetFrom(TFrom value)
Assign a value to From data member.
TTo GetTo(void) const
Get the To member data.
@ e_Int
from to
Definition: Seq_loc_.hpp:101
@ e_Whole
whole sequence
Definition: Seq_loc_.hpp:100
range(_Ty, _Ty) -> range< _Ty >
mdb_mode_t mode
Definition: lmdb++.h:38
T max(T x_, T y_)
T min(T x_, T y_)
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
USING_SCOPE(objects)
Modified on Sat Dec 09 04:47:31 2023 by modify_doxy.py rev. 669887