Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:26:27

0001 /*
0002  */
0003 #include "RecoLocalTracker/SiStripClusterizer/interface/StripClusterizerAlgorithmFactory.h"
0004 #include "RecoLocalTracker/SiStripZeroSuppression/interface/SiStripRawProcessingFactory.h"
0005 
0006 #include "RecoLocalTracker/SiStripClusterizer/interface/StripClusterizerAlgorithm.h"
0007 #include "RecoLocalTracker/SiStripZeroSuppression/interface/SiStripRawProcessingAlgorithms.h"
0008 
0009 #include "DataFormats/SiStripCluster/interface/SiStripCluster.h"
0010 #include "DataFormats/Common/interface/DetSetVectorNew.h"
0011 
0012 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
0013 #include "EventFilter/SiStripRawToDigi/interface/SiStripFEDBuffer.h"
0014 #include "DataFormats/SiStripCommon/interface/SiStripConstants.h"
0015 
0016 #include "CalibFormats/SiStripObjects/interface/SiStripDetCabling.h"
0017 
0018 #include "FWCore/Framework/interface/stream/EDProducer.h"
0019 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0020 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0021 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0022 #include "FWCore/Utilities/interface/InputTag.h"
0023 #include "FWCore/Framework/interface/Event.h"
0024 #include "FWCore/Framework/interface/EventSetup.h"
0025 #include "FWCore/Framework/interface/ESHandle.h"
0026 #include "FWCore/Utilities/interface/Likely.h"
0027 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0028 
0029 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0030 #include <sstream>
0031 #include <memory>
0032 #include <atomic>
0033 #include <mutex>
0034 
0035 // #define VIDEBUG
0036 #ifdef VIDEBUG
0037 #include <iostream>
0038 #define COUT std::cout << "VI "
0039 #else
0040 #define COUT LogDebug("")
0041 #endif
0042 
0043 namespace {
0044   std::unique_ptr<sistrip::FEDBuffer> fillBuffer(int fedId, const FEDRawDataCollection& rawColl) {
0045     std::unique_ptr<sistrip::FEDBuffer> buffer;
0046 
0047     // Retrieve FED raw data for given FED
0048     const FEDRawData& rawData = rawColl.FEDData(fedId);
0049 
0050     // Check on FEDRawData pointer
0051     const auto st_buffer = sistrip::preconstructCheckFEDBuffer(rawData);
0052     if UNLIKELY (sistrip::FEDBufferStatusCode::SUCCESS != st_buffer) {
0053       if (edm::isDebugEnabled()) {
0054         edm::LogWarning(sistrip::mlRawToCluster_)
0055             << "[ClustersFromRawProducer::" << __func__ << "]" << st_buffer << " for FED ID " << fedId;
0056       }
0057       return buffer;
0058     }
0059     buffer = std::make_unique<sistrip::FEDBuffer>(rawData);
0060     const auto st_chan = buffer->findChannels();
0061     if UNLIKELY (sistrip::FEDBufferStatusCode::SUCCESS != st_chan) {
0062       if (edm::isDebugEnabled()) {
0063         edm::LogWarning(sistrip::mlRawToCluster_)
0064             << "Exception caught when creating FEDBuffer object for FED " << fedId << ": " << st_chan;
0065       }
0066       buffer.reset();
0067       return buffer;
0068     }
0069     if UNLIKELY (!buffer->doChecks(false)) {
0070       if (edm::isDebugEnabled()) {
0071         edm::LogWarning(sistrip::mlRawToCluster_)
0072             << "Exception caught when creating FEDBuffer object for FED " << fedId << ": FED Buffer check fails";
0073       }
0074       buffer.reset();
0075       return buffer;
0076     }
0077 
0078     /*
0079     // dump of FEDRawData to stdout
0080     if ( dump_ ) {
0081     std::stringstream ss;
0082     RawToDigiUnpacker::dumpRawData( fedId, rawData, ss );
0083     LogTrace(mlRawToDigi_) 
0084     << ss.str();
0085     }
0086     */
0087 
0088     return buffer;
0089   }
0090 
0091   class ClusterFiller final : public StripClusterizerAlgorithm::output_t::Getter {
0092   public:
0093     ClusterFiller(const FEDRawDataCollection& irawColl,
0094                   StripClusterizerAlgorithm& iclusterizer,
0095                   SiStripRawProcessingAlgorithms& irawAlgos,
0096                   bool idoAPVEmulatorCheck,
0097                   bool legacy,
0098                   bool hybridZeroSuppressed)
0099         : rawColl(irawColl),
0100           clusterizer(iclusterizer),
0101           conditions(iclusterizer.conditions()),
0102           rawAlgos(irawAlgos),
0103           doAPVEmulatorCheck(idoAPVEmulatorCheck),
0104           legacy_(legacy),
0105           hybridZeroSuppressed_(hybridZeroSuppressed) {
0106       incTot(clusterizer.conditions().allDetIds().size());
0107       for (auto& d : done)
0108         d = nullptr;
0109     }
0110 
0111     ~ClusterFiller() override { printStat(); }
0112 
0113     void fill(StripClusterizerAlgorithm::output_t::TSFastFiller& record) const override;
0114 
0115   private:
0116     CMS_THREAD_GUARD(done) mutable std::unique_ptr<sistrip::FEDBuffer> buffers[1024];
0117     mutable std::atomic<sistrip::FEDBuffer*> done[1024];
0118 
0119     const FEDRawDataCollection& rawColl;
0120 
0121     StripClusterizerAlgorithm& clusterizer;
0122     const SiStripClusterizerConditions& conditions;
0123     SiStripRawProcessingAlgorithms& rawAlgos;
0124 
0125     // March 2012: add flag for disabling APVe check in configuration
0126     bool doAPVEmulatorCheck;
0127 
0128     bool legacy_;
0129     bool hybridZeroSuppressed_;
0130 
0131 #ifdef VIDEBUG
0132     struct Stat {
0133       Stat() : totDet(0), detReady(0), detSet(0), detAct(0), detNoZ(0), detAbrt(0), totClus(0) {}
0134       std::atomic<int> totDet;    // all dets
0135       std::atomic<int> detReady;  // dets "updated"
0136       std::atomic<int> detSet;    // det actually set not empty
0137       std::atomic<int> detAct;    // det actually set with content
0138       std::atomic<int> detNoZ;    // det actually set with content
0139       std::atomic<int> detAbrt;   // det aborted
0140       std::atomic<int> totClus;   // total number of clusters
0141     };
0142 
0143     mutable Stat stat;
0144     // void zeroStat() const { stat = std::move(Stat()); }
0145     void incTot(int n) const { stat.totDet = n; }
0146     void incReady() const { stat.detReady++; }
0147     void incSet() const { stat.detSet++; }
0148     void incAct() const { stat.detAct++; }
0149     void incNoZ() const { stat.detNoZ++; }
0150     void incAbrt() const { stat.detAbrt++; }
0151     void incClus(int n) const { stat.totClus += n; }
0152     void printStat() const {
0153       COUT << "VI clusters " << stat.totDet << ',' << stat.detReady << ',' << stat.detSet << ',' << stat.detAct << ','
0154            << stat.detNoZ << ',' << stat.detAbrt << ',' << stat.totClus << std::endl;
0155     }
0156 
0157 #else
0158     static void zeroStat() {}
0159     static void incTot(int) {}
0160     static void incReady() {}
0161     static void incSet() {}
0162     static void incAct() {}
0163     static void incNoZ() {}
0164     static void incAbrt() {}
0165     static void incClus(int) {}
0166     static void printStat() {}
0167 #endif
0168   };
0169 }  // namespace
0170 
0171 class SiStripClusterizerFromRaw final : public edm::stream::EDProducer<> {
0172 public:
0173   explicit SiStripClusterizerFromRaw(const edm::ParameterSet& conf)
0174       : onDemand(conf.getParameter<bool>("onDemand")),
0175         clusterizer_(StripClusterizerAlgorithmFactory::create(consumesCollector(),
0176                                                               conf.getParameter<edm::ParameterSet>("Clusterizer"))),
0177         rawAlgos_(SiStripRawProcessingFactory::create(conf.getParameter<edm::ParameterSet>("Algorithms"),
0178                                                       consumesCollector())),
0179         doAPVEmulatorCheck_(conf.getParameter<bool>("DoAPVEmulatorCheck")),
0180         legacy_(conf.getParameter<bool>("LegacyUnpacker")),
0181         hybridZeroSuppressed_(conf.getParameter<bool>("HybridZeroSuppressed")) {
0182     productToken_ = consumes<FEDRawDataCollection>(conf.getParameter<edm::InputTag>("ProductLabel"));
0183     produces<edmNew::DetSetVector<SiStripCluster> >();
0184     assert(clusterizer_.get());
0185     assert(rawAlgos_.get());
0186   }
0187 
0188   void produce(edm::Event& ev, const edm::EventSetup& es) override {
0189     initialize(es);
0190 
0191     // get raw data
0192     edm::Handle<FEDRawDataCollection> rawData;
0193     ev.getByToken(productToken_, rawData);
0194 
0195     std::unique_ptr<edmNew::DetSetVector<SiStripCluster> > output(
0196         onDemand ? new edmNew::DetSetVector<SiStripCluster>(
0197                        std::shared_ptr<edmNew::DetSetVector<SiStripCluster>::Getter>(std::make_shared<ClusterFiller>(
0198                            *rawData, *clusterizer_, *rawAlgos_, doAPVEmulatorCheck_, legacy_, hybridZeroSuppressed_)),
0199                        clusterizer_->conditions().allDetIds())
0200                  : new edmNew::DetSetVector<SiStripCluster>());
0201 
0202     if (onDemand)
0203       assert(output->onDemand());
0204 
0205     output->reserve(15000, 24 * 10000);
0206 
0207     if (!onDemand) {
0208       run(*rawData, *output);
0209       output->shrink_to_fit();
0210       COUT << output->dataSize() << " clusters from " << output->size() << " modules" << std::endl;
0211     }
0212 
0213     ev.put(std::move(output));
0214   }
0215 
0216   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0217 
0218 private:
0219   void initialize(const edm::EventSetup& es);
0220 
0221   void run(const FEDRawDataCollection& rawColl, edmNew::DetSetVector<SiStripCluster>& output);
0222 
0223 private:
0224   bool onDemand;
0225 
0226   edm::EDGetTokenT<FEDRawDataCollection> productToken_;
0227 
0228   std::unique_ptr<StripClusterizerAlgorithm> clusterizer_;
0229   std::unique_ptr<SiStripRawProcessingAlgorithms> rawAlgos_;
0230 
0231   // March 2012: add flag for disabling APVe check in configuration
0232   bool doAPVEmulatorCheck_;
0233 
0234   bool legacy_;
0235   bool hybridZeroSuppressed_;
0236 };
0237 
0238 void SiStripClusterizerFromRaw::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0239   edm::ParameterSetDescription desc;
0240 
0241   desc.add("ProductLabel", edm::InputTag("rawDataCollector"));
0242   desc.add<std::string>("ConditionsLabel", "");
0243   desc.add("onDemand", true);
0244   desc.add("DoAPVEmulatorCheck", true);
0245   desc.add("LegacyUnpacker", false);
0246   desc.add("HybridZeroSuppressed", false);
0247 
0248   edm::ParameterSetDescription clusterizer;
0249   StripClusterizerAlgorithmFactory::fillDescriptions(clusterizer);
0250   desc.add("Clusterizer", clusterizer);
0251 
0252   edm::ParameterSetDescription algorithms;
0253   SiStripRawProcessingFactory::fillDescriptions(algorithms);
0254   desc.add("Algorithms", algorithms);
0255 
0256   descriptions.addWithDefaultLabel(desc);
0257 }
0258 
0259 #include "FWCore/Framework/interface/MakerMacros.h"
0260 DEFINE_FWK_MODULE(SiStripClusterizerFromRaw);
0261 
0262 void SiStripClusterizerFromRaw::initialize(const edm::EventSetup& es) {
0263   (*clusterizer_).initialize(es);
0264   (*rawAlgos_).initialize(es);
0265 }
0266 
0267 void SiStripClusterizerFromRaw::run(const FEDRawDataCollection& rawColl, edmNew::DetSetVector<SiStripCluster>& output) {
0268   ClusterFiller filler(rawColl, *clusterizer_, *rawAlgos_, doAPVEmulatorCheck_, legacy_, hybridZeroSuppressed_);
0269 
0270   // loop over good det in cabling
0271   for (auto idet : clusterizer_->conditions().allDetIds()) {
0272     StripClusterizerAlgorithm::output_t::TSFastFiller record(output, idet);
0273 
0274     filler.fill(record);
0275 
0276     if (record.empty())
0277       record.abort();
0278   }  // end loop over dets
0279 }
0280 
0281 namespace {
0282   class StripByStripAdder {
0283   public:
0284     typedef std::output_iterator_tag iterator_category;
0285     typedef void value_type;
0286     typedef void difference_type;
0287     typedef void pointer;
0288     typedef void reference;
0289 
0290     StripByStripAdder(StripClusterizerAlgorithm& clusterizer,
0291                       StripClusterizerAlgorithm::State& state,
0292                       StripClusterizerAlgorithm::output_t::TSFastFiller& record)
0293         : clusterizer_(clusterizer), state_(state), record_(record) {}
0294 
0295     StripByStripAdder& operator=(SiStripDigi digi) {
0296       clusterizer_.stripByStripAdd(state_, digi.strip(), digi.adc(), record_);
0297       return *this;
0298     }
0299 
0300     StripByStripAdder& operator*() { return *this; }
0301     StripByStripAdder& operator++() { return *this; }
0302     StripByStripAdder& operator++(int) { return *this; }
0303 
0304   private:
0305     StripClusterizerAlgorithm& clusterizer_;
0306     StripClusterizerAlgorithm::State& state_;
0307     StripClusterizerAlgorithm::output_t::TSFastFiller& record_;
0308   };
0309 
0310   template <typename Container>
0311   class ADC_back_inserter {
0312   public:
0313     ADC_back_inserter(Container& c) : c_(c) {}
0314 
0315     ADC_back_inserter& operator=(SiStripRawDigi digi) {
0316       c_.push_back(digi.adc());
0317       return *this;
0318     }
0319     ADC_back_inserter& operator*() { return *this; }
0320     ADC_back_inserter& operator++() { return *this; }
0321     ADC_back_inserter& operator++(int) { return *this; }
0322 
0323   private:
0324     Container& c_;
0325   };
0326 }  // namespace
0327 
0328 void ClusterFiller::fill(StripClusterizerAlgorithm::output_t::TSFastFiller& record) const {
0329   try {  // edmNew::CapacityExaustedException
0330     incReady();
0331 
0332     auto idet = record.id();
0333 
0334     COUT << "filling " << idet << std::endl;
0335 
0336     auto const& det = clusterizer.stripByStripBegin(idet);
0337     if (!det.valid())
0338       return;
0339     StripClusterizerAlgorithm::State state(det);
0340 
0341     incSet();
0342     record.reserve(16);
0343     // Loop over apv-pairs of det
0344     for (auto const conn : conditions.currentConnection(det)) {
0345       if UNLIKELY (!conn)
0346         continue;
0347 
0348       const uint16_t fedId = conn->fedId();
0349 
0350       // If fed id is null or connection is invalid continue
0351       if UNLIKELY (!fedId || !conn->isConnected()) {
0352         continue;
0353       }
0354 
0355       // If Fed hasnt already been initialised, extract data and initialise
0356       sistrip::FEDBuffer* buffer = done[fedId];
0357       if (!buffer) {
0358         buffer = fillBuffer(fedId, rawColl).release();
0359         if (!buffer) {
0360           continue;
0361         }
0362         sistrip::FEDBuffer* exp = nullptr;
0363         if (done[fedId].compare_exchange_strong(exp, buffer))
0364           buffers[fedId].reset(buffer);
0365         else {
0366           delete buffer;
0367           buffer = done[fedId];
0368         }
0369       }
0370       assert(buffer);
0371 
0372       buffer->setLegacyMode(legacy_);
0373 
0374       // check channel
0375       const uint8_t fedCh = conn->fedCh();
0376 
0377       if UNLIKELY (!buffer->channelGood(fedCh, doAPVEmulatorCheck)) {
0378         if (edm::isDebugEnabled()) {
0379           std::ostringstream ss;
0380           ss << "Problem unpacking channel " << fedCh << " on FED " << fedId;
0381           edm::LogWarning(sistrip::mlRawToCluster_) << ss.str();
0382         }
0383         continue;
0384       }
0385 
0386       // Determine APV std::pair number
0387       uint16_t ipair = conn->apvPairNumber();
0388 
0389       const sistrip::FEDReadoutMode mode = buffer->readoutMode();
0390       const sistrip::FEDLegacyReadoutMode lmode =
0391           legacy_ ? buffer->legacyReadoutMode() : sistrip::READOUT_MODE_LEGACY_INVALID;
0392 
0393       using namespace sistrip;
0394       if LIKELY (fedchannelunpacker::isZeroSuppressed(mode, legacy_, lmode)) {
0395         auto perStripAdder = StripByStripAdder(clusterizer, state, record);
0396         const auto isNonLite = fedchannelunpacker::isNonLiteZS(mode, legacy_, lmode);
0397         const uint8_t pCode = (isNonLite ? buffer->packetCode(legacy_, fedCh) : 0);
0398         auto st_ch = fedchannelunpacker::StatusCode::SUCCESS;
0399         if LIKELY (!hybridZeroSuppressed_) {
0400           st_ch = fedchannelunpacker::unpackZeroSuppressed(
0401               buffer->channel(fedCh), perStripAdder, ipair * 256, isNonLite, mode, legacy_, lmode, pCode);
0402         } else {
0403           const uint32_t id = conn->detId();
0404           edm::DetSet<SiStripDigi> unpDigis{id};
0405           unpDigis.reserve(256);
0406           st_ch = fedchannelunpacker::unpackZeroSuppressed(
0407               buffer->channel(fedCh), std::back_inserter(unpDigis), ipair * 256, isNonLite, mode, legacy_, lmode, pCode);
0408           if (fedchannelunpacker::StatusCode::SUCCESS == st_ch) {
0409             edm::DetSet<SiStripDigi> suppDigis{id};
0410             rawAlgos.suppressHybridData(unpDigis, suppDigis, ipair * 2);
0411             std::copy(std::begin(suppDigis), std::end(suppDigis), perStripAdder);
0412           }
0413         }
0414         if (fedchannelunpacker::StatusCode::SUCCESS != st_ch && edm::isDebugEnabled()) {
0415           edm::LogWarning(sistrip::mlRawToCluster_)
0416               << "Unordered clusters for channel " << fedCh << " on FED " << fedId << ": " << toString(st_ch);
0417           continue;
0418         }
0419       } else {
0420         auto st_ch = fedchannelunpacker::StatusCode::SUCCESS;
0421         if (fedchannelunpacker::isVirginRaw(mode, legacy_, lmode)) {
0422           std::vector<int16_t> digis;
0423           st_ch = fedchannelunpacker::unpackVirginRaw(
0424               buffer->channel(fedCh), ADC_back_inserter(digis), buffer->channel(fedCh).packetCode());
0425           if (fedchannelunpacker::StatusCode::SUCCESS == st_ch) {
0426             //process raw
0427             uint32_t id = conn->detId();
0428             edm::DetSet<SiStripDigi> zsdigis(id);
0429             //rawAlgos_->subtractorPed->subtract( id, ipair*256, digis);
0430             //rawAlgos_->subtractorCMN->subtract( id, digis);
0431             //rawAlgos_->suppressor->suppress( digis, zsdigis);
0432             uint16_t firstAPV = ipair * 2;
0433             rawAlgos.suppressVirginRawData(id, firstAPV, digis, zsdigis);
0434             for (const auto digi : zsdigis) {
0435               clusterizer.stripByStripAdd(state, digi.strip(), digi.adc(), record);
0436             }
0437           }
0438         } else if (fedchannelunpacker::isProcessedRaw(mode, legacy_, lmode)) {
0439           std::vector<int16_t> digis;
0440           st_ch = fedchannelunpacker::unpackProcessedRaw(buffer->channel(fedCh), ADC_back_inserter(digis));
0441           if (fedchannelunpacker::StatusCode::SUCCESS == st_ch) {
0442             //process raw
0443             uint32_t id = conn->detId();
0444             edm::DetSet<SiStripDigi> zsdigis(id);
0445             //rawAlgos_->subtractorCMN->subtract( id, digis);
0446             //rawAlgos_->suppressor->suppress( digis, zsdigis);
0447             uint16_t firstAPV = ipair * 2;
0448             rawAlgos.suppressProcessedRawData(id, firstAPV, digis, zsdigis);
0449             for (edm::DetSet<SiStripDigi>::const_iterator it = zsdigis.begin(); it != zsdigis.end(); it++) {
0450               clusterizer.stripByStripAdd(state, it->strip(), it->adc(), record);
0451             }
0452           }
0453         } else {
0454           edm::LogWarning(sistrip::mlRawToCluster_)
0455               << "[ClustersFromRawProducer::" << __func__ << "]"
0456               << " FEDRawData readout mode " << mode << " from FED id " << fedId << " not supported.";
0457         }
0458         if (fedchannelunpacker::StatusCode::SUCCESS != st_ch && edm::isDebugEnabled()) {
0459           edm::LogWarning(sistrip::mlRawToCluster_)
0460               << "[ClustersFromRawProducer::" << __func__ << "]" << toString(st_ch) << " from FED id " << fedId
0461               << " channel " << fedCh;
0462         }
0463       }
0464     }  // end loop over conn
0465 
0466     clusterizer.stripByStripEnd(state, record);
0467 
0468     incAct();
0469 
0470     if (record.full()) {
0471       edm::LogError(sistrip::mlRawToCluster_) << "too many Sistrip Clusters to fit space allocated for OnDemand for "
0472                                               << record.id() << ' ' << record.size();
0473       record.abort();
0474       incAbrt();
0475     }
0476 
0477     if (!record.empty())
0478       incNoZ();
0479 
0480     COUT << "filled " << record.size() << std::endl;
0481     for (auto const& cl : record)
0482       COUT << cl.firstStrip() << ',' << cl.amplitudes().size() << std::endl;
0483     incClus(record.size());
0484   } catch (edmNew::CapacityExaustedException const&) {
0485     edm::LogError(sistrip::mlRawToCluster_) << "too many Sistrip Clusters to fit space allocated for OnDemand";
0486   }
0487 }