CMS 3D CMS Logo

TrackCollectionMerger.cc
Go to the documentation of this file.
2 
3 
6 
13 
21 
24 
25 #include<vector>
26 #include<memory>
27 #include<cassert>
28 namespace {
29  class TrackCollectionMerger final : public edm::global::EDProducer<> {
30  public:
31  explicit TrackCollectionMerger(const edm::ParameterSet& conf) :
32  collectionCloner(*this, conf, true),
33  priorityName_(conf.getParameter<std::string>("trackAlgoPriorityOrder")),
34  m_foundHitBonus(conf.getParameter<double>("foundHitBonus")),
35  m_lostHitPenalty(conf.getParameter<double>("lostHitPenalty")),
36  m_shareFrac(conf.getParameter<double>("shareFrac")),
37  m_minShareHits(conf.getParameter<unsigned int>("minShareHits")),
38  m_minQuality(reco::TrackBase::qualityByName(conf.getParameter<std::string>("minQuality"))),
39  m_allowFirstHitShare(conf.getParameter<bool>("allowFirstHitShare"))
40 {
41  for (auto const & it : conf.getParameter<std::vector<edm::InputTag> >("trackProducers") )
42  srcColls.emplace_back(it,consumesCollector());
43  for (auto const & it : conf.getParameter<std::vector<std::string> >("inputClassifiers")) {
44  srcMVAs.push_back(consumes<MVACollection>(edm::InputTag(it,"MVAValues")));
45  srcQuals.push_back(consumes<QualityMaskCollection>(edm::InputTag(it,"QualityMasks")));
46  }
47 
48  assert(srcColls.size()==srcQuals.size());
49 
50 
51  produces<MVACollection>("MVAValues");
52  produces<QualityMaskCollection>("QualityMasks");
53 
54  }
55 
56  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
58  desc.add<std::vector<edm::InputTag> >("trackProducers",std::vector<edm::InputTag>());
59  desc.add<std::vector<std::string> >("inputClassifiers",std::vector<std::string>());
60  desc.add<std::string>("trackAlgoPriorityOrder", "trackAlgoPriorityOrder");
61  desc.add<double>("shareFrac",.19);
62  desc.add<double>("foundHitBonus",10.);
63  desc.add<double>("lostHitPenalty",5.);
64  desc.add<unsigned int>("minShareHits",2);
65  desc.add<bool>("allowFirstHitShare",true);
66  desc.add<std::string>("minQuality","loose");
68  descriptions.add("TrackCollectionMerger", desc);
69  }
70 
71  private:
72 
73 
74  TrackCollectionCloner collectionCloner;
75  std::vector<TrackCollectionCloner::Tokens> srcColls;
76 
77  using MVACollection = std::vector<float>;
78  using QualityMaskCollection = std::vector<unsigned char>;
79 
80  using IHit = std::pair<unsigned int, TrackingRecHit const *>;
81  using IHitV = std::vector<IHit>;
82 
83  std::vector<edm::EDGetTokenT<MVACollection>> srcMVAs;
84  std::vector<edm::EDGetTokenT<QualityMaskCollection>> srcQuals;
85 
86  std::string priorityName_;
87 
88  float m_foundHitBonus;
89  float m_lostHitPenalty;
90  float m_shareFrac;
91  unsigned int m_minShareHits;
92  reco::TrackBase::TrackQuality m_minQuality;
93  bool m_allowFirstHitShare;
94 
95  virtual void produce(edm::StreamID, edm::Event& evt, const edm::EventSetup&) const override;
96 
97 
98  bool areDuplicate(IHitV const& rh1, IHitV const& rh2) const;
99 
100 
101  };
102 
103 }
104 
106 
107 
108 namespace {
109 
110  void TrackCollectionMerger::produce(edm::StreamID, edm::Event& evt, const edm::EventSetup& es) const {
111 
112  TrackCollectionCloner::Producer producer(evt, collectionCloner);
113 
115  es.get<CkfComponentsRecord>().get(priorityName_, priorityH);
116  auto const & trackAlgoPriorityOrder = *priorityH;
117 
118  // load collections
119  auto collsSize = srcColls.size();
120  auto rSize=0U;
121  declareDynArray(reco::TrackCollection const *, collsSize, trackColls);
122  for (auto i=0U; i< collsSize; ++i) {
123  trackColls[i] = &srcColls[i].tracks(evt);
124  rSize += (*trackColls[i]).size();
125  }
126 
127 
128  unsigned char qualMask = ~0;
129  if (m_minQuality!=reco::TrackBase::undefQuality) qualMask = 1<<m_minQuality;
130 
131 
132  // load tracks
133  initDynArray(unsigned int,collsSize,nGoods,0);
134  declareDynArray(float,rSize, mvas);
135  declareDynArray(unsigned char,rSize, quals);
136  declareDynArray(unsigned int,rSize, tkInds);
137  auto k=0U;
138  for (auto i=0U; i< collsSize; ++i) {
139  auto const & tkColl = *trackColls[i];
140  auto size = tkColl.size();
142  evt.getByToken(srcMVAs[i], hmva);
143  assert((*hmva).size()==size);
145  evt.getByToken(srcQuals[i], hqual);
146  for (auto j=0U; j<size; ++j) {
147  if (! (qualMask&(* hqual)[j]) ) continue;
148  mvas[k]=(*hmva)[j];
149  quals[k] = (*hqual)[j];
150  tkInds[k]=j;
151  ++k;
152  ++nGoods[i];
153  }
154  }
155 
156  auto ntotTk=k;
157  std::vector<bool> selected(ntotTk,true);
158 
161  declareDynArray(reco::TrackBase::AlgoMask, ntotTk, algoMask);
162 
163 
164  // merge (if more than one collection...)
165 
166  auto merger = [&]()->void {
167 
168  // load hits and score
169  declareDynArray(float,ntotTk,score);
170  declareDynArray(IHitV, ntotTk, rh1);
171 
172  k=0U;
173  for (auto i=0U; i< collsSize; ++i) {
174  auto const & tkColl = *trackColls[i];
175  for (auto j=0U; j< nGoods[i]; ++j) {
176  auto const & track = tkColl[tkInds[k]];
177  algo[k] = track.algo();
178  oriAlgo[k] = track.originalAlgo();
179  algoMask[k] = track.algoMask();
180 
181  auto validHits=track.numberOfValidHits();
182  auto validPixelHits=track.hitPattern().numberOfValidPixelHits();
183  auto lostHits=track.numberOfLostHits();
184  score[k] = m_foundHitBonus*validPixelHits+m_foundHitBonus*validHits - m_lostHitPenalty*lostHits - track.chi2();
185 
186  auto & rhv = rh1[k];
187  rhv.reserve(validHits) ;
188  auto compById = [](IHit const & h1, IHit const & h2) {return h1.first < h2.first;};
189  for (auto it = track.recHitsBegin(); it != track.recHitsEnd(); ++it) {
190  auto const & hit = *(*it);
191  auto id = hit.rawId() ;
192  if(hit.geographicalId().subdetId()>2) id &= (~3); // mask mono/stereo in strips...
193  if likely(hit.isValid()) { rhv.emplace_back(id,&hit); std::push_heap(rhv.begin(),rhv.end(),compById); }
194  }
195  std::sort_heap(rhv.begin(),rhv.end(),compById);
196 
197 
198  ++k;
199  }
200  }
201  assert(ntotTk==k);
202 
203  auto seti = [&](unsigned int ii, unsigned int jj) {
204  selected[jj]=false;
205  selected[ii]=true;
206  if (trackAlgoPriorityOrder.priority(oriAlgo[jj]) < trackAlgoPriorityOrder.priority(oriAlgo[ii])) oriAlgo[ii] = oriAlgo[jj];
207  algoMask[ii] |= algoMask[jj];
208  quals[ii] |= (1<<reco::TrackBase::confirmed);
209  algoMask[jj] = algoMask[ii]; // in case we keep discarded
210  quals[jj] |= (1<<reco::TrackBase::discarded);
211  };
212 
213 
214 
215  auto iStart2=0U;
216  for (auto i=0U; i<collsSize-1; ++i) {
217  auto iStart1=iStart2;
218  iStart2=iStart1+nGoods[i];
219  for (auto t1=iStart1; t1<iStart2; ++t1) {
220  if (!selected[t1]) continue;
221  auto score1 = score[t1];
222  for (auto t2=iStart2; t2 <ntotTk; ++t2) {
223  if (!selected[t1]) break;
224  if (!selected[t2]) continue;
225  if (!areDuplicate(rh1[t1],rh1[t2])) continue;
226  auto score2 = score[t2];
227  constexpr float almostSame = 0.01f; // difference rather than ratio due to possible negative values for score
228 
229  if ( score1 - score2 > almostSame ) {
230  seti(t1,t2);
231  } else if ( score2 - score1 > almostSame ) {
232  seti(t2,t1);
233  } else { // take best
235  if ( (quals[t1]&qmask) == (quals[t2]&qmask) ) {
236  // take first
237  if (trackAlgoPriorityOrder.priority(algo[t1]) <= trackAlgoPriorityOrder.priority(algo[t2])) {
238  seti(t1,t2);
239  } else {
240  seti(t2,t1);
241  }
242  } else if ( (quals[t1]&qmask) > (quals[t2]&qmask) )
243  seti(t1,t2);
244  else
245  seti(t2,t1);
246  } // end ifs...
247 
248  } // end t2
249  } // end t1
250  } // end colls
251  }; // end merger;
252 
253 
254  if (collsSize>1) merger();
255 
256  // products
257  auto pmvas = std::make_unique<MVACollection>();
258  auto pquals = std::make_unique<QualityMaskCollection>();
259 
260  // clone selected tracks...
261  auto nsel=0U;
262  auto iStart2=0U;
263  auto isel=0U;
264  for (auto i=0U; i<collsSize; ++i) {
265  std::vector<unsigned int> selId;
266  std::vector<unsigned int> tid;
267  auto iStart1=iStart2;
268  iStart2=iStart1+nGoods[i];
269  assert(producer.selTracks_->size()==isel);
270  for (auto t1=iStart1; t1<iStart2; ++t1) {
271  if (!selected[t1]) continue;
272  ++nsel;
273  tid.push_back(t1);
274  selId.push_back(tkInds[t1]);
275  pmvas->push_back(mvas[t1]);
276  pquals->push_back(quals[t1]);
277  }
278  producer(srcColls[i],selId);
279  assert(producer.selTracks_->size()==nsel);
280  assert(tid.size()==nsel-isel);
281  auto k=0U;
282  for (;isel<nsel;++isel) {
283  auto & otk = (*producer.selTracks_)[isel];
284  otk.setQualityMask((*pquals)[isel]);
285  otk.setOriginalAlgorithm(oriAlgo[tid[k]]);
286  otk.setAlgoMask(algoMask[tid[k++]]);
287  }
288  assert(tid.size()==k);
289  }
290 
291  assert(producer.selTracks_->size()==pmvas->size());
292 
293  evt.put(std::move(pmvas),"MVAValues");
294  evt.put(std::move(pquals),"QualityMasks");
295 
296 
297  }
298 
299 
300 
301  bool TrackCollectionMerger::areDuplicate(IHitV const& rh1, IHitV const& rh2) const {
302  auto nh1=rh1.size();
303  auto nh2=rh2.size();
304 
305 
306  auto share = // use_sharesInput_ ?
307  [](const TrackingRecHit* it,const TrackingRecHit* jt)->bool { return it->sharesInput(jt,TrackingRecHit::some); };
308  //:
309  // [](const TrackingRecHit* it,const TrackingRecHit* jt)->bool {
310  // float delta = std::abs ( it->localPosition().x()-jt->localPosition().x() );
311  // return (it->geographicalId()==jt->geographicalId())&&(delta<epsilon_);
312  // };
313 
314 
315  //loop over rechits
316  int noverlap=0;
317  int firstoverlap=0;
318  // check first hit (should use REAL first hit?)
319  if unlikely(m_allowFirstHitShare && rh1[0].first==rh2[0].first ) {
320  if (share( rh1[0].second, rh2[0].second)) firstoverlap=1;
321  }
322 
323  // exploit sorting
324  unsigned int jh=0;
325  unsigned int ih=0;
326  while (ih!=nh1 && jh!=nh2) {
327  // break if not enough to go...
328  // if ( nprecut-noverlap+firstoverlap > int(nh1-ih)) break;
329  // if ( nprecut-noverlap+firstoverlap > int(nh2-jh)) break;
330  auto const id1 = rh1[ih].first;
331  auto const id2 = rh2[jh].first;
332  if (id1<id2) ++ih;
333  else if (id2<id1) ++jh;
334  else {
335  // in case of split-hit do full conbinatorics
336  auto li=ih; while( (++li)!=nh1 && id1 == rh1[li].first);
337  auto lj=jh; while( (++lj)!=nh2 && id2 == rh2[lj].first);
338  for (auto ii=ih; ii!=li; ++ii)
339  for (auto jj=jh; jj!=lj; ++jj) {
340  if (share( rh1[ii].second, rh2[jj].second)) noverlap++;
341  }
342  jh=lj; ih=li;
343  } // equal ids
344 
345  } //loop over ih & jh
346 
347  return noverlap >= int(m_minShareHits) &&
348  (noverlap-firstoverlap) > (std::min(nh1,nh2)-firstoverlap)*m_shareFrac;
349 
350  }
351 
352 
353 }
354 
355 
358 
359 DEFINE_FWK_MODULE(TrackCollectionMerger);
size
Write out results.
T getParameter(std::string const &) const
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:122
#define initDynArray(T, n, x, i)
Definition: DynArray.h:60
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:457
TrackQuality
track quality
Definition: TrackBase.h:151
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
std::vector< Track > TrackCollection
collection of Tracks
Definition: TrackFwd.h:14
virtual bool sharesInput(const TrackingRecHit *other, SharedInputType what) const
static void fill(edm::ParameterSetDescription &desc)
#define constexpr
TrackAlgorithm
track algorithm
Definition: TrackBase.h:99
virtual void produce(StreamID, Event &, EventSetup const &) const =0
#define unlikely(x)
U second(std::pair< T, U > const &p)
#define likely(x)
auto const T2 &decltype(t1.eta()) t2
Definition: deltaR.h:16
ConsumesCollector consumesCollector()
Use a ConsumesCollector to gather consumes information from helper functions.
T min(T a, T b)
Definition: MathUtil.h:58
ParameterDescriptionBase * add(U const &iLabel, T const &value)
static void fillDescriptions(ConfigurationDescriptions &descriptions)
ii
Definition: cuy.py:588
int k[5][pyjets_maxn]
std::bitset< algoSize > AlgoMask
algo mask
Definition: TrackBase.h:146
const T & get() const
Definition: EventSetup.h:56
fixed size matrix
std::array< unsigned int, reco::TrackBase::algoSize > trackAlgoPriorityOrder
#define declareDynArray(T, n, x)
Definition: DynArray.h:59
def move(src, dest)
Definition: eostools.py:510