Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-05-04 04:04:15

0001 #ifndef CondFormats_HGCalObjects_interface_HGCalMappingParameterIndex_h
0002 #define CondFormats_HGCalObjects_interface_HGCalMappingParameterIndex_h
0003 
0004 #include <cstdint>
0005 #include <vector>
0006 #include <algorithm>
0007 
0008 #include "DataFormats/HGCalDigi/interface/HGCalElectronicsId.h"
0009 #include "CondFormats/Serialization/interface/Serializable.h"
0010 #include "CondFormats/HGCalObjects/interface/HGCalDenseIndexerBase.h"
0011 #include "CondFormats/HGCalObjects/interface/HGCalMappingCellIndexer.h"
0012 #include "FWCore/Utilities/interface/Exception.h"
0013 
0014 /**
0015    @short this structure holds the indices and types in the readout sequence
0016    as the 12 capture blocks may not all be used and the each capture block may also be under-utilized
0017    a lookup table is used to hold the compact index
0018  */
0019 struct HGCalFEDReadoutSequence_t {
0020   uint32_t id;
0021   ///>look-up table (capture block, econd idx) -> internal dense index
0022   std::vector<int> moduleLUT_;
0023   ///>dense sequence of modules in the readout: the type is the one in use in the cell mapping
0024   std::vector<int> readoutTypes_;
0025   ///>dense sequence of offsets for modules, e-Rx and channel data
0026   std::vector<uint32_t> modOffsets_, erxOffsets_, chDataOffsets_;
0027   COND_SERIALIZABLE;
0028 };
0029 
0030 /**
0031    @short utility class to assign dense readout module indexing
0032    the class holds the information on the expected readout sequence (module types) per FED and their offset in the SoAs of data
0033  */
0034 class HGCalMappingModuleIndexer {
0035 public:
0036   HGCalMappingModuleIndexer() : modFedIndexer_({maxCBperFED_, maxECONDperCB_}) {}
0037 
0038   ~HGCalMappingModuleIndexer() = default;
0039 
0040   /**
0041      @short for a new module it adds it's type to the readaout sequence vector
0042      if the fed id is not yet existing in the mapping it's added
0043      a dense indexer is used to create the necessary indices for the new module
0044      unused indices will be set with -1
0045    */
0046   void processNewModule(uint32_t fedid,
0047                         uint16_t captureblockIdx,
0048                         uint16_t econdIdx,
0049                         uint32_t typecodeIdx,
0050                         uint32_t nerx,
0051                         uint32_t nwords) {
0052     //add fed if needed
0053     if (fedid >= fedReadoutSequences_.size()) {
0054       fedReadoutSequences_.resize(fedid + 1);
0055     }
0056     HGCalFEDReadoutSequence_t &frs = fedReadoutSequences_[fedid];
0057     frs.id = fedid;
0058 
0059     //assign position, resize if needed, and fill the type code
0060     uint32_t idx = modFedIndexer_.denseIndex({{captureblockIdx, econdIdx}});
0061     if (idx >= frs.readoutTypes_.size()) {
0062       frs.readoutTypes_.resize(idx + 1, -1);
0063     }
0064     frs.readoutTypes_[idx] = typecodeIdx;
0065 
0066     //count another typecodein the global list
0067     if (typecodeIdx >= globalTypesCounter_.size()) {
0068       globalTypesCounter_.resize(typecodeIdx + 1, 0);
0069       globalTypesNErx_.resize(typecodeIdx + 1, 0);
0070       globalTypesNWords_.resize(typecodeIdx + 1, 0);
0071       dataOffsets_.resize(typecodeIdx + 1, 0);
0072     }
0073     globalTypesCounter_[typecodeIdx]++;
0074     globalTypesNErx_[typecodeIdx] = nerx;
0075     globalTypesNWords_[typecodeIdx] = nwords;
0076   }
0077 
0078   /**
0079      @short
0080    */
0081   void finalize() {
0082     //max indices at different levels
0083     nfeds_ = fedReadoutSequences_.size();
0084     maxModulesIdx_ = std::accumulate(globalTypesCounter_.begin(), globalTypesCounter_.end(), 0);
0085     maxErxIdx_ =
0086         std::inner_product(globalTypesCounter_.begin(), globalTypesCounter_.end(), globalTypesNErx_.begin(), 0);
0087     maxDataIdx_ =
0088         std::inner_product(globalTypesCounter_.begin(), globalTypesCounter_.end(), globalTypesNWords_.begin(), 0);
0089 
0090     //compute the global offset to assign per board type, eRx and channel data
0091     moduleOffsets_.resize(maxModulesIdx_, 0);
0092     erxOffsets_.resize(maxModulesIdx_, 0);
0093     dataOffsets_.resize(maxModulesIdx_, 0);
0094     for (size_t i = 1; i < globalTypesCounter_.size(); i++) {
0095       moduleOffsets_[i] = globalTypesCounter_[i - 1];
0096       erxOffsets_[i] = globalTypesCounter_[i - 1] * globalTypesNErx_[i - 1];
0097       dataOffsets_[i] = globalTypesCounter_[i - 1] * globalTypesNWords_[i - 1];
0098     }
0099     std::partial_sum(moduleOffsets_.begin(), moduleOffsets_.end(), moduleOffsets_.begin());
0100     std::partial_sum(erxOffsets_.begin(), erxOffsets_.end(), erxOffsets_.begin());
0101     std::partial_sum(dataOffsets_.begin(), dataOffsets_.end(), dataOffsets_.begin());
0102 
0103     //now go through the FEDs and ascribe the offsets per module in the readout sequence
0104     std::vector<uint32_t> typeCounters(globalTypesCounter_.size(), 0);
0105     for (auto &fedit : fedReadoutSequences_) {
0106       //assign the indexing in the look-up table
0107       size_t nconn(0);
0108       fedit.moduleLUT_.resize(fedit.readoutTypes_.size(), -1);
0109       for (size_t i = 0; i < fedit.readoutTypes_.size(); i++) {
0110         if (fedit.readoutTypes_[i] == -1)
0111           continue;  //unexisting
0112         fedit.moduleLUT_[i] = nconn;
0113         nconn++;
0114       }
0115 
0116       //remove unexisting ECONs building a final compact readout sequence
0117       std::remove_if(
0118           fedit.readoutTypes_.begin(), fedit.readoutTypes_.end(), [&](int val) -> bool { return val == -1; });
0119 
0120       //assign the final offsets at the different levels
0121       size_t nmods = fedit.readoutTypes_.size();
0122       fedit.modOffsets_.resize(nmods, 0);
0123       fedit.erxOffsets_.resize(nmods, 0);
0124       fedit.chDataOffsets_.resize(nmods, 0);
0125       for (size_t i = 0; i < nmods; i++) {
0126         uint32_t type_val = fedit.readoutTypes_[i];
0127 
0128         //module offset : global offset for this type + current index for this type
0129         uint32_t baseMod_offset = moduleOffsets_[type_val] + typeCounters[type_val];
0130         fedit.modOffsets_[i] = baseMod_offset;  // + internalMod_offset;
0131 
0132         //erx-level offset : global offset of e-Rx of this type + #e-Rrx * current index for this type
0133         uint32_t baseErx_offset = erxOffsets_[type_val];
0134         uint32_t internalErx_offset = globalTypesNErx_[type_val] * typeCounters[type_val];
0135         fedit.erxOffsets_[i] = baseErx_offset + internalErx_offset;
0136 
0137         //channel data offset: global offset for data of this type + #words * current index for this type
0138         uint32_t baseData_offset = dataOffsets_[type_val];
0139         uint32_t internalData_offset = globalTypesNWords_[type_val] * typeCounters[type_val];
0140         fedit.chDataOffsets_[i] = baseData_offset + internalData_offset;
0141 
0142         typeCounters[type_val]++;
0143       }
0144     }
0145   }
0146 
0147   /**
0148      @short decodes silicon or sipm type and cell type for the detector id 
0149      from the typecode string
0150    */
0151   static std::pair<bool, int> convertTypeCode(std::string_view typecode) {
0152     if (typecode.size() < 5)
0153       throw cms::Exception("InvalidHGCALTypeCode") << typecode << " is invalid for decoding readout cell type";
0154 
0155     bool isSiPM = {typecode.find("TM") != std::string::npos ? true : false};
0156     int celltype;
0157     if (isSiPM) {
0158       celltype = 0;  // Assign SiPM type coarse or molded with next version of modulelocator
0159     } else {
0160       celltype = {typecode[4] == '1' ? 0 : typecode[4] == '2' ? 1 : 2};
0161     }
0162     return std::pair<bool, bool>(isSiPM, celltype);
0163   }
0164 
0165   /**
0166      @short returns the index for the n-th module in the readout sequence of a FED
0167      if the index in the readout sequence is unknown alternative methods which take the (capture block, econd idx) are provided
0168      which will find first what should be the internal dense index (index in the readout sequence)
0169    */
0170   uint32_t getIndexForModule(uint32_t fedid, uint32_t nmod) const {
0171     return fedReadoutSequences_[fedid].modOffsets_[nmod];
0172   };
0173   uint32_t getIndexForModule(uint32_t fedid, uint16_t captureblockIdx, uint16_t econdIdx) const {
0174     uint32_t nmod = denseIndexingFor(fedid, captureblockIdx, econdIdx);
0175     return getIndexForModule(fedid, nmod);
0176   };
0177   uint32_t getIndexForModuleErx(uint32_t fedid, uint32_t nmod, uint32_t erxidx) const {
0178     return fedReadoutSequences_[fedid].erxOffsets_[nmod] + erxidx;
0179   };
0180   uint32_t getIndexForModuleErx(uint32_t fedid, uint16_t captureblockIdx, uint16_t econdIdx, uint32_t erxidx) const {
0181     uint32_t nmod = denseIndexingFor(fedid, captureblockIdx, econdIdx);
0182     return getIndexForModuleErx(fedid, nmod, erxidx);
0183   }
0184   uint32_t getIndexForModuleData(uint32_t fedid, uint32_t nmod, uint32_t erxidx, uint32_t chidx) const {
0185     return fedReadoutSequences_[fedid].chDataOffsets_[nmod] + erxidx * HGCalMappingCellIndexer::maxChPerErx_ + chidx;
0186   };
0187   uint32_t getIndexForModuleData(
0188       uint32_t fedid, uint16_t captureblockIdx, uint16_t econdIdx, uint32_t erxidx, uint32_t chidx) const {
0189     uint32_t nmod = denseIndexingFor(fedid, captureblockIdx, econdIdx);
0190     return getIndexForModuleData(fedid, nmod, erxidx, chidx);
0191   };
0192 
0193   int getTypeForModule(uint32_t fedid, uint32_t nmod) const { return fedReadoutSequences_[fedid].readoutTypes_[nmod]; }
0194   int getTypeForModule(uint32_t fedid, uint16_t captureblockIdx, uint16_t econdIdx) const {
0195     uint32_t nmod = denseIndexingFor(fedid, captureblockIdx, econdIdx);
0196     return getTypeForModule(fedid, nmod);
0197   }
0198 
0199   ///< internal indexer
0200   HGCalDenseIndexerBase modFedIndexer_;
0201   ///< the sequence of FED readout sequence descriptors
0202   std::vector<HGCalFEDReadoutSequence_t> fedReadoutSequences_;
0203   ///< global counters for types of modules, number of e-Rx and words
0204   std::vector<uint32_t> globalTypesCounter_, globalTypesNErx_, globalTypesNWords_;
0205   ///< base offsets to apply per module type with different granularity : module, e-Rx, channel data
0206   std::vector<uint32_t> moduleOffsets_, erxOffsets_, dataOffsets_;
0207   ///< global counters (sizes of vectors)
0208   uint32_t nfeds_, maxDataIdx_, maxErxIdx_, maxModulesIdx_;
0209 
0210   ///< max number of main buffers/capture blocks per FED
0211   constexpr static uint32_t maxCBperFED_ = 10;
0212   ///< max number of ECON-Ds processed by a main buffer/capture block
0213   constexpr static uint32_t maxECONDperCB_ = 12;
0214 
0215 private:
0216   /**
0217      @short given capture block and econd indices returns the dense indexer
0218    */
0219   uint32_t denseIndexingFor(uint32_t fedid, uint16_t captureblockIdx, uint16_t econdIdx) const {
0220     if (fedid > nfeds_)
0221       throw cms::Exception("ValueError") << "FED ID=" << fedid << " is unknown to current mapping";
0222     uint32_t idx = modFedIndexer_.denseIndex({{captureblockIdx, econdIdx}});
0223     auto dense_idx = fedReadoutSequences_[fedid].moduleLUT_[idx];
0224     if (dense_idx < 0)
0225       throw cms::Exception("ValueError") << "FED ID=" << fedid << " capture block=" << captureblockIdx
0226                                          << " econ=" << econdIdx << "has not been assigned a dense indexing"
0227                                          << std::endl;
0228     return uint32_t(dense_idx);
0229   }
0230 
0231   COND_SERIALIZABLE;
0232 };
0233 
0234 #endif