CMS 3D CMS Logo

OniaPhotonConversionProducer.cc
Go to the documentation of this file.
8 
12 
15 
17 
18 #include <TMath.h>
19 #include <boost/foreach.hpp>
20 #include <vector>
21 
22 
23 // to order from high to low ProbChi2
25  return TMath::Prob(c1.conversionVertex().chi2(),c1.conversionVertex().ndof()) > TMath::Prob(c2.conversionVertex().chi2(),c2.conversionVertex().ndof());
26 }
27 
28 
30  bool atLeastOneInCommon=false;
31  BOOST_FOREACH(const edm::RefToBase<reco::Track> tk1, c1.tracks()){
32  BOOST_FOREACH(const edm::RefToBase<reco::Track> tk2, c2.tracks()){
33  if(tk1==tk2){
34  atLeastOneInCommon=true;
35  break;
36  }
37  }
38  }
39  return atLeastOneInCommon;
40 }
41 
42 bool lt_(std::pair<double,short> a, std::pair<double,short> b) {
43  return a.first < b.first; }
44 
45 // define operator== for conversions, those with at least one track in common
46 namespace reco {
47  bool operator==(const reco::Conversion& c1, const reco::Conversion& c2) {
48  return c1.tracks()[0] == c2.tracks()[0] ||
49  c1.tracks()[1] == c2.tracks()[1] ||
50  c1.tracks()[1] == c2.tracks()[0] ||
51  c1.tracks()[0] == c2.tracks()[1] ;
52  }
53 }
54 
56  convCollectionToken_ = consumes<reco::ConversionCollection>(ps.getParameter<edm::InputTag>("conversions"));
57  thePVsToken_ = consumes<reco::VertexCollection>(ps.getParameter<edm::InputTag>("primaryVertexTag"));
58 
59  wantTkVtxCompatibility_ = ps.getParameter<bool>("wantTkVtxCompatibility");
60  sigmaTkVtxComp_ = ps.getParameter<uint32_t>("sigmaTkVtxComp");
61  wantCompatibleInnerHits_ = ps.getParameter<bool>("wantCompatibleInnerHits");
62  TkMinNumOfDOF_ = ps.getParameter<uint32_t>("TkMinNumOfDOF");
63 
64  wantHighpurity_ = ps.getParameter<bool>("wantHighpurity");
65  _vertexChi2ProbCut = ps.getParameter<double>("vertexChi2ProbCut");
66  _trackchi2Cut = ps.getParameter<double>("trackchi2Cut");
67  _minDistanceOfApproachMinCut = ps.getParameter<double>("minDistanceOfApproachMinCut");
68  _minDistanceOfApproachMaxCut = ps.getParameter<double>("minDistanceOfApproachMaxCut");
69 
70  pfCandidateCollectionToken_ = consumes<reco::PFCandidateCollection>(ps.getParameter<edm::InputTag>("pfcandidates"));
71 
72  pi0OnlineSwitch_ = ps.getParameter<bool>("pi0OnlineSwitch");
73  pi0SmallWindow_ = ps.getParameter<std::vector<double> >("pi0SmallWindow");
74  pi0LargeWindow_ = ps.getParameter<std::vector<double> >("pi0LargeWindow");
75 
76  std::string algo = ps.getParameter<std::string>("convAlgo");
77  convAlgo_ = StringToEnumValue<reco::Conversion::ConversionAlgorithm>(algo);
78 
79  std::vector<std::string> qual = ps.getParameter<std::vector<std::string> >("convQuality");
80  if( qual[0] != "" ) convQuality_ =StringToEnumValue<reco::Conversion::ConversionQuality>(qual);
81 
82  convSelectionCuts_ = ps.getParameter<std::string>("convSelection");
83 
84  produces<pat::CompositeCandidateCollection>("conversions");
85 
86  total_conversions = 0;
87  selection_fail = 0;
88  algo_fail = 0;
89  flag_fail = 0;
90  pizero_fail = 0;
91  duplicates = 0;
92  TkVtxC = 0;
93  CInnerHits = 0;
94  highpurity_count = 0;
95  final_conversion = 0;
96  store_conversion = 0;
97 }
98 
99 
101 
102  std::unique_ptr<reco::ConversionCollection> outCollection(new reco::ConversionCollection);
103  std::unique_ptr<pat::CompositeCandidateCollection> patoutCollection(new pat::CompositeCandidateCollection);
104 
106  event.getByToken(thePVsToken_, priVtxs);
107 
109  event.getByToken(convCollectionToken_,pConv);
110 
112  event.getByToken(pfCandidateCollectionToken_,pfcandidates);
113 
114  const reco::PFCandidateCollection pfphotons = selectPFPhotons(*pfcandidates);
115 
117 
118  for(reco::ConversionCollection::const_iterator conv = pConv->begin(); conv != pConv->end(); ++conv){
119  total_conversions++;
120 
121  if (! ( *convSelection_)(*conv)){
122  selection_fail++;
123  continue; // selection string
124  }
125  if (convAlgo_ != 0 && conv->algo()!= convAlgo_){
126  algo_fail++;
127  continue; // select algorithm
128  }
129  if(convQuality_.size() > 0){
130  bool flagsok=true;
131  for (std::vector<int>::const_iterator flag = convQuality_.begin(); flag!=convQuality_.end(); ++flag){
133  if (!conv->quality(q)) {
134  flagsok=false;
135  break;
136  }
137  }
138  if (!flagsok){
139  flag_fail++;
140  continue;
141  }
142  }
143  outCollection->push_back(*conv);
144  }
145 
146  removeDuplicates(*outCollection);
147 
148  for (reco::ConversionCollection::const_iterator conv = outCollection->begin(); conv != outCollection->end(); ++conv){
149 
150  bool flag1 = true;
151  bool flag2 = true;
152  bool flag3 = true;
153  bool flag4 = true;
154 
155  // The logic implies that by default this flags are true and if the check are not wanted conversions are saved.
156  // If checks are required and failed then don't save the conversion.
157 
158  bool flagTkVtxCompatibility = true;
159  if (! checkTkVtxCompatibility(*conv,*priVtxs.product())) {
160  flagTkVtxCompatibility = false;
161  if (wantTkVtxCompatibility_) {
162  TkVtxC++;
163  flag1 = false;
164  }
165  }
166  bool flagCompatibleInnerHits = false;
167  if (conv->tracks().size()==2) {
168  reco::HitPattern hitPatA=conv->tracks().at(0)->hitPattern();
169  reco::HitPattern hitPatB=conv->tracks().at(1)->hitPattern();
170  if ( foundCompatibleInnerHits(hitPatA,hitPatB) && foundCompatibleInnerHits(hitPatB,hitPatA) ) flagCompatibleInnerHits = true;
171  }
172  if (wantCompatibleInnerHits_ && ! flagCompatibleInnerHits) {
173  CInnerHits++;
174  flag2 = false;
175  }
176  bool flagHighpurity = true;
177  if (!HighpuritySubset(*conv,*priVtxs.product())) {
178  flagHighpurity = false;
179  if (wantHighpurity_) {
180  highpurity_count++;
181  flag3 = false;
182  }
183  }
184  bool pizero_rejected = false;
185  bool large_pizero_window = CheckPi0(*conv, pfphotons, pizero_rejected);
186  if (pi0OnlineSwitch_ && pizero_rejected) {
187  pizero_fail++;
188  flag4 = false;
189  }
190 
191  int flags = 0;
192  if (flag1 && flag2 && flag3 && flag4){
193  flags = PackFlags(*conv,flagTkVtxCompatibility,flagCompatibleInnerHits,flagHighpurity,pizero_rejected,large_pizero_window);
194  pat::CompositeCandidate *pat_conv = makePhotonCandidate(*conv);
195  pat_conv->addUserInt("flags",flags);
196  patoutCollection->push_back(*pat_conv);
197  final_conversion++;
198  }
199  }
200  store_conversion += patoutCollection->size();
201  event.put(std::move(patoutCollection),"conversions");
202 
203  delete convSelection_;
204 }
205 
206 int OniaPhotonConversionProducer::PackFlags(const reco::Conversion& conv, bool flagTkVtxCompatibility,
207  bool flagCompatibleInnerHits, bool flagHighpurity,
208  bool pizero_rejected, bool large_pizero_window ) {
209  int flags = 0;
210  if ( flagTkVtxCompatibility ) flags += 1;
211  if ( flagCompatibleInnerHits ) flags += 2;
212  if ( flagHighpurity ) flags += 4;
213  if ( pizero_rejected ) flags += 8;
214  if ( large_pizero_window ) flags += 16;
215 
216  flags += (conv.algo()*32);
217  int q_mask = 0;
218  std::vector<std::string> s_quals;
219  s_quals.push_back("generalTracksOnly");
220  s_quals.push_back("arbitratedEcalSeeded");
221  s_quals.push_back("arbitratedMerged");
222  s_quals.push_back("arbitratedMergedEcalGeneral");
223  s_quals.push_back("highPurity");
224  s_quals.push_back("highEfficiency");
225  s_quals.push_back("ecalMatched1Track");
226  s_quals.push_back("ecalMatched2Track");
227  std::vector<int> i_quals = StringToEnumValue<reco::Conversion::ConversionQuality>(s_quals);
228  for (std::vector<int>::const_iterator qq = i_quals.begin(); qq!=i_quals.end(); ++qq) {
230  if (conv.quality(q)) q_mask = *qq;
231  }
232  flags += (q_mask*32*8);
233  return flags;
234 }
235 
240  // first sort from high to low chi2 prob
241  std::sort(c.begin(),c.end(),ConversionLessByChi2);
242  int iter1 = 0;
243  // Cycle over all the elements of the collection and compare to all the following,
244  // if two elements have at least one track in common delete the element with the lower chi2
245  while(iter1 < (( (int) c.size() ) - 1) ){
246  int iter2 = iter1+1;
247  while( iter2 < (int) c.size()) if(ConversionEqualByTrack( c[iter1], c[iter2] ) ){
248  c.erase( c.begin() + iter2 );
249  duplicates++;
250  }else{
251  iter2++; // Increment index only if this element is no duplicate.
252  // If it is duplicate check again the same index since the vector rearranged elements index after erasing
253  }
254  iter1++;
255  }
256 }
257 
259  std::vector< std::pair< double, short> > idx[2];
260  short ik=-1;
261  BOOST_FOREACH(edm::RefToBase<reco::Track> tk, conv.tracks()){
262  ik++;
263  short count=-1;
264  BOOST_FOREACH(const reco::Vertex& vtx,priVtxs){
265  count++;
266 
267  double dz_= tk->dz(vtx.position());
268  double dzError_=tk->dzError();
269  dzError_=sqrt(dzError_*dzError_+vtx.covariance(2,2));
270 
271  if(fabs(dz_)/dzError_ > sigmaTkVtxComp_) continue;
272 
273  idx[ik].push_back(std::pair<double,short>(fabs(dz_),count));
274  }
275  if(idx[ik].size()==0) {return false;}
276 
277  std::stable_sort(idx[ik].begin(),idx[ik].end(),lt_);
278  }
279  if (idx[0][0].second==idx[1][0].second || idx[0][1].second==idx[1][0].second || idx[0][0].second==idx[1][1].second) return true;
280  return false;
281 }
282 
284  size_t count=0;
285  uint32_t oldSubStr=0;
286  for (int i=0; i<hitPatA.numberOfHits(reco::HitPattern::HitCategory::TRACK_HITS) && count<2; i++) {
287  uint32_t hitA = hitPatA.getHitPattern(reco::HitPattern::HitCategory::TRACK_HITS,i);
288  if (!hitPatA.validHitFilter(hitA) || !hitPatA.trackerHitFilter(hitA)) continue;
289 
290  if(hitPatA.getSubStructure(hitA)==oldSubStr && hitPatA.getLayer(hitA)==oldSubStr)
291  continue;
292 
293  if(hitPatB.getTrackerMonoStereo(reco::HitPattern::HitCategory::TRACK_HITS,hitPatA.getSubStructure(hitA),hitPatA.getLayer(hitA)) != 0)
294  return true;
295 
296  oldSubStr=hitPatA.getSubStructure(hitA);
297  count++;
298  }
299  return false;
300 }
301 
304  // select high purity conversions our way:
305  // vertex chi2 cut
306  if(ChiSquaredProbability(conv.conversionVertex().chi2(),conv.conversionVertex().ndof())< _vertexChi2ProbCut) return false;
307 
308  // d0 cut
309  // Find closest primary vertex
310  int closest_pv_index = 0;
311  int i=0;
312  BOOST_FOREACH(const reco::Vertex& vtx,priVtxs){
313  if( conv.zOfPrimaryVertexFromTracks( vtx.position() ) < conv.zOfPrimaryVertexFromTracks( priVtxs[closest_pv_index].position() ) ) closest_pv_index = i;
314  i++;
315  }
316  // Now check impact parameter wtr with the just found closest primary vertex
317  BOOST_FOREACH(const edm::RefToBase<reco::Track> tk, conv.tracks()) if(-tk->dxy(priVtxs[closest_pv_index].position())*tk->charge()/tk->dxyError()<0) return false;
318 
319  // chi2 of single tracks
320  BOOST_FOREACH(const edm::RefToBase<reco::Track> tk, conv.tracks()) if(tk->normalizedChi2() > _trackchi2Cut) return false;
321 
322  // dof for each track
323  BOOST_FOREACH(const edm::RefToBase<reco::Track> tk, conv.tracks()) if(tk->ndof()< TkMinNumOfDOF_) return false;
324 
325  // distance of approach cut
326  if (conv.distOfMinimumApproach() < _minDistanceOfApproachMinCut || conv.distOfMinimumApproach() > _minDistanceOfApproachMaxCut ) return false;
327 
328  return true;
329 }
330 
332 
334  photonCand->setP4(convertVector(conv.refittedPair4Momentum()));
335  photonCand->setVertex(conv.conversionVertex().position());
336 
337  photonCand->addUserData<reco::Track>( "track0", *conv.tracks()[0] );
338  photonCand->addUserData<reco::Track>( "track1", *conv.tracks()[1] );
339 
340  return photonCand;
341 
342 }
343 
344 // create a collection of PF photons
346  reco::PFCandidateCollection pfphotons;
347  for (reco::PFCandidateCollection::const_iterator cand = pfcandidates.begin(); cand != pfcandidates.end(); ++cand){
348  if (cand->particleId() == reco::PFCandidate::gamma) pfphotons.push_back(*cand);
349  }
350  return pfphotons;
351 }
352 
354  bool &pizero_rejected ) {
355  // 2 windows are defined for Pi0 rejection, Conversions that, paired with others photons from the event, have an
356  // invariant mass inside the "small" window will be pizero_rejected and those that falls in the large window will
357  // be CheckPi0.
358  bool check_small = false;
359  bool check_large = false;
360 
361  float small1 = pi0SmallWindow_[0];
362  float small2 = pi0SmallWindow_[1];
363  float large1 = pi0LargeWindow_[0];
364  float large2 = pi0LargeWindow_[1];
365  for (reco::PFCandidateCollection::const_iterator photon = photons.begin(); photon!=photons.end(); ++photon) {
366  float inv = (conv.refittedPair4Momentum() + photon->p4()).M();
367  if (inv > large1 && inv < large2) {
368  check_large = true;
369  if (inv > small1 && inv < small2) {
370  check_small = true;
371  break;
372  }
373  }
374  }
375  pizero_rejected = check_small;
376  return check_large;
377 }
378 
380  return reco::Candidate::LorentzVector(v.x(),v.y(), v.z(), v.t());
381 }
382 
383 
385  std::cout << "############################" << std::endl;
386  std::cout << "Conversion Candidate producer report" << std::endl;
387  std::cout << "############################" << std::endl;
388  std::cout << "Total examined conversions: " << total_conversions << std::endl;
389  std::cout << "Selection fail candidates: " << selection_fail << std::endl;
390  std::cout << "Algo fail candidates: " << algo_fail << std::endl;
391  std::cout << "Quality fail candidates: " << flag_fail << std::endl;
392  std::cout << "Pi0 fail: " << pizero_fail << std::endl;
393  std::cout << "Total duplicates found: " << duplicates << std::endl;
394  std::cout << "Vertex compatibility fail: " << TkVtxC << std::endl;
395  std::cout << "Compatible inner hits fail: " << CInnerHits << std::endl;
396  std::cout << "Highpurity Subset fail: " << highpurity_count << std::endl;
397  std::cout << "############################" << std::endl;
398  std::cout << "Final number of conversions: " << final_conversion << std::endl;
399  std::cout << "Stored number of conversions: " << store_conversion << std::endl;
400  std::cout << "############################" << std::endl;
401 }
402 //define this as a plug-in
size
Write out results.
const reco::Vertex & conversionVertex() const
returns the reco conversion vertex
Definition: Conversion.h:97
Analysis-level particle class.
T getParameter(std::string const &) const
int i
Definition: DBlmapReader.cc:9
static uint32_t getLayer(uint16_t pattern)
Definition: HitPattern.h:700
bool foundCompatibleInnerHits(const reco::HitPattern &hitPatA, const reco::HitPattern &hitPatB)
ConversionAlgorithm algo() const
Definition: Conversion.h:223
double normalizedChi2() const
chi-squared divided by n.d.o.f. (or chi-squared * 1e6 if n.d.o.f. is zero)
Definition: TrackBase.h:556
static HepMC::IO_HEPEVT conv
double dxyError() const
error on dxy
Definition: TrackBase.h:791
bool quality(ConversionQuality q) const
Definition: Conversion.h:181
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
reco::Candidate::LorentzVector convertVector(const math::XYZTLorentzVectorF &)
uint16_t getTrackerMonoStereo(HitCategory category, uint16_t substr, uint16_t layer) const
Definition: HitPattern.cc:460
double zOfPrimaryVertexFromTracks(const math::XYZPoint &myBeamSpot=math::XYZPoint()) const
Definition: Conversion.h:145
double distOfMinimumApproach() const
Definition: Conversion.h:125
bool HighpuritySubset(const reco::Conversion &, const reco::VertexCollection &)
std::vector< Variable::Flags > flags
Definition: MVATrainer.cc:135
std::vector< Vertex > VertexCollection
collection of Vertex objects
Definition: VertexFwd.h:9
bool ConversionLessByChi2(const reco::Conversion &c1, const reco::Conversion &c2)
double covariance(int i, int j) const
(i, j)-th element of error matrix, i, j = 0, ... 2
Definition: Vertex.h:130
const Point & position() const
position
Definition: Vertex.h:109
std::vector< Conversion > ConversionCollection
collectin of Conversion objects
Definition: ConversionFwd.h:9
static bool validHitFilter(uint16_t pattern)
Definition: HitPattern.h:787
U second(std::pair< T, U > const &p)
virtual void produce(edm::Event &event, const edm::EventSetup &esetup)
bool operator==(const reco::Conversion &c1, const reco::Conversion &c2)
bool ConversionEqualByTrack(const reco::Conversion &c1, const reco::Conversion &c2)
bool checkTkVtxCompatibility(const reco::Conversion &, const reco::VertexCollection &)
double ndof() const
number of degrees of freedom of the fit
Definition: TrackBase.h:550
T sqrt(T t)
Definition: SSEVec.h:18
int PackFlags(const reco::Conversion &, bool, bool, bool, bool, bool)
double chi2() const
chi-squares
Definition: Vertex.h:98
float ChiSquaredProbability(double chiSquared, double nrDOF)
#define end
Definition: vmac.h:37
virtual void setVertex(const Point &vertex)
set vertex
void addUserInt(const std::string &label, int32_t data, const bool overwrite=false)
Set user-defined int.
Definition: PATObject.h:855
static uint32_t getSubStructure(uint16_t pattern)
Definition: HitPattern.h:691
double ndof() const
Definition: Vertex.h:105
const reco::PFCandidateCollection selectPFPhotons(const reco::PFCandidateCollection &)
OniaPhotonConversionProducer(const edm::ParameterSet &ps)
double dz() const
dz parameter (= dsz/cos(lambda)). This is the track z0 w.r.t (0,0,0) only if the refPoint is close to...
Definition: TrackBase.h:604
double dzError() const
error on dz
Definition: TrackBase.h:809
math::XYZTLorentzVectorF refittedPair4Momentum() const
Conversion track pair 4-momentum from the tracks refitted with vertex constraint. ...
Definition: Conversion.cc:235
bool lt_(std::pair< double, short > a, std::pair< double, short > b)
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
static bool trackerHitFilter(uint16_t pattern)
Definition: HitPattern.h:677
std::vector< CompositeCandidate > CompositeCandidateCollection
T const * product() const
Definition: Handle.h:81
double b
Definition: hdecay.h:120
virtual void setP4(const LorentzVector &p4) final
set 4-momentum
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:37
fixed size matrix
#define begin
Definition: vmac.h:30
bool CheckPi0(const reco::Conversion &, const reco::PFCandidateCollection &, bool &)
pat::CompositeCandidate * makePhotonCandidate(const reco::Conversion &)
double a
Definition: hdecay.h:121
int charge() const
track electric charge
Definition: TrackBase.h:562
void removeDuplicates(reco::ConversionCollection &)
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< float > > XYZTLorentzVectorF
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:22
uint16_t getHitPattern(HitCategory category, int position) const
Definition: HitPattern.h:515
double dxy() const
dxy parameter. (This is the transverse impact parameter w.r.t. to (0,0,0) ONLY if refPoint is close t...
Definition: TrackBase.h:586
void addUserData(const std::string &label, const T &data, bool transientOnly=false, bool overwrite=false)
Definition: PATObject.h:309
def move(src, dest)
Definition: eostools.py:510
std::vector< edm::RefToBase< reco::Track > > const & tracks() const
vector of track to base references
Definition: Conversion.cc:176
Definition: event.py:1
int numberOfHits(HitCategory category) const
Definition: HitPattern.h:807