CMS 3D CMS Logo

HitPairEDProducer.cc
Go to the documentation of this file.
11 
20 
21 namespace {
22  class ImplBase;
23 }
24 
26 public:
27  HitPairEDProducer(const edm::ParameterSet& iConfig);
28  ~HitPairEDProducer() override = default;
29 
30  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
31 
32  void produce(edm::Event& iEvent, const edm::EventSetup& iSetup) override;
33 
34 private:
36 
37  std::unique_ptr<::ImplBase> impl_;
38 };
39 
40 namespace {
41  class ImplBase {
42  public:
43  ImplBase(const edm::ParameterSet& iConfig, edm::ConsumesCollector iC);
44  virtual ~ImplBase() = default;
45 
46  virtual void produces(edm::ProducesCollector) const = 0;
47 
48  virtual void produce(const bool clusterCheckOk, edm::Event& iEvent, const edm::EventSetup& iSetup) = 0;
49 
50  protected:
51  edm::RunningAverage localRA_;
52  const unsigned int maxElement_;
53  const unsigned int maxElementTotal_;
54 
56  std::vector<unsigned> layerPairBegins_;
57  };
58  ImplBase::ImplBase(const edm::ParameterSet& iConfig, edm::ConsumesCollector iC)
59  : maxElement_(iConfig.getParameter<unsigned int>("maxElement")),
60  maxElementTotal_(iConfig.getParameter<unsigned int>("maxElementTotal")),
61  generator_(
62  iC, 0, 1, nullptr, maxElement_), // these indices are dummy, TODO: cleanup HitPairGeneratorFromLayerPair
63  layerPairBegins_(iConfig.getParameter<std::vector<unsigned>>("layerPairs")) {
64  if (layerPairBegins_.empty())
65  throw cms::Exception("Configuration")
66  << "HitPairEDProducer requires at least index for layer pairs (layerPairs parameter), none was given";
67  }
68 
70  template <typename T_SeedingHitSets, typename T_IntermediateHitDoublets, typename T_RegionLayers>
71  class Impl : public ImplBase {
72  public:
73  template <typename... Args>
74  Impl(const edm::ParameterSet& iConfig, edm::ConsumesCollector iC, Args&&... args)
75  : ImplBase(iConfig, iC), regionsLayers_(&layerPairBegins_, std::forward<Args>(args)..., iC) {}
76  ~Impl() override = default;
77 
78  void produces(edm::ProducesCollector producesCollector) const override {
79  T_SeedingHitSets::produces(producesCollector);
80  T_IntermediateHitDoublets::produces(producesCollector);
81  }
82 
83  void produce(const bool clusterCheckOk, edm::Event& iEvent, const edm::EventSetup& iSetup) override {
84  auto regionsLayers = regionsLayers_.beginEvent(iEvent);
85 
86  auto seedingHitSetsProducer = T_SeedingHitSets(&localRA_);
87  auto intermediateHitDoubletsProducer = T_IntermediateHitDoublets(regionsLayers.seedingLayerSetsHitsPtr());
88 
89  if (!clusterCheckOk) {
90  seedingHitSetsProducer.putEmpty(iEvent);
91  intermediateHitDoubletsProducer.putEmpty(iEvent);
92  return;
93  }
94 
95  seedingHitSetsProducer.reserve(regionsLayers.regionsSize());
96  intermediateHitDoubletsProducer.reserve(regionsLayers.regionsSize());
97 
98  unsigned int nDoublets = 0;
99 
100  for (const auto& regionLayers : regionsLayers) {
101  const TrackingRegion& region = regionLayers.region();
102  auto hitCachePtr_filler_shs = seedingHitSetsProducer.beginRegion(&region, nullptr);
103  auto hitCachePtr_filler_ihd =
104  intermediateHitDoubletsProducer.beginRegion(&region, std::get<0>(hitCachePtr_filler_shs));
105  auto hitCachePtr = std::get<0>(hitCachePtr_filler_ihd);
106 
107  for (SeedingLayerSetsHits::SeedingLayerSet layerSet : regionLayers.layerPairs()) {
108  auto doublets = generator_.doublets(region, iEvent, iSetup, layerSet, *hitCachePtr);
109  LogTrace("HitPairEDProducer") << " created " << doublets.size() << " doublets for layers "
110  << layerSet[0].index() << "," << layerSet[1].index();
111  if (doublets.empty())
112  continue; // don't bother if no pairs from these layers
113  nDoublets += doublets.size();
114  if (nDoublets >= maxElementTotal_) {
115  edm::LogError("TooManyPairs") << "number of total pairs exceed maximum, no pairs produced";
116  auto seedingHitSetsProducerDummy = T_SeedingHitSets(&localRA_);
117  auto intermediateHitDoubletsProducerDummy =
118  T_IntermediateHitDoublets(regionsLayers.seedingLayerSetsHitsPtr());
119  seedingHitSetsProducerDummy.putEmpty(iEvent);
120  intermediateHitDoubletsProducerDummy.putEmpty(iEvent);
121  return;
122  }
123  seedingHitSetsProducer.fill(std::get<1>(hitCachePtr_filler_shs), doublets);
124  intermediateHitDoubletsProducer.fill(std::get<1>(hitCachePtr_filler_ihd), layerSet, std::move(doublets));
125  }
126  }
127 
128  seedingHitSetsProducer.put(iEvent);
129  intermediateHitDoubletsProducer.put(iEvent);
130  }
131 
132  private:
133  T_RegionLayers regionsLayers_;
134  };
135 
137  class DoNothing {
138  public:
139  DoNothing(const SeedingLayerSetsHits*) {}
140  DoNothing(edm::RunningAverage*) {}
141 
142  static void produces(edm::ProducesCollector){};
143 
144  void reserve(size_t) {}
145 
146  auto beginRegion(const TrackingRegion*, LayerHitMapCache* ptr) { return std::make_tuple(ptr, 0); }
147 
148  void fill(int, const HitDoublets&) {}
150 
151  void put(edm::Event&) {}
152  void putEmpty(edm::Event&) {}
153  };
154 
156  class ImplSeedingHitSets {
157  public:
158  ImplSeedingHitSets(edm::RunningAverage* localRA)
159  : seedingHitSets_(std::make_unique<RegionsSeedingHitSets>()), localRA_(localRA) {}
160 
161  static void produces(edm::ProducesCollector producesCollector) {
162  producesCollector.produces<RegionsSeedingHitSets>();
163  }
164 
165  void reserve(size_t regionsSize) { seedingHitSets_->reserve(regionsSize, localRA_->upper()); }
166 
167  auto beginRegion(const TrackingRegion* region, LayerHitMapCache*) {
168  hitCacheTmp_.clear();
169  return std::make_tuple(&hitCacheTmp_, seedingHitSets_->beginRegion(region));
170  }
171 
173  for (size_t i = 0, size = doublets.size(); i < size; ++i) {
174  filler.emplace_back(doublets.hit(i, HitDoublets::inner), doublets.hit(i, HitDoublets::outer));
175  }
176  }
177 
178  void put(edm::Event& iEvent) {
179  seedingHitSets_->shrink_to_fit();
180  localRA_->update(seedingHitSets_->size());
181  putEmpty(iEvent);
182  }
183 
184  void putEmpty(edm::Event& iEvent) { iEvent.put(std::move(seedingHitSets_)); }
185 
186  private:
187  std::unique_ptr<RegionsSeedingHitSets> seedingHitSets_;
188  edm::RunningAverage* localRA_;
189  LayerHitMapCache hitCacheTmp_; // used if !produceIntermediateHitDoublets
190  };
191 
193  class ImplIntermediateHitDoublets {
194  public:
195  ImplIntermediateHitDoublets(const SeedingLayerSetsHits* layers)
196  : intermediateHitDoublets_(std::make_unique<IntermediateHitDoublets>(layers)), layers_(layers) {}
197 
198  static void produces(edm::ProducesCollector producesCollector) {
199  producesCollector.produces<IntermediateHitDoublets>();
200  }
201 
202  void reserve(size_t regionsSize) { intermediateHitDoublets_->reserve(regionsSize, layers_->size()); }
203 
204  auto beginRegion(const TrackingRegion* region, LayerHitMapCache*) {
205  auto filler = intermediateHitDoublets_->beginRegion(region);
206  return std::make_tuple(&(filler.layerHitMapCache()), filler);
207  }
208 
211  HitDoublets&& doublets) {
212  filler.addDoublets(layerSet, std::move(doublets));
213  }
214 
215  void put(edm::Event& iEvent) {
216  intermediateHitDoublets_->shrink_to_fit();
217  putEmpty(iEvent);
218  }
219 
220  void putEmpty(edm::Event& iEvent) { iEvent.put(std::move(intermediateHitDoublets_)); }
221 
222  private:
223  std::unique_ptr<IntermediateHitDoublets> intermediateHitDoublets_;
224  const SeedingLayerSetsHits* layers_;
225  };
226 
228  // For the usual case that TrackingRegions and seeding layers are read separately
229  class RegionsLayersSeparate {
230  public:
231  class RegionLayers {
232  public:
233  RegionLayers(const TrackingRegion* region, const std::vector<SeedingLayerSetsHits::SeedingLayerSet>* layerPairs)
234  : region_(region), layerPairs_(layerPairs) {}
235 
236  const TrackingRegion& region() const { return *region_; }
237  const std::vector<SeedingLayerSetsHits::SeedingLayerSet>& layerPairs() const { return *layerPairs_; }
238 
239  private:
240  const TrackingRegion* region_;
241  const std::vector<SeedingLayerSetsHits::SeedingLayerSet>* layerPairs_;
242  };
243 
244  class EventTmp {
245  public:
246  class const_iterator {
247  public:
248  using internal_iterator_type = edm::OwnVector<TrackingRegion>::const_iterator;
249  using value_type = RegionLayers;
250  using difference_type = internal_iterator_type::difference_type;
251 
252  const_iterator(internal_iterator_type iter,
253  const std::vector<SeedingLayerSetsHits::SeedingLayerSet>* layerPairs)
254  : iter_(iter), layerPairs_(layerPairs) {}
255 
256  value_type operator*() const { return value_type(&(*iter_), layerPairs_); }
257 
258  const_iterator& operator++() {
259  ++iter_;
260  return *this;
261  }
262  const_iterator operator++(int) {
263  const_iterator clone(*this);
264  ++(*this);
265  return clone;
266  }
267 
268  bool operator==(const const_iterator& other) const { return iter_ == other.iter_; }
269  bool operator!=(const const_iterator& other) const { return !operator==(other); }
270 
271  private:
272  internal_iterator_type iter_;
273  const std::vector<SeedingLayerSetsHits::SeedingLayerSet>* layerPairs_;
274  };
275 
276  EventTmp(const SeedingLayerSetsHits* seedingLayerSetsHits,
278  const std::vector<unsigned>& layerPairBegins)
279  : seedingLayerSetsHits_(seedingLayerSetsHits), regions_(regions) {
280  // construct the pairs from the sets
281  if (seedingLayerSetsHits_->numberOfLayersInSet() > 2) {
282  for (const auto& layerSet : *seedingLayerSetsHits_) {
283  for (const auto pairBeginIndex : layerPairBegins) {
284  if (pairBeginIndex + 1 >= seedingLayerSetsHits->numberOfLayersInSet()) {
285  throw cms::Exception("LogicError")
286  << "Layer pair index " << pairBeginIndex
287  << " is out of bounds, input SeedingLayerSetsHits has only "
288  << seedingLayerSetsHits->numberOfLayersInSet()
289  << " layers per set, and the index+1 must be < than the number of layers in set";
290  }
291 
292  // Take only the requested pair of the set
293  SeedingLayerSetsHits::SeedingLayerSet pairCandidate = layerSet.slice(pairBeginIndex, pairBeginIndex + 1);
294 
295  // it would be trivial to use 128-bit bitfield for O(1) check
296  // if a layer pair has been inserted, but let's test first how
297  // a "straightforward" solution works
298  auto found = std::find_if(
299  layerPairs.begin(), layerPairs.end(), [&](const SeedingLayerSetsHits::SeedingLayerSet& pair) {
300  return pair[0].index() == pairCandidate[0].index() && pair[1].index() == pairCandidate[1].index();
301  });
302  if (found != layerPairs.end())
303  continue;
304 
305  layerPairs.push_back(pairCandidate);
306  }
307  }
308  } else {
309  if (layerPairBegins.size() != 1) {
310  throw cms::Exception("LogicError")
311  << "With pairs of input layers, it doesn't make sense to specify more than one input layer pair, got "
312  << layerPairBegins.size();
313  }
314  if (layerPairBegins[0] != 0) {
315  throw cms::Exception("LogicError")
316  << "With pairs of input layers, it doesn't make sense to specify other input layer pair than 0; got "
317  << layerPairBegins[0];
318  }
319 
320  layerPairs.reserve(seedingLayerSetsHits->size());
321  for (const auto& set : *seedingLayerSetsHits)
322  layerPairs.push_back(set);
323  }
324  }
325 
326  const SeedingLayerSetsHits* seedingLayerSetsHitsPtr() const { return seedingLayerSetsHits_; }
327 
328  size_t regionsSize() const { return regions_->size(); }
329 
330  const_iterator begin() const { return const_iterator(regions_->begin(), &layerPairs); }
331  const_iterator cbegin() const { return begin(); }
332  const_iterator end() const { return const_iterator(regions_->end(), &layerPairs); }
333  const_iterator cend() const { return end(); }
334 
335  private:
336  const SeedingLayerSetsHits* seedingLayerSetsHits_;
337  const edm::OwnVector<TrackingRegion>* regions_;
338  std::vector<SeedingLayerSetsHits::SeedingLayerSet> layerPairs;
339  };
340 
341  RegionsLayersSeparate(const std::vector<unsigned>* layerPairBegins,
342  const edm::InputTag& seedingLayerTag,
343  const edm::InputTag& regionTag,
345  : layerPairBegins_(layerPairBegins),
346  seedingLayerToken_(iC.consumes<SeedingLayerSetsHits>(seedingLayerTag)),
347  regionToken_(iC.consumes<edm::OwnVector<TrackingRegion>>(regionTag)) {}
348 
349  EventTmp beginEvent(const edm::Event& iEvent) const {
351  iEvent.getByToken(seedingLayerToken_, hlayers);
352  const auto* layers = hlayers.product();
353  if (layers->numberOfLayersInSet() < 2)
354  throw cms::Exception("LogicError")
355  << "HitPairEDProducer expects SeedingLayerSetsHits::numberOfLayersInSet() to be >= 2, got "
356  << layers->numberOfLayersInSet()
357  << ". This is likely caused by a configuration error of this module, or SeedingLayersEDProducer.";
359  iEvent.getByToken(regionToken_, hregions);
360 
361  return EventTmp(layers, hregions.product(), *layerPairBegins_);
362  }
363 
364  private:
365  const std::vector<unsigned>* layerPairBegins_;
366  edm::EDGetTokenT<SeedingLayerSetsHits> seedingLayerToken_;
368  };
369 
371  // For the case of automated pixel inactive region recovery where
372  // TrackingRegions and seeding layers become together
373  class RegionsLayersTogether {
374  public:
375  class EventTmp {
376  public:
378 
379  explicit EventTmp(const TrackingRegionsSeedingLayerSets* regionsLayers) : regionsLayers_(regionsLayers) {
380  if (regionsLayers->seedingLayerSetsHits().numberOfLayersInSet() != 2) {
381  throw cms::Exception("LogicError")
382  << "With trackingRegionsSeedingLayers input, the seeding layer sets may only contain layer pairs, now "
383  "got sets with "
384  << regionsLayers->seedingLayerSetsHits().numberOfLayersInSet() << " layers";
385  }
386  }
387 
388  const SeedingLayerSetsHits* seedingLayerSetsHitsPtr() const { return &(regionsLayers_->seedingLayerSetsHits()); }
389 
390  size_t regionsSize() const { return regionsLayers_->regionsSize(); }
391 
392  const_iterator begin() const { return regionsLayers_->begin(); }
393  const_iterator cbegin() const { return begin(); }
394  const_iterator end() const { return regionsLayers_->end(); }
395  const_iterator cend() const { return end(); }
396 
397  private:
398  const TrackingRegionsSeedingLayerSets* regionsLayers_;
399  };
400 
401  RegionsLayersTogether(const std::vector<unsigned>* layerPairBegins,
402  const edm::InputTag& regionLayerTag,
404  : regionLayerToken_(iC.consumes<TrackingRegionsSeedingLayerSets>(regionLayerTag)) {
405  if (layerPairBegins->size() != 1) {
406  throw cms::Exception("LogicError") << "With trackingRegionsSeedingLayers mode, it doesn't make sense to "
407  "specify more than one input layer pair, got "
408  << layerPairBegins->size();
409  }
410  if ((*layerPairBegins)[0] != 0) {
411  throw cms::Exception("LogicError") << "With trackingRegionsSeedingLayers mode, it doesn't make sense to "
412  "specify other input layer pair than 0; got "
413  << (*layerPairBegins)[0];
414  }
415  }
416 
417  EventTmp beginEvent(const edm::Event& iEvent) const {
419  iEvent.getByToken(regionLayerToken_, hregions);
420  return EventTmp(hregions.product());
421  }
422 
423  private:
425  };
426 } // namespace
427 
429  auto layersTag = iConfig.getParameter<edm::InputTag>("seedingLayers");
430  auto regionTag = iConfig.getParameter<edm::InputTag>("trackingRegions");
431  auto regionLayerTag = iConfig.getParameter<edm::InputTag>("trackingRegionsSeedingLayers");
432  const bool useRegionLayers = !regionLayerTag.label().empty();
433  if (useRegionLayers) {
434  if (!regionTag.label().empty()) {
435  throw cms::Exception("Configuration")
436  << "HitPairEDProducer requires either trackingRegions or trackingRegionsSeedingLayers to be set, now both "
437  "are set to non-empty value. Set the unneeded parameter to empty value.";
438  }
439  if (!layersTag.label().empty()) {
440  throw cms::Exception("Configuration")
441  << "With non-empty trackingRegionsSeedingLayers, please set also seedingLayers to empty value to reduce "
442  "confusion, because the parameter is not used";
443  }
444  }
445  if (regionTag.label().empty() && regionLayerTag.label().empty()) {
446  throw cms::Exception("Configuration")
447  << "HitPairEDProducer requires either trackingRegions or trackingRegionsSeedingLayers to be set, now both are "
448  "set to empty value. Set the needed parameter to a non-empty value.";
449  }
450 
451  const bool produceSeedingHitSets = iConfig.getParameter<bool>("produceSeedingHitSets");
452  const bool produceIntermediateHitDoublets = iConfig.getParameter<bool>("produceIntermediateHitDoublets");
453 
455  if (useRegionLayers)
456  throw cms::Exception("Configuration")
457  << "Mode 'trackingRegionsSeedingLayers' makes sense only with 'produceSeedingHitsSets', now also "
458  "'produceIntermediateHitDoublets is active";
459  impl_ = std::make_unique<::Impl<::ImplSeedingHitSets, ::ImplIntermediateHitDoublets, ::RegionsLayersSeparate>>(
460  iConfig, consumesCollector(), layersTag, regionTag);
461  } else if (produceSeedingHitSets) {
462  if (useRegionLayers) {
463  impl_ = std::make_unique<::Impl<::ImplSeedingHitSets, ::DoNothing, ::RegionsLayersTogether>>(
464  iConfig, consumesCollector(), regionLayerTag);
465  } else {
466  impl_ = std::make_unique<::Impl<::ImplSeedingHitSets, ::DoNothing, ::RegionsLayersSeparate>>(
467  iConfig, consumesCollector(), layersTag, regionTag);
468  }
469  } else if (produceIntermediateHitDoublets) {
470  if (useRegionLayers)
471  throw cms::Exception("Configuration")
472  << "Mode 'trackingRegionsSeedingLayers' makes sense only with 'produceSeedingHitsSets', now "
473  "'produceIntermediateHitDoublets is active instead";
474  impl_ = std::make_unique<::Impl<::DoNothing, ::ImplIntermediateHitDoublets, ::RegionsLayersSeparate>>(
475  iConfig, consumesCollector(), layersTag, regionTag);
476  } else
477  throw cms::Exception("Configuration")
478  << "HitPairEDProducer requires either produceIntermediateHitDoublets or produceSeedingHitSets to be True. If "
479  "neither are needed, just remove this module from your sequence/path as it doesn't do anything useful";
480 
481  auto clusterCheckTag = iConfig.getParameter<edm::InputTag>("clusterCheck");
482  if (!clusterCheckTag.label().empty())
483  clusterCheckToken_ = consumes<bool>(clusterCheckTag);
484 
485  impl_->produces(producesCollector());
486 }
487 
490 
491  desc.add<edm::InputTag>("seedingLayers", edm::InputTag("seedingLayersEDProducer"))
492  ->setComment("Set this empty if 'trackingRegionsSeedingLayers' is non-empty");
493  desc.add<edm::InputTag>("trackingRegions", edm::InputTag("globalTrackingRegionFromBeamSpot"))
494  ->setComment(
495  "Input tracking regions when using all layer sets in 'seedingLayers' (conflicts with "
496  "'trackingRegionsSeedingLayers', set this empty to use the other)");
497  desc.add<edm::InputTag>("trackingRegionsSeedingLayers", edm::InputTag(""))
498  ->setComment(
499  "Input tracking regions and corresponding layer sets in case of dynamically limiting the seeding layers "
500  "(conflicts with 'trackingRegions', set this empty to use the other; if using this set also 'seedingLayers' "
501  "to empty)");
502  desc.add<edm::InputTag>("clusterCheck", edm::InputTag("trackerClusterCheck"));
503  desc.add<bool>("produceSeedingHitSets", false);
504  desc.add<bool>("produceIntermediateHitDoublets", false);
505  desc.add<unsigned int>("maxElement", 1000000);
506  desc.add<unsigned int>("maxElementTotal", 50000000);
507  desc.add<std::vector<unsigned>>("layerPairs", std::vector<unsigned>{0})
508  ->setComment("Indices to the pairs of consecutive layers, i.e. 0 means (0,1), 1 (1,2) etc.");
509 
510  descriptions.add("hitPairEDProducerDefault", desc);
511 }
512 
514  bool clusterCheckOk = true;
516  edm::Handle<bool> hclusterCheck;
517  iEvent.getByToken(clusterCheckToken_, hclusterCheck);
518  clusterCheckOk = *hclusterCheck;
519  }
520 
521  impl_->produce(clusterCheckOk, iEvent, iSetup);
522 }
523 
size
Write out results.
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
const_iterator begin() const
ProductRegistryHelper::BranchAliasSetterT< ProductType > produces()
SeedingLayerSet slice(size_t begin, size_t end) const
std::unique_ptr<::ImplBase > impl_
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
T const * product() const
Definition: Handle.h:70
constexpr bool isUninitialized() const noexcept
Definition: EDGetToken.h:99
void produce(edm::Event &iEvent, const edm::EventSetup &iSetup) override
unsigned short size() const
Get the number of SeedingLayerSets.
std::string const & label() const
Definition: InputTag.h:36
Helper class enforcing correct way of filling the doublets of a region.
Log< level::Error, false > LogError
#define LogTrace(id)
void put(edm::Event &evt, double value, const char *instanceName)
~HitPairEDProducer() override=default
Definition: __init__.py:1
int iEvent
Definition: GenABIO.cc:224
bool operator==(const QGLikelihoodParameters &lhs, const QGLikelihoodCategory &rhs)
Test if parameters are compatible with category.
edm::EDGetTokenT< bool > clusterCheckToken_
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
HitPairEDProducer(const edm::ParameterSet &iConfig)
unsigned short numberOfLayersInSet() const
Get number of layers in each SeedingLayerSets.
void reserve(size_t nregions, size_t nhitsets)
Helper class enforcing correct way of filling the doublets of a region.
bool operator!=(DTCELinkId const &lhs, DTCELinkId const &rhs)
Definition: DTCELinkId.h:81
const SeedingLayerSetsHits & seedingLayerSetsHits() const
void add(std::string const &label, ParameterSetDescription const &psetDescription)
TEveGeoShape * clone(const TEveElement *element, TEveElement *parent)
Definition: eve_macros.cc:135
HLT enums.
void reserve(size_t nregions, size_t nlayersets)
MatrixMeschach operator*(const MatrixMeschach &mat1, const MatrixMeschach &mat2)
def move(src, dest)
Definition: eostools.py:511