File indexing completed on 2024-04-06 12:09:15
0001
0002
0003
0004
0005
0006 #include "CommonTools/Statistics/interface/ChiSquaredProbability.h"
0007 #include "DQMOffline/Alignment/interface/DiMuonMassBiasMonitor.h"
0008 #include "DQMServices/Core/interface/DQMStore.h"
0009 #include "DataFormats/Histograms/interface/DQMToken.h"
0010 #include "DataFormats/Math/interface/deltaR.h"
0011 #include "DataFormats/TrackReco/interface/Track.h"
0012 #include "DataFormats/TrackReco/interface/TrackBase.h"
0013 #include "DataFormats/TrackReco/interface/TrackFwd.h"
0014 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0015 #include "FWCore/Utilities/interface/InputTag.h"
0016 #include "Geometry/CommonDetUnit/interface/GeomDet.h"
0017 #include "RecoVertex/KalmanVertexFit/interface/KalmanVertexFitter.h"
0018 #include "RecoVertex/VertexTools/interface/VertexDistance3D.h"
0019 #include "RecoVertex/VertexTools/interface/VertexDistanceXY.h"
0020 #include "TrackingTools/IPTools/interface/IPTools.h"
0021
0022 #include "TLorentzVector.h"
0023
0024 namespace {
0025
0026 constexpr float mumass2 = 0.105658367 * 0.105658367;
0027 }
0028
0029 DiMuonMassBiasMonitor::DiMuonMassBiasMonitor(const edm::ParameterSet& iConfig)
0030 : ttbESToken_(esConsumes(edm::ESInputTag("", "TransientTrackBuilder"))),
0031 tracksToken_(consumes<reco::TrackCollection>(iConfig.getParameter<edm::InputTag>("muonTracks"))),
0032 vertexToken_(consumes<reco::VertexCollection>(iConfig.getParameter<edm::InputTag>("vertices"))),
0033 beamSpotToken_(consumes<reco::BeamSpot>(iConfig.getParameter<edm::InputTag>("beamSpot"))),
0034 MEFolderName_(iConfig.getParameter<std::string>("FolderName")),
0035 decayMotherName_(iConfig.getParameter<std::string>("decayMotherName")),
0036 distanceScaleFactor_(iConfig.getParameter<double>("distanceScaleFactor")),
0037 DiMuMassConfiguration_(iConfig.getParameter<edm::ParameterSet>("DiMuMassConfig")) {}
0038
0039 void DiMuonMassBiasMonitor::bookHistograms(DQMStore::IBooker& iBooker, edm::Run const&, edm::EventSetup const&) {
0040 iBooker.setCurrentFolder(MEFolderName_ + "/DiMuonMassBiasMonitor/MassBias");
0041 ZMassPlots.bookFromPSet(iBooker, DiMuMassConfiguration_);
0042
0043 iBooker.setCurrentFolder(MEFolderName_ + "/DiMuonMassBiasMonitor");
0044
0045
0046 const auto& mass_bins = DiMuMassConfiguration_.getParameter<int32_t>("NyBins");
0047 const auto& mass_min = DiMuMassConfiguration_.getParameter<double>("ymin");
0048 const auto& mass_max = DiMuMassConfiguration_.getParameter<double>("ymax");
0049
0050 bookDecayHists(
0051 iBooker, histosZmm, decayMotherName_, "#mu^{+}#mu^{-}", mass_bins, mass_min, mass_max, distanceScaleFactor_);
0052
0053 iBooker.setCurrentFolder(MEFolderName_ + "/DiMuonMassBiasMonitor/components");
0054 bookDecayComponentHistograms(iBooker, histosZmm);
0055 }
0056
0057 void DiMuonMassBiasMonitor::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) {
0058 std::vector<const reco::Track*> myTracks;
0059 const auto trackHandle = iEvent.getHandle(tracksToken_);
0060 if (!trackHandle.isValid()) {
0061 edm::LogError("DiMuonMassBiasMonitor") << "invalid track collection encountered!";
0062 return;
0063 }
0064
0065 for (const auto& muonTrk : *trackHandle) {
0066 myTracks.emplace_back(&muonTrk);
0067 }
0068
0069 if (myTracks.size() != 2) {
0070 edm::LogWarning("DiMuonMassBiasMonitor") << "There are not enough tracks to monitor!";
0071 return;
0072 }
0073
0074 const auto& t1 = myTracks[1]->momentum();
0075 const auto& t0 = myTracks[0]->momentum();
0076 const auto& ditrack = t1 + t0;
0077
0078 const auto& tplus = myTracks[0]->charge() > 0 ? myTracks[0] : myTracks[1];
0079 const auto& tminus = myTracks[0]->charge() < 0 ? myTracks[0] : myTracks[1];
0080
0081 TLorentzVector p4_tplus(tplus->px(), tplus->py(), tplus->pz(), sqrt((tplus->p() * tplus->p()) + mumass2));
0082 TLorentzVector p4_tminus(tminus->px(), tminus->py(), tminus->pz(), sqrt((tminus->p() * tminus->p()) + mumass2));
0083
0084 const auto& Zp4 = p4_tplus + p4_tminus;
0085 float track_invMass = Zp4.M();
0086
0087
0088 std::pair<TLorentzVector, TLorentzVector> tktk_p4 = std::make_pair(p4_tplus, p4_tminus);
0089
0090
0091 ZMassPlots.fillPlots(track_invMass, tktk_p4);
0092
0093 math::XYZPoint ZpT(ditrack.x(), ditrack.y(), 0);
0094 math::XYZPoint Zp(ditrack.x(), ditrack.y(), ditrack.z());
0095
0096
0097 const auto& vertexHandle = iEvent.getHandle(vertexToken_);
0098 if (!vertexHandle.isValid()) {
0099 edm::LogError("DiMuonMassBiasMonitor") << "invalid vertex collection encountered!";
0100 return;
0101 }
0102
0103
0104 const auto& vertices = vertexHandle.product();
0105
0106
0107 auto decayVertex = fillDecayHistograms(histosZmm, myTracks, vertices, iSetup);
0108
0109
0110 const reco::BeamSpot* bs;
0111 const auto& beamSpotHandle = iEvent.getHandle(beamSpotToken_);
0112 if (!beamSpotHandle.isValid()) {
0113 bs = nullptr;
0114 } else {
0115 bs = beamSpotHandle.product();
0116 }
0117
0118
0119 fillComponentHistograms(histosZmm.decayComponents[0], tplus, bs, decayVertex);
0120 fillComponentHistograms(histosZmm.decayComponents[1], tminus, bs, decayVertex);
0121 }
0122
0123 void DiMuonMassBiasMonitor::bookDecayComponentHistograms(DQMStore::IBooker& ibook, DecayHists& histos) const {
0124 bookComponentHists(ibook, histos, "mu_plus", 0.1);
0125 bookComponentHists(ibook, histos, "mu_minus", 0.1);
0126 }
0127
0128 void DiMuonMassBiasMonitor::bookComponentHists(DQMStore::IBooker& ibook,
0129 DecayHists& histos,
0130 TString const& componentName,
0131 float distanceScaleFactor) const {
0132 ComponentHists comp;
0133
0134 comp.h_pt = ibook.book1D(componentName + "_pt", "track momentum ;p_{T} [GeV]", 100, 0., 100.);
0135 comp.h_eta = ibook.book1D(componentName + "_eta", "track rapidity;#eta", 100, -2.5, 2.5);
0136 comp.h_phi = ibook.book1D(componentName + "_phi", "track azimuth;#phi", 100, -M_PI, M_PI);
0137 comp.h_dxy = ibook.book1D(componentName + "_dxyBS",
0138 "TIP w.r.t BS;d_{xy}(BS) [cm]",
0139 100,
0140 -0.5 * distanceScaleFactor,
0141 0.5 * distanceScaleFactor);
0142 comp.h_exy =
0143 ibook.book1D(componentName + "_exy", "Error on TIP ;#sigma(d_{xy}(BS)) [cm]", 100, 0, 0.05 * distanceScaleFactor);
0144 comp.h_dz = ibook.book1D(componentName + "_dzPV",
0145 "LIP w.r.t PV;d_{z}(PV) [cm]",
0146 100,
0147 -0.5 * distanceScaleFactor,
0148 0.5 * distanceScaleFactor);
0149 comp.h_ez =
0150 ibook.book1D(componentName + "_ez", "Error on LIP;#sigma(d_{z}(PV)) [cm]", 100, 0, 0.5 * distanceScaleFactor);
0151 comp.h_chi2 = ibook.book1D(componentName + "_chi2", ";#chi^{2}", 100, 0, 20);
0152
0153 histos.decayComponents.push_back(comp);
0154 }
0155
0156 void DiMuonMassBiasMonitor::bookDecayHists(DQMStore::IBooker& ibook,
0157 DecayHists& decayHists,
0158 std::string const& name,
0159 std::string const& products,
0160 int nMassBins,
0161 float massMin,
0162 float massMax,
0163 float distanceScaleFactor) const {
0164 std::string histTitle = name + " #rightarrow " + products + ";";
0165
0166 decayHists.h_mass = ibook.book1D("h_mass", histTitle + "M(" + products + ") [GeV]", nMassBins, massMin, massMax);
0167 decayHists.h_pt = ibook.book1D("h_pt", histTitle + "p_{T} [GeV]", 100, 0.00, 200.0);
0168 decayHists.h_eta = ibook.book1D("h_eta", histTitle + "#eta", 100, -5., 5.);
0169 decayHists.h_phi = ibook.book1D("h_phi", histTitle + "#varphi [rad]", 100, -M_PI, M_PI);
0170 decayHists.h_displ2D =
0171 ibook.book1D("h_displ2D", histTitle + "vertex 2D displacement [cm]", 100, 0.00, 0.1 * distanceScaleFactor);
0172 decayHists.h_sign2D =
0173 ibook.book1D("h_sign2D", histTitle + "vertex 2D displ. significance", 100, 0.00, 100.0 * distanceScaleFactor);
0174 decayHists.h_ct = ibook.book1D("h_ct", histTitle + "c#tau [cm]", 100, 0.00, 0.4 * distanceScaleFactor);
0175 decayHists.h_pointing = ibook.book1D("h_pointing", histTitle + "cos( 2D pointing angle )", 100, -1, 1);
0176 decayHists.h_vertNormChi2 = ibook.book1D("h_vertNormChi2", histTitle + "vertex #chi^{2}/ndof", 100, 0.00, 10);
0177 decayHists.h_vertProb = ibook.book1D("h_vertProb", histTitle + "vertex prob.", 100, 0.00, 1.0);
0178 }
0179
0180 reco::Vertex const* DiMuonMassBiasMonitor::fillDecayHistograms(DecayHists const& histos,
0181 std::vector<const reco::Track*> const& tracks,
0182 const reco::VertexCollection* const& pvs,
0183 const edm::EventSetup& iSetup) const {
0184 if (tracks.size() != 2) {
0185 edm::LogWarning("DiMuonVertexMonitor") << "There are not enough tracks to construct a vertex!";
0186 return nullptr;
0187 }
0188
0189 const TransientTrackBuilder* theB = &iSetup.getData(ttbESToken_);
0190 TransientVertex mumuTransientVtx;
0191 std::vector<reco::TransientTrack> tks;
0192
0193 for (const auto& track : tracks) {
0194 reco::TransientTrack trajectory = theB->build(track);
0195 tks.push_back(trajectory);
0196 }
0197
0198 KalmanVertexFitter kalman(true);
0199 mumuTransientVtx = kalman.vertex(tks);
0200
0201 auto svtx = reco::Vertex(mumuTransientVtx);
0202 if (not svtx.isValid()) {
0203 return nullptr;
0204 }
0205
0206 const auto& mom_t1 = tracks[1]->momentum();
0207 const auto& mom_t0 = tracks[0]->momentum();
0208 const auto& momentum = mom_t1 + mom_t0;
0209
0210 TLorentzVector p4_t0(mom_t0.x(), mom_t0.y(), mom_t0.z(), sqrt(mom_t0.mag2() + mumass2));
0211 TLorentzVector p4_t1(mom_t1.x(), mom_t1.y(), mom_t1.z(), sqrt(mom_t1.mag2() + mumass2));
0212
0213 const auto& p4 = p4_t0 + p4_t1;
0214 float mass = p4.M();
0215
0216 auto pvtx = std::min_element(pvs->begin(), pvs->end(), [svtx](reco::Vertex const& pv1, reco::Vertex const& pv2) {
0217 return abs(pv1.z() - svtx.z()) < abs(pv2.z() - svtx.z());
0218 });
0219
0220 if (pvtx == pvs->end()) {
0221 return nullptr;
0222 }
0223
0224 VertexDistanceXY vdistXY;
0225 Measurement1D distXY = vdistXY.distance(svtx, *pvtx);
0226
0227 auto pvtPos = pvtx->position();
0228 const auto& svtPos = svtx.position();
0229
0230 math::XYZVector displVect2D(svtPos.x() - pvtPos.x(), svtPos.y() - pvtPos.y(), 0);
0231 auto cosAlpha = displVect2D.Dot(momentum) / (displVect2D.Rho() * momentum.rho());
0232
0233 auto ct = distXY.value() * cosAlpha * mass / momentum.rho();
0234
0235 histos.h_pointing->Fill(cosAlpha);
0236
0237 histos.h_mass->Fill(mass);
0238
0239 histos.h_pt->Fill(momentum.rho());
0240 histos.h_eta->Fill(momentum.eta());
0241 histos.h_phi->Fill(momentum.phi());
0242
0243 histos.h_ct->Fill(ct);
0244
0245 histos.h_displ2D->Fill(distXY.value());
0246 histos.h_sign2D->Fill(distXY.significance());
0247
0248 if (svtx.chi2() >= 0) {
0249 histos.h_vertNormChi2->Fill(svtx.chi2() / svtx.ndof());
0250 histos.h_vertProb->Fill(ChiSquaredProbability(svtx.chi2(), svtx.ndof()));
0251 }
0252
0253 return &*pvtx;
0254 }
0255
0256 void DiMuonMassBiasMonitor::fillComponentHistograms(ComponentHists const& histos,
0257 const reco::Track* const& component,
0258 reco::BeamSpot const* bs,
0259 reco::Vertex const* pv) const {
0260 histos.h_pt->Fill(component->pt());
0261 histos.h_eta->Fill(component->eta());
0262 histos.h_phi->Fill(component->phi());
0263
0264 math::XYZPoint zero(0, 0, 0);
0265 math::Error<3>::type zeroCov;
0266 if (bs) {
0267 histos.h_dxy->Fill(component->dxy(*bs));
0268 histos.h_exy->Fill(component->dxyError(*bs));
0269 } else {
0270 histos.h_dxy->Fill(component->dxy(zero));
0271 histos.h_exy->Fill(component->dxyError(zero, zeroCov));
0272 }
0273 if (pv) {
0274 histos.h_dz->Fill(component->dz(pv->position()));
0275 } else {
0276 histos.h_dz->Fill(component->dz(zero));
0277 }
0278 histos.h_ez->Fill(component->dzError());
0279
0280 histos.h_chi2->Fill(component->chi2() / component->ndof());
0281 }
0282
0283 void DiMuonMassBiasMonitor::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0284 edm::ParameterSetDescription desc;
0285 desc.add<edm::InputTag>("muonTracks", edm::InputTag("ALCARECOTkAlDiMuon"));
0286 desc.add<edm::InputTag>("vertices", edm::InputTag("offlinePrimaryVertices"));
0287 desc.add<edm::InputTag>("beamSpot", edm::InputTag("offlineBeamSpot"));
0288 desc.add<std::string>("FolderName", "DiMuonMassBiasMonitor");
0289 desc.add<std::string>("decayMotherName", "Z");
0290 desc.add<double>("distanceScaleFactor", 0.1);
0291
0292 {
0293 edm::ParameterSetDescription psDiMuMass;
0294 psDiMuMass.add<std::string>("name", "DiMuMass");
0295 psDiMuMass.add<std::string>("title", "M(#mu#mu)");
0296 psDiMuMass.add<std::string>("yUnits", "[GeV]");
0297 psDiMuMass.add<int>("NxBins", 24);
0298 psDiMuMass.add<int>("NyBins", 50);
0299 psDiMuMass.add<double>("ymin", 65.);
0300 psDiMuMass.add<double>("ymax", 115.);
0301 psDiMuMass.add<double>("maxDeltaEta", 3.7);
0302 desc.add<edm::ParameterSetDescription>("DiMuMassConfig", psDiMuMass);
0303 }
0304
0305 descriptions.addWithDefaultLabel(desc);
0306 }
0307
0308 DEFINE_FWK_MODULE(DiMuonMassBiasMonitor);