Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-05-11 02:21:49

0001 /****************************************************************************
0002 *
0003 * This is a part of TOTEM offline software.
0004 * Authors:
0005 *   Maciej Wróbel (wroblisko@gmail.com)
0006 *   Jan Kašpar (jan.kaspar@cern.ch)
0007 *   Marcin Borratynski (mborratynski@gmail.com)
0008 *   Seyed Mohsen Etesami (setesami@cern.ch)
0009 *   Laurent Forthomme
0010 ****************************************************************************/
0011 
0012 #include "FWCore/Framework/interface/MakerMacros.h"
0013 #include "FWCore/Framework/interface/SourceFactory.h"
0014 #include "FWCore/Framework/interface/ModuleFactory.h"
0015 #include "FWCore/Framework/interface/ESHandle.h"
0016 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0017 #include "FWCore/Framework/interface/ESProducer.h"
0018 #include "FWCore/Framework/interface/EventSetupRecordIntervalFinder.h"
0019 #include "FWCore/Framework/interface/ESProducts.h"
0020 #include "FWCore/Framework/interface/SourceFactory.h"
0021 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0022 
0023 #include "DataFormats/CTPPSDetId/interface/TotemRPDetId.h"
0024 #include "DataFormats/CTPPSDetId/interface/CTPPSDiamondDetId.h"
0025 #include "DataFormats/CTPPSDetId/interface/TotemTimingDetId.h"
0026 #include "DataFormats/CTPPSDetId/interface/TotemT2DetId.h"
0027 
0028 #include "CondFormats/DataRecord/interface/TotemReadoutRcd.h"
0029 #include "CondFormats/PPSObjects/interface/TotemDAQMapping.h"
0030 #include "CondFormats/PPSObjects/interface/TotemAnalysisMask.h"
0031 #include "CondFormats/PPSObjects/interface/TotemFramePosition.h"
0032 #include "Utilities/Xerces/interface/Xerces.h"
0033 #include "Utilities/Xerces/interface/XercesStrUtils.h"
0034 
0035 #include <xercesc/parsers/XercesDOMParser.hpp>
0036 #include <xercesc/dom/DOM.hpp>
0037 #include <xercesc/sax/HandlerBase.hpp>
0038 #include <xercesc/util/XMLString.hpp>
0039 #include <xercesc/util/PlatformUtils.hpp>
0040 
0041 #include <memory>
0042 #include <sstream>
0043 
0044 //#define DEBUG 1
0045 
0046 //----------------------------------------------------------------------------------------------------
0047 
0048 using namespace std;
0049 
0050 /**
0051  * \brief Loads TotemDAQMapping and TotemAnalysisMask from two XML files.
0052  **/
0053 class TotemDAQMappingESSourceXML : public edm::ESProducer, public edm::EventSetupRecordIntervalFinder {
0054 public:
0055   static const std::string tagVFAT;
0056   static const std::string tagChannel;
0057   static const std::string tagAnalysisMask;
0058 
0059   /// Common position tags
0060   static const std::string tagArm;
0061 
0062   /// RP XML tags
0063   static const std::string tagRPStation;
0064   static const std::string tagRPPot;
0065   static const std::string tagRPPlane;
0066 
0067   /// COMMON Chip XML tags
0068   static const std::string tagChip1;
0069   static const std::string tagChip2;
0070 
0071   /// diamond specific tags
0072   static const std::string tagDiamondPlane;
0073   static const std::string tagDiamondCh;
0074 
0075   /// totem timing specific tags
0076   static const std::string tagSampicBoard;
0077   static const std::string tagSampicCh;
0078   static const std::string tagTotemTimingCh;
0079   static const std::string tagTotemTimingPlane;
0080 
0081   /// TOTEM nT2 specific tags
0082   static const std::string tagTotemT2Plane;
0083   static const std::string tagTotemT2Tile;
0084 
0085   TotemDAQMappingESSourceXML(const edm::ParameterSet &);
0086   ~TotemDAQMappingESSourceXML() override;
0087 
0088   edm::ESProducts<std::unique_ptr<TotemDAQMapping>, std::unique_ptr<TotemAnalysisMask>> produce(const TotemReadoutRcd &);
0089 
0090 private:
0091   unsigned int verbosity;
0092 
0093   /// label of the CTPPS sub-system
0094   string subSystemName;
0095 
0096   //subdetector id for sampic
0097   unsigned int sampicSubDetId;
0098 
0099   //Unpack multiple channels per payload for T2
0100   bool packedPayload;
0101 
0102   /// the mapping files
0103   std::vector<std::string> mappingFileNames;
0104 
0105   struct ConfigBlock {
0106     /// validity interval
0107     edm::EventRange validityRange;
0108 
0109     /// the mapping files
0110     std::vector<std::string> mappingFileNames;
0111 
0112     /// the mask files
0113     std::vector<std::string> maskFileNames;
0114   };
0115 
0116   vector<ConfigBlock> configuration;
0117 
0118   /// index of the current block in 'configuration' array
0119   unsigned int currentBlock;
0120 
0121   /// flag whether the 'currentBlock' index is valid
0122   bool currentBlockValid;
0123 
0124   /// enumeration of XML node types
0125   enum NodeType {
0126     nUnknown,
0127     nSkip,
0128     nTop,
0129     nArm,
0130     nRPStation,
0131     nRPPot,
0132     nRPPlane,
0133     nDiamondPlane,
0134     nChip,
0135     nDiamondCh,
0136     nChannel,
0137     nSampicBoard,
0138     nSampicChannel,
0139     nTotemTimingPlane,
0140     nTotemTimingCh,
0141     nTotemT2Plane,
0142     nTotemT2Tile
0143   };
0144 
0145   /// whether to parse a mapping of a mask XML
0146   enum ParseType { pMapping, pMask };
0147 
0148   /// parses XML file
0149   void ParseXML(ParseType,
0150                 const string &file,
0151                 const std::unique_ptr<TotemDAQMapping> &,
0152                 const std::unique_ptr<TotemAnalysisMask> &);
0153 
0154   /// recursive method to extract RP-related information from the DOM tree
0155   void ParseTreeRP(ParseType,
0156                    xercesc::DOMNode *,
0157                    NodeType,
0158                    unsigned int parentID,
0159                    const std::unique_ptr<TotemDAQMapping> &,
0160                    const std::unique_ptr<TotemAnalysisMask> &);
0161 
0162   /// recursive method to extract RP-related information from the DOM tree
0163   void ParseTreeDiamond(ParseType,
0164                         xercesc::DOMNode *,
0165                         NodeType,
0166                         unsigned int parentID,
0167                         const std::unique_ptr<TotemDAQMapping> &,
0168                         const std::unique_ptr<TotemAnalysisMask> &);
0169 
0170   /// recursive method to extract RP-related information from the DOM tree
0171   void ParseTreeTotemTiming(ParseType,
0172                             xercesc::DOMNode *,
0173                             NodeType,
0174                             unsigned int parentID,
0175                             const std::unique_ptr<TotemDAQMapping> &,
0176                             const std::unique_ptr<TotemAnalysisMask> &);
0177 
0178   /// recursive method to extract nT2-related information from the DOM tree
0179   void ParseTreeTotemT2(ParseType,
0180                         xercesc::DOMNode *,
0181                         NodeType,
0182                         unsigned int parentID,
0183                         const std::unique_ptr<TotemDAQMapping> &,
0184                         const std::unique_ptr<TotemAnalysisMask> &);
0185 
0186 private:
0187   /// adds the path prefix, if needed
0188   string CompleteFileName(const string &fn);
0189 
0190   /// returns true iff the node is of the given name
0191   bool Test(xercesc::DOMNode *node, const std::string &name) {
0192     return !(name.compare(cms::xerces::toString(node->getNodeName())));
0193   }
0194 
0195   /// determines node type
0196   NodeType GetNodeType(xercesc::DOMNode *);
0197 
0198   /// returns the content of the node
0199   string GetNodeContent(xercesc::DOMNode *parent) { return string(cms::xerces::toString(parent->getTextContent())); }
0200 
0201   /// returns the value of the node
0202   string GetNodeValue(xercesc::DOMNode *node) { return cms::xerces::toString(node->getNodeValue()); }
0203 
0204   /// extracts VFAT's DAQ channel from XML attributes
0205   TotemFramePosition ChipFramePosition(xercesc::DOMNode *chipnode);
0206 
0207   /// extracts VFAT's DAQ channel from XML attributes for packed T2 payload
0208   TotemT2FramePosition ChipT2FramePosition(xercesc::DOMNode *chipnode);
0209 
0210   void GetChannels(xercesc::DOMNode *n, std::set<unsigned char> &channels);
0211 
0212   bool RPNode(NodeType type) {
0213     return ((type == nArm) || (type == nRPStation) || (type == nRPPot) || (type == nRPPlane) || (type == nChip));
0214   }
0215 
0216   bool DiamondNode(NodeType type) {
0217     return ((type == nArm) || (type == nRPStation) || (type == nRPPot) || (type == nDiamondPlane) ||
0218             (type == nDiamondCh));
0219   }
0220 
0221   bool TotemTimingNode(NodeType type) {
0222     return ((type == nArm) || (type == nRPStation) || (type == nRPPot) || (type == nSampicBoard) ||
0223             (type == nSampicChannel) || (type == nTotemTimingPlane) || (type == nTotemTimingCh));
0224   }
0225 
0226   bool TotemT2Node(NodeType type) { return type == nArm || type == nTotemT2Plane || type == nTotemT2Tile; }
0227 
0228   bool CommonNode(NodeType type) { return ((type == nChip) || (type == nArm)); }
0229 
0230 protected:
0231   /// sets infinite validity of this data
0232   void setIntervalFor(const edm::eventsetup::EventSetupRecordKey &,
0233                       const edm::IOVSyncValue &,
0234                       edm::ValidityInterval &) override;
0235 };
0236 
0237 //----------------------------------------------------------------------------------------------------
0238 
0239 using namespace std;
0240 using namespace edm;
0241 using namespace xercesc;
0242 
0243 const string TotemDAQMappingESSourceXML::tagVFAT = "vfat";
0244 const string TotemDAQMappingESSourceXML::tagChannel = "channel";
0245 const string TotemDAQMappingESSourceXML::tagAnalysisMask = "analysisMask";
0246 
0247 // common XML position tags
0248 const string TotemDAQMappingESSourceXML::tagArm = "arm";
0249 
0250 // common XML Chip tags
0251 const string TotemDAQMappingESSourceXML::tagChip1 = "vfat";
0252 const string TotemDAQMappingESSourceXML::tagChip2 = "test_vfat";
0253 
0254 // specific RP XML tags
0255 const string TotemDAQMappingESSourceXML::tagRPStation = "station";
0256 const string TotemDAQMappingESSourceXML::tagRPPot = "rp_detector_set";
0257 const string TotemDAQMappingESSourceXML::tagRPPlane = "rp_plane";
0258 
0259 // specific tags for diamond
0260 const string TotemDAQMappingESSourceXML::tagDiamondPlane = "rp_plane_diamond";
0261 const string TotemDAQMappingESSourceXML::tagDiamondCh = "diamond_channel";
0262 
0263 // specific tags for totem timing
0264 const string TotemDAQMappingESSourceXML::tagSampicBoard = "rp_sampic_board";
0265 const string TotemDAQMappingESSourceXML::tagSampicCh = "rp_sampic_channel";
0266 const string TotemDAQMappingESSourceXML::tagTotemTimingCh = "timing_channel";
0267 const string TotemDAQMappingESSourceXML::tagTotemTimingPlane = "timing_plane";
0268 
0269 // specific tags for TOTEM nT2
0270 const string TotemDAQMappingESSourceXML::tagTotemT2Plane = "nt2_plane";
0271 const string TotemDAQMappingESSourceXML::tagTotemT2Tile = "nt2_tile";
0272 
0273 //----------------------------------------------------------------------------------------------------
0274 
0275 TotemDAQMappingESSourceXML::TotemDAQMappingESSourceXML(const edm::ParameterSet &conf)
0276     : verbosity(conf.getUntrackedParameter<unsigned int>("verbosity", 0)),
0277       subSystemName(conf.getUntrackedParameter<string>("subSystem")),
0278       sampicSubDetId(conf.getParameter<unsigned int>("sampicSubDetId")),
0279       packedPayload(conf.getUntrackedParameter<bool>("multipleChannelsPerPayload", false)),
0280       currentBlock(0),
0281       currentBlockValid(false) {
0282   for (const auto &it : conf.getParameter<vector<ParameterSet>>("configuration")) {
0283     ConfigBlock b;
0284     b.validityRange = it.getParameter<EventRange>("validityRange");
0285     b.mappingFileNames = it.getParameter<vector<string>>("mappingFileNames");
0286     b.maskFileNames = it.getParameter<vector<string>>("maskFileNames");
0287     configuration.push_back(b);
0288   }
0289 
0290   setWhatProduced(this, subSystemName);
0291   findingRecord<TotemReadoutRcd>();
0292 }
0293 
0294 //----------------------------------------------------------------------------------------------------
0295 
0296 void TotemDAQMappingESSourceXML::setIntervalFor(const edm::eventsetup::EventSetupRecordKey &key,
0297                                                 const edm::IOVSyncValue &iosv,
0298                                                 edm::ValidityInterval &oValidity) {
0299   LogVerbatim("TotemDAQMappingESSourceXML") << ">> TotemDAQMappingESSourceXML::setIntervalFor(" << key.name() << ")";
0300 
0301   LogVerbatim("TotemDAQMappingESSourceXML")
0302       << "    run=" << iosv.eventID().run() << ", event=" << iosv.eventID().event();
0303 
0304   currentBlockValid = false;
0305   for (unsigned int idx = 0; idx < configuration.size(); ++idx) {
0306     const auto &bl = configuration[idx];
0307 
0308     edm::EventRange range = bl.validityRange;
0309 
0310     // If "<run>:min" is specified in python config, it is translated into event <run>:0:1.
0311     // However, the truly minimal event id often found in data is <run>:0:0. Therefore the
0312     // adjustment below is needed.
0313     if (range.startEventID().luminosityBlock() == 0 && range.startEventID().event() == 1)
0314       range = edm::EventRange(edm::EventID(range.startEventID().run(), 0, 0), range.endEventID());
0315 
0316     if (edm::contains(range, iosv.eventID())) {
0317       currentBlockValid = true;
0318       currentBlock = idx;
0319 
0320       const IOVSyncValue begin(range.startEventID());
0321       const IOVSyncValue end(range.endEventID());
0322       oValidity = edm::ValidityInterval(begin, end);
0323 
0324       LogVerbatim("TotemDAQMappingESSourceXML") << "    block found: index=" << currentBlock << ", interval=("
0325                                                 << range.startEventID() << " - " << range.endEventID() << ")";
0326 
0327       return;
0328     }
0329   }
0330 
0331   if (!currentBlockValid) {
0332     throw cms::Exception("TotemDAQMappingESSourceXML::setIntervalFor")
0333         << "No configuration for event " << iosv.eventID();
0334   }
0335 }
0336 
0337 //----------------------------------------------------------------------------------------------------
0338 
0339 TotemDAQMappingESSourceXML::~TotemDAQMappingESSourceXML() {}
0340 
0341 //----------------------------------------------------------------------------------------------------
0342 
0343 string TotemDAQMappingESSourceXML::CompleteFileName(const string &fn) {
0344   FileInPath fip(fn);
0345   return fip.fullPath();
0346 }
0347 
0348 //----------------------------------------------------------------------------------------------------
0349 static inline std::string to_string(const XMLCh *ch) { return XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(ch); }
0350 
0351 edm::ESProducts<std::unique_ptr<TotemDAQMapping>, std::unique_ptr<TotemAnalysisMask>>
0352 TotemDAQMappingESSourceXML::produce(const TotemReadoutRcd &) {
0353   assert(currentBlockValid);
0354 
0355   auto mapping = std::make_unique<TotemDAQMapping>();
0356   auto mask = std::make_unique<TotemAnalysisMask>();
0357 
0358   try {
0359     // initialize Xerces
0360     cms::concurrency::xercesInitialize();
0361 
0362     // load mapping files
0363     for (const auto &fn : configuration[currentBlock].mappingFileNames)
0364       ParseXML(pMapping, CompleteFileName(fn), mapping, mask);
0365 
0366     // load mask files
0367     for (const auto &fn : configuration[currentBlock].maskFileNames)
0368       ParseXML(pMask, CompleteFileName(fn), mapping, mask);
0369 
0370     // release Xerces
0371     cms::concurrency::xercesTerminate();
0372   } catch (const XMLException &e) {
0373     throw cms::Exception("XMLDocument") << "cms::concurrency::xercesInitialize failed because of "
0374                                         << to_string(e.getMessage()) << std::endl;
0375   } catch (const SAXException &e) {
0376     throw cms::Exception("XMLDocument") << "XML parser reported: " << to_string(e.getMessage()) << "." << std::endl;
0377   }
0378 
0379   // commit the products
0380   return edm::es::products(std::move(mapping), std::move(mask));
0381 }
0382 
0383 //----------------------------------------------------------------------------------------------------
0384 
0385 void TotemDAQMappingESSourceXML::ParseXML(ParseType pType,
0386                                           const string &file,
0387                                           const std::unique_ptr<TotemDAQMapping> &mapping,
0388                                           const std::unique_ptr<TotemAnalysisMask> &mask) {
0389   unique_ptr<XercesDOMParser> parser(new XercesDOMParser());
0390   parser->parse(file.c_str());
0391 
0392   DOMDocument *domDoc = parser->getDocument();
0393 
0394   if (!domDoc)
0395     throw cms::Exception("TotemDAQMappingESSourceXML::ParseXML")
0396         << "Cannot parse file `" << file << "' (domDoc = NULL).";
0397 
0398   DOMElement *elementRoot = domDoc->getDocumentElement();
0399 
0400   if (!elementRoot)
0401     throw cms::Exception("TotemDAQMappingESSourceXML::ParseXML") << "File `" << file << "' is empty.";
0402 
0403   ParseTreeRP(pType, elementRoot, nTop, 0, mapping, mask);
0404 
0405   ParseTreeDiamond(pType, elementRoot, nTop, 0, mapping, mask);
0406 
0407   ParseTreeTotemTiming(pType, elementRoot, nTop, 0, mapping, mask);
0408 
0409   ParseTreeTotemT2(pType, elementRoot, nTop, 0, mapping, mask);
0410 }
0411 
0412 //-----------------------------------------------------------------------------------------------------------
0413 
0414 void TotemDAQMappingESSourceXML::ParseTreeRP(ParseType pType,
0415                                              xercesc::DOMNode *parent,
0416                                              NodeType parentType,
0417                                              unsigned int parentID,
0418                                              const std::unique_ptr<TotemDAQMapping> &mapping,
0419                                              const std::unique_ptr<TotemAnalysisMask> &mask) {
0420 #ifdef DEBUG
0421   printf(">> TotemDAQMappingESSourceXML::ParseTreeRP(%s, %u, %u)\n",
0422          cms::xerces::toString(parent->getNodeName()),
0423          parentType,
0424          parentID);
0425 #endif
0426 
0427   DOMNodeList *children = parent->getChildNodes();
0428 
0429   for (unsigned int i = 0; i < children->getLength(); i++) {
0430     DOMNode *n = children->item(i);
0431     if (n->getNodeType() != DOMNode::ELEMENT_NODE)
0432       continue;
0433 
0434     NodeType type = GetNodeType(n);
0435 
0436 #ifdef DEBUG
0437     printf("\tname = %s, type = %u\n", cms::xerces::toString(n->getNodeName()), type);
0438 #endif
0439 
0440     // structure control
0441     if (!RPNode(type))
0442       continue;
0443 
0444     NodeType expectedParentType;
0445     switch (type) {
0446       case nArm:
0447         expectedParentType = nTop;
0448         break;
0449       case nRPStation:
0450         expectedParentType = nArm;
0451         break;
0452       case nRPPot:
0453         expectedParentType = nRPStation;
0454         break;
0455       case nRPPlane:
0456         expectedParentType = nRPPot;
0457         break;
0458       case nChip:
0459         expectedParentType = nRPPlane;
0460         break;
0461       case nChannel:
0462         expectedParentType = nChip;
0463         break;
0464       default:
0465         expectedParentType = nUnknown;
0466         break;
0467     }
0468 
0469     if (expectedParentType != parentType) {
0470       throw cms::Exception("TotemDAQMappingESSourceXML")
0471           << "Node " << cms::xerces::toString(n->getNodeName()) << " not allowed within "
0472           << cms::xerces::toString(parent->getNodeName()) << " block.\n";
0473     }
0474 
0475     // parse tag attributes
0476     unsigned int id = 0, hw_id = 0;
0477     bool id_set = false, hw_id_set = false;
0478     bool fullMask = false;
0479     DOMNamedNodeMap *attr = n->getAttributes();
0480 
0481     for (unsigned int j = 0; j < attr->getLength(); j++) {
0482       DOMNode *a = attr->item(j);
0483 
0484       if (!strcmp(cms::xerces::toString(a->getNodeName()).c_str(), "id")) {
0485         sscanf(cms::xerces::toString(a->getNodeValue()).c_str(), "%u", &id);
0486         id_set = true;
0487       }
0488 
0489       if (!strcmp(cms::xerces::toString(a->getNodeName()).c_str(), "hw_id")) {
0490         sscanf(cms::xerces::toString(a->getNodeValue()).c_str(), "%x", &hw_id);
0491         hw_id_set = true;
0492       }
0493 
0494       if (!strcmp(cms::xerces::toString(a->getNodeName()).c_str(), "full_mask"))
0495         fullMask = (strcmp(cms::xerces::toString(a->getNodeValue()).c_str(), "no") != 0);
0496     }
0497 
0498     // content control
0499     if (!id_set)
0500       throw cms::Exception("TotemDAQMappingESSourceXML::ParseTreeRP")
0501           << "id not given for element `" << cms::xerces::toString(n->getNodeName()) << "'";
0502 
0503     if (!hw_id_set && type == nChip && pType == pMapping)
0504       throw cms::Exception("TotemDAQMappingESSourceXML::ParseTreeRP")
0505           << "hw_id not given for element `" << cms::xerces::toString(n->getNodeName()) << "'";
0506 
0507     if (type == nRPPlane && id > 9)
0508       throw cms::Exception("TotemDAQMappingESSourceXML::ParseTreeRP")
0509           << "Plane IDs range from 0 to 9. id = " << id << " is invalid.";
0510 
0511 #ifdef DEBUG
0512     printf("\tID found: 0x%x\n", id);
0513 #endif
0514 
0515     // store mapping data
0516     if (pType == pMapping && type == nChip) {
0517       const TotemFramePosition &framepos = ChipFramePosition(n);
0518       TotemVFATInfo vfatInfo;
0519       vfatInfo.hwID = hw_id;
0520 
0521       const unsigned int armIdx = (parentID / 1000) % 10;
0522       const unsigned int stIdx = (parentID / 100) % 10;
0523       const unsigned int rpIdx = (parentID / 10) % 10;
0524       const unsigned int plIdx = parentID % 10;
0525 
0526       vfatInfo.symbolicID.symbolicID = TotemRPDetId(armIdx, stIdx, rpIdx, plIdx, id);
0527 
0528       mapping->insert(framepos, vfatInfo);
0529 
0530       continue;
0531     }
0532 
0533     // store mask data
0534     if (pType == pMask && type == nChip) {
0535       const unsigned int armIdx = (parentID / 1000) % 10;
0536       const unsigned int stIdx = (parentID / 100) % 10;
0537       const unsigned int rpIdx = (parentID / 10) % 10;
0538       const unsigned int plIdx = parentID % 10;
0539 
0540       TotemSymbID symbId;
0541       symbId.symbolicID = TotemRPDetId(armIdx, stIdx, rpIdx, plIdx, id);
0542 
0543       TotemVFATAnalysisMask am;
0544       am.fullMask = fullMask;
0545       GetChannels(n, am.maskedChannels);
0546 
0547       mask->insert(symbId, am);
0548 
0549       continue;
0550     }
0551 
0552     // recursion (deeper in the tree)
0553     ParseTreeRP(pType, n, type, parentID * 10 + id, mapping, mask);
0554   }
0555 }
0556 
0557 //----------------------------------------------------------------------------------------------------
0558 
0559 void TotemDAQMappingESSourceXML::ParseTreeDiamond(ParseType pType,
0560                                                   xercesc::DOMNode *parent,
0561                                                   NodeType parentType,
0562                                                   unsigned int parentID,
0563                                                   const std::unique_ptr<TotemDAQMapping> &mapping,
0564                                                   const std::unique_ptr<TotemAnalysisMask> &mask) {
0565 #ifdef DEBUG
0566   printf(">> TotemDAQMappingESSourceXML::ParseTreeDiamond(%s, %u, %u)\n",
0567          cms::xerces::toString(parent->getNodeName()),
0568          parentType,
0569          parentID);
0570 #endif
0571 
0572   DOMNodeList *children = parent->getChildNodes();
0573 
0574   for (unsigned int i = 0; i < children->getLength(); i++) {
0575     DOMNode *n = children->item(i);
0576     if (n->getNodeType() != DOMNode::ELEMENT_NODE)
0577       continue;
0578 
0579     NodeType type = GetNodeType(n);
0580 #ifdef DEBUG
0581     printf("\tname = %s, type = %u\n", cms::xerces::toString(n->getNodeName()), type);
0582 #endif
0583 
0584     // structure control
0585     if (!DiamondNode(type))
0586       continue;
0587 
0588     NodeType expectedParentType;
0589     switch (type) {
0590       case nArm:
0591         expectedParentType = nTop;
0592         break;
0593       case nRPStation:
0594         expectedParentType = nArm;
0595         break;
0596       case nRPPot:
0597         expectedParentType = nRPStation;
0598         break;
0599       case nDiamondPlane:
0600         expectedParentType = nRPPot;
0601         break;
0602       case nDiamondCh:
0603         expectedParentType = nDiamondPlane;
0604         break;
0605       default:
0606         expectedParentType = nUnknown;
0607         break;
0608     }
0609 
0610     if (expectedParentType != parentType) {
0611       throw cms::Exception("TotemDAQMappingESSourceXML")
0612           << "Node " << cms::xerces::toString(n->getNodeName()) << " not allowed within "
0613           << cms::xerces::toString(parent->getNodeName()) << " block.\n";
0614     }
0615 
0616     // parse tag attributes
0617     unsigned int id = 0, hw_id = 0;
0618     bool id_set = false, hw_id_set = false;
0619     DOMNamedNodeMap *attr = n->getAttributes();
0620 
0621     for (unsigned int j = 0; j < attr->getLength(); j++) {
0622       DOMNode *a = attr->item(j);
0623 
0624       if (!strcmp(cms::xerces::toString(a->getNodeName()).c_str(), "id")) {
0625         sscanf(cms::xerces::toString(a->getNodeValue()).c_str(), "%u", &id);
0626         id_set = true;
0627       }
0628 
0629       if (!strcmp(cms::xerces::toString(a->getNodeName()).c_str(), "hw_id")) {
0630         sscanf(cms::xerces::toString(a->getNodeValue()).c_str(), "%x", &hw_id);
0631         hw_id_set = true;
0632       }
0633     }
0634 
0635     // content control
0636     if (!id_set)
0637       throw cms::Exception("TotemDAQMappingESSourceXML::ParseTreeDiamond")
0638           << "id not given for element `" << cms::xerces::toString(n->getNodeName()) << "'";
0639 
0640     if (!hw_id_set && type == nDiamondCh && pType == pMapping)
0641       throw cms::Exception("TotemDAQMappingESSourceXML::ParseTreeDiamond")
0642           << "hw_id not given for element `" << cms::xerces::toString(n->getNodeName()) << "'";
0643 
0644     if (type == nDiamondPlane && id > 3)
0645       throw cms::Exception("TotemDAQMappingESSourceXML::ParseTreeDiamond")
0646           << "Plane IDs range from 0 to 3. id = " << id << " is invalid.";
0647 
0648 #ifdef DEBUG
0649     printf("\tID found: 0x%x\n", id);
0650 #endif
0651 
0652     // store mapping data
0653     if (pType == pMapping && type == nDiamondCh) {
0654       const TotemFramePosition &framepos = ChipFramePosition(n);
0655 
0656       TotemVFATInfo vfatInfo;
0657       vfatInfo.hwID = hw_id;
0658 
0659       if (type == nDiamondCh) {
0660         unsigned int ArmNum = (parentID / 10000) % 10;
0661         unsigned int StationNum = (parentID / 1000) % 10;
0662         unsigned int RpNum = (parentID / 100) % 10;
0663         unsigned int PlaneNum = (parentID % 100);
0664 
0665         vfatInfo.symbolicID.symbolicID = CTPPSDiamondDetId(ArmNum, StationNum, RpNum, PlaneNum, id);
0666       }
0667 
0668       mapping->insert(framepos, vfatInfo);
0669 
0670       continue;
0671     }
0672 
0673     unsigned int childId;
0674     if (pType == pMapping && type == nDiamondPlane)
0675       childId = parentID * 100 + id;
0676     else
0677       childId = parentID * 10 + id;
0678 
0679     ParseTreeDiamond(pType, n, type, childId, mapping, mask);
0680   }
0681 }
0682 
0683 //----------------------------------------------------------------------------------------------------
0684 
0685 void TotemDAQMappingESSourceXML::ParseTreeTotemTiming(ParseType pType,
0686                                                       xercesc::DOMNode *parent,
0687                                                       NodeType parentType,
0688                                                       unsigned int parentID,
0689                                                       const std::unique_ptr<TotemDAQMapping> &mapping,
0690                                                       const std::unique_ptr<TotemAnalysisMask> &mask) {
0691   DOMNodeList *children = parent->getChildNodes();
0692 
0693   // Fill map hwId -> TotemTimingPlaneChannelPair
0694   for (unsigned int i = 0; i < children->getLength(); i++) {
0695     DOMNode *child = children->item(i);
0696     if ((child->getNodeType() != DOMNode::ELEMENT_NODE) || (GetNodeType(child) != nTotemTimingCh))
0697       continue;
0698 
0699     int plane = -1;
0700     DOMNamedNodeMap *attr = parent->getAttributes();
0701     for (unsigned int j = 0; j < attr->getLength(); j++) {
0702       DOMNode *a = attr->item(j);
0703 
0704       if (!strcmp(cms::xerces::toString(a->getNodeName()).c_str(), "id"))
0705         sscanf(cms::xerces::toString(a->getNodeValue()).c_str(), "%d", &plane);
0706     }
0707 
0708     int channel = -1;
0709     unsigned int hwId = 0;
0710     attr = child->getAttributes();
0711     for (unsigned int j = 0; j < attr->getLength(); j++) {
0712       DOMNode *a = attr->item(j);
0713 
0714       if (!strcmp(cms::xerces::toString(a->getNodeName()).c_str(), "id"))
0715         sscanf(cms::xerces::toString(a->getNodeValue()).c_str(), "%d", &channel);
0716       if (!strcmp(cms::xerces::toString(a->getNodeName()).c_str(), "hwId"))
0717         sscanf(cms::xerces::toString(a->getNodeValue()).c_str(), "%x", &hwId);
0718     }
0719 
0720     mapping->totemTimingChannelMap[(uint8_t)hwId] = TotemDAQMapping::TotemTimingPlaneChannelPair(plane, channel);
0721   }
0722 
0723   for (unsigned int i = 0; i < children->getLength(); i++) {
0724     DOMNode *n = children->item(i);
0725     if (n->getNodeType() != DOMNode::ELEMENT_NODE)
0726       continue;
0727 
0728     NodeType type = GetNodeType(n);
0729 
0730     // structure control
0731     if (!TotemTimingNode(type))
0732       continue;
0733 
0734     NodeType expectedParentType;
0735     switch (type) {
0736       case nArm:
0737         expectedParentType = nTop;
0738         break;
0739       case nRPStation:
0740         expectedParentType = nArm;
0741         break;
0742       case nRPPot:
0743         expectedParentType = nRPStation;
0744         break;
0745       case nSampicBoard:
0746         expectedParentType = nRPPot;
0747         break;
0748       case nSampicChannel:
0749         expectedParentType = nSampicBoard;
0750         break;
0751       case nTotemTimingPlane:
0752         expectedParentType = nRPPot;
0753         break;
0754       case nTotemTimingCh:
0755         expectedParentType = nTotemTimingPlane;
0756         break;
0757       default:
0758         expectedParentType = nUnknown;
0759         break;
0760     }
0761 
0762     if (expectedParentType != parentType) {
0763       throw cms::Exception("TotemDAQMappingESSourceXML")
0764           << "Node " << cms::xerces::toString(n->getNodeName()) << " not allowed within "
0765           << cms::xerces::toString(parent->getNodeName()) << " block.\n";
0766     }
0767 
0768     // parse tag attributes
0769     unsigned int id = 0;
0770     bool id_set = false;
0771     DOMNamedNodeMap *attr = n->getAttributes();
0772 
0773     for (unsigned int j = 0; j < attr->getLength(); j++) {
0774       DOMNode *a = attr->item(j);
0775 
0776       if (!strcmp(cms::xerces::toString(a->getNodeName()).c_str(), "id")) {
0777         sscanf(cms::xerces::toString(a->getNodeValue()).c_str(), "%u", &id);
0778         id_set = true;
0779       }
0780     }
0781 
0782     // content control
0783     if (!id_set)
0784       throw cms::Exception("TotemDAQMappingESSourceXML::ParseTreeTotemTiming")
0785           << "id not given for element `" << cms::xerces::toString(n->getNodeName()) << "'";
0786     if (type == nSampicBoard && id > 5)
0787       throw cms::Exception("TotemDAQMappingESSourceXML::ParseTreeTotemTiming")
0788           << "SampicBoard IDs range from 0 to 5. id = " << id << " is invalid.";
0789 
0790     // store mapping data
0791     if (pType == pMapping && type == nSampicChannel) {
0792       const TotemFramePosition &framepos = ChipFramePosition(n);
0793 
0794       TotemVFATInfo vfatInfo;
0795       unsigned int ArmNum = (parentID / 10000) % 10;
0796       unsigned int StationNum = (parentID / 1000) % 10;
0797       unsigned int RpNum = (parentID / 100) % 10;
0798 
0799       vfatInfo.symbolicID.symbolicID = TotemTimingDetId(ArmNum,
0800                                                         StationNum,
0801                                                         RpNum,
0802                                                         0,
0803                                                         TotemTimingDetId::ID_NOT_SET,
0804                                                         sampicSubDetId);  //Dynamical: it is encoded in the frame
0805 
0806       mapping->insert(framepos, vfatInfo);
0807 
0808       continue;
0809     }
0810 
0811     unsigned int childId;
0812     if (pType == pMapping && type == nSampicBoard)
0813       childId = parentID * 100 + id;
0814     else
0815       childId = parentID * 10 + id;
0816 
0817     ParseTreeTotemTiming(pType, n, type, childId, mapping, mask);
0818   }
0819 }
0820 
0821 //----------------------------------------------------------------------------------------------------
0822 
0823 void TotemDAQMappingESSourceXML::ParseTreeTotemT2(ParseType pType,
0824                                                   xercesc::DOMNode *parent,
0825                                                   NodeType parentType,
0826                                                   unsigned int parentID,
0827                                                   const std::unique_ptr<TotemDAQMapping> &mapping,
0828                                                   const std::unique_ptr<TotemAnalysisMask> &mask) {
0829   DOMNodeList *children = parent->getChildNodes();
0830 
0831   for (unsigned int i = 0; i < children->getLength(); i++) {
0832     DOMNode *child = children->item(i);
0833     if (child->getNodeType() != DOMNode::ELEMENT_NODE)
0834       continue;
0835 
0836     NodeType type = GetNodeType(child);
0837 
0838     // structure control
0839     if (!TotemT2Node(type))
0840       continue;
0841 
0842     NodeType expectedParentType;
0843     switch (type) {
0844       case nArm:
0845         expectedParentType = nTop;
0846         break;
0847       case nTotemT2Plane:
0848         expectedParentType = nArm;
0849         break;
0850       case nTotemT2Tile:
0851         expectedParentType = nTotemT2Plane;
0852         break;
0853       default:
0854         expectedParentType = nUnknown;
0855         break;
0856     }
0857 
0858     if (expectedParentType != parentType) {
0859       throw cms::Exception("TotemDAQMappingESSourceXML")
0860           << "Node " << cms::xerces::toString(child->getNodeName()) << " not allowed within "
0861           << cms::xerces::toString(parent->getNodeName()) << " block.\n";
0862     }
0863 
0864     unsigned int id = 0;
0865     bool id_set = false;
0866     DOMNamedNodeMap *attr = child->getAttributes();
0867 
0868     for (unsigned int j = 0; j < attr->getLength(); j++) {
0869       DOMNode *a = attr->item(j);
0870       if (!strcmp(cms::xerces::toString(a->getNodeName()).c_str(), "id")) {
0871         sscanf(cms::xerces::toString(a->getNodeValue()).c_str(), "%u", &id);
0872         id_set = true;
0873       }
0874     }
0875     if (pType == pMapping && type == nTotemT2Tile) {
0876       // parse tag attributes
0877       unsigned int hw_id = 0;
0878       bool hw_id_set = false;
0879       unsigned int channel_in_payload = 0;
0880       bool payload_set = false;
0881       DOMNamedNodeMap *attr = child->getAttributes();
0882 
0883       for (unsigned int j = 0; j < attr->getLength(); j++) {
0884         DOMNode *a = attr->item(j);
0885         if (!strcmp(cms::xerces::toString(a->getNodeName()).c_str(), "hwId")) {
0886           sscanf(cms::xerces::toString(a->getNodeValue()).c_str(), "%x", &hw_id);
0887           hw_id_set = true;
0888         }
0889         if (packedPayload && (!strcmp(cms::xerces::toString(a->getNodeName()).c_str(), "pay"))) {
0890           sscanf(cms::xerces::toString(a->getNodeValue()).c_str(), "%u", &channel_in_payload);
0891           payload_set = true;
0892         }
0893       }
0894 
0895       // content control
0896       if (!id_set)
0897         throw cms::Exception("TotemDAQMappingESSourceXML::ParseTreeTotemT2")
0898             << "id not given for element `" << cms::xerces::toString(child->getNodeName()) << "'";
0899       if (!hw_id_set)
0900         throw cms::Exception("TotemDAQMappingESSourceXML::ParseTreeTotemT2")
0901             << "hwId not given for element `" << cms::xerces::toString(child->getNodeName()) << "'";
0902       if (packedPayload && (!payload_set))
0903         throw cms::Exception("TotemDAQMappingESSourceXML::ParseTreeTotemT2")
0904             << "Payload position in fibre not given for element `" << cms::xerces::toString(child->getNodeName())
0905             << "'";
0906 
0907       // store mapping data
0908       const TotemT2FramePosition &framepos = (packedPayload ? ChipT2FramePosition(child) : TotemT2FramePosition());
0909       const TotemFramePosition &frameposSingle = (packedPayload ? TotemFramePosition() : ChipFramePosition(child));
0910       TotemVFATInfo vfatInfo;
0911       vfatInfo.hwID = hw_id;
0912       unsigned int arm = parentID / 10, plane = parentID % 10;
0913       vfatInfo.symbolicID.symbolicID = TotemT2DetId(arm, plane, id);
0914       if (verbosity > 2) {
0915         edm::LogWarning("Totem") << "Print T2 frame pos (payload):" << framepos << " ("
0916                                  << (packedPayload ? "true" : "false") << ") hw_id / T2 DetID" << hw_id << "/"
0917                                  << TotemT2DetId(arm, plane, id) << endl;
0918       }
0919 
0920       if (packedPayload)
0921         mapping->insert(framepos, vfatInfo);
0922       else
0923         mapping->insert(frameposSingle, vfatInfo);
0924 
0925       continue;
0926     }
0927     // follow tree recursively
0928     ParseTreeTotemT2(pType, child, type, parentID * 10 + id, mapping, mask);
0929   }
0930 }
0931 
0932 //----------------------------------------------------------------------------------------------------
0933 
0934 TotemFramePosition TotemDAQMappingESSourceXML::ChipFramePosition(xercesc::DOMNode *chipnode) {
0935   TotemFramePosition fp;
0936   unsigned char attributeFlag = 0;
0937 
0938   DOMNamedNodeMap *attr = chipnode->getAttributes();
0939   for (unsigned int j = 0; j < attr->getLength(); j++) {
0940     DOMNode *a = attr->item(j);
0941     if (fp.setXMLAttribute(
0942             cms::xerces::toString(a->getNodeName()), cms::xerces::toString(a->getNodeValue()), attributeFlag) > 1) {
0943       throw cms::Exception("TotemDAQMappingESSourceXML")
0944           << "Unrecognized tag `" << cms::xerces::toString(a->getNodeName()) << "' or incompatible value `"
0945           << cms::xerces::toString(a->getNodeValue()) << "'.";
0946     }
0947   }
0948 
0949   if (!fp.checkXMLAttributeFlag(attributeFlag)) {
0950     throw cms::Exception("TotemDAQMappingESSourceXML")
0951         << "Wrong/incomplete DAQ channel specification (attributeFlag = " << attributeFlag << ").";
0952   }
0953 
0954   return fp;
0955 }
0956 
0957 //----------------------------------------------------------------------------------------------------
0958 
0959 TotemT2FramePosition TotemDAQMappingESSourceXML::ChipT2FramePosition(xercesc::DOMNode *chipnode) {
0960   TotemT2FramePosition fp;
0961   unsigned char attributeFlag = 0;
0962 
0963   DOMNamedNodeMap *attr = chipnode->getAttributes();
0964   for (unsigned int j = 0; j < attr->getLength(); j++) {
0965     DOMNode *a = attr->item(j);
0966     if (fp.setXMLAttribute(
0967             cms::xerces::toString(a->getNodeName()), cms::xerces::toString(a->getNodeValue()), attributeFlag) > 1) {
0968       throw cms::Exception("TotemDAQMappingESSourceXML")
0969           << "Unrecognized T2 tag `" << cms::xerces::toString(a->getNodeName()) << "' or incompatible value `"
0970           << cms::xerces::toString(a->getNodeValue()) << "'.";
0971     }
0972   }
0973 
0974   if (!fp.checkXMLAttributeFlag(attributeFlag)) {
0975     throw cms::Exception("TotemDAQMappingESSourceXML")
0976         << "Wrong/incomplete T2 DAQ channel specification (attributeFlag = " << attributeFlag << ").";
0977   }
0978 
0979   return fp;
0980 }
0981 //----------------------------------------------------------------------------------------------------
0982 
0983 TotemDAQMappingESSourceXML::NodeType TotemDAQMappingESSourceXML::GetNodeType(xercesc::DOMNode *n) {
0984   // common node types
0985   if (Test(n, tagArm))
0986     return nArm;
0987   if (Test(n, tagChip1))
0988     return nChip;
0989   if (Test(n, tagChip2))
0990     return nChip;
0991 
0992   // RP node types
0993   if (Test(n, tagRPStation))
0994     return nRPStation;
0995   if (Test(n, tagRPPot))
0996     return nRPPot;
0997   if (Test(n, tagRPPlane))
0998     return nRPPlane;
0999 
1000   //diamond specifics
1001   if (Test(n, tagDiamondCh))
1002     return nDiamondCh;
1003   if (Test(n, tagDiamondPlane))
1004     return nDiamondPlane;
1005 
1006   //totem timing specifics
1007   if (Test(n, tagSampicBoard))
1008     return nSampicBoard;
1009   if (Test(n, tagSampicCh))
1010     return nSampicChannel;
1011   if (Test(n, tagTotemTimingCh))
1012     return nTotemTimingCh;
1013   if (Test(n, tagTotemTimingPlane))
1014     return nTotemTimingPlane;
1015 
1016   // TOTEM nT2 specifics
1017   if (Test(n, tagTotemT2Plane))
1018     return nTotemT2Plane;
1019   if (Test(n, tagTotemT2Tile))
1020     return nTotemT2Tile;
1021 
1022   // for backward compatibility
1023   if (Test(n, "trigger_vfat"))
1024     return nSkip;
1025 
1026   throw cms::Exception("TotemDAQMappingESSourceXML::GetNodeType")
1027       << "Unknown tag `" << cms::xerces::toString(n->getNodeName()) << "'.\n";
1028 }
1029 
1030 //----------------------------------------------------------------------------------------------------
1031 
1032 void TotemDAQMappingESSourceXML::GetChannels(xercesc::DOMNode *n, set<unsigned char> &channels) {
1033   DOMNodeList *children = n->getChildNodes();
1034   for (unsigned int i = 0; i < children->getLength(); i++) {
1035     DOMNode *n = children->item(i);
1036     if (n->getNodeType() != DOMNode::ELEMENT_NODE || !Test(n, "channel"))
1037       continue;
1038 
1039     DOMNamedNodeMap *attr = n->getAttributes();
1040     bool idSet = false;
1041     for (unsigned int j = 0; j < attr->getLength(); j++) {
1042       DOMNode *a = attr->item(j);
1043 
1044       if (!strcmp(cms::xerces::toString(a->getNodeName()).c_str(), "id")) {
1045         unsigned int id = 0;
1046         sscanf(cms::xerces::toString(a->getNodeValue()).c_str(), "%u", &id);
1047         channels.insert(id);
1048         idSet = true;
1049         break;
1050       }
1051     }
1052 
1053     if (!idSet) {
1054       throw cms::Exception("TotemDAQMappingESSourceXML::GetChannels") << "Channel tags must have an `id' attribute.";
1055     }
1056   }
1057 }
1058 
1059 //----------------------------------------------------------------------------------------------------
1060 
1061 DEFINE_FWK_EVENTSETUP_SOURCE(TotemDAQMappingESSourceXML);