66 std::ostream & operator<<(std::ostream & os, const OAttr<T> & oa) {
67 os <<
" " << oa.
name <<
"=\"" << oa.val <<
"\"";
82 typedef std::string::size_type
pos_t;
103 for (
int i = 0, N =
tags.size(); i < N; ++i )
delete tags[i];
130 bool getattr(std::string n,
double & v)
const {
131 AttributeMap::const_iterator it =
attr.find(n);
132 if ( it ==
attr.end() )
return false;
133 v = std::atof(it->second.c_str());
143 AttributeMap::const_iterator it =
attr.find(n);
144 if ( it ==
attr.end() )
return false;
145 if ( it->second ==
"yes" ) v =
true;
154 AttributeMap::const_iterator it =
attr.find(n);
155 if ( it ==
attr.end() )
return false;
156 v = std::atoi(it->second.c_str());
165 AttributeMap::const_iterator it =
attr.find(n);
166 if ( it ==
attr.end() )
return false;
167 v = int(std::atoi(it->second.c_str()));
175 bool getattr(std::string n, std::string & v)
const {
176 AttributeMap::const_iterator it =
attr.find(n);
177 if ( it ==
attr.end() )
return false;
189 std::string * leftover = 0) {
190 std::vector<XMLTag*>
tags;
193 while ( curr !=
end ) {
196 pos_t begin = str.find(
"<", curr);
199 if ( str.find(
"<!--", curr) == begin ) {
200 pos_t endcom = str.find(
"-->", begin);
201 tags.push_back(
new XMLTag());
202 if ( endcom ==
end ) {
203 tags.back()->contents = str.substr(curr);
204 if ( leftover ) *leftover += str.substr(curr);
207 tags.back()->contents = str.substr(curr, endcom - curr);
208 if ( leftover ) *leftover += str.substr(curr, endcom - curr);
213 if ( begin != curr ) {
214 tags.push_back(
new XMLTag());
215 tags.back()->contents = str.substr(curr, begin - curr);
216 if ( leftover ) *leftover += str.substr(curr, begin - curr);
218 if ( begin ==
end || begin > str.length() - 3 || str[begin + 1] ==
'/' )
221 pos_t close = str.find(
">", curr);
222 if ( close ==
end )
return tags;
225 curr = str.find_first_of(
" \t\n/>", begin);
226 tags.push_back(
new XMLTag());
227 tags.back()->name = str.substr(begin + 1, curr - begin - 1);
232 curr = str.find_first_not_of(
" \t\n", curr);
233 if ( curr ==
end || curr >= close )
break;
235 pos_t tend = str.find_first_of(
"= \t\n", curr);
236 if ( tend ==
end || tend >= close )
break;
238 std::string
name = str.substr(curr, tend - curr);
239 curr = str.find(
"=", curr) + 1;
242 curr = str.find_first_of(
"\"'", curr);
243 if ( curr ==
end || curr >= close )
break;
244 char quote = str[curr];
246 curr = str.find(quote, curr);
247 while ( curr !=
end && str[curr - 1] ==
'\\' )
248 curr = str.find(quote, curr + 1);
250 std::string value = str.substr(bega, curr ==
end?
end: curr - bega);
252 tags.back()->attr[
name] = value;
259 if ( str[close - 1] ==
'/' )
continue;
261 pos_t endtag = str.find(
"</" + tags.back()->name +
">", curr);
262 if ( endtag ==
end ) {
263 tags.back()->contents = str.substr(curr);
266 tags.back()->contents = str.substr(curr, endtag - curr);
267 curr = endtag + tags.back()->name.length() + 3;
270 std::string leftovers;
271 tags.back()->tags =
findXMLTags(tags.back()->contents, &leftovers);
272 if ( leftovers.find_first_not_of(
" \t\n") ==
end ) leftovers=
"";
273 tags.back()->contents = leftovers;
284 while ( tags.size() && tags.back() ) {
292 void print(std::ostream & os)
const {
293 if (
name.empty() ) {
298 for ( AttributeMap::const_iterator it =
attr.begin();
299 it !=
attr.end(); ++it )
300 os <<
oattr(it->first, it->second);
302 os <<
"/>" << std::endl;
306 for (
int i = 0, N =
tags.size(); i < N; ++i )
309 os <<
contents <<
"</" << name <<
">" << std::endl;
320 std::istringstream is(s);
322 while ( getline(is, ss) ) {
323 if ( ss.empty() )
continue;
324 if ( ss.find_first_not_of(
" \t") == std::string::npos )
continue;
325 if ( ss.find(
'#') == std::string::npos ||
326 ss.find(
'#') != ss.find_first_not_of(
" \t") ) ss =
"# " + ss;
359 bool getattr(std::string n,
double & v,
bool erase =
true) {
360 AttributeMap::iterator it =
attributes.find(n);
362 v = std::atof(it->second.c_str());
373 bool getattr(std::string n,
bool & v,
bool erase =
true) {
374 AttributeMap::iterator it =
attributes.find(n);
376 if ( it->second ==
"yes" ) v =
true;
387 bool getattr(std::string n,
long & v,
bool erase =
true) {
388 AttributeMap::iterator it =
attributes.find(n);
390 v = std::atoi(it->second.c_str());
401 bool getattr(std::string n,
int & v,
bool erase =
true) {
402 AttributeMap::iterator it =
attributes.find(n);
404 v = int(std::atoi(it->second.c_str()));
415 bool getattr(std::string n, std::string & v,
bool erase =
true) {
416 AttributeMap::iterator it =
attributes.find(n);
427 for ( AttributeMap::const_iterator it =
attributes.begin();
429 file <<
oattr(it->first, it->second);
436 void closetag(std::ostream & file, std::string tag)
const {
439 else if (
contents.find(
'\n') != std::string::npos )
440 file <<
">\n" <<
contents <<
"\n</" << tag <<
">\n";
442 file <<
">" <<
contents <<
"</" << tag <<
">\n";
458 static std::string
yes() {
return "yes"; }
479 void print(std::ostream & file)
const {
480 file <<
"<generator";
517 throw std::runtime_error(
"Found xsecinfo tag without neve attribute "
518 "in Les Houches Event File.");
520 throw std::runtime_error(
"Found xsecinfo tag without totxsec "
521 "attribute in Les Houches Event File.");
532 void print(std::ostream & file)
const {
583 max(0.99*std::numeric_limits<double>::
max()) {}
589 const std::map<std::string,std::set<long> >& ptypes)
591 min(-0.99*std::numeric_limits<double>::
max()),
592 max(0.99*std::numeric_limits<double>::
max()) {
594 throw std::runtime_error(
"Found cut tag without type attribute "
595 "in Les Houches file");
598 if ( ptypes.find(
np1) != ptypes.end() ) {
599 p1 = ptypes.find(
np1)->second;
608 if ( ptypes.find(
np2) != ptypes.end() ) {
609 p2 = ptypes.find(
np2)->second;
618 std::istringstream iss(tag.
contents);
622 min = -0.99*std::numeric_limits<double>::max();
624 max = 0.99*std::numeric_limits<double>::max();
630 void print(std::ostream & file)
const {
635 if (
p1.size() == 1 ) file <<
oattr(
"p1", *
p1.begin());
639 if (
p2.size() == 1 ) file <<
oattr(
"p2", *
p2.begin());
643 if (
min > -0.9*std::numeric_limits<double>::max() )
647 if ( max < 0.9*std::numeric_limits<double>::max() )
650 file <<
"</cut>" << std::endl;
657 bool match(
long id1,
long id2 = 0)
const {
658 std::pair<bool,bool> ret(
false,
false);
659 if ( !id2 ) ret.second =
true;
660 if ( !id1 ) ret.first =
true;
661 if (
p1.find(0) !=
p1.end() ) ret.first =
true;
662 if (
p1.find(id1) !=
p1.end() ) ret.first =
true;
663 if (
p2.find(0) !=
p2.end() ) ret.second =
true;
664 if (
p2.find(id2) !=
p2.end() ) ret.second =
true;
665 return ret.first && ret.second;
674 const std::vector< std::vector<double> >& p )
const {
675 if ( (
type ==
"m" && !
p2.size() ) ||
type ==
"kt" ||
type ==
"eta" ||
677 for (
int i = 0, N =
id.size(); i < N; ++i )
678 if (
match(
id[i]) ) {
680 double v = p[i][4]*p[i][4] - p[i][3]*p[i][3] - p[i][2]*p[i][2]
682 v = v >= 0.0? std::sqrt(v): -std::sqrt(-v);
683 if (
outside(v) )
return false;
685 else if (
type ==
"kt" ) {
686 if (
outside(std::sqrt(p[i][2]*p[i][2] + p[i][1]*p[i][1])) )
689 else if (
type ==
"E" ) {
690 if (
outside(p[i][4]) )
return false;
692 else if (
type ==
"eta" ) {
695 else if (
type ==
"y" ) {
700 else if (
type ==
"m" ||
type ==
"deltaR" ) {
701 for (
int i = 1, N =
id.size(); i < N; ++i )
702 for (
int j = 0; j < i; ++j )
703 if (
match(
id[i],
id[j]) ||
match(
id[j],
id[i]) ) {
705 double v = (p[i][4] + p[j][4])*(p[i][4] + p[j][4])
706 - (p[i][3] + p[j][3])*(p[i][3] + p[j][3])
707 - (p[i][2] + p[j][2])*(p[i][2] + p[j][2])
708 - (p[i][1] + p[j][1])*(p[i][1] + p[j][1]);
709 v = v >= 0.0? std::sqrt(v): -std::sqrt(-v);
710 if (
outside(v) )
return false;
712 else if (
type ==
"deltaR" ) {
717 else if (
type ==
"ETmiss" ) {
720 for (
int i = 0, N =
id.size(); i < N; ++i )
725 if (
outside(std::sqrt(x*x + y*y)) )
return false;
727 else if (
type ==
"HT" ) {
729 for (
int i = 0, N =
id.size(); i < N; ++i )
731 pt += std::sqrt(p[i][1]*p[i][1] + p[i][2]*p[i][2]);
732 if (
outside(pt) )
return false;
740 static double eta(
const std::vector<double> & p) {
741 double pt2 = p[2]*p[2] + p[1]*p[1];
743 double dum = std::sqrt(pt2 + p[3]*p[3]) + p[3];
745 return std::log(dum/std::sqrt(pt2));
747 return p[3] < 0.0? -std::numeric_limits<double>::max():
748 std::numeric_limits<double>::max();
754 static double rap(
const std::vector<double> & p) {
755 double pt2 = p[5]*p[5] + p[2]*p[2] + p[1]*p[1];
757 double dum = std::sqrt(pt2 + p[3]*p[3]) + p[3];
759 return std::log(dum/std::sqrt(pt2));
761 return p[3] < 0.0? -std::numeric_limits<double>::max():
762 std::numeric_limits<double>::max();
768 static double deltaR(
const std::vector<double> &
p1,
769 const std::vector<double> &
p2) {
770 double deta =
eta(p1) -
eta(p2);
771 double dphi = std::atan2(p1[1], p1[2]) - std::atan2(p2[1], p2[2]);
772 if ( dphi > M_PI ) dphi -= 2.0*M_PI;
773 if ( dphi < -M_PI ) dphi += 2.0*M_PI;
774 return std::sqrt(dphi*dphi + deta*deta);
781 return value < min || value >=
max;
848 void print(std::ostream & file)
const {
921 void print(std::ostream & file)
const {
922 file <<
"<mergeinfo" <<
oattr(
"iproc",
iproc);
978 void print(std::ostream & file)
const {
983 file <<
"<weightinfo" <<
oattr(
"name",
name);
1051 for (
int i = 0, N = tag.
tags.size(); i < N; ++i ) {
1052 if ( tag.
tags[i]->name ==
"weight" ||
1053 tag.
tags[i]->name ==
"weightinfo" ) {
1096 std::istringstream iss(tag.
contents);
1098 while ( iss >> w )
weights.push_back(w);
1115 for (
int j = 0, M =
weights.size(); j < M; ++j ) file <<
" " <<
weights[j];
1116 file <<
"</weight>" << std::endl;
1169 std::istringstream iss(tag.
contents);
1171 if ( !( iss >>
p0 ) )
p0 =
p1;
1181 file <<
">" <<
p1 <<
" " <<
p2;
1182 if (
p1 !=
p0 ) file <<
" " <<
p0;
1183 file <<
"</clus>" << std::endl;
1301 if (
xf1 <= 0 )
return;
1309 file <<
">" <<
xf1 <<
" " <<
xf2 <<
"</pdfinfo>" << std::endl;
1410 std::vector<XMLTag*> tags = tag.
tags;
1413 std::istringstream iss(tags[0]->
contents);
1417 throw std::runtime_error(
"Could not parse init block "
1418 "in Les Houches Event File.");
1422 for (
int i = 0; i <
NPRUP; ++i ) {
1424 throw std::runtime_error(
"Could not parse processes in init block "
1425 "in Les Houches Event File.");
1429 for (
int i = 1, N = tags.size(); i < N; ++i ) {
1430 const XMLTag & tag = *tags[i];
1434 if ( tag.
name ==
"initrwgt" ) {
1435 for (
int j = 0, M = tag.
tags.size(); j < M; ++j ) {
1436 if ( tag.
tags[j]->name ==
"weightgroup" )
1439 if ( tag.
tags[j]->name ==
"weight" )
1444 if ( tag.
name ==
"weightinfo" ) {
1447 if ( tag.
name ==
"weightgroup" ) {
1451 if ( tag.
name ==
"xsecinfo" ) {
1454 if ( tag.
name ==
"generator" ) {
1457 else if ( tag.
name ==
"cutsinfo" ) {
1458 for (
int j = 0, M = tag.
tags.size(); j < M; ++j ) {
1461 if ( ctag.
name ==
"ptype" ) {
1462 std::string tname = ctag.
attr[
"name"];
1464 std::istringstream iss(ctag.
contents);
1465 while ( iss >>
id )
ptypes[tname].insert(
id);
1467 else if ( ctag.
name ==
"cut" )
1471 else if ( tag.
name ==
"procinfo" ) {
1475 else if ( tag.
name ==
"mergeinfo" ) {
1483 for (
int i = 0, N =
weightinfo.size(); i < N; ++i )
1502 if ( i < 0 || i >= (
int)
weightinfo.size() )
return name;
1519 <<
" " << setw(8) <<
IDBMUP.first
1520 <<
" " << setw(8) <<
IDBMUP.second
1521 <<
" " << setw(14) <<
EBMUP.first
1522 <<
" " << setw(14) <<
EBMUP.second
1523 <<
" " << setw(4) <<
PDFGUP.first
1524 <<
" " << setw(4) <<
PDFGUP.second
1525 <<
" " << setw(4) <<
PDFSUP.first
1526 <<
" " << setw(4) <<
PDFSUP.second
1527 <<
" " << setw(4) <<
IDWTUP
1528 <<
" " << setw(4) <<
NPRUP << std::endl;
1530 for (
int i = 0; i <
NPRUP; ++i )
1531 file <<
" " << setw(14) <<
XSECUP[i]
1532 <<
" " << setw(14) <<
XERRUP[i]
1533 <<
" " << setw(14) <<
XMAXUP[i]
1534 <<
" " << setw(6) <<
LPRUP[i] << std::endl;
1536 for (
int i = 0, N =
generators.size(); i < N; ++i )
1541 if (
cuts.size() > 0 ) {
1542 file <<
"<cutsinfo>" << std::endl;
1544 for ( std::map<std::string, std::set<long> >::const_iterator ptit =
1546 file <<
"<ptype" <<
oattr(
"name", ptit->first) <<
">";
1547 for ( std::set<long>::const_iterator it = ptit->second.begin();
1548 it != ptit->second.end(); ++it )
1550 file <<
"</ptype>" << std::endl;
1553 for (
int i = 0, N =
cuts.size(); i < N; ++i )
1555 file <<
"</cutsinfo>" << std::endl;
1558 for ( std::map<long,ProcInfo>::const_iterator it =
procinfo.begin();
1560 it->second.print(file);
1562 for ( std::map<long,MergeInfo>::const_iterator it =
mergeinfo.begin();
1564 it->second.print(file);
1566 bool isrwgt =
false;
1568 for (
int i = 0, N =
weightinfo.size(); i < N; ++i ) {
1570 if ( !isrwgt ) file <<
"<initrwgt>\n";
1573 if ( isrwgt ) file <<
"</initrwgt>\n";
1577 if ( group != ingroup ) {
1578 if ( ingroup != -1 ) file <<
"</weightgroup>\n";
1579 if ( group != -1 ) {
1580 file <<
"<weightgroup"
1590 if ( ingroup != -1 ) file <<
"</weightgroup>\n";
1591 if ( isrwgt ) file <<
"</initrwgt>\n";
1637 std::map<std::string, int>::const_iterator it =
weightmap.find(name);
1638 if ( it !=
weightmap.end() )
return it->second;
1720 std::map<std::string, std::set<long> >
ptypes;
1794 inline void clear();
1907 throw std::runtime_error(
"Tried to read events but no processes defined "
1908 "in init block of Les Houches file.");
1910 std::vector<XMLTag*> tags = tag.
tags;
1915 for (
int i = 0, N = tags.size(); i < N; ++i )
1916 if ( tags[i]->name ==
"event" )
1924 std::istringstream iss(tags[0]->
contents);
1926 throw std::runtime_error(
"Failed to parse event in Les Houches file.");
1931 for (
int i = 0; i <
NUP; ++i ) {
1935 >>
PUP[i][3] >>
PUP[i][4]
1937 throw std::runtime_error(
"Failed to parse event in Les Houches file.");
1942 while ( getline(iss, ss) )
junk += ss +
'\n';
1951 for (
int i = 1, N =
weights.size(); i < N; ++i )
1954 for (
int i = 1, N = tags.size(); i < N; ++i ) {
1959 if ( tag.
name ==
"weights" ) {
1963 for (
int i = 1, N =
weights.size(); i < N; ++i )
1967 std::istringstream iss(tag.
contents);
1969 if ( ++i <
int(
weights.size()) )
1974 if ( tag.
name ==
"weight" ) {
1977 if ( tag.
name ==
"rwgt" ) {
1978 for (
int j = 0, M = tag.
tags.size(); j < M; ++j ) {
1979 if ( tag.
tags[j]->name ==
"wgt" ) {
1984 else if ( tag.
name ==
"clustering" ) {
1985 for (
int j = 0, M= tag.
tags.size(); j < M; ++j ) {
1986 if ( tag.
tags[j]->name ==
"clus" )
1990 else if ( tag.
name ==
"pdfinfo" ) {
1993 else if ( tag.
name ==
"scales" ) {
1999 for (
int i = 0, N =
namedweights.size(); i < N; ++i ) {
2026 file <<
"<eventgroup";
2033 for (
int i = 0, N =
subevents.size(); i < N; ++i )
2035 file <<
"</eventgroup>\n";
2042 file <<
" " << setw(4) <<
NUP
2043 <<
" " << setw(6) <<
IDPRUP
2044 <<
" " << setw(14) <<
XWGTUP
2045 <<
" " << setw(14) <<
SCALUP
2046 <<
" " << setw(14) <<
AQEDUP
2047 <<
" " << setw(14) <<
AQCDUP <<
"\n";
2049 for (
int i = 0; i <
NUP; ++i )
2050 file <<
" " << setw(8) <<
IDUP[i]
2051 <<
" " << setw(2) <<
ISTUP[i]
2052 <<
" " << setw(4) <<
MOTHUP[i].first
2053 <<
" " << setw(4) <<
MOTHUP[i].second
2054 <<
" " << setw(4) <<
ICOLUP[i].first
2055 <<
" " << setw(4) <<
ICOLUP[i].second
2056 <<
" " << setw(14) <<
PUP[i][0]
2057 <<
" " << setw(14) <<
PUP[i][1]
2058 <<
" " << setw(14) <<
PUP[i][2]
2059 <<
" " << setw(14) <<
PUP[i][3]
2060 <<
" " << setw(14) <<
PUP[i][4]
2061 <<
" " << setw(1) <<
VTIMUP[i]
2062 <<
" " << setw(1) <<
SPINUP[i] << std::endl;
2065 file <<
"<weights>";
2066 for (
int i = 1, N =
weights.size(); i < N; ++i )
2067 file <<
" " <<
weights[i].first;
2068 file <<
"</weights>\n";
2072 for (
int i = 0, N =
namedweights.size(); i < N; ++i ) {
2074 if ( !iswgt ) file <<
"<rwgt>\n";
2077 if ( iswgt ) file <<
"</rwgt>\n";
2080 for (
int j = 0, M =
namedweights[i].indices.size(); j < M; ++j )
2084 if ( iswgt ) file <<
"</rwgt>\n";
2087 file <<
"<clustering>" << std::endl;
2088 for (
int i = 0, N =
clustering.size(); i < N; ++i )
2090 file <<
"</clustering>" << std::endl;
2137 for (
int i = 0, N =
subevents.size(); i < N; ++i )
2175 if ( i >=
int(
weights.size()) )
return false;
2191 PUP.resize(
NUP, std::vector<double>(5));
2201 if ( i >=
weights.size() )
return false;
2236 for (
int i = 1, N =
subevents.size(); i < N; ++i )
2237 for (
int j = 0, M =
weights.size(); j < M; ++j )
2313 std::vector< std::vector<double> >
PUP;
2346 std::vector< std::pair<double, const WeightInfo *> >
weights;
2396 while ( size() > 0 ) {
2407 : std::vector<
HEPEUP*>(eg.size()) {
2408 for (
int i = 0, N = eg.size(); i < N; ++i ) at(i) =
new HEPEUP(*eg.at(i));
2412 if ( &x ==
this )
return *
this;
2416 for (
int i = 0, N = x.size(); i < N; ++i ) push_back(
new HEPEUP(*x.at(i)));
2479 bool readingHeader =
false;
2480 bool readingInit =
false;
2485 throw std::runtime_error
2486 (
"Tried to read a file which does not start with the "
2487 "LesHouchesEvents tag.");
2494 throw std::runtime_error
2495 (
"Tried to read a LesHouchesEvents file which is above version 3.");
2503 readingHeader =
true;
2514 readingHeader =
false;
2517 else if ( readingHeader ) {
2522 else if ( readingInit ) {
2532 throw std::runtime_error(
"Found incomplete init tag in "
2533 "Les Houches file.");
2536 for (
int i = 0, N = tags.size(); i < N; ++i )
2537 if ( tags[i]->name ==
"init" ) {
2559 std::string eventLines;
2566 if ( inEvent == 1 &&
currentFind(
"</event>") )
break;
2567 if ( inEvent == 2 &&
currentFind(
"</eventgroup>") )
break;
2581 if ( inEvent == 1 && !
currentFind(
"</event>") )
return false;
2582 if ( inEvent == 2 && !
currentFind(
"</eventgroup>") )
return false;
2586 for (
int i = 0, N = tags.size(); i < N ; ++i ) {
2587 if ( tags[i]->name ==
"event" || tags[i]->name ==
"eventgroup" ) {
2612 return currentLine.find(str) != std::string::npos;
2734 file <<
"</LesHouchesEvents>" << std::endl;
2766 file <<
"<LesHouchesEvents version=\"3.0\">\n";
2768 file <<
"<LesHouchesEvents version=\"2.0\">\n";
2770 file <<
"<LesHouchesEvents version=\"1.0\">\n";
2773 file << std::setprecision(8);
2778 if ( headerBlock.length() ) {
2779 if ( headerBlock.find(
"<header>") == std::string::npos )
2780 file <<
"<header>\n";
2781 if ( headerBlock[headerBlock.length() - 1] !=
'\n' )
2782 headerBlock +=
'\n';
2784 if ( headerBlock.find(
"</header>") == std::string::npos )
2785 file <<
"</header>\n";