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 
52  std::vector<unsigned> layerPairBegins_;
53  };
54  ImplBase::ImplBase(const edm::ParameterSet& iConfig):
55  maxElement_(iConfig.getParameter<unsigned int>("maxElement")),
56  generator_(0, 1, nullptr, maxElement_), // these indices are dummy, TODO: cleanup HitPairGeneratorFromLayerPair
57  layerPairBegins_(iConfig.getParameter<std::vector<unsigned> >("layerPairs"))
58  {
59  if(layerPairBegins_.empty())
60  throw cms::Exception("Configuration") << "HitPairEDProducer requires at least index for layer pairs (layerPairs parameter), none was given";
61  }
62 
64  template <typename T_SeedingHitSets, typename T_IntermediateHitDoublets, typename T_RegionLayers>
65  class Impl: public ImplBase {
66  public:
67  template <typename... Args>
68  Impl(const edm::ParameterSet& iConfig, Args&&... args):
69  ImplBase(iConfig),
70  regionsLayers_(&layerPairBegins_, std::forward<Args>(args)...)
71  {}
72  ~Impl() override = default;
73 
74  void produces(edm::ProducerBase& producer) const override {
75  T_SeedingHitSets::produces(producer);
76  T_IntermediateHitDoublets::produces(producer);
77  }
78 
79  void produce(const bool clusterCheckOk, edm::Event& iEvent, const edm::EventSetup& iSetup) override {
80  auto regionsLayers = regionsLayers_.beginEvent(iEvent);
81 
82  auto seedingHitSetsProducer = T_SeedingHitSets(&localRA_);
83  auto intermediateHitDoubletsProducer = T_IntermediateHitDoublets(regionsLayers.seedingLayerSetsHitsPtr());
84 
85  if(!clusterCheckOk) {
86  seedingHitSetsProducer.putEmpty(iEvent);
87  intermediateHitDoubletsProducer.putEmpty(iEvent);
88  return;
89  }
90 
91  seedingHitSetsProducer.reserve(regionsLayers.regionsSize());
92  intermediateHitDoubletsProducer.reserve(regionsLayers.regionsSize());
93 
94  for(const auto& regionLayers: regionsLayers) {
95  const TrackingRegion& region = regionLayers.region();
96  auto hitCachePtr_filler_shs = seedingHitSetsProducer.beginRegion(&region, nullptr);
97  auto hitCachePtr_filler_ihd = intermediateHitDoubletsProducer.beginRegion(&region, std::get<0>(hitCachePtr_filler_shs));
98  auto hitCachePtr = std::get<0>(hitCachePtr_filler_ihd);
99 
100  for(SeedingLayerSetsHits::SeedingLayerSet layerSet: regionLayers.layerPairs()) {
101  auto doublets = generator_.doublets(region, iEvent, iSetup, layerSet, *hitCachePtr);
102  LogTrace("HitPairEDProducer") << " created " << doublets.size() << " doublets for layers " << layerSet[0].index() << "," << layerSet[1].index();
103  if(doublets.empty()) continue; // don't bother if no pairs from these layers
104  seedingHitSetsProducer.fill(std::get<1>(hitCachePtr_filler_shs), doublets);
105  intermediateHitDoubletsProducer.fill(std::get<1>(hitCachePtr_filler_ihd), layerSet, std::move(doublets));
106  }
107  }
108 
109  seedingHitSetsProducer.put(iEvent);
110  intermediateHitDoubletsProducer.put(iEvent);
111  }
112 
113  private:
114  T_RegionLayers regionsLayers_;
115  };
116 
118  class DoNothing {
119  public:
120  DoNothing(const SeedingLayerSetsHits *) {}
121  DoNothing(edm::RunningAverage *) {}
122 
123  static void produces(edm::ProducerBase&) {};
124 
125  void reserve(size_t) {}
126 
127  auto beginRegion(const TrackingRegion *, LayerHitMapCache *ptr) {
128  return std::make_tuple(ptr, 0);
129  }
130 
131  void fill(int, const HitDoublets&) {}
133 
134  void put(edm::Event&) {}
135  void putEmpty(edm::Event&) {}
136  };
137 
139  class ImplSeedingHitSets {
140  public:
141  ImplSeedingHitSets(edm::RunningAverage *localRA):
142  seedingHitSets_(std::make_unique<RegionsSeedingHitSets>()),
143  localRA_(localRA)
144  {}
145 
146  static void produces(edm::ProducerBase& producer) {
147  producer.produces<RegionsSeedingHitSets>();
148  }
149 
150  void reserve(size_t regionsSize) {
151  seedingHitSets_->reserve(regionsSize, localRA_->upper());
152  }
153 
154  auto beginRegion(const TrackingRegion *region, LayerHitMapCache *) {
155  hitCacheTmp_.clear();
156  return std::make_tuple(&hitCacheTmp_, seedingHitSets_->beginRegion(region));
157  }
158 
160  for(size_t i=0, size=doublets.size(); i<size; ++i) {
161  filler.emplace_back(doublets.hit(i, HitDoublets::inner),
162  doublets.hit(i, HitDoublets::outer));
163  }
164  }
165 
166  void put(edm::Event& iEvent) {
167  seedingHitSets_->shrink_to_fit();
168  localRA_->update(seedingHitSets_->size());
169  putEmpty(iEvent);
170  }
171 
172  void putEmpty(edm::Event& iEvent) {
173  iEvent.put(std::move(seedingHitSets_));
174  }
175 
176  private:
177  std::unique_ptr<RegionsSeedingHitSets> seedingHitSets_;
178  edm::RunningAverage *localRA_;
179  LayerHitMapCache hitCacheTmp_; // used if !produceIntermediateHitDoublets
180  };
181 
183  class ImplIntermediateHitDoublets {
184  public:
185  ImplIntermediateHitDoublets(const SeedingLayerSetsHits *layers):
186  intermediateHitDoublets_(std::make_unique<IntermediateHitDoublets>(layers)),
187  layers_(layers)
188  {}
189 
190  static void produces(edm::ProducerBase& producer) {
191  producer.produces<IntermediateHitDoublets>();
192  }
193 
194  void reserve(size_t regionsSize) {
195  intermediateHitDoublets_->reserve(regionsSize, layers_->size());
196  }
197 
198  auto beginRegion(const TrackingRegion *region, LayerHitMapCache *) {
199  auto filler = intermediateHitDoublets_->beginRegion(region);
200  return std::make_tuple(&(filler.layerHitMapCache()), std::move(filler));
201  }
202 
204  filler.addDoublets(layerSet, std::move(doublets));
205  }
206 
207  void put(edm::Event& iEvent) {
208  intermediateHitDoublets_->shrink_to_fit();
209  putEmpty(iEvent);
210  }
211 
212  void putEmpty(edm::Event& iEvent) {
213  iEvent.put(std::move(intermediateHitDoublets_));
214  }
215 
216  private:
217  std::unique_ptr<IntermediateHitDoublets> intermediateHitDoublets_;
218  const SeedingLayerSetsHits *layers_;
219  };
220 
222  // For the usual case that TrackingRegions and seeding layers are read separately
223  class RegionsLayersSeparate {
224  public:
225  class RegionLayers {
226  public:
227  RegionLayers(const TrackingRegion *region, const std::vector<SeedingLayerSetsHits::SeedingLayerSet> *layerPairs):
228  region_(region), layerPairs_(layerPairs) {}
229 
230  const TrackingRegion& region() const { return *region_; }
231  const std::vector<SeedingLayerSetsHits::SeedingLayerSet>& layerPairs() const { return *layerPairs_; }
232 
233  private:
234  const TrackingRegion *region_;
235  const std::vector<SeedingLayerSetsHits::SeedingLayerSet> *layerPairs_;
236  };
237 
238  class EventTmp {
239  public:
240  class const_iterator {
241  public:
242  using internal_iterator_type = edm::OwnVector<TrackingRegion>::const_iterator;
243  using value_type = RegionLayers;
244  using difference_type = internal_iterator_type::difference_type;
245 
246  const_iterator(internal_iterator_type iter, const std::vector<SeedingLayerSetsHits::SeedingLayerSet> *layerPairs):
247  iter_(iter), layerPairs_(layerPairs) {}
248 
249  value_type operator*() const { return value_type(&(*iter_), layerPairs_); }
250 
251  const_iterator& operator++() { ++iter_; return *this; }
252  const_iterator operator++(int) {
253  const_iterator clone(*this);
254  ++(*this);
255  return clone;
256  }
257 
258  bool operator==(const const_iterator& other) const { return iter_ == other.iter_; }
259  bool operator!=(const const_iterator& other) const { return !operator==(other); }
260 
261  private:
262  internal_iterator_type iter_;
263  const std::vector<SeedingLayerSetsHits::SeedingLayerSet> *layerPairs_;
264  };
265 
266  EventTmp(const SeedingLayerSetsHits *seedingLayerSetsHits,
268  const std::vector<unsigned>& layerPairBegins):
269  seedingLayerSetsHits_(seedingLayerSetsHits), regions_(regions) {
270 
271  // construct the pairs from the sets
272  if(seedingLayerSetsHits_->numberOfLayersInSet() > 2) {
273  for(const auto& layerSet: *seedingLayerSetsHits_) {
274  for(const auto pairBeginIndex: layerPairBegins) {
275  if(pairBeginIndex+1 >= seedingLayerSetsHits->numberOfLayersInSet()) {
276  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";
277  }
278 
279  // Take only the requested pair of the set
280  SeedingLayerSetsHits::SeedingLayerSet pairCandidate = layerSet.slice(pairBeginIndex, pairBeginIndex+1);
281 
282  // it would be trivial to use 128-bit bitfield for O(1) check
283  // if a layer pair has been inserted, but let's test first how
284  // a "straightforward" solution works
285  auto found = std::find_if(layerPairs.begin(), layerPairs.end(), [&](const SeedingLayerSetsHits::SeedingLayerSet& pair) {
286  return pair[0].index() == pairCandidate[0].index() && pair[1].index() == pairCandidate[1].index();
287  });
288  if(found != layerPairs.end())
289  continue;
290 
291  layerPairs.push_back(pairCandidate);
292  }
293  }
294  }
295  else {
296  if(layerPairBegins.size() != 1) {
297  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();
298  }
299  if(layerPairBegins[0] != 0) {
300  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];
301  }
302 
303  layerPairs.reserve(seedingLayerSetsHits->size());
304  for(const auto& set: *seedingLayerSetsHits)
305  layerPairs.push_back(set);
306  }
307  }
308 
309  const SeedingLayerSetsHits *seedingLayerSetsHitsPtr() const { return seedingLayerSetsHits_; }
310 
311  size_t regionsSize() const { return regions_->size(); }
312 
313  const_iterator begin() const { return const_iterator(regions_->begin(), &layerPairs); }
314  const_iterator cbegin() const { return begin(); }
315  const_iterator end() const { return const_iterator(regions_->end(), &layerPairs); }
316  const_iterator cend() const { return end(); }
317 
318  private:
319  const SeedingLayerSetsHits *seedingLayerSetsHits_;
320  const edm::OwnVector<TrackingRegion> *regions_;
321  std::vector<SeedingLayerSetsHits::SeedingLayerSet> layerPairs;
322  };
323 
324  RegionsLayersSeparate(const std::vector<unsigned> *layerPairBegins,
325  const edm::InputTag& seedingLayerTag,
326  const edm::InputTag& regionTag,
328  layerPairBegins_(layerPairBegins),
329  seedingLayerToken_(iC.consumes<SeedingLayerSetsHits>(seedingLayerTag)),
330  regionToken_(iC.consumes<edm::OwnVector<TrackingRegion> >(regionTag))
331  {}
332 
333  EventTmp beginEvent(const edm::Event& iEvent) const {
335  iEvent.getByToken(seedingLayerToken_, hlayers);
336  const auto *layers = hlayers.product();
337  if(layers->numberOfLayersInSet() < 2)
338  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.";
340  iEvent.getByToken(regionToken_, hregions);
341 
342  return EventTmp(layers, hregions.product(), *layerPairBegins_);
343  }
344 
345  private:
346  const std::vector<unsigned> *layerPairBegins_;
347  edm::EDGetTokenT<SeedingLayerSetsHits> seedingLayerToken_;
349  };
350 
352  // For the case of automated pixel inactive region recovery where
353  // TrackingRegions and seeding layers become together
354  class RegionsLayersTogether {
355  public:
356  class EventTmp {
357  public:
359 
360  explicit EventTmp(const TrackingRegionsSeedingLayerSets *regionsLayers):
361  regionsLayers_(regionsLayers) {
362  if(regionsLayers->seedingLayerSetsHits().numberOfLayersInSet() != 2) {
363  throw cms::Exception("LogicError") << "With trackingRegionsSeedingLayers input, the seeding layer sets may only contain layer pairs, now got sets with " << regionsLayers->seedingLayerSetsHits().numberOfLayersInSet() << " layers";
364  }
365  }
366 
367  const SeedingLayerSetsHits *seedingLayerSetsHitsPtr() const { return &(regionsLayers_->seedingLayerSetsHits()); }
368 
369  size_t regionsSize() const { return regionsLayers_->regionsSize(); }
370 
371  const_iterator begin() const { return regionsLayers_->begin(); }
372  const_iterator cbegin() const { return begin(); }
373  const_iterator end() const { return regionsLayers_->end(); }
374  const_iterator cend() const { return end(); }
375 
376  private:
377  const TrackingRegionsSeedingLayerSets *regionsLayers_;
378  };
379 
380  RegionsLayersTogether(const std::vector<unsigned> *layerPairBegins,
381  const edm::InputTag& regionLayerTag,
383  regionLayerToken_(iC.consumes<TrackingRegionsSeedingLayerSets>(regionLayerTag))
384  {
385  if(layerPairBegins->size() != 1) {
386  throw cms::Exception("LogicError") << "With trackingRegionsSeedingLayers mode, it doesn't make sense to specify more than one input layer pair, got " << layerPairBegins->size();
387  }
388  if((*layerPairBegins)[0] != 0) {
389  throw cms::Exception("LogicError") << "With trackingRegionsSeedingLayers mode, it doesn't make sense to specify other input layer pair than 0; got " << (*layerPairBegins)[0];
390  }
391  }
392 
393  EventTmp beginEvent(const edm::Event& iEvent) const {
395  iEvent.getByToken(regionLayerToken_, hregions);
396  return EventTmp(hregions.product());
397  }
398 
399  private:
401  };
402 }
403 
404 
405 
407  auto layersTag = iConfig.getParameter<edm::InputTag>("seedingLayers");
408  auto regionTag = iConfig.getParameter<edm::InputTag>("trackingRegions");
409  auto regionLayerTag = iConfig.getParameter<edm::InputTag>("trackingRegionsSeedingLayers");
410  const bool useRegionLayers = regionLayerTag.label() != "";
411  if(useRegionLayers) {
412  if(regionTag.label() != "") {
413  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.";
414  }
415  if(layersTag.label() != "") {
416  throw cms::Exception("Configuration") << "With non-empty trackingRegionsSeedingLayers, please set also seedingLayers to empty value to reduce confusion, because the parameter is not used";
417  }
418  }
419  if(regionTag.label() == "" && regionLayerTag.label() == "") {
420  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.";
421  }
422 
423  const bool produceSeedingHitSets = iConfig.getParameter<bool>("produceSeedingHitSets");
424  const bool produceIntermediateHitDoublets = iConfig.getParameter<bool>("produceIntermediateHitDoublets");
425 
426  if(produceSeedingHitSets && produceIntermediateHitDoublets) {
427  if(useRegionLayers) throw cms::Exception("Configuration") << "Mode 'trackingRegionsSeedingLayers' makes sense only with 'produceSeedingHitsSets', now also 'produceIntermediateHitDoublets is active";
428  impl_ = std::make_unique<::Impl<::ImplSeedingHitSets, ::ImplIntermediateHitDoublets, ::RegionsLayersSeparate>>(iConfig, layersTag, regionTag, consumesCollector());
429  }
430  else if(produceSeedingHitSets) {
431  if(useRegionLayers) {
432  impl_ = std::make_unique<::Impl<::ImplSeedingHitSets, ::DoNothing, ::RegionsLayersTogether>>(iConfig, regionLayerTag, consumesCollector());
433  }
434  else {
435  impl_ = std::make_unique<::Impl<::ImplSeedingHitSets, ::DoNothing, ::RegionsLayersSeparate>>(iConfig, layersTag, regionTag, consumesCollector());
436  }
437  }
438  else if(produceIntermediateHitDoublets) {
439  if(useRegionLayers) throw cms::Exception("Configuration") << "Mode 'trackingRegionsSeedingLayers' makes sense only with 'produceSeedingHitsSets', now 'produceIntermediateHitDoublets is active instead";
440  impl_ = std::make_unique<::Impl<::DoNothing, ::ImplIntermediateHitDoublets, ::RegionsLayersSeparate>>(iConfig, layersTag, regionTag, consumesCollector());
441  }
442  else
443  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";
444 
445  auto clusterCheckTag = iConfig.getParameter<edm::InputTag>("clusterCheck");
446  if(clusterCheckTag.label() != "")
447  clusterCheckToken_ = consumes<bool>(clusterCheckTag);
448 
449  impl_->produces(*this);
450 }
451 
454 
455  desc.add<edm::InputTag>("seedingLayers", edm::InputTag("seedingLayersEDProducer"))->setComment("Set this empty if 'trackingRegionsSeedingLayers' is non-empty");
456  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)");
457  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)");
458  desc.add<edm::InputTag>("clusterCheck", edm::InputTag("trackerClusterCheck"));
459  desc.add<bool>("produceSeedingHitSets", false);
460  desc.add<bool>("produceIntermediateHitDoublets", false);
461  desc.add<unsigned int>("maxElement", 1000000);
462  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.");
463 
464  descriptions.add("hitPairEDProducerDefault", desc);
465 }
466 
468  bool clusterCheckOk = true;
470  edm::Handle<bool> hclusterCheck;
471  iEvent.getByToken(clusterCheckToken_, hclusterCheck);
472  clusterCheckOk = *hclusterCheck;
473  }
474 
475  impl_->produce(clusterCheckOk, iEvent, iSetup);
476 }
477 
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:510