]> git.uio.no Git - u/mrichter/AliRoot.git/blame - TEvtGen/HepMC/GenEvent.cc
Resolving the symbols in each library
[u/mrichter/AliRoot.git] / TEvtGen / HepMC / GenEvent.cc
CommitLineData
0ca57c2f 1//////////////////////////////////////////////////////////////////////////
2// Matt.Dobbs@Cern.CH, September 1999
3// Updated: 7.1.2000 iterators complete and working!
4// Updated: 10.1.2000 GenEvent::vertex, particle iterators are made
5// constant WRT this event ... note that
6// GenVertex::***_iterator is not const, since it must
7// be able to return a mutable pointer to itself.
8// Updated: 08.2.2000 the event now holds a set of all attached vertices
9// rather than just the roots of the graph
10// Event record for MC generators (for use at any stage of generation)
11//////////////////////////////////////////////////////////////////////////
12
13#include <iomanip>
14
15#include "HepMC/GenEvent.h"
16#include "HepMC/GenCrossSection.h"
17#include "HepMC/Version.h"
18#include "HepMC/StreamHelpers.h"
19
20namespace HepMC {
21
22 GenEvent::GenEvent( int signal_process_id,
23 int event_number,
24 GenVertex* signal_vertex,
25 const WeightContainer& weights,
26 const std::vector<long>& random_states,
27 Units::MomentumUnit mom,
28 Units::LengthUnit len ) :
29 m_signal_process_id(signal_process_id),
30 m_event_number(event_number),
31 m_mpi(-1),
32 m_event_scale(-1),
33 m_alphaQCD(-1),
34 m_alphaQED(-1),
35 m_signal_process_vertex(signal_vertex),
36 m_beam_particle_1(0),
37 m_beam_particle_2(0),
38 m_weights(weights),
39 m_random_states(random_states),
40 m_vertex_barcodes(),
41 m_particle_barcodes(),
42 m_cross_section(0),
43 m_heavy_ion(0),
44 m_pdf_info(0),
45 m_momentum_unit(mom),
46 m_position_unit(len)
47 {
48 /// This constructor only allows null pointers to HeavyIon and PdfInfo
49 ///
50 /// note: default values for m_event_scale, m_alphaQCD, m_alphaQED
51 /// are as suggested in hep-ph/0109068, "Generic Interface..."
52 ///
53 }
54
55 GenEvent::GenEvent( int signal_process_id, int event_number,
56 GenVertex* signal_vertex,
57 const WeightContainer& weights,
58 const std::vector<long>& random_states,
59 const HeavyIon& ion,
60 const PdfInfo& pdf,
61 Units::MomentumUnit mom,
62 Units::LengthUnit len ) :
63 m_signal_process_id(signal_process_id),
64 m_event_number(event_number),
65 m_mpi(-1),
66 m_event_scale(-1),
67 m_alphaQCD(-1),
68 m_alphaQED(-1),
69 m_signal_process_vertex(signal_vertex),
70 m_beam_particle_1(0),
71 m_beam_particle_2(0),
72 m_weights(weights),
73 m_random_states(random_states),
74 m_vertex_barcodes(),
75 m_particle_barcodes(),
76 m_cross_section(0),
77 m_heavy_ion( new HeavyIon(ion) ),
78 m_pdf_info( new PdfInfo(pdf) ),
79 m_momentum_unit(mom),
80 m_position_unit(len)
81 {
82 /// GenEvent makes its own copy of HeavyIon and PdfInfo
83 ///
84 /// note: default values for m_event_scale, m_alphaQCD, m_alphaQED
85 /// are as suggested in hep-ph/0109068, "Generic Interface..."
86 }
87
88 GenEvent::GenEvent( Units::MomentumUnit mom,
89 Units::LengthUnit len,
90 int signal_process_id,
91 int event_number,
92 GenVertex* signal_vertex,
93 const WeightContainer& weights,
94 const std::vector<long>& random_states ) :
95 m_signal_process_id(signal_process_id),
96 m_event_number(event_number),
97 m_mpi(-1),
98 m_event_scale(-1),
99 m_alphaQCD(-1),
100 m_alphaQED(-1),
101 m_signal_process_vertex(signal_vertex),
102 m_beam_particle_1(0),
103 m_beam_particle_2(0),
104 m_weights(weights),
105 m_random_states(random_states),
106 m_vertex_barcodes(),
107 m_particle_barcodes(),
108 m_cross_section(0),
109 m_heavy_ion(0),
110 m_pdf_info(0),
111 m_momentum_unit(mom),
112 m_position_unit(len)
113 {
114 /// constructor requiring units - all else is default
115 /// This constructor only allows null pointers to HeavyIon and PdfInfo
116 ///
117 /// note: default values for m_event_scale, m_alphaQCD, m_alphaQED
118 /// are as suggested in hep-ph/0109068, "Generic Interface..."
119 ///
120 }
121
122 GenEvent::GenEvent( Units::MomentumUnit mom,
123 Units::LengthUnit len,
124 int signal_process_id, int event_number,
125 GenVertex* signal_vertex,
126 const WeightContainer& weights,
127 const std::vector<long>& random_states,
128 const HeavyIon& ion,
129 const PdfInfo& pdf ) :
130 m_signal_process_id(signal_process_id),
131 m_event_number(event_number),
132 m_mpi(-1),
133 m_event_scale(-1),
134 m_alphaQCD(-1),
135 m_alphaQED(-1),
136 m_signal_process_vertex(signal_vertex),
137 m_beam_particle_1(0),
138 m_beam_particle_2(0),
139 m_weights(weights),
140 m_random_states(random_states),
141 m_vertex_barcodes(),
142 m_particle_barcodes(),
143 m_cross_section(0),
144 m_heavy_ion( new HeavyIon(ion) ),
145 m_pdf_info( new PdfInfo(pdf) ),
146 m_momentum_unit(mom),
147 m_position_unit(len)
148 {
149 /// explicit constructor with units first that takes HeavyIon and PdfInfo
150 /// GenEvent makes its own copy of HeavyIon and PdfInfo
151 ///
152 /// note: default values for m_event_scale, m_alphaQCD, m_alphaQED
153 /// are as suggested in hep-ph/0109068, "Generic Interface..."
154 }
155
156 GenEvent::GenEvent( const GenEvent& inevent )
157 : m_signal_process_id ( inevent.signal_process_id() ),
158 m_event_number ( inevent.event_number() ),
159 m_mpi ( inevent.mpi() ),
160 m_event_scale ( inevent.event_scale() ),
161 m_alphaQCD ( inevent.alphaQCD() ),
162 m_alphaQED ( inevent.alphaQED() ),
163 m_signal_process_vertex( /* inevent.m_signal_process_vertex */ ),
164 m_beam_particle_1 ( /* inevent.m_beam_particle_1 */ ),
165 m_beam_particle_2 ( /* inevent.m_beam_particle_2 */ ),
166 m_weights ( /* inevent.m_weights */ ),
167 m_random_states ( /* inevent.m_random_states */ ),
168 m_vertex_barcodes ( /* inevent.m_vertex_barcodes */ ),
169 m_particle_barcodes ( /* inevent.m_particle_barcodes */ ),
170 m_cross_section ( inevent.cross_section() ? new GenCrossSection(*inevent.cross_section()) : 0 ),
171 m_heavy_ion ( inevent.heavy_ion() ? new HeavyIon(*inevent.heavy_ion()) : 0 ),
172 m_pdf_info ( inevent.pdf_info() ? new PdfInfo(*inevent.pdf_info()) : 0 ),
173 m_momentum_unit ( inevent.momentum_unit() ),
174 m_position_unit ( inevent.length_unit() )
175 {
176 /// deep copy - makes a copy of all vertices!
177 //
178
179 // 1. create a NEW copy of all vertices from inevent
180 // taking care to map new vertices onto the vertices being copied
181 // and add these new vertices to this event.
182 // We do not use GenVertex::operator= because that would copy
183 // the attached particles as well.
184 std::map<const GenVertex*,GenVertex*> map_in_to_new;
185 for ( GenEvent::vertex_const_iterator v = inevent.vertices_begin();
186 v != inevent.vertices_end(); ++v ) {
187 GenVertex* newvertex = new GenVertex(
188 (*v)->position(), (*v)->id(), (*v)->weights() );
189 newvertex->suggest_barcode( (*v)->barcode() );
190 map_in_to_new[*v] = newvertex;
191 add_vertex( newvertex );
192 }
193 // 2. copy the signal process vertex info.
194 if ( inevent.signal_process_vertex() ) {
195 set_signal_process_vertex(
196 map_in_to_new[inevent.signal_process_vertex()] );
197 } else set_signal_process_vertex( 0 );
198 //
199 // 3. create a NEW copy of all particles from inevent
200 // taking care to attach them to the appropriate vertex
201 GenParticle* beam1(0);
202 GenParticle* beam2(0);
203 for ( GenEvent::particle_const_iterator p = inevent.particles_begin();
204 p != inevent.particles_end(); ++p )
205 {
206 GenParticle* oldparticle = *p;
207 GenParticle* newparticle = new GenParticle(*oldparticle);
208 if ( oldparticle->end_vertex() ) {
209 map_in_to_new[ oldparticle->end_vertex() ]->
210 add_particle_in(newparticle);
211 }
212 if ( oldparticle->production_vertex() ) {
213 map_in_to_new[ oldparticle->production_vertex() ]->
214 add_particle_out(newparticle);
215 }
216 if ( oldparticle == inevent.beam_particles().first ) beam1 = newparticle;
217 if ( oldparticle == inevent.beam_particles().second ) beam2 = newparticle;
218 }
219 set_beam_particles( beam1, beam2 );
220 //
221 // 4. now that vtx/particles are copied, copy weights and random states
222 set_random_states( inevent.random_states() );
223 weights() = inevent.weights();
224 }
225
226 void GenEvent::swap( GenEvent & other )
227 {
228 // if a container has a swap method, use that for improved performance
229 std::swap(m_signal_process_id , other.m_signal_process_id );
230 std::swap(m_event_number , other.m_event_number );
231 std::swap(m_mpi , other.m_mpi );
232 std::swap(m_event_scale , other.m_event_scale );
233 std::swap(m_alphaQCD , other.m_alphaQCD );
234 std::swap(m_alphaQED , other.m_alphaQED );
235 std::swap(m_signal_process_vertex, other.m_signal_process_vertex);
236 std::swap(m_beam_particle_1 , other.m_beam_particle_1 );
237 std::swap(m_beam_particle_2 , other.m_beam_particle_2 );
238 m_weights.swap( other.m_weights );
239 m_random_states.swap( other.m_random_states );
240 m_vertex_barcodes.swap( other.m_vertex_barcodes );
241 m_particle_barcodes.swap( other.m_particle_barcodes );
242 std::swap(m_cross_section , other.m_cross_section );
243 std::swap(m_heavy_ion , other.m_heavy_ion );
244 std::swap(m_pdf_info , other.m_pdf_info );
245 std::swap(m_momentum_unit , other.m_momentum_unit );
246 std::swap(m_position_unit , other.m_position_unit );
247 // must now adjust GenVertex back pointers
248 for ( GenEvent::vertex_const_iterator vthis = vertices_begin();
249 vthis != vertices_end(); ++vthis ) {
250 (*vthis)->change_parent_event_( this );
251 }
252 for ( GenEvent::vertex_const_iterator voth = other.vertices_begin();
253 voth != other.vertices_end(); ++voth ) {
254 (*voth)->change_parent_event_( &other );
255 }
256 }
257
258 GenEvent::~GenEvent()
259 {
260 /// Deep destructor.
261 /// deletes all vertices/particles in this GenEvent
262 /// deletes the associated HeavyIon and PdfInfo
263 delete_all_vertices();
264 delete m_cross_section;
265 delete m_heavy_ion;
266 delete m_pdf_info;
267 }
268
269 GenEvent& GenEvent::operator=( const GenEvent& inevent )
270 {
271 /// best practices implementation
272 GenEvent tmp( inevent );
273 swap( tmp );
274 return *this;
275 }
276
277 void GenEvent::print( std::ostream& ostr ) const {
278 /// dumps the content of this event to ostr
279 /// to dump to cout use: event.print();
280 /// if you want to write this event to file outfile.txt you could use:
281 /// std::ofstream outfile("outfile.txt"); event.print( outfile );
282 ostr << "________________________________________"
283 << "________________________________________\n";
284 ostr << "GenEvent: #" << event_number()
285 << " ID=" << signal_process_id()
286 << " SignalProcessGenVertex Barcode: "
287 << ( signal_process_vertex() ? signal_process_vertex()->barcode()
288 : 0 )
289 << "\n";
290 write_units( ostr );
291 write_cross_section(ostr);
292 ostr << " Entries this event: " << vertices_size() << " vertices, "
293 << particles_size() << " particles.\n";
294 if( m_beam_particle_1 && m_beam_particle_2 ) {
295 ostr << " Beam Particle barcodes: " << beam_particles().first->barcode() << " "
296 << beam_particles().second->barcode() << " \n";
297 } else {
298 ostr << " Beam Particles are not defined.\n";
299 }
300 // Random State
301 ostr << " RndmState(" << m_random_states.size() << ")=";
302 for ( std::vector<long>::const_iterator rs
303 = m_random_states.begin();
304 rs != m_random_states.end(); ++rs ) { ostr << *rs << " "; }
305 ostr << "\n";
306 // Weights
307 ostr << " Wgts(" << weights().size() << ")=";
308 weights().print(ostr);
309 ostr << " EventScale " << event_scale()
310 << " [energy] \t alphaQCD=" << alphaQCD()
311 << "\t alphaQED=" << alphaQED() << std::endl;
312 // print a legend to describe the particle info
313 ostr << " GenParticle Legend\n";
314 ostr << " Barcode PDG ID "
315 << "( Px, Py, Pz, E )"
316 << " Stat DecayVtx\n";
317 ostr << "________________________________________"
318 << "________________________________________\n";
319 // Print all Vertices
320 for ( GenEvent::vertex_const_iterator vtx = this->vertices_begin();
321 vtx != this->vertices_end(); ++vtx ) {
322 (*vtx)->print(ostr);
323 }
324 ostr << "________________________________________"
325 << "________________________________________" << std::endl;
326 }
327
328 void GenEvent::print_version( std::ostream& ostr ) const {
329 ostr << "---------------------------------------------" << std::endl;
330 writeVersion( ostr );
331 ostr << "---------------------------------------------" << std::endl;
332 }
333
334 bool GenEvent::add_vertex( GenVertex* vtx ) {
335 /// returns true if successful - generally will only return false
336 /// if the inserted vertex is already included in the event.
337 if ( !vtx ) return false;
338 // if vtx previously pointed to another GenEvent, remove it from that
339 // GenEvent's list
340 if ( vtx->parent_event() && vtx->parent_event() != this ) {
341 bool remove_status = vtx->parent_event()->remove_vertex( vtx );
342 if ( !remove_status ) {
343 std::cerr << "GenEvent::add_vertex ERROR "
344 << "GenVertex::parent_event points to \n"
345 << "an event that does not point back to the "
346 << "GenVertex. \n This probably indicates a deeper "
347 << "problem. " << std::endl;
348 }
349 }
350 //
351 // setting the vertex parent also inserts the vertex into this
352 // event
353 vtx->set_parent_event_( this );
354 return ( m_vertex_barcodes.count(vtx->barcode()) ? true : false );
355 }
356
357 bool GenEvent::remove_vertex( GenVertex* vtx ) {
358 /// this removes vtx from the event but does NOT delete it.
359 /// returns True if an entry vtx existed in the table and was erased
360 if ( m_signal_process_vertex == vtx ) m_signal_process_vertex = 0;
361 if ( vtx->parent_event() == this ) vtx->set_parent_event_( 0 );
362 return ( m_vertex_barcodes.count(vtx->barcode()) ? false : true );
363 }
364
365 void GenEvent::clear()
366 {
367 /// remove all information from the event
368 /// deletes all vertices/particles in this evt
369 ///
370 delete_all_vertices();
371 // remove existing objects and set pointers to null
372 delete m_cross_section;
373 m_cross_section = 0;
374 delete m_heavy_ion;
375 m_heavy_ion = 0;
376 delete m_pdf_info;
377 m_pdf_info = 0;
378 m_signal_process_id = 0;
379 m_beam_particle_1 = 0;
380 m_beam_particle_2 = 0;
381 m_event_number = 0;
382 m_mpi = -1;
383 m_event_scale = -1;
384 m_alphaQCD = -1;
385 m_alphaQED = -1;
386 m_weights = std::vector<double>();
387 m_random_states = std::vector<long>();
388 // resetting unit information
389 m_momentum_unit = Units::default_momentum_unit();
390 m_position_unit = Units::default_length_unit();
391 // error check just to be safe
392 if ( m_vertex_barcodes.size() != 0
393 || m_particle_barcodes.size() != 0 ) {
394 std::cerr << "GenEvent::clear() strange result ... \n"
395 << "either the particle and/or the vertex map isn't empty" << std::endl;
396 std::cerr << "Number vtx,particle the event after deleting = "
397 << m_vertex_barcodes.size() << " "
398 << m_particle_barcodes.size() << std::endl;
399 }
400 return;
401 }
402
403 void GenEvent::delete_all_vertices() {
404 /// deletes all vertices in the vertex container
405 /// (i.e. all vertices owned by this event)
406 /// The vertices are the "owners" of the particles, so as we delete
407 /// the vertices, the vertex desctructors are automatically
408 /// deleting their particles.
409
410 // delete each vertex individually (this deletes particles as well)
411 while ( !vertices_empty() ) {
412 GenVertex* vtx = ( m_vertex_barcodes.begin() )->second;
413 m_vertex_barcodes.erase( m_vertex_barcodes.begin() );
414 delete vtx;
415 }
416 //
417 // Error checking:
418 if ( !vertices_empty() || ! particles_empty() ) {
419 std::cerr << "GenEvent::delete_all_vertices strange result ... "
420 << "after deleting all vertices, \nthe particle and "
421 << "vertex maps aren't empty.\n This probably "
422 << "indicates deeper problems or memory leak in the "
423 << "code." << std::endl;
424 std::cerr << "Number vtx,particle the event after deleting = "
425 << m_vertex_barcodes.size() << " "
426 << m_particle_barcodes.size() << std::endl;
427 }
428 }
429
430 bool GenEvent::set_barcode( GenParticle* p, int suggested_barcode )
431 {
432 if ( p->parent_event() != this ) {
433 std::cerr << "GenEvent::set_barcode attempted, but the argument's"
434 << "\n parent_event is not this ... request rejected."
435 << std::endl;
436 return false;
437 }
438 // M.Dobbs Nov 4, 2002
439 // First we must check to see if the particle already has a
440 // barcode which is different from the suggestion. If yes, we
441 // remove it from the particle map.
442 if ( p->barcode() != 0 && p->barcode() != suggested_barcode ) {
443 if ( m_particle_barcodes.count(p->barcode()) &&
444 m_particle_barcodes[p->barcode()] == p ) {
445 m_particle_barcodes.erase( p->barcode() );
446 }
447 // At this point either the particle is NOT in
448 // m_particle_barcodes, or else it is in the map, but
449 // already with the suggested barcode.
450 }
451 //
452 // First case --- a valid barcode has been suggested
453 // (valid barcodes are numbers greater than zero)
454 bool insert_success = true;
455 if ( suggested_barcode > 0 ) {
456 if ( m_particle_barcodes.count(suggested_barcode) ) {
457 // the suggested_barcode is already used.
458 if ( m_particle_barcodes[suggested_barcode] == p ) {
459 // but it was used for this particle ... so everythings ok
460 p->set_barcode_( suggested_barcode );
461 return true;
462 }
463 insert_success = false;
464 suggested_barcode = 0;
465 } else { // suggested barcode is OK, proceed to insert
466 m_particle_barcodes[suggested_barcode] = p;
467 p->set_barcode_( suggested_barcode );
468 return true;
469 }
470 }
471 //
472 // Other possibility -- a valid barcode has not been suggested,
473 // so one is automatically generated
474 if ( suggested_barcode < 0 ) insert_success = false;
475 if ( suggested_barcode <= 0 ) {
476 if ( !m_particle_barcodes.empty() ) {
477 // in this case we find the highest barcode that was used,
478 // and increment it by 1
479 suggested_barcode = m_particle_barcodes.rbegin()->first;
480 ++suggested_barcode;
481 }
482 // For the automatically assigned barcodes, the first one
483 // we use is 10001 ... this is just because when we read
484 // events from HEPEVT, we will suggest their index as the
485 // barcode, and that index has maximum value 10000.
486 // This way we will immediately be able to recognize the hepevt
487 // particles from the auto-assigned ones.
488 if ( suggested_barcode <= 10000 ) suggested_barcode = 10001;
489 }
490 // At this point we should have a valid barcode
491 if ( m_particle_barcodes.count(suggested_barcode) ) {
492 std::cerr << "GenEvent::set_barcode ERROR, this should never "
493 << "happen \n report bug to matt.dobbs@cern.ch"
494 << std::endl;
495 }
496 m_particle_barcodes[suggested_barcode] = p;
497 p->set_barcode_( suggested_barcode );
498 return insert_success;
499 }
500
501 bool GenEvent::set_barcode( GenVertex* v, int suggested_barcode )
502 {
503 if ( v->parent_event() != this ) {
504 std::cerr << "GenEvent::set_barcode attempted, but the argument's"
505 << "\n parent_event is not this ... request rejected."
506 << std::endl;
507 return false;
508 }
509 // M.Dobbs Nov 4, 2002
510 // First we must check to see if the vertex already has a
511 // barcode which is different from the suggestion. If yes, we
512 // remove it from the vertex map.
513 if ( v->barcode() != 0 && v->barcode() != suggested_barcode ) {
514 if ( m_vertex_barcodes.count(v->barcode()) &&
515 m_vertex_barcodes[v->barcode()] == v ) {
516 m_vertex_barcodes.erase( v->barcode() );
517 }
518 // At this point either the vertex is NOT in
519 // m_vertex_barcodes, or else it is in the map, but
520 // already with the suggested barcode.
521 }
522
523 //
524 // First case --- a valid barcode has been suggested
525 // (valid barcodes are numbers greater than zero)
526 bool insert_success = true;
527 if ( suggested_barcode < 0 ) {
528 if ( m_vertex_barcodes.count(suggested_barcode) ) {
529 // the suggested_barcode is already used.
530 if ( m_vertex_barcodes[suggested_barcode] == v ) {
531 // but it was used for this vertex ... so everythings ok
532 v->set_barcode_( suggested_barcode );
533 return true;
534 }
535 insert_success = false;
536 suggested_barcode = 0;
537 } else { // suggested barcode is OK, proceed to insert
538 m_vertex_barcodes[suggested_barcode] = v;
539 v->set_barcode_( suggested_barcode );
540 return true;
541 }
542 }
543 //
544 // Other possibility -- a valid barcode has not been suggested,
545 // so one is automatically generated
546 if ( suggested_barcode > 0 ) insert_success = false;
547 if ( suggested_barcode >= 0 ) {
548 if ( !m_vertex_barcodes.empty() ) {
549 // in this case we find the highest barcode that was used,
550 // and increment it by 1, (vertex barcodes are negative)
551 suggested_barcode = m_vertex_barcodes.rbegin()->first;
552 --suggested_barcode;
553 }
554 if ( suggested_barcode >= 0 ) suggested_barcode = -1;
555 }
556 // At this point we should have a valid barcode
557 if ( m_vertex_barcodes.count(suggested_barcode) ) {
558 std::cerr << "GenEvent::set_barcode ERROR, this should never "
559 << "happen \n report bug to matt.dobbs@cern.ch"
560 << std::endl;
561 }
562 m_vertex_barcodes[suggested_barcode] = v;
563 v->set_barcode_( suggested_barcode );
564 return insert_success;
565 }
566
567 /// test to see if we have two valid beam particles
568 bool GenEvent::valid_beam_particles() const {
569 bool have1 = false;
570 bool have2 = false;
571 // first check that both are defined
572 if(m_beam_particle_1 && m_beam_particle_2) {
573 // now look for a match with the particle "list"
574 for ( particle_const_iterator p = particles_begin();
575 p != particles_end(); ++p ) {
576 if( m_beam_particle_1 == *p ) have1 = true;
577 if( m_beam_particle_2 == *p ) have2 = true;
578 }
579 }
580 if( have1 && have2 ) return true;
581 return false;
582 }
583
584 /// construct the beam particle information using pointers to GenParticle
585 /// returns false if either GenParticle* is null
586 bool GenEvent::set_beam_particles(GenParticle* bp1, GenParticle* bp2) {
587 m_beam_particle_1 = bp1;
588 m_beam_particle_2 = bp2;
589 if( m_beam_particle_1 && m_beam_particle_2 ) return true;
590 return false;
591 }
592
593 /// construct the beam particle information using a std::pair of pointers to GenParticle
594 /// returns false if either GenParticle* is null
595 bool GenEvent::set_beam_particles(std::pair<HepMC::GenParticle*, HepMC::GenParticle*> const & bp) {
596 return set_beam_particles(bp.first,bp.second);
597 }
598
599 void GenEvent::write_units( std::ostream & os ) const {
600 os << " Momenutm units:" << std::setw(8) << name(momentum_unit());
601 os << " Position units:" << std::setw(8) << name(length_unit());
602 os << std::endl;
603 }
604
605 void GenEvent::write_cross_section( std::ostream& os ) const
606 {
607 // write the GenCrossSection information if the cross section was set
608 if( !cross_section() ) return;
609 if( cross_section()->is_set() ) {
610 os << " Cross Section: " << cross_section()->cross_section() ;
611 os << " +/- " << cross_section()->cross_section_error() ;
612 os << std::endl;
613 }
614 }
615
616 bool GenEvent::use_momentum_unit( Units::MomentumUnit newunit ) {
617 // currently not exception-safe.
618 // Easy to fix, though, if needed.
619 if ( m_momentum_unit != newunit ) {
620 const double factor = Units::conversion_factor( m_momentum_unit, newunit );
621 // multiply all momenta by 'factor',
622 // loop is entered only if particle list is not empty
623 for ( GenEvent::particle_iterator p = particles_begin();
624 p != particles_end(); ++p )
625 {
626 (*p)->convert_momentum(factor);
627 }
628 // ...
629 m_momentum_unit = newunit;
630 }
631 return true;
632 }
633
634 bool GenEvent::use_length_unit( Units::LengthUnit newunit ) {
635 // currently not exception-safe.
636 // Easy to fix, though, if needed.
637 if ( m_position_unit != newunit ) {
638 const double factor = Units::conversion_factor( m_position_unit, newunit );
639 // multiply all lengths by 'factor',
640 // loop is entered only if vertex list is not empty
641 for ( GenEvent::vertex_iterator vtx = vertices_begin();
642 vtx != vertices_end(); ++vtx ) {
643 (*vtx)->convert_position(factor);
644 }
645 // ...
646 m_position_unit = newunit;
647 }
648 return true;
649 }
650
651 bool GenEvent::use_momentum_unit( std::string& newunit ) {
652 if ( newunit == "MEV" ) return use_momentum_unit( Units::MEV );
653 else if( newunit == "GEV" ) return use_momentum_unit( Units::GEV );
654 else std::cerr << "GenEvent::use_momentum_unit ERROR: use either MEV or GEV\n";
655 return false;
656 }
657
658 bool GenEvent::use_length_unit( std::string& newunit ) {
659 if ( newunit == "MM" ) return use_length_unit( Units::MM );
660 else if( newunit == "CM" ) return use_length_unit( Units::CM );
661 else std::cerr << "GenEvent::use_length_unit ERROR: use either MM or CM\n";
662 return false;
663 }
664
665 void GenEvent::define_units( std::string& new_m, std::string& new_l ) {
666
667 if ( new_m == "MEV" ) m_momentum_unit = Units::MEV ;
668 else if( new_m == "GEV" ) m_momentum_unit = Units::GEV ;
669 else std::cerr << "GenEvent::define_units ERROR: use either MEV or GEV\n";
670
671 if ( new_l == "MM" ) m_position_unit = Units::MM ;
672 else if( new_l == "CM" ) m_position_unit = Units::CM ;
673 else std::cerr << "GenEvent::define_units ERROR: use either MM or CM\n";
674
675 }
676
677 bool GenEvent::is_valid() const {
678 /// A GenEvent is presumed valid if it has both associated
679 /// particles and vertices. No other information is checked.
680 if ( vertices_empty() ) return false;
681 if ( particles_empty() ) return false;
682 return true;
683 }
684
685 std::ostream & GenEvent::write_beam_particles(std::ostream & os,
686 std::pair<HepMC::GenParticle *,HepMC::GenParticle *> pr )
687 {
688 GenParticle* p = pr.first;
689 if(!p) {
690 detail::output( os, 0 );
691 } else {
692 detail::output( os, p->barcode() );
693 }
694 p = pr.second;
695 if(!p) {
696 detail::output( os, 0 );
697 } else {
698 detail::output( os, p->barcode() );
699 }
700
701 return os;
702 }
703
704 std::ostream & GenEvent::write_vertex(std::ostream & os, GenVertex const * v)
705 {
706 if ( !v || !os ) {
707 std::cerr << "GenEvent::write_vertex !v||!os, "
708 << "v="<< v << " setting badbit" << std::endl;
709 os.clear(std::ios::badbit);
710 return os;
711 }
712 // First collect info we need
713 // count the number of orphan particles going into v
714 int num_orphans_in = 0;
715 for ( GenVertex::particles_in_const_iterator p1
716 = v->particles_in_const_begin();
717 p1 != v->particles_in_const_end(); ++p1 ) {
718 if ( !(*p1)->production_vertex() ) ++num_orphans_in;
719 }
720 //
721 os << 'V';
722 detail::output( os, v->barcode() ); // v's unique identifier
723 detail::output( os, v->id() );
724 detail::output( os, v->position().x() );
725 detail::output( os, v->position().y() );
726 detail::output( os, v->position().z() );
727 detail::output( os, v->position().t() );
728 detail::output( os, num_orphans_in );
729 detail::output( os, (int)v->particles_out_size() );
730 detail::output( os, (int)v->weights().size() );
731 for ( WeightContainer::const_iterator w = v->weights().begin();
732 w != v->weights().end(); ++w ) {
733 detail::output( os, *w );
734 }
735 detail::output( os,'\n');
736 // incoming particles
737 for ( GenVertex::particles_in_const_iterator p2
738 = v->particles_in_const_begin();
739 p2 != v->particles_in_const_end(); ++p2 ) {
740 if ( !(*p2)->production_vertex() ) {
741 write_particle( os, *p2 );
742 }
743 }
744 // outgoing particles
745 for ( GenVertex::particles_out_const_iterator p3
746 = v->particles_out_const_begin();
747 p3 != v->particles_out_const_end(); ++p3 ) {
748 write_particle( os, *p3 );
749 }
750 return os;
751 }
752
753 std::ostream & GenEvent::write_particle( std::ostream & os, GenParticle const * p )
754 {
755 if ( !p || !os ) {
756 std::cerr << "GenEvent::write_particle !p||!os, "
757 << "p="<< p << " setting badbit" << std::endl;
758 os.clear(std::ios::badbit);
759 return os;
760 }
761 os << 'P';
762 detail::output( os, p->barcode() );
763 detail::output( os, p->pdg_id() );
764 detail::output( os, p->momentum().px() );
765 detail::output( os, p->momentum().py() );
766 detail::output( os, p->momentum().pz() );
767 detail::output( os, p->momentum().e() );
768 detail::output( os, p->generated_mass() );
769 detail::output( os, p->status() );
770 detail::output( os, p->polarization().theta() );
771 detail::output( os, p->polarization().phi() );
772 // since end_vertex is oftentimes null, this CREATES a null vertex
773 // in the map
774 detail::output( os, ( p->end_vertex() ? p->end_vertex()->barcode() : 0 ) );
775 os << ' ' << p->flow() << "\n";
776
777 return os;
778 }
779
780} // HepMC