CMS 3D CMS Logo

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