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     //{
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

Generated on Thu Jan 7 13:10:15 2010 for HepMC by  doxygen 1.4.7