![]() |
HepMC Reference DocumentationHepMC |
00001 00002 // Matt.Dobbs@Cern.CH, September 1999 00003 // GenVertex within an event 00005 00006 #include "HepMC/GenParticle.h" 00007 #include "HepMC/GenVertex.h" 00008 #include "HepMC/GenEvent.h" 00009 #include "HepMC/SearchVector.h" 00010 #include <iomanip> // needed for formatted output 00011 00012 namespace HepMC { 00013 00014 GenVertex::GenVertex( const FourVector& position, 00015 int id, const WeightContainer& weights ) 00016 : m_position(position), m_id(id), m_weights(weights), m_event(0), 00017 m_barcode(0) 00018 {} 00019 //{ 00020 //s_counter++; 00021 //} 00022 00023 GenVertex::GenVertex( const GenVertex& invertex ) 00024 : m_position( invertex.position() ), 00025 m_particles_in(), 00026 m_particles_out(), 00027 m_id( invertex.id() ), 00028 m_weights( invertex.weights() ), 00029 m_event(0), 00030 m_barcode(0) 00031 { 00043 // 00044 for ( particles_in_const_iterator 00045 part1 = invertex.particles_in_const_begin(); 00046 part1 != invertex.particles_in_const_end(); ++part1 ) { 00047 if ( !(*part1)->production_vertex() ) { 00048 GenParticle* pin = new GenParticle(**part1); 00049 add_particle_in(pin); 00050 } 00051 } 00052 for ( particles_out_const_iterator 00053 part2 = invertex.particles_out_const_begin(); 00054 part2 != invertex.particles_out_const_end(); part2++ ) { 00055 GenParticle* pin = new GenParticle(**part2); 00056 add_particle_out(pin); 00057 } 00058 suggest_barcode( invertex.barcode() ); 00059 // 00060 //s_counter++; 00061 } 00062 00063 GenVertex::~GenVertex() { 00064 // 00065 // need to delete any particles previously owned by this vertex 00066 if ( parent_event() ) parent_event()->remove_barcode(this); 00067 delete_adopted_particles(); 00068 //s_counter--; 00069 } 00070 00071 void GenVertex::swap( GenVertex & other) 00072 { 00073 m_position.swap( other.m_position ); 00074 m_particles_in.swap( other.m_particles_in ); 00075 m_particles_out.swap( other.m_particles_out ); 00076 std::swap( m_id, other.m_id ); 00077 m_weights.swap( other.m_weights ); 00078 std::swap( m_event, other.m_event ); 00079 std::swap( m_barcode, other.m_barcode ); 00080 } 00081 00082 GenVertex& GenVertex::operator=( const GenVertex& invertex ) { 00096 00097 // best practices implementation 00098 GenVertex tmp( invertex ); 00099 swap( tmp ); 00100 return *this; 00101 } 00102 00103 bool GenVertex::operator==( const GenVertex& a ) const { 00109 // 00110 if ( a.position() != this->position() ) return false; 00111 // if the size of the inlist differs, return false. 00112 if ( a.particles_in_size() != this->particles_in_size() ) return false; 00113 // if the size of the outlist differs, return false. 00114 if ( a.particles_out_size() != this->particles_out_size() ) return false; 00115 // loop over the inlist and ensure particles are identical 00116 // (only do this if the lists aren't empty - we already know 00117 // if one isn't, then other isn't either!) 00118 if ( a.particles_in_const_begin() != a.particles_in_const_end() ) { 00119 for ( GenVertex::particles_in_const_iterator 00120 ia = a.particles_in_const_begin(), 00121 ib = this->particles_in_const_begin(); 00122 ia != a.particles_in_const_end(); ia++, ib++ ){ 00123 if ( **ia != **ib ) return false; 00124 } 00125 } 00126 // loop over the outlist and ensure particles are identical 00127 // (only do this if the lists aren't empty - we already know 00128 // if one isn't, then other isn't either!) 00129 if ( a.particles_out_const_begin() != a.particles_out_const_end() ) { 00130 for ( GenVertex::particles_out_const_iterator 00131 ia = a.particles_out_const_begin(), 00132 ib = this->particles_out_const_begin(); 00133 ia != a.particles_out_const_end(); ia++, ib++ ){ 00134 if ( **ia != **ib ) return false; 00135 } 00136 } 00137 return true; 00138 } 00139 00140 bool GenVertex::operator!=( const GenVertex& a ) const { 00141 // Returns true if the positions and lists of a and this are not equal. 00142 return !( a == *this ); 00143 } 00144 00145 void GenVertex::print( std::ostream& ostr ) const { 00146 // find the current stream state 00147 std::ios_base::fmtflags orig = ostr.flags(); 00148 std::streamsize prec = ostr.precision(); 00149 if ( barcode()!=0 ) { 00150 if ( position() != FourVector(0,0,0,0) ) { 00151 ostr << "Vertex:"; 00152 ostr.width(9); 00153 ostr << barcode(); 00154 ostr << " ID:"; 00155 ostr.width(5); 00156 ostr << id(); 00157 ostr << " (X,cT)="; 00158 ostr.width(9); 00159 ostr.precision(2); 00160 ostr.setf(std::ios::scientific, std::ios::floatfield); 00161 ostr.setf(std::ios_base::showpos); 00162 ostr << position().x() << ","; 00163 ostr.width(9); 00164 ostr << position().y() << ","; 00165 ostr.width(9); 00166 ostr << position().z() << ","; 00167 ostr.width(9); 00168 ostr << position().t(); 00169 ostr.setf(std::ios::fmtflags(0), std::ios::floatfield); 00170 ostr.unsetf(std::ios_base::showpos); 00171 ostr << std::endl; 00172 } else { 00173 ostr << "GenVertex:"; 00174 ostr.width(9); 00175 ostr << barcode(); 00176 ostr << " ID:"; 00177 ostr.width(5); 00178 ostr << id(); 00179 ostr << " (X,cT):0"; 00180 ostr << std::endl; 00181 } 00182 } else { 00183 // If the vertex doesn't have a unique barcode assigned, then 00184 // we print its memory address instead... so that the 00185 // print out gives us a unique tag for the particle. 00186 if ( position() != FourVector(0,0,0,0) ) { 00187 ostr << "Vertex:"; 00188 ostr.width(9); 00189 ostr << (void*)this; 00190 ostr << " ID:"; 00191 ostr.width(5); 00192 ostr << id(); 00193 ostr << " (X,cT)="; 00194 ostr.width(9); 00195 ostr.precision(2); 00196 ostr.setf(std::ios::scientific, std::ios::floatfield); 00197 ostr.setf(std::ios_base::showpos); 00198 ostr << position().x(); 00199 ostr.width(9); 00200 ostr << position().y(); 00201 ostr.width(9); 00202 ostr << position().z(); 00203 ostr.width(9); 00204 ostr << position().t(); 00205 ostr.setf(std::ios::fmtflags(0), std::ios::floatfield); 00206 ostr.unsetf(std::ios_base::showpos); 00207 ostr << std::endl; 00208 } else { 00209 ostr << "GenVertex:"; 00210 ostr.width(9); 00211 ostr << (void*)this; 00212 ostr << " ID:"; 00213 ostr.width(5); 00214 ostr << id(); 00215 ostr << " (X,cT):0"; 00216 ostr << std::endl; 00217 } 00218 } 00219 00220 // print the weights if there are any 00221 if ( ! weights().empty() ) { 00222 ostr << " Wgts(" << weights().size() << ")="; 00223 for ( WeightContainer::const_iterator wgt = weights().begin(); 00224 wgt != weights().end(); wgt++ ) { ostr << *wgt << " "; } 00225 ostr << std::endl; 00226 } 00227 // print out all the incoming, then outgoing particles 00228 for ( particles_in_const_iterator part1 = particles_in_const_begin(); 00229 part1 != particles_in_const_end(); part1++ ) { 00230 if ( part1 == particles_in_const_begin() ) { 00231 ostr << " I:"; 00232 ostr.width(2); 00233 ostr << m_particles_in.size(); 00234 } else { ostr << " "; } 00235 //(*part1)->print( ostr ); //uncomment for long debugging printout 00236 ostr << **part1 << std::endl; 00237 } 00238 for ( particles_out_const_iterator part2 = particles_out_const_begin(); 00239 part2 != particles_out_const_end(); part2++ ) { 00240 if ( part2 == particles_out_const_begin() ) { 00241 ostr << " O:"; 00242 ostr.width(2); 00243 ostr << m_particles_out.size(); 00244 } else { ostr << " "; } 00245 //(*part2)->print( ostr ); // uncomment for long debugging printout 00246 ostr << **part2 << std::endl; 00247 } 00248 // restore the stream state 00249 ostr.flags(orig); 00250 ostr.precision(prec); 00251 } 00252 00253 double GenVertex::check_momentum_conservation() const { 00257 double sumpx = 0, sumpy = 0, sumpz = 0; 00258 for ( particles_in_const_iterator part1 = particles_in_const_begin(); 00259 part1 != particles_in_const_end(); part1++ ) { 00260 sumpx += (*part1)->momentum().px(); 00261 sumpy += (*part1)->momentum().py(); 00262 sumpz += (*part1)->momentum().pz(); 00263 } 00264 for ( particles_out_const_iterator part2 = particles_out_const_begin(); 00265 part2 != particles_out_const_end(); part2++ ) { 00266 sumpx -= (*part2)->momentum().px(); 00267 sumpy -= (*part2)->momentum().py(); 00268 sumpz -= (*part2)->momentum().pz(); 00269 } 00270 return sqrt( sumpx*sumpx + sumpy*sumpy + sumpz*sumpz ); 00271 } 00272 00273 void GenVertex::add_particle_in( GenParticle* inparticle ) { 00274 if ( !inparticle ) return; 00275 // if inparticle previously had a decay vertex, remove it from that 00276 // vertex's list 00277 if ( inparticle->end_vertex() ) { 00278 inparticle->end_vertex()->remove_particle_in( inparticle ); 00279 } 00280 m_particles_in.push_back( inparticle ); 00281 inparticle->set_end_vertex_( this ); 00282 } 00283 00284 void GenVertex::add_particle_out( GenParticle* outparticle ) { 00285 if ( !outparticle ) return; 00286 // if outparticle previously had a production vertex, 00287 // remove it from that vertex's list 00288 if ( outparticle->production_vertex() ) { 00289 outparticle->production_vertex()->remove_particle_out( outparticle ); 00290 } 00291 m_particles_out.push_back( outparticle ); 00292 outparticle->set_production_vertex_( this ); 00293 } 00294 00295 GenParticle* GenVertex::remove_particle( GenParticle* particle ) { 00305 if ( !particle ) return 0; 00306 if ( particle->end_vertex() == this ) { 00307 particle->set_end_vertex_( 0 ); 00308 remove_particle_in(particle); 00309 } 00310 if ( particle->production_vertex() == this ) { 00311 particle->set_production_vertex_(0); 00312 remove_particle_out(particle); 00313 } 00314 return particle; 00315 } 00316 00317 void GenVertex::remove_particle_in( GenParticle* particle ) { 00319 if ( !particle ) return; 00320 m_particles_in.erase( already_in_vector( &m_particles_in, particle ) ); 00321 } 00322 00323 void GenVertex::remove_particle_out( GenParticle* particle ) { 00325 if ( !particle ) return; 00326 m_particles_out.erase( already_in_vector( &m_particles_out, particle ) ); 00327 } 00328 00329 void GenVertex::delete_adopted_particles() { 00332 // 00333 if ( m_particles_out.empty() && m_particles_in.empty() ) return; 00334 // 1. delete all outgoing particles which don't have decay vertices. 00335 // those that do become the responsibility of the decay vertex 00336 // and have their productionvertex pointer set to NULL 00337 for ( std::vector<GenParticle*>::iterator part1 = m_particles_out.begin(); 00338 part1 != m_particles_out.end(); ) { 00339 if ( !(*part1)->end_vertex() ) { 00340 delete *(part1++); 00341 } else { 00342 (*part1)->set_production_vertex_(0); 00343 ++part1; 00344 } 00345 } 00346 m_particles_out.clear(); 00347 // 00348 // 2. delete all incoming particles which don't have production 00349 // vertices. those that do become the responsibility of the 00350 // production vertex and have their decayvertex pointer set to NULL 00351 for ( std::vector<GenParticle*>::iterator part2 = m_particles_in.begin(); 00352 part2 != m_particles_in.end(); ) { 00353 if ( !(*part2)->production_vertex() ) { 00354 delete *(part2++); 00355 } else { 00356 (*part2)->set_end_vertex_(0); 00357 ++part2; 00358 } 00359 } 00360 m_particles_in.clear(); 00361 } 00362 00363 bool GenVertex::suggest_barcode( int the_bar_code ) 00364 { 00374 if ( the_bar_code >0 ) { 00375 std::cerr << "GenVertex::suggest_barcode WARNING, vertex bar codes" 00376 << "\n MUST be negative integers. Positive integers " 00377 << "\n are reserved for particles only. Your suggestion " 00378 << "\n has been rejected." << std::endl; 00379 return false; 00380 } 00381 bool success = false; 00382 if ( parent_event() ) { 00383 success = parent_event()->set_barcode( this, the_bar_code ); 00384 } else { set_barcode_( the_bar_code ); } 00385 return success; 00386 } 00387 00388 void GenVertex::set_parent_event_( GenEvent* new_evt ) 00389 { 00390 GenEvent* orig_evt = m_event; 00391 m_event = new_evt; 00392 // 00393 // every time a vertex's parent event changes, the map of barcodes 00394 // in the new and old parent event needs to be modified to 00395 // reflect this 00396 if ( orig_evt != new_evt ) { 00397 if (new_evt) new_evt->set_barcode( this, barcode() ); 00398 if (orig_evt) orig_evt->remove_barcode( this ); 00399 // we also need to loop over all the particles which are owned by 00400 // this vertex, and remove their barcodes from the old event. 00401 for ( particles_in_const_iterator part1=particles_in_const_begin(); 00402 part1 != particles_in_const_end(); part1++ ) { 00403 if ( !(*part1)->production_vertex() ) { 00404 if ( orig_evt ) orig_evt->remove_barcode( *part1 ); 00405 if ( new_evt ) new_evt->set_barcode( *part1, 00406 (*part1)->barcode() ); 00407 } 00408 } 00409 for ( particles_out_const_iterator 00410 part2 = particles_out_const_begin(); 00411 part2 != particles_out_const_end(); part2++ ) { 00412 if ( orig_evt ) orig_evt->remove_barcode( *part2 ); 00413 if ( new_evt ) new_evt->set_barcode( *part2, 00414 (*part2)->barcode() ); 00415 } 00416 } 00417 } 00418 00419 void GenVertex::change_parent_event_( GenEvent* new_evt ) 00420 { 00421 // 00422 // this method is for use with swap 00423 // particles and vertices have already been exchanged, 00424 // but the backpointer needs to be fixed 00425 //GenEvent* orig_evt = m_event; 00426 m_event = new_evt; 00427 } 00428 00430 // Static // 00432 //unsigned int GenVertex::counter() { return s_counter; } 00433 //unsigned int GenVertex::s_counter = 0; 00434 00436 // Friends // 00438 00440 std::ostream& operator<<( std::ostream& ostr, const GenVertex& vtx ) { 00441 if ( vtx.barcode()!=0 ) ostr << "BarCode " << vtx.barcode(); 00442 else ostr << "Address " << &vtx; 00443 ostr << " (X,cT)="; 00444 if ( vtx.position() != FourVector(0,0,0,0)) { 00445 ostr << vtx.position().x() << "," 00446 << vtx.position().y() << "," 00447 << vtx.position().z() << "," 00448 << vtx.position().t(); 00449 } else { ostr << 0; } 00450 ostr << " #in:" << vtx.particles_in_size() 00451 << " #out:" << vtx.particles_out_size(); 00452 return ostr; 00453 } 00454 00456 // edge_iterator // (protected - for internal use only) 00458 // If the user wants the functionality of the edge_iterator, he should 00459 // use particle_iterator with IteratorRange = family, parents, or children 00460 // 00461 00462 GenVertex::edge_iterator::edge_iterator() : m_vertex(0), m_range(family), 00463 m_is_inparticle_iter(false), m_is_past_end(true) 00464 {} 00465 00466 GenVertex::edge_iterator::edge_iterator( const GenVertex& vtx, 00467 IteratorRange range ) : 00468 m_vertex(&vtx), m_range(family) 00469 { 00470 // Note: (26.1.2000) the original version of edge_iterator inheritted 00471 // from set<GenParticle*>::const_iterator() rather than using 00472 // composition as it does now. 00473 // The inheritted version suffered from a strange bug, which 00474 // I have not fully understood --- it only occurred after many 00475 // events were processed and only when I called the delete 00476 // function on past events. I believe it had something to do with 00477 // the past the end values, which are now robustly coded in this 00478 // version as boolean members. 00479 // 00480 // default range is family, only other choices are children/parents 00481 // descendants/ancestors not allowed & recasted ot children/parents 00482 if ( range == descendants || range == children ) m_range = children; 00483 if ( range == ancestors || range == parents ) m_range = parents; 00484 // 00485 if ( m_vertex->m_particles_in.empty() && 00486 m_vertex->m_particles_out.empty() ) { 00487 // Case: particles_in and particles_out is empty. 00488 m_is_inparticle_iter = false; 00489 m_is_past_end = true; 00490 } else if ( m_range == parents && m_vertex->m_particles_in.empty() ){ 00491 // Case: particles in is empty and parents is requested. 00492 m_is_inparticle_iter = true; 00493 m_is_past_end = true; 00494 } else if ( m_range == children && m_vertex->m_particles_out.empty() ){ 00495 // Case: particles out is empty and children is requested. 00496 m_is_inparticle_iter = false; 00497 m_is_past_end = true; 00498 } else if ( m_range == children ) { 00499 // Case: particles out is NOT empty, and children is requested 00500 m_set_iter = m_vertex->m_particles_out.begin(); 00501 m_is_inparticle_iter = false; 00502 m_is_past_end = false; 00503 } else if ( m_range == family && m_vertex->m_particles_in.empty() ) { 00504 // Case: particles in is empty, particles out is NOT empty, 00505 // and family is requested. Then skip ahead to partilces out. 00506 m_set_iter = m_vertex->m_particles_out.begin(); 00507 m_is_inparticle_iter = false; 00508 m_is_past_end = false; 00509 } else { 00510 // Normal scenario: start with the first incoming particle 00511 m_set_iter = m_vertex->m_particles_in.begin(); 00512 m_is_inparticle_iter = true; 00513 m_is_past_end = false; 00514 } 00515 } 00516 00517 GenVertex::edge_iterator::edge_iterator( const edge_iterator& p ) { 00518 *this = p; 00519 } 00520 00521 GenVertex::edge_iterator::~edge_iterator() {} 00522 00523 GenVertex::edge_iterator& GenVertex::edge_iterator::operator=( 00524 const edge_iterator& p ) { 00525 m_vertex = p.m_vertex; 00526 m_range = p.m_range; 00527 m_set_iter = p.m_set_iter; 00528 m_is_inparticle_iter = p.m_is_inparticle_iter; 00529 m_is_past_end = p.m_is_past_end; 00530 return *this; 00531 } 00532 00533 GenParticle* GenVertex::edge_iterator::operator*(void) const { 00534 if ( !m_vertex || m_is_past_end ) return 0; 00535 return *m_set_iter; 00536 } 00537 00538 GenVertex::edge_iterator& GenVertex::edge_iterator::operator++(void){ 00539 // Pre-fix increment 00540 // 00541 // increment the set iterator (unless we're past the end value) 00542 if ( m_is_past_end ) return *this; 00543 ++m_set_iter; 00544 // handle cases where m_set_iter points past the end 00545 if ( m_range == family && m_is_inparticle_iter && 00546 m_set_iter == m_vertex->m_particles_in.end() ) { 00547 // at the end on in particle set, and range is family, so move to 00548 // out particle set 00549 m_set_iter = m_vertex->m_particles_out.begin(); 00550 m_is_inparticle_iter = false; 00551 } else if ( m_range == parents && 00552 m_set_iter == m_vertex->m_particles_in.end() ) { 00553 // at the end on in particle set, and range is parents only, so 00554 // move into past the end state 00555 m_is_past_end = true; 00556 // might as well bail out now 00557 return *this; 00558 } 00559 // are we iterating over input or output particles? 00560 if( m_is_inparticle_iter ) { 00561 // the following is not else if because we might have range=family 00562 // with an empty particles_in set. 00563 if ( m_set_iter == m_vertex->m_particles_in.end() ) { 00564 //whenever out particles end is reached, go into past the end state 00565 m_is_past_end = true; 00566 } 00567 } else { 00568 // the following is not else if because we might have range=family 00569 // with an empty particles_out set. 00570 if ( m_set_iter == m_vertex->m_particles_out.end() ) { 00571 //whenever out particles end is reached, go into past the end state 00572 m_is_past_end = true; 00573 } 00574 } 00575 return *this; 00576 } 00577 00578 GenVertex::edge_iterator GenVertex::edge_iterator::operator++(int){ 00579 // Post-fix increment 00580 edge_iterator returnvalue = *this; 00581 ++*this; 00582 return returnvalue; 00583 } 00584 00585 bool GenVertex::edge_iterator::is_parent() const { 00586 if ( **this && (**this)->end_vertex() == m_vertex ) return true; 00587 return false; 00588 } 00589 00590 bool GenVertex::edge_iterator::is_child() const { 00591 if ( **this && (**this)->production_vertex() == m_vertex ) return true; 00592 return false; 00593 } 00594 00595 int GenVertex::edges_size( IteratorRange range ) const { 00596 if ( range == children ) return m_particles_out.size(); 00597 if ( range == parents ) return m_particles_in.size(); 00598 if ( range == family ) return m_particles_out.size() 00599 + m_particles_in.size(); 00600 return 0; 00601 } 00602 00604 // vertex_iterator // 00606 00607 GenVertex::vertex_iterator::vertex_iterator() 00608 : m_vertex(0), m_range(), m_visited_vertices(0), m_it_owns_set(0), 00609 m_recursive_iterator(0) 00610 {} 00611 00612 GenVertex::vertex_iterator::vertex_iterator( GenVertex& vtx_root, 00613 IteratorRange range ) 00614 : m_vertex(&vtx_root), m_range(range) 00615 { 00616 // standard public constructor 00617 // 00618 m_visited_vertices = new std::set<const GenVertex*>; 00619 m_it_owns_set = 1; 00620 m_visited_vertices->insert( m_vertex ); 00621 m_recursive_iterator = 0; 00622 m_edge = m_vertex->edges_begin( m_range ); 00623 // advance to the first good return value 00624 if ( !follow_edge_() && 00625 m_edge != m_vertex->edges_end( m_range )) ++*this; 00626 } 00627 00628 GenVertex::vertex_iterator::vertex_iterator( GenVertex& vtx_root, 00629 IteratorRange range, std::set<const HepMC::GenVertex*>& visited_vertices ) : 00630 m_vertex(&vtx_root), m_range(range), 00631 m_visited_vertices(&visited_vertices), m_it_owns_set(0), 00632 m_recursive_iterator(0) 00633 { 00634 // This constuctor is only to be called internally by this class 00635 // for use with its recursive member pointer (m_recursive_iterator). 00636 // Note: we do not need to insert m_vertex_root in the vertex - that is 00637 // the responsibility of this iterator's mother, which is normally 00638 // done just before calling this protected constructor. 00639 m_edge = m_vertex->edges_begin( m_range ); 00640 // advance to the first good return value 00641 if ( !follow_edge_() && 00642 m_edge != m_vertex->edges_end( m_range )) ++*this; 00643 } 00644 00645 GenVertex::vertex_iterator::vertex_iterator( const vertex_iterator& v_iter) 00646 : m_vertex(0), m_visited_vertices(0), m_it_owns_set(0), 00647 m_recursive_iterator(0) 00648 { 00649 *this = v_iter; 00650 } 00651 00652 GenVertex::vertex_iterator::~vertex_iterator() { 00653 if ( m_recursive_iterator ) delete m_recursive_iterator; 00654 if ( m_it_owns_set ) delete m_visited_vertices; 00655 } 00656 00657 GenVertex::vertex_iterator& GenVertex::vertex_iterator::operator=( 00658 const vertex_iterator& v_iter ) 00659 { 00660 // Note: when copying a vertex_iterator that is NOT the owner 00661 // of its set container, the pointer to the set is copied. Beware! 00662 // (see copy_with_own_set() if you want a different set pointed to) 00663 // In practise the user never needs to worry 00664 // since such iterators are only intended to be used internally. 00665 // 00666 // destruct data member pointers 00667 if ( m_recursive_iterator ) delete m_recursive_iterator; 00668 m_recursive_iterator = 0; 00669 if ( m_it_owns_set ) delete m_visited_vertices; 00670 m_visited_vertices = 0; 00671 m_it_owns_set = 0; 00672 // copy the target vertex_iterator to this iterator 00673 m_vertex = v_iter.m_vertex; 00674 m_range = v_iter.m_range; 00675 if ( v_iter.m_it_owns_set ) { 00676 // i.e. this vertex will own its set if v_iter points to any 00677 // vertex set regardless of whether v_iter owns the set or not! 00678 m_visited_vertices = 00679 new std::set<const GenVertex*>(*v_iter.m_visited_vertices); 00680 m_it_owns_set = 1; 00681 } else { 00682 m_visited_vertices = v_iter.m_visited_vertices; 00683 m_it_owns_set = 0; 00684 } 00685 // 00686 // Note: m_vertex_root is already included in the set of 00687 // tv_iter.m_visited_vertices, we do not need to insert it. 00688 // 00689 m_edge = v_iter.m_edge; 00690 copy_recursive_iterator_( v_iter.m_recursive_iterator ); 00691 return *this; 00692 } 00693 00694 GenVertex* GenVertex::vertex_iterator::operator*(void) const { 00695 // de-reference operator 00696 // 00697 // if this iterator has an iterator_node, then we return the iterator 00698 // node. 00699 if ( m_recursive_iterator ) return **m_recursive_iterator; 00700 // 00701 // an iterator can only return its m_vertex -- any other vertex 00702 // is returned by means of a recursive iterator_node 00703 // (so this is the only place in the iterator code that a vertex 00704 // is returned!) 00705 if ( m_vertex ) return m_vertex; 00706 return 0; 00707 } 00708 00709 GenVertex::vertex_iterator& GenVertex::vertex_iterator::operator++(void) { 00710 // Pre-fix incremental operator 00711 // 00712 // check for "past the end condition" denoted by m_vertex=0 00713 if ( !m_vertex ) return *this; 00714 // if at the last edge, move into the "past the end condition" 00715 if ( m_edge == m_vertex->edges_end( m_range ) ) { 00716 m_vertex = 0; 00717 return *this; 00718 } 00719 // check to see if we need to create a new recursive iterator by 00720 // following the current edge only if a recursive iterator doesn't 00721 // already exist. If a new recursive_iterator is created, return it. 00722 if ( follow_edge_() ) { 00723 return *this; 00724 } 00725 // 00726 // if a recursive iterator already exists, increment it, and return its 00727 // value (unless the recursive iterator has null root_vertex [its 00728 // root vertex is set to null if it has already returned its root] 00729 // - in which case we delete it) 00730 // and return the vertex pointed to by the edge. 00731 if ( m_recursive_iterator ) { 00732 ++(*m_recursive_iterator); 00733 if ( **m_recursive_iterator ) { 00734 return *this; 00735 } else { 00736 delete m_recursive_iterator; 00737 m_recursive_iterator = 0; 00738 } 00739 } 00740 // 00741 // increment to the next particle edge 00742 ++m_edge; 00743 // if m_edge is at the end, then we have incremented through all 00744 // edges, and it is time to return m_vertex, which we accomplish 00745 // by returning *this 00746 if ( m_edge == m_vertex->edges_end( m_range ) ) return *this; 00747 // otherwise we follow the current edge by recursively ++ing. 00748 return ++(*this); 00749 } 00750 00751 GenVertex::vertex_iterator GenVertex::vertex_iterator::operator++(int) { 00752 // Post-fix increment 00753 vertex_iterator returnvalue(*this); 00754 ++(*this); 00755 return returnvalue; 00756 } 00757 00758 void GenVertex::vertex_iterator::copy_with_own_set( 00759 const vertex_iterator& v_iter, 00760 std::set<const HepMC::GenVertex*>& visited_vertices ) { 00765 // 00766 // destruct data member pointers 00767 if ( m_recursive_iterator ) delete m_recursive_iterator; 00768 m_recursive_iterator = 0; 00769 if ( m_it_owns_set ) delete m_visited_vertices; 00770 m_visited_vertices = 0; 00771 m_it_owns_set = false; 00772 // copy the target vertex_iterator to this iterator 00773 m_vertex = v_iter.m_vertex; 00774 m_range = v_iter.m_range; 00775 m_visited_vertices = &visited_vertices; 00776 m_it_owns_set = false; 00777 m_edge = v_iter.m_edge; 00778 copy_recursive_iterator_( v_iter.m_recursive_iterator ); 00779 } 00780 00781 GenVertex* GenVertex::vertex_iterator::follow_edge_() { 00782 // follows the edge pointed to by m_edge by creating a 00783 // recursive iterator for it. 00784 // 00785 // if a m_recursive_iterator already exists, 00786 // this routine has nothing to do, 00787 // if there's no m_vertex, there's no point following anything, 00788 // also there's no point trying to follow a null edge. 00789 if ( m_recursive_iterator || !m_vertex || !*m_edge ) return 0; 00790 // 00791 // if the range is parents, children, or family (i.e. <= family) 00792 // then only the iterator which owns the set is allowed to create 00793 // recursive iterators (i.e. recursivity is only allowed to go one 00794 // layer deep) 00795 if ( m_range <= family && m_it_owns_set == 0 ) return 0; 00796 // 00797 // M.Dobbs 2001-07-16 00798 // Take care of the very special-rare case where a particle might 00799 // point to the same vertex for both production and end 00800 if ( (*m_edge)->production_vertex() == 00801 (*m_edge)->end_vertex() ) return 0; 00802 // 00803 // figure out which vertex m_edge is pointing to 00804 GenVertex* vtx = ( m_edge.is_parent() ? 00805 (*m_edge)->production_vertex() : 00806 (*m_edge)->end_vertex() ); 00807 // if the pointed to vertex doesn't exist or has already been visited, 00808 // then return null 00809 if ( !vtx || !(m_visited_vertices->insert(vtx).second) ) return 0; 00810 // follow that edge by creating a recursive iterator 00811 m_recursive_iterator = new vertex_iterator( *vtx, m_range, 00812 *m_visited_vertices); 00813 // and return the vertex pointed to by m_recursive_iterator 00814 return **m_recursive_iterator; 00815 } 00816 00817 void GenVertex::vertex_iterator::copy_recursive_iterator_( 00818 const vertex_iterator* recursive_v_iter ) { 00819 // to properly copy the recursive iterator, we need to ensure 00820 // the proper set container is transfered ... then do this 00821 // operation .... you guessed it .... recursively! 00822 // 00823 if ( !recursive_v_iter ) return; 00824 m_recursive_iterator = new vertex_iterator(); 00825 m_recursive_iterator->m_vertex = recursive_v_iter->m_vertex; 00826 m_recursive_iterator->m_range = recursive_v_iter->m_range; 00827 m_recursive_iterator->m_visited_vertices = m_visited_vertices; 00828 m_recursive_iterator->m_it_owns_set = 0; 00829 m_recursive_iterator->m_edge = recursive_v_iter->m_edge; 00830 m_recursive_iterator->copy_recursive_iterator_( 00831 recursive_v_iter->m_recursive_iterator ); 00832 } 00833 00835 // particle_iterator // 00837 00838 GenVertex::particle_iterator::particle_iterator() {} 00839 00840 GenVertex::particle_iterator::particle_iterator( GenVertex& vertex_root, 00841 IteratorRange range ) { 00842 // General Purpose Constructor 00843 // 00844 if ( range <= family ) { 00845 m_edge = GenVertex::edge_iterator( vertex_root, range ); 00846 } else { 00847 m_vertex_iterator = GenVertex::vertex_iterator(vertex_root, range); 00848 m_edge = GenVertex::edge_iterator( **m_vertex_iterator, 00849 m_vertex_iterator.range() ); 00850 } 00851 advance_to_first_(); 00852 } 00853 00854 GenVertex::particle_iterator::particle_iterator( 00855 const particle_iterator& p_iter ){ 00856 *this = p_iter; 00857 } 00858 00859 GenVertex::particle_iterator::~particle_iterator() {} 00860 00861 GenVertex::particle_iterator& 00862 GenVertex::particle_iterator::operator=( const particle_iterator& p_iter ) 00863 { 00864 m_vertex_iterator = p_iter.m_vertex_iterator; 00865 m_edge = p_iter.m_edge; 00866 return *this; 00867 } 00868 00869 GenParticle* GenVertex::particle_iterator::operator*(void) const { 00870 return *m_edge; 00871 } 00872 00873 GenVertex::particle_iterator& 00874 GenVertex::particle_iterator::operator++(void) { 00875 //Pre-fix increment 00876 // 00877 if ( *m_edge ) { 00878 ++m_edge; 00879 } else if ( *m_vertex_iterator ) { // !*m_edge is implicit 00880 // past end of edge, but still have more vertices to visit 00881 // increment the vertex, checking that the result is valid 00882 if ( !*(++m_vertex_iterator) ) return *this; 00883 m_edge = GenVertex::edge_iterator( **m_vertex_iterator, 00884 m_vertex_iterator.range() ); 00885 } else { // !*m_edge and !*m_vertex_iterator are implicit 00886 // past the end condition: do nothing 00887 return *this; 00888 } 00889 advance_to_first_(); 00890 return *this; 00891 } 00892 00893 GenVertex::particle_iterator GenVertex::particle_iterator::operator++(int){ 00894 //Post-fix increment 00895 particle_iterator returnvalue(*this); 00896 ++(*this); 00897 return returnvalue; 00898 } 00899 00900 GenParticle* GenVertex::particle_iterator::advance_to_first_() { 00904 if ( !*m_edge ) return *(++*this); 00905 // if the range is relatives, we need to uniquely assign each particle 00906 // to a single vertex so as to guarantee particles are returned 00907 // exactly once. 00908 if ( m_vertex_iterator.range() == relatives && 00909 m_edge.is_parent() && 00910 (*m_edge)->production_vertex() ) return *(++*this); 00911 return *m_edge; 00912 } 00913 00918 void GenVertex::convert_position( const double& f ) { 00919 m_position = FourVector( f*m_position.x(), 00920 f*m_position.y(), 00921 f*m_position.z(), 00922 f*m_position.t() ); 00923 } 00924 00925 } // HepMC