Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:28:50

0001 #include "FWCore/Framework/interface/stream/EDProducer.h"
0002 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0003 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0004 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0005 #include "FWCore/Framework/interface/ConsumesCollector.h"
0006 #include "FWCore/Framework/interface/ProducesCollector.h"
0007 #include "FWCore/Utilities/interface/EDGetToken.h"
0008 #include "FWCore/Framework/interface/Event.h"
0009 #include "DataFormats/Common/interface/Handle.h"
0010 #include "FWCore/Utilities/interface/RunningAverage.h"
0011 
0012 #include "RecoTracker/TkTrackingRegions/interface/TrackingRegion.h"
0013 #include "TrackingTools/TransientTrackingRecHit/interface/SeedingLayerSetsHits.h"
0014 #include "RecoTracker/TkTrackingRegions/interface/TrackingRegionsSeedingLayerSets.h"
0015 #include "RecoTracker/TkHitPairs/interface/LayerHitMapCache.h"
0016 #include "RecoTracker/TkHitPairs/interface/HitPairGeneratorFromLayerPair.h"
0017 #include "RecoTracker/TkHitPairs/interface/IntermediateHitDoublets.h"
0018 #include "RecoTracker/TkHitPairs/interface/RegionsSeedingHitSets.h"
0019 
0020 #include <memory>
0021 #include <vector>
0022 
0023 namespace {
0024   class ImplBase;
0025 }
0026 
0027 class HitPairEDProducer : public edm::stream::EDProducer<> {
0028 public:
0029   HitPairEDProducer(const edm::ParameterSet& iConfig);
0030   ~HitPairEDProducer() override = default;
0031 
0032   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0033 
0034   void produce(edm::Event& iEvent, const edm::EventSetup& iSetup) override;
0035 
0036 private:
0037   edm::EDGetTokenT<bool> clusterCheckToken_;
0038 
0039   std::unique_ptr<::ImplBase> impl_;
0040 };
0041 
0042 namespace {
0043   class ImplBase {
0044   public:
0045     ImplBase(const edm::ParameterSet& iConfig, edm::ConsumesCollector iC);
0046     virtual ~ImplBase() = default;
0047 
0048     virtual void produces(edm::ProducesCollector) const = 0;
0049 
0050     virtual void produce(const bool clusterCheckOk, edm::Event& iEvent, const edm::EventSetup& iSetup) = 0;
0051 
0052   protected:
0053     edm::RunningAverage localRA_;
0054     const unsigned int maxElement_;
0055     const unsigned int maxElementTotal_;
0056     const bool putEmptyIfMaxElementReached_;
0057 
0058     HitPairGeneratorFromLayerPair generator_;
0059     std::vector<unsigned> layerPairBegins_;
0060   };
0061   ImplBase::ImplBase(const edm::ParameterSet& iConfig, edm::ConsumesCollector iC)
0062       : maxElement_(iConfig.getParameter<unsigned int>("maxElement")),
0063         maxElementTotal_(iConfig.getParameter<unsigned int>("maxElementTotal")),
0064         putEmptyIfMaxElementReached_(iConfig.getParameter<bool>("putEmptyIfMaxElementReached")),
0065         generator_(
0066             iC, 0, 1, nullptr, maxElement_),  // these indices are dummy, TODO: cleanup HitPairGeneratorFromLayerPair
0067         layerPairBegins_(iConfig.getParameter<std::vector<unsigned>>("layerPairs")) {
0068     if (layerPairBegins_.empty())
0069       throw cms::Exception("Configuration")
0070           << "HitPairEDProducer requires at least index for layer pairs (layerPairs parameter), none was given";
0071   }
0072 
0073   /////
0074   template <typename T_SeedingHitSets, typename T_IntermediateHitDoublets, typename T_RegionLayers>
0075   class Impl : public ImplBase {
0076   public:
0077     template <typename... Args>
0078     Impl(const edm::ParameterSet& iConfig, edm::ConsumesCollector iC, Args&&... args)
0079         : ImplBase(iConfig, iC), regionsLayers_(&layerPairBegins_, std::forward<Args>(args)..., iC) {}
0080     ~Impl() override = default;
0081 
0082     void produces(edm::ProducesCollector producesCollector) const override {
0083       T_SeedingHitSets::produces(producesCollector);
0084       T_IntermediateHitDoublets::produces(producesCollector);
0085     }
0086 
0087     void produce(const bool clusterCheckOk, edm::Event& iEvent, const edm::EventSetup& iSetup) override {
0088       auto regionsLayers = regionsLayers_.beginEvent(iEvent);
0089 
0090       auto seedingHitSetsProducer = T_SeedingHitSets(&localRA_);
0091       auto intermediateHitDoubletsProducer = T_IntermediateHitDoublets(regionsLayers.seedingLayerSetsHitsPtr());
0092 
0093       if (!clusterCheckOk) {
0094         seedingHitSetsProducer.putEmpty(iEvent);
0095         intermediateHitDoubletsProducer.putEmpty(iEvent);
0096         return;
0097       }
0098 
0099       seedingHitSetsProducer.reserve(regionsLayers.regionsSize());
0100       intermediateHitDoubletsProducer.reserve(regionsLayers.regionsSize());
0101 
0102       unsigned int nDoublets = 0;
0103 
0104       for (const auto& regionLayers : regionsLayers) {
0105         const TrackingRegion& region = regionLayers.region();
0106         auto hitCachePtr_filler_shs = seedingHitSetsProducer.beginRegion(&region, nullptr);
0107         auto hitCachePtr_filler_ihd =
0108             intermediateHitDoubletsProducer.beginRegion(&region, std::get<0>(hitCachePtr_filler_shs));
0109         auto hitCachePtr = std::get<0>(hitCachePtr_filler_ihd);
0110 
0111         for (SeedingLayerSetsHits::SeedingLayerSet layerSet : regionLayers.layerPairs()) {
0112           auto doubletsOpt = generator_.doublets(region, iEvent, iSetup, layerSet, *hitCachePtr);
0113           if (not doubletsOpt) {
0114             if (putEmptyIfMaxElementReached_) {
0115               putEmpty(iEvent, regionsLayers);
0116               return;
0117             } else {
0118               continue;
0119             }
0120           }
0121           auto& doublets = *doubletsOpt;
0122           LogTrace("HitPairEDProducer") << " created " << doublets.size() << " doublets for layers "
0123                                         << layerSet[0].index() << "," << layerSet[1].index();
0124           if (doublets.empty())
0125             continue;  // don't bother if no pairs from these layers
0126           nDoublets += doublets.size();
0127           if (nDoublets >= maxElementTotal_) {
0128             edm::LogError("TooManyPairs") << "number of total pairs exceed maximum, no pairs produced";
0129             putEmpty(iEvent, regionsLayers);
0130             return;
0131           }
0132           seedingHitSetsProducer.fill(std::get<1>(hitCachePtr_filler_shs), doublets);
0133           intermediateHitDoubletsProducer.fill(std::get<1>(hitCachePtr_filler_ihd), layerSet, std::move(doublets));
0134         }
0135       }
0136 
0137       seedingHitSetsProducer.put(iEvent);
0138       intermediateHitDoubletsProducer.put(iEvent);
0139     }
0140 
0141   private:
0142     template <typename T>
0143     void putEmpty(edm::Event& iEvent, T& regionsLayers) {
0144       auto seedingHitSetsProducerDummy = T_SeedingHitSets(&localRA_);
0145       auto intermediateHitDoubletsProducerDummy = T_IntermediateHitDoublets(regionsLayers.seedingLayerSetsHitsPtr());
0146       seedingHitSetsProducerDummy.putEmpty(iEvent);
0147       intermediateHitDoubletsProducerDummy.putEmpty(iEvent);
0148     }
0149 
0150     T_RegionLayers regionsLayers_;
0151   };
0152 
0153   /////
0154   class DoNothing {
0155   public:
0156     DoNothing(const SeedingLayerSetsHits*) {}
0157     DoNothing(edm::RunningAverage*) {}
0158 
0159     static void produces(edm::ProducesCollector){};
0160 
0161     void reserve(size_t) {}
0162 
0163     auto beginRegion(const TrackingRegion*, LayerHitMapCache* ptr) { return std::make_tuple(ptr, 0); }
0164 
0165     void fill(int, const HitDoublets&) {}
0166     void fill(int, const SeedingLayerSetsHits::SeedingLayerSet&, HitDoublets&&) {}
0167 
0168     void put(edm::Event&) {}
0169     void putEmpty(edm::Event&) {}
0170   };
0171 
0172   /////
0173   class ImplSeedingHitSets {
0174   public:
0175     ImplSeedingHitSets(edm::RunningAverage* localRA)
0176         : seedingHitSets_(std::make_unique<RegionsSeedingHitSets>()), localRA_(localRA) {}
0177 
0178     static void produces(edm::ProducesCollector producesCollector) {
0179       producesCollector.produces<RegionsSeedingHitSets>();
0180     }
0181 
0182     void reserve(size_t regionsSize) { seedingHitSets_->reserve(regionsSize, localRA_->upper()); }
0183 
0184     auto beginRegion(const TrackingRegion* region, LayerHitMapCache*) {
0185       hitCacheTmp_.clear();
0186       return std::make_tuple(&hitCacheTmp_, seedingHitSets_->beginRegion(region));
0187     }
0188 
0189     void fill(RegionsSeedingHitSets::RegionFiller& filler, const HitDoublets& doublets) {
0190       for (size_t i = 0, size = doublets.size(); i < size; ++i) {
0191         filler.emplace_back(doublets.hit(i, HitDoublets::inner), doublets.hit(i, HitDoublets::outer));
0192       }
0193     }
0194 
0195     void put(edm::Event& iEvent) {
0196       seedingHitSets_->shrink_to_fit();
0197       localRA_->update(seedingHitSets_->size());
0198       putEmpty(iEvent);
0199     }
0200 
0201     void putEmpty(edm::Event& iEvent) { iEvent.put(std::move(seedingHitSets_)); }
0202 
0203   private:
0204     std::unique_ptr<RegionsSeedingHitSets> seedingHitSets_;
0205     edm::RunningAverage* localRA_;
0206     LayerHitMapCache hitCacheTmp_;  // used if !produceIntermediateHitDoublets
0207   };
0208 
0209   /////
0210   class ImplIntermediateHitDoublets {
0211   public:
0212     ImplIntermediateHitDoublets(const SeedingLayerSetsHits* layers)
0213         : intermediateHitDoublets_(std::make_unique<IntermediateHitDoublets>(layers)), layers_(layers) {}
0214 
0215     static void produces(edm::ProducesCollector producesCollector) {
0216       producesCollector.produces<IntermediateHitDoublets>();
0217     }
0218 
0219     void reserve(size_t regionsSize) { intermediateHitDoublets_->reserve(regionsSize, layers_->size()); }
0220 
0221     auto beginRegion(const TrackingRegion* region, LayerHitMapCache*) {
0222       auto filler = intermediateHitDoublets_->beginRegion(region);
0223       return std::make_tuple(&(filler.layerHitMapCache()), filler);
0224     }
0225 
0226     void fill(IntermediateHitDoublets::RegionFiller& filler,
0227               const SeedingLayerSetsHits::SeedingLayerSet& layerSet,
0228               HitDoublets&& doublets) {
0229       filler.addDoublets(layerSet, std::move(doublets));
0230     }
0231 
0232     void put(edm::Event& iEvent) {
0233       intermediateHitDoublets_->shrink_to_fit();
0234       putEmpty(iEvent);
0235     }
0236 
0237     void putEmpty(edm::Event& iEvent) { iEvent.put(std::move(intermediateHitDoublets_)); }
0238 
0239   private:
0240     std::unique_ptr<IntermediateHitDoublets> intermediateHitDoublets_;
0241     const SeedingLayerSetsHits* layers_;
0242   };
0243 
0244   /////
0245   // For the usual case that TrackingRegions and seeding layers are read separately
0246   class RegionsLayersSeparate {
0247   public:
0248     class RegionLayers {
0249     public:
0250       RegionLayers(const TrackingRegion* region, const std::vector<SeedingLayerSetsHits::SeedingLayerSet>* layerPairs)
0251           : region_(region), layerPairs_(layerPairs) {}
0252 
0253       const TrackingRegion& region() const { return *region_; }
0254       const std::vector<SeedingLayerSetsHits::SeedingLayerSet>& layerPairs() const { return *layerPairs_; }
0255 
0256     private:
0257       const TrackingRegion* region_;
0258       const std::vector<SeedingLayerSetsHits::SeedingLayerSet>* layerPairs_;
0259     };
0260 
0261     class EventTmp {
0262     public:
0263       class const_iterator {
0264       public:
0265         using internal_iterator_type = std::vector<std::unique_ptr<TrackingRegion>>::const_iterator;
0266         using value_type = RegionLayers;
0267         using difference_type = internal_iterator_type::difference_type;
0268 
0269         const_iterator(internal_iterator_type iter,
0270                        const std::vector<SeedingLayerSetsHits::SeedingLayerSet>* layerPairs)
0271             : iter_(iter), layerPairs_(layerPairs) {}
0272 
0273         value_type operator*() const { return value_type(&(**iter_), layerPairs_); }
0274 
0275         const_iterator& operator++() {
0276           ++iter_;
0277           return *this;
0278         }
0279         const_iterator operator++(int) {
0280           const_iterator clone(*this);
0281           ++(*this);
0282           return clone;
0283         }
0284 
0285         bool operator==(const const_iterator& other) const { return iter_ == other.iter_; }
0286         bool operator!=(const const_iterator& other) const { return !operator==(other); }
0287 
0288       private:
0289         internal_iterator_type iter_;
0290         const std::vector<SeedingLayerSetsHits::SeedingLayerSet>* layerPairs_;
0291       };
0292 
0293       EventTmp(const SeedingLayerSetsHits* seedingLayerSetsHits,
0294                const std::vector<std::unique_ptr<TrackingRegion>>* regions,
0295                const std::vector<unsigned>& layerPairBegins)
0296           : seedingLayerSetsHits_(seedingLayerSetsHits), regions_(regions) {
0297         // construct the pairs from the sets
0298         if (seedingLayerSetsHits_->numberOfLayersInSet() > 2) {
0299           for (const auto& layerSet : *seedingLayerSetsHits_) {
0300             for (const auto pairBeginIndex : layerPairBegins) {
0301               if (pairBeginIndex + 1 >= seedingLayerSetsHits->numberOfLayersInSet()) {
0302                 throw cms::Exception("LogicError")
0303                     << "Layer pair index " << pairBeginIndex
0304                     << " is out of bounds, input SeedingLayerSetsHits has only "
0305                     << seedingLayerSetsHits->numberOfLayersInSet()
0306                     << " layers per set, and the index+1 must be < than the number of layers in set";
0307               }
0308 
0309               // Take only the requested pair of the set
0310               SeedingLayerSetsHits::SeedingLayerSet pairCandidate = layerSet.slice(pairBeginIndex, pairBeginIndex + 1);
0311 
0312               // it would be trivial to use 128-bit bitfield for O(1) check
0313               // if a layer pair has been inserted, but let's test first how
0314               // a "straightforward" solution works
0315               auto found = std::find_if(
0316                   layerPairs.begin(), layerPairs.end(), [&](const SeedingLayerSetsHits::SeedingLayerSet& pair) {
0317                     return pair[0].index() == pairCandidate[0].index() && pair[1].index() == pairCandidate[1].index();
0318                   });
0319               if (found != layerPairs.end())
0320                 continue;
0321 
0322               layerPairs.push_back(pairCandidate);
0323             }
0324           }
0325         } else {
0326           if (layerPairBegins.size() != 1) {
0327             throw cms::Exception("LogicError")
0328                 << "With pairs of input layers, it doesn't make sense to specify more than one input layer pair, got "
0329                 << layerPairBegins.size();
0330           }
0331           if (layerPairBegins[0] != 0) {
0332             throw cms::Exception("LogicError")
0333                 << "With pairs of input layers, it doesn't make sense to specify other input layer pair than 0; got "
0334                 << layerPairBegins[0];
0335           }
0336 
0337           layerPairs.reserve(seedingLayerSetsHits->size());
0338           for (const auto& set : *seedingLayerSetsHits)
0339             layerPairs.push_back(set);
0340         }
0341       }
0342 
0343       const SeedingLayerSetsHits* seedingLayerSetsHitsPtr() const { return seedingLayerSetsHits_; }
0344 
0345       size_t regionsSize() const { return regions_->size(); }
0346 
0347       const_iterator begin() const { return const_iterator(regions_->begin(), &layerPairs); }
0348       const_iterator cbegin() const { return begin(); }
0349       const_iterator end() const { return const_iterator(regions_->end(), &layerPairs); }
0350       const_iterator cend() const { return end(); }
0351 
0352     private:
0353       const SeedingLayerSetsHits* seedingLayerSetsHits_;
0354       const std::vector<std::unique_ptr<TrackingRegion>>* regions_;
0355       std::vector<SeedingLayerSetsHits::SeedingLayerSet> layerPairs;
0356     };
0357 
0358     RegionsLayersSeparate(const std::vector<unsigned>* layerPairBegins,
0359                           const edm::InputTag& seedingLayerTag,
0360                           const edm::InputTag& regionTag,
0361                           edm::ConsumesCollector iC)
0362         : layerPairBegins_(layerPairBegins),
0363           seedingLayerToken_(iC.consumes<SeedingLayerSetsHits>(seedingLayerTag)),
0364           regionToken_(iC.consumes(regionTag)) {}
0365 
0366     EventTmp beginEvent(const edm::Event& iEvent) const {
0367       edm::Handle<SeedingLayerSetsHits> hlayers;
0368       iEvent.getByToken(seedingLayerToken_, hlayers);
0369       const auto* layers = hlayers.product();
0370       if (layers->numberOfLayersInSet() < 2)
0371         throw cms::Exception("LogicError")
0372             << "HitPairEDProducer expects SeedingLayerSetsHits::numberOfLayersInSet() to be >= 2, got "
0373             << layers->numberOfLayersInSet()
0374             << ". This is likely caused by a configuration error of this module, or SeedingLayersEDProducer.";
0375       auto const& regions = iEvent.get(regionToken_);
0376       return EventTmp(layers, &regions, *layerPairBegins_);
0377     }
0378 
0379   private:
0380     const std::vector<unsigned>* layerPairBegins_;
0381     edm::EDGetTokenT<SeedingLayerSetsHits> seedingLayerToken_;
0382     edm::EDGetTokenT<std::vector<std::unique_ptr<TrackingRegion>>> regionToken_;
0383   };
0384 
0385   /////
0386   // For the case of automated pixel inactive region recovery where
0387   // TrackingRegions and seeding layers become together
0388   class RegionsLayersTogether {
0389   public:
0390     class EventTmp {
0391     public:
0392       using const_iterator = TrackingRegionsSeedingLayerSets::const_iterator;
0393 
0394       explicit EventTmp(const TrackingRegionsSeedingLayerSets* regionsLayers) : regionsLayers_(regionsLayers) {
0395         if (regionsLayers->seedingLayerSetsHits().numberOfLayersInSet() != 2) {
0396           throw cms::Exception("LogicError")
0397               << "With trackingRegionsSeedingLayers input, the seeding layer sets may only contain layer pairs, now "
0398                  "got sets with "
0399               << regionsLayers->seedingLayerSetsHits().numberOfLayersInSet() << " layers";
0400         }
0401       }
0402 
0403       const SeedingLayerSetsHits* seedingLayerSetsHitsPtr() const { return &(regionsLayers_->seedingLayerSetsHits()); }
0404 
0405       size_t regionsSize() const { return regionsLayers_->regionsSize(); }
0406 
0407       const_iterator begin() const { return regionsLayers_->begin(); }
0408       const_iterator cbegin() const { return begin(); }
0409       const_iterator end() const { return regionsLayers_->end(); }
0410       const_iterator cend() const { return end(); }
0411 
0412     private:
0413       const TrackingRegionsSeedingLayerSets* regionsLayers_;
0414     };
0415 
0416     RegionsLayersTogether(const std::vector<unsigned>* layerPairBegins,
0417                           const edm::InputTag& regionLayerTag,
0418                           edm::ConsumesCollector iC)
0419         : regionLayerToken_(iC.consumes<TrackingRegionsSeedingLayerSets>(regionLayerTag)) {
0420       if (layerPairBegins->size() != 1) {
0421         throw cms::Exception("LogicError") << "With trackingRegionsSeedingLayers mode, it doesn't make sense to "
0422                                               "specify more than one input layer pair, got "
0423                                            << layerPairBegins->size();
0424       }
0425       if ((*layerPairBegins)[0] != 0) {
0426         throw cms::Exception("LogicError") << "With trackingRegionsSeedingLayers mode, it doesn't make sense to "
0427                                               "specify other input layer pair than 0; got "
0428                                            << (*layerPairBegins)[0];
0429       }
0430     }
0431 
0432     EventTmp beginEvent(const edm::Event& iEvent) const {
0433       edm::Handle<TrackingRegionsSeedingLayerSets> hregions;
0434       iEvent.getByToken(regionLayerToken_, hregions);
0435       return EventTmp(hregions.product());
0436     }
0437 
0438   private:
0439     edm::EDGetTokenT<TrackingRegionsSeedingLayerSets> regionLayerToken_;
0440   };
0441 }  // namespace
0442 
0443 HitPairEDProducer::HitPairEDProducer(const edm::ParameterSet& iConfig) {
0444   auto layersTag = iConfig.getParameter<edm::InputTag>("seedingLayers");
0445   auto regionTag = iConfig.getParameter<edm::InputTag>("trackingRegions");
0446   auto regionLayerTag = iConfig.getParameter<edm::InputTag>("trackingRegionsSeedingLayers");
0447   const bool useRegionLayers = !regionLayerTag.label().empty();
0448   if (useRegionLayers) {
0449     if (!regionTag.label().empty()) {
0450       throw cms::Exception("Configuration")
0451           << "HitPairEDProducer requires either trackingRegions or trackingRegionsSeedingLayers to be set, now both "
0452              "are set to non-empty value. Set the unneeded parameter to empty value.";
0453     }
0454     if (!layersTag.label().empty()) {
0455       throw cms::Exception("Configuration")
0456           << "With non-empty trackingRegionsSeedingLayers, please set also seedingLayers to empty value to reduce "
0457              "confusion, because the parameter is not used";
0458     }
0459   }
0460   if (regionTag.label().empty() && regionLayerTag.label().empty()) {
0461     throw cms::Exception("Configuration")
0462         << "HitPairEDProducer requires either trackingRegions or trackingRegionsSeedingLayers to be set, now both are "
0463            "set to empty value. Set the needed parameter to a non-empty value.";
0464   }
0465 
0466   const bool produceSeedingHitSets = iConfig.getParameter<bool>("produceSeedingHitSets");
0467   const bool produceIntermediateHitDoublets = iConfig.getParameter<bool>("produceIntermediateHitDoublets");
0468 
0469   if (produceSeedingHitSets && produceIntermediateHitDoublets) {
0470     if (useRegionLayers)
0471       throw cms::Exception("Configuration")
0472           << "Mode 'trackingRegionsSeedingLayers' makes sense only with 'produceSeedingHitsSets', now also "
0473              "'produceIntermediateHitDoublets is active";
0474     impl_ = std::make_unique<::Impl<::ImplSeedingHitSets, ::ImplIntermediateHitDoublets, ::RegionsLayersSeparate>>(
0475         iConfig, consumesCollector(), layersTag, regionTag);
0476   } else if (produceSeedingHitSets) {
0477     if (useRegionLayers) {
0478       impl_ = std::make_unique<::Impl<::ImplSeedingHitSets, ::DoNothing, ::RegionsLayersTogether>>(
0479           iConfig, consumesCollector(), regionLayerTag);
0480     } else {
0481       impl_ = std::make_unique<::Impl<::ImplSeedingHitSets, ::DoNothing, ::RegionsLayersSeparate>>(
0482           iConfig, consumesCollector(), layersTag, regionTag);
0483     }
0484   } else if (produceIntermediateHitDoublets) {
0485     if (useRegionLayers)
0486       throw cms::Exception("Configuration")
0487           << "Mode 'trackingRegionsSeedingLayers' makes sense only with 'produceSeedingHitsSets', now "
0488              "'produceIntermediateHitDoublets is active instead";
0489     impl_ = std::make_unique<::Impl<::DoNothing, ::ImplIntermediateHitDoublets, ::RegionsLayersSeparate>>(
0490         iConfig, consumesCollector(), layersTag, regionTag);
0491   } else
0492     throw cms::Exception("Configuration")
0493         << "HitPairEDProducer requires either produceIntermediateHitDoublets or produceSeedingHitSets to be True. If "
0494            "neither are needed, just remove this module from your sequence/path as it doesn't do anything useful";
0495 
0496   auto clusterCheckTag = iConfig.getParameter<edm::InputTag>("clusterCheck");
0497   if (!clusterCheckTag.label().empty())
0498     clusterCheckToken_ = consumes<bool>(clusterCheckTag);
0499 
0500   impl_->produces(producesCollector());
0501 }
0502 
0503 void HitPairEDProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0504   edm::ParameterSetDescription desc;
0505 
0506   desc.add<edm::InputTag>("seedingLayers", edm::InputTag("seedingLayersEDProducer"))
0507       ->setComment("Set this empty if 'trackingRegionsSeedingLayers' is non-empty");
0508   desc.add<edm::InputTag>("trackingRegions", edm::InputTag("globalTrackingRegionFromBeamSpot"))
0509       ->setComment(
0510           "Input tracking regions when using all layer sets in 'seedingLayers' (conflicts with "
0511           "'trackingRegionsSeedingLayers', set this empty to use the other)");
0512   desc.add<edm::InputTag>("trackingRegionsSeedingLayers", edm::InputTag(""))
0513       ->setComment(
0514           "Input tracking regions and corresponding layer sets in case of dynamically limiting the seeding layers "
0515           "(conflicts with 'trackingRegions', set this empty to use the other; if using this set also 'seedingLayers' "
0516           "to empty)");
0517   desc.add<edm::InputTag>("clusterCheck", edm::InputTag("trackerClusterCheck"));
0518   desc.add<bool>("produceSeedingHitSets", false);
0519   desc.add<bool>("produceIntermediateHitDoublets", false);
0520   desc.add<unsigned int>("maxElement", 1000000);
0521   desc.add<unsigned int>("maxElementTotal", 50000000);
0522   desc.add<bool>("putEmptyIfMaxElementReached", false)
0523       ->setComment(
0524           "If set to true (default is 'false'), abort processing and put empty data products also if any layer pair "
0525           "yields at least maxElement doublets, in addition to aborting processing if the sum of doublets from all "
0526           "layer pairs reaches maxElementTotal.");
0527   desc.add<std::vector<unsigned>>("layerPairs", std::vector<unsigned>{0})
0528       ->setComment("Indices to the pairs of consecutive layers, i.e. 0 means (0,1), 1 (1,2) etc.");
0529 
0530   descriptions.add("hitPairEDProducerDefault", desc);
0531 }
0532 
0533 void HitPairEDProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0534   bool clusterCheckOk = true;
0535   if (!clusterCheckToken_.isUninitialized()) {
0536     edm::Handle<bool> hclusterCheck;
0537     iEvent.getByToken(clusterCheckToken_, hclusterCheck);
0538     clusterCheckOk = *hclusterCheck;
0539   }
0540 
0541   impl_->produce(clusterCheckOk, iEvent, iSetup);
0542 }
0543 
0544 #include "FWCore/PluginManager/interface/ModuleDef.h"
0545 #include "FWCore/Framework/interface/MakerMacros.h"
0546 DEFINE_FWK_MODULE(HitPairEDProducer);