CMS 3D CMS Logo

OniaPhotonConversionProducer.cc
Go to the documentation of this file.
8 
11 
14 
16 
17 #include <TMath.h>
18 #include <vector>
19 
20 
21 // to order from high to low ProbChi2
23  return TMath::Prob(c1.conversionVertex().chi2(),c1.conversionVertex().ndof()) > TMath::Prob(c2.conversionVertex().chi2(),c2.conversionVertex().ndof());
24 }
25 
26 
28  bool atLeastOneInCommon=false;
29  for(auto const& tk1 : c1.tracks()){
30  for(auto const& tk2 : c2.tracks()){
31  if(tk1==tk2){
32  atLeastOneInCommon=true;
33  break;
34  }
35  }
36  }
37  return atLeastOneInCommon;
38 }
39 
40 bool lt_(std::pair<double,short> a, std::pair<double,short> b) {
41  return a.first < b.first; }
42 
43 // define operator== for conversions, those with at least one track in common
44 namespace reco {
45  bool operator==(const reco::Conversion& c1, const reco::Conversion& c2) {
46  return c1.tracks()[0] == c2.tracks()[0] ||
47  c1.tracks()[1] == c2.tracks()[1] ||
48  c1.tracks()[1] == c2.tracks()[0] ||
49  c1.tracks()[0] == c2.tracks()[1] ;
50  }
51 }
52 
54  convCollectionToken_ = consumes<reco::ConversionCollection>(ps.getParameter<edm::InputTag>("conversions"));
55  thePVsToken_ = consumes<reco::VertexCollection>(ps.getParameter<edm::InputTag>("primaryVertexTag"));
56 
57  wantTkVtxCompatibility_ = ps.getParameter<bool>("wantTkVtxCompatibility");
58  sigmaTkVtxComp_ = ps.getParameter<uint32_t>("sigmaTkVtxComp");
59  wantCompatibleInnerHits_ = ps.getParameter<bool>("wantCompatibleInnerHits");
60  TkMinNumOfDOF_ = ps.getParameter<uint32_t>("TkMinNumOfDOF");
61 
62  wantHighpurity_ = ps.getParameter<bool>("wantHighpurity");
63  _vertexChi2ProbCut = ps.getParameter<double>("vertexChi2ProbCut");
64  _trackchi2Cut = ps.getParameter<double>("trackchi2Cut");
65  _minDistanceOfApproachMinCut = ps.getParameter<double>("minDistanceOfApproachMinCut");
66  _minDistanceOfApproachMaxCut = ps.getParameter<double>("minDistanceOfApproachMaxCut");
67 
68  pfCandidateCollectionToken_ = consumes<reco::PFCandidateCollection>(ps.getParameter<edm::InputTag>("pfcandidates"));
69 
70  pi0OnlineSwitch_ = ps.getParameter<bool>("pi0OnlineSwitch");
71  pi0SmallWindow_ = ps.getParameter<std::vector<double> >("pi0SmallWindow");
72  pi0LargeWindow_ = ps.getParameter<std::vector<double> >("pi0LargeWindow");
73 
74  std::string algo = ps.getParameter<std::string>("convAlgo");
75  convAlgo_ = StringToEnumValue<reco::Conversion::ConversionAlgorithm>(algo);
76 
77  std::vector<std::string> qual = ps.getParameter<std::vector<std::string> >("convQuality");
78  if( !qual[0].empty() ) convQuality_ =StringToEnumValue<reco::Conversion::ConversionQuality>(qual);
79 
80  convSelectionCuts_ = ps.getParameter<std::string>("convSelection");
81  convSelection_ = std::make_unique<StringCutObjectSelector<reco::Conversion>>(convSelectionCuts_);
82  produces<pat::CompositeCandidateCollection>("conversions");
83 }
84 
86 
87  std::unique_ptr<reco::ConversionCollection> outCollection(new reco::ConversionCollection);
88  std::unique_ptr<pat::CompositeCandidateCollection> patoutCollection(new pat::CompositeCandidateCollection);
89 
91  event.getByToken(thePVsToken_, priVtxs);
92 
94  event.getByToken(convCollectionToken_,pConv);
95 
97  event.getByToken(pfCandidateCollectionToken_,pfcandidates);
98 
99  const reco::PFCandidateCollection pfphotons = selectPFPhotons(*pfcandidates);
100 
101  for(reco::ConversionCollection::const_iterator conv = pConv->begin(); conv != pConv->end(); ++conv){
102 
103  if (! ( *convSelection_)(*conv)){
104  continue; // selection string
105  }
106  if (convAlgo_ != 0 && conv->algo()!= convAlgo_){
107  continue; // select algorithm
108  }
109  if(!convQuality_.empty()){
110  bool flagsok=true;
111  for (std::vector<int>::const_iterator flag = convQuality_.begin(); flag!=convQuality_.end(); ++flag){
113  if (!conv->quality(q)) {
114  flagsok=false;
115  break;
116  }
117  }
118  if (!flagsok){
119  continue;
120  }
121  }
122  outCollection->push_back(*conv);
123  }
124 
125  removeDuplicates(*outCollection);
126 
127  for (reco::ConversionCollection::const_iterator conv = outCollection->begin(); conv != outCollection->end(); ++conv){
128 
129  bool flag1 = true;
130  bool flag2 = true;
131  bool flag3 = true;
132  bool flag4 = true;
133 
134  // The logic implies that by default this flags are true and if the check are not wanted conversions are saved.
135  // If checks are required and failed then don't save the conversion.
136 
137  bool flagTkVtxCompatibility = true;
138  if (! checkTkVtxCompatibility(*conv,*priVtxs.product())) {
139  flagTkVtxCompatibility = false;
140  if (wantTkVtxCompatibility_) {
141  flag1 = false;
142  }
143  }
144  bool flagCompatibleInnerHits = false;
145  if (conv->tracks().size()==2) {
146  reco::HitPattern hitPatA=conv->tracks().at(0)->hitPattern();
147  reco::HitPattern hitPatB=conv->tracks().at(1)->hitPattern();
148  if ( foundCompatibleInnerHits(hitPatA,hitPatB) && foundCompatibleInnerHits(hitPatB,hitPatA) ) flagCompatibleInnerHits = true;
149  }
150  if (wantCompatibleInnerHits_ && ! flagCompatibleInnerHits) {
151  flag2 = false;
152  }
153  bool flagHighpurity = true;
154  if (!HighpuritySubset(*conv,*priVtxs.product())) {
155  flagHighpurity = false;
156  if (wantHighpurity_) {
157  flag3 = false;
158  }
159  }
160  bool pizero_rejected = false;
161  bool large_pizero_window = CheckPi0(*conv, pfphotons, pizero_rejected);
162  if (pi0OnlineSwitch_ && pizero_rejected) {
163  flag4 = false;
164  }
165 
166  int flags = 0;
167  if (flag1 && flag2 && flag3 && flag4){
168  flags = PackFlags(*conv,flagTkVtxCompatibility,flagCompatibleInnerHits,flagHighpurity,pizero_rejected,large_pizero_window);
169  std::unique_ptr<pat::CompositeCandidate> pat_conv(makePhotonCandidate(*conv));
170  pat_conv->addUserInt("flags",flags);
171  patoutCollection->push_back(*pat_conv);
172  }
173  }
174  event.put(std::move(patoutCollection),"conversions");
175 }
176 
177 int OniaPhotonConversionProducer::PackFlags(const reco::Conversion& conv, bool flagTkVtxCompatibility,
178  bool flagCompatibleInnerHits, bool flagHighpurity,
179  bool pizero_rejected, bool large_pizero_window ) {
180  int flags = 0;
181  if ( flagTkVtxCompatibility ) flags += 1;
182  if ( flagCompatibleInnerHits ) flags += 2;
183  if ( flagHighpurity ) flags += 4;
184  if ( pizero_rejected ) flags += 8;
185  if ( large_pizero_window ) flags += 16;
186 
187  flags += (conv.algo()*32);
188  int q_mask = 0;
189  std::vector<std::string> s_quals;
190  s_quals.push_back("generalTracksOnly");
191  s_quals.push_back("arbitratedEcalSeeded");
192  s_quals.push_back("arbitratedMerged");
193  s_quals.push_back("arbitratedMergedEcalGeneral");
194  s_quals.push_back("highPurity");
195  s_quals.push_back("highEfficiency");
196  s_quals.push_back("ecalMatched1Track");
197  s_quals.push_back("ecalMatched2Track");
198  std::vector<int> i_quals = StringToEnumValue<reco::Conversion::ConversionQuality>(s_quals);
199  for (std::vector<int>::const_iterator qq = i_quals.begin(); qq!=i_quals.end(); ++qq) {
201  if (conv.quality(q)) q_mask = *qq;
202  }
203  flags += (q_mask*32*8);
204  return flags;
205 }
206 
211  // first sort from high to low chi2 prob
212  std::sort(c.begin(),c.end(),ConversionLessByChi2);
213  int iter1 = 0;
214  // Cycle over all the elements of the collection and compare to all the following,
215  // if two elements have at least one track in common delete the element with the lower chi2
216  while(iter1 < (( (int) c.size() ) - 1) ){
217  int iter2 = iter1+1;
218  while( iter2 < (int) c.size()) if(ConversionEqualByTrack( c[iter1], c[iter2] ) ){
219  c.erase( c.begin() + iter2 );
220  }else{
221  iter2++; // Increment index only if this element is no duplicate.
222  // If it is duplicate check again the same index since the vector rearranged elements index after erasing
223  }
224  iter1++;
225  }
226 }
227 
229  std::vector< std::pair< double, short> > idx[2];
230  short ik=-1;
231  for(auto const& tk : conv.tracks()){
232  ik++;
233  short count=-1;
234  for(auto const& vtx : priVtxs){
235  count++;
236 
237  double dz_= tk->dz(vtx.position());
238  double dzError_=tk->dzError();
239  dzError_=sqrt(dzError_*dzError_+vtx.covariance(2,2));
240  if(fabs(dz_)/dzError_ > sigmaTkVtxComp_) continue;
241  idx[ik].push_back(std::pair<double,short>(fabs(dz_),count));
242  }
243  if (idx[ik].empty()) return false;
244  if (idx[ik].size()>1) std::stable_sort(idx[ik].begin(),idx[ik].end(),lt_);
245  }
246  if (ik!=1) return false;
247  if (idx[0][0].second==idx[1][0].second) return true;
248  if (idx[0].size()>1 && idx[0][1].second==idx[1][0].second) return true;
249  if (idx[1].size()>1 && idx[0][0].second==idx[1][1].second) return true;
250 
251  return false;
252 }
253 
255  size_t count=0;
256  uint32_t oldSubStr=0;
257  for (int i=0; i<hitPatA.numberOfAllHits(reco::HitPattern::HitCategory::TRACK_HITS) && count<2; i++) {
258  uint32_t hitA = hitPatA.getHitPattern(reco::HitPattern::HitCategory::TRACK_HITS,i);
259  if (!hitPatA.validHitFilter(hitA) || !hitPatA.trackerHitFilter(hitA)) continue;
260 
261  if(hitPatA.getSubStructure(hitA)==oldSubStr && hitPatA.getLayer(hitA)==oldSubStr)
262  continue;
263 
264  if(hitPatB.getTrackerMonoStereo(reco::HitPattern::HitCategory::TRACK_HITS,hitPatA.getSubStructure(hitA),hitPatA.getLayer(hitA)) != 0)
265  return true;
266 
267  oldSubStr=hitPatA.getSubStructure(hitA);
268  count++;
269  }
270  return false;
271 }
272 
275  // select high purity conversions our way:
276  // vertex chi2 cut
277  if(ChiSquaredProbability(conv.conversionVertex().chi2(),conv.conversionVertex().ndof())< _vertexChi2ProbCut) return false;
278 
279  // d0 cut
280  // Find closest primary vertex
281  int closest_pv_index = 0;
282  int i=0;
283  for(auto const& vtx : priVtxs){
284  if( conv.zOfPrimaryVertexFromTracks( vtx.position() ) < conv.zOfPrimaryVertexFromTracks( priVtxs[closest_pv_index].position() ) ) closest_pv_index = i;
285  i++;
286  }
287  // Now check impact parameter wtr with the just found closest primary vertex
288  for(auto const& tk : conv.tracks()) if(-tk->dxy(priVtxs[closest_pv_index].position())*tk->charge()/tk->dxyError()<0) return false;
289 
290  // chi2 of single tracks
291  for(auto const& tk : conv.tracks()) if(tk->normalizedChi2() > _trackchi2Cut) return false;
292 
293  // dof for each track
294  for(auto const& tk : conv.tracks()) if(tk->ndof()< TkMinNumOfDOF_) return false;
295 
296  // distance of approach cut
297  if (conv.distOfMinimumApproach() < _minDistanceOfApproachMinCut || conv.distOfMinimumApproach() > _minDistanceOfApproachMaxCut ) return false;
298 
299  return true;
300 }
301 
303 
305  photonCand->setP4(convertVector(conv.refittedPair4Momentum()));
306  photonCand->setVertex(conv.conversionVertex().position());
307 
308  photonCand->addUserData<reco::Track>( "track0", *conv.tracks()[0] );
309  photonCand->addUserData<reco::Track>( "track1", *conv.tracks()[1] );
310 
311  return photonCand;
312 
313 }
314 
315 // create a collection of PF photons
317  reco::PFCandidateCollection pfphotons;
318  for (reco::PFCandidateCollection::const_iterator cand = pfcandidates.begin(); cand != pfcandidates.end(); ++cand){
319  if (cand->particleId() == reco::PFCandidate::gamma) pfphotons.push_back(*cand);
320  }
321  return pfphotons;
322 }
323 
325  bool &pizero_rejected ) {
326  // 2 windows are defined for Pi0 rejection, Conversions that, paired with others photons from the event, have an
327  // invariant mass inside the "small" window will be pizero_rejected and those that falls in the large window will
328  // be CheckPi0.
329  bool check_small = false;
330  bool check_large = false;
331 
332  float small1 = pi0SmallWindow_[0];
333  float small2 = pi0SmallWindow_[1];
334  float large1 = pi0LargeWindow_[0];
335  float large2 = pi0LargeWindow_[1];
336  for (reco::PFCandidateCollection::const_iterator photon = photons.begin(); photon!=photons.end(); ++photon) {
337  float inv = (conv.refittedPair4Momentum() + photon->p4()).M();
338  if (inv > large1 && inv < large2) {
339  check_large = true;
340  if (inv > small1 && inv < small2) {
341  check_small = true;
342  break;
343  }
344  }
345  }
346  pizero_rejected = check_small;
347  return check_large;
348 }
349 
351  return reco::Candidate::LorentzVector(v.x(),v.y(), v.z(), v.t());
352 }
353 
354 
356 }
357 //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
static uint32_t getLayer(uint16_t pattern)
Definition: HitPattern.h:751
bool foundCompatibleInnerHits(const reco::HitPattern &hitPatA, const reco::HitPattern &hitPatB)
ConversionAlgorithm algo() const
Definition: Conversion.h:223
static HepMC::IO_HEPEVT conv
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:499
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)
const Point & position() const
position
Definition: Vertex.h:109
std::vector< Conversion > ConversionCollection
collectin of Conversion objects
Definition: ConversionFwd.h:9
void setVertex(const Point &vertex) override
set vertex
static bool validHitFilter(uint16_t pattern)
Definition: HitPattern.h:847
U second(std::pair< T, U > const &p)
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 &)
void produce(edm::Event &event, const edm::EventSetup &esetup) override
T sqrt(T t)
Definition: SSEVec.h:18
int numberOfAllHits(HitCategory category) const
Definition: HitPattern.h:867
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:39
static uint32_t getSubStructure(uint16_t pattern)
Definition: HitPattern.h:742
double ndof() const
Definition: Vertex.h:105
const reco::PFCandidateCollection selectPFPhotons(const reco::PFCandidateCollection &)
OniaPhotonConversionProducer(const edm::ParameterSet &ps)
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:707
std::vector< CompositeCandidate > CompositeCandidateCollection
T const * product() const
Definition: Handle.h:81
double b
Definition: hdecay.h:120
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:37
fixed size matrix
#define begin
Definition: vmac.h:32
bool CheckPi0(const reco::Conversion &, const reco::PFCandidateCollection &, bool &)
pat::CompositeCandidate * makePhotonCandidate(const reco::Conversion &)
double a
Definition: hdecay.h:121
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:545
void setP4(const LorentzVector &p4) final
set 4-momentum
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:511
std::vector< edm::RefToBase< reco::Track > > const & tracks() const
vector of track to base references
Definition: Conversion.cc:176
Definition: event.py:1