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

Go to the SVN repository for this file.

1 /* $Id: tax_tree.cpp 45992 2021-01-20 18:24:18Z grichenk $
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: Mike DiCuccio
27  *
28  * File Description:
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
36 #include <gui/utils/reporter.hpp>
37 #include <gui/objutils/utils.hpp>
39 #include <algorithm>
40 #include <stack>
41 
42 
45 
46 
47 
48 //
49 // internal class to fill our tree structure
50 //
51 
53 {
54 public:
55 
56  virtual ~CTreeFiller() { }
58  const CTaxTreeBrowser::TTaxMap& tax_map)
59  : m_TaxMap(tax_map),
60  m_Curr(NULL),
61  m_DS(&ds)
62  {
63  }
64 
66  {
67  if (m_Curr) {
68  m_Nodes.push(m_Curr);
69  }
70 
71  m_Curr = NULL;
72  return ITreeIterator::eOk;
73  }
74 
76  {
78  info.data_source = m_DS;
79  info.tax_node = tax_node;
80 
81  TTaxId tax_id = tax_node->GetTaxId();
83  if (iter != m_TaxMap.end()) {
84  info.uids = iter->second;
85  } else {
86  LOG_POST(Warning << "failed to find tax-id " << tax_id
87  << " in list of sequences");
88  }
89 
91  if ( !m_Tree.get() ) {
93  node = m_Tree.get();
94  } else if (m_Nodes.size()) {
95  CTaxTreeBrowser::TTaxTree* parent = m_Nodes.top();
96  node = parent->AddNode(info);
97  } else {
98  LOG_POST(Warning << "failed to find current node");
99  }
100 
101  m_Curr = node;
102  return ITreeIterator::eOk;
103  }
104 
106  {
107  m_Curr = m_Nodes.top();
108  m_Nodes.pop();
109  return ITreeIterator::eOk;
110  }
111 
113  unique_ptr<CTaxTreeBrowser::TTaxTree> m_Tree;
116  stack<CTaxTreeBrowser::TTaxTree*> m_Nodes;
117 };
118 
119 
120 // callback - not a good way to go, but keeps FluTree unchanged
121 // in case it will be updated externally
122 //static void s_OnTaxTreeNotify_cb(Fl_Widget * widget, void * data)
123 //{
124 // CTaxTreeBrowser* pTaxTree = dynamic_cast<CTaxTreeBrowser*> (widget);
125 //
126 // if (pTaxTree) {
127 // CTaxTreeDataSource::TUidVec uids;
128 // uids.clear();
129 //
130 // pTaxTree->GetSelectedUids(uids);
131 //
132 // switch (pTaxTree->callback_reason()) {
133 // case FLU_SELECTED:
134 // case FLU_UNSELECTED: {
135 // CEventAttachmentFor< vector<CConstRef<objects::CSeq_id> > > csid;
136 // csid = uids;
137 // pTaxTree->Send(new CEvent(CEvent::eEvent_Message, CViewEvent::eSelectionChanged, &csid, pTaxTree));
138 // }
139 // }
140 // }
141 //}
142 
143 CTaxTreeBrowser::CTaxTreeBrowser(wxWindow *parent, wxWindowID id,
144  const wxPoint& pos, const wxSize& size,
145  long style, const wxValidator& validator,
146  const wxString& name)
147 {
148  m_Reporter = NULL;
149  style = style & ~wxTR_MULTIPLE;
150  wxTreeCtrl::Create(parent, id, pos, size, style, validator, name);
151 }
152 
153 
154 CTaxTreeBrowser::CTaxTreeBrowser(wxWindow *parent, wxWindowID id,
155  const wxPoint& pos, const wxSize& size,
156  long style)
157 {
158  m_Reporter = NULL;
159  style = style & ~wxTR_MULTIPLE;
160  wxTreeCtrl::Create(parent, id, pos, size, style);
161 }
162 
163 
164 
166 {
167 }
168 
169 
171 {
172  m_Reporter = reporter;
173 }
174 
175 
177 {
178  m_DataSource.Reset(&ds);
179 
180  x_Refresh();
181 }
182 
183 
185 {
186  // clear the tree to start
187  DeleteAllItems();
188  if ( !m_DataSource ) {
189  return;
190  }
191 
192  if (m_Reporter) {
193  m_Reporter->SetMessage("Retrieving taxonomic IDs...");
194  }
195 
196  TTaxMap tax_map;
197  m_DataSource->GetTaxMap(tax_map);
198 
200  CTreeFiller filler(*m_DataSource, tax_map);
201  iter.TraverseDownward(filler);
202  m_TaxTree.reset(filler.m_Tree.release());
203 
204  // next, populate the browser
205  if (m_TaxTree.get()) {
206  x_PopulateTree(GetRootItem(), m_TaxTree.get());
207  }
208 
209  if (m_Reporter) {
210  m_Reporter->SetMessage("Done.");
212  }
213 }
214 
215 
217 {
218  m_DispMode = mode;
219  x_Refresh();
220 }
221 
222 
224 {
227  {
228  switch (delta) {
229  case 0:
230  case 1:
231  uids.insert(uids.end(),
232  node.GetValue().uids.begin(),
233  node.GetValue().uids.end());
234  break;
235 
236  case -1:
237  break;
238  }
239 
240  return eTreeTraverse;
241  }
242 };
243 
244 
246 {
247  SUidCollector collector;
248  wxArrayTreeItemIds selections;
249 
250  if( GetSelections( selections ) ){
251  for( size_t ix = 0; ix < selections.size(); ix++ ){
252  wxTreeItemData* item_data = GetItemData( selections[ix] );
253  TTaxTree* tree = dynamic_cast<wxTaxTreeData*>(item_data)->GetData();
254  if( tree ){
255  collector = TreeDepthFirstTraverse( *tree, collector );
256  }
257  }
258  }
259 
260  std::sort( collector.uids.begin(), collector.uids.end() );
261  collector.uids.erase(
262  std::unique( collector.uids.begin(), collector.uids.end() ),
263  collector.uids.end()
264  );
265  uids.swap( collector.uids );
266 }
267 
268 
270 {
271  // add a node for the current branch
272  string name;
273  x_GetName(*tree, name);
274 
275  node = AppendItem(node, ToWxString(name), -1, -1, new wxTaxTreeData(tree));
276 
277  // recurse our tree
278  if ( !tree->IsLeaf()) {
279  /// not a leaf node - just add the children recursively
280  TTaxTree::TNodeList_CI begin = tree->SubNodeBegin();
281  TTaxTree::TNodeList_CI begin2 = begin;
282  TTaxTree::TNodeList_CI end = tree->SubNodeEnd();
283  if (++begin2 == end) {
284  // 1 child only
285  Expand(node);
286  }
287  for ( ; begin != end; ++begin) {
288  x_PopulateTree(node, *begin);
289  }
290  } else {
291  // leaf node
292  // we go ahead and transform the tree as well, making sure
293  // that leaves represent sequences, not taxa
294  string str;
295  const STaxInfo& info = tree->GetValue();
296  ITERATE (CTaxTreeDataSource::TUidVec, iter, tree->GetValue().uids) {
297  /// add a leaf in the tax tree for the sequence as well
299  new_info.data_source = info.data_source;
300  new_info.uids.push_back(*iter);
301  new_info.tax_node = info.tax_node;
302  TTaxTree* new_tree = tree->AddNode(new_info);
303 
304  /// add a node for this sequence
305  str.erase();
306  m_DataSource->GetTitle(**iter, &str);
307 
308  AppendItem(node, ToWxString(str), -1, -1, new wxTaxTreeData(new_tree));
309  }
310  }
311 }
312 
314 {
315  // TO DO this is not a very effective solution, can be optimized
317  GetSelectedUids(uids);
318 
320  objs.push_back(CConstRef<CObject>(&**it));
321  }
322 }
323 
324 
326 {
327  UnselectAll();
328  SetSelectedUids(uids, GetRootItem());
329 }
330 
331 
332 // retrieve a name for a node
333 void CTaxTreeBrowser::x_GetName(TTaxTree& node, string& str) const
334 {
335  size_t uids = x_CountNodes(node);
336  m_DataSource->GetTitle(*node.GetValue().tax_node, &str);
337  str += " - ";
338  str += NStr::SizetToString(uids);
339  str += " sequences";
340 }
341 
342 
344 {
346  : uids(0) { }
347 
348  size_t uids;
350  int delta_level)
351  {
352  switch (delta_level) {
353  case 0:
354  case 1:
355  uids += node.GetValue().uids.size();
356  break;
357  case -1:
358  break;
359  }
360  return eTreeTraverse;
361  }
362 };
363 
364 // count the number of UIDs held underneath a given tree
366 {
367  SUidCounter counter;
368  counter = TreeDepthFirstTraverse(node, counter);
369  return counter.uids;
370 }
371 
372 
374  wxTreeItemId node)
375 {
376  TTaxTree * tree = (dynamic_cast<wxTaxTreeData*>(GetItemData(node)))->GetData();
377 
378  /**
379  if ( !tree ) {
380  /// the root doesn't have a tree associated with it
381  /// descend always
382  for (int i = 0; i < node->children(); ++i) {
383  SetSelectedUids(uids, node->child(i));
384  }
385  } else {
386  /// check to see if the number of UIDs match
387  CRef<CScope> scope = m_DataSource->GetScope();
388  const CTaxTreeDataSource::TUidVec& this_uids = tree->GetValue().uids;
389  if (this_uids.size() == uids.size()) {
390  bool all_match = true;
391  ITERATE (CTaxTreeDataSource::TUidVec, it1, this_uids) {
392  bool found = false;
393  ITERATE (CTaxTreeDataSource::TUidVec, it2, uids) {
394  if (CSeqUtils::Match(**it1, **it2, scope) ) {
395  found = true;
396  break;
397  }
398  }
399  if ( !found ) {
400  all_match = false;
401  break;
402  }
403  }
404 
405  if (all_match) {
406  node->select(true);
407  }
408  } else if (this_uids.size() > uids.size()) {
409  /// descend
410  for (int i = 0; i < node->children(); ++i) {
411  SetSelectedUids(uids, node->child(i));
412  }
413  }
414  }
415  **/
416 
417 
418 
419  if (!GetChildrenCount(node)) {
420  const CTaxTreeDataSource::TUidVec& uid_vec =
421  tree->GetValue().uids;
422  _ASSERT(uid_vec.size() == 1);
423  if (uid_vec.size() != 1) {
424  return;
425  }
426 
427  CTaxTreeDataSource::TUid uid = uid_vec.front();
429  ITERATE (CTaxTreeDataSource::TUidVec, itt, uids) {
430  if (CSeqUtils::Match(**itt, *uid, scope)) {
431  SelectItem(node);
432 
433  wxTreeItemId parNode = node;
434  while ( (parNode=GetItemParent(parNode)).IsOk() ) {
435  Expand(parNode);
436 
437  wxTreeItemId chNode;
438  bool bsel = true;
439  wxTreeItemIdValue cookie;
440  do {
441  if (!chNode.IsOk()) {
442  chNode = GetFirstChild(parNode, cookie);
443  } else {
444  chNode = GetNextChild(parNode, cookie);
445  }
446  if ( !(bsel=IsSelected(chNode)) ) {
447  break;
448  }
449  } while (chNode!=GetLastChild(parNode));
450 
451  SelectItem(parNode, bsel);
452  }
453  }
454  }
455  }
456 
457  wxTreeItemIdValue ck;
458  wxTreeItemId next = GetNextChild(node, ck);
459  if (next.IsOk()) {
460  SetSelectedUids(uids, next);
461  }
462 }
463 
void x_PopulateTree(wxTreeItemId node, TTaxTree *tree)
populate a given node from a tax tree node
Definition: tax_tree.cpp:269
void x_GetName(TTaxTree &node, string &str) const
retrieve a name for a node
Definition: tax_tree.cpp:333
size_t x_CountNodes(TTaxTree &node) const
count the number of UIDs held underneath a given tree
Definition: tax_tree.cpp:365
CTaxTreeBrowser(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style, const wxValidator &validator, const wxString &name)
default ctor (for FLTK)
Definition: tax_tree.cpp:143
void SetReporter(IReporter *reporter)
set the abstract reporter interface
Definition: tax_tree.cpp:170
void SetDataSource(CTaxTreeDataSource &ds)
set the data source for this widget
Definition: tax_tree.cpp:176
void x_Refresh()
callback function
Definition: tax_tree.cpp:184
~CTaxTreeBrowser()
dtor
Definition: tax_tree.cpp:165
IReporter * m_Reporter
our reporter interface
Definition: tax_tree.hpp:165
void SetSelectedUids(const CTaxTreeDataSource::TUidVec &uids, wxTreeItemId node)
set selected ids
Definition: tax_tree.cpp:373
CRef< CTaxTreeDataSource > m_DataSource
the data source we use
Definition: tax_tree.hpp:153
void GetObjectSelection(TConstObjects &objs)
Selection API.
Definition: tax_tree.cpp:313
unique_ptr< TTaxTree > m_TaxTree
Definition: tax_tree.hpp:155
CTaxTreeDataSource::EDisplayMode m_DispMode
display mode
Definition: tax_tree.hpp:162
void SetObjectSelection(const CTaxTreeDataSource::TUidVec &uids)
Definition: tax_tree.cpp:325
void GetSelectedUids(CTaxTreeDataSource::TUidVec &uids) const
retrieve the selected UIDs
Definition: tax_tree.cpp:245
void SetDisplayMode(CTaxTreeDataSource::EDisplayMode mode)
set the current display mode.
Definition: tax_tree.cpp:216
virtual objects::ITreeIterator & GetIterator(EDisplayMode mode=eDisplay_Default)=0
virtual void GetTitle(const objects::CSeq_id &uid, string *title) const =0
virtual void GetTaxMap(TTaxMap &taxmap)=0
virtual const CRef< objects::CScope > & GetScope(void)=0
vector< TUid > TUidVec
Definition: tax_tree_ds.hpp:63
CRef< CTaxTreeDataSource > m_DS
Definition: tax_tree.cpp:115
stack< CTaxTreeBrowser::TTaxTree * > m_Nodes
Definition: tax_tree.cpp:116
virtual ~CTreeFiller()
Definition: tax_tree.cpp:56
unique_ptr< CTaxTreeBrowser::TTaxTree > m_Tree
Definition: tax_tree.cpp:113
CTaxTreeBrowser::TTaxTree * m_Curr
Definition: tax_tree.cpp:114
const CTaxTreeBrowser::TTaxMap & m_TaxMap
Definition: tax_tree.cpp:112
ITreeIterator::EAction LevelEnd(const ITaxon1Node *tax_node)
Definition: tax_tree.cpp:105
ITreeIterator::EAction Execute(const ITaxon1Node *tax_node)
Definition: tax_tree.cpp:75
CTreeFiller(CTaxTreeDataSource &ds, const CTaxTreeBrowser::TTaxMap &tax_map)
Definition: tax_tree.cpp:57
ITreeIterator::EAction LevelBegin(const ITaxon1Node *tax_node)
Definition: tax_tree.cpp:65
definition of a Culling tree
Definition: ncbi_tree.hpp:100
virtual TTaxId GetTaxId() const =0
EAction TraverseDownward(I4Each &, unsigned levels=kMax_UInt)
Definition: taxon1.cpp:1983
container_type::const_iterator const_iterator
Definition: map.hpp:53
const_iterator end() const
Definition: map.hpp:152
const_iterator find(const key_type &key) const
Definition: map.hpp:153
Definition: map.hpp:338
static DLIST_TYPE *DLIST_NAME() next(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
Definition: dlist.tmpl.h:56
static const char * str(char *buf, int n)
Definition: stats.c:84
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
SStrictId_Tax::TId TTaxId
Taxon id type.
Definition: ncbimisc.hpp:1048
#define NULL
Definition: ncbistd.hpp:225
#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 Warning(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1191
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.
virtual void SetMessage(const string &msg)=0
vector< CConstRef< CObject > > TConstObjects
Definition: objects.hpp:64
virtual void SetPctCompleted(int pct)=0
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:773
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
static string SizetToString(size_t value, TNumToStringFlags flags=0, int base=10)
Convert size_t to string.
Definition: ncbistr.cpp:2742
Fun TreeDepthFirstTraverse(TTreeNode &tree_node, Fun func)
Depth-first tree traversal algorithm.
Definition: ncbi_tree.hpp:504
ETreeTraverseCode
Tree traverse code returned by the traverse predicate function.
Definition: ncbi_tree.hpp:51
TNodeList::const_iterator TNodeList_CI
Definition: ncbi_tree.hpp:110
void AddNode(TTreeType *subnode)
Add new subnode.
Definition: ncbi_tree.hpp:743
const TValue & GetValue(void) const
Return node's value.
Definition: ncbi_tree.hpp:184
@ eTreeTraverse
Keep traversal.
Definition: ncbi_tree.hpp:52
static MDB_envinfo info
Definition: mdb_load.c:37
constexpr auto sort(_Init &&init)
mdb_mode_t mode
Definition: lmdb++.h:38
const struct ncbi::grid::netcache::search::fields::SIZE size
Int4 delta(size_t dimension_, const Int4 *score_)
static int new_info(pcre *re, pcre_extra *study, int option, void *ptr)
Definition: pcretest.c:2421
our internal tree structure
Definition: tax_tree.hpp:76
CTaxTreeDataSource::TUidVec uids
Definition: tax_tree.cpp:225
ETreeTraverseCode operator()(CTaxTreeBrowser::TTaxTree &node, int delta)
Definition: tax_tree.cpp:226
ETreeTraverseCode operator()(CTaxTreeBrowser::TTaxTree &node, int delta_level)
Definition: tax_tree.cpp:349
size_t uids
Definition: tax_tree.cpp:348
USING_SCOPE(objects)
#define _ASSERT
wxString ToWxString(const string &s)
Definition: wx_utils.hpp:173
Modified on Fri Jul 19 17:07:40 2024 by modify_doxy.py rev. 669887