00001 #include <algorithm>
00002 #include <iostream>
00003 #include <iomanip>
00004 #include <string>
00005 #include <cctype>
00006 #include <vector>
00007 #include <memory>
00008 #include <cmath>
00009
00010 #include <boost/bind.hpp>
00011
00012 #include <xercesc/dom/DOM.hpp>
00013 #include <xercesc/parsers/XercesDOMParser.hpp>
00014 #include <xercesc/sax/HandlerBase.hpp>
00015
00016 #include "FWCore/Utilities/interface/Exception.h"
00017 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00018
00019 #include "SimDataFormats/GeneratorProducts/interface/LesHouches.h"
00020
00021 #include "GeneratorInterface/LHEInterface/interface/LHERunInfo.h"
00022
00023 #include "XMLUtils.h"
00024
00025 XERCES_CPP_NAMESPACE_USE
00026
00027 static int skipWhitespace(std::istream &in)
00028 {
00029 int ch;
00030 do {
00031 ch = in.get();
00032 } while(std::isspace(ch));
00033 if (ch != std::istream::traits_type::eof())
00034 in.putback(ch);
00035 return ch;
00036 }
00037
00038 namespace lhef {
00039
00040 LHERunInfo::LHERunInfo(std::istream &in)
00041 {
00042 in >> heprup.IDBMUP.first >> heprup.IDBMUP.second
00043 >> heprup.EBMUP.first >> heprup.EBMUP.second
00044 >> heprup.PDFGUP.first >> heprup.PDFGUP.second
00045 >> heprup.PDFSUP.first >> heprup.PDFSUP.second
00046 >> heprup.IDWTUP >> heprup.NPRUP;
00047 if (!in.good())
00048 throw cms::Exception("InvalidFormat")
00049 << "Les Houches file contained invalid"
00050 " header in init section." << std::endl;
00051
00052 heprup.resize();
00053
00054 for(int i = 0; i < heprup.NPRUP; i++) {
00055 in >> heprup.XSECUP[i] >> heprup.XERRUP[i]
00056 >> heprup.XMAXUP[i] >> heprup.LPRUP[i];
00057 if (!in.good())
00058 throw cms::Exception("InvalidFormat")
00059 << "Les Houches file contained invalid data"
00060 " in header payload line " << (i + 1)
00061 << "." << std::endl;
00062 }
00063
00064 while(skipWhitespace(in) == '#') {
00065 std::string line;
00066 std::getline(in, line);
00067 comments.push_back(line + "\n");
00068 }
00069
00070 if (!in.eof())
00071 edm::LogWarning("Generator|LHEInterface")
00072 << "Les Houches file contained spurious"
00073 " content after the regular data." << std::endl;
00074
00075 init();
00076 }
00077
00078 LHERunInfo::LHERunInfo(const HEPRUP &heprup) :
00079 heprup(heprup)
00080 {
00081 init();
00082 }
00083
00084 LHERunInfo::LHERunInfo(const HEPRUP &heprup,
00085 const std::vector<LHERunInfoProduct::Header> &headers,
00086 const std::vector<std::string> &comments) :
00087 heprup(heprup)
00088 {
00089 std::copy(headers.begin(), headers.end(),
00090 std::back_inserter(this->headers));
00091 std::copy(comments.begin(), comments.end(),
00092 std::back_inserter(this->comments));
00093
00094 init();
00095 }
00096
00097 LHERunInfo::LHERunInfo(const LHERunInfoProduct &product) :
00098 heprup(product.heprup())
00099 {
00100 std::copy(product.headers_begin(), product.headers_end(),
00101 std::back_inserter(headers));
00102 std::copy(product.comments_begin(), product.comments_end(),
00103 std::back_inserter(comments));
00104
00105 init();
00106 }
00107
00108 LHERunInfo::~LHERunInfo()
00109 {
00110 }
00111
00112 void LHERunInfo::init()
00113 {
00114 for(int i = 0; i < heprup.NPRUP; i++) {
00115 Process proc;
00116
00117 proc.process = heprup.LPRUP[i];
00118 proc.heprupIndex = (unsigned int)i;
00119
00120 processes.push_back(proc);
00121 }
00122
00123 std::sort(processes.begin(), processes.end());
00124 }
00125
00126 bool LHERunInfo::operator == (const LHERunInfo &other) const
00127 {
00128 return heprup == other.heprup;
00129 }
00130
00131 void LHERunInfo::count(int process, CountMode mode, double eventWeight,
00132 double brWeight, double matchWeight)
00133 {
00134 std::vector<Process>::iterator proc =
00135 std::lower_bound(processes.begin(), processes.end(), process);
00136 if (proc == processes.end() || proc->process != process)
00137 return;
00138
00139 switch(mode) {
00140 case kAccepted:
00141 proc->acceptedBr.add(eventWeight * brWeight * matchWeight);
00142 proc->accepted.add(eventWeight * matchWeight);
00143 case kKilled:
00144 proc->killed.add(eventWeight * matchWeight);
00145 case kSelected:
00146 proc->selected.add(eventWeight);
00147 case kTried:
00148 proc->tried.add(eventWeight);
00149 }
00150 }
00151
00152 LHERunInfo::XSec LHERunInfo::xsec() const
00153 {
00154 double sigSelSum = 0.0;
00155 double sigSum = 0.0;
00156 double sigBrSum = 0.0;
00157 double err2Sum = 0.0;
00158 double errBr2Sum = 0.0;
00159
00160 for(std::vector<Process>::const_iterator proc = processes.begin();
00161 proc != processes.end(); ++proc) {
00162 unsigned int idx = proc->heprupIndex;
00163
00164 double sigmaSum, sigma2Sum, sigma2Err;
00165 if (std::abs(heprup.IDWTUP) == 3) {
00166 sigmaSum = proc->tried.n * heprup.XSECUP[idx];
00167 sigma2Sum = sigmaSum * heprup.XSECUP[idx];
00168 sigma2Err = proc->tried.n * heprup.XERRUP[idx]
00169 * heprup.XERRUP[idx];
00170 } else {
00171 sigmaSum = proc->tried.sum;
00172 sigma2Sum = proc->tried.sum2;
00173 sigma2Err = 0.0;
00174 }
00175
00176 if (!proc->killed.n)
00177 continue;
00178
00179 double sigmaAvg = sigmaSum / proc->tried.sum;
00180 double fracAcc = proc->killed.sum / proc->selected.sum;
00181 double fracBr = proc->accepted.sum > 0.0 ?
00182 proc->acceptedBr.sum / proc->accepted.sum : 1;
00183 double sigmaFin = sigmaAvg * fracAcc * fracBr;
00184 double sigmaFinBr = sigmaFin * fracBr;
00185
00186 double relErr = 1.0;
00187 if (proc->killed.n > 1) {
00188 double sigmaAvg2 = sigmaAvg * sigmaAvg;
00189 double delta2Sig =
00190 (sigma2Sum / proc->tried.n - sigmaAvg2) /
00191 (proc->tried.n * sigmaAvg2);
00192 double delta2Veto =
00193 ((double)proc->selected.n - proc->killed.n) /
00194 ((double)proc->selected.n * proc->killed.n);
00195 double delta2Sum = delta2Sig + delta2Veto
00196 + sigma2Err / sigma2Sum;
00197 relErr = (delta2Sum > 0.0 ?
00198 std::sqrt(delta2Sum) : 0.0);
00199 }
00200 double deltaFin = sigmaFin * relErr;
00201 double deltaFinBr = sigmaFinBr * relErr;
00202
00203 sigSelSum += sigmaAvg;
00204 sigSum += sigmaFin;
00205 sigBrSum += sigmaFinBr;
00206 err2Sum += deltaFin * deltaFin;
00207 errBr2Sum += deltaFinBr * deltaFinBr;
00208 }
00209
00210 XSec result;
00211 result.value = 1.0e-9 * sigBrSum;
00212 result.error = 1.0e-9 * std::sqrt(errBr2Sum);
00213
00214 return result;
00215 }
00216
00217 void LHERunInfo::statistics() const
00218 {
00219 double sigSelSum = 0.0;
00220 double sigSum = 0.0;
00221 double sigBrSum = 0.0;
00222 double err2Sum = 0.0;
00223 double errBr2Sum = 0.0;
00224 unsigned long nAccepted = 0;
00225 unsigned long nTried = 0;
00226
00227 std::cout << std::endl;
00228 std::cout << "Process and cross-section statistics" << std::endl;
00229 std::cout << "------------------------------------" << std::endl;
00230 std::cout << "Process\tevents\ttried\txsec [pb]\t\taccepted [%]"
00231 << std::endl;
00232
00233 for(std::vector<Process>::const_iterator proc = processes.begin();
00234 proc != processes.end(); ++proc) {
00235 unsigned int idx = proc->heprupIndex;
00236
00237 double sigmaSum, sigma2Sum, sigma2Err;
00238 if (std::abs(heprup.IDWTUP) == 3) {
00239 sigmaSum = proc->tried.n * heprup.XSECUP[idx];
00240 sigma2Sum = sigmaSum * heprup.XSECUP[idx];
00241 sigma2Err = proc->tried.n * heprup.XERRUP[idx]
00242 * heprup.XERRUP[idx];
00243 } else {
00244 sigmaSum = proc->tried.sum;
00245 sigma2Sum = proc->tried.sum2;
00246 sigma2Err = 0.0;
00247 }
00248
00249 if (!proc->selected.n) {
00250 std::cout << proc->process << "\t0\t0\tn/a\t\t\tn/a"
00251 << std::endl;
00252 continue;
00253 }
00254
00255 double sigmaAvg = sigmaSum / proc->tried.sum;
00256 double fracAcc = proc->killed.sum / proc->selected.sum;
00257 double fracBr = proc->accepted.sum > 0.0 ?
00258 proc->acceptedBr.sum / proc->accepted.sum : 1;
00259 double sigmaFin = sigmaAvg * fracAcc;
00260 double sigmaFinBr = sigmaFin * fracBr;
00261
00262 double relErr = 1.0;
00263 if (proc->killed.n > 1) {
00264 double sigmaAvg2 = sigmaAvg * sigmaAvg;
00265 double delta2Sig =
00266 (sigma2Sum / proc->tried.n - sigmaAvg2) /
00267 (proc->tried.n * sigmaAvg2);
00268 double delta2Veto =
00269 ((double)proc->selected.n - proc->killed.n) /
00270 ((double)proc->selected.n * proc->killed.n);
00271 double delta2Sum = delta2Sig + delta2Veto
00272 + sigma2Err / sigma2Sum;
00273 relErr = (delta2Sum > 0.0 ?
00274 std::sqrt(delta2Sum) : 0.0);
00275 }
00276 double deltaFin = sigmaFin * relErr;
00277 double deltaFinBr = sigmaFinBr * relErr;
00278
00279 std::cout << proc->process << "\t"
00280 << proc->accepted.n << "\t"
00281 << proc->tried.n << "\t"
00282 << std::scientific << std::setprecision(3)
00283 << sigmaFinBr << " +/- "
00284 << deltaFinBr << "\t"
00285 << std::fixed << std::setprecision(1)
00286 << (fracAcc * 100) << std::endl;
00287
00288 nAccepted += proc->accepted.n;
00289 nTried += proc->tried.n;
00290 sigSelSum += sigmaAvg;
00291 sigSum += sigmaFin;
00292 sigBrSum += sigmaFinBr;
00293 err2Sum += deltaFin * deltaFin;
00294 errBr2Sum += deltaFinBr * deltaFinBr;
00295 }
00296
00297 std::cout << "Total\t"
00298 << nAccepted << "\t"
00299 << nTried << "\t"
00300 << std::scientific << std::setprecision(3)
00301 << sigBrSum << " +/- "
00302 << std::sqrt(errBr2Sum) << "\t"
00303 << std::fixed << std::setprecision(1)
00304 << (sigSum / sigSelSum * 100) << std::endl;
00305 }
00306
00307 LHERunInfo::Header::Header() :
00308 xmlDoc(0)
00309 {
00310 }
00311
00312 LHERunInfo::Header::Header(const std::string &tag) :
00313 LHERunInfoProduct::Header(tag), xmlDoc(0)
00314 {
00315 }
00316
00317 LHERunInfo::Header::Header(const Header &orig) :
00318 LHERunInfoProduct::Header(orig), xmlDoc(0)
00319 {
00320 }
00321
00322 LHERunInfo::Header::Header(const LHERunInfoProduct::Header &orig) :
00323 LHERunInfoProduct::Header(orig), xmlDoc(0)
00324 {
00325 }
00326
00327 LHERunInfo::Header::~Header()
00328 {
00329 if (xmlDoc)
00330 xmlDoc->release();
00331 }
00332
00333 static void fillLines(std::vector<std::string> &lines, const char *data,
00334 int len = -1)
00335 {
00336 const char *end = len >= 0 ? (data + len) : 0;
00337 while(*data && (!end || data < end)) {
00338 std::size_t len = std::strcspn(data, "\r\n");
00339 if (end && data + len > end)
00340 len = end - data;
00341 if (data[len] == '\r' && data[len + 1] == '\n')
00342 len += 2;
00343 else if (data[len])
00344 len++;
00345 lines.push_back(std::string(data, len));
00346 data += len;
00347 }
00348 }
00349
00350 static std::vector<std::string> domToLines(const DOMNode *node)
00351 {
00352 std::vector<std::string> result;
00353 DOMImplementation *impl =
00354 DOMImplementationRegistry::getDOMImplementation(
00355 XMLUniStr("Core"));
00356 std::auto_ptr<DOMWriter> writer(
00357 static_cast<DOMImplementationLS*>(impl)->createDOMWriter());
00358
00359 writer->setEncoding(XMLUniStr("UTF-8"));
00360 XMLSimpleStr buffer(writer->writeToString(*node));
00361
00362 const char *p = std::strchr((const char*)buffer, '>') + 1;
00363 const char *q = std::strrchr(p, '<');
00364 fillLines(result, p, q - p);
00365
00366 return result;
00367 }
00368
00369 std::vector<std::string> LHERunInfo::findHeader(const std::string &tag) const
00370 {
00371 const LHERunInfo::Header *header = 0;
00372 for(std::vector<Header>::const_iterator iter = headers.begin();
00373 iter != headers.end(); ++iter) {
00374 if (iter->tag() == tag)
00375 return std::vector<std::string>(iter->begin(),
00376 iter->end());
00377 if (iter->tag() == "header")
00378 header = &*iter;
00379 }
00380
00381 if (!header)
00382 return std::vector<std::string>();
00383
00384 const DOMNode *root = header->getXMLNode();
00385 if (!root)
00386 return std::vector<std::string>();
00387
00388 for(const DOMNode *iter = root->getFirstChild();
00389 iter; iter = iter->getNextSibling()) {
00390 if (iter->getNodeType() != DOMNode::ELEMENT_NODE)
00391 continue;
00392 if (tag == (const char*)XMLSimpleStr(iter->getNodeName()))
00393 return domToLines(iter);
00394 }
00395
00396 return std::vector<std::string>();
00397 }
00398
00399 namespace {
00400 class HeaderReader : public CBInputStream::Reader {
00401 public:
00402 HeaderReader(const LHERunInfo::Header *header) :
00403 header(header), mode(kHeader),
00404 iter(header->begin())
00405 {
00406 }
00407
00408 const std::string &data()
00409 {
00410 switch(mode) {
00411 case kHeader:
00412 tmp = "<" + header->tag() + ">";
00413 mode = kBody;
00414 break;
00415 case kBody:
00416 if (iter != header->end())
00417 return *iter++;
00418 tmp = "</" + header->tag() + ">";
00419 mode = kFooter;
00420 break;
00421 case kFooter:
00422 tmp.clear();
00423 }
00424
00425 return tmp;
00426 }
00427
00428 private:
00429 enum Mode {
00430 kHeader,
00431 kBody,
00432 kFooter
00433 };
00434
00435 const LHERunInfo::Header *header;
00436 Mode mode;
00437 LHERunInfo::Header::const_iterator iter;
00438 std::string tmp;
00439 };
00440 }
00441
00442 const DOMNode *LHERunInfo::Header::getXMLNode() const
00443 {
00444 if (tag().empty())
00445 return 0;
00446
00447 if (!xmlDoc) {
00448 XercesDOMParser parser;
00449 parser.setValidationScheme(XercesDOMParser::Val_Auto);
00450 parser.setDoNamespaces(false);
00451 parser.setDoSchema(false);
00452 parser.setValidationSchemaFullChecking(false);
00453
00454 HandlerBase errHandler;
00455 parser.setErrorHandler(&errHandler);
00456 parser.setCreateEntityReferenceNodes(false);
00457
00458 try {
00459 std::auto_ptr<CBInputStream::Reader> reader(
00460 new HeaderReader(this));
00461 CBInputSource source(reader);
00462 parser.parse(source);
00463 xmlDoc = parser.adoptDocument();
00464 } catch(const XMLException &e) {
00465 throw cms::Exception("Generator|LHEInterface")
00466 << "XML parser reported DOM error no. "
00467 << (unsigned long)e.getCode()
00468 << ": " << XMLSimpleStr(e.getMessage()) << "."
00469 << std::endl;
00470 } catch(const SAXException &e) {
00471 throw cms::Exception("Generator|LHEInterface")
00472 << "XML parser reported: "
00473 << XMLSimpleStr(e.getMessage()) << "."
00474 << std::endl;
00475 }
00476 }
00477
00478 return xmlDoc->getDocumentElement();
00479 }
00480
00481 }