HepMC Reference Documentation

HepMC

GenVertex.cc

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

Generated on Tue Feb 5 13:25:44 2008 for HepMC by  doxygen 1.5.1-3