LHEF  3.0(beta)
LHEF.h
1 // -*- C++ -*-
2 #ifndef HEPMC_LHEF_H
3 #define HEPMC_LHEF_H
4 //
5 // This is the declaration of the Les Houches Event File classes,
6 // implementing a simple C++ parser/writer for Les Houches Event files.
7 // Copyright (C) 2009-2016 Leif Lonnblad
8 //
9 // The code is licenced under version 2 of the GPL, see COPYING for
10 // details. Please respect the MCnet academic guidelines, see
11 // http://montecarlonet.org/index.php?p=Publications/Guidelines for
12 // 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 
29 namespace LHEF {
30 
34 template <typename T>
35 struct OAttr {
36 
40  OAttr(std::string n, const T & v): name(n), val(v) {}
41 
45  std::string name;
46 
50  T val;
51 
52 };
53 
57 template <typename T>
58 OAttr<T> oattr(std::string name, const T & value) {
59  return OAttr<T>(name, value);
60 }
61 
65 template <typename T>
66 std::ostream & operator<<(std::ostream & os, const OAttr<T> & oa) {
67  os << " " << oa.name << "=\"" << oa.val << "\"";
68  return os;
69 }
70 
77 struct XMLTag {
78 
82  typedef std::string::size_type pos_t;
83 
87  typedef std::map<std::string,std::string> AttributeMap;
88 
92  static const pos_t end = std::string::npos;
93 
97  XMLTag() {}
98 
103  for ( int i = 0, N = tags.size(); i < N; ++i ) delete tags[i];
104  }
105 
109  std::string name;
110 
115 
119  std::vector<XMLTag*> tags;
120 
124  std::string contents;
125 
130  bool getattr(std::string n, double & v) const {
131  AttributeMap::const_iterator it = attr.find(n);
132  if ( it == attr.end() ) return false;
133  v = std::atof(it->second.c_str());
134  return true;
135  }
136 
142  bool getattr(std::string n, bool & v) const {
143  AttributeMap::const_iterator it = attr.find(n);
144  if ( it == attr.end() ) return false;
145  if ( it->second == "yes" ) v = true;
146  return true;
147  }
148 
153  bool getattr(std::string n, long & v) const {
154  AttributeMap::const_iterator it = attr.find(n);
155  if ( it == attr.end() ) return false;
156  v = std::atoi(it->second.c_str());
157  return true;
158  }
159 
164  bool getattr(std::string n, int & v) const {
165  AttributeMap::const_iterator it = attr.find(n);
166  if ( it == attr.end() ) return false;
167  v = int(std::atoi(it->second.c_str()));
168  return true;
169  }
170 
175  bool getattr(std::string n, std::string & v) const {
176  AttributeMap::const_iterator it = attr.find(n);
177  if ( it == attr.end() ) return false;
178  v = it->second;
179  return true;
180  }
181 
188  static std::vector<XMLTag*> findXMLTags(std::string str,
189  std::string * leftover = 0) {
190  std::vector<XMLTag*> tags;
191  pos_t curr = 0;
192 
193  while ( curr != end ) {
194 
195  // Find the first tag
196  pos_t begin = str.find("<", curr);
197 
198  // Check for comments
199  if ( str.find("<!--", curr) == begin ) {
200  pos_t endcom = str.find("-->", begin);
201  tags.push_back(new XMLTag());
202  if ( endcom == end ) {
203  tags.back()->contents = str.substr(curr);
204  if ( leftover ) *leftover += str.substr(curr);
205  return tags;
206  }
207  tags.back()->contents = str.substr(curr, endcom - curr);
208  if ( leftover ) *leftover += str.substr(curr, endcom - curr);
209  curr = endcom;
210  continue;
211  }
212 
213  if ( begin != curr ) {
214  tags.push_back(new XMLTag());
215  tags.back()->contents = str.substr(curr, begin - curr);
216  if ( leftover ) *leftover += str.substr(curr, begin - curr);
217  }
218  if ( begin == end || begin > str.length() - 3 || str[begin + 1] == '/' )
219  return tags;
220 
221  pos_t close = str.find(">", curr);
222  if ( close == end ) return tags;
223 
224  // find the tag name.
225  curr = str.find_first_of(" \t\n/>", begin);
226  tags.push_back(new XMLTag());
227  tags.back()->name = str.substr(begin + 1, curr - begin - 1);
228 
229  while ( true ) {
230 
231  // Now skip some white space to see if we can find an attribute.
232  curr = str.find_first_not_of(" \t\n", curr);
233  if ( curr == end || curr >= close ) break;
234 
235  pos_t tend = str.find_first_of("= \t\n", curr);
236  if ( tend == end || tend >= close ) break;
237 
238  std::string name = str.substr(curr, tend - curr);
239  curr = str.find("=", curr) + 1;
240 
241  // OK now find the beginning and end of the atribute.
242  curr = str.find_first_of("\"'", curr);
243  if ( curr == end || curr >= close ) break;
244  char quote = str[curr];
245  pos_t bega = ++curr;
246  curr = str.find(quote, curr);
247  while ( curr != end && str[curr - 1] == '\\' )
248  curr = str.find(quote, curr + 1);
249 
250  std::string value = str.substr(bega, curr == end? end: curr - bega);
251 
252  tags.back()->attr[name] = value;
253 
254  ++curr;
255 
256  }
257 
258  curr = close + 1;
259  if ( str[close - 1] == '/' ) continue;
260 
261  pos_t endtag = str.find("</" + tags.back()->name + ">", curr);
262  if ( endtag == end ) {
263  tags.back()->contents = str.substr(curr);
264  curr = endtag;
265  } else {
266  tags.back()->contents = str.substr(curr, endtag - curr);
267  curr = endtag + tags.back()->name.length() + 3;
268  }
269 
270  std::string leftovers;
271  tags.back()->tags = findXMLTags(tags.back()->contents, &leftovers);
272  if ( leftovers.find_first_not_of(" \t\n") == end ) leftovers="";
273  tags.back()->contents = leftovers;
274 
275  }
276  return tags;
277 
278  }
279 
283  static void deleteAll(std::vector<XMLTag*> & tags) {
284  while ( tags.size() && tags.back() ) {
285  delete tags.back();
286  tags.pop_back();
287  }
288  }
292  void print(std::ostream & os) const {
293  if ( name.empty() ) {
294  os << contents;
295  return;
296  }
297  os << "<" << name;
298  for ( AttributeMap::const_iterator it = attr.begin();
299  it != attr.end(); ++it )
300  os << oattr(it->first, it->second);
301  if ( contents.empty() && tags.empty() ) {
302  os << "/>" << std::endl;
303  return;
304  }
305  os << ">";
306  for ( int i = 0, N = tags.size(); i < N; ++i )
307  tags[i]->print(os);
308 
309  os << contents << "</" << name << ">" << std::endl;
310  }
311 
312 };
313 
318 inline std::string hashline(std::string s) {
319  std::string ret;
320  std::istringstream is(s);
321  std::string ss;
322  while ( getline(is, ss) ) {
323  if ( ss.empty() ) continue;
324  if ( ss.find_first_not_of(" \t") == std::string::npos ) continue;
325  if ( ss.find('#') == std::string::npos ||
326  ss.find('#') != ss.find_first_not_of(" \t") ) ss = "# " + ss;
327  ret += ss + '\n';
328  }
329  return ret;
330 }
331 
335 struct TagBase {
336 
341 
345  TagBase() {}
346 
350  TagBase(const AttributeMap & attr, std::string conts = std::string())
351  : attributes(attr), contents(conts) {}
352 
359  bool getattr(std::string n, double & v, bool erase = true) {
360  AttributeMap::iterator it = attributes.find(n);
361  if ( it == attributes.end() ) return false;
362  v = std::atof(it->second.c_str());
363  if ( erase) attributes.erase(it);
364  return true;
365  }
366 
373  bool getattr(std::string n, bool & v, bool erase = true) {
374  AttributeMap::iterator it = attributes.find(n);
375  if ( it == attributes.end() ) return false;
376  if ( it->second == "yes" ) v = true;
377  if ( erase) attributes.erase(it);
378  return true;
379  }
380 
387  bool getattr(std::string n, long & v, bool erase = true) {
388  AttributeMap::iterator it = attributes.find(n);
389  if ( it == attributes.end() ) return false;
390  v = std::atoi(it->second.c_str());
391  if ( erase) attributes.erase(it);
392  return true;
393  }
394 
401  bool getattr(std::string n, int & v, bool erase = true) {
402  AttributeMap::iterator it = attributes.find(n);
403  if ( it == attributes.end() ) return false;
404  v = int(std::atoi(it->second.c_str()));
405  if ( erase) attributes.erase(it);
406  return true;
407  }
408 
415  bool getattr(std::string n, std::string & v, bool erase = true) {
416  AttributeMap::iterator it = attributes.find(n);
417  if ( it == attributes.end() ) return false;
418  v = it->second;
419  if ( erase) attributes.erase(it);
420  return true;
421  }
422 
426  void printattrs(std::ostream & file) const {
427  for ( AttributeMap::const_iterator it = attributes.begin();
428  it != attributes.end(); ++ it )
429  file << oattr(it->first, it->second);
430  }
431 
436  void closetag(std::ostream & file, std::string tag) const {
437  if ( contents.empty() )
438  file << "/>\n";
439  else if ( contents.find('\n') != std::string::npos )
440  file << ">\n" << contents << "\n</" << tag << ">\n";
441  else
442  file << ">" << contents << "</" << tag << ">\n";
443  }
444 
449 
453  std::string contents;
454 
458  static std::string yes() { return "yes"; }
459 
460 };
461 
465 struct Generator : public TagBase {
466 
470  Generator(const XMLTag & tag)
471  : TagBase(tag.attr, tag.contents) {
472  getattr("name", name);
473  getattr("version", version);
474  }
475 
479  void print(std::ostream & file) const {
480  file << "<generator";
481  if ( !name.empty() ) file << oattr("name", name);
482  if ( !version.empty() ) file << oattr("version", version);
483  printattrs(file);
484  closetag(file, "generator");
485  }
486 
490  std::string name;
491 
495  std::string version;
496 
497 };
498 
502 struct XSecInfo : public TagBase {
503 
507  XSecInfo(): neve(-1), totxsec(0.0), maxweight(1.0), meanweight(1.0),
508  negweights(false), varweights(false) {}
509 
513  XSecInfo(const XMLTag & tag)
514  : TagBase(tag.attr, tag.contents), neve(-1), totxsec(0.0),
515  maxweight(1.0), meanweight(1.0), negweights(false), varweights(false) {
516  if ( !getattr("neve", neve) )
517  throw std::runtime_error("Found xsecinfo tag without neve attribute "
518  "in Les Houches Event File.");
519  if ( !getattr("totxsec", totxsec) )
520  throw std::runtime_error("Found xsecinfo tag without totxsec "
521  "attribute in Les Houches Event File.");
522  getattr("maxweight", maxweight);
523  getattr("meanweight", meanweight);
524  getattr("negweights", negweights);
525  getattr("varweights", varweights);
526 
527  }
528 
532  void print(std::ostream & file) const {
533  file << "<xsecinfo" << oattr("neve", neve) << oattr("totxsec", totxsec)
534  << oattr("maxweight", maxweight) << oattr("meanweight", meanweight);
535  if ( negweights ) file << oattr("negweights", yes());
536  if ( varweights ) file << oattr("varweights", yes());
537  printattrs(file);
538  closetag(file, "xsecinfo");
539  }
540 
544  long neve;
545 
549  double totxsec;
550 
554  double maxweight;
555 
559  double meanweight;
560 
565 
570 
571 
572 };
573 
577 struct Cut : public TagBase {
578 
582  Cut(): min(-0.99*std::numeric_limits<double>::max()),
583  max(0.99*std::numeric_limits<double>::max()) {}
584 
588  Cut(const XMLTag & tag,
589  const std::map<std::string,std::set<long> >& ptypes)
590  : TagBase(tag.attr),
591  min(-0.99*std::numeric_limits<double>::max()),
592  max(0.99*std::numeric_limits<double>::max()) {
593  if ( !getattr("type", type) )
594  throw std::runtime_error("Found cut tag without type attribute "
595  "in Les Houches file");
596  long tmp;
597  if ( tag.getattr("p1", np1) ) {
598  if ( ptypes.find(np1) != ptypes.end() ) {
599  p1 = ptypes.find(np1)->second;
600  attributes.erase("p1");
601  } else {
602  getattr("p1", tmp);
603  p1.insert(tmp);
604  np1 = "";
605  }
606  }
607  if ( tag.getattr("p2", np2) ) {
608  if ( ptypes.find(np2) != ptypes.end() ) {
609  p2 = ptypes.find(np2)->second;
610  attributes.erase("p2");
611  } else {
612  getattr("p2", tmp);
613  p2.insert(tmp);
614  np2 = "";
615  }
616  }
617 
618  std::istringstream iss(tag.contents);
619  iss >> min;
620  if ( iss >> max ) {
621  if ( min >= max )
622  min = -0.99*std::numeric_limits<double>::max();
623  } else
624  max = 0.99*std::numeric_limits<double>::max();
625  }
626 
630  void print(std::ostream & file) const {
631  file << "<cut" << oattr("type", type);
632  if ( !np1.empty() )
633  file << oattr("p1", np1);
634  else
635  if ( p1.size() == 1 ) file << oattr("p1", *p1.begin());
636  if ( !np2.empty() )
637  file << oattr("p2", np2);
638  else
639  if ( p2.size() == 1 ) file << oattr("p2", *p2.begin());
640  printattrs(file);
641 
642  file << ">";
643  if ( min > -0.9*std::numeric_limits<double>::max() )
644  file << min;
645  else
646  file << max;
647  if ( max < 0.9*std::numeric_limits<double>::max() )
648  file << " " << max;
649  if ( !contents.empty() ) file << std::endl << contents << std::endl;
650  file << "</cut>" << std::endl;
651  }
652 
657  bool match(long id1, long id2 = 0) const {
658  std::pair<bool,bool> ret(false, false);
659  if ( !id2 ) ret.second = true;
660  if ( !id1 ) ret.first = true;
661  if ( p1.find(0) != p1.end() ) ret.first = true;
662  if ( p1.find(id1) != p1.end() ) ret.first = true;
663  if ( p2.find(0) != p2.end() ) ret.second = true;
664  if ( p2.find(id2) != p2.end() ) ret.second = true;
665  return ret.first && ret.second;
666  }
667 
673  bool passCuts(const std::vector<long> & id,
674  const std::vector< std::vector<double> >& p ) const {
675  if ( ( type == "m" && !p2.size() ) || type == "kt" || type == "eta" ||
676  type == "y" || type == "E" ) {
677  for ( int i = 0, N = id.size(); i < N; ++i )
678  if ( match(id[i]) ) {
679  if ( type == "m" ) {
680  double v = p[i][4]*p[i][4] - p[i][3]*p[i][3] - p[i][2]*p[i][2]
681  - p[i][1]*p[i][1];
682  v = v >= 0.0? std::sqrt(v): -std::sqrt(-v);
683  if ( outside(v) ) return false;
684  }
685  else if ( type == "kt" ) {
686  if ( outside(std::sqrt(p[i][2]*p[i][2] + p[i][1]*p[i][1])) )
687  return false;
688  }
689  else if ( type == "E" ) {
690  if ( outside(p[i][4]) ) return false;
691  }
692  else if ( type == "eta" ) {
693  if ( outside(eta(p[i])) ) return false;
694  }
695  else if ( type == "y" ) {
696  if ( outside(rap(p[i])) ) return false;
697  }
698  }
699  }
700  else if ( type == "m" || type == "deltaR" ) {
701  for ( int i = 1, N = id.size(); i < N; ++i )
702  for ( int j = 0; j < i; ++j )
703  if ( match(id[i], id[j]) || match(id[j], id[i]) ) {
704  if ( type == "m" ) {
705  double v = (p[i][4] + p[j][4])*(p[i][4] + p[j][4])
706  - (p[i][3] + p[j][3])*(p[i][3] + p[j][3])
707  - (p[i][2] + p[j][2])*(p[i][2] + p[j][2])
708  - (p[i][1] + p[j][1])*(p[i][1] + p[j][1]);
709  v = v >= 0.0? std::sqrt(v): -std::sqrt(-v);
710  if ( outside(v) ) return false;
711  }
712  else if ( type == "deltaR" ) {
713  if ( outside(deltaR(p[i], p[j])) ) return false;
714  }
715  }
716  }
717  else if ( type == "ETmiss" ) {
718  double x = 0.0;
719  double y = 0.0;
720  for ( int i = 0, N = id.size(); i < N; ++i )
721  if ( match(id[i]) && !match(0, id[i]) ) {
722  x += p[i][1];
723  y += p[i][2];
724  }
725  if ( outside(std::sqrt(x*x + y*y)) ) return false;
726  }
727  else if ( type == "HT" ) {
728  double pt = 0.0;
729  for ( int i = 0, N = id.size(); i < N; ++i )
730  if ( match(id[i]) && !match(0, id[i]) )
731  pt += std::sqrt(p[i][1]*p[i][1] + p[i][2]*p[i][2]);
732  if ( outside(pt) ) return false;
733  }
734  return true;
735  }
736 
740  static double eta(const std::vector<double> & p) {
741  double pt2 = p[2]*p[2] + p[1]*p[1];
742  if ( pt2 != 0.0 ) {
743  double dum = std::sqrt(pt2 + p[3]*p[3]) + p[3];
744  if ( dum != 0.0 )
745  return std::log(dum/std::sqrt(pt2));
746  }
747  return p[3] < 0.0? -std::numeric_limits<double>::max():
748  std::numeric_limits<double>::max();
749  }
750 
754  static double rap(const std::vector<double> & p) {
755  double pt2 = p[5]*p[5] + p[2]*p[2] + p[1]*p[1];
756  if ( pt2 != 0.0 ) {
757  double dum = std::sqrt(pt2 + p[3]*p[3]) + p[3];
758  if ( dum != 0.0 )
759  return std::log(dum/std::sqrt(pt2));
760  }
761  return p[3] < 0.0? -std::numeric_limits<double>::max():
762  std::numeric_limits<double>::max();
763  }
764 
768  static double deltaR(const std::vector<double> & p1,
769  const std::vector<double> & p2) {
770  double deta = eta(p1) - eta(p2);
771  double dphi = std::atan2(p1[1], p1[2]) - std::atan2(p2[1], p2[2]);
772  if ( dphi > M_PI ) dphi -= 2.0*M_PI;
773  if ( dphi < -M_PI ) dphi += 2.0*M_PI;
774  return std::sqrt(dphi*dphi + deta*deta);
775  }
776 
780  bool outside(double value) const {
781  return value < min || value >= max;
782  }
783 
787  std::string type;
788 
792  std::set<long> p1;
793 
797  std::string np1;
798 
802  std::set<long> p2;
803 
807  std::string np2;
808 
812  double min;
816  double max;
817 
818 };
819 
823 struct ProcInfo : public TagBase {
824 
828  ProcInfo(): iproc(0), loops(0), qcdorder(-1), eworder(-1) {}
829 
833  ProcInfo(const XMLTag & tag)
834  : TagBase(tag.attr, tag.contents),
835  iproc(0), loops(0), qcdorder(-1), eworder(-1) {
836  getattr("iproc", iproc);
837  getattr("loops", loops);
838  getattr("qcdorder", qcdorder);
839  getattr("eworder", eworder);
840  getattr("rscheme", rscheme);
841  getattr("fscheme", fscheme);
842  getattr("scheme", scheme);
843  }
844 
848  void print(std::ostream & file) const {
849  file << "<procinfo" << oattr("iproc", iproc);
850  if ( loops >= 0 ) file << oattr("loops", loops);
851  if ( qcdorder >= 0 ) file << oattr("qcdorder", qcdorder);
852  if ( eworder >= 0 ) file<< oattr("eworder", eworder);
853  if ( !rscheme.empty() ) file << oattr("rscheme", rscheme);
854  if ( !fscheme.empty() ) file << oattr("fscheme", fscheme);
855  if ( !scheme.empty() ) file << oattr("scheme", scheme);
856  printattrs(file);
857  closetag(file, "procinfo");
858  }
859 
863  int iproc;
864 
868  int loops;
869 
873  int qcdorder;
874 
878  int eworder;
879 
883  std::string fscheme;
884 
888  std::string rscheme;
889 
893  std::string scheme;
894 
895 };
896 
900 struct MergeInfo : public TagBase {
901 
905  MergeInfo(): iproc(0), mergingscale(0.0), maxmult(false) {}
906 
910  MergeInfo(const XMLTag & tag)
911  : TagBase(tag.attr, tag.contents),
912  iproc(0), mergingscale(0.0), maxmult(false) {
913  getattr("iproc", iproc);
914  getattr("mergingscale", mergingscale);
915  getattr("maxmult", maxmult);
916  }
917 
921  void print(std::ostream & file) const {
922  file << "<mergeinfo" << oattr("iproc", iproc);
923  if ( mergingscale > 0.0 ) file << oattr("mergingscale", mergingscale);
924  if ( maxmult ) file << oattr("maxmult", yes());
925  printattrs(file);
926  closetag(file, "mergeinfo");
927  }
928 
932  int iproc;
933 
937  double mergingscale;
938 
942  bool maxmult;
943 
944 };
945 
950 struct WeightInfo : public TagBase {
951 
955  WeightInfo(): inGroup(-1), isrwgt(false),
956  muf(1.0), mur(1.0), pdf(0), pdf2(0) {}
957 
961  WeightInfo(const XMLTag & tag)
962  : TagBase(tag.attr, tag.contents),
963  inGroup(-1), isrwgt(tag.name == "weight"),
964  muf(1.0), mur(1.0), pdf(0), pdf2(0) {
965  getattr("mur", mur);
966  getattr("muf", muf);
967  getattr("pdf", pdf);
968  getattr("pdf2", pdf2);
969  if ( isrwgt )
970  getattr("id", name);
971  else
972  getattr("name", name);
973  }
974 
978  void print(std::ostream & file) const {
979 
980  if ( isrwgt )
981  file << "<weight" << oattr("id", name);
982  else
983  file << "<weightinfo" << oattr("name", name);
984  if ( mur != 1.0 ) file << oattr("mur", mur);
985  if ( muf != 1.0 ) file << oattr("muf", muf);
986  if ( pdf != 0 ) file << oattr("pdf", pdf);
987  if ( pdf2 != 0 ) file << oattr("pdf2", pdf2);
988  printattrs(file);
989  if ( isrwgt )
990  closetag(file, "weight");
991  else
992  closetag(file, "weightinfo");
993  }
994 
998  int inGroup;
999 
1003  bool isrwgt;
1004 
1008  std::string name;
1009 
1013  double muf;
1014 
1018  double mur;
1019 
1023  long pdf;
1024 
1029  long pdf2;
1030 
1031 };
1032 
1036 struct WeightGroup : public TagBase {
1037 
1042 
1047  WeightGroup(const XMLTag & tag, int groupIndex, std::vector<WeightInfo> & wiv)
1048  : TagBase(tag.attr) {
1049  getattr("type", type);
1050  getattr("combine", combine);
1051  for ( int i = 0, N = tag.tags.size(); i < N; ++i ) {
1052  if ( tag.tags[i]->name == "weight" ||
1053  tag.tags[i]->name == "weightinfo" ) {
1054  WeightInfo wi(*tag.tags[i]);
1055  wi.inGroup = groupIndex;
1056  wiv.push_back(wi);
1057  }
1058  }
1059  }
1060 
1064  std::string type;
1065 
1069  std::string combine;
1070 
1071 };
1072 
1073 
1077 struct Weight : public TagBase {
1078 
1082  Weight(): iswgt(false), born(0.0), sudakov(0.0) {}
1083 
1087  Weight(const XMLTag & tag)
1088  : TagBase(tag.attr, tag.contents),
1089  iswgt(tag.name == "wgt"), born(0.0), sudakov(0.0) {
1090  if ( iswgt )
1091  getattr("id", name);
1092  else
1093  getattr("name", name);
1094  getattr("born", born);
1095  getattr("sudakov", sudakov);
1096  std::istringstream iss(tag.contents);
1097  double w;
1098  while ( iss >> w ) weights.push_back(w);
1099  indices.resize(weights.size(), 0.0);
1100  }
1101 
1105  void print(std::ostream & file) const {
1106  if ( iswgt )
1107  file << "<wgt" << oattr("id", name);
1108  else {
1109  file << "<weight";
1110  if ( !name.empty() ) file << oattr("name", name);
1111  }
1112  if ( born != 0.0 ) file << oattr("born", born);
1113  if ( sudakov != 0.0 ) file << oattr("sudakov", sudakov);
1114  file << ">";
1115  for ( int j = 0, M = weights.size(); j < M; ++j ) file << " " << weights[j];
1116  file << "</weight>" << std::endl;
1117  }
1118 
1122  std::string name;
1123 
1127  bool iswgt;
1128 
1132  double born;
1133 
1137  double sudakov;
1138 
1142  mutable std::vector<double> weights;
1143 
1147  std::vector<int> indices;
1148 
1149 };
1150 
1155 struct Clus : public TagBase {
1156 
1160  Clus(): scale(-1.0), alphas(-1.0) {}
1161 
1165  Clus(const XMLTag & tag)
1166  : TagBase(tag.attr, tag.contents), scale(-1.0), alphas(-1.0) {
1167  getattr("scale", scale);
1168  getattr("alphas", alphas);
1169  std::istringstream iss(tag.contents);
1170  iss >> p1 >> p2;
1171  if ( !( iss >> p0 ) ) p0 = p1;
1172  }
1173 
1177  void print(std::ostream & file) const {
1178  file << "<clus";
1179  if ( scale > 0.0 ) file << oattr("scale", scale);
1180  if ( alphas > 0.0 ) file << oattr("alphas", alphas);
1181  file << ">" << p1 << " " << p2;
1182  if ( p1 != p0 ) file << " " << p0;
1183  file << "</clus>" << std::endl;
1184  }
1185 
1189  int p1;
1190 
1194  int p2;
1195 
1199  int p0;
1200 
1204  double scale;
1205 
1210  double alphas;
1211 
1212 };
1213 
1217 struct Scales : public TagBase {
1218 
1222  Scales(double defscale = -1.0)
1223  : muf(defscale), mur(defscale), mups(defscale), SCALUP(defscale) {}
1224 
1228  Scales(const XMLTag & tag, double defscale = -1.0)
1229  : TagBase(tag.attr, tag.contents),
1230  muf(defscale), mur(defscale), mups(defscale), SCALUP(defscale) {
1231  getattr("muf", muf);
1232  getattr("mur", mur);
1233  getattr("mups", mups);
1234  }
1235 
1239  void print(std::ostream & file) const {
1240  if ( muf == SCALUP && mur == SCALUP && mups == SCALUP ) return;
1241  file << "<scales";
1242  if ( muf != SCALUP ) file << oattr("muf", muf);
1243  if ( mur != SCALUP ) file << oattr("mur", mur);
1244  if ( mups != SCALUP ) file << oattr("mups", mups);
1245  printattrs(file);
1246  closetag(file, "scales");
1247  }
1248 
1252  double muf;
1253 
1257  double mur;
1258 
1263  double mups;
1264 
1268  double SCALUP;
1269 
1270 };
1271 
1275 struct PDFInfo : public TagBase {
1276 
1280  PDFInfo(double defscale = -1.0): p1(0), p2(0), x1(-1.0), x2(-1.0),
1281  xf1(-1.0), xf2(-1.0), scale(defscale), SCALUP(defscale) {}
1282 
1286  PDFInfo(const XMLTag & tag, double defscale = -1.0)
1287  : TagBase(tag.attr, tag.contents),
1288  p1(0), p2(0), x1(-1.0), x2(-1.0), xf1(-1.0), xf2(-1.0),
1289  scale(defscale), SCALUP(defscale) {
1290  getattr("scale", scale);
1291  getattr("p1", p1);
1292  getattr("p2", p2);
1293  getattr("x1", x1);
1294  getattr("x2", x2);
1295  }
1296 
1300  void print(std::ostream & file) const {
1301  if ( xf1 <= 0 ) return;
1302  file << "<pdfinfo";
1303  if ( p1 != 0 ) file << oattr("p1", p1);
1304  if ( p2 != 0 ) file << oattr("p2", p2);
1305  if ( x1 > 0 ) file << oattr("x1", x1);
1306  if ( x2 > 0 ) file << oattr("x2", x2);
1307  if ( scale != SCALUP ) file << oattr("scale", scale);
1308  printattrs(file);
1309  file << ">" << xf1 << " " << xf2 << "</pdfinfo>" << std::endl;
1310  }
1311 
1315  long p1;
1316 
1320  long p2;
1321 
1325  double x1;
1326 
1330  double x2;
1331 
1335  double xf1;
1336 
1340  double xf2;
1341 
1345  double scale;
1346 
1350  double SCALUP;
1351 
1352 };
1353 
1362 class HEPRUP : public TagBase {
1363 
1364 public:
1365 
1372  : IDWTUP(0), NPRUP(0), version(3) {}
1373 
1377  HEPRUP & operator=(const HEPRUP & x) {
1378  attributes = x.attributes;
1379  contents = x.contents;
1380  IDBMUP = x.IDBMUP;
1381  EBMUP = x.EBMUP;
1382  PDFGUP = x.PDFGUP;
1383  PDFSUP = x.PDFSUP;
1384  IDWTUP = x.IDWTUP;
1385  NPRUP = x.NPRUP;
1386  XSECUP = x.XSECUP;
1387  XERRUP = x.XERRUP;
1388  XMAXUP = x.XMAXUP;
1389  LPRUP = x.LPRUP;
1390  xsecinfo = x.xsecinfo;
1391  cuts = x.cuts;
1392  ptypes = x.ptypes;
1393  procinfo = x.procinfo;
1394  mergeinfo = x.mergeinfo;
1395  generators = x.generators;
1397  weightinfo = x.weightinfo;
1398  junk = x.junk;
1399  version = x.version;
1400  weightmap = x.weightmap;
1401  return *this;
1402  }
1403 
1407  HEPRUP(const XMLTag & tag, int versin)
1408  : TagBase(tag.attr, tag.contents), version(versin) {
1409 
1410  std::vector<XMLTag*> tags = tag.tags;
1411 
1412  // The first (anonymous) tag should just be the init block.
1413  std::istringstream iss(tags[0]->contents);
1414  if ( !( iss >> IDBMUP.first >> IDBMUP.second >> EBMUP.first >> EBMUP.second
1415  >> PDFGUP.first >> PDFGUP.second >> PDFSUP.first >> PDFSUP.second
1416  >> IDWTUP >> NPRUP ) ) {
1417  throw std::runtime_error("Could not parse init block "
1418  "in Les Houches Event File.");
1419  }
1420  resize();
1421 
1422  for ( int i = 0; i < NPRUP; ++i ) {
1423  if ( !( iss >> XSECUP[i] >> XERRUP[i] >> XMAXUP[i] >> LPRUP[i] ) ) {
1424  throw std::runtime_error("Could not parse processes in init block "
1425  "in Les Houches Event File.");
1426  }
1427  }
1428 
1429  for ( int i = 1, N = tags.size(); i < N; ++i ) {
1430  const XMLTag & tag = *tags[i];
1431 
1432  if ( tag.name.empty() ) junk += tag.contents;
1433 
1434  if ( tag.name == "initrwgt" ) {
1435  for ( int j = 0, M = tag.tags.size(); j < M; ++j ) {
1436  if ( tag.tags[j]->name == "weightgroup" )
1437  weightgroup.push_back(WeightGroup(*tag.tags[j], weightgroup.size(),
1438  weightinfo));
1439  if ( tag.tags[j]->name == "weight" )
1440  weightinfo.push_back(WeightInfo(*tag.tags[j]));
1441 
1442  }
1443  }
1444  if ( tag.name == "weightinfo" ) {
1445  weightinfo.push_back(WeightInfo(tag));
1446  }
1447  if ( tag.name == "weightgroup" ) {
1448  weightgroup.push_back(WeightGroup(tag, weightgroup.size(),
1449  weightinfo));
1450  }
1451  if ( tag.name == "xsecinfo" ) {
1452  xsecinfo = XSecInfo(tag);
1453  }
1454  if ( tag.name == "generator" ) {
1455  generators.push_back(Generator(tag));
1456  }
1457  else if ( tag.name == "cutsinfo" ) {
1458  for ( int j = 0, M = tag.tags.size(); j < M; ++j ) {
1459  XMLTag & ctag = *tag.tags[j];
1460 
1461  if ( ctag.name == "ptype" ) {
1462  std::string tname = ctag.attr["name"];
1463  long id;
1464  std::istringstream iss(ctag.contents);
1465  while ( iss >> id ) ptypes[tname].insert(id);
1466  }
1467  else if ( ctag.name == "cut" )
1468  cuts.push_back(Cut(ctag, ptypes));
1469  }
1470  }
1471  else if ( tag.name == "procinfo" ) {
1472  ProcInfo proc(tag);
1473  procinfo[proc.iproc] = proc;
1474  }
1475  else if ( tag.name == "mergeinfo" ) {
1476  MergeInfo merge(tag);
1477  mergeinfo[merge.iproc] = merge;
1478  }
1479 
1480  }
1481 
1482  weightmap.clear();
1483  for ( int i = 0, N = weightinfo.size(); i < N; ++i )
1484  weightmap[weightinfo[i].name] = i + 1;
1485 
1486  }
1487 
1491  ~HEPRUP() {}
1493 
1494 public:
1495 
1500  std::string weightNameHepMC(int i) const {
1501  std::string name;
1502  if ( i < 0 || i >= (int)weightinfo.size() ) return name;
1503  if ( weightinfo[i].inGroup >= 0 )
1504  name = weightgroup[weightinfo[i].inGroup].type + "/"
1505  + weightgroup[weightinfo[i].inGroup].combine + "/";
1506  name += weightinfo[i].name;
1507  return name;
1508  }
1509 
1510 
1514  void print(std::ostream & file) const {
1515 
1516  using std::setw;
1517 
1518  file << "<init>\n"
1519  << " " << setw(8) << IDBMUP.first
1520  << " " << setw(8) << IDBMUP.second
1521  << " " << setw(14) << EBMUP.first
1522  << " " << setw(14) << EBMUP.second
1523  << " " << setw(4) << PDFGUP.first
1524  << " " << setw(4) << PDFGUP.second
1525  << " " << setw(4) << PDFSUP.first
1526  << " " << setw(4) << PDFSUP.second
1527  << " " << setw(4) << IDWTUP
1528  << " " << setw(4) << NPRUP << std::endl;
1529 
1530  for ( int i = 0; i < NPRUP; ++i )
1531  file << " " << setw(14) << XSECUP[i]
1532  << " " << setw(14) << XERRUP[i]
1533  << " " << setw(14) << XMAXUP[i]
1534  << " " << setw(6) << LPRUP[i] << std::endl;
1535 
1536  for ( int i = 0, N = generators.size(); i < N; ++i )
1537  generators[i].print(file);
1538 
1539  if ( xsecinfo.neve > 0 ) xsecinfo.print(file);
1540 
1541  if ( cuts.size() > 0 ) {
1542  file << "<cutsinfo>" << std::endl;
1543 
1544  for ( std::map<std::string, std::set<long> >::const_iterator ptit =
1545  ptypes.begin(); ptit != ptypes.end(); ++ptit ) {
1546  file << "<ptype" << oattr("name", ptit->first) << ">";
1547  for ( std::set<long>::const_iterator it = ptit->second.begin();
1548  it != ptit->second.end(); ++it )
1549  file << " " << *it;
1550  file << "</ptype>" << std::endl;
1551  }
1552 
1553  for ( int i = 0, N = cuts.size(); i < N; ++i )
1554  cuts[i].print(file);
1555  file << "</cutsinfo>" << std::endl;
1556  }
1557 
1558  for ( std::map<long,ProcInfo>::const_iterator it = procinfo.begin();
1559  it != procinfo.end(); ++it )
1560  it->second.print(file);
1561 
1562  for ( std::map<long,MergeInfo>::const_iterator it = mergeinfo.begin();
1563  it != mergeinfo.end(); ++it )
1564  it->second.print(file);
1565 
1566  bool isrwgt = false;
1567  int ingroup = -1;
1568  for ( int i = 0, N = weightinfo.size(); i < N; ++i ) {
1569  if ( weightinfo[i].isrwgt ) {
1570  if ( !isrwgt ) file << "<initrwgt>\n";
1571  isrwgt = true;
1572  } else {
1573  if ( isrwgt ) file << "</initrwgt>\n";
1574  isrwgt = false;
1575  }
1576  int group = weightinfo[i].inGroup;
1577  if ( group != ingroup ) {
1578  if ( ingroup != -1 ) file << "</weightgroup>\n";
1579  if ( group != -1 ) {
1580  file << "<weightgroup"
1581  << oattr("type", weightgroup[group].type);
1582  if ( !weightgroup[group].combine.empty() )
1583  file << oattr("combine", weightgroup[group].combine);
1584  file << ">\n";
1585  }
1586  ingroup = group;
1587  }
1588  weightinfo[i].print(file);
1589  }
1590  if ( ingroup != -1 ) file << "</weightgroup>\n";
1591  if ( isrwgt ) file << "</initrwgt>\n";
1592 
1593 
1594  file << hashline(junk) << "</init>" << std::endl;
1595 
1596  }
1597 
1601  void clear() {
1602  procinfo.clear();
1603  mergeinfo.clear();
1604  weightinfo.clear();
1605  weightgroup.clear();
1606  cuts.clear();
1607  ptypes.clear();
1608  junk.clear();
1609  }
1610 
1616  void resize(int nrup) {
1617  NPRUP = nrup;
1618  resize();
1619  }
1620 
1626  void resize() {
1627  XSECUP.resize(NPRUP);
1628  XERRUP.resize(NPRUP);
1629  XMAXUP.resize(NPRUP);
1630  LPRUP.resize(NPRUP);
1631  }
1632 
1636  int weightIndex(std::string name) const {
1637  std::map<std::string, int>::const_iterator it = weightmap.find(name);
1638  if ( it != weightmap.end() ) return it->second;
1639  return 0;
1640  }
1641 
1645  int nWeights() const {
1646  return weightmap.size() + 1;
1647  }
1648 
1649 public:
1650 
1654  std::pair<long,long> IDBMUP;
1655 
1659  std::pair<double,double> EBMUP;
1660 
1665  std::pair<int,int> PDFGUP;
1666 
1671  std::pair<int,int> PDFSUP;
1672 
1678  int IDWTUP;
1679 
1683  int NPRUP;
1684 
1688  std::vector<double> XSECUP;
1689 
1694  std::vector<double> XERRUP;
1695 
1700  std::vector<double> XMAXUP;
1701 
1705  std::vector<int> LPRUP;
1706 
1711 
1715  std::vector<Cut> cuts;
1716 
1720  std::map<std::string, std::set<long> > ptypes;
1721 
1725  std::map<long,ProcInfo> procinfo;
1726 
1730  std::map<long,MergeInfo> mergeinfo;
1731 
1736  std::vector<Generator> generators;
1737 
1741  std::vector<WeightInfo> weightinfo;
1742 
1746  std::map<std::string,int> weightmap;
1747 
1751  std::vector<WeightGroup> weightgroup;
1752 
1756  std::string junk;
1757 
1761  int version;
1762 
1763 };
1764 
1768 class HEPEUP;
1769 
1774 struct EventGroup: public std::vector<HEPEUP*> {
1775 
1779  inline EventGroup(): nreal(-1), ncounter(-1) {}
1780 
1784  inline EventGroup(const EventGroup &);
1785 
1789  inline EventGroup & operator=(const EventGroup &);
1790 
1794  inline void clear();
1795 
1799  inline ~EventGroup();
1800 
1804  int nreal;
1805 
1810 
1811 };
1812 
1813 
1822 class HEPEUP : public TagBase {
1823 
1824 public:
1825 
1832  : NUP(0), IDPRUP(0), XWGTUP(0.0), XPDWUP(0.0, 0.0),
1833  SCALUP(0.0), AQEDUP(0.0), AQCDUP(0.0), heprup(0), currentWeight(0),
1834  isGroup(false) {}
1835 
1839  HEPEUP(const HEPEUP & x)
1840  : TagBase(x), isGroup(false) {
1841  operator=(x);
1842  }
1843 
1848  HEPEUP & setEvent(const HEPEUP & x) {
1849  NUP = x.NUP;
1850  IDPRUP = x.IDPRUP;
1851  XWGTUP = x.XWGTUP;
1852  XPDWUP = x.XPDWUP;
1853  SCALUP = x.SCALUP;
1854  AQEDUP = x.AQEDUP;
1855  AQCDUP = x.AQCDUP;
1856  IDUP = x.IDUP;
1857  ISTUP = x.ISTUP;
1858  MOTHUP = x.MOTHUP;
1859  ICOLUP = x.ICOLUP;
1860  PUP = x.PUP;
1861  VTIMUP = x.VTIMUP;
1862  SPINUP = x.SPINUP;
1863  heprup = x.heprup;
1865  weights = x.weights;
1866  pdfinfo = x.pdfinfo;
1867  PDFGUPsave = x.PDFGUPsave;
1868  PDFSUPsave = x.PDFSUPsave;
1869  clustering = x.clustering;
1870  scales = x.scales;
1871  junk = x.junk;
1873  return *this;
1874  }
1875 
1879  HEPEUP & operator=(const HEPEUP & x) {
1880  clear();
1881  setEvent(x);
1882  subevents = x.subevents;
1883  isGroup = x.isGroup;
1884  return *this;
1885  }
1886 
1891  clear();
1892  };
1894 
1895 public:
1896 
1897 
1901  HEPEUP(const XMLTag & tag, HEPRUP & heprupin)
1902  : TagBase(tag.attr), NUP(0), IDPRUP(0), XWGTUP(0.0), XPDWUP(0.0, 0.0),
1903  SCALUP(0.0), AQEDUP(0.0), AQCDUP(0.0), heprup(&heprupin),
1904  currentWeight(0), isGroup(tag.name == "eventgroup") {
1905 
1906  if ( heprup->NPRUP < 0 )
1907  throw std::runtime_error("Tried to read events but no processes defined "
1908  "in init block of Les Houches file.");
1909 
1910  std::vector<XMLTag*> tags = tag.tags;
1911 
1912  if ( isGroup ) {
1913  getattr("nreal", subevents.nreal);
1914  getattr("ncounter", subevents.ncounter);
1915  for ( int i = 0, N = tags.size(); i < N; ++i )
1916  if ( tags[i]->name == "event" )
1917  subevents.push_back(new HEPEUP(*tags[i], heprupin));
1918  return;
1919  }
1920 
1921 
1922 
1923  // The event information should be in the first (anonymous) tag
1924  std::istringstream iss(tags[0]->contents);
1925  if ( !( iss >> NUP >> IDPRUP >> XWGTUP >> SCALUP >> AQEDUP >> AQCDUP ) )
1926  throw std::runtime_error("Failed to parse event in Les Houches file.");
1927 
1928  resize();
1929 
1930  // Read all particle lines.
1931  for ( int i = 0; i < NUP; ++i ) {
1932  if ( !( iss >> IDUP[i] >> ISTUP[i] >> MOTHUP[i].first >> MOTHUP[i].second
1933  >> ICOLUP[i].first >> ICOLUP[i].second
1934  >> PUP[i][0] >> PUP[i][1] >> PUP[i][2]
1935  >> PUP[i][3] >> PUP[i][4]
1936  >> VTIMUP[i] >> SPINUP[i] ) )
1937  throw std::runtime_error("Failed to parse event in Les Houches file.");
1938  }
1939 
1940  junk.clear();
1941  std::string ss;
1942  while ( getline(iss, ss) ) junk += ss + '\n';
1943 
1944  scales = Scales(SCALUP);
1945  pdfinfo = PDFInfo(SCALUP);
1946  namedweights.clear();
1947  weights.clear();
1948  weights.resize(heprup->nWeights(),
1949  std::make_pair(XWGTUP, (WeightInfo*)(0)));
1950  weights.front().first = XWGTUP;
1951  for ( int i = 1, N = weights.size(); i < N; ++i )
1952  weights[i].second = &heprup->weightinfo[i - 1];
1953 
1954  for ( int i = 1, N = tags.size(); i < N; ++i ) {
1955  XMLTag & tag = *tags[i];
1956 
1957  if ( tag.name.empty() ) junk += tag.contents;
1958 
1959  if ( tag.name == "weights" ) {
1960  weights.resize(heprup->nWeights(),
1961  std::make_pair(XWGTUP, (WeightInfo*)(0)));
1962  weights.front().first = XWGTUP;
1963  for ( int i = 1, N = weights.size(); i < N; ++i )
1964  weights[i].second = &heprup->weightinfo[i - 1];
1965  double w = 0.0;
1966  int i = 0;
1967  std::istringstream iss(tag.contents);
1968  while ( iss >> w )
1969  if ( ++i < int(weights.size()) )
1970  weights[i].first = w;
1971  else
1972  weights.push_back(std::make_pair(w, (WeightInfo*)(0)));
1973  }
1974  if ( tag.name == "weight" ) {
1975  namedweights.push_back(Weight(tag));
1976  }
1977  if ( tag.name == "rwgt" ) {
1978  for ( int j = 0, M = tag.tags.size(); j < M; ++j ) {
1979  if ( tag.tags[j]->name == "wgt" ) {
1980  namedweights.push_back(Weight(*tag.tags[j]));
1981  }
1982  }
1983  }
1984  else if ( tag.name == "clustering" ) {
1985  for ( int j = 0, M= tag.tags.size(); j < M; ++j ) {
1986  if ( tag.tags[j]->name == "clus" )
1987  clustering.push_back(Clus(*tag.tags[j]));
1988  }
1989  }
1990  else if ( tag.name == "pdfinfo" ) {
1991  pdfinfo = PDFInfo(tag, SCALUP);
1992  }
1993  else if ( tag.name == "scales" ) {
1994  scales = Scales(tag, SCALUP);
1995  }
1996 
1997  }
1998 
1999  for ( int i = 0, N = namedweights.size(); i < N; ++i ) {
2000  int indx = heprup->weightIndex(namedweights[i].name);
2001  if ( indx > 0 ) {
2002  weights[indx].first = namedweights[i].weights[0];
2003  namedweights[i].indices[0] = indx;
2004  } else {
2005  weights.push_back(std::make_pair(namedweights[i].weights[0],
2006  (WeightInfo*)(0)));
2007  namedweights[i].indices[0] = weights.size() - 1;
2008  }
2009  for ( int j = 1, M = namedweights[i].weights.size(); j < M; ++j ) {
2010  weights.push_back(std::make_pair(namedweights[i].weights[j],
2011  (WeightInfo*)(0)));
2012  namedweights[i].indices[j] = weights.size() - 1;
2013  }
2014  }
2015 
2016  }
2017 
2021  void print(std::ostream & file) const {
2022 
2023  using std::setw;
2024 
2025  if ( isGroup ) {
2026  file << "<eventgroup";
2027  if ( subevents.nreal > 0 )
2028  file << oattr("nreal", subevents.nreal);
2029  if ( subevents.ncounter > 0 )
2030  file << oattr("ncounter", subevents.ncounter);
2031  printattrs(file);
2032  file << ">\n";
2033  for ( int i = 0, N = subevents.size(); i < N; ++i )
2034  subevents[i]->print(file);
2035  file << "</eventgroup>\n";
2036  return;
2037  }
2038 
2039  file << "<event";
2040  printattrs(file);
2041  file << ">\n";
2042  file << " " << setw(4) << NUP
2043  << " " << setw(6) << IDPRUP
2044  << " " << setw(14) << XWGTUP
2045  << " " << setw(14) << SCALUP
2046  << " " << setw(14) << AQEDUP
2047  << " " << setw(14) << AQCDUP << "\n";
2048 
2049  for ( int i = 0; i < NUP; ++i )
2050  file << " " << setw(8) << IDUP[i]
2051  << " " << setw(2) << ISTUP[i]
2052  << " " << setw(4) << MOTHUP[i].first
2053  << " " << setw(4) << MOTHUP[i].second
2054  << " " << setw(4) << ICOLUP[i].first
2055  << " " << setw(4) << ICOLUP[i].second
2056  << " " << setw(14) << PUP[i][0]
2057  << " " << setw(14) << PUP[i][1]
2058  << " " << setw(14) << PUP[i][2]
2059  << " " << setw(14) << PUP[i][3]
2060  << " " << setw(14) << PUP[i][4]
2061  << " " << setw(1) << VTIMUP[i]
2062  << " " << setw(1) << SPINUP[i] << std::endl;
2063 
2064  if ( weights.size() > 0 ) {
2065  file << "<weights>";
2066  for ( int i = 1, N = weights.size(); i < N; ++i )
2067  file << " " << weights[i].first;
2068  file << "</weights>\n";
2069  }
2070 
2071  bool iswgt = false;
2072  for ( int i = 0, N = namedweights.size(); i < N; ++i ) {
2073  if ( namedweights[i].iswgt ) {
2074  if ( !iswgt ) file << "<rwgt>\n";
2075  iswgt = true;
2076  } else {
2077  if ( iswgt ) file << "</rwgt>\n";
2078  iswgt = false;
2079  }
2080  for ( int j = 0, M = namedweights[i].indices.size(); j < M; ++j )
2081  namedweights[i].weights[j] = weight(namedweights[i].indices[j]);
2082  namedweights[i].print(file);
2083  }
2084  if ( iswgt ) file << "</rwgt>\n";
2085 
2086  if ( !clustering.empty() ) {
2087  file << "<clustering>" << std::endl;
2088  for ( int i = 0, N = clustering.size(); i < N; ++i )
2089  clustering[i].print(file);
2090  file << "</clustering>" << std::endl;
2091  }
2092 
2093  pdfinfo.print(file);
2094  scales.print(file);
2095 
2096  // }
2097 
2098  file << hashline(junk) << "</event>\n";
2099 
2100  }
2101 
2105  void reset() {
2106  setWeightInfo(0);
2107  NUP = 0;
2108  clustering.clear();
2109  weights.clear();
2110  }
2111 
2115  void clear() {
2116  reset();
2117  subevents.clear();
2118  }
2119 
2125  void resize(int nup) {
2126  NUP = nup;
2127  resize();
2128  }
2129 
2134  double totalWeight(int i = 0) const {
2135  if ( subevents.empty() ) return weight(i);
2136  double w = 0.0;
2137  for ( int i = 0, N = subevents.size(); i < N; ++i )
2138  w += subevents[i]->weight(i);
2139  return w;
2140  }
2141 
2146  double totalWeight(std::string name) const {
2147  return totalWeight(heprup->weightIndex(name));
2148  }
2149 
2153  double weight(int i = 0) const {
2154  return weights[i].first;
2155  }
2156 
2160  double weight(std::string name) const {
2161  return weight(heprup->weightIndex(name));
2162  }
2163 
2167  void setWeight(int i, double w) {
2168  weights[i].first = w;
2169  }
2173  bool setWeight(std::string name, double w) {
2174  int i = heprup->weightIndex(name);
2175  if ( i >= int(weights.size()) ) return false;
2176  setWeight(i, w);
2177  return true;
2178  }
2179 
2180 
2186  void resize() {
2187  IDUP.resize(NUP);
2188  ISTUP.resize(NUP);
2189  MOTHUP.resize(NUP);
2190  ICOLUP.resize(NUP);
2191  PUP.resize(NUP, std::vector<double>(5));
2192  VTIMUP.resize(NUP);
2193  SPINUP.resize(NUP);
2194  }
2195 
2200  bool setWeightInfo(unsigned int i) {
2201  if ( i >= weights.size() ) return false;
2202  if ( currentWeight ) {
2207  }
2208  XWGTUP = weights[i].first;
2209  currentWeight = weights[i].second;
2210  if ( currentWeight ) {
2215  if ( currentWeight->pdf ) {
2216  heprup->PDFGUP.first = heprup->PDFGUP.second = 0;
2217  heprup->PDFSUP.first = heprup->PDFSUP.second = currentWeight->pdf;
2218  }
2219  if ( currentWeight->pdf2 ) {
2220  heprup->PDFSUP.second = currentWeight->pdf2;
2221  }
2222 
2223  }
2224  return true;
2225  }
2226 
2231  bool setSubEvent(unsigned int i) {
2232  if ( i > subevents.size() || subevents.empty() ) return false;
2233  if ( i == 0 ) {
2234  reset();
2235  weights = subevents[0]->weights;
2236  for ( int i = 1, N = subevents.size(); i < N; ++i )
2237  for ( int j = 0, M = weights.size(); j < M; ++j )
2238  weights[j].first += subevents[i]->weights[j].first;
2239  currentWeight = 0;
2240  } else {
2241  setEvent(*subevents[i - 1]);
2242  }
2243  return true;
2244  }
2245 
2246 public:
2247 
2251  int NUP;
2252 
2256  int IDPRUP;
2257 
2261  double XWGTUP;
2262 
2269  std::pair<double,double> XPDWUP;
2270 
2275  double SCALUP;
2276 
2280  double AQEDUP;
2281 
2285  double AQCDUP;
2286 
2290  std::vector<long> IDUP;
2291 
2295  std::vector<int> ISTUP;
2296 
2301  std::vector< std::pair<int,int> > MOTHUP;
2302 
2307  std::vector< std::pair<int,int> > ICOLUP;
2308 
2313  std::vector< std::vector<double> > PUP;
2314 
2319  std::vector<double> VTIMUP;
2320 
2326  std::vector<double> SPINUP;
2327 
2332 
2337 
2341  std::vector<Weight> namedweights;
2342 
2346  std::vector< std::pair<double, const WeightInfo *> > weights;
2347 
2351  std::vector<Clus> clustering;
2352 
2357 
2361  std::pair<int,int> PDFGUPsave;
2362 
2366  std::pair<int,int> PDFSUPsave;
2367 
2368 
2373 
2377  bool isGroup;
2378 
2384 
2388  std::string junk;
2389 
2390 };
2391 
2392 
2393 // Destructor implemented here.
2394 
2395 inline void EventGroup::clear() {
2396  while ( size() > 0 ) {
2397  delete back();
2398  pop_back();
2399  }
2400 }
2401 
2403  clear();
2404 }
2405 
2407  : std::vector<HEPEUP*>(eg.size()) {
2408  for ( int i = 0, N = eg.size(); i < N; ++i ) at(i) = new HEPEUP(*eg.at(i));
2409 }
2410 
2412  if ( &x == this ) return *this;
2413  clear();
2414  nreal = x.nreal;
2415  ncounter = x.ncounter;
2416  for ( int i = 0, N = x.size(); i < N; ++i ) push_back(new HEPEUP(*x.at(i)));
2417  return *this;
2418 }
2419 
2420 
2437 class Reader {
2438 
2439 public:
2440 
2451  Reader(std::istream & is)
2452  : file(is) {
2453  init();
2454  }
2455 
2466  Reader(std::string filename)
2467  : intstream(filename.c_str()), file(intstream) {
2468  init();
2469  }
2470 
2471 private:
2472 
2477  void init() {
2478 
2479  bool readingHeader = false;
2480  bool readingInit = false;
2481 
2482  // Make sure we are reading a LHEF file:
2483  getline();
2484  if ( !currentFind("<LesHouchesEvents") )
2485  throw std::runtime_error
2486  ("Tried to read a file which does not start with the "
2487  "LesHouchesEvents tag.");
2488  version = 1;
2489  if ( currentFind("version=\"3" ) )
2490  version = 3;
2491  else if ( currentFind("version=\"2" ) )
2492  version = 2;
2493  else if ( !currentFind("version=\"1" ) )
2494  throw std::runtime_error
2495  ("Tried to read a LesHouchesEvents file which is above version 3.");
2496 
2497  // Loop over all lines until we hit the </init> tag.
2498  while ( getline() && !currentFind("</init>") ) {
2499  if ( currentFind("<header") ) {
2500  // We have hit the header block, so we should dump this and
2501  // all following lines to headerBlock until we hit the end of
2502  // it.
2503  readingHeader = true;
2504  headerBlock = currentLine + "\n";
2505  }
2506  else if ( currentFind("<init>") ) {
2507  // We have hit the init block
2508  readingInit = true;
2509  initComments = currentLine + "\n";
2510  }
2511  else if ( currentFind("</header>") ) {
2512  // The end of the header block. Dump this line as well to the
2513  // headerBlock and we're done.
2514  readingHeader = false;
2515  headerBlock += currentLine + "\n";
2516  }
2517  else if ( readingHeader ) {
2518  // We are in the process of reading the header block. Dump the
2519  // line to haderBlock.
2520  headerBlock += currentLine + "\n";
2521  }
2522  else if ( readingInit ) {
2523  // Here we found a comment line. Dump it to initComments.
2524  initComments += currentLine + "\n";
2525  }
2526  else {
2527  // We found some other stuff outside the standard tags.
2528  outsideBlock += currentLine + "\n";
2529  }
2530  }
2531  if ( !currentFind("</init>") )
2532  throw std::runtime_error("Found incomplete init tag in "
2533  "Les Houches file.");
2534  initComments += currentLine + "\n";
2535  std::vector<XMLTag*> tags = XMLTag::findXMLTags(initComments);
2536  for ( int i = 0, N = tags.size(); i < N; ++i )
2537  if ( tags[i]->name == "init" ) {
2538  heprup = HEPRUP(*tags[i], version);
2539  break;
2540  }
2541  XMLTag::deleteAll(tags);
2542 
2543  }
2544 
2545 public:
2546 
2553  bool readEvent() {
2554 
2555  // Check if the initialization was successful. Otherwise we will
2556  // not read any events.
2557  if ( heprup.NPRUP < 0 ) return false;
2558 
2559  std::string eventLines;
2560  int inEvent = 0;;
2561 
2562  // Keep reading lines until we hit the end of an event or event group.
2563  while ( getline() ) {
2564  if ( inEvent ) {
2565  eventLines += currentLine + "\n";
2566  if ( inEvent == 1 && currentFind("</event>") ) break;
2567  if ( inEvent == 2 && currentFind("</eventgroup>") ) break;
2568  }
2569  else if ( currentFind("<eventgroup") ) {
2570  eventLines += currentLine + "\n";
2571  inEvent = 2;
2572  }
2573  else if ( currentFind("<event") ) {
2574  eventLines += currentLine + "\n";
2575  inEvent = 1;
2576  }
2577  else {
2578  outsideBlock += currentLine + "\n";
2579  }
2580  }
2581  if ( inEvent == 1 && !currentFind("</event>") ) return false;
2582  if ( inEvent == 2 && !currentFind("</eventgroup>") ) return false;
2583 
2584  std::vector<XMLTag*> tags = XMLTag::findXMLTags(eventLines);
2585 
2586  for ( int i = 0, N = tags.size(); i < N ; ++i ) {
2587  if ( tags[i]->name == "event" || tags[i]->name == "eventgroup" ) {
2588  hepeup = HEPEUP(*tags[i], heprup);
2589  XMLTag::deleteAll(tags);
2590  return true;
2591  }
2592  }
2593 
2594  XMLTag::deleteAll(tags);
2595  return false;
2596 
2597  }
2598 
2599 protected:
2600 
2604  bool getline() {
2605  return ( (bool)std::getline(file, currentLine) );
2606  }
2607 
2611  bool currentFind(std::string str) const {
2612  return currentLine.find(str) != std::string::npos;
2613  }
2614 
2615 protected:
2616 
2621  std::ifstream intstream;
2622 
2627  std::istream & file;
2628 
2632  std::string currentLine;
2633 
2634 public:
2635 
2639  int version;
2640 
2645  std::string outsideBlock;
2646 
2650  std::string headerBlock;
2651 
2656 
2660  std::string initComments;
2661 
2666 
2670  std::string eventComments;
2671 
2672 private:
2673 
2677  Reader();
2678 
2682  Reader(const Reader &);
2683 
2687  Reader & operator=(const Reader &);
2688 
2689 };
2690 
2712 class Writer {
2713 
2714 public:
2715 
2720  Writer(std::ostream & os)
2721  : file(os) { }
2722 
2727  Writer(std::string filename)
2728  : intstream(filename.c_str()), file(intstream) {}
2729 
2734  file << "</LesHouchesEvents>" << std::endl;
2735  }
2736 
2740  std::ostream & headerBlock() {
2741  return headerStream;
2742  }
2743 
2747  std::ostream & initComments() {
2748  return initStream;
2749  }
2750 
2754  std::ostream & eventComments() {
2755  return eventStream;
2756  }
2757 
2762  void init() {
2763 
2764  // Write out the standard XML tag for the event file.
2765  if ( heprup.version == 3 )
2766  file << "<LesHouchesEvents version=\"3.0\">\n";
2767  else if ( heprup.version == 2 )
2768  file << "<LesHouchesEvents version=\"2.0\">\n";
2769  else
2770  file << "<LesHouchesEvents version=\"1.0\">\n";
2771 
2772 
2773  file << std::setprecision(8);
2774 
2775  using std::setw;
2776 
2777  std::string headerBlock = headerStream.str();
2778  if ( headerBlock.length() ) {
2779  if ( headerBlock.find("<header>") == std::string::npos )
2780  file << "<header>\n";
2781  if ( headerBlock[headerBlock.length() - 1] != '\n' )
2782  headerBlock += '\n';
2783  file << headerBlock;
2784  if ( headerBlock.find("</header>") == std::string::npos )
2785  file << "</header>\n";
2786  }
2787 
2788  heprup.print(file);
2789 
2790  }
2791 
2795  void writeEvent() {
2796  hepeup.print(file);
2797  }
2798 
2799 protected:
2800 
2805  std::ofstream intstream;
2806 
2811  std::ostream & file;
2812 
2813 public:
2814 
2818  std::ostringstream headerStream;
2819 
2824 
2828  std::ostringstream initStream;
2829 
2834 
2838  std::ostringstream eventStream;
2839 
2840 private:
2841 
2845  Writer();
2846 
2850  Writer(const Writer &);
2851 
2855  Writer & operator=(const Writer &);
2856 
2857 };
2858 
2859 }
2860 
2861 /* \example LHEFCat.cc This is a main function which simply reads a
2862  Les Houches Event File from the standard input and writes it again
2863  to the standard output.
2864  This file can be downloaded from
2865  <A HREF="http://www.thep.lu.se/~leif/LHEF/LHEFCat.cc">here</A>.
2866  There are also two sample event files,
2867  <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>
2868  to try it on.
2869 */
2870 
2871 /* \mainpage Les Houches Event File
2872 
2873 Here are some example classes for reading and writing Les Houches
2874 Event Files according to the
2875 <A HREF="http://www.thep.lu.se/~torbjorn/lhef/lhafile2.pdf">proposal</A>
2876 by Torbj&ouml;rn Sj&ouml;strand discussed at the
2877 <A HREF="http://mc4lhc06.web.cern.ch/mc4lhc06/">MC4LHC</A>
2878 workshop at CERN 2006.
2879 
2880 The classes has now been updated to handle the suggested version 3 of
2881 this 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>).
2882 
2883 There is a whole set of classes available in a single header file
2884 called <A
2885 HREF="http://www.thep.lu.se/~leif/LHEF/LHEF.h">LHEF.h</A>. The idea is
2886 that matrix element or parton shower generators will implement their
2887 own wrapper using these classes as containers.
2888 
2889 The two classes LHEF::HEPRUP and LHEF::HEPEUP are simple container
2890 classes which contain the same information as the Les Houches standard
2891 Fortran common blocks with the same names. They also contain the extra
2892 information defined in version 3 in the standard. The other two main
2893 classes are called LHEF::Reader and LHEF::Writer and are used to read
2894 and write Les Houches Event Files
2895 
2896 Here are a few <A HREF="examples.html">examples</A> of how to use the
2897 classes:
2898 
2899 \namespace LHEF The LHEF namespace contains some example classes for reading and writing Les Houches
2900 Event Files according to the
2901 <A HREF="http://www.thep.lu.se/~torbjorn/lhef/lhafile2.pdf">proposal</A>
2902 by Torbj&ouml;rn Sj&ouml;strand discussed at the
2903 <A HREF="http://mc4lhc06.web.cern.ch/mc4lhc06/">MC4LHC</A>
2904 workshop at CERN 2006.
2905 
2906 
2907 
2908  */
2909 
2910 
2911 #endif /* HEPMC_LHEF_H */