CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
DuplicateTrackMerger.cc
Go to the documentation of this file.
1 
9 
13 
14 
17 
19 
20 #include "TrackMerger.h"
21 
22 #include <vector>
23 #include <algorithm>
24 #include <string>
25 #include <iostream>
26 #include <atomic>
27 
29 
30 using namespace reco;
31 namespace {
32  class DuplicateTrackMerger final : public edm::stream::EDProducer<> {
33  public:
35  explicit DuplicateTrackMerger(const edm::ParameterSet& iPara);
37  virtual ~DuplicateTrackMerger();
38 
39  using CandidateToDuplicate = std::vector<std::pair<int, int>>;
40 
41  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
42 
43 
44  private:
46  void produce( edm::Event &, const edm::EventSetup &) override;
47 
48  private:
50  const GBRForest* forest_;
51 
52 
54  std::string dbFileName_;
55  bool useForestFromDB_;
56  std::string forestLabel_;
57 
58 
62  double minDeltaR3d2_;
64  double minBDTG_;
66  double minpT2_;
68  double minP_;
70  float maxDCA2_;
72  float maxDPhi_;
74  float maxDLambda_;
76  float maxDdxy_;
78  float maxDdsz_;
80  float maxDQoP_;
81 
83 
85  TrackMerger merger_;
86  };
87  }
88 
98 #include "TFile.h"
99 
100 namespace {
101 
102 
103 void
105 {
107  desc.add<edm::InputTag>("source",edm::InputTag());
108  desc.add<double>("minDeltaR3d",-4.0);
109  desc.add<double>("minBDTG",-0.1);
110  desc.add<double>("minpT",0.2);
111  desc.add<double>("minP",0.4);
112  desc.add<double>("maxDCA",30.0);
113  desc.add<double>("maxDPhi",0.30);
114  desc.add<double>("maxDLambda",0.30);
115  desc.add<double>("maxDdsz",10.0);
116  desc.add<double>("maxDdxy",10.0);
117  desc.add<double>("maxDQoP",0.25);
118  desc.add<std::string>("forestLabel","MVADuplicate");
119  desc.add<std::string>("GBRForestFileName","");
120  desc.add<bool>("useInnermostState",true);
121  desc.add<std::string>("ttrhBuilderName","WithAngleAndTemplate");
122  descriptions.add("DuplicateTrackMerger", desc);
123 }
124 
125 
126 DuplicateTrackMerger::DuplicateTrackMerger(const edm::ParameterSet& iPara) : forest_(nullptr), merger_(iPara)
127 {
128 
129  trackSource_ = consumes<reco::TrackCollection>(iPara.getParameter<edm::InputTag>("source"));
130  minDeltaR3d2_ = iPara.getParameter<double>("minDeltaR3d"); minDeltaR3d2_*=std::abs(minDeltaR3d2_);
131  minBDTG_ = iPara.getParameter<double>("minBDTG");
132  minpT2_ = iPara.getParameter<double>("minpT"); minpT2_ *= minpT2_;
133  minP_ = iPara.getParameter<double>("minP");
134  maxDCA2_ = iPara.getParameter<double>("maxDCA"); maxDCA2_*=maxDCA2_;
135  maxDPhi_ = iPara.getParameter<double>("maxDPhi");
136  maxDLambda_ = iPara.getParameter<double>("maxDLambda");
137  maxDdsz_ = iPara.getParameter<double>("maxDdsz");
138  maxDdxy_ = iPara.getParameter<double>("maxDdxy");
139  maxDQoP_ = iPara.getParameter<double>("maxDQoP");
140 
141  produces<std::vector<TrackCandidate> >("candidates");
142  produces<CandidateToDuplicate>("candidateMap");
143 
144  forestLabel_ = iPara.getParameter<std::string>("forestLabel");
145 
146  dbFileName_ = iPara.getParameter<std::string>("GBRForestFileName");
147  useForestFromDB_ = dbFileName_.empty();
148 
149  /*
150  tmvaReader_ = new TMVA::Reader("!Color:Silent");
151  tmvaReader_->AddVariable("ddsz",&tmva_ddsz_);
152  tmvaReader_->AddVariable("ddxy",&tmva_ddxy_);
153  tmvaReader_->AddVariable("dphi",&tmva_dphi_);
154  tmvaReader_->AddVariable("dlambda",&tmva_dlambda_);
155  tmvaReader_->AddVariable("dqoverp",&tmva_dqoverp_);
156  tmvaReader_->AddVariable("delta3d_r",&tmva_d3dr_);
157  tmvaReader_->AddVariable("delta3d_z",&tmva_d3dz_);
158  tmvaReader_->AddVariable("outer_nMissingInner",&tmva_outer_nMissingInner_);
159  tmvaReader_->AddVariable("inner_nMissingOuter",&tmva_inner_nMissingOuter_);
160  tmvaReader_->BookMVA("BDTG",mvaFilePath);
161  */
162 
163 
164 }
165 
166 DuplicateTrackMerger::~DuplicateTrackMerger()
167 {
168 
169  if(!useForestFromDB_) delete forest_;
170 
171 }
172 
173 
174 #ifdef VI_STAT
175  struct Stat {
176  Stat() : maxCos(1.1), nCand(0),nLoop0(0) {}
177  ~Stat() {
178  std::cout << "Stats " << nCand << ' ' << nLoop0 << ' ' << maxCos << std::endl;
179  }
180  std::atomic<float> maxCos;
181  std::atomic<int> nCand, nLoop0;
182  };
183  Stat stat;
184 #endif
185 
186 template<typename T>
187 void update_maximum(std::atomic<T>& maximum_value, T const& value) noexcept
188 {
189  T prev_value = maximum_value;
190  while(prev_value < value &&
191  !maximum_value.compare_exchange_weak(prev_value, value))
192  ;
193 }
194 
195  template<typename T>
196 void update_minimum(std::atomic<T>& minimum_value, T const& value) noexcept
197 {
198  T prev_value = minimum_value;
199  while(prev_value > value &&
200  !minimum_value.compare_exchange_weak(prev_value, value))
201  ;
202 }
203 
204 
205 void DuplicateTrackMerger::produce(edm::Event& iEvent, const edm::EventSetup& iSetup)
206 {
207 
208  merger_.init(iSetup);
209 
210  if(!forest_){
211  if(useForestFromDB_){
212  edm::ESHandle<GBRForest> forestHandle;
213  iSetup.get<GBRWrapperRcd>().get(forestLabel_,forestHandle);
214  forest_ = forestHandle.product();
215  }else{
216  TFile gbrfile(dbFileName_.c_str());
217  forest_ = dynamic_cast<const GBRForest*>(gbrfile.Get(forestLabel_.c_str()));
218  }
219  }
220 
221  //edm::Handle<edm::View<reco::Track> >handle;
223  iEvent.getByToken(trackSource_,handle);
224  auto const & tracks = *handle;
225 
226  iSetup.get<IdealMagneticFieldRecord>().get(magfield_);
228  TSCPBuilderNoMaterial tscpBuilder;
229  std::unique_ptr<std::vector<TrackCandidate> > out_duplicateCandidates(new std::vector<TrackCandidate>());
230 
231  std::unique_ptr<CandidateToDuplicate> out_candidateMap(new CandidateToDuplicate());
232 
233  for(int i = 0; i < (int)tracks.size(); i++){
234  const reco::Track *rt1 = &tracks[i];
235  if(rt1->innerMomentum().perp2() < minpT2_)continue;
236  // if(rt1->innerMomentum().R() < minP_)continue;
237  for(int j = i+1; j < (int)tracks.size();j++){
238  const reco::Track *rt2 = &tracks[j];
239  if(rt1->charge() != rt2->charge())continue;
240  auto cosT = (*rt1).momentum().unit().Dot((*rt2).momentum().unit());
241  if (cosT<0.) continue;
242  if(rt2->innerMomentum().perp2() < minpT2_)continue;
243  // if(rt2->innerMomentum().R() < minP_)continue;
244  const reco::Track* t1,*t2;
245  if(rt1->outerPosition().perp2() < rt2->outerPosition().perp2()){
246  t1 = rt1;
247  t2 = rt2;
248  }else{
249  t1 = rt2;
250  t2 = rt1;
251  }
252  auto deltaR3d2 = (t1->outerPosition() - t2->innerPosition()).mag2();
253 
254  if(t1->outerPosition().perp2() > t2->innerPosition().perp2()) deltaR3d2 *= -1.0;
255  if(deltaR3d2 < minDeltaR3d2_)continue;
256 
257  FreeTrajectoryState fts1 = trajectoryStateTransform::outerFreeState(*t1, &*magfield_,false);
258  FreeTrajectoryState fts2 = trajectoryStateTransform::innerFreeState(*t2, &*magfield_,false);
259  GlobalPoint avgPoint((t1->outerPosition().x()+t2->innerPosition().x())*0.5,(t1->outerPosition().y()+t2->innerPosition().y())*0.5,(t1->outerPosition().z()+t2->innerPosition().z())*0.5);
260  TrajectoryStateClosestToPoint TSCP1 = tscpBuilder(fts1, avgPoint);
261  TrajectoryStateClosestToPoint TSCP2 = tscpBuilder(fts2, avgPoint);
262  if(!TSCP1.isValid())continue;
263  if(!TSCP2.isValid())continue;
264 
265  const FreeTrajectoryState ftsn1 = TSCP1.theState();
266  const FreeTrajectoryState ftsn2 = TSCP2.theState();
267 
268  if ( (ftsn2.position()-ftsn1.position()).mag2() > maxDCA2_ ) continue;
269 
270  auto qoverp1 = ftsn1.signedInverseMomentum();
271  auto qoverp2 = ftsn2.signedInverseMomentum();
272  float tmva_dqoverp_ = qoverp1-qoverp2;
273  if ( std::abs(tmva_dqoverp_) > maxDQoP_ ) continue;
274 
275 
276  //auto pp = [&](TrajectoryStateClosestToPoint const & ts) { std::cout << ' ' << ts.perigeeParameters().vector()[0] << '/' << ts.perigeeError().transverseCurvatureError();};
277  //if(qoverp1*qoverp2 <0) { std::cout << "charge different " << qoverp1 <<',' << qoverp2; pp(TSCP1); pp(TSCP2); std::cout << std::endl;}
278 
279  auto lambda1 = M_PI/2 - ftsn1.momentum().theta();
280  auto lambda2 = M_PI/2 - ftsn2.momentum().theta();
281  float tmva_dlambda_ = lambda1-lambda2;
282  if ( std::abs(tmva_dlambda_) > maxDLambda_ ) continue;
283 
284  auto phi1 = ftsn1.momentum().phi();
285  auto phi2 = ftsn2.momentum().phi();
286  float tmva_dphi_ = phi1-phi2;
287  if(std::abs(tmva_dphi_) > float(M_PI)) tmva_dphi_ = 2.f*float(M_PI) - std::abs(tmva_dphi_);
288  if (std::abs(tmva_dphi_) > maxDPhi_ ) continue;
289 
290  auto dxy1 = (-ftsn1.position().x() * ftsn1.momentum().y() + ftsn1.position().y() * ftsn1.momentum().x())/TSCP1.pt();
291  auto dxy2 = (-ftsn2.position().x() * ftsn2.momentum().y() + ftsn2.position().y() * ftsn2.momentum().x())/TSCP2.pt();
292  float tmva_ddxy_ = dxy1-dxy2;
293  if ( std::abs(tmva_ddxy_) > maxDdxy_ ) continue;
294 
295  auto dsz1 = ftsn1.position().z() * TSCP1.pt() / TSCP1.momentum().mag()
296  - (ftsn1.position().x() * ftsn1.momentum().y() + ftsn1.position().y() * ftsn1.momentum().x())/TSCP1.pt() * ftsn1.momentum().z()/ftsn1.momentum().mag();
297  auto dsz2 = ftsn2.position().z() * TSCP2.pt() / TSCP2.momentum().mag()
298  - (ftsn2.position().x() * ftsn2.momentum().y() + ftsn2.position().y() * ftsn2.momentum().x())/TSCP2.pt() * ftsn2.momentum().z()/ftsn2.momentum().mag();
299  float tmva_ddsz_ = dsz1-dsz2;
300  if ( std::abs(tmva_ddsz_) > maxDdsz_ ) continue;
301 
302  float tmva_d3dr_ = avgPoint.perp();
303  float tmva_d3dz_ = avgPoint.z();
304  float tmva_outer_nMissingInner_ = t2->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_INNER_HITS);
305  float tmva_inner_nMissingOuter_ = t1->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS);
306 
307  float gbrVals_[9];
308  gbrVals_[0] = tmva_ddsz_;
309  gbrVals_[1] = tmva_ddxy_;
310  gbrVals_[2] = tmva_dphi_;
311  gbrVals_[3] = tmva_dlambda_;
312  gbrVals_[4] = tmva_dqoverp_;
313  gbrVals_[5] = tmva_d3dr_;
314  gbrVals_[6] = tmva_d3dz_;
315  gbrVals_[7] = tmva_outer_nMissingInner_;
316  gbrVals_[8] = tmva_inner_nMissingOuter_;
317 
318 
319  auto mvaBDTG = forest_->GetClassifier(gbrVals_);
320  if(mvaBDTG < minBDTG_)continue;
321 
322  // std::cout << "to merge " << mvaBDTG << ' ' << std::copysign(std::sqrt(std::abs(deltaR3d2)),deltaR3d2) << ' ' << tmva_dphi_ << ' ' << TSCP1.pt() <<'/'<<TSCP2.pt() << std::endl;
323 
324  out_duplicateCandidates->push_back(merger_.merge(*t1,*t2));
325  out_candidateMap->emplace_back(i,j);
326 
327 #ifdef VI_STAT
328  ++stat.nCand;
329  // auto cosT = float((*t1).momentum().unit().Dot((*t2).momentum().unit()));
330  if (cosT>0) update_minimum(stat.maxCos,float(cosT));
331  else ++stat.nLoop0;
332 #endif
333 
334  }
335  }
336  iEvent.put(std::move(out_duplicateCandidates),"candidates");
337  iEvent.put(std::move(out_candidateMap),"candidateMap");
338 
339 
340 }
341 
342 
343 
344 }
345 
348 
T getParameter(std::string const &) const
int i
Definition: DBlmapReader.cc:9
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:462
const FreeTrajectoryState & theState() const
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
static void fillDescriptions(ConfigurationDescriptions &descriptions)
T y() const
Definition: PV3DBase.h:63
#define noexcept
#define nullptr
const math::XYZPoint & outerPosition() const
position of the outermost hit
Definition: Track.h:65
Geom::Theta< T > theta() const
Definition: PV3DBase.h:75
const math::XYZPoint & innerPosition() const
position of the innermost hit
Definition: Track.h:55
int iEvent
Definition: GenABIO.cc:230
T mag() const
Definition: PV3DBase.h:67
auto const T2 &decltype(t1.eta()) t2
Definition: deltaR.h:16
OrphanHandle< PROD > put(std::auto_ptr< PROD > product)
Put a new product.
Definition: Event.h:121
T z() const
Definition: PV3DBase.h:64
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
def move
Definition: eostools.py:510
tuple handle
Definition: patZpeak.py:22
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
int j
Definition: DBlmapReader.cc:9
ParameterDescriptionBase * add(U const &iLabel, T const &value)
GlobalVector momentum() const
#define M_PI
GlobalPoint position() const
const HitPattern & hitPattern() const
Access the hit pattern, indicating in which Tracker layers the track has hits.
Definition: TrackBase.h:445
tuple tracks
Definition: testEve_cfg.py:39
const T & get() const
Definition: EventSetup.h:56
T const * product() const
Definition: ESHandle.h:86
int numberOfLostHits(HitCategory category) const
Definition: HitPattern.h:902
const math::XYZVector & innerMomentum() const
momentum vector at the innermost hit position
Definition: Track.h:60
tuple cout
Definition: gather_cfg.py:145
int charge() const
track electric charge
Definition: TrackBase.h:562
FreeTrajectoryState innerFreeState(const reco::Track &tk, const MagneticField *field, bool withErr=true)
long double T
T x() const
Definition: PV3DBase.h:62
FreeTrajectoryState outerFreeState(const reco::Track &tk, const MagneticField *field, bool withErr=true)
double signedInverseMomentum() const