NCBI C++ ToolKit
component_search_tool.cpp
Go to the documentation of this file.
00001 /*  $Id: component_search_tool.cpp 25238 2012-02-14 16:11:43Z ucko $
00002  * ===========================================================================
00003  *
00004  *                            PUBLIC DOMAIN NOTICE
00005  *               National Center for Biotechnology Information
00006  *
00007  *  This software/database is a "United States Government Work" under the
00008  *  terms of the United States Copyright Act.  It was written as part of
00009  *  the author's official duties as a United States Government employee and
00010  *  thus cannot be copyrighted.  This software/database is freely available
00011  *  to the public for use. The National Library of Medicine and the U.S.
00012  *  Government have not placed any restriction on its use or reproduction.
00013  *
00014  *  Although all reasonable efforts have been taken to ensure the accuracy
00015  *  and reliability of the software and data, the NLM and the U.S.
00016  *  Government do not and cannot warrant the performance or results that
00017  *  may be obtained by using this software or data. The NLM and the U.S.
00018  *  Government disclaim all warranties, express or implied, including
00019  *  warranties of performance, merchantability or fitness for any particular
00020  *  purpose.
00021  *
00022  *  Please cite the author in any work or product based on this material.
00023  *
00024  * ===========================================================================
00025  *
00026  * Authors:  Andrey Yazhuk
00027  *
00028  * File Description:
00029  *
00030  */
00031 
00032 #include <ncbi_pch.hpp>
00033 
00034 #include <gui/core/data_mining_service.hpp>
00035 #include "component_search_tool.hpp"
00036 
00037 #include <corelib/ncbitime.hpp>
00038 
00039 #include <gui/widgets/wx/message_box.hpp>
00040 #include <gui/widgets/wx/wx_utils.hpp>
00041 
00042 #include <gui/objutils/label.hpp>
00043 #include <gui/objutils/utils.hpp>
00044 #include <gui/widgets/wx/ui_tool_registry.hpp>
00045 
00046 #include <gui/utils/app_job_dispatcher.hpp>
00047 #include <gui/utils/init_registrar.hpp>
00048 
00049 #include <objmgr/util/sequence.hpp>
00050 #include <objmgr/seq_map_ci.hpp>
00051 
00052 #include <gui/utils/extension_impl.hpp>
00053 
00054 #include <wx/sizer.h>
00055 #include <wx/stattext.h>
00056 #include <wx/choice.h>
00057 #include <wx/srchctrl.h>
00058 
00059 
00060 #define ID_COMBOBOX 10003
00061 #define ID_TEXT     11414
00062 
00063 
00064 BEGIN_NCBI_SCOPE
00065 USING_SCOPE(objects);
00066 
00067 ///////////////////////////////////////////////////////////////////////////////
00068 /// IDMSearchTool
00069 CComponentSearchTool::CComponentSearchTool()
00070 {
00071 }
00072 
00073 
00074 string CComponentSearchTool::GetName() const
00075 {
00076     static string name("Component Search");
00077     return name;
00078 }
00079 
00080 
00081 IUITool* CComponentSearchTool::Clone() const
00082 {
00083     return new CComponentSearchTool();
00084 }
00085 
00086 
00087 string CComponentSearchTool::GetDescription() const
00088 {
00089     return "";
00090 }
00091 
00092 
00093 CIRef<IDMSearchForm> CComponentSearchTool::CreateSearchForm()
00094 {
00095     CIRef<IDMSearchForm> form(new CComponentSearchForm(*this));
00096     return form;
00097 }
00098 
00099 
00100 bool CComponentSearchTool::IsCompatible(IDataMiningContext* context)
00101 {
00102     ISeqLocSearchContext* sl_ctx =
00103         dynamic_cast<ISeqLocSearchContext*>(context);
00104     return sl_ctx != NULL;
00105 }
00106 
00107 
00108 CRef<CSearchJobBase> CComponentSearchTool::x_CreateJob(IDMSearchQuery& query)
00109 {
00110     CRef<CSearchJobBase> job;
00111     CComponentSearchQuery* f_query = dynamic_cast<CComponentSearchQuery*>(&query);
00112     if(f_query) {
00113         job.Reset(new CComponentSearchJob(*f_query));
00114     }
00115     return job;
00116 }
00117 
00118 
00119 
00120 string  CComponentSearchTool::GetExtensionIdentifier() const
00121 {
00122     return "search_tool::component_search_tool";
00123 }
00124 
00125 string  CComponentSearchTool::GetExtensionLabel() const
00126 {
00127     return "Datamining Tool - Component search";
00128 }
00129 
00130 
00131 ///////////////////////////////////////////////////////////////////////////////
00132 /// CComponentSearchQuery
00133 
00134 CComponentSearchQuery::CComponentSearchQuery(TScopedLocs& locs, const string& ids)
00135 :   CSearchQueryBase(locs),
00136     m_Ids(ids)
00137 {
00138 }
00139 
00140 
00141 ///////////////////////////////////////////////////////////////////////////////
00142 /// CComponentSearchForm
00143 
00144 CComponentSearchForm::CComponentSearchForm(CComponentSearchTool& tool)
00145 :   m_Tool(&tool)
00146 {
00147 }
00148 
00149 
00150 void CComponentSearchForm::Create()
00151 {
00152     x_CreateWidgets();
00153 }
00154 
00155 
00156 void CComponentSearchForm::Init()
00157 {
00158     CSearchFormBase::Init();
00159     
00160 
00161 
00162   //  x_UpdateData(eDDX_Set);
00163 }
00164 
00165 
00166 void CComponentSearchForm::UpdateContexts()
00167 {
00168     CSearchFormBase::UpdateContexts();
00169 }
00170 
00171 
00172 void CComponentSearchForm::x_CreateWidgets()
00173 {
00174 //    CSearchFormBase::x_CreateWidgets(2, 3, true);
00175 }
00176 
00177 
00178 IDMSearchTool* CComponentSearchForm::x_GetTool()
00179 {
00180     return m_Tool.GetPointer();
00181     
00182 }
00183 
00184 
00185 wxSizer *  CComponentSearchForm::GetWidget(wxWindow * parent)
00186 {
00187     if (!m_Sizer) {     
00188         wxFlexGridSizer * sz = new wxFlexGridSizer(1, 4, 0, 0);     
00189         sz->AddGrowableCol(3);
00190         m_Sizer = sz;
00191         
00192         m_Sizer->Add(new wxStaticText( parent, wxID_STATIC, wxT("Search Context:"), wxDefaultPosition, wxDefaultSize, 0 ),
00193             0, wxALIGN_CENTER_VERTICAL|wxALL, 5);   
00194 
00195         m_DbCombo = new wxChoice(parent, ID_COMBOBOX,
00196                                    wxDefaultPosition, wxDefaultSize,
00197                                    0, (const wxString*)NULL);
00198         
00199         m_Sizer->Add(m_DbCombo,1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);     
00200         
00201         m_Sizer->Add(new wxStaticText( parent, wxID_STATIC, wxT("Search Expression:"), wxDefaultPosition, wxDefaultSize, 0 ),
00202             0, wxALIGN_CENTER_VERTICAL|wxALL, 5);   
00203     
00204         m_Text = new CSearchControl(parent, ID_TEXT, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
00205         m_Sizer->Add(m_Text,1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
00206         
00207     }
00208     return m_Sizer;
00209 }
00210 
00211 void  CComponentSearchForm::Update()
00212 {
00213     UpdateContextCombo(m_DbCombo);
00214 }
00215 
00216 CIRef<IDMSearchQuery> CComponentSearchForm::ConstructQuery()
00217 {
00218 
00219     CIRef<IDMSearchQuery> ref;
00220 
00221     m_SeqLocContexts.clear();
00222     for( size_t i = 0;  i < m_Contexts.size();  i++ )   {
00223         if (m_DbCombo->GetSelection() != 0  &&
00224             m_DbCombo->GetSelection() != int(i + 1)) {
00225              continue;
00226         }
00227         ISeqLocSearchContext* seq_ctx =
00228             dynamic_cast<ISeqLocSearchContext*>(m_Contexts[i]);
00229         m_SeqLocContexts.push_back(seq_ctx);
00230       }
00231 
00232     _ASSERT(m_SeqLocContexts.size());
00233 
00234     /// accumulate locations from all selected contexts
00235     TScopedLocs sc_locs;
00236     for( size_t i = 0;  i < m_SeqLocContexts.size();  i++ ) {
00237         ISeqLocSearchContext* sl_ctx = m_SeqLocContexts[i];
00238         _ASSERT(sl_ctx);
00239 
00240          // tereshko: skip context if it can't participate in search anymore (selection loss, etc) 
00241         if (sl_ctx->GetSearchLoc().IsNull()) continue;
00242 
00243         CRef<CSeq_loc> loc(new CSeq_loc());
00244         if (m_bRange) {
00245             loc = sl_ctx->GetSearchLoc();
00246         }
00247         else {
00248             CRef<CSeq_id> id(new CSeq_id());
00249             id->Assign(*(sl_ctx->GetSearchLoc()->GetId()));
00250             loc->SetWhole(*id);
00251         }
00252 
00253         CSearchQueryBase::SScopedLoc sl;
00254         sl.m_Loc = loc;       
00255         sl.m_Scope = sl_ctx->GetSearchScope();
00256         sl.m_ContextName = sl_ctx->GetDMContextName();
00257         sc_locs.push_back(sl);
00258     }
00259     
00260     ref = new CComponentSearchQuery(sc_locs, ToStdString(m_Text->GetValue()));
00261     return ref;
00262 }
00263 
00264 
00265 ///////////////////////////////////////////////////////////////////////////////
00266 /// CComponentSearchJob
00267 
00268 CComponentSearchJob::CComponentSearchJob(CComponentSearchQuery& query)
00269 :   m_Query(&query)
00270 {
00271     string s_locs, id;
00272     static string sep(", ");
00273     NON_CONST_ITERATE(TScopedLocs, it, m_Query->GetScopedLocs())    {
00274         CLabel::GetLabel(*it->m_Loc, &id, CLabel::eDefault,
00275             it->m_Scope.GetPointer());
00276 
00277         if ( !s_locs.empty() ) {
00278             s_locs += sep;
00279         }
00280         s_locs += id;
00281     }
00282     m_Descr = "Search Components \"" + m_Query->GetIds() + "\" on " + s_locs;
00283 }
00284 
00285 
00286 bool CComponentSearchJob::x_ValidateParams()
00287 {
00288     m_Error.Reset();
00289 
00290     if( m_Query->GetScopedLocs().empty())   {
00291         // this should never happen
00292         m_Error = new CAppJobError("Invalid input parameters - search context is undefined.");
00293     } else if(m_Query->GetIds().empty())  {
00294         m_Error = new CAppJobError("No sequence ids are provided.");
00295     }
00296     return m_Error ? false : true;
00297 }
00298 
00299 
00300 void CComponentSearchJob::x_SetupColumns(CObjectList& obj_list)
00301 {
00302     obj_list.AddColumn(CObjectList::eString, "Component");
00303     obj_list.AddColumn(CObjectList::eString, "Context");
00304 }
00305 
00306 
00307 //TODO this functions is too long
00308 IAppJob::EJobState CComponentSearchJob::x_DoSearch()
00309 {
00310     CStopWatch sw;
00311     sw.Start();
00312     {
00313         CMutexGuard Guard(m_Mutex);
00314         m_ProgressStr = "Loading data." ;
00315     }
00316 
00317     TScopedLocs& scoped_locs = m_Query->GetScopedLocs();
00318     string ids = m_Query->GetIds();
00319 
00320     /// for every Seq_loc
00321     int count = 0;
00322     int found = 0;
00323     NON_CONST_ITERATE(TScopedLocs, it_sl, scoped_locs)    {
00324         if(x_IsCanceled()) {
00325             break;
00326         }
00327         /// extract context data
00328         TScopedLoc& sc_loc = *it_sl;
00329         CSeq_loc& seq_loc = *sc_loc.m_Loc;
00330         CScope& scope = *sc_loc.m_Scope;
00331 
00332         string loc_label;
00333         CLabel::GetLabel(seq_loc, &loc_label, CLabel::eDefault, &scope);
00334 
00335         /// determine our list of seq-ids from the input query
00336         list<CSeq_id_Handle> idhs;
00337         list<string> toks;
00338         NStr::Split(ids, " \t\n;:,", toks);
00339         ITERATE (list<string>, iter, toks) {
00340             const string& s = *iter;
00341             try {
00342                 CSeq_id id(s);
00343                 CSeq_id_Handle idh = CSeq_id_Handle::GetHandle(id);
00344 
00345                 // make sure seq_id's lifetime is long enough to ensure
00346                 // a valid tex_id
00347                 CConstRef<CSeq_id> seq_id = idh.GetSeqId();
00348                 const CTextseq_id* txt_id = seq_id->GetTextseq_Id();
00349                 if (txt_id  &&  txt_id->IsSetVersion()) {
00350                     try {
00351                         CSeq_id_Handle gi = sequence::GetId(idh, scope, sequence::eGetId_ForceGi);
00352                         if (gi) {
00353                             idh = gi;
00354                         }
00355                     }
00356                     catch (CException& e) {
00357                         LOG_POST(Info << "accession: " << s
00358                                  << "not a gi: " << e.GetMsg());
00359                     }
00360                 }
00361 
00362                 idhs.push_back(idh);
00363             }
00364             catch (CException& e) {
00365                 LOG_POST(Error << "error handling accession: " << s
00366                          << ": " << e.GetMsg());
00367             }
00368         }
00369 
00370         /// retrieve the sequence of interest and establish our search range
00371         CSeq_id_Handle bsh_idh = sequence::GetIdHandle(seq_loc, &scope);
00372         CBioseq_Handle bsh = scope.GetBioseqHandle(bsh_idh);
00373         const CSeqMap& seqmap = bsh.GetSeqMap();
00374         TSeqRange range;
00375         if (seq_loc.IsWhole()) {
00376             range.SetFrom(0);
00377             range.SetTo(bsh.GetBioseqLength());
00378         } else {
00379             range = seq_loc.GetTotalRange();
00380         }
00381 
00382         /// scan up to five levels deep in the seq-map structure
00383         for (size_t level = 0;
00384              level < 5  &&  ! x_IsCanceled()  &&  idhs.size();  ++level) {
00385             CSeqMap_CI map_it =
00386                 seqmap.ResolvedRangeIterator(&scope, range.GetFrom(),
00387                                              range.GetLength(), eNa_strand_plus,
00388                                              level, CSeqMap::fFindRef);
00389 
00390             for ( ;  idhs.size()  &&  map_it  &&  ! x_IsCanceled();  ++map_it) {
00391                 CSeq_id_Handle handle = map_it.GetRefSeqid();
00392 
00393                 if (map_it.GetType() != CSeqMap::eSeqRef) {
00394                     continue;
00395                 }
00396 
00397                 list<CSeq_id_Handle>::iterator id_it = idhs.begin();
00398                 for ( ;  id_it != idhs.end();  ) {
00399                     if (CSeqUtils::Match(*id_it, handle, &scope)) {
00400 
00401                         /// format the label for this entry
00402                         string seq_id_str;
00403                         CLabel::GetLabel(*handle.GetSeqId(), &seq_id_str,
00404                                          CLabel::eDefault, &scope);
00405 
00406                         /// get a location for display
00407                         CRef<CSeq_loc> loc(new CSeq_loc);
00408                         loc->SetInt().SetFrom(map_it.GetPosition());
00409                         loc->SetInt().SetTo  (map_it.GetEndPosition() - 1);
00410                         loc->SetId(*bsh_idh.GetSeqId());
00411                         x_AddToResults(*loc, scope, seq_id_str,
00412                                        sc_loc.m_ContextName);
00413                         idhs.erase(id_it++);
00414                         ++found;
00415                     } else {
00416                         ++id_it;
00417                         ++count;
00418                         if (count % 20 == 0) {
00419                             // time to update the Result
00420                             CMutexGuard Guard(m_Mutex);
00421                             m_ProgressStr =
00422                                 NStr::IntToString(count, NStr::fWithCommas) +
00423                                 " components searched, " +
00424                                 NStr::IntToString(found, NStr::fWithCommas) +
00425                                 " component";
00426                             if (found != 1) {
00427                                 m_ProgressStr += "s";
00428                             }
00429                             m_ProgressStr += " found.";
00430                         }
00431                     }
00432                 }
00433             }
00434         }
00435     }
00436 
00437     LOG_POST(Info << "CComponentSearchJob::x_DoSearch(): done: "
00438              << sw.Elapsed() << " seconds");
00439     return x_IsCanceled() ? eCanceled : eCompleted;
00440 }
00441 
00442 
00443 void CComponentSearchJob::x_AddToResults(CObject& obj,
00444                                          CScope& scope,
00445                                          const string& loc_name,
00446                                          const string& ctx_name)
00447 {
00448     static const int kUpdateIncrement = 20;
00449 
00450     int row = m_AccList.AddRow(&obj, &scope);
00451     m_AccList.SetString(0, row, loc_name);
00452     m_AccList.SetString(1, row, ctx_name);
00453 
00454     int count = m_AccList.GetNumRows();
00455     if(count >= kUpdateIncrement)   {
00456         // time to update the Result
00457         CMutexGuard Guard(m_Mutex);
00458 
00459         /// transfer results from Accumulator to m_TempResult
00460         m_TempResult->GetObjectList()->Append(m_AccList);
00461         m_AccList.ClearRows();
00462     }
00463 }
00464 
00465 
00466 END_NCBI_SCOPE
Modified on Wed May 23 13:26:16 2012 by modify_doxy.py rev. 337098