CMS 3D CMS Logo

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