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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: build_tree.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 20:57:01  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.12
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: build_tree.cpp,v 1000.1 2004/06/01 20:57:01 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:  Josh Cherry
  35.  *
  36.  * File Description:  gbench plugin for phylogenetic tree building
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include "build_tree.hpp"
  41. #include <gui/core/idocument.hpp>
  42. #include <gui/core/plugin_utils.hpp>
  43. #include <gui/plugin/PluginCommandSet.hpp>
  44. #include <gui/plugin/PluginValue.hpp>
  45. #include <gui/plugin/PluginInfo.hpp>
  46. #include <gui/plugin/PluginReply.hpp>
  47. #include <gui/plugin/PluginRequest.hpp>
  48. #include <gui/plugin/PluginValueConstraint.hpp>
  49. #include <gui/core/version.hpp>
  50. #include <gui/core/doc_manager.hpp>
  51. #include <gui/objutils/utils.hpp>
  52. #include <gui/utils/message_box.hpp>
  53. #include <objmgr/scope.hpp>
  54. #include <objmgr/util/sequence.hpp>
  55. #include <objtools/alnmgr/alnmix.hpp>
  56. #include <algo/phy_tree/dist_methods.hpp>
  57. #include <algo/phy_tree/phy_tree_serial.hpp>
  58. #include <objects/seq/Seq_descr.hpp>
  59. #include <objects/seq/Seqdesc.hpp>
  60. #include <objects/seqfeat/Org_ref.hpp>
  61. #include <objects/seqfeat/BioSource.hpp>
  62. #include <objtools/alnmgr/alnmix.hpp>
  63. #include <objtools/alnmgr/alnvec.hpp>
  64. BEGIN_NCBI_SCOPE
  65. USING_SCOPE(objects);
  66. static const string sc_JukesCantor("Jukes-Cantor (DNA)");
  67. static const string sc_Kimura("Kimura (protein)");
  68. static const string sc_Poisson("Poisson (protein)");
  69. static const string sc_FastMe("Fast Minimum Evolution");
  70. static const string sc_Nj("Neighbor Joining");
  71. static const string sc_SeqId("Sequence ID");
  72. static const string sc_TaxName("Taxonomic Name (if available)");
  73. static const string sc_SeqTitle("Sequence Title (if available)");
  74. // standard info boilerplate
  75. void CAlgoPlugin_BuildTree::GetInfo(CPluginInfo& info)
  76. {
  77.     info.Reset();
  78.     // version info macro
  79.     info.SetInfo(CPluginVersion::eMajor, CPluginVersion::eMinor, 0,
  80.                  string(__DATE__) + " " + string(__TIME__),
  81.                  "CAlgoPlugin_BuildTree", "Phylogenetic trees/Build tree",
  82.                  "Build tree from alignment using a distance method",
  83.                  "");
  84.     // command info
  85.     CPluginCommandSet& cmds = info.SetCommands();
  86.     CPluginCommand&    args = cmds.AddAlgoCommand(eAlgoCommand_run);
  87.     args.AddArgument("aligns", "Input alignments",
  88.                      CSeq_align::GetTypeInfo(),
  89.                      CPluginArg::TData::e_Array);
  90.     args.AddDefaultArgument("dist_calc", "Distance Method",
  91.                             CPluginArg::eString, sc_Kimura);
  92.     args.SetConstraint("dist_calc", (*CPluginValueConstraint::CreateSet(),
  93.                                      sc_Kimura, sc_Poisson, sc_JukesCantor));
  94.     args.AddDefaultArgument("tree_method", "Tree Construct Method",
  95.                             CPluginArg::eString, sc_FastMe);
  96.     args.SetConstraint("tree_method", (*CPluginValueConstraint::CreateSet(),
  97.                                        sc_FastMe, sc_Nj));
  98.     args.AddDefaultArgument("label_type", "Labels for Leaf Nodes",
  99.                             CPluginArg::eString, sc_SeqId);
  100.     args.SetConstraint("label_type", (*CPluginValueConstraint::CreateSet(),
  101.                                       sc_SeqId, sc_TaxName, sc_SeqTitle));
  102. }
  103. void CAlgoPlugin_BuildTree::RunCommand(CPluginMessage& msg)
  104. {
  105.     const CPluginCommand& args = msg.GetRequest().GetCommand();
  106.     CPluginReply& reply = msg.SetReply();
  107.     reply.SetStatus(eMessageStatus_failed);
  108.     _TRACE("CAlgoPlugin_BuildTree::Run()");
  109.     // retrieve our alignments
  110.     plugin_args::TAlignList aligns;
  111.     GetArgValue(args["aligns"], aligns);
  112.     // merge them
  113.     CConstRef<IDocument> doc_ref;
  114.     ITERATE (plugin_args::TAlignList, iter, aligns) {
  115.         if (doc_ref.GetPointer()  &&  iter->first != doc_ref) {
  116.             NcbiMessageBox("Failed to merge alignments:n"
  117.                            "All alignments must be in the same document");
  118.             return;
  119.         }
  120.         doc_ref = iter->first;
  121.     }
  122.     CAlnMix mix(doc_ref->GetScope());
  123.     CAlnMix::TAddFlags   add_flags = 0;
  124.     CAlnMix::TMergeFlags merge_flags =
  125.         CAlnMix::fGen2EST |
  126.         CAlnMix::fTryOtherMethodOnFail |
  127.         CAlnMix::fGapJoin;
  128.     try {
  129.         ITERATE (plugin_args::TAlignList, iter, aligns) {
  130.             mix.Add(*iter->second, add_flags);
  131.         }
  132.         mix.Merge(merge_flags);
  133.     }
  134.     catch (CException& e) {
  135.         NcbiMessageBox("Failed to merge alignments:n" +
  136.                        e.GetMsg());
  137.         return;
  138.     }
  139.     
  140.     CAlnVec alnvec(mix.GetSeqAlign().GetSegs().GetDenseg(),
  141.                    doc_ref->GetScope());
  142.     alnvec.SetGapChar('-');
  143.     const string& dist_calc = args["dist_calc"].AsString();
  144.     const string& tree_method = args["tree_method"].AsString();
  145.     // Come up with some labels for the terminal nodes
  146.     vector<string> labels(alnvec.GetNumRows());
  147.     for (int i = 0;  i < alnvec.GetNumRows();  ++i) {
  148.         if (args["label_type"].AsString() == sc_TaxName) {
  149.             if (alnvec.GetBioseqHandle(i).IsSetDescr()) {
  150.                 ITERATE (list<CRef<CSeqdesc> >, iter,
  151.                          alnvec.GetBioseqHandle(i).GetDescr().Get()) {
  152.                     if ((*iter)->IsSource()) {
  153.                         if ((*iter)->GetSource().GetOrg().IsSetTaxname()) {
  154.                             labels[i] = (*iter)->GetSource().GetOrg()
  155.                                 .GetTaxname();
  156.                             break;
  157.                         }
  158.                     }
  159.                 }
  160.             }
  161.         }
  162.         if (args["label_type"].AsString() == sc_SeqTitle) {
  163.             if (alnvec.GetBioseqHandle(i).IsSetDescr()) {
  164.                 ITERATE (list<CRef<CSeqdesc> >, iter,
  165.                          alnvec.GetBioseqHandle(i).GetDescr().Get()) {
  166.                     if ((*iter)->IsTitle()) {
  167.                         labels[i] = (*iter)->GetTitle();
  168.                         break;
  169.                     }
  170.                 }
  171.             }
  172.         }
  173.         // if sc_SeqId, or if above found no appropriate data
  174.         if (labels[i].empty()) {
  175.             const CSeq_id& best_id =
  176.                 sequence::GetId(alnvec.GetBioseqHandle(i),
  177.                                 sequence::eGetId_Best);
  178.             best_id.GetLabel(&labels[i]);
  179.         }
  180.     }
  181.     // Calculate pairwise distances
  182.     CDistMethods::TMatrix pmat;
  183.     CDistMethods::Divergence(alnvec, pmat);
  184.     CDistMethods::TMatrix dmat;
  185.     if (dist_calc == sc_Kimura) {
  186.         CDistMethods::KimuraDist(pmat, dmat);
  187.     } else if (dist_calc == sc_JukesCantor) {
  188.         CDistMethods::JukesCantorDist(pmat, dmat);
  189.     } else if (dist_calc == sc_Poisson) {
  190.         CDistMethods::PoissonDist(pmat, dmat);
  191.     } else {
  192.         throw runtime_error(string("Invalid distance calculation type:  ")
  193.                             + dist_calc);
  194.     }
  195.     // Build a tree based on distances
  196.     auto_ptr<TPhyTreeNode> tree;
  197.     if (tree_method == sc_FastMe) {
  198.         tree.reset(CDistMethods::FastMeTree(dmat, labels));
  199.     } else if (tree_method == sc_Nj) {
  200.         tree.reset(CDistMethods::NjTree(dmat, labels));
  201.     } else {
  202.         throw runtime_error(string("Invalid tree reconstruction algorithm:  ")
  203.                             + tree_method);
  204.     }
  205.     CRef<CPhyTreeSerial> stree(new CPhyTreeSerial(*tree.get()));
  206.     // Set Seq-ids, in order.  This relies on the tree-building
  207.     // algorithm to set the node ids of the leaf nodes
  208.     // to {0, 1, 2...} in the appropriate order.
  209.     CPhyTreeSerial::TIds& ids = stree->SetIds();
  210.     ids.reserve(alnvec.GetNumRows());
  211.     for (int i = 0;  i < alnvec.GetNumRows();  ++i) {
  212.         CRef<CSeq_id> id(new CSeq_id);
  213.         id->Assign(sequence::GetId(alnvec.GetBioseqHandle(i),
  214.                                    sequence::eGetId_Best));
  215.         ids.push_back(id);
  216.     }
  217.     reply.AddObject(*doc_ref, *stree);
  218.     reply.AddAction(CPluginReplyAction::e_Add_to_document);
  219.     reply.SetStatus(eMessageStatus_success);
  220.     CRef<CSelectionBuffer> buf(new CSelectionBuffer());
  221.     buf->AddSelection(doc_ref, *stree);
  222.     CPluginUtils::CallPlugin("CPhyloTreeView",
  223.                              eViewCommand_new_view, *buf);
  224.     /**
  225.     CRef<CScope> scope(new CScope(CDocManager::GetObjectManager()));
  226.     scope->AddDefaults();
  227.     IDocument* new_doc = CDocManager::CreateDocument(*scope, *stree);
  228.     CDocManager::UpdateAllViews();
  229.     // launch tree viewer plugin
  230.     CRef<CSelectionBuffer> buf(new CSelectionBuffer());
  231.     buf->AddSelection(new_doc, *stree);
  232.     CPluginUtils::CallPlugin("CPhyloTreeView", eViewCommand_new_view, *buf);
  233.     reply.AddObject(*new_doc);
  234.     reply.SetStatus(eMessageStatus_success);
  235.     **/
  236. }
  237. END_NCBI_SCOPE
  238. /*
  239.  * ===========================================================================
  240.  * $Log: build_tree.cpp,v $
  241.  * Revision 1000.1  2004/06/01 20:57:01  gouriano
  242.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.12
  243.  *
  244.  * Revision 1.12  2004/05/21 22:27:48  gorelenk
  245.  * Added PCH ncbi_pch.hpp
  246.  *
  247.  * Revision 1.11  2004/05/20 12:38:30  dicuccio
  248.  * Added missing includes previously acquired through gui/objutils/utils.hpp (seq_vector.hpp, alignment manager
  249.  *
  250.  * Revision 1.10  2004/05/15 03:17:04  ucko
  251.  * Add missing #includes (formerly indirect?)
  252.  *
  253.  * Revision 1.9  2004/05/03 13:05:42  dicuccio
  254.  * gui/utils --> gui/objutils where needed
  255.  *
  256.  * Revision 1.8  2004/04/07 13:00:55  dicuccio
  257.  * Fixed handling of documents.  Make sure not to create a new document for the
  258.  * phylogenetic tree - just add it to the current document
  259.  *
  260.  * Revision 1.7  2004/04/05 19:57:56  jcherry
  261.  * More options for leaf labels
  262.  *
  263.  * Revision 1.6  2004/03/17 17:58:27  jcherry
  264.  * Seq-ids for fastme too
  265.  *
  266.  * Revision 1.5  2004/03/17 16:54:14  jcherry
  267.  * Record Seq-ids when doing neighbor-joining
  268.  *
  269.  * Revision 1.4  2004/03/11 17:41:27  dicuccio
  270.  * Cleaned up text description of parameters.  Changed merge flags to be
  271.  * consistent with other parts of toolkit.  Use sequence::GetId() instead of
  272.  * CSeq_id::GetStringDescr()
  273.  *
  274.  * Revision 1.3  2004/02/19 17:41:34  jcherry
  275.  * Automatically launch tree viewer plugin
  276.  *
  277.  * Revision 1.2  2004/02/17 21:31:41  jcherry
  278.  * Call UpdateAllViews() to update document menu
  279.  *
  280.  * ===========================================================================
  281.  */