File indexing completed on 2024-06-25 22:35:16
0001 #include "FWCore/Framework/interface/Frameworkfwd.h"
0002 #include "FWCore/Framework/interface/stream/EDProducer.h"
0003 #include "FWCore/Framework/interface/Event.h"
0004 #include "FWCore/Framework/interface/EventSetup.h"
0005 #include "FWCore/Framework/interface/ESHandle.h"
0006 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0007 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0008
0009 #include "DataFormats/VertexReco/interface/VertexFwd.h"
0010 #include "DataFormats/TrackReco/interface/TrackFwd.h"
0011 #include "DataFormats/Common/interface/ValueMap.h"
0012 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
0013 #include "DataFormats/TrackReco/interface/Track.h"
0014 #include "DataFormats/VertexReco/interface/Vertex.h"
0015 #include <CLHEP/Units/GlobalPhysicalConstants.h>
0016 #include <CLHEP/Units/SystemOfUnits.h>
0017
0018 using namespace std;
0019 using namespace edm;
0020
0021 class TOFPIDProducer : public edm::stream::EDProducer<> {
0022 public:
0023 TOFPIDProducer(const ParameterSet& pset);
0024
0025 static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0026
0027 template <class H, class T>
0028 void fillValueMap(edm::Event& iEvent,
0029 const edm::Handle<H>& handle,
0030 const std::vector<T>& vec,
0031 const std::string& name) const;
0032
0033 void produce(edm::Event& ev, const edm::EventSetup& es) final;
0034
0035 private:
0036 static constexpr char t0Name[] = "t0";
0037 static constexpr char sigmat0Name[] = "sigmat0";
0038 static constexpr char t0safeName[] = "t0safe";
0039 static constexpr char sigmat0safeName[] = "sigmat0safe";
0040 static constexpr char probPiName[] = "probPi";
0041 static constexpr char probKName[] = "probK";
0042 static constexpr char probPName[] = "probP";
0043
0044 edm::EDGetTokenT<reco::TrackCollection> tracksToken_;
0045 edm::EDGetTokenT<edm::ValueMap<float>> t0Token_;
0046 edm::EDGetTokenT<edm::ValueMap<float>> tmtdToken_;
0047 edm::EDGetTokenT<edm::ValueMap<float>> sigmat0Token_;
0048 edm::EDGetTokenT<edm::ValueMap<float>> sigmatmtdToken_;
0049 edm::EDGetTokenT<edm::ValueMap<float>> tofkToken_;
0050 edm::EDGetTokenT<edm::ValueMap<float>> tofpToken_;
0051 edm::EDGetTokenT<edm::ValueMap<float>> sigmatofpiToken_;
0052 edm::EDGetTokenT<edm::ValueMap<float>> sigmatofkToken_;
0053 edm::EDGetTokenT<edm::ValueMap<float>> sigmatofpToken_;
0054 edm::EDGetTokenT<reco::VertexCollection> vtxsToken_;
0055 edm::EDGetTokenT<edm::ValueMap<float>> trackMTDTimeQualityToken_;
0056 const double vtxMaxSigmaT_;
0057 const double maxDz_;
0058 const double maxDtSignificance_;
0059 const double minProbHeavy_;
0060 const double fixedT0Error_;
0061 const double probPion_;
0062 const double probKaon_;
0063 const double probProton_;
0064 const double minTrackTimeQuality_;
0065 const bool MVASel_;
0066 const bool vertexReassignment_;
0067 };
0068
0069 TOFPIDProducer::TOFPIDProducer(const ParameterSet& iConfig)
0070 : tracksToken_(consumes<reco::TrackCollection>(iConfig.getParameter<edm::InputTag>("tracksSrc"))),
0071 t0Token_(consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("t0Src"))),
0072 tmtdToken_(consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("tmtdSrc"))),
0073 sigmat0Token_(consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("sigmat0Src"))),
0074 sigmatmtdToken_(consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("sigmatmtdSrc"))),
0075 tofkToken_(consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("tofkSrc"))),
0076 tofpToken_(consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("tofpSrc"))),
0077 sigmatofpiToken_(consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("sigmatofpiSrc"))),
0078 sigmatofkToken_(consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("sigmatofkSrc"))),
0079 sigmatofpToken_(consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("sigmatofpSrc"))),
0080 vtxsToken_(consumes<reco::VertexCollection>(iConfig.getParameter<edm::InputTag>("vtxsSrc"))),
0081 trackMTDTimeQualityToken_(
0082 consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("trackMTDTimeQualityVMapTag"))),
0083 vtxMaxSigmaT_(iConfig.getParameter<double>("vtxMaxSigmaT")),
0084 maxDz_(iConfig.getParameter<double>("maxDz")),
0085 maxDtSignificance_(iConfig.getParameter<double>("maxDtSignificance")),
0086 minProbHeavy_(iConfig.getParameter<double>("minProbHeavy")),
0087 fixedT0Error_(iConfig.getParameter<double>("fixedT0Error")),
0088 probPion_(iConfig.getParameter<double>("probPion")),
0089 probKaon_(iConfig.getParameter<double>("probKaon")),
0090 probProton_(iConfig.getParameter<double>("probProton")),
0091 minTrackTimeQuality_(iConfig.getParameter<double>("minTrackTimeQuality")),
0092 MVASel_(iConfig.getParameter<bool>("MVASel")),
0093 vertexReassignment_(iConfig.getParameter<bool>("vertexReassignment")) {
0094 produces<edm::ValueMap<float>>(t0Name);
0095 produces<edm::ValueMap<float>>(sigmat0Name);
0096 produces<edm::ValueMap<float>>(t0safeName);
0097 produces<edm::ValueMap<float>>(sigmat0safeName);
0098 produces<edm::ValueMap<float>>(probPiName);
0099 produces<edm::ValueMap<float>>(probKName);
0100 produces<edm::ValueMap<float>>(probPName);
0101 }
0102
0103
0104 void TOFPIDProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0105 edm::ParameterSetDescription desc;
0106 desc.add<edm::InputTag>("tracksSrc", edm::InputTag("generalTracks"))->setComment("Input tracks collection");
0107 desc.add<edm::InputTag>("t0Src", edm::InputTag("trackExtenderWithMTD:generalTrackt0"))
0108 ->setComment("Input ValueMap for track time at beamline");
0109 desc.add<edm::InputTag>("tmtdSrc", edm::InputTag("trackExtenderWithMTD:generalTracktmtd"))
0110 ->setComment("Input ValueMap for track time at MTD");
0111 desc.add<edm::InputTag>("sigmat0Src", edm::InputTag("trackExtenderWithMTD:generalTracksigmat0"))
0112 ->setComment("Input ValueMap for track time uncertainty at beamline");
0113 desc.add<edm::InputTag>("sigmatmtdSrc", edm::InputTag("trackExtenderWithMTD:generalTracksigmatmtd"))
0114 ->setComment("Input ValueMap for track time uncertainty at MTD");
0115 desc.add<edm::InputTag>("tofkSrc", edm::InputTag("trackExtenderWithMTD:generalTrackTofK"))
0116 ->setComment("Input ValueMap for track tof as kaon");
0117 desc.add<edm::InputTag>("tofpSrc", edm::InputTag("trackExtenderWithMTD:generalTrackTofP"))
0118 ->setComment("Input ValueMap for track tof as proton");
0119 desc.add<edm::InputTag>("sigmatofpiSrc", edm::InputTag("trackExtenderWithMTD:generalTrackSigmaTofPi"))
0120 ->setComment("Input ValueMap for track sigma(tof) as pion");
0121 desc.add<edm::InputTag>("sigmatofkSrc", edm::InputTag("trackExtenderWithMTD:generalTrackSigmaTofK"))
0122 ->setComment("Input ValueMap for track sigma(tof) as kaon");
0123 desc.add<edm::InputTag>("sigmatofpSrc", edm::InputTag("trackExtenderWithMTD:generalTrackSigmaTofP"))
0124 ->setComment("Input ValueMap for track sigma(tof) as proton");
0125 desc.add<edm::InputTag>("vtxsSrc", edm::InputTag("unsortedOfflinePrimaryVertices4DwithPID"))
0126 ->setComment("Input primary vertex collection");
0127 desc.add<edm::InputTag>("trackMTDTimeQualityVMapTag", edm::InputTag("mtdTrackQualityMVA:mtdQualMVA"))
0128 ->setComment("Track MVA quality value");
0129 desc.add<double>("vtxMaxSigmaT", 0.025)
0130 ->setComment("Maximum primary vertex time uncertainty for use in particle id [ns]");
0131 desc.add<double>("maxDz", 0.1)
0132 ->setComment("Maximum distance in z for track-primary vertex association for particle id [cm]");
0133 desc.add<double>("maxDtSignificance", 5.0)
0134 ->setComment(
0135 "Maximum distance in time (normalized by uncertainty) for track-primary vertex association for particle id");
0136 desc.add<double>("minProbHeavy", 0.75)
0137 ->setComment("Minimum probability for a particle to be a kaon or proton before reassigning the timestamp");
0138 desc.add<double>("fixedT0Error", 0.)->setComment("Use a fixed T0 uncertainty [ns]");
0139 desc.add<double>("probPion", 1.)->setComment("A priori probability pions");
0140 desc.add<double>("probKaon", 1.)->setComment("A priori probability kaons");
0141 desc.add<double>("probProton", 1.)->setComment("A priori probability for protons");
0142 desc.add<double>("minTrackTimeQuality", 0.8)->setComment("Minimum MVA Quality selection on tracks");
0143 desc.add<bool>("MVASel", false)->setComment("Use MVA Quality selection");
0144 desc.add<bool>("vertexReassignment", true)->setComment("Track-vertex reassignment");
0145
0146 descriptions.add("tofPIDProducer", desc);
0147 }
0148
0149 template <class H, class T>
0150 void TOFPIDProducer::fillValueMap(edm::Event& iEvent,
0151 const edm::Handle<H>& handle,
0152 const std::vector<T>& vec,
0153 const std::string& name) const {
0154 auto out = std::make_unique<edm::ValueMap<T>>();
0155 typename edm::ValueMap<T>::Filler filler(*out);
0156 filler.insert(handle, vec.begin(), vec.end());
0157 filler.fill();
0158 iEvent.put(std::move(out), name);
0159 }
0160
0161 void TOFPIDProducer::produce(edm::Event& ev, const edm::EventSetup& es) {
0162 edm::Handle<reco::TrackCollection> tracksH;
0163 ev.getByToken(tracksToken_, tracksH);
0164 const auto& tracks = *tracksH;
0165
0166 const auto& t0In = ev.get(t0Token_);
0167
0168 const auto& tmtdIn = ev.get(tmtdToken_);
0169
0170 const auto& sigmat0In = ev.get(sigmat0Token_);
0171
0172 const auto& sigmatmtdIn = ev.get(sigmatmtdToken_);
0173
0174 const auto& tofkIn = ev.get(tofkToken_);
0175
0176 const auto& tofpIn = ev.get(tofpToken_);
0177
0178 const auto& sigmatofpiIn = ev.get(sigmatofpiToken_);
0179
0180 const auto& sigmatofkIn = ev.get(sigmatofkToken_);
0181
0182 const auto& sigmatofpIn = ev.get(sigmatofpToken_);
0183
0184 const auto& vtxs = ev.get(vtxsToken_);
0185
0186 const auto& trackMVAQualIn = ev.get(trackMTDTimeQualityToken_);
0187
0188
0189 std::vector<float> t0OutRaw;
0190 std::vector<float> sigmat0OutRaw;
0191 std::vector<float> t0safeOutRaw;
0192 std::vector<float> sigmat0safeOutRaw;
0193 std::vector<float> probPiOutRaw;
0194 std::vector<float> probKOutRaw;
0195 std::vector<float> probPOutRaw;
0196
0197
0198 for (unsigned int itrack = 0; itrack < tracks.size(); ++itrack) {
0199 const reco::Track& track = tracks[itrack];
0200 const reco::TrackRef trackref(tracksH, itrack);
0201 float t0 = t0In[trackref];
0202 float t0safe = t0;
0203 float sigmat0safe = sigmat0In[trackref];
0204 float sigmatmtd = (sigmatmtdIn[trackref] > 0. && fixedT0Error_ > 0.) ? fixedT0Error_ : sigmatmtdIn[trackref];
0205 float sigmat0 = sigmatmtd;
0206 float sigmatofpi = sigmatofpiIn[trackref];
0207 float sigmatofk = sigmatofkIn[trackref];
0208 float sigmatofp = sigmatofpIn[trackref];
0209
0210 float prob_pi = -1.;
0211 float prob_k = -1.;
0212 float prob_p = -1.;
0213
0214 float trackMVAQual = trackMVAQualIn[trackref];
0215
0216 if (sigmat0 > 0. && (!MVASel_ || (MVASel_ && trackMVAQual >= minTrackTimeQuality_))) {
0217 double rsigmazsq = 1. / track.dzError() / track.dzError();
0218 std::array<double, 3> rsigmat = {{1. / std::sqrt(sigmatmtd * sigmatmtd + sigmatofpi * sigmatofpi),
0219 1. / std::sqrt(sigmatmtd * sigmatmtd + sigmatofk * sigmatofk),
0220 1. / std::sqrt(sigmatmtd * sigmatmtd + sigmatofp * sigmatofp)}};
0221
0222
0223 int vtxidx = -1;
0224 int vtxidxmindz = -1;
0225 int vtxidxminchisq = -1;
0226 double mindz = maxDz_;
0227 double minchisq = std::numeric_limits<double>::max();
0228
0229 for (unsigned int ivtx = 0; ivtx < vtxs.size(); ++ivtx) {
0230 const reco::Vertex& vtx = vtxs[ivtx];
0231 float w = vtx.trackWeight(trackref);
0232 if (w > 0.5) {
0233 vtxidx = ivtx;
0234 break;
0235 }
0236 double dz = std::abs(track.dz(vtx.position()));
0237 if (dz < mindz) {
0238 mindz = dz;
0239 vtxidxmindz = ivtx;
0240 }
0241 if (vtx.tError() > 0. && vtx.tError() < vtxMaxSigmaT_) {
0242 double dt = std::abs(t0 - vtx.t());
0243 double dtsig = dt * rsigmat[0];
0244 double chisq = dz * dz * rsigmazsq + dtsig * dtsig;
0245 if (dz < maxDz_ && dtsig < maxDtSignificance_ && chisq < minchisq) {
0246 minchisq = chisq;
0247 vtxidxminchisq = ivtx;
0248 }
0249 }
0250 }
0251
0252
0253 if (vtxidx < 0) {
0254
0255
0256 if (vtxidxmindz >= 0 && !(vtxs[vtxidxmindz].tError() > 0. && vtxs[vtxidxmindz].tError() < vtxMaxSigmaT_)) {
0257 vtxidx = vtxidxmindz;
0258 } else if (vtxidxminchisq >= 0) {
0259 vtxidx = vtxidxminchisq;
0260 } else if (vtxidxmindz >= 0) {
0261 vtxidx = vtxidxmindz;
0262 }
0263 }
0264
0265
0266 if (vtxidx >= 0 && vtxs[vtxidx].tError() > 0. && vtxs[vtxidx].tError() < vtxMaxSigmaT_) {
0267
0268 const reco::Vertex& vtxnom = vtxs[vtxidx];
0269 double dznom = std::abs(track.dz(vtxnom.position()));
0270 double dtnom = std::abs(t0 - vtxnom.t());
0271 double dtsignom = dtnom * rsigmat[0];
0272 double chisqnom = dznom * dznom * rsigmazsq + dtsignom * dtsignom;
0273
0274
0275 double t0_best = t0;
0276
0277
0278 if (dtsignom < maxDtSignificance_) {
0279 sigmat0safe = 1. / rsigmat[0];
0280 sigmat0 = sigmat0safe;
0281 }
0282
0283 double tmtd = tmtdIn[trackref];
0284 double t0_k = tmtd - tofkIn[trackref];
0285 double t0_p = tmtd - tofpIn[trackref];
0286
0287 double chisqmin = chisqnom;
0288
0289 double chisqmin_pi = chisqnom;
0290 double chisqmin_k = std::numeric_limits<double>::max();
0291 double chisqmin_p = std::numeric_limits<double>::max();
0292
0293 for (unsigned int ivtx = 0; ivtx < vtxs.size(); ++ivtx) {
0294 const reco::Vertex& vtx = vtxs[ivtx];
0295 if (!vertexReassignment_) {
0296 if (ivtx != (unsigned int)vtxidx)
0297 continue;
0298 }
0299 if (!(vtx.tError() > 0. && vtx.tError() < vtxMaxSigmaT_)) {
0300 continue;
0301 }
0302
0303 double dz = std::abs(track.dz(vtx.position()));
0304 if (dz >= maxDz_) {
0305 continue;
0306 }
0307
0308 double chisqdz = dz * dz * rsigmazsq;
0309
0310 double dt_k = std::abs(t0_k - vtx.t());
0311 double dtsig_k = dt_k * rsigmat[1];
0312 double chisq_k = chisqdz + dtsig_k * dtsig_k;
0313
0314 if (dtsig_k < maxDtSignificance_ && chisq_k < chisqmin_k) {
0315 chisqmin_k = chisq_k;
0316 }
0317
0318 double dt_p = std::abs(t0_p - vtx.t());
0319 double dtsig_p = dt_p * rsigmat[2];
0320 double chisq_p = chisqdz + dtsig_p * dtsig_p;
0321
0322 if (dtsig_p < maxDtSignificance_ && chisq_p < chisqmin_p) {
0323 chisqmin_p = chisq_p;
0324 }
0325
0326 if (dtsig_k < maxDtSignificance_ && chisq_k < chisqmin) {
0327 chisqmin = chisq_k;
0328 t0_best = t0_k;
0329 t0safe = t0_k;
0330 sigmat0safe = 1. / rsigmat[1];
0331 sigmat0 = sigmat0safe;
0332 }
0333 if (dtsig_p < maxDtSignificance_ && chisq_p < chisqmin) {
0334 chisqmin = chisq_p;
0335 t0_best = t0_p;
0336 t0safe = t0_p;
0337 sigmat0safe = 1. / rsigmat[2];
0338 sigmat0 = sigmat0safe;
0339 }
0340 }
0341
0342
0343
0344 double rawprob_pi = probPion_ * exp(-0.5 * chisqmin_pi);
0345 double rawprob_k = probKaon_ * exp(-0.5 * chisqmin_k);
0346 double rawprob_p = probProton_ * exp(-0.5 * chisqmin_p);
0347
0348 double normprob = 1. / (rawprob_pi + rawprob_k + rawprob_p);
0349
0350 prob_pi = rawprob_pi * normprob;
0351 prob_k = rawprob_k * normprob;
0352 prob_p = rawprob_p * normprob;
0353
0354 double prob_heavy = 1. - prob_pi;
0355
0356 if (prob_heavy > minProbHeavy_) {
0357 t0 = t0_best;
0358 }
0359 }
0360 }
0361
0362 t0OutRaw.push_back(t0);
0363 sigmat0OutRaw.push_back(sigmat0);
0364 t0safeOutRaw.push_back(t0safe);
0365 sigmat0safeOutRaw.push_back(sigmat0safe);
0366 probPiOutRaw.push_back(prob_pi);
0367 probKOutRaw.push_back(prob_k);
0368 probPOutRaw.push_back(prob_p);
0369 }
0370
0371 fillValueMap(ev, tracksH, t0OutRaw, t0Name);
0372 fillValueMap(ev, tracksH, sigmat0OutRaw, sigmat0Name);
0373 fillValueMap(ev, tracksH, t0safeOutRaw, t0safeName);
0374 fillValueMap(ev, tracksH, sigmat0safeOutRaw, sigmat0safeName);
0375 fillValueMap(ev, tracksH, probPiOutRaw, probPiName);
0376 fillValueMap(ev, tracksH, probKOutRaw, probKName);
0377 fillValueMap(ev, tracksH, probPOutRaw, probPName);
0378 }
0379
0380
0381 #include <FWCore/Framework/interface/MakerMacros.h>
0382 DEFINE_FWK_MODULE(TOFPIDProducer);