CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/GeneratorInterface/LHEInterface/src/LHERunInfo.cc

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