|
NCBI C++ ToolKit
|
00001 /* $Id: obj_event.cpp 20108 2009-09-15 19:27:21Z kuznets $ 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/objutils/obj_event.hpp> 00035 00036 #include <corelib/ncbitime.hpp> 00037 #include <serial/iterator.hpp> 00038 00039 #include <objects/seq/seq_id_mapper.hpp> 00040 #include <objmgr/util/sequence.hpp> 00041 00042 #include <gui/objutils/utils.hpp> 00043 00044 00045 BEGIN_NCBI_SCOPE 00046 USING_SCOPE(objects); 00047 00048 00049 CSelectionEvent::TRawNameToType CSelectionEvent::sm_RawNameToType; 00050 00051 CSelectionEvent::EObjMatchPolicy 00052 CSelectionEvent::sm_ObjMatchPolicy = CSelectionEvent::eAtLeastOne; 00053 CSelectionEvent::EIdMatchPolicy 00054 CSelectionEvent::sm_IdMatchPolicy = CSelectionEvent::eAccOnly; 00055 bool CSelectionEvent::sm_MatchAlnLocs = true; 00056 bool CSelectionEvent::sm_MatchByProduct = true; 00057 bool CSelectionEvent::sm_AutoBroadcast = true; 00058 bool CSelectionEvent::sm_InterDocBroadcast = true; 00059 00060 00061 CSelectionEvent::CSelectionEvent( objects::CScope& scope, CEventHandler* sender ) 00062 : CViewEvent( eSelectionChanged ) 00063 , m_Scope( &scope ) 00064 , m_HasRangeSelection( false ) 00065 , m_HasObjectSelection( false ) 00066 { 00067 m_Sender = sender; 00068 00069 x_Init(); 00070 } 00071 00072 CSelectionEvent::CSelectionEvent( CRef<objects::CScope> scope, CEventHandler* sender ) 00073 : CViewEvent( eSelectionChanged ) 00074 , m_Scope( scope ) 00075 , m_HasRangeSelection( false ) 00076 , m_HasObjectSelection( false ) 00077 { 00078 m_Sender = sender; 00079 00080 x_Init(); 00081 } 00082 00083 void CSelectionEvent::x_Init() 00084 { 00085 if( sm_RawNameToType.size() == 0 ){ // fill the map only once 00086 string feat_key = typeid(CSeq_feat).name(); 00087 string align_key = typeid(CSeq_align).name(); 00088 string loc_key = typeid(CSeq_loc).name(); 00089 string id_key = typeid(CSeq_id).name(); 00090 00091 sm_RawNameToType[feat_key] = eSeq_feat; 00092 sm_RawNameToType[align_key] = eSeq_align; 00093 sm_RawNameToType[loc_key] = eSeq_loc; 00094 sm_RawNameToType[id_key] = eSeq_id; 00095 } 00096 } 00097 00098 00099 00100 00101 bool CSelectionEvent::HasRangeSelection() const 00102 { 00103 return m_HasRangeSelection; 00104 } 00105 00106 00107 const CHandleRangeMap& CSelectionEvent::GetRangeSelection() const 00108 { 00109 return m_RangeMap; 00110 } 00111 00112 00113 void CSelectionEvent::AddRangeSelection(const CSeq_id& id, const TRangeColl& segs) 00114 { 00115 m_HasRangeSelection = true; 00116 00117 CSeq_id_Handle h_id = CSeq_id_Handle::GetHandle(id); 00118 if (segs.size()) { 00119 ITERATE(TRangeColl, it, segs) { 00120 m_RangeMap.AddRange(h_id, *it, eNa_strand_both); 00121 } 00122 } else { 00123 CRef<CSeq_loc> loc(new CSeq_loc()); 00124 loc->SetEmpty().Assign(id); 00125 AddRangeSelection(*loc); 00126 } 00127 } 00128 00129 void CSelectionEvent::AddRangeSelection(const objects::CSeq_loc& loc) 00130 { 00131 m_HasRangeSelection = true; 00132 00133 m_RangeMap.AddLocation(loc); 00134 } 00135 00136 00137 bool CSelectionEvent::GetRangeSelection(const CSeq_id& id, CScope& scope, 00138 TRangeColl& segs) 00139 { 00140 bool ok = false; 00141 const CHandleRangeMap::TLocMap& loc_map = m_RangeMap.GetMap(); 00142 ITERATE(CHandleRangeMap::TLocMap, it, loc_map) { // for every CSeq_id 00143 CConstRef<CSeq_id> sel_id = it->first.GetSeqId(); 00144 00145 if(Match(*sel_id, *m_Scope, id, scope)) { 00146 bool res = CSeqUtils::GetRangeCollection(*sel_id, m_RangeMap, segs); 00147 ok |= res; 00148 } 00149 } 00150 return ok; 00151 } 00152 00153 00154 void CSelectionEvent::GetRangeSelectionAsLocs(TConstObjects& objs) const 00155 { 00156 const CHandleRangeMap::TLocMap& loc_map = m_RangeMap.GetMap(); 00157 CSeq_loc::TRanges ranges; 00158 00159 ITERATE(CHandleRangeMap::TLocMap, it, loc_map) { // for every CSeq_id 00160 CRef<CSeq_id> sel_id(new CSeq_id()); 00161 sel_id->Assign(*it->first.GetSeqId()); 00162 00163 const CHandleRange& h_range = it->second; 00164 00165 // create a CSeq_loc 00166 ranges.clear(); 00167 ITERATE(CHandleRange, it_r, h_range) { 00168 if (it_r->first.NotEmpty()) { 00169 ranges.push_back(it_r->first); 00170 } 00171 } 00172 if(! ranges.empty()) { 00173 CSeq_loc* loc = new CSeq_loc(*sel_id, ranges); 00174 objs.push_back(CConstRef<CObject>(loc)); 00175 } 00176 } 00177 } 00178 00179 00180 bool CSelectionEvent::HasObjectSelection() 00181 { 00182 return m_HasObjectSelection; 00183 } 00184 00185 00186 bool CSelectionEvent::AddObjectSelection(const CObject& obj) 00187 { 00188 const type_info& info = typeid(obj); 00189 if(info == typeid(CSeq_feat)) { 00190 const CSeq_feat* feat = dynamic_cast<const CSeq_feat*>(&obj); 00191 AddObjectSelection(*feat); 00192 return true; 00193 } else if(info == typeid(CSeq_align)) { 00194 const CSeq_align* align = dynamic_cast<const CSeq_align*>(&obj); 00195 AddObjectSelection(*align); 00196 return true; 00197 } else if(info == typeid(CSeq_loc)) { 00198 const CSeq_loc* loc = dynamic_cast<const CSeq_loc*>(&obj); 00199 AddObjectSelection(*loc); 00200 return true; 00201 } else if(info == typeid(CSeq_id)) { 00202 const CSeq_id* id = dynamic_cast<const CSeq_id*>(&obj); 00203 AddObjectSelection(*id); 00204 return true; 00205 } 00206 return false; 00207 } 00208 00209 00210 void CSelectionEvent::AddObjectSelection(const TConstObjects& objs) 00211 { 00212 ITERATE(TConstObjects, it, objs) { 00213 const CObject& obj = **it; 00214 const type_info& info = typeid(obj); 00215 00216 if(info == typeid(CSeq_feat)) { 00217 const CSeq_feat* feat = dynamic_cast<const CSeq_feat*>(&obj); 00218 AddObjectSelection(*feat); 00219 } else if(info == typeid(CSeq_align)) { 00220 const CSeq_align* align = dynamic_cast<const CSeq_align*>(&obj); 00221 AddObjectSelection(*align); 00222 } else if(info == typeid(CSeq_loc)) { 00223 const CSeq_loc* loc = dynamic_cast<const CSeq_loc*>(&obj); 00224 AddObjectSelection(*loc); 00225 } else if(info == typeid(CSeq_id)) { 00226 const CSeq_id* id = dynamic_cast<const CSeq_id*>(&obj); 00227 AddObjectSelection(*id); 00228 } 00229 } 00230 } 00231 00232 00233 void CSelectionEvent::AddObjectSelection(const CSeq_id& id) 00234 { 00235 m_HasObjectSelection = true; 00236 00237 m_Ids.push_back(CConstRef<CSeq_id>(&id)); 00238 } 00239 00240 00241 void CSelectionEvent::AddObjectSelection(const CSeq_feat& feat) 00242 { 00243 m_HasObjectSelection = true; 00244 00245 m_Feats.push_back(CConstRef<CSeq_feat>(&feat)); 00246 00247 if(sm_MatchByProduct && feat.IsSetProduct()) { 00248 const CSeq_loc& prod_loc = feat.GetProduct(); 00249 const CSeq_id* id = prod_loc.GetId(); 00250 if(id) { 00251 m_Ids.push_back(CConstRef<CSeq_id>(id)); 00252 } 00253 } 00254 } 00255 00256 00257 void CSelectionEvent::AddObjectSelection(const CSeq_align& align) 00258 { 00259 m_HasObjectSelection = true; 00260 00261 m_Aligns.push_back(CConstRef<CSeq_align>(&align)); 00262 } 00263 00264 00265 00266 void CSelectionEvent::AddObjectSelection(const CSeq_loc& loc) 00267 { 00268 m_HasObjectSelection = true; 00269 00270 m_SeqLocs.push_back(CConstRef<CSeq_loc>(&loc)); 00271 } 00272 00273 00274 void CSelectionEvent::AddObjectSelection(const objects::CSeq_id& id, const CRange<TSeqPos>& range) 00275 { 00276 m_HasObjectSelection = true; 00277 00278 CIdLoc* loc = new CIdLoc(); 00279 loc->m_Id.Reset(&id); 00280 loc->m_Range = range; 00281 m_IdLocs.push_back(CConstRef<CIdLoc>(loc)); 00282 } 00283 00284 00285 void CSelectionEvent::GetAllObjects(TConstObjects& objs) const 00286 { 00287 typedef CConstRef<CObject> TR; 00288 00289 ITERATE(TFeats, it_feat, m_Feats) { 00290 objs.push_back(TR(&**it_feat)); 00291 } 00292 ITERATE(TAligns, it_align, m_Aligns) { 00293 objs.push_back(TR(&**it_align)); 00294 } 00295 ITERATE(TSeqLocs, it_loc, m_SeqLocs) { 00296 objs.push_back(TR(&**it_loc)); 00297 } 00298 ITERATE(TIds, it_id, m_Ids) { 00299 objs.push_back(TR(&**it_id)); 00300 } 00301 ITERATE(TIdLocs, it_loc, m_IdLocs) { 00302 objs.push_back(TR(&**it_loc)); 00303 } 00304 } 00305 00306 00307 bool CSelectionEvent::Match(const CObject& obj1, CScope& scope1, 00308 const CObject& obj2, CScope& scope2) 00309 { 00310 if(&obj1 == &obj2) { // trivial matching 00311 return true; 00312 } 00313 00314 const CSeq_feat *feat1 = NULL, *feat2 = NULL; 00315 const CSeq_align *align1 = NULL, *align2 = NULL; 00316 const CSeq_loc *loc1 = NULL, *loc2 = NULL; 00317 const CSeq_id *id1 = NULL, *id2 = NULL; 00318 00319 const type_info& info2 = typeid(obj2); 00320 string name2 = info2.name(); 00321 TRawNameToType::const_iterator it = sm_RawNameToType.find(name2); 00322 if(it == sm_RawNameToType.end()) { 00323 return false; // unsupported type 00324 } 00325 EObjType type2 = it->second; 00326 00327 switch(type2) { 00328 case eSeq_feat: feat2 = dynamic_cast<const CSeq_feat*>(&obj2); break; 00329 case eSeq_align: align2 = dynamic_cast<const CSeq_align*>(&obj2); break; 00330 case eSeq_loc: loc2 = dynamic_cast<const CSeq_loc*>(&obj2); break; 00331 case eSeq_id: id2 = dynamic_cast<const CSeq_id*>(&obj2); break; 00332 } 00333 00334 const type_info& info1 = typeid(obj1); 00335 string name1 = info1.name(); 00336 it = sm_RawNameToType.find(name1); 00337 if(it == sm_RawNameToType.end()) { 00338 return false; // unsupported type 00339 } 00340 EObjType type1 = it->second; 00341 00342 switch(type1) { 00343 case eSeq_feat: 00344 feat1 = dynamic_cast<const CSeq_feat*>(&obj1); 00345 switch(type2) { 00346 case eSeq_feat: return MatchFeatWithFeat(*feat1, scope1, *feat2, scope2); 00347 case eSeq_align: return false; 00348 case eSeq_loc: return MatchFeatWithLoc(*feat1, scope1, *loc2, scope2); 00349 case eSeq_id: return MatchFeatWithId(*feat1, scope1, *id2, scope2); 00350 } 00351 case eSeq_align: 00352 align1 = dynamic_cast<const CSeq_align*>(&obj1); 00353 if(type2 == eSeq_align) { 00354 return MatchAlignWithAlign(*align1, scope1, *align2, scope2); 00355 } else { 00356 return false; 00357 } 00358 case eSeq_loc: 00359 loc1 = dynamic_cast<const CSeq_loc*>(&obj1); 00360 switch(type2) { 00361 case eSeq_feat: return MatchFeatWithLoc(*feat2, scope1, *loc1, scope2); 00362 case eSeq_align: return false; 00363 case eSeq_loc: return MatchLocWithLoc(*loc1, scope1, *loc2, scope2); 00364 case eSeq_id: return MatchLocWithId(*loc1, scope1, *id2, scope2); 00365 } 00366 case eSeq_id: 00367 id1 = dynamic_cast<const CSeq_id*>(&obj1); 00368 switch(type2) { 00369 case eSeq_feat: return MatchFeatWithId(*feat2, scope1, *id1, scope2); 00370 case eSeq_align: return false; 00371 case eSeq_loc: return MatchLocWithId(*loc2, scope1, *id1, scope2); 00372 case eSeq_id: return MatchIdWithId(*id1, scope1, *id2, scope2); 00373 } 00374 } 00375 00376 _ASSERT(false); // must be unreachable 00377 return false; 00378 } 00379 00380 00381 bool CSelectionEvent::MatchFeatWithFeat(const CSeq_feat& feat1, CScope& scope1, 00382 const CSeq_feat& feat2, CScope& scope2) 00383 { 00384 // TO DO extend to support comparision by values (not by pointer) 00385 return &feat1 == &feat2 || feat1.Equals(feat2); 00386 } 00387 00388 00389 bool CSelectionEvent::MatchFeatWithLoc(const CSeq_feat& feat1, CScope& scope1, 00390 const CSeq_loc& loc2, CScope& scope2) 00391 { 00392 if(feat1.CanGetLocation()) { 00393 const CSeq_loc& feat_loc = feat1.GetLocation(); 00394 if(MatchLocWithLoc(feat_loc, scope1, loc2, scope2)) { 00395 return true; 00396 } 00397 } 00398 if(sm_MatchByProduct && feat1.CanGetProduct()) { 00399 const CSeq_loc& prod_loc = feat1.GetProduct(); 00400 if(MatchLocWithLoc(prod_loc, scope1, loc2, scope2)) { 00401 return true; 00402 } 00403 } 00404 return false; 00405 } 00406 00407 00408 bool CSelectionEvent::MatchFeatWithId(const CSeq_feat& feat1, CScope& scope1, 00409 const CSeq_id& id2, CScope& scope2) 00410 { 00411 if(sm_MatchByProduct && feat1.IsSetProduct()) { 00412 const CSeq_loc& prod_loc = feat1.GetProduct(); 00413 if(MatchLocWithId(prod_loc, scope1, id2, scope2)) { 00414 return true; 00415 } 00416 } 00417 return false; 00418 } 00419 00420 00421 bool CSelectionEvent::MatchAlignWithAlign(const CSeq_align& align1, CScope& scope1, 00422 const CSeq_align& align2, CScope& scope2) 00423 { 00424 // TO DO extend to support comparision by values (not by pointer) 00425 return &align1 == &align2 || align1.Equals(align2); 00426 } 00427 00428 00429 bool CSelectionEvent::MatchLocWithLoc(const CSeq_loc& loc1, CScope& scope1, 00430 const CSeq_loc& loc2, CScope& scope2) 00431 { 00432 // TO DO extend to support flexiable ID matching 00433 return &loc1 == &loc2 || loc1.Equals(loc2); 00434 } 00435 00436 00437 bool CSelectionEvent::MatchLocWithId(const CSeq_loc& loc1, CScope& scope1, 00438 const CSeq_id& id2, CScope& scope2) 00439 { 00440 // iterate by all CSeq_id-s in the loc1 and try to match them with id2 00441 set<CSeq_id_Handle> id_set; 00442 CTypeConstIterator<CSeq_id> id_it(loc1); 00443 for ( ; id_it; ++id_it) { 00444 id_set.insert(CSeq_id_Handle::GetHandle(*id_it)); 00445 } 00446 00447 switch(sm_ObjMatchPolicy) { 00448 case eAtLeastOne: 00449 {{ 00450 CSeq_id_Handle id2h = CSeq_id_Handle::GetHandle(id2); 00451 if (id_set.find(id2h) != id_set.end()) { 00452 return true; 00453 } 00454 }} 00455 00456 default: 00457 ITERATE (set<CSeq_id_Handle>, iter, id_set) { 00458 if (MatchIdWithId(*iter->GetSeqId(), scope1, id2, scope2)) { 00459 return true; 00460 } 00461 } 00462 break; 00463 } 00464 00465 return false; 00466 } 00467 00468 struct SW 00469 { 00470 CStopWatch m_W; 00471 SW() { m_W.Start(); } 00472 ~SW() { LOG_POST(Info << "Time " << m_W.Elapsed()); } 00473 }; 00474 00475 00476 bool CSelectionEvent::MatchIdWithId(const CSeq_id& sel_id, CScope& scope1, 00477 const CSeq_id& id, CScope& scope2) 00478 { 00479 //SW w; 00480 00481 switch(sm_ObjMatchPolicy) { 00482 case eAllIds: { 00483 vector<CSeq_id_Handle> ids1 = scope1.GetIds(sel_id); 00484 vector<CSeq_id_Handle> ids2 = scope2.GetIds(id); 00485 if(ids1.size() == ids2.size()) { 00486 sort(ids1.begin(), ids1.end()); 00487 sort(ids2.begin(), ids2.end()); 00488 for( size_t i = 0; i < ids1.size(); i++ ) { 00489 if(! x_SimpleMatch(ids1[i], ids2[i])) 00490 return false; 00491 } 00492 return true; 00493 } else return false; 00494 } 00495 case eAtLeastOne: { 00496 vector<CSeq_id_Handle> ids1 = scope1.GetIds(sel_id); 00497 vector<CSeq_id_Handle> ids2 = scope2.GetIds(id); 00498 for( size_t i = 0; i < ids1.size(); i++ ) { 00499 for( size_t j = 0; j < ids2.size(); j++) { 00500 if(x_SimpleMatch(ids1[i], ids2[j])) 00501 return true; 00502 } 00503 } 00504 return false; 00505 } 00506 } 00507 _ASSERT(false); // must be unreachable 00508 return false; 00509 } 00510 00511 00512 bool CSelectionEvent::x_SimpleMatch(const objects::CSeq_id_Handle& h_sel_id, 00513 const objects::CSeq_id_Handle& h_id) 00514 { 00515 //cout << "\nx_SimpleMatch() " << h_sel_id.AsString() << " " << h_id.AsString(); 00516 switch(sm_IdMatchPolicy) { 00517 case eAccOnly: 00518 return h_sel_id.MatchesTo(h_id) || h_id.MatchesTo(h_sel_id); 00519 case eExact: 00520 return h_sel_id == h_id; 00521 }; 00522 _ASSERT(false); // must be unreachable 00523 return false; 00524 } 00525 00526 00527 END_NCBI_SCOPE
1.7.5.1
Modified on Wed May 23 13:29:13 2012 by modify_doxy.py rev. 337098