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