Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:01:13

0001 // -*- C++ -*-
0002 #ifndef HEPMC3_LHEF_H
0003 #define HEPMC3_LHEF_H
0004 
0005 /**
0006  * @file LHEF.h 
0007  * @brief This is the declaration of the Les Houches Event File classes,
0008  * implementing a simple C++ parser/writer for Les Houches Event files.
0009  * Copyright (C) 2009-2024 Leif Lonnblad
0010  *
0011  * The code is licenced under LGPLv3+, see COPYING for details.
0012  * Please respect the MCnet academic guidelines, see GUIDELINES for details.
0013  */
0014 
0015 #include <iostream>
0016 #include <iomanip>
0017 #include <sstream>
0018 #include <fstream>
0019 #include <string>
0020 #include <vector>
0021 #include <map>
0022 #include <set>
0023 #include <utility>
0024 #include <stdexcept>
0025 #include <cstdlib>
0026 #include <cmath>
0027 #include <limits>
0028 #ifndef M_PI
0029 #define M_PI 3.14159265358979323846264338327950288
0030 #endif
0031 
0032 
0033 /**
0034  * @brief Les Houches event file classes.
0035  *
0036  * The namespace containing helper classes and Reader and Writer
0037  * classes for handling Les Houches event files.
0038  *
0039  * @ingroup LHEF
0040  */
0041 namespace LHEF {
0042 
0043 /**
0044  * Helper struct for output of attributes.
0045  */
0046 template <typename T>
0047 struct OAttr {
0048 
0049   /**
0050    * Constructor
0051    */
0052   OAttr(const std::string & n, const T & v): name(n), val(v) {}
0053 
0054   /**
0055    * The name of the attribute being printed.
0056    */
0057   std::string name;
0058 
0059   /**
0060    * The value of the attribute being printed.
0061    */
0062   T val;
0063 
0064 };
0065 
0066 /**
0067  * Output manipulator for writing attributes.
0068  */
0069 template <typename T>
0070 OAttr<T> oattr(std::string name, const T & value) {
0071   return OAttr<T>(name, value);
0072 }
0073 
0074 /**
0075  * Output operator for attributes.
0076  */
0077 template <typename T>
0078 std::ostream & operator<<(std::ostream & os, const OAttr<T> & oa) {
0079   os << " " << oa.name << "=\"" << oa.val << "\"";
0080   return os;
0081 }
0082 
0083 /**
0084  * The XMLTag struct is used to represent all information within an
0085  * XML tag. It contains the attributes as a map, any sub-tags as a
0086  * vector of pointers to other XMLTag objects, and any other
0087  * information as a single string.
0088  */
0089 struct XMLTag {
0090 
0091   /**
0092    * Convenient typdef.
0093    */
0094   typedef std::string::size_type pos_t;
0095 
0096   /**
0097    * Convenient typdef.
0098    */
0099   typedef std::map<std::string,std::string> AttributeMap;
0100 
0101   /**
0102    * Convenient alias for npos.
0103    */
0104   static const pos_t end = std::string::npos;
0105 
0106   /**
0107    * Default constructor.
0108    */
0109   XMLTag() {}
0110 
0111   /**
0112    * The destructor also destroys any sub-tags.
0113    */
0114   ~XMLTag() {
0115     for ( int i = 0, N = tags.size(); i < N; ++i ) delete tags[i];
0116   }
0117 
0118   /**
0119    * The name of this tag.
0120    */
0121   std::string name;
0122 
0123   /**
0124    * The attributes of this tag.
0125    */
0126   AttributeMap attr;
0127 
0128   /**
0129    * A vector of sub-tags.
0130    */
0131   std::vector<XMLTag*> tags;
0132 
0133   /**
0134    * The contents of this tag.
0135    */
0136   std::string contents;
0137 
0138   /**
0139    * Find an attribute named \a n and set the double variable \a v to
0140    * the corresponding value. @return false if no attribute was found.
0141    */
0142   bool getattr(const std::string & n, double & v) const {
0143     AttributeMap::const_iterator it = attr.find(n);
0144     if ( it == attr.end() ) return false;
0145     v = std::atof(it->second.c_str());
0146     return true;
0147   }
0148 
0149   /**
0150    * Find an attribute named \a n and set the bool variable \a v to
0151    * true if the corresponding value is "yes". @return false if no
0152    * attribute was found.
0153    */
0154   bool getattr(const std::string & n, bool & v) const {
0155     AttributeMap::const_iterator it = attr.find(n);
0156     if ( it == attr.end() ) return false;
0157     if ( it->second == "yes" ) v = true;
0158     return true;
0159   }
0160 
0161   /**
0162    * Find an attribute named \a n and set the long variable \a v to
0163    * the corresponding value. @return false if no attribute was found.
0164    */
0165   bool getattr(const std::string & n, long & v) const {
0166     AttributeMap::const_iterator it = attr.find(n);
0167     if ( it == attr.end() ) return false;
0168     v = std::atoi(it->second.c_str());
0169     return true;
0170   }
0171 
0172   /**
0173    * Find an attribute named \a n and set the long variable \a v to
0174    * the corresponding value. @return false if no attribute was found.
0175    */
0176   bool getattr(const std::string & n, int & v) const {
0177     AttributeMap::const_iterator it = attr.find(n);
0178     if ( it == attr.end() ) return false;
0179     v = int(std::atoi(it->second.c_str()));
0180     return true;
0181   }
0182 
0183   /**
0184    * Find an attribute named \a n and set the string variable \a v to
0185    * the corresponding value. @return false if no attribute was found.
0186    */
0187   bool getattr(const std::string &n, std::string & v) const {
0188     AttributeMap::const_iterator it = attr.find(n);
0189     if ( it == attr.end() ) return false;
0190     v = it->second;
0191     return true;
0192   }
0193 
0194   /**
0195    * Scan the given string and return all XML tags found as a vector
0196    * of pointers to XMLTag objects. Text which does not belong to any
0197    * tag is stored in tags without name and in the string pointed to
0198    * by leftover (if not null).
0199    */
0200   static std::vector<XMLTag*> findXMLTags(std::string str,
0201                                           std::string * leftover = 0) {
0202     std::vector<XMLTag*> tags;
0203     pos_t curr = 0;
0204 
0205     while ( curr != end ) {
0206 
0207       // Find the first tag
0208       pos_t begin = str.find("<", curr);
0209 
0210       // Check for comments
0211       if ( begin != end && str.find("<!--", curr) == begin ) {
0212         pos_t endcom = str.find("-->", begin);
0213         tags.push_back(new XMLTag());
0214         if ( endcom == end ) {
0215           tags.back()->contents = str.substr(curr);
0216           if ( leftover ) *leftover += str.substr(curr);
0217           return tags;
0218         }
0219         tags.back()->contents = str.substr(curr, endcom - curr);
0220         if ( leftover ) *leftover += str.substr(curr, endcom - curr);
0221         curr = endcom;
0222         continue;
0223       }
0224 
0225       // Check for character data
0226       if ( begin != end && str.find("<![CDATA[", curr) == begin ) {
0227         pos_t endcom = str.find("]]>", begin);
0228         tags.push_back(new XMLTag());
0229         if ( endcom == end ) {
0230           tags.back()->contents = str.substr(curr);
0231           if ( leftover ) *leftover += str.substr(curr);
0232           return tags;
0233         }
0234         tags.back()->contents = str.substr(curr, endcom - curr);
0235         if ( leftover ) *leftover += str.substr(curr, endcom - curr);
0236         curr = endcom;
0237         continue;
0238       }
0239 
0240       if ( begin != curr ) {
0241         tags.push_back(new XMLTag());
0242         tags.back()->contents = str.substr(curr, begin - curr);
0243         if ( leftover ) *leftover += str.substr(curr, begin - curr);
0244       }
0245       if ( begin == end || begin > str.length() - 3 || str[begin + 1] == '/' )
0246         return tags;
0247 
0248       pos_t close = str.find(">", curr);
0249       if ( close == end ) return tags;
0250 
0251       // find the tag name.
0252       curr = str.find_first_of(" \t\n/>", begin);
0253       tags.push_back(new XMLTag());
0254       tags.back()->name = str.substr(begin + 1, curr - begin - 1);
0255 
0256       while ( true ) {
0257 
0258         // Now skip some white space to see if we can find an attribute.
0259         curr = str.find_first_not_of(" \t\n", curr);
0260         if ( curr == end || curr >= close ) break;
0261 
0262         pos_t tend = str.find_first_of("= \t\n", curr);
0263         if ( tend == end || tend >= close ) break;
0264 
0265         std::string namex = str.substr(curr, tend - curr);
0266         curr = str.find("=", curr) + 1;
0267 
0268         // OK now find the beginning and end of the atribute.
0269         curr = str.find_first_of("\"'", curr);
0270         if ( curr == end || curr >= close ) break;
0271         char quote = str[curr];
0272         pos_t bega = ++curr;
0273         curr = str.find(quote, curr);
0274         while ( curr != end && str[curr - 1] == '\\' )
0275           curr = str.find(quote, curr + 1);
0276 
0277         std::string value = str.substr(bega, curr == end? end: curr - bega);
0278 
0279         tags.back()->attr[namex] = value;
0280 
0281         ++curr;
0282 
0283       }
0284 
0285       curr = close + 1;
0286       if ( str[close - 1] == '/' ) continue;
0287 
0288       pos_t endtag = str.find("</" + tags.back()->name + ">", curr);
0289       if ( endtag == end ) {
0290         tags.back()->contents = str.substr(curr);
0291         curr = endtag;
0292       } else {
0293         tags.back()->contents = str.substr(curr, endtag - curr);
0294         curr = endtag + tags.back()->name.length() + 3;
0295       }
0296 
0297       std::string leftovers;
0298       tags.back()->tags = findXMLTags(tags.back()->contents, &leftovers);
0299       if ( leftovers.find_first_not_of(" \t\n") == end ) leftovers="";
0300       tags.back()->contents = leftovers;
0301 
0302     }
0303     return tags;
0304 
0305   }
0306 
0307   /**
0308    * Delete all tags in a vector.
0309    */
0310   static void deleteAll(std::vector<XMLTag*> & tags) {
0311     while ( tags.size() && tags.back() ) {
0312       delete tags.back();
0313       tags.pop_back();
0314     }
0315   }
0316   /**
0317    * Print out this tag to a stream.
0318    */
0319   void print(std::ostream & os) const {
0320     if ( name.empty() ) {
0321       os << contents;
0322       return;
0323     }
0324     os << "<" << name;
0325     for ( AttributeMap::const_iterator it = attr.begin();
0326           it != attr.end(); ++it )
0327       os << oattr(it->first, it->second);
0328     if ( contents.empty() && tags.empty() ) {
0329       os << "/>" << std::endl;
0330       return;
0331     }
0332     os << ">";
0333     for ( int i = 0, N = tags.size(); i < N; ++i )
0334       tags[i]->print(os);
0335 
0336     os << contents << "</" << name << ">" << std::endl;
0337   }
0338 
0339 };
0340 
0341 /**
0342  * Helper function to make sure that each line in the string \a s starts with a
0343  * #-character and that the string ends with a new-line.
0344  */
0345 inline std::string hashline(std::string s) {
0346   std::string ret;
0347   std::istringstream is(s);
0348   std::string ss;
0349   while ( getline(is, ss) ) {
0350     if ( ss.empty() ) continue;
0351     if ( ss.find_first_not_of(" \t") == std::string::npos ) continue;
0352     if ( ss.find('#') == std::string::npos ||
0353          ss.find('#') != ss.find_first_not_of(" \t") ) ss = "# " + ss;
0354     ret += ss + '\n';
0355   }
0356   return ret;
0357 }
0358 
0359 /**
0360  * This is the base class of all classes representing xml tags.
0361  */
0362 struct TagBase {
0363 
0364   /**
0365    * Convenient typedef.
0366    */
0367   typedef XMLTag::AttributeMap AttributeMap;
0368 
0369   /**
0370    * Default constructor does nothing.
0371    */
0372   TagBase() {}
0373 
0374   /**
0375    * Main constructor stores the attributes and contents of a tag.
0376    */
0377   TagBase(const AttributeMap & attr, const std::string &conts = std::string())
0378     : attributes(attr), contents(conts) {}
0379 
0380   /**
0381    * Find an attribute named \a n and set the double variable \a v to
0382    * the corresponding value. Remove the correspondig attribute from
0383    * the list if found and \a erase is true. @return false if no
0384    * attribute was found.
0385    */
0386   bool getattr(const std::string & n, double & v, bool erase = true) {
0387     AttributeMap::iterator it = attributes.find(n);
0388     if ( it == attributes.end() ) return false;
0389     v = std::atof(it->second.c_str());
0390     if ( erase) attributes.erase(it);
0391     return true;
0392   }
0393 
0394   /**
0395    * Find an attribute named \a n and set the bool variable \a v to
0396    * true if the corresponding value is "yes". Remove the correspondig
0397    * attribute from the list if found and \a erase is true. @return
0398    * false if no attribute was found.
0399    */
0400   bool getattr(const std::string & n, bool & v, bool erase = true) {
0401     AttributeMap::iterator it = attributes.find(n);
0402     if ( it == attributes.end() ) return false;
0403     if ( it->second == "yes" ) v = true;
0404     if ( erase) attributes.erase(it);
0405     return true;
0406   }
0407 
0408   /**
0409    * Find an attribute named \a n and set the long variable \a v to
0410    * the corresponding value. Remove the correspondig attribute from
0411    * the list if found and \a erase is true. @return false if no
0412    * attribute was found.
0413    */
0414   bool getattr(const std::string & n, long & v, bool erase = true) {
0415     AttributeMap::iterator it = attributes.find(n);
0416     if ( it == attributes.end() ) return false;
0417     v = std::atoi(it->second.c_str());
0418     if ( erase) attributes.erase(it);
0419     return true;
0420   }
0421 
0422   /**
0423    * Find an attribute named \a n and set the long variable \a v to
0424    * the corresponding value. Remove the correspondig attribute from
0425    * the list if found and \a erase is true. @return false if no
0426    * attribute was found.
0427    */
0428   bool getattr(const std::string & n, int & v, bool erase = true) {
0429     AttributeMap::iterator it = attributes.find(n);
0430     if ( it == attributes.end() ) return false;
0431     v = int(std::atoi(it->second.c_str()));
0432     if ( erase) attributes.erase(it);
0433     return true;
0434   }
0435 
0436   /**
0437    * Find an attribute named \a n and set the string variable \a v to
0438    * the corresponding value. Remove the correspondig attribute from
0439    * the list if found and \a erase is true. @return false if no
0440    * attribute was found.
0441    */
0442   bool getattr(const std::string & n, std::string & v, bool erase = true) {
0443     AttributeMap::iterator it = attributes.find(n);
0444     if ( it == attributes.end() ) return false;
0445     v = it->second;
0446     if ( erase) attributes.erase(it);
0447     return true;
0448   }
0449 
0450   /**
0451    * print out ' name="value"' for all unparsed attributes.
0452    */
0453   void printattrs(std::ostream & file) const {
0454     for ( AttributeMap::const_iterator it = attributes.begin();
0455           it != attributes.end(); ++ it )
0456       file << oattr(it->first, it->second);
0457   }
0458 
0459   /**
0460    * Print out end of tag marker. Print contents if not empty else
0461    * print simple close tag.
0462    */
0463   void closetag(std::ostream & file, const std::string & tag) const {
0464     if ( contents.empty() )
0465       file << "/>\n";
0466     else if ( contents.find('\n') != std::string::npos )
0467       file << ">\n" << contents << "\n</" << tag << ">\n";
0468     else
0469       file << ">" << contents << "</" << tag << ">\n";
0470   }
0471 
0472   /**
0473    * The attributes of this tag;
0474    */
0475   XMLTag::AttributeMap attributes;
0476 
0477   /**
0478    * The contents of this tag.
0479    */
0480   mutable std::string contents;
0481 
0482   /**
0483    * Static string token for truth values.
0484    */
0485   static std::string yes() { return "yes"; }
0486 
0487 };
0488 
0489 /**
0490  * The Generator class contains information about a generator used in a run.
0491  */
0492 struct Generator : public TagBase {
0493 
0494   /**
0495    * Construct from XML tag.
0496    */
0497   Generator(const XMLTag & tag)
0498     : TagBase(tag.attr, tag.contents) {
0499     getattr("name", name);
0500     getattr("version", version);
0501   }
0502 
0503   /**
0504    * Print the object as a generator tag.
0505    */
0506   void print(std::ostream & file) const {
0507     file << "<generator";
0508     if ( !name.empty() ) file << oattr("name", name);
0509     if ( !version.empty() ) file << oattr("version", version);
0510     printattrs(file);
0511     closetag(file, "generator");
0512   }
0513 
0514   /**
0515    * The name of the generator.
0516    */
0517   std::string name;
0518 
0519   /**
0520    * The version of the generator.
0521    */
0522   std::string version;
0523 
0524 };
0525 
0526 /**
0527  * The XSecInfo class contains information given in the xsecinfo tag.
0528  */
0529 struct XSecInfo : public TagBase {
0530 
0531   /**
0532    * Intitialize default values.
0533    */
0534   XSecInfo(): neve(-1), ntries(-1), totxsec(0.0), xsecerr(0.0), maxweight(1.0),
0535               meanweight(1.0), negweights(false), varweights(false) {}
0536 
0537   /**
0538    * Create from XML tag
0539    */
0540   XSecInfo(const XMLTag & tag)
0541     : TagBase(tag.attr, tag.contents), neve(-1), ntries(-1),
0542       totxsec(0.0), xsecerr(0.0), maxweight(1.0), meanweight(1.0),
0543       negweights(false), varweights(false) {
0544     if ( !getattr("neve", neve) )
0545       throw std::runtime_error("Found xsecinfo tag without neve attribute "
0546                                "in Les Houches Event File.");
0547     ntries = neve;
0548     getattr("ntries", ntries);
0549     if ( !getattr("totxsec", totxsec) )
0550       throw std::runtime_error("Found xsecinfo tag without totxsec "
0551                                "attribute in Les Houches Event File.");
0552     getattr("xsecerr", xsecerr);
0553     getattr("weightname", weightname);
0554     getattr("maxweight", maxweight);
0555     getattr("meanweight", meanweight);
0556     getattr("negweights", negweights);
0557     getattr("varweights", varweights);
0558 
0559   }
0560 
0561   /**
0562    * Print out an XML tag.
0563    */
0564   void print(std::ostream & file) const {
0565     file << "<xsecinfo" << oattr("neve", neve)
0566          << oattr("totxsec", totxsec);
0567     if ( maxweight != 1.0 )
0568       file << oattr("maxweight", maxweight)
0569            << oattr("meanweight", meanweight);
0570     if ( ntries > neve ) file << oattr("ntries", ntries);
0571     if ( xsecerr > 0.0 ) file << oattr("xsecerr", xsecerr);
0572     if ( !weightname.empty() ) file << oattr("weightname", weightname);
0573     if ( negweights ) file << oattr("negweights", yes());
0574     if ( varweights ) file << oattr("varweights", yes());
0575     printattrs(file);
0576     closetag(file, "xsecinfo");
0577   }
0578 
0579   /**
0580    * The number of events.
0581    */
0582   long neve;
0583 
0584   /**
0585    * The number of attempte that was needed to produce the neve events.
0586    */
0587   long ntries;
0588 
0589   /**
0590    * The total cross section in pb.
0591    */
0592   double totxsec;
0593 
0594   /**
0595    * The estimated statistical error on totxsec.
0596    */
0597   double xsecerr;
0598 
0599   /**
0600    * The maximum weight.
0601    */
0602   double maxweight;
0603 
0604   /**
0605    * The average weight.
0606    */
0607   double meanweight;
0608 
0609   /**
0610    * Does the file contain negative weights?
0611    */
0612   bool negweights;
0613 
0614   /**
0615    * Does the file contain varying weights?
0616    */
0617   bool varweights;
0618 
0619   /**
0620    * The named weight to which this object belongs.
0621    */
0622   std::string weightname;
0623 
0624 };
0625 
0626 /**
0627  * Convenient Alias.
0628  */
0629 typedef std::map<std::string,XSecInfo> XSecInfos;
0630 
0631 /**
0632  * Simple struct to store information about separate eventfiles to be
0633  * loaded.
0634  */
0635 struct EventFile : public TagBase {
0636 
0637   /**
0638    * Intitialize default values.
0639    */
0640   EventFile(): filename(""), neve(-1), ntries(-1) {}
0641 
0642   /**
0643    * Create from XML tag
0644    */
0645   EventFile(const XMLTag & tag)
0646     : TagBase(tag.attr, tag.contents), filename(""), neve(-1), ntries(-1) {
0647     if ( !getattr("name", filename) )
0648       throw std::runtime_error("Found eventfile tag without name attribute "
0649                                "in Les Houches Event File.");
0650     getattr("neve", neve);
0651     ntries = neve;
0652     getattr("ntries", ntries);
0653   }
0654 
0655   /**
0656    * Print out an XML tag.
0657    */
0658   void print(std::ostream & file) const {
0659     if ( filename.empty() ) return;
0660     file << "  <eventfile" << oattr("name", filename);
0661     if ( neve > 0 ) file << oattr("neve", neve);
0662     if ( ntries > neve ) file << oattr("ntries", ntries);
0663     printattrs(file);
0664     closetag(file, "eventfile");
0665   }
0666 
0667   /**
0668    * The name of the file.
0669    */
0670   std::string filename;
0671 
0672   /**
0673    * The number of events.
0674    */
0675   long neve;
0676 
0677   /**
0678    * The number of attempte that was needed to produce the neve events.
0679    */
0680   long ntries;
0681 
0682 };
0683 
0684 /**
0685  * The Cut class represents a cut used by the Matrix Element generator.
0686  */
0687 struct Cut : public TagBase {
0688 
0689   /**
0690    * Intitialize default values.
0691    */
0692   Cut(): min(-0.99*std::numeric_limits<double>::max()),
0693          max(0.99*std::numeric_limits<double>::max()) {}
0694 
0695   /**
0696    * Create from XML tag.
0697    */
0698   Cut(const XMLTag & tag,
0699       const std::map<std::string,std::set<long> >& ptypes)
0700     : TagBase(tag.attr),
0701       min(-0.99*std::numeric_limits<double>::max()),
0702       max(0.99*std::numeric_limits<double>::max()) {
0703     if ( !getattr("type", type) )
0704       throw std::runtime_error("Found cut tag without type attribute "
0705                                "in Les Houches file");
0706     long tmp;
0707     if ( tag.getattr("p1", np1) ) {
0708       if ( ptypes.find(np1) != ptypes.end() ) {
0709         p1 =  ptypes.find(np1)->second;
0710         attributes.erase("p1");
0711       } else {
0712         getattr("p1", tmp);
0713         p1.insert(tmp);
0714         np1 = "";
0715       }
0716     }
0717     if ( tag.getattr("p2", np2) ) {
0718       if ( ptypes.find(np2) != ptypes.end() ) {
0719         p2 =  ptypes.find(np2)->second;
0720         attributes.erase("p2");
0721       } else {
0722         getattr("p2", tmp);
0723         p2.insert(tmp);
0724         np2 = "";
0725       }
0726     }
0727 
0728     std::istringstream iss(tag.contents);
0729     iss >> min;
0730     if ( iss >> max ) {
0731       if ( min >= max )
0732         min = -0.99*std::numeric_limits<double>::max();
0733     } else
0734       max = 0.99*std::numeric_limits<double>::max();
0735   }
0736 
0737   /**
0738    * Print out an XML tag.
0739    */
0740   void print(std::ostream & file) const {
0741     file << "<cut" << oattr("type", type);
0742     if ( !np1.empty() )
0743       file << oattr("p1", np1);
0744     else
0745       if ( p1.size() == 1 ) file << oattr("p1", *p1.begin());
0746     if ( !np2.empty() )
0747       file << oattr("p2", np2);
0748     else
0749       if ( p2.size() == 1 ) file << oattr("p2", *p2.begin());
0750     printattrs(file);
0751 
0752     file << ">";
0753     if ( min > -0.9*std::numeric_limits<double>::max() )
0754       file << min;
0755     else
0756       file << max;
0757     if ( max < 0.9*std::numeric_limits<double>::max() )
0758       file << " " << max;
0759     if ( !contents.empty() ) file << std::endl << contents << std::endl;
0760     file << "</cut>" << std::endl;
0761   }
0762 
0763   /**
0764    * Check if a \a id1 matches p1 and \a id2 matches p2. Only non-zero
0765    * values are considered.
0766    */
0767   bool match(long id1, long id2 = 0) const {
0768     std::pair<bool,bool> ret(false, false);
0769     if ( !id2 ) ret.second = true;
0770     if ( !id1 ) ret.first = true;
0771     if ( p1.find(0) != p1.end() ) ret.first = true;
0772     if ( p1.find(id1) != p1.end() ) ret.first = true;
0773     if ( p2.find(0) != p2.end() ) ret.second = true;
0774     if ( p2.find(id2) != p2.end() ) ret.second = true;
0775     return ret.first && ret.second;
0776   }
0777 
0778   /**
0779    * Check if the particles given as a vector of PDG \a id numbers,
0780    * and a vector of vectors of momentum components, \a p, will pass
0781    * the cut defined in this event.
0782    */
0783   bool passCuts(const std::vector<long> & id,
0784                 const std::vector< std::vector<double> >& p ) const {
0785     if ( ( type == "m" && !p2.size() ) || type == "kt" || type == "eta" ||
0786          type == "y" || type == "E" ) {
0787       for ( int i = 0, N = id.size(); i < N; ++i )
0788         if ( match(id[i]) ) {
0789           if ( type == "m" ) {
0790             double v = p[i][4]*p[i][4] - p[i][3]*p[i][3] - p[i][2]*p[i][2]
0791               - p[i][1]*p[i][1];
0792             v = v >= 0.0? std::sqrt(v): -std::sqrt(-v);
0793             if ( outside(v) ) return false;
0794           }
0795           else if ( type == "kt" ) {
0796             if ( outside(std::sqrt(p[i][2]*p[i][2] + p[i][1]*p[i][1])) )
0797               return false;
0798           }
0799           else if ( type == "E" ) {
0800             if ( outside(p[i][4]) ) return false;
0801           }
0802           else if ( type == "eta" ) {
0803             if ( outside(eta(p[i])) ) return false;
0804           }
0805           else if ( type == "y" ) {
0806             if ( outside(rap(p[i])) ) return false;
0807           }
0808         }
0809     }
0810     else if ( type == "m"  || type == "deltaR" ) {
0811       for ( int i = 1, N = id.size(); i < N; ++i )
0812         for ( int j = 0; j < i; ++j )
0813           if ( match(id[i], id[j]) || match(id[j], id[i]) ) {
0814             if ( type == "m" ) {
0815               double v = (p[i][4] + p[j][4])*(p[i][4] + p[j][4])
0816                 - (p[i][3] + p[j][3])*(p[i][3] + p[j][3])
0817                 - (p[i][2] + p[j][2])*(p[i][2] + p[j][2])
0818                 - (p[i][1] + p[j][1])*(p[i][1] + p[j][1]);
0819               v = v >= 0.0? std::sqrt(v): -std::sqrt(-v);
0820               if ( outside(v) ) return false;
0821             }
0822             else if ( type == "deltaR" ) {
0823               if ( outside(deltaR(p[i], p[j])) ) return false;
0824             }
0825           }
0826     }
0827     else if ( type == "ETmiss" ) {
0828       double x = 0.0;
0829       double y = 0.0;
0830       for ( int i = 0, N = id.size(); i < N; ++i )
0831         if ( match(id[i]) && !match(0, id[i]) ) {
0832           x += p[i][1];
0833           y += p[i][2];
0834         }
0835       if ( outside(std::sqrt(x*x + y*y)) ) return false;
0836     }
0837     else if ( type == "HT" ) {
0838       double pt = 0.0;
0839       for ( int i = 0, N = id.size(); i < N; ++i )
0840         if ( match(id[i]) && !match(0, id[i]) )
0841           pt += std::sqrt(p[i][1]*p[i][1] + p[i][2]*p[i][2]);
0842       if ( outside(pt) ) return false;
0843     }
0844     return true;
0845   }
0846 
0847   /**
0848    * Return the pseudorapidity of a particle with momentum \a p.
0849    */
0850   static double eta(const std::vector<double> & p) {
0851     double pt2 = p[2]*p[2] + p[1]*p[1];
0852     if ( pt2 != 0.0 ) {
0853       double dum = std::sqrt(pt2 + p[3]*p[3]) + p[3];
0854       if ( dum != 0.0 )
0855         return std::log(dum/std::sqrt(pt2));
0856     }
0857     return p[3] < 0.0? -std::numeric_limits<double>::max():
0858       std::numeric_limits<double>::max();
0859   }
0860 
0861   /**
0862    * Return the true rapidity of a particle with momentum \a p.
0863    */
0864   static double rap(const std::vector<double> & p) {
0865     double pt2 = p[5]*p[5] + p[2]*p[2] + p[1]*p[1];
0866     if ( pt2 != 0.0 ) {
0867       double dum = std::sqrt(pt2 + p[3]*p[3]) + p[3];
0868       if ( dum != 0.0 )
0869         return std::log(dum/std::sqrt(pt2));
0870     }
0871     return p[3] < 0.0? -std::numeric_limits<double>::max():
0872       std::numeric_limits<double>::max();
0873   }
0874 
0875   /**
0876    * Return the delta-R of a particle pair with momenta \a p1 and \a p2.
0877    */
0878   static double deltaR(const std::vector<double> & p1,
0879                        const std::vector<double> & p2) {
0880     double deta = eta(p1) - eta(p2);
0881     double dphi = std::atan2(p1[1], p1[2]) - std::atan2(p2[1], p2[2]);
0882     if ( dphi > M_PI ) dphi -= 2.0*M_PI;
0883     if ( dphi < -M_PI ) dphi += 2.0*M_PI;
0884     return std::sqrt(dphi*dphi + deta*deta);
0885   }
0886 
0887   /**
0888    * Return true if the given \a value is outside limits.
0889    */
0890   bool outside(double value) const {
0891     return value < min || value >= max;
0892   }
0893 
0894   /**
0895    * The variable in which to cut.
0896    */
0897   std::string type;
0898 
0899   /**
0900    * The first types particle types for which this cut applies.
0901    */
0902   std::set<long> p1;
0903 
0904   /**
0905    * Symbolic name for p1.
0906    */
0907   std::string np1;
0908 
0909   /**
0910    * The second type of particles for which this cut applies.
0911    */
0912   std::set<long> p2;
0913 
0914   /**
0915    * Symbolic name for p1.
0916    */
0917   std::string np2;
0918 
0919   /**
0920    * The minimum value of the variable
0921    */
0922   double min;
0923   /**
0924    * The maximum value of the variable
0925    */
0926   double max;
0927 
0928 };
0929 
0930 /**
0931  * The ProcInfo class represents the information in a procinfo tag.
0932  */
0933 struct ProcInfo : public TagBase {
0934 
0935   /**
0936    * Intitialize default values.
0937    */
0938   ProcInfo(): iproc(0), loops(0), qcdorder(-1), eworder(-1) {}
0939 
0940   /**
0941    * Create from XML tag.
0942    */
0943   ProcInfo(const XMLTag & tag)
0944     : TagBase(tag.attr, tag.contents),
0945       iproc(0), loops(0), qcdorder(-1), eworder(-1) {
0946     getattr("iproc", iproc);
0947     getattr("loops", loops);
0948     getattr("qcdorder", qcdorder);
0949     getattr("eworder", eworder);
0950     getattr("rscheme", rscheme);
0951     getattr("fscheme", fscheme);
0952     getattr("scheme", scheme);
0953   }
0954 
0955   /**
0956    * Print out an XML tag.
0957    */
0958   void print(std::ostream & file) const {
0959     file << "<procinfo" << oattr("iproc", iproc);
0960     if ( loops >= 0 ) file << oattr("loops", loops);
0961     if ( qcdorder >= 0 ) file << oattr("qcdorder", qcdorder);
0962     if ( eworder >= 0 )    file<< oattr("eworder", eworder);
0963     if ( !rscheme.empty() ) file << oattr("rscheme", rscheme);
0964     if ( !fscheme.empty() ) file << oattr("fscheme", fscheme);
0965     if ( !scheme.empty() ) file << oattr("scheme", scheme);
0966     printattrs(file);
0967     closetag(file, "procinfo");
0968   }
0969 
0970   /**
0971    * The id number for the process.
0972    */
0973   int iproc;
0974 
0975   /**
0976    * The number of loops
0977    */
0978   int loops;
0979 
0980   /**
0981    * The number of QCD vertices.
0982    */
0983   int qcdorder;
0984 
0985   /**
0986    * The number of electro-weak vertices.
0987    */
0988   int eworder;
0989 
0990   /**
0991    * The factorization scheme used.
0992    */
0993   std::string fscheme;
0994 
0995   /**
0996    * The renormalization scheme used.
0997    */
0998   std::string rscheme;
0999 
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  */
1010 struct 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    */
1042   int iproc;
1043 
1044   /**
1045    * The merging scale used if different from the cut definitions.
1046    */
1047   double mergingscale;
1048 
1049   /**
1050    * Is this event reweighted as if it was the maximum multiplicity.
1051    */
1052   bool maxmult;
1053 
1054 };
1055 
1056 /**
1057  * The WeightInfo class encodes the description of a given weight
1058  * present for all events.
1059  */
1060 struct 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    */
1108   int inGroup;
1109 
1110   /**
1111    * Is this a weightinfo or an rwgt tag?
1112    */
1113   bool isrwgt;
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  */
1146 struct WeightGroup : public TagBase {
1147 
1148   /**
1149    * Default constructor;
1150    */
1151   WeightGroup() {}
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  */
1187 struct 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  */
1268 struct 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 
1331 struct 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    */
1412   int emitter;
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  */
1434 struct 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  */
1558 struct 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  */
1646 class HEPRUP : public TagBase {
1647 
1648 public:
1649 
1650   /** @name Standard constructors and destructors. */
1651   /// @{
1652   /**
1653    * Default constructor.
1654    */
1655   HEPRUP()
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 
1764 public:
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 >= (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 
1952 public:
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    */
1981   int IDWTUP;
1982 
1983   /**
1984    * The number of different subprocesses in this file.
1985    */
1986   int NPRUP;
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    */
2013   XSecInfos xsecinfos;
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    */
2070   int version;
2071 
2072   /**
2073    * The precision used for outputing real numbers.
2074    */
2075   int dprec;
2076 
2077 };
2078 
2079 /**
2080  * Forward declaration of the HEPEUP class.
2081  */
2082 class HEPEUP;
2083 
2084 /**
2085  * The EventGroup represents a set of events which are to be
2086  * considered together.
2087  */
2088 struct 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    */
2118   int nreal;
2119 
2120   /**
2121    * The number of counter events in this event group.
2122    */
2123   int ncounter;
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  */
2136 class HEPEUP : public TagBase {
2137 
2138 public:
2139 
2140   /** @name Standard constructors and destructors. */
2141   /// @{
2142   /**
2143    * Default constructor.
2144    */
2145   HEPEUP()
2146     : NUP(0), IDPRUP(0), XWGTUP(0.0), XPDWUP(0.0, 0.0),
2147       SCALUP(0.0), AQEDUP(0.0), AQCDUP(0.0), heprup(0), currentWeight(0),
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;
2178     namedweights = x.namedweights;
2179     weights = x.weights;
2180     pdfinfo = x.pdfinfo;
2181     PDFGUPsave = x.PDFGUPsave;
2182     PDFSUPsave = x.PDFSUPsave;
2183     clustering = x.clustering;
2184     scales = x.scales;
2185     junk = x.junk;
2186     currentWeight = x.currentWeight;
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    */
2207   ~HEPEUP() {
2208     clear();
2209   };
2210   /// @}
2211 
2212 public:
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(0), 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);
2263     pdfinfo = PDFInfo(SCALUP);
2264     namedweights.clear();
2265     weights.clear();
2266     weights.resize(heprup->nWeights(),
2267                    std::make_pair(XWGTUP, (WeightInfo*)(0)));
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, (WeightInfo*)(0)));
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, (WeightInfo*)(0)));
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                                          (WeightInfo*)(0)));
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                                          (WeightInfo*)(0)));
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 = 0;
2558     } else {
2559       setEvent(*subevents[i - 1]);
2560     }
2561     return true;
2562   }
2563 
2564 public:
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    */
2574   int IDPRUP;
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    */
2649   HEPRUP * heprup;
2650 
2651   /**
2652    * The current weight info object.
2653    */
2654   const WeightInfo * currentWeight;
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    */
2674   PDFInfo pdfinfo;
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    */
2690   Scales scales;
2691 
2692   /**
2693    * The number of attempts the ME generator did before accepting this
2694    * event.
2695    */
2696   int ntries;
2697 
2698   /**
2699    * Is this an event or an event group?
2700    */
2701   bool isGroup;
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    */
2707   EventGroup subevents;
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 
2719 inline void EventGroup::clear() {
2720   while ( size() > 0 ) {
2721     delete back();
2722     pop_back();
2723   }
2724 }
2725 
2726 inline EventGroup::~EventGroup() {
2727   clear();
2728 }
2729 
2730 inline EventGroup::EventGroup(const EventGroup & eg)
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 
2735 inline EventGroup & EventGroup::operator=(const EventGroup & x) {
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  */
2761 class Reader {
2762 
2763 public:
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 
2800 private:
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 
2879 public:
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;
2919       openeventfile(curreventfile);
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()) ) {
2937       openeventfile(curreventfile);
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 
2965 protected:
2966 
2967   /**
2968    * Used internally to read a single line from the stream.
2969    */
2970   bool getline() {
2971     return ( (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 
2981 protected:
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 
3011 public:
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    */
3031   int version;
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    */
3047   HEPRUP heprup;
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    */
3057   HEPEUP hepeup;
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    */
3067   int currevent;
3068 
3069   /**
3070    * The current event file being read from (-1 means there are no
3071    * separate event files).
3072    */
3073   int curreventfile;
3074 
3075   /**
3076    * The number of the current event in the current event file.
3077    */
3078   int currfileevent;
3079 
3080   /**
3081    * The directory from where we are reading files.
3082    */
3083   std::string dirpath;
3084 
3085 private:
3086 
3087   /**
3088    * The default constructor should never be used.
3089    */
3090   Reader();
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    */
3100   Reader & operator=(const Reader &);
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  */
3125 class Writer {
3126 
3127 public:
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    */
3151   ~Writer() {
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;
3210     curreventfile = currfileevent = -1;
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()) )
3282         openeventfile(curreventfile + 1);
3283     }
3284 
3285     hepeup.print(*file);
3286 
3287     ++lastevent;
3288     ++currfileevent;
3289   }
3290 
3291 protected:
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    */
3318   int lastevent;
3319 
3320   /**
3321    * The current event file being written to (-1 means there are no
3322    * separate event files).
3323    */
3324   int curreventfile;
3325 
3326   /**
3327    * The number of the current event in the current event file.
3328    */
3329   int currfileevent;
3330 
3331   /**
3332    * The directory from where we are reading files.
3333    */
3334   std::string dirpath;
3335 
3336 public:
3337   /**
3338    * The standard init information.
3339    */
3340   HEPRUP heprup;
3341 
3342 
3343   /**
3344    * The standard information about the event we will write next.
3345    */
3346   HEPEUP hepeup;
3347 
3348 
3349 
3350 private:
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    */
3371   Writer();
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    */
3381   Writer & operator=(const Writer &);
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 
3399 Here are some example classes for reading and writing Les Houches
3400 Event Files according to the
3401 <A HREF="http://www.thep.lu.se/~torbjorn/lhef/lhafile2.pdf">proposal</A>
3402 by Torbj&ouml;rn Sj&ouml;strand discussed at the
3403 <A HREF="http://mc4lhc06.web.cern.ch/mc4lhc06/">MC4LHC</A>
3404 workshop at CERN 2006.
3405 
3406 The classes has now been updated to handle the suggested version 3 of
3407 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>).
3408 
3409 There is a whole set of classes available in a single header file
3410 called <A
3411 HREF="http://www.thep.lu.se/~leif/LHEF/LHEF.h">LHEF.h</A>. The idea is
3412 that matrix element or parton shower generators will implement their
3413 own wrapper using these classes as containers.
3414 
3415 The two classes LHEF::HEPRUP and LHEF::HEPEUP are simple container
3416 classes which contain the same information as the Les Houches standard
3417 Fortran common blocks with the same names. They also contain the extra
3418 information defined in version 3 in the standard. The other two main
3419 classes are called LHEF::Reader and LHEF::Writer and are used to read
3420 and write Les Houches Event Files
3421 
3422 Here are a few <A HREF="examples.html">examples</A> of how to use the
3423 classes:
3424 
3425 \namespace LHEF The LHEF namespace contains some example classes for reading and writing Les Houches
3426 Event Files according to the
3427 <A HREF="http://www.thep.lu.se/~torbjorn/lhef/lhafile2.pdf">proposal</A>
3428 by Torbj&ouml;rn Sj&ouml;strand discussed at the
3429 <A HREF="http://mc4lhc06.web.cern.ch/mc4lhc06/">MC4LHC</A>
3430 workshop at CERN 2006.
3431 
3432 
3433 
3434  */
3435 
3436 
3437 #endif /* HEPMC3_LHEF_H */