CMS 3D CMS Logo

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::XMLHandler : public XMLDocument::Handler {
00065     public:
00066         XMLHandler() :
00067                 impl(0), gotObject(kNone), mode(kNone),
00068                 xmlHeader(0), headerOk(false) {}
00069         ~XMLHandler()
00070         { if (xmlHeader) xmlHeader->release(); }
00071 
00072         enum Object {
00073                 kNone = 0,
00074                 kHeader,
00075                 kInit,
00076                 kComment,
00077                 kEvent
00078         };
00079 
00080     protected:
00081         void startElement(const XMLCh *const uri,
00082                           const XMLCh *const localname,
00083                           const XMLCh *const qname,
00084                           const Attributes &attributes);
00085 
00086         void endElement(const XMLCh *const uri,
00087                         const XMLCh *const localname,
00088                         const XMLCh *const qname);
00089 
00090         void characters(const XMLCh *const data, const unsigned int length);
00091         void comment(const XMLCh *const data, const unsigned int length);
00092 
00093     private:
00094         friend class LHEReader;
00095 
00096         DOMImplementation               *impl;
00097         std::string                     buffer;
00098         Object                          gotObject;
00099         Object                          mode;
00100         DOMDocument                     *xmlHeader;
00101         std::vector<DOMElement*>        xmlNodes;
00102         bool                            headerOk;
00103         std::vector<LHERunInfo::Header> headers;
00104 };
00105 
00106 static void attributesToDom(DOMElement *dom, const Attributes &attributes)
00107 {
00108         for(unsigned int i = 0; i < attributes.getLength(); i++) {
00109                 const XMLCh *name = attributes.getQName(i);
00110                 const XMLCh *value = attributes.getValue(i);
00111 
00112                 dom->setAttribute(name, value);
00113         }
00114 }
00115 
00116 static void fillHeader(LHERunInfo::Header &header, const char *data,
00117                        int len = -1)
00118 {
00119         const char *end = len >= 0 ? (data + len) : 0;
00120         while(*data && (!end || data < end)) {
00121                 std::size_t len = std::strcspn(data, "\r\n");
00122                 if (end && data + len > end)
00123                         len = end - data;
00124                 if (data[len] == '\r' && data[len + 1] == '\n')
00125                         len += 2;
00126                 else if (data[len])
00127                         len++;
00128                 header.addLine(std::string(data, len));
00129                 data += len;
00130         }
00131 }
00132 
00133 void LHEReader::XMLHandler::startElement(const XMLCh *const uri,
00134                                          const XMLCh *const localname,
00135                                          const XMLCh *const qname,
00136                                          const Attributes &attributes)
00137 {
00138         std::string name((const char*)XMLSimpleStr(qname));
00139 
00140         if (!headerOk) {
00141                 if (name != "LesHouchesEvents")
00142                         throw cms::Exception("InvalidFormat")
00143                                 << "LHE file has invalid header" << std::endl;
00144                 headerOk = true;
00145                 return;
00146         }
00147 
00148         if (mode == kHeader) {
00149                 DOMElement *elem = xmlHeader->createElement(qname);
00150                 attributesToDom(elem, attributes);
00151                 xmlNodes.back()->appendChild(elem);
00152                 xmlNodes.push_back(elem);
00153                 return;
00154         } else if (mode != kNone)
00155                 throw cms::Exception("InvalidFormat")
00156                         << "LHE file has invalid format" << std::endl;
00157 
00158         if (name == "header") {
00159                 if (!impl)
00160                         impl = DOMImplementationRegistry::getDOMImplementation(
00161                                                         XMLUniStr("Core"));
00162                 xmlHeader = impl->createDocument(0, qname, 0);
00163                 xmlNodes.resize(1);
00164                 xmlNodes[0] = xmlHeader->getDocumentElement();
00165                 mode = kHeader;
00166         } if (name == "init")
00167                 mode = kInit;
00168         else if (name == "event")
00169                 mode = kEvent;
00170 
00171         if (mode == kNone)
00172                 throw cms::Exception("InvalidFormat")
00173                         << "LHE file has invalid format" << std::endl;
00174 
00175         buffer.clear();
00176 }
00177 
00178 void LHEReader::XMLHandler::endElement(const XMLCh *const uri,
00179                                        const XMLCh *const localname,
00180                                        const XMLCh *const qname)
00181 {
00182         if (mode) {
00183                 if (mode == kHeader && xmlNodes.size() > 1) {
00184                         xmlNodes.resize(xmlNodes.size() - 1);
00185                         return;
00186                 } else if (mode == kHeader) {
00187                         std::auto_ptr<DOMWriter> writer(
00188                                 static_cast<DOMImplementationLS*>(
00189                                                 impl)->createDOMWriter());
00190                         writer->setEncoding(XMLUniStr("UTF-8"));
00191                         XMLSimpleStr buffer(
00192                                         writer->writeToString(*xmlNodes[0]));
00193                         LHERunInfo::Header header("header");
00194                         const char *p =
00195                                 std::strchr((const char*)buffer, '>') + 1;
00196                         const char *q = std::strrchr(p, '<');
00197                         fillHeader(header, p, q - p);
00198                         headers.push_back(header);
00199 
00200                         xmlHeader->release();
00201                         xmlHeader = 0;
00202                 }
00203 
00204                 if (gotObject != kNone)
00205                         throw cms::Exception("InvalidState")
00206                                 << "Unexpected pileup in"
00207                                     " LHEReader::XMLHandler::endElement"
00208                                 << std::endl;
00209 
00210                 gotObject = mode;
00211                 mode = kNone;
00212         }
00213 }
00214 
00215 void LHEReader::XMLHandler::characters(const XMLCh *const data_,
00216                                        const unsigned int length)
00217 {
00218         if (mode == kHeader) {
00219                 DOMText *text = xmlHeader->createTextNode(data_);
00220                 xmlNodes.back()->appendChild(text);
00221                 return;
00222         }
00223 
00224         if (XMLSimpleStr::isAllSpaces(data_, length))
00225                 return;
00226 
00227         unsigned int offset = 0;
00228         while(offset < length && XMLSimpleStr::isSpace(data_[offset]))
00229                 offset++;
00230 
00231         XMLSimpleStr data(data_ + offset);
00232 
00233         if (mode == kNone)
00234                 throw cms::Exception("InvalidFormat")
00235                         << "LHE file has invalid format" << std::endl;
00236 
00237         buffer.append(data);
00238 }
00239 
00240 void LHEReader::XMLHandler::comment(const XMLCh *const data_,
00241                                     const unsigned int length)
00242 {
00243         if (mode == kHeader) {
00244                 DOMComment *comment = xmlHeader->createComment(data_);
00245                 xmlNodes.back()->appendChild(comment);
00246                 return;
00247         }
00248 
00249         XMLSimpleStr data(data_);
00250 
00251         LHERunInfo::Header header;
00252         fillHeader(header, data);
00253         headers.push_back(header);
00254 }
00255 
00256 LHEReader::LHEReader(const edm::ParameterSet &params) :
00257         fileURLs(params.getUntrackedParameter< std::vector<std::string> >("fileNames")),
00258         firstEvent(params.getUntrackedParameter<unsigned int>("seekEvent", 0)),
00259         maxEvents(params.getUntrackedParameter<int>("limitEvents", -1)),
00260         curIndex(0), handler(new XMLHandler())
00261 {
00262 }
00263 
00264 LHEReader::LHEReader(const std::vector<std::string> &fileNames,
00265                      unsigned int firstEvent) :
00266         fileURLs(fileNames), firstEvent(firstEvent), maxEvents(-1),
00267         curIndex(0), handler(new XMLHandler())
00268 {
00269 }
00270 
00271 LHEReader::~LHEReader()
00272 {
00273 }
00274 
00275 boost::shared_ptr<LHEEvent> LHEReader::next()
00276 {
00277         while(curDoc.get() || curIndex < fileURLs.size()) {
00278                 if (!curDoc.get()) {
00279                         curSource.reset(new FileSource(fileURLs[curIndex++]));
00280                         curDoc.reset(curSource->createReader(*handler));
00281                         curRunInfo.reset();
00282                 }
00283 
00284                 XMLHandler::Object event = handler->gotObject;
00285                 handler->gotObject = XMLHandler::kNone;
00286 
00287                 std::istringstream data;
00288                 if (event != XMLHandler::kNone) {
00289                         data.str(handler->buffer);
00290                         handler->buffer.clear();
00291                 }
00292 
00293                 switch(event) {
00294                     case XMLHandler::kNone:
00295                         if (!curDoc->parse())
00296                                 curDoc.reset();
00297                         break;
00298 
00299                     case XMLHandler::kHeader:
00300                         break;
00301 
00302                     case XMLHandler::kInit:
00303                         curRunInfo.reset(new LHERunInfo(data));
00304                         std::for_each(handler->headers.begin(),
00305                                       handler->headers.end(),
00306                                       boost::bind(&LHERunInfo::addHeader,
00307                                                   curRunInfo.get(), _1));
00308                         handler->headers.clear();
00309                         break;
00310 
00311                     case XMLHandler::kComment:
00312                         break;
00313 
00314                     case XMLHandler::kEvent:
00315                         if (!curRunInfo.get())
00316                                 throw cms::Exception("InvalidState")
00317                                         << "Got LHE event without"
00318                                            " initialization." << std::endl;
00319 
00320                         if (firstEvent > 0) {
00321                                 firstEvent--;
00322                                 continue;
00323                         }
00324 
00325                         if (maxEvents == 0)
00326                                 return boost::shared_ptr<LHEEvent>();
00327                         else if (maxEvents > 0)
00328                                 maxEvents--;
00329 
00330                         return boost::shared_ptr<LHEEvent>(
00331                                         new LHEEvent(curRunInfo, data));
00332                 }
00333         }
00334 
00335         return boost::shared_ptr<LHEEvent>();
00336 }
00337 
00338 } // namespace lhef

Generated on Tue Jun 9 17:37:07 2009 for CMSSW by  doxygen 1.5.4