CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch13/src/GeneratorInterface/LHEInterface/src/LHEReader.cc

Go to the documentation of this file.
00001 #include <algorithm>
00002 #include <iostream>
00003 #include <sstream>
00004 #include <fstream>
00005 #include <cstring>
00006 #include <string>
00007 #include <vector>
00008 
00009 #include <boost/bind.hpp>
00010 
00011 #include <xercesc/sax2/Attributes.hpp>
00012 #include <xercesc/dom/DOM.hpp>
00013 
00014 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00015 #include "FWCore/Utilities/interface/Exception.h"
00016 
00017 #include "GeneratorInterface/LHEInterface/interface/LHEReader.h"
00018 #include "GeneratorInterface/LHEInterface/interface/LHERunInfo.h"
00019 #include "GeneratorInterface/LHEInterface/interface/LHEEvent.h"
00020 
00021 #include "Utilities/StorageFactory/interface/IOTypes.h"
00022 #include "Utilities/StorageFactory/interface/Storage.h"
00023 #include "Utilities/StorageFactory/interface/StorageFactory.h"
00024 
00025 #include "XMLUtils.h"
00026 
00027 XERCES_CPP_NAMESPACE_USE
00028 
00029 namespace lhef {
00030 
00031 class LHEReader::Source {
00032     public:
00033         Source() {}
00034         virtual ~Source() {}
00035         virtual XMLDocument *createReader(XMLDocument::Handler &handler) = 0;
00036 };
00037 
00038 class LHEReader::FileSource : public LHEReader::Source {
00039     public:
00040         FileSource(const std::string &fileURL)
00041         {
00042                 Storage *storage =
00043                         StorageFactory::get()->open(fileURL,
00044                                                     IOFlags::OpenRead);
00045 
00046                 if (!storage)
00047                         throw cms::Exception("FileOpenError")
00048                                 << "Could not open LHE file \""
00049                                 << fileURL << "\" for reading"
00050                                 << std::endl;
00051 
00052                 fileStream.reset(new StorageWrap(storage));
00053         }
00054 
00055         ~FileSource() {}
00056 
00057         XMLDocument *createReader(XMLDocument::Handler &handler)
00058         { return new XMLDocument(fileStream, handler); }
00059 
00060     private:
00061         std::auto_ptr<StorageWrap>      fileStream;
00062 };
00063 
00064 class LHEReader::StringSource : public LHEReader::Source {
00065     public:
00066         StringSource(const std::string &inputs)
00067         {
00068                 if (inputs == "")
00069                         throw cms::Exception("StreamOpenError")
00070                                 << "Empty LHE file string name \""
00071                                 << std::endl;
00072 
00073         std::stringstream * tmpis = new std::stringstream(inputs);
00074         fileStream.reset(tmpis);
00075         }
00076 
00077         ~StringSource() {}
00078 
00079         XMLDocument *createReader(XMLDocument::Handler &handler)
00080         { return new XMLDocument(fileStream, handler); }
00081 
00082     private:
00083   std::auto_ptr<std::istream>   fileStream;
00084 };
00085 
00086 class LHEReader::XMLHandler : public XMLDocument::Handler {
00087     public:
00088         XMLHandler() :
00089                 impl(0), gotObject(kNone), mode(kNone),
00090                 xmlHeader(0), headerOk(false) {}
00091         ~XMLHandler()
00092         { if (xmlHeader) xmlHeader->release(); }
00093 
00094         enum Object {
00095                 kNone = 0,
00096                 kHeader,
00097                 kInit,
00098                 kComment,
00099                 kEvent
00100         };
00101 
00102         void reset() { headerOk = false; }
00103 
00104     protected:
00105         void startElement(const XMLCh *const uri,
00106                           const XMLCh *const localname,
00107                           const XMLCh *const qname,
00108                           const Attributes &attributes);
00109 
00110         void endElement(const XMLCh *const uri,
00111                         const XMLCh *const localname,
00112                         const XMLCh *const qname);
00113 
00114         void characters(const XMLCh *const data, const unsigned int length);
00115         void comment(const XMLCh *const data, const unsigned int length);
00116 
00117     private:
00118         friend class LHEReader;
00119 
00120         DOMImplementation               *impl;
00121         std::string                     buffer;
00122         Object                          gotObject;
00123         Object                          mode;
00124         DOMDocument                     *xmlHeader;
00125         std::vector<DOMElement*>        xmlNodes;
00126         bool                            headerOk;
00127         std::vector<LHERunInfo::Header> headers;
00128 };
00129 
00130 static void attributesToDom(DOMElement *dom, const Attributes &attributes)
00131 {
00132         for(unsigned int i = 0; i < attributes.getLength(); i++) {
00133                 const XMLCh *name = attributes.getQName(i);
00134                 const XMLCh *value = attributes.getValue(i);
00135 
00136                 dom->setAttribute(name, value);
00137         }
00138 }
00139 
00140 static void fillHeader(LHERunInfo::Header &header, const char *data,
00141                        int len = -1)
00142 {
00143         const char *end = len >= 0 ? (data + len) : 0;
00144         while(*data && (!end || data < end)) {
00145                 std::size_t len = std::strcspn(data, "\r\n");
00146                 if (end && data + len > end)
00147                         len = end - data;
00148                 if (data[len] == '\r' && data[len + 1] == '\n')
00149                         len += 2;
00150                 else if (data[len])
00151                         len++;
00152                 header.addLine(std::string(data, len));
00153                 data += len;
00154         }
00155 }
00156 
00157 void LHEReader::XMLHandler::startElement(const XMLCh *const uri,
00158                                          const XMLCh *const localname,
00159                                          const XMLCh *const qname,
00160                                          const Attributes &attributes)
00161 {
00162         std::string name((const char*)XMLSimpleStr(qname));
00163 
00164         if (!headerOk) {
00165                 if (name != "LesHouchesEvents")
00166                         throw cms::Exception("InvalidFormat")
00167                                 << "LHE file has invalid header" << std::endl;
00168                 headerOk = true;
00169                 return;
00170         }
00171 
00172         if (mode == kHeader) {
00173                 DOMElement *elem = xmlHeader->createElement(qname);
00174                 attributesToDom(elem, attributes);
00175                 xmlNodes.back()->appendChild(elem);
00176                 xmlNodes.push_back(elem);
00177                 return;
00178         } else if (mode != kNone)
00179                 throw cms::Exception("InvalidFormat")
00180                         << "LHE file has invalid format" << std::endl;
00181 
00182         if (name == "header") {
00183                 if (!impl)
00184                         impl = DOMImplementationRegistry::getDOMImplementation(
00185                                                         XMLUniStr("Core"));
00186                 xmlHeader = impl->createDocument(0, qname, 0);
00187                 xmlNodes.resize(1);
00188                 xmlNodes[0] = xmlHeader->getDocumentElement();
00189                 mode = kHeader;
00190         } if (name == "init")
00191                 mode = kInit;
00192         else if (name == "event")
00193                 mode = kEvent;
00194 
00195         if (mode == kNone)
00196                 throw cms::Exception("InvalidFormat")
00197                         << "LHE file has invalid format" << std::endl;
00198 
00199         buffer.clear();
00200 }
00201 
00202 void LHEReader::XMLHandler::endElement(const XMLCh *const uri,
00203                                        const XMLCh *const localname,
00204                                        const XMLCh *const qname)
00205 {
00206         if (mode) {
00207                 if (mode == kHeader && xmlNodes.size() > 1) {
00208                         xmlNodes.resize(xmlNodes.size() - 1);
00209                         return;
00210                 } else if (mode == kHeader) {
00211                         std::auto_ptr<DOMWriter> writer(
00212                                 static_cast<DOMImplementationLS*>(
00213                                                 impl)->createDOMWriter());
00214                         writer->setEncoding(XMLUniStr("UTF-8"));
00215 
00216                         for(DOMNode *node = xmlNodes[0]->getFirstChild();
00217                             node; node = node->getNextSibling()) {
00218                                 XMLSimpleStr buffer(
00219                                         writer->writeToString(*node));
00220 
00221                                 std::string type;
00222                                 const char *p, *q;
00223                                 DOMElement *elem;
00224 
00225                                 switch(node->getNodeType()) {
00226                                     case DOMNode::ELEMENT_NODE:
00227                                         elem = static_cast<DOMElement*>(node);
00228                                         type = (const char*)XMLSimpleStr(
00229                                                         elem->getTagName());
00230                                         p = std::strchr((const char*)buffer,
00231                                                         '>') + 1;
00232                                         q = std::strrchr(p, '<');
00233                                         break;
00234                                     case DOMNode::COMMENT_NODE:
00235                                         type = "";
00236                                         p = buffer + 4;
00237                                         q = buffer + strlen(buffer) - 3;
00238                                         break;
00239                                     default:
00240                                         type = "<>";
00241                                         p = buffer +
00242                                             std::strspn(buffer, " \t\r\n");
00243                                         if (!*p)
00244                                                 continue;
00245                                         q = p + strlen(p);
00246                                 }
00247 
00248                                 LHERunInfo::Header header(type);
00249                                 fillHeader(header, p, q - p);
00250                                 headers.push_back(header);
00251                         }
00252 
00253                         xmlHeader->release();
00254                         xmlHeader = 0;
00255                 }
00256 
00257                 if (gotObject != kNone)
00258                         throw cms::Exception("InvalidState")
00259                                 << "Unexpected pileup in"
00260                                     " LHEReader::XMLHandler::endElement"
00261                                 << std::endl;
00262 
00263                 gotObject = mode;
00264                 mode = kNone;
00265         }
00266 }
00267 
00268 void LHEReader::XMLHandler::characters(const XMLCh *const data_,
00269                                        const unsigned int length)
00270 {
00271         if (mode == kHeader) {
00272                 DOMText *text = xmlHeader->createTextNode(data_);
00273                 xmlNodes.back()->appendChild(text);
00274                 return;
00275         }
00276 
00277         if (XMLSimpleStr::isAllSpaces(data_, length))
00278                 return;
00279 
00280         unsigned int offset = 0;
00281         while(offset < length && XMLSimpleStr::isSpace(data_[offset]))
00282                 offset++;
00283 
00284         XMLSimpleStr data(data_ + offset);
00285 
00286         if (mode == kNone)
00287                 throw cms::Exception("InvalidFormat")
00288                         << "LHE file has invalid format" << std::endl;
00289 
00290         buffer.append(data);
00291 }
00292 
00293 void LHEReader::XMLHandler::comment(const XMLCh *const data_,
00294                                     const unsigned int length)
00295 {
00296         if (mode == kHeader) {
00297                 DOMComment *comment = xmlHeader->createComment(data_);
00298                 xmlNodes.back()->appendChild(comment);
00299                 return;
00300         }
00301 
00302         XMLSimpleStr data(data_);
00303 
00304         LHERunInfo::Header header;
00305         fillHeader(header, data);
00306         headers.push_back(header);
00307 }
00308 
00309 LHEReader::LHEReader(const edm::ParameterSet &params) :
00310         fileURLs(params.getUntrackedParameter< std::vector<std::string> >("fileNames")),
00311     strName(""),
00312         firstEvent(params.getUntrackedParameter<unsigned int>("skipEvents", 0)),
00313         maxEvents(params.getUntrackedParameter<int>("limitEvents", -1)),
00314         curIndex(0), handler(new XMLHandler())
00315 {
00316 }
00317 
00318 LHEReader::LHEReader(const std::vector<std::string> &fileNames,
00319                      unsigned int firstEvent) :
00320   fileURLs(fileNames), strName(""), firstEvent(firstEvent), maxEvents(-1),
00321         curIndex(0), handler(new XMLHandler())
00322 {
00323 }
00324 
00325   LHEReader::LHEReader(const std::string &inputs,
00326                      unsigned int firstEvent) :
00327     strName(inputs), firstEvent(firstEvent), maxEvents(-1),
00328   curIndex(0), handler(new XMLHandler())
00329 {
00330 }
00331 
00332 LHEReader::~LHEReader()
00333 {
00334 }
00335 
00336   boost::shared_ptr<LHEEvent> LHEReader::next()
00337   {
00338 
00339     while(curDoc.get() || curIndex < fileURLs.size() || (fileURLs.size() == 0 && strName != "" ) ) {
00340       if (!curDoc.get()) {
00341         if ( fileURLs.size() > 0 ) 
00342           curSource.reset(new FileSource(fileURLs[curIndex++]));
00343         else if ( strName != "" ) 
00344           curSource.reset(new StringSource(strName));
00345         handler->reset();
00346         curDoc.reset(curSource->createReader(*handler));
00347         curRunInfo.reset();
00348       }
00349     
00350       XMLHandler::Object event = handler->gotObject;
00351       handler->gotObject = XMLHandler::kNone;
00352     
00353       std::istringstream data;
00354       if (event != XMLHandler::kNone) {
00355         data.str(handler->buffer);
00356         handler->buffer.clear();
00357       }
00358       
00359       switch(event) {
00360       case XMLHandler::kNone:
00361         if (!curDoc->parse())
00362           curDoc.reset();
00363         break;
00364         
00365       case XMLHandler::kHeader:
00366         break;
00367         
00368       case XMLHandler::kInit:
00369         curRunInfo.reset(new LHERunInfo(data));
00370                 
00371         std::for_each(handler->headers.begin(),
00372                       handler->headers.end(),
00373                       boost::bind(&LHERunInfo::addHeader,
00374                                   curRunInfo.get(), _1));
00375         handler->headers.clear();
00376         break;
00377         
00378       case XMLHandler::kComment:
00379         break;
00380         
00381       case XMLHandler::kEvent:
00382         if (!curRunInfo.get())
00383           throw cms::Exception("InvalidState")
00384             << "Got LHE event without"
00385             " initialization." << std::endl;
00386 
00387         if (firstEvent > 0) {
00388           firstEvent--;
00389           continue;
00390         }
00391         
00392         if (maxEvents == 0)
00393           return boost::shared_ptr<LHEEvent>();
00394         else if (maxEvents > 0)
00395           maxEvents--;
00396         
00397         return boost::shared_ptr<LHEEvent>(
00398                                            new LHEEvent(curRunInfo, data));
00399       }
00400         }
00401     
00402         return boost::shared_ptr<LHEEvent>();
00403   }
00404   
00405 } // namespace lhef
00406