StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
GenVertex.cc
1 // Matt.Dobbs@Cern.CH, September 1999
3 // GenVertex within an event
5 
6 #include "HepMC/GenParticle.h"
7 #include "HepMC/GenVertex.h"
8 #include "HepMC/GenEvent.h"
9 #include "HepMC/SearchVector.h"
10 #include <iomanip> // needed for formatted output
11 
12 namespace HepMC {
13 
14  GenVertex::GenVertex( const FourVector& position,
15  int id, const WeightContainer& weights )
16  : m_position(position), m_id(id), m_weights(weights), m_event(0),
17  m_barcode(0)
18  {}
19  //{
20  //s_counter++;
21  //}
22 
23  GenVertex::GenVertex( const GenVertex& invertex )
24  : m_position( invertex.position() ),
25  m_particles_in(),
26  m_particles_out(),
27  m_id( invertex.id() ),
28  m_weights( invertex.weights() ),
29  m_event(0),
30  m_barcode(0)
31  {
43  //
45  part1 = invertex.particles_in_const_begin();
46  part1 != invertex.particles_in_const_end(); ++part1 ) {
47  if ( !(*part1)->production_vertex() ) {
48  GenParticle* pin = new GenParticle(**part1);
49  add_particle_in(pin);
50  }
51  }
53  part2 = invertex.particles_out_const_begin();
54  part2 != invertex.particles_out_const_end(); part2++ ) {
55  GenParticle* pin = new GenParticle(**part2);
56  add_particle_out(pin);
57  }
58  suggest_barcode( invertex.barcode() );
59  //
60  //s_counter++;
61  }
62 
63  GenVertex::~GenVertex() {
64  //
65  // need to delete any particles previously owned by this vertex
66  if ( parent_event() ) parent_event()->remove_barcode(this);
68  //s_counter--;
69  }
70 
71  void GenVertex::swap( GenVertex & other)
72  {
73  m_position.swap( other.m_position );
74  m_particles_in.swap( other.m_particles_in );
75  m_particles_out.swap( other.m_particles_out );
76  std::swap( m_id, other.m_id );
77  m_weights.swap( other.m_weights );
78  std::swap( m_event, other.m_event );
79  std::swap( m_barcode, other.m_barcode );
80  }
81 
96 
97  // best practices implementation
98  GenVertex tmp( invertex );
99  swap( tmp );
100  return *this;
101  }
102 
103  bool GenVertex::operator==( const GenVertex& a ) const {
109  //
110  if ( a.position() != this->position() ) return false;
111  // if the size of the inlist differs, return false.
112  if ( a.particles_in_size() != this->particles_in_size() ) return false;
113  // if the size of the outlist differs, return false.
114  if ( a.particles_out_size() != this->particles_out_size() ) return false;
115  // loop over the inlist and ensure particles are identical
116  // (only do this if the lists aren't empty - we already know
117  // if one isn't, then other isn't either!)
120  ia = a.particles_in_const_begin(),
121  ib = this->particles_in_const_begin();
122  ia != a.particles_in_const_end(); ia++, ib++ ){
123  if ( **ia != **ib ) return false;
124  }
125  }
126  // loop over the outlist and ensure particles are identical
127  // (only do this if the lists aren't empty - we already know
128  // if one isn't, then other isn't either!)
131  ia = a.particles_out_const_begin(),
132  ib = this->particles_out_const_begin();
133  ia != a.particles_out_const_end(); ia++, ib++ ){
134  if ( **ia != **ib ) return false;
135  }
136  }
137  return true;
138  }
139 
140  bool GenVertex::operator!=( const GenVertex& a ) const {
141  // Returns true if the positions and lists of a and this are not equal.
142  return !( a == *this );
143  }
144 
145  void GenVertex::print( std::ostream& ostr ) const {
146  // find the current stream state
147  std::ios_base::fmtflags orig = ostr.flags();
148  std::streamsize prec = ostr.precision();
149  if ( barcode()!=0 ) {
150  if ( position() != FourVector(0,0,0,0) ) {
151  ostr << "Vertex:";
152  ostr.width(9);
153  ostr << barcode();
154  ostr << " ID:";
155  ostr.width(5);
156  ostr << id();
157  ostr << " (X,cT)=";
158  ostr.width(9);
159  ostr.precision(2);
160  ostr.setf(std::ios::scientific, std::ios::floatfield);
161  ostr.setf(std::ios_base::showpos);
162  ostr << position().x() << ",";
163  ostr.width(9);
164  ostr << position().y() << ",";
165  ostr.width(9);
166  ostr << position().z() << ",";
167  ostr.width(9);
168  ostr << position().t();
169  ostr.setf(std::ios::fmtflags(0), std::ios::floatfield);
170  ostr.unsetf(std::ios_base::showpos);
171  ostr << std::endl;
172  } else {
173  ostr << "GenVertex:";
174  ostr.width(9);
175  ostr << barcode();
176  ostr << " ID:";
177  ostr.width(5);
178  ostr << id();
179  ostr << " (X,cT):0";
180  ostr << std::endl;
181  }
182  } else {
183  // If the vertex doesn't have a unique barcode assigned, then
184  // we print its memory address instead... so that the
185  // print out gives us a unique tag for the particle.
186  if ( position() != FourVector(0,0,0,0) ) {
187  ostr << "Vertex:";
188  ostr.width(9);
189  ostr << (void*)this;
190  ostr << " ID:";
191  ostr.width(5);
192  ostr << id();
193  ostr << " (X,cT)=";
194  ostr.width(9);
195  ostr.precision(2);
196  ostr.setf(std::ios::scientific, std::ios::floatfield);
197  ostr.setf(std::ios_base::showpos);
198  ostr << position().x();
199  ostr.width(9);
200  ostr << position().y();
201  ostr.width(9);
202  ostr << position().z();
203  ostr.width(9);
204  ostr << position().t();
205  ostr.setf(std::ios::fmtflags(0), std::ios::floatfield);
206  ostr.unsetf(std::ios_base::showpos);
207  ostr << std::endl;
208  } else {
209  ostr << "GenVertex:";
210  ostr.width(9);
211  ostr << (void*)this;
212  ostr << " ID:";
213  ostr.width(5);
214  ostr << id();
215  ostr << " (X,cT):0";
216  ostr << std::endl;
217  }
218  }
219 
220  // print the weights if there are any
221  if ( ! weights().empty() ) {
222  ostr << " Wgts(" << weights().size() << ")=";
223  for ( WeightContainer::const_iterator wgt = weights().begin();
224  wgt != weights().end(); wgt++ ) { ostr << *wgt << " "; }
225  ostr << std::endl;
226  }
227  // print out all the incoming, then outgoing particles
229  part1 != particles_in_const_end(); part1++ ) {
230  if ( part1 == particles_in_const_begin() ) {
231  ostr << " I:";
232  ostr.width(2);
233  ostr << m_particles_in.size();
234  } else { ostr << " "; }
235  //(*part1)->print( ostr ); //uncomment for long debugging printout
236  ostr << **part1 << std::endl;
237  }
239  part2 != particles_out_const_end(); part2++ ) {
240  if ( part2 == particles_out_const_begin() ) {
241  ostr << " O:";
242  ostr.width(2);
243  ostr << m_particles_out.size();
244  } else { ostr << " "; }
245  //(*part2)->print( ostr ); // uncomment for long debugging printout
246  ostr << **part2 << std::endl;
247  }
248  // restore the stream state
249  ostr.flags(orig);
250  ostr.precision(prec);
251  }
252 
257  double sumpx = 0, sumpy = 0, sumpz = 0;
259  part1 != particles_in_const_end(); part1++ ) {
260  sumpx += (*part1)->momentum().px();
261  sumpy += (*part1)->momentum().py();
262  sumpz += (*part1)->momentum().pz();
263  }
265  part2 != particles_out_const_end(); part2++ ) {
266  sumpx -= (*part2)->momentum().px();
267  sumpy -= (*part2)->momentum().py();
268  sumpz -= (*part2)->momentum().pz();
269  }
270  return sqrt( sumpx*sumpx + sumpy*sumpy + sumpz*sumpz );
271  }
272 
274  if ( !inparticle ) return;
275  // if inparticle previously had a decay vertex, remove it from that
276  // vertex's list
277  if ( inparticle->end_vertex() ) {
278  inparticle->end_vertex()->remove_particle_in( inparticle );
279  }
280  m_particles_in.push_back( inparticle );
281  inparticle->set_end_vertex_( this );
282  }
283 
285  if ( !outparticle ) return;
286  // if outparticle previously had a production vertex,
287  // remove it from that vertex's list
288  if ( outparticle->production_vertex() ) {
289  outparticle->production_vertex()->remove_particle_out( outparticle );
290  }
291  m_particles_out.push_back( outparticle );
292  outparticle->set_production_vertex_( this );
293  }
294 
305  if ( !particle ) return 0;
306  if ( particle->end_vertex() == this ) {
307  particle->set_end_vertex_( 0 );
308  remove_particle_in(particle);
309  }
310  if ( particle->production_vertex() == this ) {
311  particle->set_production_vertex_(0);
312  remove_particle_out(particle);
313  }
314  return particle;
315  }
316 
319  if ( !particle ) return;
320  m_particles_in.erase( already_in_vector( &m_particles_in, particle ) );
321  }
322 
325  if ( !particle ) return;
326  m_particles_out.erase( already_in_vector( &m_particles_out, particle ) );
327  }
328 
332  //
333  if ( m_particles_out.empty() && m_particles_in.empty() ) return;
334  // 1. delete all outgoing particles which don't have decay vertices.
335  // those that do become the responsibility of the decay vertex
336  // and have their productionvertex pointer set to NULL
337  for ( std::vector<GenParticle*>::iterator part1 = m_particles_out.begin();
338  part1 != m_particles_out.end(); ) {
339  if ( !(*part1)->end_vertex() ) {
340  delete *(part1++);
341  } else {
342  (*part1)->set_production_vertex_(0);
343  ++part1;
344  }
345  }
346  m_particles_out.clear();
347  //
348  // 2. delete all incoming particles which don't have production
349  // vertices. those that do become the responsibility of the
350  // production vertex and have their decayvertex pointer set to NULL
351  for ( std::vector<GenParticle*>::iterator part2 = m_particles_in.begin();
352  part2 != m_particles_in.end(); ) {
353  if ( !(*part2)->production_vertex() ) {
354  delete *(part2++);
355  } else {
356  (*part2)->set_end_vertex_(0);
357  ++part2;
358  }
359  }
360  m_particles_in.clear();
361  }
362 
363  bool GenVertex::suggest_barcode( int the_bar_code )
364  {
374  if ( the_bar_code >0 ) {
375  std::cerr << "GenVertex::suggest_barcode WARNING, vertex bar codes"
376  << "\n MUST be negative integers. Positive integers "
377  << "\n are reserved for particles only. Your suggestion "
378  << "\n has been rejected." << std::endl;
379  return false;
380  }
381  bool success = false;
382  if ( parent_event() ) {
383  success = parent_event()->set_barcode( this, the_bar_code );
384  } else { set_barcode_( the_bar_code ); }
385  return success;
386  }
387 
389  {
390  GenEvent* orig_evt = m_event;
391  m_event = new_evt;
392  //
393  // every time a vertex's parent event changes, the map of barcodes
394  // in the new and old parent event needs to be modified to
395  // reflect this
396  if ( orig_evt != new_evt ) {
397  if (new_evt) new_evt->set_barcode( this, barcode() );
398  if (orig_evt) orig_evt->remove_barcode( this );
399  // we also need to loop over all the particles which are owned by
400  // this vertex, and remove their barcodes from the old event.
402  part1 != particles_in_const_end(); part1++ ) {
403  if ( !(*part1)->production_vertex() ) {
404  if ( orig_evt ) orig_evt->remove_barcode( *part1 );
405  if ( new_evt ) new_evt->set_barcode( *part1,
406  (*part1)->barcode() );
407  }
408  }
410  part2 = particles_out_const_begin();
411  part2 != particles_out_const_end(); part2++ ) {
412  if ( orig_evt ) orig_evt->remove_barcode( *part2 );
413  if ( new_evt ) new_evt->set_barcode( *part2,
414  (*part2)->barcode() );
415  }
416  }
417  }
418 
420  {
421  //
422  // this method is for use with swap
423  // particles and vertices have already been exchanged,
424  // but the backpointer needs to be fixed
425  //GenEvent* orig_evt = m_event;
426  m_event = new_evt;
427  }
428 
430  // Static //
432  //unsigned int GenVertex::counter() { return s_counter; }
433  //unsigned int GenVertex::s_counter = 0;
434 
436  // Friends //
438 
440  std::ostream& operator<<( std::ostream& ostr, const GenVertex& vtx ) {
441  if ( vtx.barcode()!=0 ) ostr << "BarCode " << vtx.barcode();
442  else ostr << "Address " << &vtx;
443  ostr << " (X,cT)=";
444  if ( vtx.position() != FourVector(0,0,0,0)) {
445  ostr << vtx.position().x() << ","
446  << vtx.position().y() << ","
447  << vtx.position().z() << ","
448  << vtx.position().t();
449  } else { ostr << 0; }
450  ostr << " #in:" << vtx.particles_in_size()
451  << " #out:" << vtx.particles_out_size();
452  return ostr;
453  }
454 
456  // edge_iterator // (protected - for internal use only)
458  // If the user wants the functionality of the edge_iterator, he should
459  // use particle_iterator with IteratorRange = family, parents, or children
460  //
461 
462  GenVertex::edge_iterator::edge_iterator() : m_vertex(0), m_range(family),
463  m_is_inparticle_iter(false), m_is_past_end(true)
464  {}
465 
466  GenVertex::edge_iterator::edge_iterator( const GenVertex& vtx,
467  IteratorRange range ) :
468  m_vertex(&vtx), m_range(family)
469  {
470  // Note: (26.1.2000) the original version of edge_iterator inheritted
471  // from set<GenParticle*>::const_iterator() rather than using
472  // composition as it does now.
473  // The inheritted version suffered from a strange bug, which
474  // I have not fully understood --- it only occurred after many
475  // events were processed and only when I called the delete
476  // function on past events. I believe it had something to do with
477  // the past the end values, which are now robustly coded in this
478  // version as boolean members.
479  //
480  // default range is family, only other choices are children/parents
481  // descendants/ancestors not allowed & recasted ot children/parents
482  if ( range == descendants || range == children ) m_range = children;
483  if ( range == ancestors || range == parents ) m_range = parents;
484  //
485  if ( m_vertex->m_particles_in.empty() &&
486  m_vertex->m_particles_out.empty() ) {
487  // Case: particles_in and particles_out is empty.
488  m_is_inparticle_iter = false;
489  m_is_past_end = true;
490  } else if ( m_range == parents && m_vertex->m_particles_in.empty() ){
491  // Case: particles in is empty and parents is requested.
492  m_is_inparticle_iter = true;
493  m_is_past_end = true;
494  } else if ( m_range == children && m_vertex->m_particles_out.empty() ){
495  // Case: particles out is empty and children is requested.
496  m_is_inparticle_iter = false;
497  m_is_past_end = true;
498  } else if ( m_range == children ) {
499  // Case: particles out is NOT empty, and children is requested
500  m_set_iter = m_vertex->m_particles_out.begin();
501  m_is_inparticle_iter = false;
502  m_is_past_end = false;
503  } else if ( m_range == family && m_vertex->m_particles_in.empty() ) {
504  // Case: particles in is empty, particles out is NOT empty,
505  // and family is requested. Then skip ahead to partilces out.
506  m_set_iter = m_vertex->m_particles_out.begin();
507  m_is_inparticle_iter = false;
508  m_is_past_end = false;
509  } else {
510  // Normal scenario: start with the first incoming particle
511  m_set_iter = m_vertex->m_particles_in.begin();
512  m_is_inparticle_iter = true;
513  m_is_past_end = false;
514  }
515  }
516 
517  GenVertex::edge_iterator::edge_iterator( const edge_iterator& p ) {
518  *this = p;
519  }
520 
521  GenVertex::edge_iterator::~edge_iterator() {}
522 
524  const edge_iterator& p ) {
525  m_vertex = p.m_vertex;
526  m_range = p.m_range;
527  m_set_iter = p.m_set_iter;
528  m_is_inparticle_iter = p.m_is_inparticle_iter;
529  m_is_past_end = p.m_is_past_end;
530  return *this;
531  }
532 
534  if ( !m_vertex || m_is_past_end ) return 0;
535  return *m_set_iter;
536  }
537 
539  // Pre-fix increment
540  //
541  // increment the set iterator (unless we're past the end value)
542  if ( m_is_past_end ) return *this;
543  ++m_set_iter;
544  // handle cases where m_set_iter points past the end
545  if ( m_range == family && m_is_inparticle_iter &&
546  m_set_iter == m_vertex->m_particles_in.end() ) {
547  // at the end on in particle set, and range is family, so move to
548  // out particle set
549  m_set_iter = m_vertex->m_particles_out.begin();
550  m_is_inparticle_iter = false;
551  } else if ( m_range == parents &&
552  m_set_iter == m_vertex->m_particles_in.end() ) {
553  // at the end on in particle set, and range is parents only, so
554  // move into past the end state
555  m_is_past_end = true;
556  // might as well bail out now
557  return *this;
558  }
559  // are we iterating over input or output particles?
560  if( m_is_inparticle_iter ) {
561  // the following is not else if because we might have range=family
562  // with an empty particles_in set.
563  if ( m_set_iter == m_vertex->m_particles_in.end() ) {
564  //whenever out particles end is reached, go into past the end state
565  m_is_past_end = true;
566  }
567  } else {
568  // the following is not else if because we might have range=family
569  // with an empty particles_out set.
570  if ( m_set_iter == m_vertex->m_particles_out.end() ) {
571  //whenever out particles end is reached, go into past the end state
572  m_is_past_end = true;
573  }
574  }
575  return *this;
576  }
577 
579  // Post-fix increment
580  edge_iterator returnvalue = *this;
581  ++*this;
582  return returnvalue;
583  }
584 
586  if ( **this && (**this)->end_vertex() == m_vertex ) return true;
587  return false;
588  }
589 
591  if ( **this && (**this)->production_vertex() == m_vertex ) return true;
592  return false;
593  }
594 
596  if ( range == children ) return m_particles_out.size();
597  if ( range == parents ) return m_particles_in.size();
598  if ( range == family ) return m_particles_out.size()
599  + m_particles_in.size();
600  return 0;
601  }
602 
604  // vertex_iterator //
606 
607  GenVertex::vertex_iterator::vertex_iterator()
608  : m_vertex(0), m_range(), m_visited_vertices(0), m_it_owns_set(0),
609  m_recursive_iterator(0)
610  {}
611 
612  GenVertex::vertex_iterator::vertex_iterator( GenVertex& vtx_root,
613  IteratorRange range )
614  : m_vertex(&vtx_root), m_range(range)
615  {
616  // standard public constructor
617  //
618  m_visited_vertices = new std::set<const GenVertex*>;
619  m_it_owns_set = 1;
620  m_visited_vertices->insert( m_vertex );
621  m_recursive_iterator = 0;
622  m_edge = m_vertex->edges_begin( m_range );
623  // advance to the first good return value
624  if ( !follow_edge_() &&
625  m_edge != m_vertex->edges_end( m_range )) ++*this;
626  }
627 
628  GenVertex::vertex_iterator::vertex_iterator( GenVertex& vtx_root,
629  IteratorRange range, std::set<const HepMC::GenVertex*>& visited_vertices ) :
630  m_vertex(&vtx_root), m_range(range),
631  m_visited_vertices(&visited_vertices), m_it_owns_set(0),
632  m_recursive_iterator(0)
633  {
634  // This constuctor is only to be called internally by this class
635  // for use with its recursive member pointer (m_recursive_iterator).
636  // Note: we do not need to insert m_vertex_root in the vertex - that is
637  // the responsibility of this iterator's mother, which is normally
638  // done just before calling this protected constructor.
639  m_edge = m_vertex->edges_begin( m_range );
640  // advance to the first good return value
641  if ( !follow_edge_() &&
642  m_edge != m_vertex->edges_end( m_range )) ++*this;
643  }
644 
645  GenVertex::vertex_iterator::vertex_iterator( const vertex_iterator& v_iter)
646  : m_vertex(0), m_visited_vertices(0), m_it_owns_set(0),
647  m_recursive_iterator(0)
648  {
649  *this = v_iter;
650  }
651 
652  GenVertex::vertex_iterator::~vertex_iterator() {
653  if ( m_recursive_iterator ) delete m_recursive_iterator;
654  if ( m_it_owns_set ) delete m_visited_vertices;
655  }
656 
658  const vertex_iterator& v_iter )
659  {
660  // Note: when copying a vertex_iterator that is NOT the owner
661  // of its set container, the pointer to the set is copied. Beware!
662  // (see copy_with_own_set() if you want a different set pointed to)
663  // In practise the user never needs to worry
664  // since such iterators are only intended to be used internally.
665  //
666  // destruct data member pointers
667  if ( m_recursive_iterator ) delete m_recursive_iterator;
668  m_recursive_iterator = 0;
669  if ( m_it_owns_set ) delete m_visited_vertices;
670  m_visited_vertices = 0;
671  m_it_owns_set = 0;
672  // copy the target vertex_iterator to this iterator
673  m_vertex = v_iter.m_vertex;
674  m_range = v_iter.m_range;
675  if ( v_iter.m_it_owns_set ) {
676  // i.e. this vertex will own its set if v_iter points to any
677  // vertex set regardless of whether v_iter owns the set or not!
678  m_visited_vertices =
679  new std::set<const GenVertex*>(*v_iter.m_visited_vertices);
680  m_it_owns_set = 1;
681  } else {
682  m_visited_vertices = v_iter.m_visited_vertices;
683  m_it_owns_set = 0;
684  }
685  //
686  // Note: m_vertex_root is already included in the set of
687  // tv_iter.m_visited_vertices, we do not need to insert it.
688  //
689  m_edge = v_iter.m_edge;
690  copy_recursive_iterator_( v_iter.m_recursive_iterator );
691  return *this;
692  }
693 
695  // de-reference operator
696  //
697  // if this iterator has an iterator_node, then we return the iterator
698  // node.
699  if ( m_recursive_iterator ) return **m_recursive_iterator;
700  //
701  // an iterator can only return its m_vertex -- any other vertex
702  // is returned by means of a recursive iterator_node
703  // (so this is the only place in the iterator code that a vertex
704  // is returned!)
705  if ( m_vertex ) return m_vertex;
706  return 0;
707  }
708 
710  // Pre-fix incremental operator
711  //
712  // check for "past the end condition" denoted by m_vertex=0
713  if ( !m_vertex ) return *this;
714  // if at the last edge, move into the "past the end condition"
715  if ( m_edge == m_vertex->edges_end( m_range ) ) {
716  m_vertex = 0;
717  return *this;
718  }
719  // check to see if we need to create a new recursive iterator by
720  // following the current edge only if a recursive iterator doesn't
721  // already exist. If a new recursive_iterator is created, return it.
722  if ( follow_edge_() ) {
723  return *this;
724  }
725  //
726  // if a recursive iterator already exists, increment it, and return its
727  // value (unless the recursive iterator has null root_vertex [its
728  // root vertex is set to null if it has already returned its root]
729  // - in which case we delete it)
730  // and return the vertex pointed to by the edge.
731  if ( m_recursive_iterator ) {
732  ++(*m_recursive_iterator);
733  if ( **m_recursive_iterator ) {
734  return *this;
735  } else {
736  delete m_recursive_iterator;
737  m_recursive_iterator = 0;
738  }
739  }
740  //
741  // increment to the next particle edge
742  ++m_edge;
743  // if m_edge is at the end, then we have incremented through all
744  // edges, and it is time to return m_vertex, which we accomplish
745  // by returning *this
746  if ( m_edge == m_vertex->edges_end( m_range ) ) return *this;
747  // otherwise we follow the current edge by recursively ++ing.
748  return ++(*this);
749  }
750 
752  // Post-fix increment
753  vertex_iterator returnvalue(*this);
754  ++(*this);
755  return returnvalue;
756  }
757 
759  const vertex_iterator& v_iter,
760  std::set<const HepMC::GenVertex*>& visited_vertices ) {
765  //
766  // destruct data member pointers
767  if ( m_recursive_iterator ) delete m_recursive_iterator;
768  m_recursive_iterator = 0;
769  if ( m_it_owns_set ) delete m_visited_vertices;
770  m_visited_vertices = 0;
771  m_it_owns_set = false;
772  // copy the target vertex_iterator to this iterator
773  m_vertex = v_iter.m_vertex;
774  m_range = v_iter.m_range;
775  m_visited_vertices = &visited_vertices;
776  m_it_owns_set = false;
777  m_edge = v_iter.m_edge;
778  copy_recursive_iterator_( v_iter.m_recursive_iterator );
779  }
780 
782  // follows the edge pointed to by m_edge by creating a
783  // recursive iterator for it.
784  //
785  // if a m_recursive_iterator already exists,
786  // this routine has nothing to do,
787  // if there's no m_vertex, there's no point following anything,
788  // also there's no point trying to follow a null edge.
789  if ( m_recursive_iterator || !m_vertex || !*m_edge ) return 0;
790  //
791  // if the range is parents, children, or family (i.e. <= family)
792  // then only the iterator which owns the set is allowed to create
793  // recursive iterators (i.e. recursivity is only allowed to go one
794  // layer deep)
795  if ( m_range <= family && m_it_owns_set == 0 ) return 0;
796  //
797  // M.Dobbs 2001-07-16
798  // Take care of the very special-rare case where a particle might
799  // point to the same vertex for both production and end
800  if ( (*m_edge)->production_vertex() ==
801  (*m_edge)->end_vertex() ) return 0;
802  //
803  // figure out which vertex m_edge is pointing to
804  GenVertex* vtx = ( m_edge.is_parent() ?
805  (*m_edge)->production_vertex() :
806  (*m_edge)->end_vertex() );
807  // if the pointed to vertex doesn't exist or has already been visited,
808  // then return null
809  if ( !vtx || !(m_visited_vertices->insert(vtx).second) ) return 0;
810  // follow that edge by creating a recursive iterator
811  m_recursive_iterator = new vertex_iterator( *vtx, m_range,
812  *m_visited_vertices);
813  // and return the vertex pointed to by m_recursive_iterator
814  return **m_recursive_iterator;
815  }
816 
818  const vertex_iterator* recursive_v_iter ) {
819  // to properly copy the recursive iterator, we need to ensure
820  // the proper set container is transfered ... then do this
821  // operation .... you guessed it .... recursively!
822  //
823  if ( !recursive_v_iter ) return;
824  m_recursive_iterator = new vertex_iterator();
825  m_recursive_iterator->m_vertex = recursive_v_iter->m_vertex;
826  m_recursive_iterator->m_range = recursive_v_iter->m_range;
827  m_recursive_iterator->m_visited_vertices = m_visited_vertices;
828  m_recursive_iterator->m_it_owns_set = 0;
829  m_recursive_iterator->m_edge = recursive_v_iter->m_edge;
830  m_recursive_iterator->copy_recursive_iterator_(
831  recursive_v_iter->m_recursive_iterator );
832  }
833 
835  // particle_iterator //
837 
838  GenVertex::particle_iterator::particle_iterator() {}
839 
840  GenVertex::particle_iterator::particle_iterator( GenVertex& vertex_root,
841  IteratorRange range ) {
842  // General Purpose Constructor
843  //
844  if ( range <= family ) {
845  m_edge = GenVertex::edge_iterator( vertex_root, range );
846  } else {
847  m_vertex_iterator = GenVertex::vertex_iterator(vertex_root, range);
848  m_edge = GenVertex::edge_iterator( **m_vertex_iterator,
849  m_vertex_iterator.range() );
850  }
851  advance_to_first_();
852  }
853 
854  GenVertex::particle_iterator::particle_iterator(
855  const particle_iterator& p_iter ){
856  *this = p_iter;
857  }
858 
859  GenVertex::particle_iterator::~particle_iterator() {}
860 
863  {
864  m_vertex_iterator = p_iter.m_vertex_iterator;
865  m_edge = p_iter.m_edge;
866  return *this;
867  }
868 
870  return *m_edge;
871  }
872 
875  //Pre-fix increment
876  //
877  if ( *m_edge ) {
878  ++m_edge;
879  } else if ( *m_vertex_iterator ) { // !*m_edge is implicit
880  // past end of edge, but still have more vertices to visit
881  // increment the vertex, checking that the result is valid
882  if ( !*(++m_vertex_iterator) ) return *this;
883  m_edge = GenVertex::edge_iterator( **m_vertex_iterator,
884  m_vertex_iterator.range() );
885  } else { // !*m_edge and !*m_vertex_iterator are implicit
886  // past the end condition: do nothing
887  return *this;
888  }
889  advance_to_first_();
890  return *this;
891  }
892 
894  //Post-fix increment
895  particle_iterator returnvalue(*this);
896  ++(*this);
897  return returnvalue;
898  }
899 
904  if ( !*m_edge ) return *(++*this);
905  // if the range is relatives, we need to uniquely assign each particle
906  // to a single vertex so as to guarantee particles are returned
907  // exactly once.
908  if ( m_vertex_iterator.range() == relatives &&
909  m_edge.is_parent() &&
910  (*m_edge)->production_vertex() ) return *(++*this);
911  return *m_edge;
912  }
913 
918  void GenVertex::convert_position( const double& f ) {
919  m_position = FourVector( f*m_position.x(),
920  f*m_position.y(),
921  f*m_position.z(),
922  f*m_position.t() );
923  }
924 
925 } // HepMC
void convert_position(const double &)
Definition: GenVertex.cc:918
vertex_iterator & operator++(void)
Pre-fix increment.
Definition: GenVertex.cc:709
GenVertex * follow_edge_()
non-null if recursive iter. created
Definition: GenVertex.cc:781
int barcode() const
unique identifier
Definition: GenVertex.h:416
edge_iterator edges_end(IteratorRange) const
end range
Definition: GenVertex.h:481
double z() const
return z
Definition: SimpleVector.h:77
bool is_parent() const
true if parent of root vtx
Definition: GenVertex.cc:585
std::vector< HepMC::GenParticle * >::const_iterator particles_in_const_iterator
const iterator for incoming particles
Definition: GenVertex.h:152
bool set_barcode(GenParticle *p, int suggested_barcode=false)
set the barcode - intended for use by GenParticle
Definition: GenEvent.cc:430
GenParticle * remove_particle(GenParticle *particle)
remove a particle
Definition: GenVertex.cc:295
edge_iterator edges_begin(IteratorRange range=family) const
begin range
Definition: GenVertex.h:476
void print(std::ostream &ostr=std::cout) const
print vertex information
Definition: GenVertex.cc:145
void add_particle_in(GenParticle *inparticle)
add incoming particle
Definition: GenVertex.cc:273
GenParticle * operator*(void) const
return a pointer to a particle
Definition: GenVertex.cc:869
void copy_with_own_set(const vertex_iterator &v_iter, std::set< const HepMC::GenVertex * > &visited_vertices)
intended for internal use only.
Definition: GenVertex.cc:758
particles_out_const_iterator particles_out_const_end() const
end iteration of outgoing particles
Definition: GenVertex.h:450
std::vector< HepMC::GenParticle * >::const_iterator particles_out_const_iterator
const iterator for outgoing particles
Definition: GenVertex.h:155
bool suggest_barcode(int the_bar_code)
In general there is no reason to &quot;suggest_barcode&quot;.
Definition: GenVertex.cc:363
edge_iterator & operator++(void)
Pre-fix increment.
Definition: GenVertex.cc:538
void remove_barcode(GenParticle *p)
intended for use by GenParticle
Definition: GenEvent.h:774
vertex_iterator & operator=(const vertex_iterator &)
make a copy
Definition: GenVertex.cc:657
double y() const
return y
Definition: SimpleVector.h:76
GenVertex * production_vertex() const
pointer to the production vertex
Definition: GenParticle.h:218
void set_barcode_(int the_bar_code)
set identifier
Definition: GenVertex.h:417
GenVertex contains information about decay vertices.
Definition: GenVertex.h:52
std::vector< double >::const_iterator const_iterator
const iterator for the weight container
bool is_child() const
true if child of root vtx
Definition: GenVertex.cc:590
void swap(FourVector &other)
swap
The GenEvent class is the core of HepMC.
Definition: GenEvent.h:155
bool operator==(const GenVertex &a) const
equality
Definition: GenVertex.cc:103
void remove_particle_out(GenParticle *)
for internal use only - remove particle from outgoing list
Definition: GenVertex.cc:323
void add_particle_out(GenParticle *outparticle)
add outgoing particle
Definition: GenVertex.cc:284
GenVertex * operator*(void) const
return a pointer to a vertex
Definition: GenVertex.cc:694
particles_in_const_iterator particles_in_const_end() const
end iteration of incoming particles
Definition: GenVertex.h:440
double check_momentum_conservation() const
|Sum (three_mom_in-three_mom_out)|
Definition: GenVertex.cc:253
bool operator!=(const GenVertex &a) const
inequality
Definition: GenVertex.cc:140
void change_parent_event_(GenEvent *evt)
for use with swap
Definition: GenVertex.cc:419
double x() const
return x
Definition: SimpleVector.h:75
GenEvent * parent_event() const
pointer to the event that owns this vertex
Definition: GenVertex.h:408
void set_production_vertex_(GenVertex *productionvertex=0)
set production vertex - for internal use only
Definition: GenParticle.cc:129
int particles_out_size() const
number of outgoing particles
Definition: GenVertex.h:458
int id() const
vertex ID
Definition: GenVertex.h:414
void remove_particle_in(GenParticle *)
for internal use only - remove particle from incoming list
Definition: GenVertex.cc:317
particles_out_const_iterator particles_out_const_begin() const
begin iteration of outgoing particles
Definition: GenVertex.h:445
edge_iterator & operator=(const edge_iterator &p)
make a copy
Definition: GenVertex.cc:523
particle_iterator & operator++(void)
Pre-fix increment.
Definition: GenVertex.cc:874
WeightContainer & weights()
direct access to the weights container is allowed.
Definition: GenVertex.h:419
const FourVector & position() const
vertex position and time
Definition: GenVertex.h:406
void set_parent_event_(GenEvent *evt)
set parent event
Definition: GenVertex.cc:388
FourVector is a simple representation of a physics 4 vector.
Definition: SimpleVector.h:42
iterator end()
end of the weight container
GenVertex * end_vertex() const
pointer to the decay vertex
Definition: GenParticle.h:221
IteratorRange
type of iteration
Definition: IteratorRange.h:17
std::vector< HepMC::GenParticle * >::iterator already_in_vector(std::vector< HepMC::GenParticle * > *, GenParticle *)
returns true if GenParticle is in the vector
Definition: SearchVector.cc:18
GenParticle * advance_to_first_()
&quot;first&quot; particle
Definition: GenVertex.cc:900
int edges_size(IteratorRange range=family) const
size
Definition: GenVertex.cc:595
Container for the Weights associated with an event or vertex.
void copy_recursive_iterator_(const vertex_iterator *recursive_v_iter)
copy recursive iterator
Definition: GenVertex.cc:817
GenVertex(const FourVector &position=FourVector(0, 0, 0, 0), int id=0, const WeightContainer &weights=std::vector< double >())
default constructor
Definition: GenVertex.cc:14
particles_in_const_iterator particles_in_const_begin() const
begin iteration of incoming particles
Definition: GenVertex.h:435
void swap(WeightContainer &other)
swap
int particles_in_size() const
number of incoming particles
Definition: GenVertex.h:454
GenParticle * operator*(void) const
return a pointer to a particle
Definition: GenVertex.cc:533
void delete_adopted_particles()
for internal use only
Definition: GenVertex.cc:329
void swap(GenVertex &other)
swap
Definition: GenVertex.cc:71
double t() const
return t
Definition: SimpleVector.h:78
void set_end_vertex_(GenVertex *decayvertex=0)
set decay vertex - for internal use only
Definition: GenParticle.cc:142
particle_iterator & operator=(const particle_iterator &)
make a copy
Definition: GenVertex.cc:862
size_type size() const
size of weight container
The GenParticle class contains information about generated particles.
Definition: GenParticle.h:60
GenVertex & operator=(const GenVertex &invertex)
shallow
Definition: GenVertex.cc:82