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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: tax_tree.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 21:13:24  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: tax_tree.cpp,v 1000.1 2004/06/01 21:13:24 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Mike DiCuccio
  35.  *
  36.  * File Description:
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <gui/widgets/tax_tree/tax_tree.hpp>
  41. #include <gui/widgets/tax_tree/tax_tree_ds.hpp>
  42. #include <gui/utils/reporter.hpp>
  43. #include <gui/objutils/utils.hpp>
  44. #include <objects/taxon1/taxon1.hpp>
  45. #include <algorithm>
  46. #include <stack>
  47. BEGIN_NCBI_SCOPE
  48. USING_SCOPE(objects);
  49. //
  50. // internal tree structure
  51. //
  52. class CTaxTree
  53. {
  54. public:
  55.     typedef list<CTaxTree*> TChildren;
  56.     CTaxTree(const CTaxTreeDataSource& ds,
  57.              const ITaxon1Node* node,
  58.              const CTaxTreeDataSource::TUidVec& uids)
  59.         : m_TaxNode(node)
  60.         , m_Uids(uids)
  61.         , m_DS(&ds)
  62.     {      
  63.     }
  64.     ~CTaxTree()
  65.     {
  66.         Clear();
  67.     }
  68.     void AddChild(CTaxTree* child)
  69.     {
  70.         m_Children.push_back(child);
  71.     }
  72.     void RemoveChild(CTaxTree* child)
  73.     {
  74.         m_Children.remove(child);
  75.     }
  76.     string GetName(void) const
  77.     {
  78.         string str;
  79.         m_DS->GetTitle(*m_TaxNode, &str);
  80.         str += " (" + NStr::IntToString(CountUids()) + " sequences)";
  81.         return str;
  82.     }
  83.     void Clear(void)
  84.     {
  85.         NON_CONST_ITERATE (TChildren, iter, m_Children) {
  86.             delete *iter;
  87.         }
  88.         m_Children.clear();
  89.     }
  90.     size_t CountUids(void) const
  91.     {
  92.         size_t sum = m_Uids.size();
  93.         ITERATE (TChildren, iter, m_Children) {
  94.             sum += (*iter)->CountUids();
  95.         }
  96.         return sum;
  97.     }
  98.     void CollectUids(CTaxTreeDataSource::TUidVec& uids) const
  99.     {
  100.         uids.insert(uids.end(), m_Uids.begin(), m_Uids.end());
  101.         ITERATE (TChildren, iter, m_Children) {
  102.             (*iter)->CollectUids(uids);
  103.         }
  104.     }
  105.     // information for this node
  106.     CConstRef<CTaxTreeDataSource> m_DS;
  107.     const ITaxon1Node* m_TaxNode;
  108.     CTaxTreeDataSource::TUidVec m_Uids;
  109.     TChildren m_Children;
  110. };
  111. //
  112. // internal class to fill our tree structure
  113. //
  114. class CTreeFiller : public ITreeIterator::I4Each
  115. {
  116. public:
  117.     CTreeFiller(CTaxTreeDataSource& ds,
  118.                 const CTaxTreeBrowser::TTaxMap& tax_map)
  119.         : m_TaxMap(tax_map)
  120.         , m_Curr(NULL)
  121.         , m_DS(&ds)
  122.     {
  123.     }
  124.     ITreeIterator::EAction LevelBegin(const ITaxon1Node* tax_node)
  125.     {
  126.         if (m_Curr) {
  127.             m_Nodes.push(m_Curr);
  128.         }
  129.         m_Curr = NULL;
  130.         return ITreeIterator::eOk;
  131.     }
  132.     ITreeIterator::EAction Execute(const ITaxon1Node* tax_node)
  133.     {
  134.         CTaxTreeDataSource::TUidVec uids;
  135.         int tax_id = tax_node->GetTaxId();
  136.         CTaxTreeBrowser::TTaxMap::const_iterator iter = m_TaxMap.find(tax_id);
  137.         if (iter != m_TaxMap.end()) {
  138.             uids = iter->second;
  139.         }
  140.         CTaxTree* node = new CTaxTree(*m_DS, tax_node, uids);
  141.         if ( !m_Tree.get() ) {
  142.             m_Tree.reset(node);
  143.         }
  144.         if (m_Nodes.size()) {
  145.             CTaxTree* parent = m_Nodes.top();
  146.             parent->AddChild(node);
  147.         }
  148.         m_Curr = node;
  149.         return ITreeIterator::eOk;
  150.     }
  151.     ITreeIterator::EAction LevelEnd(const ITaxon1Node* tax_node)
  152.     {
  153.         m_Curr = m_Nodes.top();
  154.         m_Nodes.pop();
  155.         return ITreeIterator::eOk;
  156.     }
  157.     const CTaxTreeBrowser::TTaxMap& m_TaxMap;
  158.     auto_ptr<CTaxTree> m_Tree;
  159.     CTaxTree* m_Curr;
  160.     CConstRef<CTaxTreeDataSource> m_DS;
  161.     stack<CTaxTree*> m_Nodes;
  162. };
  163. // callback - not a good way to go, but keeps FluTree unchanged
  164. // in case it will be updated externally
  165. void OnTaxtreeNotify(Fl_Widget * widget, void * data)
  166. {
  167.     CTaxTreeBrowser     * pTaxTree = dynamic_cast<CTaxTreeBrowser*>   (widget);
  168.     
  169.     if (pTaxTree) {    
  170.         CTaxTreeDataSource::TUidVec uids;
  171.         uids.clear();
  172.         
  173.         pTaxTree->GetSelectedUids(uids);
  174.         switch (pTaxTree->callback_reason()) {
  175.         case FLU_SELECTED: 
  176.         case FLU_UNSELECTED: {            
  177.             CObjectFor< vector<CConstRef<objects::CSeq_id> > > csid;
  178.             csid = uids;
  179.             pTaxTree->FireEvent(CViewEvent::CreateEvent(CViewEvent::eSelectionChanged,  CViewEvent::eEventViews, CViewEvent::TEventObject(&csid), pTaxTree));     
  180.         }    
  181.         }
  182.     }    
  183. }
  184. CTaxTreeBrowser::CTaxTreeBrowser(int x, int y, int w, int h, const char* label)
  185.     : CTreeBrowser(x, y, w, h, label)
  186.     , m_Reporter(NULL)
  187.     , m_DispMode(CTaxTreeDataSource::eDisplay_Default)
  188. {
  189.     callback(OnTaxtreeNotify);
  190.     show_root(false);    
  191. }
  192. CTaxTreeBrowser::~CTaxTreeBrowser()
  193. {
  194. }
  195. void CTaxTreeBrowser::SetReporter(IReporter* reporter)
  196. {
  197.     m_Reporter = reporter;
  198. }
  199. void CTaxTreeBrowser::SetDataSource(CTaxTreeDataSource& ds)
  200. {
  201.     m_DataSource.Reset(&ds);
  202.     x_Refresh();
  203. }
  204. void CTaxTreeBrowser::x_Refresh()
  205. {
  206.     // clear the tree to start
  207.     clear();
  208.     if (m_Reporter) {
  209.         m_Reporter->SetMessage("Retrieving taxonomic IDs...");
  210.     }
  211.     TTaxMap tax_map;
  212.     m_DataSource->GetTaxMap(tax_map);
  213.     ITreeIterator& iter = m_DataSource->GetIterator(m_DispMode);
  214.     CTreeFiller filler(*m_DataSource, tax_map);
  215.     iter.TraverseDownward(filler);
  216.     m_TaxTree.reset(filler.m_Tree.release());
  217.     // next, populate the browser
  218.     if (m_TaxTree.get()) {
  219.         x_PopulateTree(get_root(), m_TaxTree.get());
  220.     }
  221.     if (m_Reporter) {
  222.         m_Reporter->SetMessage("Done.");
  223.         m_Reporter->SetPctCompleted(0);
  224.     }
  225.     redraw();
  226. }
  227. void CTaxTreeBrowser::SetDisplayMode(CTaxTreeDataSource::EDisplayMode mode)
  228. {
  229.     m_DispMode = mode;
  230.     x_Refresh();
  231. }
  232. void CTaxTreeBrowser::GetSelectedUids(CTaxTreeDataSource::TUidVec& uids) const
  233. {
  234.     Node* node = NULL;
  235.     
  236.     while ( (node = GetSelected(node)) != NULL) {
  237.         
  238.         CTaxTree * tree = reinterpret_cast<CTaxTree *>(node->user_data());
  239.         
  240.         if (tree){
  241.             if (!node->is_leaf()){                        
  242.                
  243.                 tree->CollectUids(uids);                        
  244.             }
  245.             else {                   
  246.                 int idx = node->id() - node->parent()->id() - 1;                
  247.                 uids.push_back(tree->m_Uids[idx>=0?idx:0]);                            
  248.             }
  249.         }
  250.         if ((node = node->next())==NULL) break;        
  251.     }
  252.     std::sort(uids.begin(), uids.end());
  253.     uids.erase(std::unique(uids.begin(), uids.end()), uids.end());
  254. }
  255. void CTaxTreeBrowser::x_PopulateTree(Node* node, CTaxTree* tree)
  256. {
  257.     // add a node for the current branch
  258.     node = AddChild(tree->GetName(), node);
  259.     
  260.     node->user_data(tree);
  261.     
  262.     // recurse our tree
  263.     if (tree->m_Children.size()) {
  264.         if (tree->m_Children.size() == 1) {
  265.             node->open(true);
  266.         }
  267.         ITERATE (CTaxTree::TChildren, iter, tree->m_Children) {
  268.             x_PopulateTree(node, *iter);
  269.         }
  270.     } else {        
  271.         // add uids
  272.         string str;
  273.         ITERATE (CTaxTreeDataSource::TUidVec, iter, tree->m_Uids) {
  274.             str.erase();
  275.             m_DataSource->GetTitle(**iter, &str);         
  276.             
  277.             Node * leafNode = AddLeaf(str, node);                  
  278.             leafNode->user_data(tree);
  279.         }
  280.     }
  281. }
  282. void CTaxTreeBrowser::SetSelectedUids(const CTaxTreeDataSource::TUidVec& uids, Node* node)
  283. {
  284.     CTaxTree * tree = reinterpret_cast<CTaxTree *>(node->user_data());
  285.     if (node->is_leaf()){                        
  286.         int idx = node->id() - node->parent()->id() - 1;                
  287.          CTaxTreeDataSource::TUid uid = tree->m_Uids[idx>=0?idx:0];                            
  288.          for (CTaxTreeDataSource::TUidVec::const_iterator itt=uids.begin(); itt!=uids.end(); itt++){
  289.              if (CSeqUtils::Match(**itt, *uid, (CScope*) m_DataSource->GetScope().GetPointer())){         
  290.                 node->select(true);
  291.                 
  292.                 Node * parNode = node;
  293.                 while (!((parNode=parNode->parent())->is_root())) {
  294.                     parNode->open(true); 
  295.                 
  296.                     Node * chNode = NULL;
  297.                     bool   bsel   = true;
  298.                     do {
  299.                         if (!chNode) chNode = parNode->first_leaf();
  300.                         else         chNode = chNode->next_leaf();
  301.                     
  302.                         if (!(bsel=chNode->selected())) break;                    
  303.                     
  304.                     } while (chNode!=parNode->last_leaf());
  305.                     parNode->select(bsel);
  306.                 }
  307.              }
  308.          }
  309.     }
  310.     if (node->next()) SetSelectedUids(uids, node->next());   
  311. }
  312. void CTaxTreeBrowser::OnSelChangedEvent(CViewEvent::TEventObject obj)
  313. {
  314.     CObjectFor< vector<CConstRef<objects::CSeq_id> > > * csid = 
  315.             dynamic_cast< CObjectFor< vector<CConstRef<objects::CSeq_id> > > *>(obj.GetPointer());
  316.     
  317.     if (csid){           
  318.         unselect_all();        
  319.         SetSelectedUids(*csid, get_root());       
  320.     } 
  321. }
  322. END_NCBI_SCOPE
  323. /*
  324.  * ===========================================================================
  325.  * $Log: tax_tree.cpp,v $
  326.  * Revision 1000.1  2004/06/01 21:13:24  gouriano
  327.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
  328.  *
  329.  * Revision 1.11  2004/05/21 22:27:55  gorelenk
  330.  * Added PCH ncbi_pch.hpp
  331.  *
  332.  * Revision 1.10  2004/05/13 17:31:46  dicuccio
  333.  * Renamed data source file
  334.  *
  335.  * Revision 1.9  2004/05/03 13:23:58  dicuccio
  336.  * gui/utils --> gui/objutils where needed
  337.  *
  338.  * Revision 1.8  2004/04/09 20:02:28  tereshko
  339.  * Extended tree selection logic
  340.  *
  341.  * Revision 1.7  2004/04/09 16:53:32  tereshko
  342.  * Added functionality to send/accept selections
  343.  *
  344.  * Revision 1.6  2004/04/07 13:13:04  dicuccio
  345.  * Changed storage of sequence info to use CConstRef<CSeq_id>
  346.  *
  347.  * Revision 1.5  2004/04/01 19:03:13  dicuccio
  348.  * Added support for limiting the list of displayed nodes.  Changed retrieval of
  349.  * tax-id to favor sequence first
  350.  *
  351.  * Revision 1.4  2004/01/07 18:55:36  dicuccio
  352.  * Code clean-up.  Don't forget to initialize or CTaxon1 class
  353.  *
  354.  * Revision 1.3  2003/12/23 15:39:18  dicuccio
  355.  * Altered the data source - expose an ITreeIterator; the widget no longer
  356.  * directly creates a CTaxon1 class.  Chaned storage notion from 'gi' to 'uid'
  357.  *
  358.  * Revision 1.2  2003/12/22 21:57:35  ucko
  359.  * ITreeIterator::Execute: use a const_iterator because m_TaxMap is const.
  360.  *
  361.  * Revision 1.1  2003/12/22 19:42:59  dicuccio
  362.  * Initial revision
  363.  *
  364.  * ===========================================================================
  365.  */