Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 11:58:36

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