CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/GeneratorInterface/LHEInterface/src/LHEReader.cc

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