Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:29:25

0001 #include "FWCore/Framework/interface/ConsumesCollector.h"
0002 #include "FWCore/Framework/interface/stream/EDProducer.h"
0003 #include "FWCore/Utilities/interface/ESGetToken.h"
0004 #include "DataFormats/EcalDigi/interface/EcalDigiCollections.h"
0005 #include "SimCalorimetry/EcalSelectiveReadoutAlgos/interface/EcalSelectiveReadoutSuppressor.h"
0006 #include "DataFormats/Provenance/interface/ProductID.h"
0007 #include "CondFormats/EcalObjects/interface/EcalSRSettings.h"
0008 #include "CondFormats/DataRecord/interface/EcalSRSettingsRcd.h"
0009 #include "Geometry/Records/interface/CaloGeometryRecord.h"
0010 #include "Geometry/EcalMapping/interface/EcalMappingRcd.h"
0011 
0012 #include <memory>
0013 #include <vector>
0014 
0015 #include "FWCore/Common/interface/Provenance.h"
0016 #include "FWCore/Framework/interface/Event.h"
0017 #include "FWCore/Framework/interface/EventSetup.h"
0018 
0019 #include "FWCore/Framework/interface/ESHandle.h"
0020 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0021 
0022 #include "FWCore/PluginManager/interface/ModuleDef.h"
0023 #include "FWCore/Framework/interface/MakerMacros.h"
0024 
0025 //#include "DataFormats/EcalDigi/interface/EcalMGPASample.h"
0026 
0027 #include "SimCalorimetry/EcalSelectiveReadoutProducers/interface/namespace_ecalsrcondtools.h"
0028 
0029 #include <memory>
0030 #include <fstream>
0031 #include <atomic>
0032 
0033 namespace esrp {
0034   /* All stream instances of the module write to the same files. The writes are guarded
0035      by the shared mutex.
0036    */
0037   struct Cache {
0038     CMS_THREAD_GUARD("mutex_") mutable int iEvent_ = 1;
0039     mutable std::mutex mutex_;
0040   };
0041 }  // namespace esrp
0042 
0043 class EcalSelectiveReadoutProducer : public edm::stream::EDProducer<edm::GlobalCache<esrp::Cache>> {
0044 public:
0045   /** Constructor
0046    * @param params seletive readout parameters
0047    */
0048   explicit EcalSelectiveReadoutProducer(const edm::ParameterSet& params, esrp::Cache const*);
0049 
0050   /** Destructor
0051    */
0052 
0053   ~EcalSelectiveReadoutProducer() override;
0054 
0055   /** Produces the EDM products
0056    * @param CMS event
0057    * @param eventSetup event conditions
0058    */
0059   void produce(edm::Event& event, const edm::EventSetup& eventSetup) override;
0060 
0061   /** Help function to print SR flags.
0062    * @param ebSrFlags the action flags of EB
0063    * @param eeSrFlag the action flags of EE
0064    * @param iEvent event number. Ignored if <0.
0065    * @param withHeader, if true an output description is written out as header.
0066    */
0067   static void printSrFlags(std::ostream& os,
0068                            const EBSrFlagCollection& ebSrFlags,
0069                            const EESrFlagCollection& eeSrFlags,
0070                            int iEvent = -1,
0071                            bool withHeader = true);
0072 
0073   static void fillDescriptions(edm::ConfigurationDescriptions& iDesc);
0074 
0075   static std::unique_ptr<esrp::Cache> initializeGlobalCache(const edm::ParameterSet&);
0076   static void globalEndJob(esrp::Cache*) {}
0077 
0078 private:
0079   /** Sanity check on the DCC FIR filter weights. Log warning or
0080    * error message if an unexpected weight set is found. In principle
0081    * it is checked that the maximum weight is applied to the expected
0082    * maximum sample.
0083    */
0084   void checkWeights(const edm::Event& evt, const edm::ProductID& noZSDigiId) const;
0085 
0086   /** Gets the value of the digitizer binOfMaximum parameter.
0087    * @param noZsDigiId product ID of the non-suppressed digis
0088    * @param binOfMax [out] set the parameter value if found
0089    * @return true on success, false otherwise
0090    */
0091   bool getBinOfMax(const edm::Event& evt, const edm::ProductID& noZsDigiId, int& binOfMax) const;
0092 
0093   const EBDigiCollection* getEBDigis(edm::Event& event);
0094 
0095   const EEDigiCollection* getEEDigis(edm::Event& event);
0096 
0097   const EcalTrigPrimDigiCollection* getTrigPrims(edm::Event& event) const;
0098 
0099   ///@{
0100   /// call these once an event, to make sure everything
0101   /// is up-to-date
0102   void checkGeometry(const edm::EventSetup& eventSetup);
0103   void checkTriggerMap(const edm::EventSetup& eventSetup);
0104   void checkElecMap(const edm::EventSetup& eventSetup);
0105 
0106   ///@}
0107 
0108   ///Checks validity of selective setting object is valid to be used
0109   ///for MC, especially checks the number of elements in the vectors
0110   ///@param forEmulator if true check the restriction that applies for
0111   ///EcalSelectiveReadoutProducer
0112   ///@throw cms::Exception if the setting is not valid.
0113   static void checkValidity(const EcalSRSettings& settings);
0114 
0115   void printTTFlags(const EcalTrigPrimDigiCollection& tp, std::ostream& os) const;
0116 
0117 private:
0118   EcalSelectiveReadoutSuppressor suppressor_;
0119   std::string digiProducer_;         // name of module/plugin/producer making digis
0120   std::string ebdigiCollection_;     // secondary name given to collection of input digis
0121   std::string eedigiCollection_;     // secondary name given to collection of input digis
0122   std::string ebSRPdigiCollection_;  // secondary name given to collection of suppressed digis
0123   std::string eeSRPdigiCollection_;  // secondary name given to collection of suppressed digis
0124   std::string ebSrFlagCollection_;   // secondary name given to collection of SR flag digis
0125   std::string eeSrFlagCollection_;   // secondary name given to collection of SR flag digis
0126   std::string trigPrimProducer_;     // name of module/plugin/producer making triggere primitives
0127   std::string trigPrimCollection_;   // name of module/plugin/producer making triggere primitives
0128 
0129   // store the pointer, so we don't have to update it every event
0130   const CaloGeometry* theGeometry;
0131   const EcalTrigTowerConstituentsMap* theTriggerTowerMap;
0132   const EcalElectronicsMapping* theElecMap;
0133 
0134   bool suppressorSettingsSet_ = false;
0135 
0136   bool trigPrimBypass_;
0137 
0138   int trigPrimBypassMode_;
0139 
0140   /** Number of event whose TT and SR flags must be dumped into a file.
0141    */
0142   int dumpFlags_;
0143 
0144   /** switch to write out the SrFlags collections in the event
0145    */
0146   bool writeSrFlags_;
0147 
0148   /** Switch for suppressed digi production If false SR flags are produced
0149    * but selective readout is not applied on the crystal channel digis.
0150    */
0151   bool produceDigis_;
0152 
0153   /** SR settings
0154    */
0155   const EcalSRSettings* settings_;
0156 
0157   /** Switch for retrieving SR settings from condition database instead
0158    * of CMSSW python configuration file.
0159    */
0160   bool useCondDb_;
0161 
0162   /**  Special switch to turn off SR entirely using special DB entries 
0163    */
0164 
0165   bool useFullReadout_;
0166 
0167   /** keys
0168    */
0169   bool firstCallEB_;
0170   bool firstCallEE_;
0171 
0172   /** Used when settings_ is imported from configuration file. Just used
0173    * for memory management. Used settings_ to access to the object
0174    */
0175   std::unique_ptr<EcalSRSettings> settingsFromFile_;
0176 
0177   // Tokens for consumes collection:
0178 
0179   edm::EDGetTokenT<EBDigiCollection> EB_token;
0180   edm::EDGetTokenT<EEDigiCollection> EE_token;
0181   edm::EDGetTokenT<EcalTrigPrimDigiCollection> EcTP_token;
0182   edm::ESGetToken<EcalSRSettings, EcalSRSettingsRcd> hSr_token_;
0183   edm::ESGetToken<CaloGeometry, CaloGeometryRecord> geom_token_;
0184   edm::ESGetToken<EcalTrigTowerConstituentsMap, IdealGeometryRecord> eTTmap_token_;
0185   edm::ESGetToken<EcalElectronicsMapping, EcalMappingRcd> eElecmap_token_;
0186 };
0187 
0188 using namespace std;
0189 using namespace ecalsrcondtools;
0190 
0191 std::unique_ptr<esrp::Cache> EcalSelectiveReadoutProducer::initializeGlobalCache(const edm::ParameterSet&) {
0192   return std::make_unique<esrp::Cache>();
0193 }
0194 
0195 EcalSelectiveReadoutProducer::EcalSelectiveReadoutProducer(const edm::ParameterSet& params, esrp::Cache const*)
0196     : suppressor_(params, consumesCollector()), firstCallEB_(true), firstCallEE_(true) {
0197   //settings:
0198   //  settings which are only in python config files:
0199   digiProducer_ = params.getParameter<string>("digiProducer");
0200   ebdigiCollection_ = params.getParameter<std::string>("EBdigiCollection");
0201   eedigiCollection_ = params.getParameter<std::string>("EEdigiCollection");
0202   ebSRPdigiCollection_ = params.getParameter<std::string>("EBSRPdigiCollection");
0203   eeSRPdigiCollection_ = params.getParameter<std::string>("EESRPdigiCollection");
0204   ebSrFlagCollection_ = params.getParameter<std::string>("EBSrFlagCollection");
0205   eeSrFlagCollection_ = params.getParameter<std::string>("EESrFlagCollection");
0206   trigPrimProducer_ = params.getParameter<string>("trigPrimProducer");
0207   trigPrimCollection_ = params.getParameter<string>("trigPrimCollection");
0208   trigPrimBypass_ = params.getParameter<bool>("trigPrimBypass");
0209   trigPrimBypassMode_ = params.getParameter<int>("trigPrimBypassMode");
0210   dumpFlags_ = params.getUntrackedParameter<int>("dumpFlags");
0211   writeSrFlags_ = params.getUntrackedParameter<bool>("writeSrFlags");
0212   produceDigis_ = params.getUntrackedParameter<bool>("produceDigis");
0213   //   settings which can come from either condition database or python configuration file:
0214   useCondDb_ = params.getParameter<bool>("configFromCondDB");
0215   if (!useCondDb_) {
0216     settingsFromFile_ = std::make_unique<EcalSRSettings>();
0217     ecalsrcondtools::importParameterSet(*settingsFromFile_, params);
0218     settings_ = settingsFromFile_.get();
0219   }
0220 
0221   //declares the products made by this producer:
0222   if (produceDigis_) {
0223     produces<EBDigiCollection>(ebSRPdigiCollection_);
0224     produces<EEDigiCollection>(eeSRPdigiCollection_);
0225   }
0226 
0227   if (writeSrFlags_) {
0228     produces<EBSrFlagCollection>(ebSrFlagCollection_);
0229     produces<EESrFlagCollection>(eeSrFlagCollection_);
0230   }
0231 
0232   useFullReadout_ = params.getParameter<bool>("UseFullReadout");
0233 
0234   theGeometry = nullptr;
0235   theTriggerTowerMap = nullptr;
0236   theElecMap = nullptr;
0237 
0238   EB_token = consumes<EBDigiCollection>(edm::InputTag(digiProducer_, ebdigiCollection_));
0239   EE_token = consumes<EEDigiCollection>(edm::InputTag(digiProducer_, eedigiCollection_));
0240   ;
0241   EcTP_token = consumes<EcalTrigPrimDigiCollection>(edm::InputTag(trigPrimProducer_, trigPrimCollection_));
0242   if (useFullReadout_) {
0243     hSr_token_ = esConsumes<EcalSRSettings, EcalSRSettingsRcd>(edm::ESInputTag("", "fullReadout"));
0244   } else {
0245     hSr_token_ = esConsumes<EcalSRSettings, EcalSRSettingsRcd>();
0246   }
0247   geom_token_ = esConsumes<CaloGeometry, CaloGeometryRecord>();
0248   eTTmap_token_ = esConsumes<EcalTrigTowerConstituentsMap, IdealGeometryRecord>();
0249   eElecmap_token_ = esConsumes<EcalElectronicsMapping, EcalMappingRcd>();
0250   ;
0251 }
0252 
0253 void EcalSelectiveReadoutProducer::fillDescriptions(edm::ConfigurationDescriptions& iDesc) {
0254   edm::ParameterSetDescription ps;
0255 
0256   ps.add<string>("digiProducer");
0257   ps.add<std::string>("EBdigiCollection");
0258   ps.add<std::string>("EEdigiCollection");
0259   ps.add<std::string>("EBSRPdigiCollection");
0260   ps.add<std::string>("EESRPdigiCollection");
0261   ps.add<std::string>("EBSrFlagCollection");
0262   ps.add<std::string>("EESrFlagCollection");
0263   ps.add<string>("trigPrimProducer");
0264   ps.add<string>("trigPrimCollection");
0265   ps.add<bool>("trigPrimBypass");     //also used by suppressor
0266   ps.add<int>("trigPrimBypassMode");  // also used by suppressor
0267   ps.addUntracked<int>("dumpFlags", 0);
0268   ps.addUntracked<bool>("writeSrFlags", false);
0269   ps.addUntracked<bool>("produceDigis", true);
0270   ps.add<bool>("configFromCondDB", false);
0271   ps.add<bool>("UseFullReadout");
0272 
0273   //from suppressor_
0274   ps.add<int>("defaultTtf");
0275   ps.add<bool>("trigPrimBypassWithPeakFinder");
0276   ps.add<double>("trigPrimBypassLTH");
0277   ps.add<double>("trigPrimBypassHTH");
0278 
0279   //from importParameterSet
0280   ps.addOptional<int>("deltaPhi");
0281   ps.addOptional<int>("deltaEta");
0282   ps.addOptional<int>("ecalDccZs1stSample");
0283   ps.addOptional<double>("ebDccAdcToGeV");
0284   ps.addOptional<double>("eeDccAdcToGeV");
0285   ps.addOptional<std::vector<double>>("dccNormalizedWeights");
0286   ps.addOptional<bool>("symetricZS");
0287   ps.addOptional<double>("srpBarrelLowInterestChannelZS");
0288   ps.addOptional<double>("srpEndcapLowInterestChannelZS");
0289   ps.addOptional<double>("srpBarrelHighInterestChannelZS");
0290   ps.addOptional<double>("srpEndcapHighInterestChannelZS");
0291 
0292   iDesc.addDefault(ps);
0293 }
0294 
0295 EcalSelectiveReadoutProducer::~EcalSelectiveReadoutProducer() {}
0296 
0297 void EcalSelectiveReadoutProducer::produce(edm::Event& event, const edm::EventSetup& eventSetup) {
0298   if (useCondDb_) {
0299     //getting selective readout configuration:
0300     edm::ESHandle<EcalSRSettings> hSr = eventSetup.getHandle(hSr_token_);
0301 
0302     settings_ = hSr.product();
0303   }
0304 
0305   //gets the trigger primitives:
0306   EcalTrigPrimDigiCollection emptyTPColl;
0307   const EcalTrigPrimDigiCollection* trigPrims =
0308       (trigPrimBypass_ && trigPrimBypassMode_ == 0) ? &emptyTPColl : getTrigPrims(event);
0309 
0310   //gets the digis from the events:
0311   EBDigiCollection dummyEbDigiColl;
0312   EEDigiCollection dummyEeDigiColl;
0313 
0314   const EBDigiCollection* ebDigis = produceDigis_ ? getEBDigis(event) : &dummyEbDigiColl;
0315   const EEDigiCollection* eeDigis = produceDigis_ ? getEEDigis(event) : &dummyEeDigiColl;
0316 
0317   //runs the selective readout algorithm:
0318   unique_ptr<EBDigiCollection> selectedEBDigis;
0319   unique_ptr<EEDigiCollection> selectedEEDigis;
0320   unique_ptr<EBSrFlagCollection> ebSrFlags;
0321   unique_ptr<EESrFlagCollection> eeSrFlags;
0322 
0323   if (produceDigis_) {
0324     selectedEBDigis = std::make_unique<EBDigiCollection>();
0325     selectedEEDigis = std::make_unique<EEDigiCollection>();
0326   }
0327 
0328   if (writeSrFlags_) {
0329     ebSrFlags = std::make_unique<EBSrFlagCollection>();
0330     eeSrFlags = std::make_unique<EESrFlagCollection>();
0331   }
0332 
0333   if (not suppressorSettingsSet_) {
0334     //Check the validity of EcalSRSettings
0335     checkValidity(*settings_);
0336 
0337     suppressor_.setSettings(settings_);
0338     suppressorSettingsSet_ = true;
0339 
0340     // check that everything is up-to-date
0341     checkGeometry(eventSetup);
0342     checkTriggerMap(eventSetup);
0343     checkElecMap(eventSetup);
0344   }
0345 
0346   suppressor_.run(eventSetup,
0347                   *trigPrims,
0348                   *ebDigis,
0349                   *eeDigis,
0350                   selectedEBDigis.get(),
0351                   selectedEEDigis.get(),
0352                   ebSrFlags.get(),
0353                   eeSrFlags.get());
0354 
0355   if (dumpFlags_ > 0) {
0356     auto* cache = globalCache();
0357     std::lock_guard<std::mutex> guard(cache->mutex_);
0358     auto iEvent_ = cache->iEvent_;
0359     if (dumpFlags_ >= iEvent_) {
0360       ofstream ttfFile("TTF.txt", (iEvent_ == 1 ? ios::trunc : ios::app));
0361       suppressor_.printTTFlags(ttfFile, iEvent_, iEvent_ == 1 ? true : false);
0362 
0363       ofstream srfFile("SRF.txt", (iEvent_ == 1 ? ios::trunc : ios::app));
0364       if (iEvent_ == 1) {
0365         suppressor_.getEcalSelectiveReadout()->printHeader(srfFile);
0366       }
0367       srfFile << "# Event " << iEvent_ << "\n";
0368       suppressor_.getEcalSelectiveReadout()->print(srfFile);
0369       srfFile << "\n";
0370 
0371       ofstream afFile("AF.txt", (iEvent_ == 1 ? ios::trunc : ios::app));
0372       printSrFlags(afFile, *ebSrFlags, *eeSrFlags, iEvent_, iEvent_ == 1 ? true : false);
0373       ++(cache->iEvent_);
0374     } else {
0375       //do not want to dump anymore, so can turn off
0376       dumpFlags_ = 0;
0377     }
0378   }
0379 
0380   if (produceDigis_) {
0381     //puts the selected digis into the event:
0382     event.put(std::move(selectedEBDigis), ebSRPdigiCollection_);
0383     event.put(std::move(selectedEEDigis), eeSRPdigiCollection_);
0384   }
0385 
0386   //puts the SR flags into the event:
0387   if (writeSrFlags_) {
0388     event.put(std::move(ebSrFlags), ebSrFlagCollection_);
0389     event.put(std::move(eeSrFlags), eeSrFlagCollection_);
0390   }
0391 }
0392 
0393 const EBDigiCollection* EcalSelectiveReadoutProducer::getEBDigis(edm::Event& event) {
0394   edm::Handle<EBDigiCollection> hEBDigis;
0395   event.getByToken(EB_token, hEBDigis);
0396   //product() method is called before id() in order to get an exception
0397   //if the handle is not available (check not done by id() method).
0398   const EBDigiCollection* result = hEBDigis.product();
0399   if (firstCallEB_) {
0400     checkWeights(event, hEBDigis.id());
0401     firstCallEB_ = false;
0402   }
0403   return result;
0404 }
0405 
0406 const EEDigiCollection* EcalSelectiveReadoutProducer::getEEDigis(edm::Event& event) {
0407   edm::Handle<EEDigiCollection> hEEDigis;
0408   event.getByToken(EE_token, hEEDigis);
0409   //product() method is called before id() in order to get an exception
0410   //if the handle is not available (check not done by id() method).
0411   const EEDigiCollection* result = hEEDigis.product();
0412   if (firstCallEE_) {
0413     checkWeights(event, hEEDigis.id());
0414     firstCallEE_ = false;
0415   }
0416   return result;
0417 }
0418 
0419 const EcalTrigPrimDigiCollection* EcalSelectiveReadoutProducer::getTrigPrims(edm::Event& event) const {
0420   edm::Handle<EcalTrigPrimDigiCollection> hTPDigis;
0421   event.getByToken(EcTP_token, hTPDigis);
0422   return hTPDigis.product();
0423 }
0424 
0425 void EcalSelectiveReadoutProducer::checkGeometry(const edm::EventSetup& eventSetup) {
0426   edm::ESHandle<CaloGeometry> hGeometry = eventSetup.getHandle(geom_token_);
0427 
0428   const CaloGeometry* pGeometry = &*hGeometry;
0429 
0430   // see if we need to update
0431   if (pGeometry != theGeometry) {
0432     theGeometry = pGeometry;
0433     suppressor_.setGeometry(theGeometry);
0434   }
0435 }
0436 
0437 void EcalSelectiveReadoutProducer::checkTriggerMap(const edm::EventSetup& eventSetup) {
0438   edm::ESHandle<EcalTrigTowerConstituentsMap> eTTmap = eventSetup.getHandle(eTTmap_token_);
0439 
0440   const EcalTrigTowerConstituentsMap* pMap = &*eTTmap;
0441 
0442   // see if we need to update
0443   if (pMap != theTriggerTowerMap) {
0444     theTriggerTowerMap = pMap;
0445     suppressor_.setTriggerMap(theTriggerTowerMap);
0446   }
0447 }
0448 
0449 void EcalSelectiveReadoutProducer::checkElecMap(const edm::EventSetup& eventSetup) {
0450   edm::ESHandle<EcalElectronicsMapping> eElecmap = eventSetup.getHandle(eElecmap_token_);
0451 
0452   const EcalElectronicsMapping* pMap = &*eElecmap;
0453 
0454   // see if we need to update
0455   if (pMap != theElecMap) {
0456     theElecMap = pMap;
0457     suppressor_.setElecMap(theElecMap);
0458   }
0459 }
0460 
0461 void EcalSelectiveReadoutProducer::printTTFlags(const EcalTrigPrimDigiCollection& tp, ostream& os) const {
0462   const char tccFlagMarker[] = {'x', '.', 'S', '?', 'C', 'E', 'E', 'E', 'E'};
0463   const int nEta = EcalSelectiveReadout::nTriggerTowersInEta;
0464   const int nPhi = EcalSelectiveReadout::nTriggerTowersInPhi;
0465 
0466   //static bool firstCall=true;
0467   //  if(firstCall){
0468   //  firstCall=false;
0469   os << "# TCC flag map\n#\n"
0470         "# +-->Phi            "
0471      << tccFlagMarker[0 + 1]
0472      << ": 000 (low interest)\n"
0473         "# |                  "
0474      << tccFlagMarker[1 + 1]
0475      << ": 001 (mid interest)\n"
0476         "# |                  "
0477      << tccFlagMarker[2 + 1]
0478      << ": 010 (not valid)\n"
0479         "# V Eta              "
0480      << tccFlagMarker[3 + 1]
0481      << ": 011 (high interest)\n"
0482         "#                    "
0483      << tccFlagMarker[4 + 1]
0484      << ": 1xx forced readout (Hw error)\n"
0485         "#\n";
0486   //}
0487 
0488   vector<vector<int>> ttf(nEta, vector<int>(nPhi, -1));
0489   for (EcalTrigPrimDigiCollection::const_iterator it = tp.begin(); it != tp.end(); ++it) {
0490     const EcalTriggerPrimitiveDigi& trigPrim = *it;
0491     if (trigPrim.size() > 0) {
0492       int iEta = trigPrim.id().ieta();
0493       int iEta0 = iEta < 0 ? iEta + nEta / 2 : iEta + nEta / 2 - 1;
0494       int iPhi0 = trigPrim.id().iphi() - 1;
0495       ttf[iEta0][iPhi0] = trigPrim.ttFlag();
0496     }
0497   }
0498   for (int iEta = 0; iEta < nEta; ++iEta) {
0499     for (int iPhi = 0; iPhi < nPhi; ++iPhi) {
0500       os << tccFlagMarker[ttf[iEta][iPhi] + 1];
0501     }
0502     os << "\n";
0503   }
0504 }
0505 
0506 void EcalSelectiveReadoutProducer::checkWeights(const edm::Event& evt, const edm::ProductID& noZsDigiId) const {
0507   const vector<float>& weights =
0508       settings_->dccNormalizedWeights_[0];  //params_.getParameter<vector<double> >("dccNormalizedWeights");
0509   int nFIRTaps = EcalSelectiveReadoutSuppressor::getFIRTapCount();
0510   static std::atomic<bool> warnWeightCnt{true};
0511   bool expected = true;
0512   if ((int)weights.size() > nFIRTaps &&
0513       warnWeightCnt.compare_exchange_strong(expected, false, std::memory_order_acq_rel)) {
0514     edm::LogWarning("Configuration") << "The list of DCC zero suppression FIR "
0515                                         "weights given in parameter dccNormalizedWeights is longer "
0516                                         "than the expected depth of the FIR filter :("
0517                                      << nFIRTaps
0518                                      << "). "
0519                                         "The last weights will be discarded.";
0520   }
0521 
0522   if (!weights.empty()) {
0523     int iMaxWeight = 0;
0524     double maxWeight = weights[iMaxWeight];
0525     //looks for index of maximum weight
0526     for (unsigned i = 0; i < weights.size(); ++i) {
0527       if (weights[i] > maxWeight) {
0528         iMaxWeight = i;
0529         maxWeight = weights[iMaxWeight];
0530       }
0531     }
0532 
0533     //position of time sample whose maximum weight is applied:
0534     int maxWeightBin = settings_->ecalDccZs1stSample_[0]  //params_.getParameter<int>("ecalDccZs1stSample")
0535                        + iMaxWeight;
0536 
0537     //gets the bin of maximum (in case of raw data it will not exist)
0538     int binOfMax = 0;
0539     bool rc = getBinOfMax(evt, noZsDigiId, binOfMax);
0540 
0541     if (rc && maxWeightBin != binOfMax) {
0542       edm::LogWarning("Configuration") << "The maximum weight of DCC zero suppression FIR filter is not "
0543                                           "applied to the expected maximum sample("
0544                                        << binOfMax
0545                                        << (binOfMax == 1 ? "st"
0546                                                          : (binOfMax == 2 ? "nd" : (binOfMax == 3 ? "rd" : "th")))
0547                                        << " time sample). This may indicate faulty 'dccNormalizedWeights' "
0548                                           "or 'ecalDccZs1sSample' parameters.";
0549     }
0550   }
0551 }
0552 
0553 bool EcalSelectiveReadoutProducer::getBinOfMax(const edm::Event& evt,
0554                                                const edm::ProductID& noZsDigiId,
0555                                                int& binOfMax) const {
0556   bool rc;
0557   const edm::StableProvenance& p = evt.getStableProvenance(noZsDigiId);
0558   const edm::ParameterSet& result = parameterSet(p, evt.processHistory());
0559   vector<string> ebDigiParamList = result.getParameterNames();
0560   string bofm("binOfMaximum");
0561   if (find(ebDigiParamList.begin(), ebDigiParamList.end(), bofm) != ebDigiParamList.end()) {  //bofm found
0562     binOfMax = result.getParameter<int>("binOfMaximum");
0563     rc = true;
0564   } else {
0565     rc = false;
0566   }
0567   return rc;
0568 }
0569 
0570 void EcalSelectiveReadoutProducer::printSrFlags(ostream& os,
0571                                                 const EBSrFlagCollection& ebSrFlags,
0572                                                 const EESrFlagCollection& eeSrFlags,
0573                                                 int iEvent,
0574                                                 bool withHeader) {
0575   const char srpFlagMarker[] = {'.', 'z', 'Z', 'F', '4', '5', '6', '7'};
0576   if (withHeader) {
0577     time_t t;
0578     time(&t);
0579     const char* date = ctime(&t);
0580     os << "#SRP flag map\n#\n"
0581           "# Generatied on: "
0582        << date
0583        << "\n#\n"
0584           "# +-->Phi/Y "
0585        << srpFlagMarker[0]
0586        << ": suppressed\n"
0587           "# |         "
0588        << srpFlagMarker[1]
0589        << ": ZS 1\n"
0590           "# |         "
0591        << srpFlagMarker[2]
0592        << ": ZS 2\n"
0593           "# V Eta/X   "
0594        << srpFlagMarker[3]
0595        << ": full readout\n"
0596           "#\n";
0597   }
0598 
0599   //EE-,EB,EE+ map wil be written onto file in following format:
0600   //
0601   //      72
0602   // <-------------->
0603   //  20
0604   // <--->
0605   //  EEE                A             +-----> Y
0606   // EEEEE               |             |
0607   // EE EE               | 20   EE-    |
0608   // EEEEE               |             |
0609   //  EEE                V             V X
0610   // BBBBBBBBBBBBBBBBB   A
0611   // BBBBBBBBBBBBBBBBB   |             +-----> Phi
0612   // BBBBBBBBBBBBBBBBB   |             |
0613   // BBBBBBBBBBBBBBBBB   | 34  EB      |
0614   // BBBBBBBBBBBBBBBBB   |             |
0615   // BBBBBBBBBBBBBBBBB   |             V Eta
0616   // BBBBBBBBBBBBBBBBB   |
0617   // BBBBBBBBBBBBBBBBB   |
0618   // BBBBBBBBBBBBBBBBB   V
0619   //  EEE                A             +-----> Y
0620   // EEEEE               |             |
0621   // EE EE               | 20 EE+      |
0622   // EEEEE               |             |
0623   //  EEE                V             V X
0624   //
0625   //
0626   //
0627   //
0628   //event header:
0629   if (iEvent >= 0) {
0630     os << "# Event " << iEvent << "\n";
0631   }
0632 
0633   //retrieve flags:
0634   const int nEndcaps = 2;
0635   const int nScX = 20;
0636   const int nScY = 20;
0637   int eeSrf[nEndcaps][nScX][nScY];
0638   for (size_t i = 0; i < sizeof(eeSrf) / sizeof(int); ((int*)eeSrf)[i++] = -1) {
0639   };
0640   for (EESrFlagCollection::const_iterator it = eeSrFlags.begin(); it != eeSrFlags.end(); ++it) {
0641     const EESrFlag& flag = *it;
0642     int iZ0 = flag.id().zside() > 0 ? 1 : 0;
0643     int iX0 = flag.id().ix() - 1;
0644     int iY0 = flag.id().iy() - 1;
0645     assert(iZ0 >= 0 && iZ0 < nEndcaps);
0646     assert(iX0 >= 0 && iX0 < nScX);
0647     assert(iY0 >= 0 && iY0 < nScY);
0648     eeSrf[iZ0][iX0][iY0] = flag.value();
0649   }
0650   const int nEbTtEta = 34;
0651   const int nEeTtEta = 11;
0652   const int nTtEta = nEeTtEta * 2 + nEbTtEta;
0653   const int nTtPhi = 72;
0654   int ebSrf[nEbTtEta][nTtPhi];
0655   for (size_t i = 0; i < sizeof(ebSrf) / sizeof(int); ((int*)ebSrf)[i++] = -1) {
0656   };
0657   for (EBSrFlagCollection::const_iterator it = ebSrFlags.begin(); it != ebSrFlags.end(); ++it) {
0658     const EBSrFlag& flag = *it;
0659     int iEta = flag.id().ieta();
0660     int iEta0 = iEta + nTtEta / 2 - (iEta >= 0 ? 1 : 0);  //0->55 from eta=-3 to eta=3
0661     int iEbEta0 = iEta0 - nEeTtEta;                       //0->33 from eta=-1.48 to eta=1.48
0662     int iPhi0 = flag.id().iphi() - 1;
0663     assert(iEbEta0 >= 0 && iEbEta0 < nEbTtEta);
0664     assert(iPhi0 >= 0 && iPhi0 < nTtPhi);
0665 
0666     //     cout << __FILE__ << ":" << __LINE__ << ": "
0667     //   <<  iEta << "\t" << flag.id().iphi() << " -> "
0668     //   << iEbEta0 << "\t" << iPhi0
0669     //   << "... Flag: " << flag.value() << "\n";
0670 
0671     ebSrf[iEbEta0][iPhi0] = flag.value();
0672   }
0673 
0674   //print flags:
0675 
0676   //EE-
0677   for (int iX0 = 0; iX0 < nScX; ++iX0) {
0678     for (int iY0 = 0; iY0 < nScY; ++iY0) {
0679       int srFlag = eeSrf[0][iX0][iY0];
0680       assert(srFlag >= -1 && srFlag < (int)(sizeof(srpFlagMarker) / sizeof(srpFlagMarker[0])));
0681       os << (srFlag == -1 ? ' ' : srpFlagMarker[srFlag]);
0682     }
0683     os << "\n";  //one Y supercystal column per line
0684   }              //next supercrystal X-index
0685 
0686   //EB
0687   for (int iEta0 = 0; iEta0 < nEbTtEta; ++iEta0) {
0688     for (int iPhi0 = 0; iPhi0 < nTtPhi; ++iPhi0) {
0689       int srFlag = ebSrf[iEta0][iPhi0];
0690       assert(srFlag >= -1 && srFlag < (int)(sizeof(srpFlagMarker) / sizeof(srpFlagMarker[0])));
0691       os << (srFlag == -1 ? '?' : srpFlagMarker[srFlag]);
0692     }
0693     os << "\n";  //one phi per line
0694   }
0695 
0696   //EE+
0697   for (int iX0 = 0; iX0 < nScX; ++iX0) {
0698     for (int iY0 = 0; iY0 < nScY; ++iY0) {
0699       int srFlag = eeSrf[1][iX0][iY0];
0700       assert(srFlag >= -1 && srFlag < (int)(sizeof(srpFlagMarker) / sizeof(srpFlagMarker[0])));
0701       os << (srFlag == -1 ? ' ' : srpFlagMarker[srFlag]);
0702     }
0703     os << "\n";  //one Y supercystal column per line
0704   }              //next supercrystal X-index
0705 
0706   //event trailer:
0707   os << "\n";
0708 }
0709 
0710 void EcalSelectiveReadoutProducer::checkValidity(const EcalSRSettings& settings) {
0711   if (settings.dccNormalizedWeights_.size() != 1) {
0712     throw cms::Exception("Configuration")
0713         << "Selective readout emulator, EcalSelectiveReadout, supports only single set of ZS weights. "
0714            "while the configuration contains "
0715         << settings.dccNormalizedWeights_.size() << " set(s)\n";
0716   }
0717 
0718   //   if(settings.dccNormalizedWeights_.size() != 1
0719   //      && settings.dccNormalizedWeights_.size() != 2
0720   //      && settings.dccNormalizedWeights_.size() != 54
0721   //      && settings.dccNormalizedWeights_.size() != 75848){
0722   //     throw cms::Exception("Configuration") << "Invalid number of DCC weight set (" << settings.dccNormalizedWeights_.size()
0723   //       << ") in condition object EcalSRSetting::dccNormalizedWeights_. "
0724   //       << "Valid counts are: 1 (single set), 2 (EB and EE), 54 (one per DCC) and 75848 "
0725   //       "(one per crystal)\n";
0726   //   }
0727 
0728   if (settings.dccNormalizedWeights_.size() != settings.ecalDccZs1stSample_.size()) {
0729     throw cms::Exception("Configuration")
0730         << "Inconsistency between number of weigth sets (" << settings.dccNormalizedWeights_.size() << ") and "
0731         << "number of ecalDccZs1Sample values (" << settings.ecalDccZs1stSample_.size() << ").";
0732   }
0733 }
0734 
0735 DEFINE_FWK_MODULE(EcalSelectiveReadoutProducer);