File indexing completed on 2024-09-07 04:37:30
0001 #include "RecoEgamma/EgammaTools/interface/LowPtConversion.h"
0002
0003
0004
0005
0006 bool LowPtConversion::wpOpen() const { return matched_; }
0007
0008
0009
0010
0011 bool LowPtConversion::wpLoose() const {
0012 return (wpOpen() && ntracks_ == 2 && valid_ && quality_high_purity_ && chi2prob_ > 0.0005);
0013 }
0014
0015
0016
0017
0018 bool LowPtConversion::wpTight() const {
0019 return (wpLoose() && sum_nhits_before_vtx_ <= 1 && l_xy_ > 0. && mass_from_conv_ > 0. &&
0020 mass_from_conv_ < 0.05);
0021 }
0022
0023
0024
0025 void LowPtConversion::addUserVars(pat::Electron& ele) const {
0026 ele.addUserInt("convOpen", matched_ ? 1 : 0);
0027 ele.addUserInt("convLoose", wpLoose() ? 1 : 0);
0028 ele.addUserInt("convTight", wpTight() ? 1 : 0);
0029 ele.addUserInt("convLead", matched_lead_.isNonnull() ? 1 : 0);
0030 ele.addUserInt("convTrail", matched_trail_.isNonnull() ? 1 : 0);
0031 if (ele.hasUserInt("convExtra") == false) {
0032 ele.addUserInt("convExtra", 0);
0033 }
0034 }
0035
0036
0037
0038 void LowPtConversion::addExtraUserVars(pat::Electron& ele) const {
0039
0040 ele.addUserInt("convExtra", 1, true);
0041
0042
0043 ele.addUserInt("convValid", valid_ ? 1 : 0);
0044 ele.addUserFloat("convChi2Prob", chi2prob_);
0045 ele.addUserInt("convQualityHighPurity", quality_high_purity_ ? 1 : 0);
0046 ele.addUserInt("convQualityHighEff", quality_high_efficiency_ ? 1 : 0);
0047
0048
0049 ele.addUserInt("convTracksN", ntracks_);
0050 ele.addUserFloat("convMinTrkPt", min_trk_pt_);
0051 ele.addUserInt("convLeadIdx", ilead_);
0052 ele.addUserInt("convTrailIdx", itrail_);
0053
0054
0055 ele.addUserFloat("convLxy", l_xy_);
0056 ele.addUserFloat("convVtxRadius", vtx_radius_);
0057
0058
0059 ele.addUserFloat("convMass", mass_from_conv_);
0060 ele.addUserFloat("convMassFromPin", mass_from_Pin_);
0061 ele.addUserFloat("convMassBeforeFit", mass_before_fit_);
0062 ele.addUserFloat("convMassAfterFit", mass_after_fit_);
0063
0064
0065 ele.addUserInt("convLeadNHitsBeforeVtx", lead_nhits_before_vtx_);
0066 ele.addUserInt("convTrailNHitsBeforeVtx", trail_nhits_before_vtx_);
0067 ele.addUserInt("convMaxNHitsBeforeVtx", max_nhits_before_vtx_);
0068 ele.addUserInt("convSumNHitsBeforeVtx", sum_nhits_before_vtx_);
0069 ele.addUserInt("convDeltaExpectedNHitsInner", delta_expected_nhits_inner_);
0070
0071
0072 ele.addUserFloat("convDeltaCotFromPin", delta_cot_from_Pin_);
0073 }
0074
0075
0076
0077 bool LowPtConversion::match(const reco::BeamSpot& beamSpot,
0078 const reco::ConversionCollection& conversions,
0079 const pat::Electron& ele) {
0080
0081 for (const auto& conv : conversions) {
0082
0083 if (conv.tracks().size() != 2) {
0084 continue;
0085 }
0086
0087
0088 valid_ = conv.conversionVertex().isValid();
0089 chi2prob_ = ChiSquaredProbability(conv.conversionVertex().chi2(), conv.conversionVertex().ndof());
0090 quality_high_purity_ = conv.quality(reco::Conversion::highPurity);
0091 quality_high_efficiency_ = conv.quality(reco::Conversion::highEfficiency);
0092
0093
0094 ntracks_ = conv.tracks().size();
0095 min_trk_pt_ = -1.;
0096 for (const auto& trk : conv.tracks()) {
0097 if (trk.isNonnull() && trk.isAvailable() && (min_trk_pt_ < 0. || trk->pt() < min_trk_pt_)) {
0098 min_trk_pt_ = trk->pt();
0099 }
0100 }
0101 ilead_ = -1;
0102 itrail_ = -1;
0103 if (conv.tracks().size() == 2) {
0104 const edm::RefToBase<reco::Track>& trk1 = conv.tracks().front();
0105 const edm::RefToBase<reco::Track>& trk2 = conv.tracks().back();
0106 if (trk1.isNonnull() && trk1.isAvailable() && trk2.isNonnull() && trk2.isAvailable()) {
0107 if (trk1->pt() > trk2->pt()) {
0108 ilead_ = 0;
0109 itrail_ = 1;
0110 } else {
0111 ilead_ = 1;
0112 itrail_ = 0;
0113 }
0114 }
0115 }
0116
0117
0118 math::XYZVectorF p_refitted = conv.refittedPairMomentum();
0119 float dx = conv.conversionVertex().x() - beamSpot.x0();
0120 float dy = conv.conversionVertex().y() - beamSpot.y0();
0121 l_xy_ = (p_refitted.x() * dx + p_refitted.y() * dy) / p_refitted.rho();
0122 vtx_radius_ = sqrt(conv.conversionVertex().position().perp2());
0123
0124
0125 mass_from_conv_ = conv.pairInvariantMass();
0126
0127
0128 if (conv.tracksPin().size() >= 2 && ilead_ > -1 && itrail_ > -1) {
0129 math::XYZVectorF lead_Pin = conv.tracksPin().at(ilead_);
0130 math::XYZVectorF trail_Pin = conv.tracksPin().at(itrail_);
0131 mass_from_Pin_ = mee(lead_Pin.x(), lead_Pin.y(), lead_Pin.z(), trail_Pin.x(), trail_Pin.y(), trail_Pin.z());
0132
0133 delta_cot_from_Pin_ = 1. / tan(trail_Pin.theta()) - 1. / tan(lead_Pin.theta());
0134 }
0135
0136
0137 if (conv.tracks().size() >= 2 && ilead_ > -1 && itrail_ > -1) {
0138 auto lead_before_vtx_fit = conv.tracks().at(ilead_)->momentum();
0139 auto trail_before_vtx_fit = conv.tracks().at(itrail_)->momentum();
0140 mass_before_fit_ = mee(lead_before_vtx_fit.x(),
0141 lead_before_vtx_fit.y(),
0142 lead_before_vtx_fit.z(),
0143 trail_before_vtx_fit.x(),
0144 trail_before_vtx_fit.y(),
0145 trail_before_vtx_fit.z());
0146 }
0147
0148
0149 if (conv.conversionVertex().refittedTracks().size() >= 2 && ilead_ > -1 && itrail_ > -1) {
0150 auto const& lead_after_vtx_fit = conv.conversionVertex().refittedTracks().at(ilead_);
0151 auto const& trail_after_vtx_fit = conv.conversionVertex().refittedTracks().at(itrail_);
0152 mass_after_fit_ = mee(lead_after_vtx_fit.px(),
0153 lead_after_vtx_fit.py(),
0154 lead_after_vtx_fit.pz(),
0155 trail_after_vtx_fit.px(),
0156 trail_after_vtx_fit.py(),
0157 trail_after_vtx_fit.pz());
0158
0159 delta_expected_nhits_inner_ =
0160 lead_after_vtx_fit.hitPattern().numberOfLostHits(reco::HitPattern::MISSING_INNER_HITS) -
0161 trail_after_vtx_fit.hitPattern().numberOfLostHits(reco::HitPattern::MISSING_INNER_HITS);
0162 }
0163
0164
0165 if (ilead_ > -1 && itrail_ > -1) {
0166 auto const& nHits = conv.nHitsBeforeVtx();
0167 bool enoughTracks = nHits.size() > 1;
0168 lead_nhits_before_vtx_ = enoughTracks ? nHits.at(ilead_) : 0;
0169 trail_nhits_before_vtx_ = enoughTracks ? nHits.at(itrail_) : 0;
0170 max_nhits_before_vtx_ = enoughTracks ? std::max(nHits[0], nHits[1]) : 0;
0171 sum_nhits_before_vtx_ = enoughTracks ? nHits[0] + nHits[1] : 0;
0172 }
0173
0174
0175 for (uint itrk = 0; itrk < conv.tracks().size(); ++itrk) {
0176 const edm::RefToBase<reco::Track> trk = conv.tracks()[itrk];
0177 if (trk.isNull()) {
0178 continue;
0179 }
0180 reco::GsfTrackRef ref = ele.core()->gsfTrack();
0181 reco::GsfTrackRef gsf = ele.gsfTrack();
0182 if (gsf.isNull()) {
0183 continue;
0184 }
0185 if (ref.id() == trk.id() && ref.key() == trk.key()) {
0186 matched_ = true;
0187 if (static_cast<int>(itrk) == ilead_) {
0188 matched_lead_ = trk;
0189 }
0190 if (static_cast<int>(itrk) == itrail_) {
0191 matched_trail_ = trk;
0192 }
0193 }
0194 }
0195 }
0196
0197 return matched_;
0198 }
0199
0200
0201
0202 float LowPtConversion::mee(float px1, float py1, float pz1, float px2, float py2, float pz2) {
0203 const float m = 0.000511;
0204 const float px = px1 + px2;
0205 const float py = py1 + py2;
0206 const float pz = pz1 + pz2;
0207 const float p1 = px1 * px1 + py1 * py1 + pz1 * pz1;
0208 const float p2 = px2 * px2 + py2 * py2 + pz2 * pz2;
0209 const float e = sqrt(p1 + m * m) + sqrt(p2 + m * m);
0210 const float mass = (e * e - px * px - py * py - pz * pz);
0211 return mass > 0. ? sqrt(mass) : -1.;
0212 }