|
NCBI C++ ToolKit
|
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
1.7.5.1
Modified on Wed May 23 13:26:16 2012 by modify_doxy.py rev. 337098