tax_tree.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:12k
- /*
- * ===========================================================================
- * PRODUCTION $Log: tax_tree.cpp,v $
- * PRODUCTION Revision 1000.1 2004/06/01 21:13:24 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: tax_tree.cpp,v 1000.1 2004/06/01 21:13:24 gouriano Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * Authors: Mike DiCuccio
- *
- * File Description:
- *
- */
- #include <ncbi_pch.hpp>
- #include <gui/widgets/tax_tree/tax_tree.hpp>
- #include <gui/widgets/tax_tree/tax_tree_ds.hpp>
- #include <gui/utils/reporter.hpp>
- #include <gui/objutils/utils.hpp>
- #include <objects/taxon1/taxon1.hpp>
- #include <algorithm>
- #include <stack>
- BEGIN_NCBI_SCOPE
- USING_SCOPE(objects);
- //
- // internal tree structure
- //
- class CTaxTree
- {
- public:
- typedef list<CTaxTree*> TChildren;
- CTaxTree(const CTaxTreeDataSource& ds,
- const ITaxon1Node* node,
- const CTaxTreeDataSource::TUidVec& uids)
- : m_TaxNode(node)
- , m_Uids(uids)
- , m_DS(&ds)
- {
- }
- ~CTaxTree()
- {
- Clear();
- }
- void AddChild(CTaxTree* child)
- {
- m_Children.push_back(child);
- }
- void RemoveChild(CTaxTree* child)
- {
- m_Children.remove(child);
- }
- string GetName(void) const
- {
- string str;
- m_DS->GetTitle(*m_TaxNode, &str);
- str += " (" + NStr::IntToString(CountUids()) + " sequences)";
- return str;
- }
- void Clear(void)
- {
- NON_CONST_ITERATE (TChildren, iter, m_Children) {
- delete *iter;
- }
- m_Children.clear();
- }
- size_t CountUids(void) const
- {
- size_t sum = m_Uids.size();
- ITERATE (TChildren, iter, m_Children) {
- sum += (*iter)->CountUids();
- }
- return sum;
- }
- void CollectUids(CTaxTreeDataSource::TUidVec& uids) const
- {
- uids.insert(uids.end(), m_Uids.begin(), m_Uids.end());
- ITERATE (TChildren, iter, m_Children) {
- (*iter)->CollectUids(uids);
- }
- }
- // information for this node
- CConstRef<CTaxTreeDataSource> m_DS;
- const ITaxon1Node* m_TaxNode;
- CTaxTreeDataSource::TUidVec m_Uids;
- TChildren m_Children;
- };
- //
- // internal class to fill our tree structure
- //
- class CTreeFiller : public ITreeIterator::I4Each
- {
- public:
- CTreeFiller(CTaxTreeDataSource& ds,
- const CTaxTreeBrowser::TTaxMap& tax_map)
- : m_TaxMap(tax_map)
- , m_Curr(NULL)
- , m_DS(&ds)
- {
- }
- ITreeIterator::EAction LevelBegin(const ITaxon1Node* tax_node)
- {
- if (m_Curr) {
- m_Nodes.push(m_Curr);
- }
- m_Curr = NULL;
- return ITreeIterator::eOk;
- }
- ITreeIterator::EAction Execute(const ITaxon1Node* tax_node)
- {
- CTaxTreeDataSource::TUidVec uids;
- int tax_id = tax_node->GetTaxId();
- CTaxTreeBrowser::TTaxMap::const_iterator iter = m_TaxMap.find(tax_id);
- if (iter != m_TaxMap.end()) {
- uids = iter->second;
- }
- CTaxTree* node = new CTaxTree(*m_DS, tax_node, uids);
- if ( !m_Tree.get() ) {
- m_Tree.reset(node);
- }
- if (m_Nodes.size()) {
- CTaxTree* parent = m_Nodes.top();
- parent->AddChild(node);
- }
- m_Curr = node;
- return ITreeIterator::eOk;
- }
- ITreeIterator::EAction LevelEnd(const ITaxon1Node* tax_node)
- {
- m_Curr = m_Nodes.top();
- m_Nodes.pop();
- return ITreeIterator::eOk;
- }
- const CTaxTreeBrowser::TTaxMap& m_TaxMap;
- auto_ptr<CTaxTree> m_Tree;
- CTaxTree* m_Curr;
- CConstRef<CTaxTreeDataSource> m_DS;
- stack<CTaxTree*> m_Nodes;
- };
- // callback - not a good way to go, but keeps FluTree unchanged
- // in case it will be updated externally
- void OnTaxtreeNotify(Fl_Widget * widget, void * data)
- {
- CTaxTreeBrowser * pTaxTree = dynamic_cast<CTaxTreeBrowser*> (widget);
-
- if (pTaxTree) {
- CTaxTreeDataSource::TUidVec uids;
- uids.clear();
-
- pTaxTree->GetSelectedUids(uids);
- switch (pTaxTree->callback_reason()) {
- case FLU_SELECTED:
- case FLU_UNSELECTED: {
- CObjectFor< vector<CConstRef<objects::CSeq_id> > > csid;
- csid = uids;
- pTaxTree->FireEvent(CViewEvent::CreateEvent(CViewEvent::eSelectionChanged, CViewEvent::eEventViews, CViewEvent::TEventObject(&csid), pTaxTree));
- }
- }
- }
- }
- CTaxTreeBrowser::CTaxTreeBrowser(int x, int y, int w, int h, const char* label)
- : CTreeBrowser(x, y, w, h, label)
- , m_Reporter(NULL)
- , m_DispMode(CTaxTreeDataSource::eDisplay_Default)
- {
- callback(OnTaxtreeNotify);
- show_root(false);
- }
- CTaxTreeBrowser::~CTaxTreeBrowser()
- {
- }
- void CTaxTreeBrowser::SetReporter(IReporter* reporter)
- {
- m_Reporter = reporter;
- }
- void CTaxTreeBrowser::SetDataSource(CTaxTreeDataSource& ds)
- {
- m_DataSource.Reset(&ds);
- x_Refresh();
- }
- void CTaxTreeBrowser::x_Refresh()
- {
- // clear the tree to start
- clear();
- if (m_Reporter) {
- m_Reporter->SetMessage("Retrieving taxonomic IDs...");
- }
- TTaxMap tax_map;
- m_DataSource->GetTaxMap(tax_map);
- ITreeIterator& iter = m_DataSource->GetIterator(m_DispMode);
- CTreeFiller filler(*m_DataSource, tax_map);
- iter.TraverseDownward(filler);
- m_TaxTree.reset(filler.m_Tree.release());
- // next, populate the browser
- if (m_TaxTree.get()) {
- x_PopulateTree(get_root(), m_TaxTree.get());
- }
- if (m_Reporter) {
- m_Reporter->SetMessage("Done.");
- m_Reporter->SetPctCompleted(0);
- }
- redraw();
- }
- void CTaxTreeBrowser::SetDisplayMode(CTaxTreeDataSource::EDisplayMode mode)
- {
- m_DispMode = mode;
- x_Refresh();
- }
- void CTaxTreeBrowser::GetSelectedUids(CTaxTreeDataSource::TUidVec& uids) const
- {
- Node* node = NULL;
-
- while ( (node = GetSelected(node)) != NULL) {
-
- CTaxTree * tree = reinterpret_cast<CTaxTree *>(node->user_data());
-
- if (tree){
- if (!node->is_leaf()){
-
- tree->CollectUids(uids);
- }
- else {
- int idx = node->id() - node->parent()->id() - 1;
- uids.push_back(tree->m_Uids[idx>=0?idx:0]);
- }
- }
- if ((node = node->next())==NULL) break;
- }
- std::sort(uids.begin(), uids.end());
- uids.erase(std::unique(uids.begin(), uids.end()), uids.end());
- }
- void CTaxTreeBrowser::x_PopulateTree(Node* node, CTaxTree* tree)
- {
- // add a node for the current branch
- node = AddChild(tree->GetName(), node);
-
- node->user_data(tree);
-
- // recurse our tree
- if (tree->m_Children.size()) {
- if (tree->m_Children.size() == 1) {
- node->open(true);
- }
- ITERATE (CTaxTree::TChildren, iter, tree->m_Children) {
- x_PopulateTree(node, *iter);
- }
- } else {
- // add uids
- string str;
- ITERATE (CTaxTreeDataSource::TUidVec, iter, tree->m_Uids) {
- str.erase();
- m_DataSource->GetTitle(**iter, &str);
-
- Node * leafNode = AddLeaf(str, node);
- leafNode->user_data(tree);
- }
- }
- }
- void CTaxTreeBrowser::SetSelectedUids(const CTaxTreeDataSource::TUidVec& uids, Node* node)
- {
- CTaxTree * tree = reinterpret_cast<CTaxTree *>(node->user_data());
- if (node->is_leaf()){
- int idx = node->id() - node->parent()->id() - 1;
- CTaxTreeDataSource::TUid uid = tree->m_Uids[idx>=0?idx:0];
- for (CTaxTreeDataSource::TUidVec::const_iterator itt=uids.begin(); itt!=uids.end(); itt++){
- if (CSeqUtils::Match(**itt, *uid, (CScope*) m_DataSource->GetScope().GetPointer())){
- node->select(true);
-
- Node * parNode = node;
- while (!((parNode=parNode->parent())->is_root())) {
- parNode->open(true);
-
- Node * chNode = NULL;
- bool bsel = true;
- do {
- if (!chNode) chNode = parNode->first_leaf();
- else chNode = chNode->next_leaf();
-
- if (!(bsel=chNode->selected())) break;
-
- } while (chNode!=parNode->last_leaf());
- parNode->select(bsel);
- }
- }
- }
- }
- if (node->next()) SetSelectedUids(uids, node->next());
- }
- void CTaxTreeBrowser::OnSelChangedEvent(CViewEvent::TEventObject obj)
- {
- CObjectFor< vector<CConstRef<objects::CSeq_id> > > * csid =
- dynamic_cast< CObjectFor< vector<CConstRef<objects::CSeq_id> > > *>(obj.GetPointer());
-
- if (csid){
- unselect_all();
- SetSelectedUids(*csid, get_root());
- }
- }
- END_NCBI_SCOPE
- /*
- * ===========================================================================
- * $Log: tax_tree.cpp,v $
- * Revision 1000.1 2004/06/01 21:13:24 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
- *
- * Revision 1.11 2004/05/21 22:27:55 gorelenk
- * Added PCH ncbi_pch.hpp
- *
- * Revision 1.10 2004/05/13 17:31:46 dicuccio
- * Renamed data source file
- *
- * Revision 1.9 2004/05/03 13:23:58 dicuccio
- * gui/utils --> gui/objutils where needed
- *
- * Revision 1.8 2004/04/09 20:02:28 tereshko
- * Extended tree selection logic
- *
- * Revision 1.7 2004/04/09 16:53:32 tereshko
- * Added functionality to send/accept selections
- *
- * Revision 1.6 2004/04/07 13:13:04 dicuccio
- * Changed storage of sequence info to use CConstRef<CSeq_id>
- *
- * Revision 1.5 2004/04/01 19:03:13 dicuccio
- * Added support for limiting the list of displayed nodes. Changed retrieval of
- * tax-id to favor sequence first
- *
- * Revision 1.4 2004/01/07 18:55:36 dicuccio
- * Code clean-up. Don't forget to initialize or CTaxon1 class
- *
- * Revision 1.3 2003/12/23 15:39:18 dicuccio
- * Altered the data source - expose an ITreeIterator; the widget no longer
- * directly creates a CTaxon1 class. Chaned storage notion from 'gi' to 'uid'
- *
- * Revision 1.2 2003/12/22 21:57:35 ucko
- * ITreeIterator::Execute: use a const_iterator because m_TaxMap is const.
- *
- * Revision 1.1 2003/12/22 19:42:59 dicuccio
- * Initial revision
- *
- * ===========================================================================
- */