HepMC3 event record library
LHEF.h
Go to the documentation of this file.
1// -*- C++ -*-
2#ifndef HEPMC3_LHEF_H
3#define HEPMC3_LHEF_H
4
5/**
6 * @file LHEF.h
7 * @brief This is the declaration of the Les Houches Event File classes,
8 * implementing a simple C++ parser/writer for Les Houches Event files.
9 * Copyright (C) 2009-2024 Leif Lonnblad
10 *
11 * The code is licenced under LGPLv3+, see COPYING for details.
12 * Please respect the MCnet academic guidelines, see GUIDELINES for details.
13 */
14
15#include <iostream>
16#include <iomanip>
17#include <sstream>
18#include <fstream>
19#include <string>
20#include <vector>
21#include <map>
22#include <set>
23#include <utility>
24#include <stdexcept>
25#include <cstdlib>
26#include <cmath>
27#include <limits>
28#ifndef M_PI
29#define M_PI 3.14159265358979323846264338327950288
30#endif
31
32
33/**
34 * @brief Les Houches event file classes.
35 *
36 * The namespace containing helper classes and Reader and Writer
37 * classes for handling Les Houches event files.
38 *
39 * @ingroup LHEF
40 */
41namespace LHEF {
42
43/**
44 * Helper struct for output of attributes.
45 */
46template <typename T>
47struct OAttr {
48
49 /**
50 * Constructor
51 */
52 OAttr(const std::string & n, const T & v): name(n), val(v) {}
53
54 /**
55 * The name of the attribute being printed.
56 */
57 std::string name;
58
59 /**
60 * The value of the attribute being printed.
61 */
62 T val;
63
64};
65
66/**
67 * Output manipulator for writing attributes.
68 */
69template <typename T>
70OAttr<T> oattr(std::string name, const T & value) {
71 return OAttr<T>(name, value);
72}
73
74/**
75 * Output operator for attributes.
76 */
77template <typename T>
78std::ostream & operator<<(std::ostream & os, const OAttr<T> & oa) {
79 os << " " << oa.name << "=\"" << oa.val << "\"";
80 return os;
81}
82
83/**
84 * The XMLTag struct is used to represent all information within an
85 * XML tag. It contains the attributes as a map, any sub-tags as a
86 * vector of pointers to other XMLTag objects, and any other
87 * information as a single string.
88 */
89struct XMLTag {
90
91 /**
92 * Convenient typdef.
93 */
94 typedef std::string::size_type pos_t;
95
96 /**
97 * Convenient typdef.
98 */
99 typedef std::map<std::string,std::string> AttributeMap;
100
101 /**
102 * Convenient alias for npos.
103 */
104 static const pos_t end = std::string::npos;
105
106 /**
107 * Default constructor.
108 */
110
111 /**
112 * The destructor also destroys any sub-tags.
113 */
115 for ( int i = 0, N = tags.size(); i < N; ++i ) delete tags[i];
116 }
117
118 /**
119 * The name of this tag.
120 */
121 std::string name;
122
123 /**
124 * The attributes of this tag.
125 */
127
128 /**
129 * A vector of sub-tags.
130 */
131 std::vector<XMLTag*> tags;
132
133 /**
134 * The contents of this tag.
135 */
136 std::string contents;
137
138 /**
139 * Find an attribute named \a n and set the double variable \a v to
140 * the corresponding value. @return false if no attribute was found.
141 */
142 bool getattr(const std::string & n, double & v) const {
143 AttributeMap::const_iterator it = attr.find(n);
144 if ( it == attr.end() ) return false;
145 v = std::atof(it->second.c_str());
146 return true;
147 }
148
149 /**
150 * Find an attribute named \a n and set the bool variable \a v to
151 * true if the corresponding value is "yes". @return false if no
152 * attribute was found.
153 */
154 bool getattr(const std::string & n, bool & v) const {
155 AttributeMap::const_iterator it = attr.find(n);
156 if ( it == attr.end() ) return false;
157 if ( it->second == "yes" ) v = true;
158 return true;
159 }
160
161 /**
162 * Find an attribute named \a n and set the long variable \a v to
163 * the corresponding value. @return false if no attribute was found.
164 */
165 bool getattr(const std::string & n, long & v) const {
166 AttributeMap::const_iterator it = attr.find(n);
167 if ( it == attr.end() ) return false;
168 v = std::atoi(it->second.c_str());
169 return true;
170 }
171
172 /**
173 * Find an attribute named \a n and set the long variable \a v to
174 * the corresponding value. @return false if no attribute was found.
175 */
176 bool getattr(const std::string & n, int & v) const {
177 AttributeMap::const_iterator it = attr.find(n);
178 if ( it == attr.end() ) return false;
179 v = int(std::atoi(it->second.c_str()));
180 return true;
181 }
182
183 /**
184 * Find an attribute named \a n and set the string variable \a v to
185 * the corresponding value. @return false if no attribute was found.
186 */
187 bool getattr(const std::string &n, std::string & v) const {
188 AttributeMap::const_iterator it = attr.find(n);
189 if ( it == attr.end() ) return false;
190 v = it->second;
191 return true;
192 }
193
194 /**
195 * Scan the given string and return all XML tags found as a vector
196 * of pointers to XMLTag objects. Text which does not belong to any
197 * tag is stored in tags without name and in the string pointed to
198 * by leftover (if not null).
199 */
200 static std::vector<XMLTag*> findXMLTags(std::string str,
201 std::string * leftover = nullptr) {
202 std::vector<XMLTag*> tags;
203 pos_t curr = 0;
204
205 while ( curr != end ) {
206
207 // Find the first tag
208 pos_t begin = str.find("<", curr);
209
210 // Check for comments
211 if ( begin != end && str.find("<!--", curr) == begin ) {
212 pos_t endcom = str.find("-->", begin);
213 tags.push_back(new XMLTag());
214 if ( endcom == end ) {
215 tags.back()->contents = str.substr(curr);
216 if ( leftover ) *leftover += str.substr(curr);
217 return tags;
218 }
219 tags.back()->contents = str.substr(curr, endcom - curr);
220 if ( leftover ) *leftover += str.substr(curr, endcom - curr);
221 curr = endcom;
222 continue;
223 }
224
225 // Check for character data
226 if ( begin != end && str.find("<![CDATA[", curr) == begin ) {
227 pos_t endcom = str.find("]]>", begin);
228 tags.push_back(new XMLTag());
229 if ( endcom == end ) {
230 tags.back()->contents = str.substr(curr);
231 if ( leftover ) *leftover += str.substr(curr);
232 return tags;
233 }
234 tags.back()->contents = str.substr(curr, endcom - curr);
235 if ( leftover ) *leftover += str.substr(curr, endcom - curr);
236 curr = endcom;
237 continue;
238 }
239
240 if ( begin != curr ) {
241 tags.push_back(new XMLTag());
242 tags.back()->contents = str.substr(curr, begin - curr);
243 if ( leftover ) *leftover += str.substr(curr, begin - curr);
244 }
245 if ( begin == end || begin > str.length() - 3 || str[begin + 1] == '/' )
246 return tags;
247
248 pos_t close = str.find(">", curr);
249 if ( close == end ) return tags;
250
251 // find the tag name.
252 curr = str.find_first_of(" \t\n/>", begin);
253 tags.push_back(new XMLTag());
254 tags.back()->name = str.substr(begin + 1, curr - begin - 1);
255
256 while ( true ) {
257
258 // Now skip some white space to see if we can find an attribute.
259 curr = str.find_first_not_of(" \t\n", curr);
260 if ( curr == end || curr >= close ) break;
261
262 pos_t tend = str.find_first_of("= \t\n", curr);
263 if ( tend == end || tend >= close ) break;
264
265 std::string namex = str.substr(curr, tend - curr);
266 curr = str.find("=", curr) + 1;
267
268 // OK now find the beginning and end of the atribute.
269 curr = str.find_first_of("\"'", curr);
270 if ( curr == end || curr >= close ) break;
271 char quote = str[curr];
272 pos_t bega = ++curr;
273 curr = str.find(quote, curr);
274 while ( curr != end && str[curr - 1] == '\\' )
275 curr = str.find(quote, curr + 1);
276
277 std::string value = str.substr(bega, curr == end? end: curr - bega);
278
279 tags.back()->attr[namex] = value;
280
281 ++curr;
282
283 }
284
285 curr = close + 1;
286 if ( str[close - 1] == '/' ) continue;
287
288 pos_t endtag = str.find("</" + tags.back()->name + ">", curr);
289 if ( endtag == end ) {
290 tags.back()->contents = str.substr(curr);
291 curr = endtag;
292 } else {
293 tags.back()->contents = str.substr(curr, endtag - curr);
294 curr = endtag + tags.back()->name.length() + 3;
295 }
296
297 std::string leftovers;
298 tags.back()->tags = findXMLTags(tags.back()->contents, &leftovers);
299 if ( leftovers.find_first_not_of(" \t\n") == end ) leftovers="";
300 tags.back()->contents = leftovers;
301
302 }
303 return tags;
304
305 }
306
307 /**
308 * Delete all tags in a vector.
309 */
310 static void deleteAll(std::vector<XMLTag*> & tags) {
311 while ( tags.size() && tags.back() ) {
312 delete tags.back();
313 tags.pop_back();
314 }
315 }
316 /**
317 * Print out this tag to a stream.
318 */
319 void print(std::ostream & os) const {
320 if ( name.empty() ) {
321 os << contents;
322 return;
323 }
324 os << "<" << name;
325 for ( AttributeMap::const_iterator it = attr.begin();
326 it != attr.end(); ++it )
327 os << oattr(it->first, it->second);
328 if ( contents.empty() && tags.empty() ) {
329 os << "/>" << std::endl;
330 return;
331 }
332 os << ">";
333 for ( int i = 0, N = tags.size(); i < N; ++i )
334 tags[i]->print(os);
335
336 os << contents << "</" << name << ">" << std::endl;
337 }
338
339};
340
341/**
342 * Helper function to make sure that each line in the string \a s starts with a
343 * #-character and that the string ends with a new-line.
344 */
345inline std::string hashline(std::string s) {
346 std::string ret;
347 std::istringstream is(s);
348 std::string ss;
349 while ( getline(is, ss) ) {
350 if ( ss.empty() ) continue;
351 if ( ss.find_first_not_of(" \t") == std::string::npos ) continue;
352 if ( ss.find('#') == std::string::npos ||
353 ss.find('#') != ss.find_first_not_of(" \t") ) ss = "# " + ss;
354 ret += ss + '\n';
355 }
356 return ret;
357}
358
359/**
360 * This is the base class of all classes representing xml tags.
361 */
362struct TagBase {
363
364 /**
365 * Convenient typedef.
366 */
368
369 /**
370 * Default constructor does nothing.
371 */
373
374 /**
375 * Main constructor stores the attributes and contents of a tag.
376 */
377 TagBase(const AttributeMap & attr, const std::string &conts = std::string())
378 : attributes(attr), contents(conts) {}
379
380 /**
381 * Find an attribute named \a n and set the double variable \a v to
382 * the corresponding value. Remove the correspondig attribute from
383 * the list if found and \a erase is true. @return false if no
384 * attribute was found.
385 */
386 bool getattr(const std::string & n, double & v, bool erase = true) {
387 AttributeMap::iterator it = attributes.find(n);
388 if ( it == attributes.end() ) return false;
389 v = std::atof(it->second.c_str());
390 if ( erase) attributes.erase(it);
391 return true;
392 }
393
394 /**
395 * Find an attribute named \a n and set the bool variable \a v to
396 * true if the corresponding value is "yes". Remove the correspondig
397 * attribute from the list if found and \a erase is true. @return
398 * false if no attribute was found.
399 */
400 bool getattr(const std::string & n, bool & v, bool erase = true) {
401 AttributeMap::iterator it = attributes.find(n);
402 if ( it == attributes.end() ) return false;
403 if ( it->second == "yes" ) v = true;
404 if ( erase) attributes.erase(it);
405 return true;
406 }
407
408 /**
409 * Find an attribute named \a n and set the long variable \a v to
410 * the corresponding value. Remove the correspondig attribute from
411 * the list if found and \a erase is true. @return false if no
412 * attribute was found.
413 */
414 bool getattr(const std::string & n, long & v, bool erase = true) {
415 AttributeMap::iterator it = attributes.find(n);
416 if ( it == attributes.end() ) return false;
417 v = std::atoi(it->second.c_str());
418 if ( erase) attributes.erase(it);
419 return true;
420 }
421
422 /**
423 * Find an attribute named \a n and set the long variable \a v to
424 * the corresponding value. Remove the correspondig attribute from
425 * the list if found and \a erase is true. @return false if no
426 * attribute was found.
427 */
428 bool getattr(const std::string & n, int & v, bool erase = true) {
429 AttributeMap::iterator it = attributes.find(n);
430 if ( it == attributes.end() ) return false;
431 v = int(std::atoi(it->second.c_str()));
432 if ( erase) attributes.erase(it);
433 return true;
434 }
435
436 /**
437 * Find an attribute named \a n and set the string variable \a v to
438 * the corresponding value. Remove the correspondig attribute from
439 * the list if found and \a erase is true. @return false if no
440 * attribute was found.
441 */
442 bool getattr(const std::string & n, std::string & v, bool erase = true) {
443 AttributeMap::iterator it = attributes.find(n);
444 if ( it == attributes.end() ) return false;
445 v = it->second;
446 if ( erase) attributes.erase(it);
447 return true;
448 }
449
450 /**
451 * print out ' name="value"' for all unparsed attributes.
452 */
453 void printattrs(std::ostream & file) const {
454 for ( AttributeMap::const_iterator it = attributes.begin();
455 it != attributes.end(); ++ it )
456 file << oattr(it->first, it->second);
457 }
458
459 /**
460 * Print out end of tag marker. Print contents if not empty else
461 * print simple close tag.
462 */
463 void closetag(std::ostream & file, const std::string & tag) const {
464 if ( contents.empty() )
465 file << "/>\n";
466 else if ( contents.find('\n') != std::string::npos )
467 file << ">\n" << contents << "\n</" << tag << ">\n";
468 else
469 file << ">" << contents << "</" << tag << ">\n";
470 }
471
472 /**
473 * The attributes of this tag;
474 */
476
477 /**
478 * The contents of this tag.
479 */
480 mutable std::string contents;
481
482 /**
483 * Static string token for truth values.
484 */
485 static std::string yes() { return "yes"; }
486
487};
488
489/**
490 * The Generator class contains information about a generator used in a run.
491 */
492struct Generator : public TagBase {
493
494 /**
495 * Construct from XML tag.
496 */
497 Generator(const XMLTag & tag)
498 : TagBase(tag.attr, tag.contents) {
499 getattr("name", name);
500 getattr("version", version);
501 }
502
503 /**
504 * Print the object as a generator tag.
505 */
506 void print(std::ostream & file) const {
507 file << "<generator";
508 if ( !name.empty() ) file << oattr("name", name);
509 if ( !version.empty() ) file << oattr("version", version);
510 printattrs(file);
511 closetag(file, "generator");
512 }
513
514 /**
515 * The name of the generator.
516 */
517 std::string name;
518
519 /**
520 * The version of the generator.
521 */
522 std::string version;
523
524};
525
526/**
527 * The XSecInfo class contains information given in the xsecinfo tag.
528 */
529struct XSecInfo : public TagBase {
530
531 /**
532 * Intitialize default values.
533 */
534 XSecInfo(): neve(-1), ntries(-1), totxsec(0.0), xsecerr(0.0), maxweight(1.0),
535 meanweight(1.0), negweights(false), varweights(false) {}
536
537 /**
538 * Create from XML tag
539 */
540 XSecInfo(const XMLTag & tag)
541 : TagBase(tag.attr, tag.contents), neve(-1), ntries(-1),
542 totxsec(0.0), xsecerr(0.0), maxweight(1.0), meanweight(1.0),
543 negweights(false), varweights(false) {
544 if ( !getattr("neve", neve) )
545 throw std::runtime_error("Found xsecinfo tag without neve attribute "
546 "in Les Houches Event File.");
547 ntries = neve;
548 getattr("ntries", ntries);
549 if ( !getattr("totxsec", totxsec) )
550 throw std::runtime_error("Found xsecinfo tag without totxsec "
551 "attribute in Les Houches Event File.");
552 getattr("xsecerr", xsecerr);
553 getattr("weightname", weightname);
554 getattr("maxweight", maxweight);
555 getattr("meanweight", meanweight);
556 getattr("negweights", negweights);
557 getattr("varweights", varweights);
558
559 }
560
561 /**
562 * Print out an XML tag.
563 */
564 void print(std::ostream & file) const {
565 file << "<xsecinfo" << oattr("neve", neve)
566 << oattr("totxsec", totxsec);
567 if ( maxweight != 1.0 )
568 file << oattr("maxweight", maxweight)
569 << oattr("meanweight", meanweight);
570 if ( ntries > neve ) file << oattr("ntries", ntries);
571 if ( xsecerr > 0.0 ) file << oattr("xsecerr", xsecerr);
572 if ( !weightname.empty() ) file << oattr("weightname", weightname);
573 if ( negweights ) file << oattr("negweights", yes());
574 if ( varweights ) file << oattr("varweights", yes());
575 printattrs(file);
576 closetag(file, "xsecinfo");
577 }
578
579 /**
580 * The number of events.
581 */
582 long neve;
583
584 /**
585 * The number of attempte that was needed to produce the neve events.
586 */
587 long ntries;
588
589 /**
590 * The total cross section in pb.
591 */
592 double totxsec;
593
594 /**
595 * The estimated statistical error on totxsec.
596 */
597 double xsecerr;
598
599 /**
600 * The maximum weight.
601 */
602 double maxweight;
603
604 /**
605 * The average weight.
606 */
608
609 /**
610 * Does the file contain negative weights?
611 */
613
614 /**
615 * Does the file contain varying weights?
616 */
618
619 /**
620 * The named weight to which this object belongs.
621 */
622 std::string weightname;
623
624};
625
626/**
627 * Convenient Alias.
628 */
629typedef std::map<std::string,XSecInfo> XSecInfos;
630
631/**
632 * Simple struct to store information about separate eventfiles to be
633 * loaded.
634 */
635struct EventFile : public TagBase {
636
637 /**
638 * Intitialize default values.
639 */
640 EventFile(): filename(""), neve(-1), ntries(-1) {}
641
642 /**
643 * Create from XML tag
644 */
645 EventFile(const XMLTag & tag)
646 : TagBase(tag.attr, tag.contents), filename(""), neve(-1), ntries(-1) {
647 if ( !getattr("name", filename) )
648 throw std::runtime_error("Found eventfile tag without name attribute "
649 "in Les Houches Event File.");
650 getattr("neve", neve);
651 ntries = neve;
652 getattr("ntries", ntries);
653 }
654
655 /**
656 * Print out an XML tag.
657 */
658 void print(std::ostream & file) const {
659 if ( filename.empty() ) return;
660 file << " <eventfile" << oattr("name", filename);
661 if ( neve > 0 ) file << oattr("neve", neve);
662 if ( ntries > neve ) file << oattr("ntries", ntries);
663 printattrs(file);
664 closetag(file, "eventfile");
665 }
666
667 /**
668 * The name of the file.
669 */
670 std::string filename;
671
672 /**
673 * The number of events.
674 */
675 long neve;
676
677 /**
678 * The number of attempte that was needed to produce the neve events.
679 */
680 long ntries;
681
682};
683
684/**
685 * The Cut class represents a cut used by the Matrix Element generator.
686 */
687struct Cut : public TagBase {
688
689 /**
690 * Intitialize default values.
691 */
692 Cut(): min(-0.99*std::numeric_limits<double>::max()),
693 max(0.99*std::numeric_limits<double>::max()) {}
694
695 /**
696 * Create from XML tag.
697 */
698 Cut(const XMLTag & tag,
699 const std::map<std::string,std::set<long> >& ptypes)
700 : TagBase(tag.attr),
701 min(-0.99*std::numeric_limits<double>::max()),
702 max(0.99*std::numeric_limits<double>::max()) {
703 if ( !getattr("type", type) )
704 throw std::runtime_error("Found cut tag without type attribute "
705 "in Les Houches file");
706 long tmp;
707 if ( tag.getattr("p1", np1) ) {
708 if ( ptypes.find(np1) != ptypes.end() ) {
709 p1 = ptypes.find(np1)->second;
710 attributes.erase("p1");
711 } else {
712 getattr("p1", tmp);
713 p1.insert(tmp);
714 np1 = "";
715 }
716 }
717 if ( tag.getattr("p2", np2) ) {
718 if ( ptypes.find(np2) != ptypes.end() ) {
719 p2 = ptypes.find(np2)->second;
720 attributes.erase("p2");
721 } else {
722 getattr("p2", tmp);
723 p2.insert(tmp);
724 np2 = "";
725 }
726 }
727
728 std::istringstream iss(tag.contents);
729 iss >> min;
730 if ( iss >> max ) {
731 if ( min >= max )
732 min = -0.99*std::numeric_limits<double>::max();
733 } else
734 max = 0.99*std::numeric_limits<double>::max();
735 }
736
737 /**
738 * Print out an XML tag.
739 */
740 void print(std::ostream & file) const {
741 file << "<cut" << oattr("type", type);
742 if ( !np1.empty() )
743 file << oattr("p1", np1);
744 else
745 if ( p1.size() == 1 ) file << oattr("p1", *p1.begin());
746 if ( !np2.empty() )
747 file << oattr("p2", np2);
748 else
749 if ( p2.size() == 1 ) file << oattr("p2", *p2.begin());
750 printattrs(file);
751
752 file << ">";
753 if ( min > -0.9*std::numeric_limits<double>::max() )
754 file << min;
755 else
756 file << max;
757 if ( max < 0.9*std::numeric_limits<double>::max() )
758 file << " " << max;
759 if ( !contents.empty() ) file << std::endl << contents << std::endl;
760 file << "</cut>" << std::endl;
761 }
762
763 /**
764 * Check if a \a id1 matches p1 and \a id2 matches p2. Only non-zero
765 * values are considered.
766 */
767 bool match(long id1, long id2 = 0) const {
768 std::pair<bool,bool> ret(false, false);
769 if ( !id2 ) ret.second = true;
770 if ( !id1 ) ret.first = true;
771 if ( p1.find(0) != p1.end() ) ret.first = true;
772 if ( p1.find(id1) != p1.end() ) ret.first = true;
773 if ( p2.find(0) != p2.end() ) ret.second = true;
774 if ( p2.find(id2) != p2.end() ) ret.second = true;
775 return ret.first && ret.second;
776 }
777
778 /**
779 * Check if the particles given as a vector of PDG \a id numbers,
780 * and a vector of vectors of momentum components, \a p, will pass
781 * the cut defined in this event.
782 */
783 bool passCuts(const std::vector<long> & id,
784 const std::vector< std::vector<double> >& p ) const {
785 if ( ( type == "m" && !p2.size() ) || type == "kt" || type == "eta" ||
786 type == "y" || type == "E" ) {
787 for ( int i = 0, N = id.size(); i < N; ++i )
788 if ( match(id[i]) ) {
789 if ( type == "m" ) {
790 double v = p[i][4]*p[i][4] - p[i][3]*p[i][3] - p[i][2]*p[i][2]
791 - p[i][1]*p[i][1];
792 v = v >= 0.0? std::sqrt(v): -std::sqrt(-v);
793 if ( outside(v) ) return false;
794 }
795 else if ( type == "kt" ) {
796 if ( outside(std::sqrt(p[i][2]*p[i][2] + p[i][1]*p[i][1])) )
797 return false;
798 }
799 else if ( type == "E" ) {
800 if ( outside(p[i][4]) ) return false;
801 }
802 else if ( type == "eta" ) {
803 if ( outside(eta(p[i])) ) return false;
804 }
805 else if ( type == "y" ) {
806 if ( outside(rap(p[i])) ) return false;
807 }
808 }
809 }
810 else if ( type == "m" || type == "deltaR" ) {
811 for ( int i = 1, N = id.size(); i < N; ++i )
812 for ( int j = 0; j < i; ++j )
813 if ( match(id[i], id[j]) || match(id[j], id[i]) ) {
814 if ( type == "m" ) {
815 double v = (p[i][4] + p[j][4])*(p[i][4] + p[j][4])
816 - (p[i][3] + p[j][3])*(p[i][3] + p[j][3])
817 - (p[i][2] + p[j][2])*(p[i][2] + p[j][2])
818 - (p[i][1] + p[j][1])*(p[i][1] + p[j][1]);
819 v = v >= 0.0? std::sqrt(v): -std::sqrt(-v);
820 if ( outside(v) ) return false;
821 }
822 else if ( type == "deltaR" ) {
823 if ( outside(deltaR(p[i], p[j])) ) return false;
824 }
825 }
826 }
827 else if ( type == "ETmiss" ) {
828 double x = 0.0;
829 double y = 0.0;
830 for ( int i = 0, N = id.size(); i < N; ++i )
831 if ( match(id[i]) && !match(0, id[i]) ) {
832 x += p[i][1];
833 y += p[i][2];
834 }
835 if ( outside(std::sqrt(x*x + y*y)) ) return false;
836 }
837 else if ( type == "HT" ) {
838 double pt = 0.0;
839 for ( int i = 0, N = id.size(); i < N; ++i )
840 if ( match(id[i]) && !match(0, id[i]) )
841 pt += std::sqrt(p[i][1]*p[i][1] + p[i][2]*p[i][2]);
842 if ( outside(pt) ) return false;
843 }
844 return true;
845 }
846
847 /**
848 * Return the pseudorapidity of a particle with momentum \a p.
849 */
850 static double eta(const std::vector<double> & p) {
851 double pt2 = p[2]*p[2] + p[1]*p[1];
852 if ( pt2 != 0.0 ) {
853 double dum = std::sqrt(pt2 + p[3]*p[3]) + p[3];
854 if ( dum != 0.0 )
855 return std::log(dum/std::sqrt(pt2));
856 }
857 return p[3] < 0.0? -std::numeric_limits<double>::max():
858 std::numeric_limits<double>::max();
859 }
860
861 /**
862 * Return the true rapidity of a particle with momentum \a p.
863 */
864 static double rap(const std::vector<double> & p) {
865 double pt2 = p[5]*p[5] + p[2]*p[2] + p[1]*p[1];
866 if ( pt2 != 0.0 ) {
867 double dum = std::sqrt(pt2 + p[3]*p[3]) + p[3];
868 if ( dum != 0.0 )
869 return std::log(dum/std::sqrt(pt2));
870 }
871 return p[3] < 0.0? -std::numeric_limits<double>::max():
872 std::numeric_limits<double>::max();
873 }
874
875 /**
876 * Return the delta-R of a particle pair with momenta \a p1 and \a p2.
877 */
878 static double deltaR(const std::vector<double> & p1,
879 const std::vector<double> & p2) {
880 double deta = eta(p1) - eta(p2);
881 double dphi = std::atan2(p1[1], p1[2]) - std::atan2(p2[1], p2[2]);
882 if ( dphi > M_PI ) dphi -= 2.0*M_PI;
883 if ( dphi < -M_PI ) dphi += 2.0*M_PI;
884 return std::sqrt(dphi*dphi + deta*deta);
885 }
886
887 /**
888 * Return true if the given \a value is outside limits.
889 */
890 bool outside(double value) const {
891 return value < min || value >= max;
892 }
893
894 /**
895 * The variable in which to cut.
896 */
897 std::string type;
898
899 /**
900 * The first types particle types for which this cut applies.
901 */
902 std::set<long> p1;
903
904 /**
905 * Symbolic name for p1.
906 */
907 std::string np1;
908
909 /**
910 * The second type of particles for which this cut applies.
911 */
912 std::set<long> p2;
913
914 /**
915 * Symbolic name for p1.
916 */
917 std::string np2;
918
919 /**
920 * The minimum value of the variable
921 */
922 double min;
923 /**
924 * The maximum value of the variable
925 */
926 double max;
927
928};
929
930/**
931 * The ProcInfo class represents the information in a procinfo tag.
932 */
933struct ProcInfo : public TagBase {
934
935 /**
936 * Intitialize default values.
937 */
938 ProcInfo(): iproc(0), loops(0), qcdorder(-1), eworder(-1) {}
939
940 /**
941 * Create from XML tag.
942 */
943 ProcInfo(const XMLTag & tag)
944 : TagBase(tag.attr, tag.contents),
945 iproc(0), loops(0), qcdorder(-1), eworder(-1) {
946 getattr("iproc", iproc);
947 getattr("loops", loops);
948 getattr("qcdorder", qcdorder);
949 getattr("eworder", eworder);
950 getattr("rscheme", rscheme);
951 getattr("fscheme", fscheme);
952 getattr("scheme", scheme);
953 }
954
955 /**
956 * Print out an XML tag.
957 */
958 void print(std::ostream & file) const {
959 file << "<procinfo" << oattr("iproc", iproc);
960 if ( loops >= 0 ) file << oattr("loops", loops);
961 if ( qcdorder >= 0 ) file << oattr("qcdorder", qcdorder);
962 if ( eworder >= 0 ) file<< oattr("eworder", eworder);
963 if ( !rscheme.empty() ) file << oattr("rscheme", rscheme);
964 if ( !fscheme.empty() ) file << oattr("fscheme", fscheme);
965 if ( !scheme.empty() ) file << oattr("scheme", scheme);
966 printattrs(file);
967 closetag(file, "procinfo");
968 }
969
970 /**
971 * The id number for the process.
972 */
973 int iproc;
974
975 /**
976 * The number of loops
977 */
978 int loops;
979
980 /**
981 * The number of QCD vertices.
982 */
984
985 /**
986 * The number of electro-weak vertices.
987 */
989
990 /**
991 * The factorization scheme used.
992 */
993 std::string fscheme;
994
995 /**
996 * The renormalization scheme used.
997 */
998 std::string rscheme;
999
1000 /**
1001 * The NLO scheme used.
1002 */
1003 std::string scheme;
1004
1005};
1006
1007/**
1008 * The MergeInfo class represents the information in a mergeinfo tag.
1009 */
1010struct MergeInfo : public TagBase {
1011
1012 /**
1013 * Intitialize default values.
1014 */
1015 MergeInfo(): iproc(0), mergingscale(0.0), maxmult(false) {}
1016
1017 /**
1018 * Create from XML tag.
1019 */
1020 MergeInfo(const XMLTag & tag)
1021 : TagBase(tag.attr, tag.contents),
1022 iproc(0), mergingscale(0.0), maxmult(false) {
1023 getattr("iproc", iproc);
1024 getattr("mergingscale", mergingscale);
1025 getattr("maxmult", maxmult);
1026 }
1027
1028 /**
1029 * Print out an XML tag.
1030 */
1031 void print(std::ostream & file) const {
1032 file << "<mergeinfo" << oattr("iproc", iproc);
1033 if ( mergingscale > 0.0 ) file << oattr("mergingscale", mergingscale);
1034 if ( maxmult ) file << oattr("maxmult", yes());
1035 printattrs(file);
1036 closetag(file, "mergeinfo");
1037 }
1038
1039 /**
1040 * The id number for the process.
1041 */
1043
1044 /**
1045 * The merging scale used if different from the cut definitions.
1046 */
1048
1049 /**
1050 * Is this event reweighted as if it was the maximum multiplicity.
1051 */
1053
1054};
1055
1056/**
1057 * The WeightInfo class encodes the description of a given weight
1058 * present for all events.
1059 */
1060struct WeightInfo : public TagBase {
1061
1062 /**
1063 * Constructors
1064 */
1065 WeightInfo(): inGroup(-1), isrwgt(false),
1066 muf(1.0), mur(1.0), pdf(0), pdf2(0) {}
1067
1068 /**
1069 * Construct from the XML tag
1070 */
1071 WeightInfo(const XMLTag & tag)
1072 : TagBase(tag.attr, tag.contents),
1073 inGroup(-1), isrwgt(tag.name == "weight"),
1074 muf(1.0), mur(1.0), pdf(0), pdf2(0) {
1075 getattr("mur", mur);
1076 getattr("muf", muf);
1077 getattr("pdf", pdf);
1078 getattr("pdf2", pdf2);
1079 if ( isrwgt )
1080 getattr("id", name);
1081 else
1082 getattr("name", name);
1083 }
1084
1085 /**
1086 * Print out an XML tag.
1087 */
1088 void print(std::ostream & file) const {
1089
1090 if ( isrwgt )
1091 file << "<weight" << oattr("id", name);
1092 else
1093 file << "<weightinfo" << oattr("name", name);
1094 if ( mur != 1.0 ) file << oattr("mur", mur);
1095 if ( muf != 1.0 ) file << oattr("muf", muf);
1096 if ( pdf != 0 ) file << oattr("pdf", pdf);
1097 if ( pdf2 != 0 ) file << oattr("pdf2", pdf2);
1098 printattrs(file);
1099 if ( isrwgt )
1100 closetag(file, "weight");
1101 else
1102 closetag(file, "weightinfo");
1103 }
1104
1105 /**
1106 * If inside a group, this is the index of that group.
1107 */
1109
1110 /**
1111 * Is this a weightinfo or an rwgt tag?
1112 */
1114
1115 /**
1116 * The name.
1117 */
1118 std::string name;
1119
1120 /**
1121 * Factor multiplying the nominal factorization scale for this weight.
1122 */
1123 double muf;
1124
1125 /**
1126 * Factor multiplying the nominal renormalization scale for this weight.
1127 */
1128 double mur;
1129
1130 /**
1131 * The LHAPDF set relevant for this weight
1132 */
1133 long pdf;
1134
1135 /**
1136 * The LHAPDF set for the second beam relevant for this weight if
1137 * different from pdf.
1138 */
1139 long pdf2;
1140
1141};
1142
1143/**
1144 * The WeightGroup assigns a group-name to a set of WeightInfo objects.
1145 */
1146struct WeightGroup : public TagBase {
1147
1148 /**
1149 * Default constructor;
1150 */
1152
1153 /**
1154 * Construct a group of WeightInfo objects from an XML tag and
1155 * insert them in the given vector.
1156 */
1157 WeightGroup(const XMLTag & tag, int groupIndex, std::vector<WeightInfo> & wiv)
1158 : TagBase(tag.attr) {
1159 getattr("type", type);
1160 getattr("combine", combine);
1161 for ( int i = 0, N = tag.tags.size(); i < N; ++i ) {
1162 if ( tag.tags[i]->name == "weight" ||
1163 tag.tags[i]->name == "weightinfo" ) {
1164 WeightInfo wi(*tag.tags[i]);
1165 wi.inGroup = groupIndex;
1166 wiv.push_back(wi);
1167 }
1168 }
1169 }
1170
1171 /**
1172 * The type.
1173 */
1174 std::string type;
1175
1176 /**
1177 * The way in which these weights should be combined.
1178 */
1179 std::string combine;
1180
1181};
1182
1183
1184/**
1185 * The Weight class represents the information in a weight tag.
1186 */
1187struct Weight : public TagBase {
1188
1189 /**
1190 * Initialize default values.
1191 */
1192 Weight(): iswgt(false), born(0.0), sudakov(0.0) {}
1193
1194 /**
1195 * Create from XML tag
1196 */
1197 Weight(const XMLTag & tag)
1198 : TagBase(tag.attr, tag.contents),
1199 iswgt(tag.name == "wgt"), born(0.0), sudakov(0.0) {
1200 if ( iswgt )
1201 getattr("id", name);
1202 else
1203 getattr("name", name);
1204 getattr("born", born);
1205 getattr("sudakov", sudakov);
1206 std::istringstream iss(tag.contents);
1207 double w;
1208 while ( iss >> w ) weights.push_back(w);
1209 indices.resize(weights.size(), 0.0);
1210 }
1211
1212 /**
1213 * Print out an XML tag.
1214 */
1215 void print(std::ostream & file) const {
1216 if ( iswgt )
1217 file << "<wgt" << oattr("id", name);
1218 else {
1219 file << "<weight";
1220 if ( !name.empty() ) file << oattr("name", name);
1221 }
1222 if ( born != 0.0 ) file << oattr("born", born);
1223 if ( sudakov != 0.0 ) file << oattr("sudakov", sudakov);
1224 file << ">";
1225 for ( int j = 0, M = weights.size(); j < M; ++j ) file << " " << weights[j];
1226 if ( iswgt )
1227 file << "</wgt>" << std::endl;
1228 else
1229 file << "</weight>" << std::endl;
1230 }
1231
1232 /**
1233 * The identifyer for this set of weights.
1234 */
1235 std::string name;
1236
1237 /**
1238 * Is this a wgt or a weight tag
1239 */
1240 bool iswgt;
1241
1242 /**
1243 * The relative size of the born cross section of this event.
1244 */
1245 double born;
1246
1247 /**
1248 * The relative size of the sudakov applied to this event.
1249 */
1250 double sudakov;
1251
1252 /**
1253 * The weights of this event.
1254 */
1255 mutable std::vector<double> weights;
1256
1257 /**
1258 * The indices where the weights are stored.
1259 */
1260 std::vector<int> indices;
1261
1262};
1263
1264/**
1265 * The Clus class represents a clustering of two particle entries into
1266 * one as defined in a clustering tag.
1267 */
1268struct Clus : public TagBase {
1269
1270 /**
1271 * Initialize default values.
1272 */
1273 Clus(): p1(0), p2(0), p0(0), scale(-1.0), alphas(-1.0) {}
1274
1275 /**
1276 * Initialize default values.
1277 */
1278 Clus(const XMLTag & tag)
1279 : TagBase(tag.attr, tag.contents), scale(-1.0), alphas(-1.0) {
1280 getattr("scale", scale);
1281 getattr("alphas", alphas);
1282 std::istringstream iss(tag.contents);
1283 iss >> p1 >> p2;
1284 if ( !( iss >> p0 ) ) p0 = p1;
1285 }
1286
1287 /**
1288 * Print out an XML tag.
1289 */
1290 void print(std::ostream & file) const {
1291 file << "<clus";
1292 if ( scale > 0.0 ) file << oattr("scale", scale);
1293 if ( alphas > 0.0 ) file << oattr("alphas", alphas);
1294 file << ">" << p1 << " " << p2;
1295 if ( p1 != p0 ) file << " " << p0;
1296 file << "</clus>" << std::endl;
1297 }
1298
1299 /**
1300 * The first particle entry that has been clustered.
1301 */
1302 int p1;
1303
1304 /**
1305 * The second particle entry that has been clustered.
1306 */
1307 int p2;
1308
1309 /**
1310 * The particle entry corresponding to the clustered particles.
1311 */
1312 int p0;
1313
1314 /**
1315 * The scale in GeV associated with the clustering.
1316 */
1317 double scale;
1318
1319 /**
1320 * The alpha_s used in the corresponding vertex, if this was used in
1321 * the cross section.
1322 */
1323 double alphas;
1324
1325};
1326
1327/**
1328 * Store special scales from within a scales tag.
1329 */
1330
1331struct Scale : public TagBase {
1332
1333 /**
1334 * Empty constructor
1335 */
1336 Scale(std::string st = "veto", int emtr = 0, double sc = 0.0)
1337 : stype(st), emitter(emtr), scale(sc) {}
1338
1339 /**
1340 * Construct from an XML-tag.
1341 */
1342 Scale(const XMLTag & tag)
1343 : TagBase(tag.attr, tag.contents),stype("veto"), emitter(0) {
1344 if ( !getattr("stype", stype) )
1345 throw std::runtime_error("Found scale tag without stype attribute "
1346 "in Les Houches Event File.");
1347 std::string pattr;
1348 if ( getattr("pos", pattr) ) {
1349 std::istringstream pis(pattr);
1350 if ( !(pis >> emitter) ) emitter = 0;
1351 else {
1352 int rec = 0;
1353 while ( pis >> rec ) recoilers.insert(rec);
1354 }
1355 }
1356
1357 std::string eattr;
1358 if ( getattr("etype", eattr) ) {
1359 if ( eattr == "QCD" ) eattr = "-5 -4 -3 -2 -1 1 2 3 4 5 21";
1360 if ( eattr == "EW" ) eattr = "-13 -12 -11 11 12 13 22 23 24";
1361 std::istringstream eis(eattr);
1362 int pdg = 0;
1363 while ( eis >> pdg ) emitted.insert(pdg);
1364 }
1365 std::istringstream cis(tag.contents);
1366 cis >> scale;
1367
1368 }
1369
1370 /**
1371 * Print out an XML tag.
1372 */
1373 void print(std::ostream & file) const {
1374 file << "<scale" << oattr("stype", stype);
1375 if ( emitter > 0 ) {
1376 std::ostringstream pos;
1377 pos << emitter;
1378 for ( std::set<int>::iterator it = recoilers.begin();
1379 it != recoilers.end(); ++it )
1380 pos << " " << *it;
1381 file << oattr("pos", pos.str());
1382 }
1383 if ( emitted.size() > 0 ) {
1384 std::set<int>::iterator it = emitted.begin();
1385 std::ostringstream eos;
1386 eos << *it;
1387 while ( ++it != emitted.end() ) eos << " " << *it;
1388 if ( eos.str() == "-5 -4 -3 -2 -1 1 2 3 4 5 21" )
1389 file << oattr("etype", std::string("QCD"));
1390 else if ( eos.str() == "-13 -12 -11 11 12 13 22 23 24" )
1391 file << oattr("etype", std::string("EW"));
1392 else
1393 file << oattr("etype", eos.str());
1394 }
1395 std::ostringstream os;
1396 os << scale;
1397 contents = os.str();
1398 closetag(file, "scale");
1399 }
1400
1401 /**
1402 * The type of scale this represents. Predefined values are "veto"
1403 * and "start".
1404 */
1405 std::string stype;
1406
1407 /**
1408 * The emitter this scale applies to. This is the index of a
1409 * particle in HEPEUP (starting at 1). Zero corresponds to any
1410 * particle in HEPEUP.
1411 */
1413
1414 /**
1415 * The set of recoilers for which this scale applies.
1416 */
1417 std::set<int> recoilers;
1418
1419 /**
1420 * The set of emitted particles (PDG id) this applies to.
1421 */
1422 std::set<int> emitted;
1423
1424 /**
1425 * The actual scale given.
1426 */
1427 double scale;
1428
1429};
1430
1431/**
1432 * Collect different scales relevant for an event.
1433 */
1434struct Scales : public TagBase {
1435
1436 /**
1437 * Empty constructor.
1438 */
1439 Scales(double defscale = -1.0, int npart = 0)
1440 : muf(defscale), mur(defscale), mups(defscale), SCALUP(defscale) {
1441 (void) npart; // avoid "unused variable" compiler warning
1442 }
1443
1444 /**
1445 * Construct from an XML-tag
1446 */
1447 Scales(const XMLTag & tag, double defscale = -1.0, int npart = 0)
1448 : TagBase(tag.attr, tag.contents),
1449 muf(defscale), mur(defscale), mups(defscale),
1450 SCALUP(defscale) {
1451 getattr("muf", muf);
1452 getattr("mur", mur);
1453 getattr("mups", mups);
1454 for ( int i = 0, N = tag.tags.size(); i < N; ++i )
1455 if ( tag.tags[i]->name == "scale" )
1456 scales.push_back(Scale(*tag.tags[i]));
1457 for ( int i = 0; i < npart; ++i ) {
1458 std::ostringstream pttag;
1459 pttag << "pt_start_" << i + 1;
1460 double sc = 0.0;
1461 if ( getattr(pttag.str(), sc) )
1462 scales.push_back(Scale("start", i + 1, sc));
1463 }
1464
1465 }
1466
1467 /**
1468 * Check if this object contains useful information besides SCALUP.
1469 */
1470 bool hasInfo() const {
1471 return muf != SCALUP || mur != SCALUP || mups != SCALUP ||
1472 !scales.empty();
1473 }
1474
1475 /**
1476 * Print out the corresponding XML-tag.
1477 */
1478 void print(std::ostream & file) const {
1479 if ( !hasInfo() ) return;
1480 file << "<scales";
1481 if ( muf != SCALUP ) file << oattr("muf", muf);
1482 if ( mur != SCALUP ) file << oattr("mur", mur);
1483 if ( mups != SCALUP ) file << oattr("mups", mups);
1484 printattrs(file);
1485
1486 if ( !scales.empty() ) {
1487 std::ostringstream os;
1488 for ( int i = 0, N = scales.size(); i < N; ++i )
1489 scales[i].print(os);
1490 contents = os.str();
1491 }
1492 closetag(file, "scales");
1493 }
1494
1495 /**
1496 * Return the scale of type st for a given emission of particle type
1497 * pdgem from the emitter with number emr and a recoiler rec. (Note
1498 * that the indices for emr and rec starts at 1 and 0 is interpreted
1499 * as any particle.) First it will check for Scale object with an
1500 * exact match. If not found, it will search for an exact match for
1501 * the emitter and recoiler with an undefined emitted particle. If
1502 * not found, it will look for a match for only emitter and emitted,
1503 * of if not found, a match for only the emitter. Finally a general
1504 * Scale object will be used, or if nothing matches, the mups will
1505 * be returned.
1506 */
1507 double getScale(std::string st, int pdgem, int emr, int rec) const {
1508 for ( int i = 0, N = scales.size(); i < N; ++i ) {
1509 if ( scales[i].emitter == emr && st == scales[i].stype &&
1510 ( emr == rec ||
1511 scales[i].recoilers.find(rec) != scales[i].recoilers.end() ) &&
1512 scales[i].emitted.find(pdgem) != scales[i].emitted.end() )
1513 return scales[i].scale;
1514 }
1515 for ( int i = 0, N = scales.size(); i < N; ++i ) {
1516 if ( scales[i].emitter == emr && st == scales[i].stype &&
1517 ( emr == rec ||
1518 scales[i].recoilers.find(rec) != scales[i].recoilers.end() ) &&
1519 scales[i].emitted.empty() )
1520 return scales[i].scale;
1521 }
1522 if ( emr != rec ) return getScale(st, pdgem, emr, emr);
1523 if ( emr == rec ) return getScale(st, pdgem, 0, 0);
1524 return mups;
1525 }
1526
1527 /**
1528 * The factorization scale used for this event.
1529 */
1530 double muf;
1531
1532 /**
1533 * The renormalization scale used for this event.
1534 */
1535 double mur;
1536
1537 /**
1538 * The starting scale for the parton shower as suggested by the
1539 * matrix element generator.
1540 */
1541 double mups;
1542
1543 /**
1544 * The default scale in this event.
1545 */
1546 double SCALUP;
1547
1548 /**
1549 * The list of special scales.
1550 */
1551 std::vector<Scale> scales;
1552
1553};
1554
1555/**
1556 * The PDFInfo class represents the information in a pdfinto tag.
1557 */
1558struct PDFInfo : public TagBase {
1559
1560 /**
1561 * Initialize default values.
1562 */
1563 PDFInfo(double defscale = -1.0)
1564 : p1(0), p2(0), x1(-1.0), x2(-1.0), xf1(-1.0), xf2(-1.0),
1565 scale(defscale), SCALUP(defscale) {}
1566
1567 /**
1568 * Create from XML tag.
1569 */
1570 PDFInfo(const XMLTag & tag, double defscale = -1.0)
1571 : TagBase(tag.attr, tag.contents),
1572 p1(0), p2(0), x1(-1.0), x2(-1.0), xf1(-1.0), xf2(-1.0),
1573 scale(defscale), SCALUP(defscale) {
1574 getattr("scale", scale);
1575 getattr("p1", p1);
1576 getattr("p2", p2);
1577 getattr("x1", x1);
1578 getattr("x2", x2);
1579 }
1580
1581 /**
1582 * Print out an XML tag.
1583 */
1584 void print(std::ostream & file) const {
1585 if ( xf1 <= 0 ) return;
1586 file << "<pdfinfo";
1587 if ( p1 != 0 ) file << oattr("p1", p1);
1588 if ( p2 != 0 ) file << oattr("p2", p2);
1589 if ( x1 > 0 ) file << oattr("x1", x1);
1590 if ( x2 > 0 ) file << oattr("x2", x2);
1591 if ( scale != SCALUP ) file << oattr("scale", scale);
1592 printattrs(file);
1593 file << ">" << xf1 << " " << xf2 << "</pdfinfo>" << std::endl;
1594 }
1595
1596 /**
1597 * The type of the incoming particle 1.
1598 */
1599 long p1;
1600
1601 /**
1602 * The type of the incoming particle 2.
1603 */
1604 long p2;
1605
1606 /**
1607 * The x-value used for the incoming particle 1.
1608 */
1609 double x1;
1610
1611 /**
1612 * The x-value used for the incoming particle 2.
1613 */
1614 double x2;
1615
1616 /**
1617 * The value of the pdf for the incoming particle 1.
1618 */
1619 double xf1;
1620
1621 /**
1622 * The value of the pdf for the incoming particle 2.
1623 */
1624 double xf2;
1625
1626 /**
1627 * The scale used in the PDF:s
1628 */
1629 double scale;
1630
1631 /**
1632 * THe default scale in the event.
1633 */
1634 double SCALUP;
1635
1636};
1637
1638/**
1639 * The HEPRUP class is a simple container corresponding to the Les Houches
1640 * accord (<A HREF="http://arxiv.org/abs/hep-ph/0109068">hep-ph/0109068</A>)
1641 * common block with the same name. The members are named in the same
1642 * way as in the common block. However, fortran arrays are represented
1643 * by vectors, except for the arrays of length two which are
1644 * represented by pair objects.
1645 */
1646class HEPRUP : public TagBase {
1647
1648public:
1649
1650 /** @name Standard constructors and destructors. */
1651 /// @{
1652 /**
1653 * Default constructor.
1654 */
1656 : IDWTUP(0), NPRUP(0), version(3),
1657 dprec(std::numeric_limits<double>::digits10) {}
1658
1659 /**
1660 * Copy constructor
1661 */
1662 HEPRUP(const HEPRUP &) = default;
1663
1664 /**
1665 * Assignment operator.
1666 */
1667 HEPRUP & operator=(const HEPRUP & /*x*/) = default;
1668
1669 /**
1670 * Construct from a given init tag.
1671 */
1672 HEPRUP(const XMLTag & tagin, int versin)
1673 : TagBase(tagin.attr, tagin.contents), version(versin),
1674 dprec(std::numeric_limits<double>::digits10) {
1675
1676 std::vector<XMLTag*> tags = tagin.tags;
1677
1678 // The first (anonymous) tag should just be the init block.
1679 std::istringstream iss(tags[0]->contents);
1680 if ( !( iss >> IDBMUP.first >> IDBMUP.second >> EBMUP.first >> EBMUP.second
1681 >> PDFGUP.first >> PDFGUP.second >> PDFSUP.first >> PDFSUP.second
1682 >> IDWTUP >> NPRUP ) ) {
1683 throw std::runtime_error("Could not parse init block "
1684 "in Les Houches Event File.");
1685 }
1686 resize();
1687
1688 for ( int i = 0; i < NPRUP; ++i ) {
1689 if ( !( iss >> XSECUP[i] >> XERRUP[i] >> XMAXUP[i] >> LPRUP[i] ) ) {
1690 throw std::runtime_error("Could not parse processes in init block "
1691 "in Les Houches Event File.");
1692 }
1693 }
1694
1695 for ( int i = 1, N = tags.size(); i < N; ++i ) {
1696 const XMLTag & tag = *tags[i];
1697
1698 if ( tag.name.empty() ) junk += tag.contents;
1699
1700 if ( tag.name == "initrwgt" ) {
1701 for ( int j = 0, M = tag.tags.size(); j < M; ++j ) {
1702 if ( tag.tags[j]->name == "weightgroup" )
1703 weightgroup.push_back(WeightGroup(*tag.tags[j], weightgroup.size(),
1704 weightinfo));
1705 if ( tag.tags[j]->name == "weight" )
1706 weightinfo.push_back(WeightInfo(*tag.tags[j]));
1707
1708 }
1709 }
1710 if ( tag.name == "weightinfo" ) {
1711 weightinfo.push_back(WeightInfo(tag));
1712 }
1713 if ( tag.name == "weightgroup" ) {
1714 weightgroup.push_back(WeightGroup(tag, weightgroup.size(),
1715 weightinfo));
1716 }
1717 if ( tag.name == "eventfiles" ) {
1718 for ( int j = 0, M = tag.tags.size(); j < M; ++j ) {
1719 XMLTag & eftag = *tag.tags[j];
1720 if ( eftag.name == "eventfile" )
1721 eventfiles.push_back(EventFile(eftag));
1722 }
1723 }
1724 if ( tag.name == "xsecinfo" ) {
1725 XSecInfo xsecinfo(tag);
1726 xsecinfos[xsecinfo.weightname] = xsecinfo;
1727 }
1728 if ( tag.name == "generator" ) {
1729 generators.push_back(Generator(tag));
1730 }
1731 else if ( tag.name == "cutsinfo" ) {
1732 for ( int j = 0, M = tag.tags.size(); j < M; ++j ) {
1733 XMLTag & ctag = *tag.tags[j];
1734
1735 if ( ctag.name == "ptype" ) {
1736 std::string tname = ctag.attr["name"];
1737 long id;
1738 std::istringstream isss(ctag.contents);
1739 while ( isss >> id ) ptypes[tname].insert(id);
1740 }
1741 else if ( ctag.name == "cut" )
1742 cuts.push_back(Cut(ctag, ptypes));
1743 }
1744 }
1745 else if ( tag.name == "procinfo" ) {
1746 ProcInfo proc(tag);
1747 procinfo[proc.iproc] = proc;
1748 }
1749 else if ( tag.name == "mergeinfo" ) {
1750 MergeInfo merge(tag);
1751 mergeinfo[merge.iproc] = merge;
1752 }
1753
1754 }
1755
1756 weightmap.clear();
1757 for ( int i = 0, N = weightinfo.size(); i < N; ++i )
1758 weightmap[weightinfo[i].name] = i + 1;
1759
1760 }
1761
1762 /// @}
1763
1764public:
1765
1766 /**
1767 * Return the name of the weight with given index suitable to ne
1768 * used for HepMC3 output.
1769 */
1770 std::string weightNameHepMC(int i) const {
1771 std::string name;
1772 if ( i < 0 || i >= static_cast<int>(weightinfo.size()) ) return name;
1773 if ( weightinfo[i].inGroup >= 0 )
1774 name = weightgroup[weightinfo[i].inGroup].type + "/"
1775 + weightgroup[weightinfo[i].inGroup].combine + "/";
1776 name += weightinfo[i].name;
1777 return name;
1778 }
1779
1780
1781 /**
1782 * Print out the corresponding XML tag to a stream.
1783 */
1784 void print(std::ostream & file) const {
1785
1786 file << std::setprecision(dprec);
1787
1788 file << "<init>\n"
1789 << " " << std::setw(8) << IDBMUP.first
1790 << " " << std::setw(8) << IDBMUP.second
1791 << " " << std::setw(14) << EBMUP.first
1792 << " " << std::setw(14) << EBMUP.second
1793 << " " << std::setw(4) << PDFGUP.first
1794 << " " << std::setw(4) << PDFGUP.second
1795 << " " << std::setw(4) << PDFSUP.first
1796 << " " << std::setw(4) << PDFSUP.second
1797 << " " << std::setw(4) << IDWTUP
1798 << " " << std::setw(4) << NPRUP << std::endl;
1799
1800 for ( int i = 0; i < NPRUP; ++i )
1801 file << " " << std::setw(14) << XSECUP[i]
1802 << " " << std::setw(14) << XERRUP[i]
1803 << " " << std::setw(14) << XMAXUP[i]
1804 << " " << std::setw(6) << LPRUP[i] << std::endl;
1805
1806 for ( int i = 0, N = generators.size(); i < N; ++i )
1807 generators[i].print(file);
1808
1809 if ( !eventfiles.empty() ) {
1810 file << "<eventfiles>\n";
1811 for ( int i = 0, N = eventfiles.size(); i < N; ++i )
1812 eventfiles[i].print(file);
1813 file << "</eventfiles>\n";
1814 }
1815 //AV if ( !xsecinfos.empty() > 0 )
1816 if ( !xsecinfos.empty())
1817 for ( XSecInfos::const_iterator it = xsecinfos.begin();
1818 it != xsecinfos.end(); ++it )
1819 if ( it->second.neve > 0 ) it->second.print(file);
1820
1821 if ( cuts.size() > 0 ) {
1822 file << "<cutsinfo>" << std::endl;
1823
1824 for ( std::map<std::string, std::set<long> >::const_iterator ptit =
1825 ptypes.begin(); ptit != ptypes.end(); ++ptit ) {
1826 file << "<ptype" << oattr("name", ptit->first) << ">";
1827 for ( std::set<long>::const_iterator it = ptit->second.begin();
1828 it != ptit->second.end(); ++it )
1829 file << " " << *it;
1830 file << "</ptype>" << std::endl;
1831 }
1832
1833 for ( int i = 0, N = cuts.size(); i < N; ++i )
1834 cuts[i].print(file);
1835 file << "</cutsinfo>" << std::endl;
1836 }
1837
1838 for ( std::map<long,ProcInfo>::const_iterator it = procinfo.begin();
1839 it != procinfo.end(); ++it )
1840 it->second.print(file);
1841
1842 for ( std::map<long,MergeInfo>::const_iterator it = mergeinfo.begin();
1843 it != mergeinfo.end(); ++it )
1844 it->second.print(file);
1845
1846 bool isrwgt = false;
1847 int ingroup = -1;
1848 for ( int i = 0, N = weightinfo.size(); i < N; ++i ) {
1849 if ( weightinfo[i].isrwgt ) {
1850 if ( !isrwgt ) file << "<initrwgt>\n";
1851 isrwgt = true;
1852 } else {
1853 if ( isrwgt ) file << "</initrwgt>\n";
1854 isrwgt = false;
1855 }
1856 int group = weightinfo[i].inGroup;
1857 if ( group != ingroup ) {
1858 if ( ingroup != -1 ) file << "</weightgroup>\n";
1859 if ( group != -1 ) {
1860 file << "<weightgroup"
1861 << oattr("type", weightgroup[group].type);
1862 if ( !weightgroup[group].combine.empty() )
1863 file << oattr("combine", weightgroup[group].combine);
1864 file << ">\n";
1865 }
1866 ingroup = group;
1867 }
1868 weightinfo[i].print(file);
1869 }
1870 if ( ingroup != -1 ) file << "</weightgroup>\n";
1871 if ( isrwgt ) file << "</initrwgt>\n";
1872
1873
1874 file << hashline(junk) << "</init>" << std::endl;
1875
1876 }
1877
1878 /**
1879 * Clear all information.
1880 */
1881 void clear() {
1882 procinfo.clear();
1883 mergeinfo.clear();
1884 weightinfo.clear();
1885 weightgroup.clear();
1886 cuts.clear();
1887 ptypes.clear();
1888 junk.clear();
1889 }
1890
1891 /**
1892 * Set the NPRUP variable, corresponding to the number of
1893 * sub-processes, to \a nrup, and resize all relevant vectors
1894 * accordingly.
1895 */
1896 void resize(int nrup) {
1897 NPRUP = nrup;
1898 resize();
1899 }
1900
1901 /**
1902 * Assuming the NPRUP variable, corresponding to the number of
1903 * sub-processes, is correctly set, resize the relevant vectors
1904 * accordingly.
1905 */
1906 void resize() {
1907 XSECUP.resize(NPRUP);
1908 XERRUP.resize(NPRUP);
1909 XMAXUP.resize(NPRUP);
1910 LPRUP.resize(NPRUP);
1911 }
1912
1913 /**
1914 * @return the index of the weight with the given \a name
1915 */
1916 int weightIndex(const std::string & name) const {
1917 std::map<std::string, int>::const_iterator it = weightmap.find(name);
1918 if ( it != weightmap.end() ) return it->second;
1919 return 0;
1920 }
1921
1922 /**
1923 * @return the number of weights (including the nominial one).
1924 */
1925 int nWeights() const {
1926 return weightmap.size() + 1;
1927 }
1928
1929 /**
1930 * @return the XSecInfo object corresponding to the named weight \a
1931 * weithname. If no such object exists, it will be created.
1932 */
1933 XSecInfo & getXSecInfo(std::string weightname = "") {
1934 XSecInfo & xi = xsecinfos[weightname];
1935 xi.weightname = weightname;
1936 return xi;
1937 }
1938
1939 /**
1940 * @return the XSecInfo object corresponding to the named weight \a
1941 * weithname. If no such object exists, an empty XSecInfo will be
1942 * returned..
1943 */
1944 const XSecInfo & getXSecInfo(std::string weightname = "") const {
1945 static XSecInfo noinfo;
1946 XSecInfos::const_iterator it = xsecinfos.find(weightname);
1947 if ( it != xsecinfos.end() ) return it->second;
1948 else return noinfo;
1949 }
1950
1951
1952public:
1953
1954 /**
1955 * PDG id's of beam particles. (first/second is in +/-z direction).
1956 */
1957 std::pair<long,long> IDBMUP;
1958
1959 /**
1960 * Energy of beam particles given in GeV.
1961 */
1962 std::pair<double,double> EBMUP;
1963
1964 /**
1965 * The author group for the PDF used for the beams according to the
1966 * PDFLib specification.
1967 */
1968 std::pair<int,int> PDFGUP;
1969
1970 /**
1971 * The id number the PDF used for the beams according to the
1972 * PDFLib specification.
1973 */
1974 std::pair<int,int> PDFSUP;
1975
1976 /**
1977 * Master switch indicating how the ME generator envisages the
1978 * events weights should be interpreted according to the Les Houches
1979 * accord.
1980 */
1982
1983 /**
1984 * The number of different subprocesses in this file.
1985 */
1987
1988 /**
1989 * The cross sections for the different subprocesses in pb.
1990 */
1991 std::vector<double> XSECUP;
1992
1993 /**
1994 * The statistical error in the cross sections for the different
1995 * subprocesses in pb.
1996 */
1997 std::vector<double> XERRUP;
1998
1999 /**
2000 * The maximum event weights (in HEPEUP::XWGTUP) for different
2001 * subprocesses.
2002 */
2003 std::vector<double> XMAXUP;
2004
2005 /**
2006 * The subprocess code for the different subprocesses.
2007 */
2008 std::vector<int> LPRUP;
2009
2010 /**
2011 * Contents of the xsecinfo tags.
2012 */
2014
2015 /**
2016 * A vector of EventFiles where the events are stored separate fron
2017 * the init block.
2018 */
2019 std::vector<EventFile> eventfiles;
2020
2021 /**
2022 * Contents of the cuts tag.
2023 */
2024 std::vector<Cut> cuts;
2025
2026 /**
2027 * A map of codes for different particle types.
2028 */
2029 std::map<std::string, std::set<long> > ptypes;
2030
2031 /**
2032 * Contents of the procinfo tags
2033 */
2034 std::map<long,ProcInfo> procinfo;
2035
2036 /**
2037 * Contents of the mergeinfo tags
2038 */
2039 std::map<long,MergeInfo> mergeinfo;
2040
2041 /**
2042 * The names of the programs and their version information used to
2043 * create this file.
2044 */
2045 std::vector<Generator> generators;
2046
2047 /**
2048 * The vector of WeightInfo objects for this file.
2049 */
2050 std::vector<WeightInfo> weightinfo;
2051
2052 /**
2053 * A map relating names of weights to indices of the weightinfo vector.
2054 */
2055 std::map<std::string,int> weightmap;
2056
2057 /**
2058 * The vector of WeightGroup objects in this file.
2059 */
2060 std::vector<WeightGroup> weightgroup;
2061
2062 /**
2063 * Just to be on the safe side we save any junk inside the init-tag.
2064 */
2065 std::string junk;
2066
2067 /**
2068 * The main version of the information stored.
2069 */
2071
2072 /**
2073 * The precision used for outputing real numbers.
2074 */
2076
2077};
2078
2079/**
2080 * Forward declaration of the HEPEUP class.
2081 */
2082class HEPEUP;
2083
2084/**
2085 * The EventGroup represents a set of events which are to be
2086 * considered together.
2087 */
2088struct EventGroup: public std::vector<HEPEUP*> {
2089
2090 /**
2091 * Initialize default values.
2092 */
2093 inline EventGroup(): nreal(-1), ncounter(-1) {}
2094
2095 /**
2096 * The copy constructor also copies the included HEPEUP object.
2097 */
2098 inline EventGroup(const EventGroup &);
2099
2100 /**
2101 * The assignment also copies the included HEPEUP object.
2102 */
2103 inline EventGroup & operator=(const EventGroup &);
2104
2105 /**
2106 * Remove all subevents.
2107 */
2108 inline void clear();
2109
2110 /**
2111 * The destructor deletes the included HEPEUP objects.
2112 */
2113 inline ~EventGroup();
2114
2115 /**
2116 * The number of real events in this event group.
2117 */
2119
2120 /**
2121 * The number of counter events in this event group.
2122 */
2124
2125};
2126
2127
2128/**
2129 * The HEPEUP class is a simple container corresponding to the Les Houches accord
2130 * (<A HREF="http://arxiv.org/abs/hep-ph/0109068">hep-ph/0109068</A>)
2131 * common block with the same name. The members are named in the same
2132 * way as in the common block. However, fortran arrays are represented
2133 * by vectors, except for the arrays of length two which are
2134 * represented by pair objects.
2135 */
2136class HEPEUP : public TagBase {
2137
2138public:
2139
2140 /** @name Standard constructors and destructors. */
2141 /// @{
2142 /**
2143 * Default constructor.
2144 */
2146 : NUP(0), IDPRUP(0), XWGTUP(0.0), XPDWUP(0.0, 0.0),
2147 SCALUP(0.0), AQEDUP(0.0), AQCDUP(0.0), heprup(nullptr), currentWeight(nullptr),
2148 ntries(1), isGroup(false) {}
2149
2150 /**
2151 * Copy constructor
2152 */
2153 HEPEUP(const HEPEUP & x)
2154 : TagBase(x), isGroup(false) {
2155 operator=(x);
2156 }
2157
2158 /**
2159 * Copy information from the given HEPEUP. Sub event information is
2160 * left untouched.
2161 */
2162 HEPEUP & setEvent(const HEPEUP & x) {
2163 NUP = x.NUP;
2164 IDPRUP = x.IDPRUP;
2165 XWGTUP = x.XWGTUP;
2166 XPDWUP = x.XPDWUP;
2167 SCALUP = x.SCALUP;
2168 AQEDUP = x.AQEDUP;
2169 AQCDUP = x.AQCDUP;
2170 IDUP = x.IDUP;
2171 ISTUP = x.ISTUP;
2172 MOTHUP = x.MOTHUP;
2173 ICOLUP = x.ICOLUP;
2174 PUP = x.PUP;
2175 VTIMUP = x.VTIMUP;
2176 SPINUP = x.SPINUP;
2177 heprup = x.heprup;
2179 weights = x.weights;
2180 pdfinfo = x.pdfinfo;
2184 scales = x.scales;
2185 junk = x.junk;
2187 ntries = x.ntries;
2188 return *this;
2189 }
2190
2191 /**
2192 * Assignment operator.
2193 */
2194 HEPEUP & operator=(const HEPEUP & x) {
2195 if ( &x == this ) return *this;
2196 TagBase::operator=(x);
2197 clear();
2198 setEvent(x);
2199 subevents = x.subevents;
2200 isGroup = x.isGroup;
2201 return *this;
2202 }
2203
2204 /**
2205 * Destructor.
2206 */
2208 clear();
2209 };
2210 /// @}
2211
2212public:
2213
2214
2215 /**
2216 * Constructor from an event or eventgroup tag.
2217 */
2218 HEPEUP(const XMLTag & tagin, HEPRUP & heprupin)
2219 : TagBase(tagin.attr), NUP(0), IDPRUP(0), XWGTUP(0.0), XPDWUP(0.0, 0.0),
2220 SCALUP(0.0), AQEDUP(0.0), AQCDUP(0.0), heprup(&heprupin),
2221 currentWeight(nullptr), ntries(1), isGroup(tagin.name == "eventgroup") {
2222
2223 if ( heprup->NPRUP < 0 )
2224 throw std::runtime_error("Tried to read events but no processes defined "
2225 "in init block of Les Houches file.");
2226
2227 std::vector<XMLTag*> tags = tagin.tags;
2228
2229 if ( isGroup ) {
2230 getattr("nreal", subevents.nreal);
2231 getattr("ncounter", subevents.ncounter);
2232 for ( int i = 0, N = tags.size(); i < N; ++i )
2233 if ( tags[i]->name == "event" )
2234 subevents.push_back(new HEPEUP(*tags[i], heprupin));
2235 return;
2236 } else
2237 getattr("ntries", ntries);
2238
2239
2240
2241 // The event information should be in the first (anonymous) tag
2242 std::istringstream iss(tags[0]->contents);
2243 if ( !( iss >> NUP >> IDPRUP >> XWGTUP >> SCALUP >> AQEDUP >> AQCDUP ) )
2244 throw std::runtime_error("Failed to parse event in Les Houches file.");
2245
2246 resize();
2247
2248 // Read all particle lines.
2249 for ( int i = 0; i < NUP; ++i ) {
2250 if ( !( iss >> IDUP[i] >> ISTUP[i] >> MOTHUP[i].first >> MOTHUP[i].second
2251 >> ICOLUP[i].first >> ICOLUP[i].second
2252 >> PUP[i][0] >> PUP[i][1] >> PUP[i][2]
2253 >> PUP[i][3] >> PUP[i][4]
2254 >> VTIMUP[i] >> SPINUP[i] ) )
2255 throw std::runtime_error("Failed to parse event in Les Houches file.");
2256 }
2257
2258 junk.clear();
2259 std::string ss;
2260 while ( getline(iss, ss) ) junk += ss + '\n';
2261
2262 scales = Scales(SCALUP, NUP);
2264 namedweights.clear();
2265 weights.clear();
2266 weights.resize(heprup->nWeights(),
2267 std::make_pair(XWGTUP, nullptr));
2268 weights.front().first = XWGTUP;
2269 for ( int i = 1, N = weights.size(); i < N; ++i )
2270 weights[i].second = &heprup->weightinfo[i - 1];
2271
2272 for ( int i = 1, N = tags.size(); i < N; ++i ) {
2273 XMLTag & tag = *tags[i];
2274
2275 if ( tag.name.empty() ) junk += tag.contents;
2276
2277 if ( tag.name == "weights" ) {
2278 weights.resize(heprup->nWeights(),
2279 std::make_pair(XWGTUP, nullptr));
2280 weights.front().first = XWGTUP;
2281 for ( int ii = 1, NN = weights.size(); ii < NN; ++ii )
2282 weights[ii].second = &heprup->weightinfo[ii - 1];
2283 double w = 0.0;
2284 int iii = 0;
2285 std::istringstream isss(tag.contents);
2286 while ( isss >> w )
2287 if ( ++iii < int(weights.size()) )
2288 weights[iii].first = w;
2289 else
2290 weights.push_back(std::make_pair(w, nullptr));
2291 }
2292 if ( tag.name == "weight" ) {
2293 namedweights.push_back(Weight(tag));
2294 }
2295 if ( tag.name == "rwgt" ) {
2296 for ( int j = 0, M = tag.tags.size(); j < M; ++j ) {
2297 if ( tag.tags[j]->name == "wgt" ) {
2298 namedweights.push_back(Weight(*tag.tags[j]));
2299 }
2300 }
2301 }
2302 else if ( tag.name == "clustering" ) {
2303 for ( int j = 0, M= tag.tags.size(); j < M; ++j ) {
2304 if ( tag.tags[j]->name == "clus" )
2305 clustering.push_back(Clus(*tag.tags[j]));
2306 }
2307 }
2308 else if ( tag.name == "pdfinfo" ) {
2309 pdfinfo = PDFInfo(tag, SCALUP);
2310 }
2311 else if ( tag.name == "scales" ) {
2312 scales = Scales(tag, SCALUP, NUP);
2313 }
2314
2315 }
2316
2317 for ( int i = 0, N = namedweights.size(); i < N; ++i ) {
2318 int indx = heprup->weightIndex(namedweights[i].name);
2319 if ( indx > 0 ) {
2320 weights[indx].first = namedweights[i].weights[0];
2321 namedweights[i].indices[0] = indx;
2322 } else {
2323 weights.push_back(std::make_pair(namedweights[i].weights[0],
2324 nullptr));
2325 namedweights[i].indices[0] = weights.size() - 1;
2326 }
2327 for ( int j = 1, M = namedweights[i].weights.size(); j < M; ++j ) {
2328 weights.push_back(std::make_pair(namedweights[i].weights[j],
2329 nullptr));
2330 namedweights[i].indices[j] = weights.size() - 1;
2331 }
2332 }
2333
2334 }
2335
2336 /**
2337 * Print out the event (group) as an XML tag.
2338 */
2339 void print(std::ostream & file) const {
2340
2341 file << std::setprecision(heprup->dprec);
2342
2343
2344 if ( isGroup ) {
2345 file << "<eventgroup";
2346 if ( subevents.nreal > 0 )
2347 file << oattr("nreal", subevents.nreal);
2348 if ( subevents.ncounter > 0 )
2349 file << oattr("ncounter", subevents.ncounter);
2350 printattrs(file);
2351 file << ">\n";
2352 for ( int i = 0, N = subevents.size(); i < N; ++i )
2353 subevents[i]->print(file);
2354 file << "</eventgroup>\n";
2355 return;
2356 }
2357
2358 file << "<event";
2359 if ( ntries > 1 ) file << oattr("ntries", ntries);
2360 printattrs(file);
2361 file << ">\n";
2362 file << " " << std::setw(4) << NUP
2363 << " " << std::setw(6) << IDPRUP
2364 << " " << std::setw(14) << XWGTUP
2365 << " " << std::setw(14) << SCALUP
2366 << " " << std::setw(14) << AQEDUP
2367 << " " << std::setw(14) << AQCDUP << "\n";
2368
2369 for ( int i = 0; i < NUP; ++i )
2370 file << " " << std::setw(8) << IDUP[i]
2371 << " " << std::setw(2) << ISTUP[i]
2372 << " " << std::setw(4) << MOTHUP[i].first
2373 << " " << std::setw(4) << MOTHUP[i].second
2374 << " " << std::setw(4) << ICOLUP[i].first
2375 << " " << std::setw(4) << ICOLUP[i].second
2376 << " " << std::setw(14) << PUP[i][0]
2377 << " " << std::setw(14) << PUP[i][1]
2378 << " " << std::setw(14) << PUP[i][2]
2379 << " " << std::setw(14) << PUP[i][3]
2380 << " " << std::setw(14) << PUP[i][4]
2381 << " " << std::setw(1) << VTIMUP[i]
2382 << " " << std::setw(1) << SPINUP[i] << std::endl;
2383
2384 if ( weights.size() > 0 ) {
2385 file << "<weights>";
2386 for ( int i = 1, N = weights.size(); i < N; ++i )
2387 file << " " << weights[i].first;
2388 file << "</weights>\n";
2389 }
2390
2391 bool iswgt = false;
2392 for ( int i = 0, N = namedweights.size(); i < N; ++i ) {
2393 if ( namedweights[i].iswgt ) {
2394 if ( !iswgt ) file << "<rwgt>\n";
2395 iswgt = true;
2396 } else {
2397 if ( iswgt ) file << "</rwgt>\n";
2398 iswgt = false;
2399 }
2400 for ( int j = 0, M = namedweights[i].indices.size(); j < M; ++j )
2401 namedweights[i].weights[j] = weight(namedweights[i].indices[j]);
2402 namedweights[i].print(file);
2403 }
2404 if ( iswgt ) file << "</rwgt>\n";
2405
2406 if ( !clustering.empty() ) {
2407 file << "<clustering>" << std::endl;
2408 for ( int i = 0, N = clustering.size(); i < N; ++i )
2409 clustering[i].print(file);
2410 file << "</clustering>" << std::endl;
2411 }
2412
2413 pdfinfo.print(file);
2414 scales.print(file);
2415
2416 file << hashline(junk) << "</event>\n";
2417
2418 }
2419
2420 /**
2421 * Reset the HEPEUP object (does not touch the sub events).
2422 */
2423 void reset() {
2424 setWeightInfo(0);
2425 NUP = 0;
2426 clustering.clear();
2427 weights.clear();
2428 }
2429
2430 /**
2431 * Clear the HEPEUP object.
2432 */
2433 void clear() {
2434 reset();
2435 subevents.clear();
2436 }
2437
2438 /**
2439 * Set the NUP variable, corresponding to the number of particles in
2440 * the current event, to \a nup, and resize all relevant vectors
2441 * accordingly.
2442 */
2443 void resize(int nup) {
2444 NUP = nup;
2445 resize();
2446 }
2447
2448 /**
2449 * Return the total weight for this event (including all sub
2450 * evenets) for the given index.
2451 */
2452 double totalWeight(int i = 0) const {
2453 if ( subevents.empty() ) return weight(i);
2454 double w = 0.0;
2455 for ( int ii = 0, N = subevents.size(); ii < N; ++ii )
2456 w += subevents[ii]->weight(i);
2457 return w;
2458 }
2459
2460 /**
2461 * Return the total weight for this event (including all sub
2462 * evenets) for the given weight name.
2463 */
2464 double totalWeight(const std::string & name) const {
2465 return totalWeight(heprup->weightIndex(name));
2466 }
2467
2468 /**
2469 * Return the weight for the given index.
2470 */
2471 double weight(int i = 0) const {
2472 return weights[i].first;
2473 }
2474
2475 /**
2476 * Return the weight for the given weight name.
2477 */
2478 double weight(const std::string & name) const {
2479 return weight(heprup->weightIndex(name));
2480 }
2481
2482 /**
2483 * Set the weight with the given index.
2484 */
2485 void setWeight(int i, double w) {
2486 weights[i].first = w;
2487 }
2488 /**
2489 * Set the weight with the given name.
2490 */
2491 bool setWeight(const std::string & name, double w) {
2492 int i = heprup->weightIndex(name);
2493 if ( i >= int(weights.size()) ) return false;
2494 setWeight(i, w);
2495 return true;
2496 }
2497
2498
2499 /**
2500 * Assuming the NUP variable, corresponding to the number of
2501 * particles in the current event, is correctly set, resize the
2502 * relevant vectors accordingly.
2503 */
2504 void resize() {
2505 IDUP.resize(NUP);
2506 ISTUP.resize(NUP);
2507 MOTHUP.resize(NUP);
2508 ICOLUP.resize(NUP);
2509 PUP.resize(NUP, std::vector<double>(5));
2510 VTIMUP.resize(NUP);
2511 SPINUP.resize(NUP);
2512 }
2513
2514 /**
2515 * Setup the current event to use weight i. If zero, the default
2516 * weight will be used.
2517 */
2518 bool setWeightInfo(unsigned int i) {
2519 if ( i >= weights.size() ) return false;
2520 if ( currentWeight ) {
2521 scales.mur /= currentWeight->mur;
2522 scales.muf /= currentWeight->muf;
2523 heprup->PDFGUP = PDFGUPsave;
2524 heprup->PDFSUP = PDFSUPsave;
2525 }
2526 XWGTUP = weights[i].first;
2527 currentWeight = weights[i].second;
2528 if ( currentWeight ) {
2529 scales.mur *= currentWeight->mur;
2530 scales.muf *= currentWeight->muf;
2531 PDFGUPsave = heprup->PDFGUP;
2532 PDFSUPsave = heprup->PDFSUP;
2533 if ( currentWeight->pdf ) {
2534 heprup->PDFGUP.first = heprup->PDFGUP.second = 0;
2535 heprup->PDFSUP.first = heprup->PDFSUP.second = currentWeight->pdf;
2536 }
2537 if ( currentWeight->pdf2 ) {
2538 heprup->PDFSUP.second = currentWeight->pdf2;
2539 }
2540
2541 }
2542 return true;
2543 }
2544
2545 /**
2546 * Setup the current event to use sub event i. If zero, no sub event
2547 * will be chsen.
2548 */
2549 bool setSubEvent(unsigned int i) {
2550 if ( i > subevents.size() || subevents.empty() ) return false;
2551 if ( i == 0 ) {
2552 reset();
2553 weights = subevents[0]->weights;
2554 for ( int ii = 1, N = subevents.size(); ii < N; ++ii )
2555 for ( int j = 0, M = weights.size(); j < M; ++j )
2556 weights[j].first += subevents[ii]->weights[j].first;
2557 currentWeight = nullptr;
2558 } else {
2559 setEvent(*subevents[i - 1]);
2560 }
2561 return true;
2562 }
2563
2564public:
2565
2566 /**
2567 * The number of particle entries in the current event.
2568 */
2569 int NUP;
2570
2571 /**
2572 * The subprocess code for this event (as given in LPRUP).
2573 */
2575
2576 /**
2577 * The weight for this event.
2578 */
2579 double XWGTUP;
2580
2581 /**
2582 * The PDF weights for the two incoming partons. Note that this
2583 * variable is not present in the current LesHouches accord
2584 * (<A HREF="http://arxiv.org/abs/hep-ph/0109068">hep-ph/0109068</A>),
2585 * hopefully it will be present in a future accord.
2586 */
2587 std::pair<double,double> XPDWUP;
2588
2589 /**
2590 * The scale in GeV used in the calculation of the PDF's in this
2591 * event.
2592 */
2593 double SCALUP;
2594
2595 /**
2596 * The value of the QED coupling used in this event.
2597 */
2598 double AQEDUP;
2599
2600 /**
2601 * The value of the QCD coupling used in this event.
2602 */
2603 double AQCDUP;
2604
2605 /**
2606 * The PDG id's for the particle entries in this event.
2607 */
2608 std::vector<long> IDUP;
2609
2610 /**
2611 * The status codes for the particle entries in this event.
2612 */
2613 std::vector<int> ISTUP;
2614
2615 /**
2616 * Indices for the first and last mother for the particle entries in
2617 * this event.
2618 */
2619 std::vector< std::pair<int,int> > MOTHUP;
2620
2621 /**
2622 * The colour-line indices (first(second) is (anti)colour) for the
2623 * particle entries in this event.
2624 */
2625 std::vector< std::pair<int,int> > ICOLUP;
2626
2627 /**
2628 * Lab frame momentum (Px, Py, Pz, E and M in GeV) for the particle
2629 * entries in this event.
2630 */
2631 std::vector< std::vector<double> > PUP;
2632
2633 /**
2634 * Invariant lifetime (c*tau, distance from production to decay in
2635 * mm) for the particle entries in this event.
2636 */
2637 std::vector<double> VTIMUP;
2638
2639 /**
2640 * Spin info for the particle entries in this event given as the
2641 * cosine of the angle between the spin vector of a particle and the
2642 * 3-momentum of the decaying particle, specified in the lab frame.
2643 */
2644 std::vector<double> SPINUP;
2645
2646 /**
2647 * A pointer to the current HEPRUP object.
2648 */
2650
2651 /**
2652 * The current weight info object.
2653 */
2655
2656 /**
2657 * The weights associated with this event
2658 */
2659 std::vector<Weight> namedweights;
2660
2661 /**
2662 * The weights for this event and their corresponding WeightInfo object.
2663 */
2664 std::vector< std::pair<double, const WeightInfo *> > weights;
2665
2666 /**
2667 * Contents of the clustering tag.
2668 */
2669 std::vector<Clus> clustering;
2670
2671 /**
2672 * Contents of the pdfinfo tag.
2673 */
2675
2676 /**
2677 * Saved information about pdfs if different in a selected weight.
2678 */
2679 std::pair<int,int> PDFGUPsave;
2680
2681 /**
2682 * Saved information about pdfs if different in a selected weight.
2683 */
2684 std::pair<int,int> PDFSUPsave;
2685
2686
2687 /**
2688 * Contents of the scales tag
2689 */
2691
2692 /**
2693 * The number of attempts the ME generator did before accepting this
2694 * event.
2695 */
2697
2698 /**
2699 * Is this an event or an event group?
2700 */
2702
2703 /**
2704 * If this is not a single event, but an event group, the events
2705 * included in the group are in this vector;
2706 */
2708
2709 /**
2710 * Save junk stuff in events just to be on the safe side
2711 */
2712 std::string junk;
2713
2714};
2715
2716
2717// Destructor implemented here.
2718
2719inline void EventGroup::clear() {
2720 while ( size() > 0 ) {
2721 delete back();
2722 pop_back();
2723 }
2724}
2725
2727 clear();
2728}
2729
2731 : std::vector<HEPEUP*>(eg.size()),nreal(0),ncounter(0) {
2732 for ( int i = 0, N = eg.size(); i < N; ++i ) at(i) = new HEPEUP(*eg.at(i));
2733}
2734
2736 if ( &x == this ) return *this;
2737 clear();
2738 nreal = x.nreal;
2739 ncounter = x.ncounter;
2740 for ( int i = 0, N = x.size(); i < N; ++i ) push_back(new HEPEUP(*x.at(i)));
2741 return *this;
2742}
2743
2744
2745/**
2746 * The Reader class is initialized with a stream from which to read a
2747 * version 1/2 Les Houches Accord event file. In the constructor of
2748 * the Reader object the optional header information is read and then
2749 * the mandatory init is read. After this the whole header block
2750 * including the enclosing lines with tags are available in the public
2751 * headerBlock member variable. Also the information from the init
2752 * block is available in the heprup member variable and any additional
2753 * comment lines are available in initComments. After each successful
2754 * call to the readEvent() function the standard Les Houches Accord
2755 * information about the event is available in the hepeup member
2756 * variable and any additional comments in the eventComments
2757 * variable. A typical reading sequence would look as follows:
2758 *
2759 *
2760 */
2761class Reader {
2762
2763public:
2764
2765 /**
2766 * Initialize the Reader with a stream from which to read an event
2767 * file. After the constructor is called the whole header block
2768 * including the enclosing lines with tags are available in the
2769 * public headerBlock member variable. Also the information from the
2770 * init block is available in the heprup member variable and any
2771 * additional comment lines are available in initComments.
2772 *
2773 * @param is the stream to read from.
2774 */
2775 Reader(std::istream & is)
2776 : file(&is), currevent(-1),
2777 curreventfile(-1), currfileevent(-1), dirpath("") {
2778 init();
2779 }
2780
2781 /**
2782 * Initialize the Reader with a filename from which to read an event
2783 * file. After the constructor is called the whole header block
2784 * including the enclosing lines with tags are available in the
2785 * public headerBlock member variable. Also the information from the
2786 * init block is available in the heprup member variable and any
2787 * additional comment lines are available in initComments.
2788 *
2789 * @param filename the name of the file to read from.
2790 */
2791 Reader(std::string filename)
2792 : intstream(filename.c_str()), file(&intstream), currevent(-1),
2793 curreventfile(-1), currfileevent(-1), dirpath("") {
2794
2795 size_t slash = filename.find_last_of('/');
2796 if ( slash != std::string::npos ) dirpath = filename.substr(0, slash + 1);
2797 init();
2798 }
2799
2800private:
2801
2802 /**
2803 * Used internally in the constructors to read header and init
2804 * blocks.
2805 */
2806 void init() {
2807
2808 // initialize reading from multi-file runs.
2809 initfile = file;
2810
2811 bool readingHeader = false;
2812 bool readingInit = false;
2813
2814 // Make sure we are reading a LHEF file:
2815 getline();
2816 if ( !currentFind("<LesHouchesEvents") )
2817 throw std::runtime_error
2818 ("Tried to read a file which does not start with the "
2819 "LesHouchesEvents tag.");
2820 version = 1;
2821 if ( currentFind("version=\"3" ) )
2822 version = 3;
2823 else if ( currentFind("version=\"2" ) )
2824 version = 2;
2825 else if ( !currentFind("version=\"1" ) )
2826 throw std::runtime_error
2827 ("Tried to read a LesHouchesEvents file which is above version 3.");
2828
2829 // Loop over all lines until we hit the </init> tag.
2830 while ( getline() && !currentFind("</init>") ) {
2831 if ( currentFind("<header") ) {
2832 // We have hit the header block, so we should dump this and
2833 // all following lines to headerBlock until we hit the end of
2834 // it.
2835 readingHeader = true;
2836 headerBlock = currentLine + "\n";
2837 }
2838 else if ( currentFind("<init>") ) {
2839 // We have hit the init block
2840 readingInit = true;
2841 initComments = currentLine + "\n";
2842 }
2843 else if ( currentFind("</header>") ) {
2844 // The end of the header block. Dump this line as well to the
2845 // headerBlock and we're done.
2846 readingHeader = false;
2847 headerBlock += currentLine + "\n";
2848 }
2849 else if ( readingHeader ) {
2850 // We are in the process of reading the header block. Dump the
2851 // line to haderBlock.
2852 headerBlock += currentLine + "\n";
2853 }
2854 else if ( readingInit ) {
2855 // Here we found a comment line. Dump it to initComments.
2856 initComments += currentLine + "\n";
2857 }
2858 else {
2859 // We found some other stuff outside the standard tags.
2860 outsideBlock += currentLine + "\n";
2861 }
2862 }
2863 if ( !currentFind("</init>") )
2864 throw std::runtime_error("Found incomplete init tag in "
2865 "Les Houches file.");
2866 initComments += currentLine + "\n";
2867 std::vector<XMLTag*> tags = XMLTag::findXMLTags(initComments);
2868 for ( int i = 0, N = tags.size(); i < N; ++i )
2869 if ( tags[i]->name == "init" ) {
2870 heprup = HEPRUP(*tags[i], version);
2871 break;
2872 }
2873 XMLTag::deleteAll(tags);
2874
2875 if ( !heprup.eventfiles.empty() ) openeventfile(0);
2876
2877 }
2878
2879public:
2880
2881 /**
2882 * Read an event from the file and store it in the hepeup
2883 * object. Optional comment lines are stored i the eventComments
2884 * member variable.
2885 * @return true if the read sas successful.
2886 */
2887 bool readEvent() {
2888
2889 // Check if the initialization was successful. Otherwise we will
2890 // not read any events.
2891 if ( heprup.NPRUP < 0 ) return false;
2892
2893 std::string eventLines;
2894 int inEvent = 0;
2895
2896 // Keep reading lines until we hit the end of an event or event group.
2897 while ( getline() ) {
2898 if ( inEvent ) {
2899 eventLines += currentLine + "\n";
2900 if ( inEvent == 1 && currentFind("</event>") ) break;
2901 if ( inEvent == 2 && currentFind("</eventgroup>") ) break;
2902 }
2903 else if ( currentFind("<eventgroup") ) {
2904 eventLines += currentLine + "\n";
2905 inEvent = 2;
2906 }
2907 else if ( currentFind("<event") ) {
2908 eventLines += currentLine + "\n";
2909 inEvent = 1;
2910 }
2911 else {
2912 outsideBlock += currentLine + "\n";
2913 }
2914 }
2915 if ( ( inEvent == 1 && !currentFind("</event>") ) ||
2916 ( inEvent == 2 && !currentFind("</eventgroup>") ) ) {
2917 if ( heprup.eventfiles.empty() ||
2918 ++curreventfile >= int(heprup.eventfiles.size()) ) return false;
2920 return readEvent();
2921 }
2922
2923 std::vector<XMLTag*> tags = XMLTag::findXMLTags(eventLines);
2924
2925 for ( int i = 0, N = tags.size(); i < N ; ++i ) {
2926 if ( tags[i]->name == "event" || tags[i]->name == "eventgroup" ) {
2927 hepeup = HEPEUP(*tags[i], heprup);
2928 XMLTag::deleteAll(tags);
2929 ++currevent;
2930 if ( curreventfile >= 0 ) ++currfileevent;
2931 return true;
2932 }
2933 }
2934
2935 if ( !heprup.eventfiles.empty() &&
2936 ++curreventfile < int(heprup.eventfiles.size()) ) {
2938 XMLTag::deleteAll(tags);
2939 return readEvent();
2940 }
2941
2942 XMLTag::deleteAll(tags);
2943 return false;
2944
2945 }
2946
2947 /**
2948 * Open the efentfile with index ifile. If another eventfile is
2949 * being read, its remaining contents is discarded. This is a noop
2950 * if current read session is not a multi-file run.
2951 */
2952 void openeventfile(int ifile) {
2953 std::cerr << "opening file " << ifile << std::endl;
2954 efile.close();
2955 std::string fname = heprup.eventfiles[ifile].filename;
2956 if ( fname[0] != '/' ) fname = dirpath + fname;
2957 efile.open(fname.c_str());
2958 if ( !efile ) throw std::runtime_error("Could not open event file " +
2959 fname);
2960 file = &efile;
2961 curreventfile = ifile;
2962 currfileevent = 0;
2963 }
2964
2965protected:
2966
2967 /**
2968 * Used internally to read a single line from the stream.
2969 */
2970 bool getline() {
2971 return ( static_cast<bool> (std::getline(*file, currentLine)) );
2972 }
2973
2974 /**
2975 * @return true if the current line contains the given string.
2976 */
2977 bool currentFind(std::string str) const {
2978 return currentLine.find(str) != std::string::npos;
2979 }
2980
2981protected:
2982
2983 /**
2984 * A local stream which is unused if a stream is supplied from the
2985 * outside.
2986 */
2987 std::ifstream intstream;
2988
2989 /**
2990 * The stream we are reading from. This may be a pointer to an
2991 * external stream or the internal intstream, or a separate event
2992 * file from a multi-file run
2993 */
2994 std::istream * file;
2995
2996 /**
2997 * The original stream from where we read the init block.
2998 */
2999 std::istream * initfile;
3000
3001 /**
3002 * A separate stream for reading multi-file runs.
3003 */
3004 std::ifstream efile;
3005
3006 /**
3007 * The last line read in from the stream in getline().
3008 */
3009 std::string currentLine;
3010
3011public:
3012 /**
3013 * initfile rdstate
3014 */
3015 std::ios_base::iostate initfile_rdstate() const {
3016 if (initfile) return initfile->rdstate();
3017 return std::ifstream::goodbit;
3018 }
3019
3020 /**
3021 * file rdstate
3022 */
3023 std::ios_base::iostate file_rdstate() const {
3024 if (file) return file->rdstate();
3025 return std::ifstream::goodbit;
3026 }
3027
3028 /**
3029 * XML file version
3030 */
3032
3033 /**
3034 * All lines (since the last readEvent()) outside the header, init
3035 * and event tags.
3036 */
3037 std::string outsideBlock;
3038
3039 /**
3040 * All lines from the header block.
3041 */
3042 std::string headerBlock;
3043
3044 /**
3045 * The standard init information.
3046 */
3048
3049 /**
3050 * Additional comments found in the init block.
3051 */
3052 std::string initComments;
3053
3054 /**
3055 * The standard information about the last read event.
3056 */
3058
3059 /**
3060 * Additional comments found with the last read event.
3061 */
3062 std::string eventComments;
3063
3064 /**
3065 * The number of the current event (starting from 1).
3066 */
3068
3069 /**
3070 * The current event file being read from (-1 means there are no
3071 * separate event files).
3072 */
3074
3075 /**
3076 * The number of the current event in the current event file.
3077 */
3079
3080 /**
3081 * The directory from where we are reading files.
3082 */
3083 std::string dirpath;
3084
3085private:
3086
3087 /**
3088 * The default constructor should never be used.
3089 */
3091
3092 /**
3093 * The copy constructor should never be used.
3094 */
3095 Reader(const Reader &);
3096
3097 /**
3098 * The Reader cannot be assigned to.
3099 */
3101
3102};
3103
3104/**
3105 * The Writer class is initialized with a stream to which to write a
3106 * version 1.0 Les Houches Accord event file. In the constructor of
3107 * the Writer object the main XML tag is written out, with the
3108 * corresponding end tag is written in the destructor. After a Writer
3109 * object has been created, it is possible to assign standard init
3110 * information in the heprup member variable. In addition any XML
3111 * formatted information can be added to the headerBlock member
3112 * variable (directly or via the addHeader() function). Further
3113 * comment line (beginning with a <code>#</code> character) can be
3114 * added to the initComments variable (directly or with the
3115 * addInitComment() function). After this information is set, it
3116 * should be written out to the file with the init() function.
3117 *
3118 * Before each event is written out with the writeEvent() function,
3119 * the standard event information can then be assigned to the hepeup
3120 * variable and optional comment lines (beginning with a
3121 * <code>#</code> character) may be given to the eventComments
3122 * variable (directly or with the addEventComment() function).
3123 *
3124 */
3125class Writer {
3126
3127public:
3128
3129 /**
3130 * Create a Writer object giving a stream to write to.
3131 * @param os the stream where the event file is written.
3132 */
3133 Writer(std::ostream & os)
3134 : file(&os), initfile(&os), lastevent(-1), curreventfile(-1),
3135 currfileevent(-1), dirpath("") {}
3136
3137 /**
3138 * Create a Writer object giving a filename to write to.
3139 * @param filename the name of the event file to be written.
3140 */
3141 Writer(std::string filename)
3142 : intstream(filename.c_str()), file(&intstream), initfile(&intstream),
3143 lastevent(-1), curreventfile(-1), currfileevent(-1), dirpath("") {
3144 size_t slash = filename.find_last_of('/');
3145 if ( slash != std::string::npos ) dirpath = filename.substr(0, slash + 1);
3146 }
3147
3148 /**
3149 * The destructor writes out the final XML end-tag.
3150 */
3152 file = initfile;
3153 if ( !heprup.eventfiles.empty() ) {
3154 if ( curreventfile >= 0 &&
3155 curreventfile < int(heprup.eventfiles.size()) &&
3156 heprup.eventfiles[curreventfile].neve < 0 )
3157 heprup.eventfiles[curreventfile].neve = currfileevent;
3158 writeinit();
3159 }
3160 *file << "</LesHouchesEvents>" << std::endl;
3161 }
3162
3163 /**
3164 * Add header lines consisting of XML code with this stream.
3165 */
3166 std::ostream & headerBlock() {
3167 return headerStream;
3168 }
3169
3170 /**
3171 * Add comment lines to the init block with this stream.
3172 */
3173 std::ostream & initComments() {
3174 return initStream;
3175 }
3176
3177 /**
3178 * Add comment lines to the next event to be written out with this stream.
3179 */
3180 std::ostream & eventComments() {
3181 return eventStream;
3182 }
3183 /**
3184 * Add header lines consisting of XML code with this stream.
3185 */
3186 void headerBlock(const std::string& a) {
3187 headerStream<<a;;
3188 }
3189
3190 /**
3191 * Add comment lines to the init block with this stream.
3192 */
3193 void initComments(const std::string& a) {
3194 initStream<<a;
3195 }
3196
3197 /**
3198 * Add comment lines to the next event to be written out with this stream.
3199 */
3200 void eventComments(const std::string& a) {
3201 eventStream<<a;
3202 }
3203
3204 /**
3205 * Initialize the writer.
3206 */
3207 void init() {
3208 if ( heprup.eventfiles.empty() ) writeinit();
3209 lastevent = 0;
3211 if ( !heprup.eventfiles.empty() ) openeventfile(0);
3212 }
3213
3214 /**
3215 * Open a new event file, possibly closing a previous opened one.
3216 */
3217 bool openeventfile(int ifile) {
3218 if ( heprup.eventfiles.empty() ) return false;
3219 if ( ifile < 0 || ifile >= int(heprup.eventfiles.size()) ) return false;
3220 if ( curreventfile >= 0 ) {
3221 EventFile & ef = heprup.eventfiles[curreventfile];
3222 if ( ef.neve > 0 && ef.neve != currfileevent )
3223 std::cerr << "LHEF::Writer number of events in event file "
3224 << ef.filename << " does not match the given number."
3225 << std::endl;
3226 ef.neve = currfileevent;
3227 }
3228 efile.close();
3229 std::string fname = heprup.eventfiles[ifile].filename;
3230 if ( fname[0] != '/' ) fname = dirpath + fname;
3231 efile.open(fname.c_str());
3232 if ( !efile ) throw std::runtime_error("Could not open event file " +
3233 fname);
3234 std::cerr << "Opened event file " << fname << std::endl;
3235 file = &efile;
3236 curreventfile = ifile;
3237 currfileevent = 0;
3238 return true;
3239 }
3240
3241
3242 /**
3243 * Write out an optional header block followed by the standard init
3244 * block information together with any comment lines.
3245 */
3246 void writeinit() {
3247
3248 // Write out the standard XML tag for the event file.
3249 if ( heprup.version == 3 )
3250 *file << "<LesHouchesEvents version=\"3.0\">\n";
3251 else if ( heprup.version == 2 )
3252 *file << "<LesHouchesEvents version=\"2.0\">\n";
3253 else
3254 *file << "<LesHouchesEvents version=\"1.0\">\n";
3255
3256
3257 *file << std::setprecision(10);
3258
3259 std::string headBlock = headerStream.str();
3260 if ( headBlock.length() ) {
3261 if ( headBlock.find("<header>") == std::string::npos )
3262 *file << "<header>\n";
3263 if ( headBlock[headBlock.length() - 1] != '\n' )
3264 headBlock += '\n';
3265 *file << headBlock;
3266 if ( headBlock.find("</header>") == std::string::npos )
3267 *file << "</header>\n";
3268 }
3269
3270 heprup.print(*file);
3271
3272 }
3273
3274 /**
3275 * Write the current HEPEUP object to the stream;
3276 */
3277 void writeEvent() {
3278
3279 if ( !heprup.eventfiles.empty() ) {
3280 if ( currfileevent == heprup.eventfiles[curreventfile].neve &&
3281 curreventfile + 1 < int(heprup.eventfiles.size()) )
3283 }
3284
3285 hepeup.print(*file);
3286
3287 ++lastevent;
3288 ++currfileevent;
3289 }
3290
3291protected:
3292
3293 /**
3294 * A local stream which is unused if a stream is supplied from the
3295 * outside.
3296 */
3297 std::ofstream intstream;
3298
3299 /**
3300 * The stream we are writing to. This may be a reference to an
3301 * external stream or the internal intstream.
3302 */
3303 std::ostream * file;
3304
3305 /**
3306 * The original stream from where we read the init block.
3307 */
3308 std::ostream * initfile;
3309
3310 /**
3311 * A separate stream for reading multi-file runs.
3312 */
3313 std::ofstream efile;
3314
3315 /**
3316 * The number of the last event written (starting from 1).
3317 */
3319
3320 /**
3321 * The current event file being written to (-1 means there are no
3322 * separate event files).
3323 */
3325
3326 /**
3327 * The number of the current event in the current event file.
3328 */
3330
3331 /**
3332 * The directory from where we are reading files.
3333 */
3334 std::string dirpath;
3335
3336public:
3337 /**
3338 * The standard init information.
3339 */
3341
3342
3343 /**
3344 * The standard information about the event we will write next.
3345 */
3347
3348
3349
3350private:
3351
3352 /**
3353 * Stream to add all lines in the header block.
3354 */
3355 std::ostringstream headerStream;
3356
3357 /**
3358 * Stream to add additional comments to be put in the init block.
3359 */
3360 std::ostringstream initStream;
3361
3362 /**
3363 * Stream to add additional comments to be written together the next event.
3364 */
3365 std::ostringstream eventStream;
3366
3367
3368 /**
3369 * The default constructor should never be used.
3370 */
3372
3373 /**
3374 * The copy constructor should never be used.
3375 */
3376 Writer(const Writer &);
3377
3378 /**
3379 * The Writer cannot be assigned to.
3380 */
3382
3383};
3384
3385}
3386
3387/** \example LHEFCat.cc This is a main function which simply reads a
3388 Les Houches Event File from the standard input and writes it again
3389 to the standard output.
3390 This file can be downloaded from
3391 <A HREF="http://www.thep.lu.se/~leif/LHEF/LHEFCat.cc">here</A>.
3392 There are also two sample event files,
3393 <A HREF="http://www.thep.lu.se/~leif/LHEF/ttV_unweighted_events.lhe">ttV_unweighted_events.lhe</A> and <A HREF="http://www.thep.lu.se/~leif/LHEF/testlhef3.lhe">testlhef3.lhe</A>
3394 to try it on.
3395*/
3396
3397/**\mainpage Les Houches Event File
3398
3399Here are some example classes for reading and writing Les Houches
3400Event Files according to the
3401<A HREF="http://www.thep.lu.se/~torbjorn/lhef/lhafile2.pdf">proposal</A>
3402by Torbj&ouml;rn Sj&ouml;strand discussed at the
3403<A HREF="http://mc4lhc06.web.cern.ch/mc4lhc06/">MC4LHC</A>
3404workshop at CERN 2006.
3405
3406The classes has now been updated to handle the suggested version 3 of
3407this file standard as discussed at the <a href="http://phystev.in2p3.fr/wiki/2013:groups:tools:lhef3">Les Houches workshop 2013</a> (The previous suggested version 2.0 was discussed at the <a href="http://www.lpthe.jussieu.fr/LesHouches09Wiki/index.php/LHEF_for_Matching">Les Houches workshop 2009</a>).
3408
3409There is a whole set of classes available in a single header file
3410called <A
3411HREF="http://www.thep.lu.se/~leif/LHEF/LHEF.h">LHEF.h</A>. The idea is
3412that matrix element or parton shower generators will implement their
3413own wrapper using these classes as containers.
3414
3415The two classes LHEF::HEPRUP and LHEF::HEPEUP are simple container
3416classes which contain the same information as the Les Houches standard
3417Fortran common blocks with the same names. They also contain the extra
3418information defined in version 3 in the standard. The other two main
3419classes are called LHEF::Reader and LHEF::Writer and are used to read
3420and write Les Houches Event Files
3421
3422Here are a few <A HREF="examples.html">examples</A> of how to use the
3423classes:
3424
3425\namespace LHEF The LHEF namespace contains some example classes for reading and writing Les Houches
3426Event Files according to the
3427<A HREF="http://www.thep.lu.se/~torbjorn/lhef/lhafile2.pdf">proposal</A>
3428by Torbj&ouml;rn Sj&ouml;strand discussed at the
3429<A HREF="http://mc4lhc06.web.cern.ch/mc4lhc06/">MC4LHC</A>
3430workshop at CERN 2006.
3431
3432
3433
3434 */
3435
3436
3437#endif /* HEPMC3_LHEF_H */
#define M_PI
Definition of PI. Needed on some platforms.
Definition FourVector.h:16
std::vector< double > VTIMUP
Definition LHEF.h:2637
double totalWeight(int i=0) const
Definition LHEF.h:2452
bool isGroup
Definition LHEF.h:2701
void resize()
Definition LHEF.h:2504
void print(std::ostream &file) const
Definition LHEF.h:2339
std::pair< int, int > PDFGUPsave
Definition LHEF.h:2679
HEPEUP & operator=(const HEPEUP &x)
Definition LHEF.h:2194
std::vector< long > IDUP
Definition LHEF.h:2608
std::vector< std::pair< int, int > > MOTHUP
Definition LHEF.h:2619
void resize(int nup)
Definition LHEF.h:2443
HEPEUP & setEvent(const HEPEUP &x)
Definition LHEF.h:2162
const WeightInfo * currentWeight
Definition LHEF.h:2654
std::pair< int, int > PDFSUPsave
Definition LHEF.h:2684
double totalWeight(const std::string &name) const
Definition LHEF.h:2464
EventGroup subevents
Definition LHEF.h:2707
std::vector< Clus > clustering
Definition LHEF.h:2669
HEPRUP * heprup
Definition LHEF.h:2649
bool setWeightInfo(unsigned int i)
Definition LHEF.h:2518
std::vector< std::pair< double, const WeightInfo * > > weights
Definition LHEF.h:2664
HEPEUP(const XMLTag &tagin, HEPRUP &heprupin)
Definition LHEF.h:2218
std::vector< int > ISTUP
Definition LHEF.h:2613
double XWGTUP
Definition LHEF.h:2579
int ntries
Definition LHEF.h:2696
HEPEUP(const HEPEUP &x)
Definition LHEF.h:2153
bool setSubEvent(unsigned int i)
Definition LHEF.h:2549
double AQCDUP
Definition LHEF.h:2603
void setWeight(int i, double w)
Definition LHEF.h:2485
double AQEDUP
Definition LHEF.h:2598
std::vector< Weight > namedweights
Definition LHEF.h:2659
Scales scales
Definition LHEF.h:2690
double SCALUP
Definition LHEF.h:2593
double weight(int i=0) const
Definition LHEF.h:2471
std::vector< double > SPINUP
Definition LHEF.h:2644
bool setWeight(const std::string &name, double w)
Definition LHEF.h:2491
double weight(const std::string &name) const
Definition LHEF.h:2478
void clear()
Definition LHEF.h:2433
int IDPRUP
Definition LHEF.h:2574
std::vector< std::pair< int, int > > ICOLUP
Definition LHEF.h:2625
void reset()
Definition LHEF.h:2423
std::pair< double, double > XPDWUP
Definition LHEF.h:2587
PDFInfo pdfinfo
Definition LHEF.h:2674
std::vector< std::vector< double > > PUP
Definition LHEF.h:2631
std::string junk
Definition LHEF.h:2712
std::vector< double > XMAXUP
Definition LHEF.h:2003
int dprec
Definition LHEF.h:2075
std::vector< WeightGroup > weightgroup
Definition LHEF.h:2060
void resize()
Definition LHEF.h:1906
std::vector< Generator > generators
Definition LHEF.h:2045
void print(std::ostream &file) const
Definition LHEF.h:1784
std::vector< int > LPRUP
Definition LHEF.h:2008
XSecInfo & getXSecInfo(std::string weightname="")
Definition LHEF.h:1933
int IDWTUP
Definition LHEF.h:1981
XSecInfos xsecinfos
Definition LHEF.h:2013
HEPRUP(const HEPRUP &)=default
std::pair< double, double > EBMUP
Definition LHEF.h:1962
int NPRUP
Definition LHEF.h:1986
std::vector< EventFile > eventfiles
Definition LHEF.h:2019
int weightIndex(const std::string &name) const
Definition LHEF.h:1916
std::pair< int, int > PDFGUP
Definition LHEF.h:1968
std::map< long, MergeInfo > mergeinfo
Definition LHEF.h:2039
HEPRUP & operator=(const HEPRUP &)=default
int nWeights() const
Definition LHEF.h:1925
std::vector< WeightInfo > weightinfo
Definition LHEF.h:2050
std::map< long, ProcInfo > procinfo
Definition LHEF.h:2034
std::map< std::string, int > weightmap
Definition LHEF.h:2055
int version
Definition LHEF.h:2070
HEPRUP(const XMLTag &tagin, int versin)
Definition LHEF.h:1672
std::map< std::string, std::set< long > > ptypes
Definition LHEF.h:2029
void resize(int nrup)
Definition LHEF.h:1896
void clear()
Definition LHEF.h:1881
std::pair< int, int > PDFSUP
Definition LHEF.h:1974
std::vector< Cut > cuts
Definition LHEF.h:2024
std::pair< long, long > IDBMUP
Definition LHEF.h:1957
std::vector< double > XSECUP
Definition LHEF.h:1991
const XSecInfo & getXSecInfo(std::string weightname="") const
Definition LHEF.h:1944
std::string junk
Definition LHEF.h:2065
std::vector< double > XERRUP
Definition LHEF.h:1997
std::string weightNameHepMC(int i) const
Definition LHEF.h:1770
void init()
Definition LHEF.h:2806
int currevent
Definition LHEF.h:3067
std::string outsideBlock
Definition LHEF.h:3037
std::ios_base::iostate file_rdstate() const
Definition LHEF.h:3023
Reader(std::istream &is)
Definition LHEF.h:2775
Reader(const Reader &)
std::string eventComments
Definition LHEF.h:3062
int currfileevent
Definition LHEF.h:3078
int curreventfile
Definition LHEF.h:3073
HEPEUP hepeup
Definition LHEF.h:3057
void openeventfile(int ifile)
Definition LHEF.h:2952
HEPRUP heprup
Definition LHEF.h:3047
std::istream * file
Definition LHEF.h:2994
std::istream * initfile
Definition LHEF.h:2999
bool currentFind(std::string str) const
Definition LHEF.h:2977
bool readEvent()
Definition LHEF.h:2887
std::string headerBlock
Definition LHEF.h:3042
std::ifstream intstream
Definition LHEF.h:2987
std::string initComments
Definition LHEF.h:3052
int version
Definition LHEF.h:3031
std::string currentLine
Definition LHEF.h:3009
bool getline()
Definition LHEF.h:2970
std::ifstream efile
Definition LHEF.h:3004
Reader & operator=(const Reader &)
std::string dirpath
Definition LHEF.h:3083
Reader(std::string filename)
Definition LHEF.h:2791
std::ios_base::iostate initfile_rdstate() const
Definition LHEF.h:3015
void init()
Definition LHEF.h:3207
std::ofstream efile
Definition LHEF.h:3313
int currfileevent
Definition LHEF.h:3329
int curreventfile
Definition LHEF.h:3324
HEPEUP hepeup
Definition LHEF.h:3346
Writer(const Writer &)
std::ostream & initComments()
Definition LHEF.h:3173
void initComments(const std::string &a)
Definition LHEF.h:3193
std::ostream * file
Definition LHEF.h:3303
void eventComments(const std::string &a)
Definition LHEF.h:3200
std::ostream & headerBlock()
Definition LHEF.h:3166
std::ostringstream initStream
Definition LHEF.h:3360
HEPRUP heprup
Definition LHEF.h:3340
std::ostringstream eventStream
Definition LHEF.h:3365
std::ofstream intstream
Definition LHEF.h:3297
int lastevent
Definition LHEF.h:3318
std::ostream & eventComments()
Definition LHEF.h:3180
void headerBlock(const std::string &a)
Definition LHEF.h:3186
void writeinit()
Definition LHEF.h:3246
Writer(std::string filename)
Definition LHEF.h:3141
std::ostringstream headerStream
Definition LHEF.h:3355
std::string dirpath
Definition LHEF.h:3334
bool openeventfile(int ifile)
Definition LHEF.h:3217
std::ostream * initfile
Definition LHEF.h:3308
Writer & operator=(const Writer &)
Writer(std::ostream &os)
Definition LHEF.h:3133
void writeEvent()
Definition LHEF.h:3277
Les Houches event file classes.
Definition LHEF.h:41
std::string hashline(std::string s)
Definition LHEF.h:345
std::map< std::string, XSecInfo > XSecInfos
Definition LHEF.h:629
OAttr< T > oattr(std::string name, const T &value)
Definition LHEF.h:70
std::ostream & operator<<(std::ostream &os, const OAttr< T > &oa)
Definition LHEF.h:78
int p0
Definition LHEF.h:1312
void print(std::ostream &file) const
Definition LHEF.h:1290
Clus(const XMLTag &tag)
Definition LHEF.h:1278
int p2
Definition LHEF.h:1307
double alphas
Definition LHEF.h:1323
double scale
Definition LHEF.h:1317
int p1
Definition LHEF.h:1302
double max
Definition LHEF.h:926
std::set< long > p2
Definition LHEF.h:912
void print(std::ostream &file) const
Definition LHEF.h:740
bool match(long id1, long id2=0) const
Definition LHEF.h:767
Cut(const XMLTag &tag, const std::map< std::string, std::set< long > > &ptypes)
Definition LHEF.h:698
Cut()
Definition LHEF.h:692
std::string np2
Definition LHEF.h:917
bool outside(double value) const
Definition LHEF.h:890
std::string type
Definition LHEF.h:897
bool passCuts(const std::vector< long > &id, const std::vector< std::vector< double > > &p) const
Definition LHEF.h:783
static double rap(const std::vector< double > &p)
Definition LHEF.h:864
std::set< long > p1
Definition LHEF.h:902
double min
Definition LHEF.h:922
static double eta(const std::vector< double > &p)
Definition LHEF.h:850
static double deltaR(const std::vector< double > &p1, const std::vector< double > &p2)
Definition LHEF.h:878
std::string np1
Definition LHEF.h:907
EventFile(const XMLTag &tag)
Definition LHEF.h:645
void print(std::ostream &file) const
Definition LHEF.h:658
long ntries
Definition LHEF.h:680
std::string filename
Definition LHEF.h:670
EventGroup & operator=(const EventGroup &)
Definition LHEF.h:2735
void clear()
Definition LHEF.h:2719
void print(std::ostream &file) const
Definition LHEF.h:506
Generator(const XMLTag &tag)
Definition LHEF.h:497
std::string version
Definition LHEF.h:522
std::string name
Definition LHEF.h:517
void print(std::ostream &file) const
Definition LHEF.h:1031
double mergingscale
Definition LHEF.h:1047
MergeInfo(const XMLTag &tag)
Definition LHEF.h:1020
OAttr(const std::string &n, const T &v)
Definition LHEF.h:52
std::string name
Definition LHEF.h:57
void print(std::ostream &file) const
Definition LHEF.h:1584
PDFInfo(const XMLTag &tag, double defscale=-1.0)
Definition LHEF.h:1570
double scale
Definition LHEF.h:1629
double SCALUP
Definition LHEF.h:1634
double x1
Definition LHEF.h:1609
double x2
Definition LHEF.h:1614
double xf1
Definition LHEF.h:1619
PDFInfo(double defscale=-1.0)
Definition LHEF.h:1563
double xf2
Definition LHEF.h:1624
std::string rscheme
Definition LHEF.h:998
ProcInfo(const XMLTag &tag)
Definition LHEF.h:943
int qcdorder
Definition LHEF.h:983
void print(std::ostream &file) const
Definition LHEF.h:958
std::string fscheme
Definition LHEF.h:993
int eworder
Definition LHEF.h:988
std::string scheme
Definition LHEF.h:1003
void print(std::ostream &file) const
Definition LHEF.h:1373
Scale(std::string st="veto", int emtr=0, double sc=0.0)
Definition LHEF.h:1336
std::set< int > emitted
Definition LHEF.h:1422
int emitter
Definition LHEF.h:1412
std::string stype
Definition LHEF.h:1405
std::set< int > recoilers
Definition LHEF.h:1417
double scale
Definition LHEF.h:1427
Scale(const XMLTag &tag)
Definition LHEF.h:1342
double getScale(std::string st, int pdgem, int emr, int rec) const
Definition LHEF.h:1507
void print(std::ostream &file) const
Definition LHEF.h:1478
double mups
Definition LHEF.h:1541
Scales(double defscale=-1.0, int npart=0)
Definition LHEF.h:1439
double muf
Definition LHEF.h:1530
bool hasInfo() const
Definition LHEF.h:1470
double SCALUP
Definition LHEF.h:1546
Scales(const XMLTag &tag, double defscale=-1.0, int npart=0)
Definition LHEF.h:1447
std::vector< Scale > scales
Definition LHEF.h:1551
double mur
Definition LHEF.h:1535
bool getattr(const std::string &n, double &v, bool erase=true)
Definition LHEF.h:386
bool getattr(const std::string &n, int &v, bool erase=true)
Definition LHEF.h:428
void closetag(std::ostream &file, const std::string &tag) const
Definition LHEF.h:463
bool getattr(const std::string &n, long &v, bool erase=true)
Definition LHEF.h:414
XMLTag::AttributeMap attributes
Definition LHEF.h:475
void printattrs(std::ostream &file) const
Definition LHEF.h:453
static std::string yes()
Definition LHEF.h:485
TagBase(const AttributeMap &attr, const std::string &conts=std::string())
Definition LHEF.h:377
bool getattr(const std::string &n, bool &v, bool erase=true)
Definition LHEF.h:400
XMLTag::AttributeMap AttributeMap
Definition LHEF.h:367
bool getattr(const std::string &n, std::string &v, bool erase=true)
Definition LHEF.h:442
std::string contents
Definition LHEF.h:480
std::string type
Definition LHEF.h:1174
std::string combine
Definition LHEF.h:1179
WeightGroup(const XMLTag &tag, int groupIndex, std::vector< WeightInfo > &wiv)
Definition LHEF.h:1157
void print(std::ostream &file) const
Definition LHEF.h:1088
WeightInfo(const XMLTag &tag)
Definition LHEF.h:1071
std::string name
Definition LHEF.h:1118
Weight(const XMLTag &tag)
Definition LHEF.h:1197
std::vector< int > indices
Definition LHEF.h:1260
void print(std::ostream &file) const
Definition LHEF.h:1215
double born
Definition LHEF.h:1245
bool iswgt
Definition LHEF.h:1240
std::string name
Definition LHEF.h:1235
double sudakov
Definition LHEF.h:1250
std::vector< double > weights
Definition LHEF.h:1255
bool getattr(const std::string &n, int &v) const
Definition LHEF.h:176
static const pos_t end
Definition LHEF.h:104
AttributeMap attr
Definition LHEF.h:126
bool getattr(const std::string &n, double &v) const
Definition LHEF.h:142
std::map< std::string, std::string > AttributeMap
Definition LHEF.h:99
std::string name
Definition LHEF.h:121
std::string::size_type pos_t
Definition LHEF.h:94
static std::vector< XMLTag * > findXMLTags(std::string str, std::string *leftover=nullptr)
Definition LHEF.h:200
static void deleteAll(std::vector< XMLTag * > &tags)
Definition LHEF.h:310
bool getattr(const std::string &n, long &v) const
Definition LHEF.h:165
void print(std::ostream &os) const
Definition LHEF.h:319
std::string contents
Definition LHEF.h:136
bool getattr(const std::string &n, bool &v) const
Definition LHEF.h:154
std::vector< XMLTag * > tags
Definition LHEF.h:131
bool getattr(const std::string &n, std::string &v) const
Definition LHEF.h:187
void print(std::ostream &file) const
Definition LHEF.h:564
double meanweight
Definition LHEF.h:607
double xsecerr
Definition LHEF.h:597
XSecInfo(const XMLTag &tag)
Definition LHEF.h:540
double maxweight
Definition LHEF.h:602
long neve
Definition LHEF.h:582
long ntries
Definition LHEF.h:587
bool varweights
Definition LHEF.h:617
bool negweights
Definition LHEF.h:612
std::string weightname
Definition LHEF.h:622
double totxsec
Definition LHEF.h:592