CMS 3D CMS Logo

DiMuonVertexMonitor.cc
Go to the documentation of this file.
1 /*
2  * See header file for a description of this class.
3  *
4  */
5 
6 #include <fmt/printf.h>
7 
21 
22 #include "TLorentzVector.h"
23 
24 namespace {
25  constexpr float cmToum = 10e4;
26  constexpr float mumass2 = 0.105658367 * 0.105658367; //mu mass squared (GeV^2/c^4)
27 } // namespace
28 
30  : ttbESToken_(esConsumes(edm::ESInputTag("", "TransientTrackBuilder"))),
31  tracksToken_(consumes<reco::TrackCollection>(iConfig.getParameter<edm::InputTag>("muonTracks"))),
32  vertexToken_(consumes<reco::VertexCollection>(iConfig.getParameter<edm::InputTag>("vertices"))),
33  motherName_(iConfig.getParameter<std::string>("decayMotherName")),
34  MEFolderName_(iConfig.getParameter<std::string>("FolderName")),
35  useClosestVertex_(iConfig.getParameter<bool>("useClosestVertex")),
36  maxSVdist_(iConfig.getParameter<double>("maxSVdist")) {
37  if (motherName_.find('Z') != std::string::npos) {
38  massLimits_ = std::make_pair(50., 120);
39  } else if (motherName_.find("J/#psi") != std::string::npos) {
40  massLimits_ = std::make_pair(2.7, 3.4);
41  } else if (motherName_.find("#Upsilon") != std::string::npos) {
42  massLimits_ = std::make_pair(8.9, 9.9);
43  } else {
44  edm::LogError("DiMuonVertexMonitor") << " unrecognized decay mother particle: " << motherName_
45  << " setting the default for the Z->mm (50.,120.)" << std::endl;
46  massLimits_ = std::make_pair(50., 120);
47  }
48 }
49 
51  iBooker.setCurrentFolder(MEFolderName_ + "/DiMuonVertexMonitor");
52 
53  // clang-format off
54  std::string ts = fmt::sprintf(";%s vertex probability;N(#mu#mu pairs)", motherName_);
55  std::string ps = "N(#mu#mu pairs)";
56  hSVProb_ = iBooker.book1D("VtxProb", ts, 100, 0., 1.);
57 
58  ts = fmt::sprintf("#chi^{2} of the %s vertex; #chi^{2} of the %s vertex; %s", motherName_, motherName_, ps);
59  hSVChi2_ = iBooker.book1D("VtxChi2", ts, 200, 0., 200.);
60 
61  ts = fmt::sprintf("#chi^{2}/ndf of the %s vertex; #chi^{2}/ndf of %s vertex; %s", motherName_, motherName_, ps);
62  hSVNormChi2_ = iBooker.book1D("VtxNormChi2", ts, 100, 0., 20.);
63 
64  std::string histTit = motherName_ + " #rightarrow #mu^{+}#mu^{-}";
65  ts = fmt::sprintf("%s;PV- %sV xy distance [#mum];%s", histTit, motherName_, ps);
66  hSVDist_ = iBooker.book1D("VtxDist", ts, 100, 0., 300.);
67 
68  ts = fmt::sprintf("%s;PV-%sV xy distance error [#mum];%s", histTit, motherName_, ps);
69  hSVDistErr_ = iBooker.book1D("VtxDistErr", ts, 100, 0., 1000.);
70 
71  ts = fmt::sprintf("%s;PV-%sV xy distance signficance;%s", histTit, motherName_, ps);
72  hSVDistSig_ = iBooker.book1D("VtxDistSig", ts, 100, 0., 5.);
73 
74  ts = fmt::sprintf("compatibility of %s vertex; compatibility of %s vertex; %s", motherName_, motherName_, ps);
75  hSVCompatibility_ = iBooker.book1D("VtxCompatibility", ts, 100, 0., 100.);
76 
77  ts = fmt::sprintf("%s;PV-%sV 3D distance [#mum];%s", histTit, motherName_, ps);
78  hSVDist3D_ = iBooker.book1D("VtxDist3D", ts, 100, 0., 300.);
79 
80  ts = fmt::sprintf("%s;PV-%sV 3D distance error [#mum];%s", histTit, motherName_, ps);
81  hSVDist3DErr_ = iBooker.book1D("VtxDist3DErr", ts, 100, 0., 1000.);
82 
83  ts = fmt::sprintf("%s;PV-%sV 3D distance signficance;%s", histTit, motherName_, ps);
84  hSVDist3DSig_ = iBooker.book1D("VtxDist3DSig", ts, 100, 0., 5.);
85 
86  ts = fmt::sprintf("3D compatibility of %s vertex;3D compatibility of %s vertex; %s", motherName_, motherName_, ps);
87  hSVCompatibility3D_ = iBooker.book1D("VtxCompatibility3D", ts, 100, 0., 100.);
88 
89  hInvMass_ = iBooker.book1D("InvMass", fmt::sprintf("%s;M(#mu,#mu) [GeV];%s", histTit, ps), 70., massLimits_.first, massLimits_.second);
90  hCosPhi_ = iBooker.book1D("CosPhi", fmt::sprintf("%s;cos(#phi_{xy});%s", histTit, ps), 50, -1., 1.);
91  hCosPhi3D_ = iBooker.book1D("CosPhi3D", fmt::sprintf("%s;cos(#phi_{3D});%s", histTit, ps), 50, -1., 1.);
92  hCosPhiInv_ = iBooker.book1D("CosPhiInv", fmt::sprintf("%s;inverted cos(#phi_{xy});%s", histTit, ps), 50, -1., 1.);
93  hCosPhiInv3D_ = iBooker.book1D("CosPhiInv3D", fmt::sprintf("%s;inverted cos(#phi_{3D});%s", histTit, ps), 50, -1., 1.);
94 
95  hdxy_ = iBooker.book1D("dxy", fmt::sprintf("%s;muon track d_{xy}(PV) [#mum];muon tracks", histTit), 150, -300, 300);
96  hdz_ = iBooker.book1D("dz", fmt::sprintf("%s;muon track d_{z}(PV) [#mum];muon tracks", histTit), 150, -300, 300);
97  hdxyErr_ = iBooker.book1D("dxyErr", fmt::sprintf("%s;muon track err_{dxy} [#mum];muon tracks", histTit), 250, 0., 500.);
98  hdzErr_ = iBooker.book1D("dzErr", fmt::sprintf("%s;muon track err_{dz} [#mum];muon tracks", histTit), 250, 0., 500.);
99  hIP2d_ = iBooker.book1D("IP2d", fmt::sprintf("%s;muon track IP_{2D} [#mum];muon tracks", histTit), 150, -300, 300);
100  hIP3d_ = iBooker.book1D("IP3d", fmt::sprintf("%s;muon track IP_{3D} [#mum];muon tracks", histTit), 150, -300, 300);
101  hIP2dsig_ = iBooker.book1D("IP2Dsig", fmt::sprintf("%s;muon track IP_{2D} significance;muon tracks", histTit), 100, 0., 5.);
102  hIP3dsig_ = iBooker.book1D("IP3Dsig", fmt::sprintf("%s;muon track IP_{3D} significance;muon tracks", histTit), 100, 0., 5.);
103  // clang-format on
104 }
105 
107  std::vector<const reco::Track*> myTracks;
108  const auto trackHandle = iEvent.getHandle(tracksToken_);
109  if (!trackHandle.isValid()) {
110  edm::LogError("DiMuonVertexMonitor") << "invalid track collection encountered!";
111  return;
112  }
113 
114  for (const auto& muonTrk : *trackHandle) {
115  myTracks.emplace_back(&muonTrk);
116  }
117 
118  const TransientTrackBuilder* theB = &iSetup.getData(ttbESToken_);
119  TransientVertex mumuTransientVtx;
120  std::vector<reco::TransientTrack> tks;
121 
122  if (myTracks.size() != 2) {
123  edm::LogWarning("DiMuonVertexMonitor") << "There are not enough tracks to monitor!";
124  return;
125  }
126 
127  const auto& t1 = myTracks[1]->momentum();
128  const auto& t0 = myTracks[0]->momentum();
129  const auto& ditrack = t1 + t0;
130 
131  const auto& tplus = myTracks[0]->charge() > 0 ? myTracks[0] : myTracks[1];
132  const auto& tminus = myTracks[0]->charge() < 0 ? myTracks[0] : myTracks[1];
133 
134  TLorentzVector p4_tplus(tplus->px(), tplus->py(), tplus->pz(), sqrt((tplus->p() * tplus->p()) + mumass2));
135  TLorentzVector p4_tminus(tminus->px(), tminus->py(), tminus->pz(), sqrt((tminus->p() * tminus->p()) + mumass2));
136 
137  const auto& Zp4 = p4_tplus + p4_tminus;
138  float track_invMass = Zp4.M();
139  hInvMass_->Fill(track_invMass);
140 
141  // creat the pair of TLorentVectors used to make the plos
142  std::pair<TLorentzVector, TLorentzVector> tktk_p4 = std::make_pair(p4_tplus, p4_tminus);
143 
144  math::XYZPoint ZpT(ditrack.x(), ditrack.y(), 0);
145  math::XYZPoint Zp(ditrack.x(), ditrack.y(), ditrack.z());
146 
147  for (const auto& track : myTracks) {
148  reco::TransientTrack trajectory = theB->build(track);
149  tks.push_back(trajectory);
150  }
151 
152  KalmanVertexFitter kalman(true);
153  mumuTransientVtx = kalman.vertex(tks);
154 
155  double SVProb = TMath::Prob(mumuTransientVtx.totalChiSquared(), (int)mumuTransientVtx.degreesOfFreedom());
156  hSVProb_->Fill(SVProb);
157  hSVChi2_->Fill(mumuTransientVtx.totalChiSquared());
158  hSVNormChi2_->Fill(mumuTransientVtx.totalChiSquared() / (int)mumuTransientVtx.degreesOfFreedom());
159 
160  if (!mumuTransientVtx.isValid())
161  return;
162 
163  const reco::Vertex* theClosestVertex;
164  // get collection of reconstructed vertices from event
165  edm::Handle<reco::VertexCollection> vertexHandle = iEvent.getHandle(vertexToken_);
166  if (vertexHandle.isValid()) {
167  const reco::VertexCollection* vertices = vertexHandle.product();
168  theClosestVertex = this->findClosestVertex(mumuTransientVtx, vertices);
169  } else {
170  edm::LogWarning("DiMuonVertexMonitor") << "invalid vertex collection encountered Skipping event!";
171  return;
172  }
173 
174  reco::Vertex theMainVtx;
175  if (!useClosestVertex_ || theClosestVertex == nullptr) {
176  theMainVtx = *theClosestVertex;
177  } else {
178  theMainVtx = vertexHandle.product()->front();
179  }
180 
181  const math::XYZPoint theMainVtxPos(theMainVtx.position().x(), theMainVtx.position().y(), theMainVtx.position().z());
182  const math::XYZPoint myVertex(
183  mumuTransientVtx.position().x(), mumuTransientVtx.position().y(), mumuTransientVtx.position().z());
184  const math::XYZPoint deltaVtx(
185  theMainVtxPos.x() - myVertex.x(), theMainVtxPos.y() - myVertex.y(), theMainVtxPos.z() - myVertex.z());
186 
187  if (theMainVtx.isValid()) {
188  // fill the impact parameter plots
189  for (const auto& track : myTracks) {
190  hdxy_->Fill(track->dxy(theMainVtxPos) * cmToum);
191  hdz_->Fill(track->dz(theMainVtxPos) * cmToum);
192  hdxyErr_->Fill(track->dxyError() * cmToum);
193  hdzErr_->Fill(track->dzError() * cmToum);
194 
195  const auto& ttrk = theB->build(track);
196  Global3DVector dir(track->px(), track->py(), track->pz());
197  const auto& ip2d = IPTools::signedTransverseImpactParameter(ttrk, dir, theMainVtx);
198  const auto& ip3d = IPTools::signedImpactParameter3D(ttrk, dir, theMainVtx);
199 
200  hIP2d_->Fill(ip2d.second.value() * cmToum);
201  hIP3d_->Fill(ip3d.second.value() * cmToum);
202  hIP2dsig_->Fill(ip2d.second.significance());
203  hIP3dsig_->Fill(ip3d.second.significance());
204  }
205 
206  // Z Vertex distance in the xy plane
207  VertexDistanceXY vertTool;
208  double distance = vertTool.distance(mumuTransientVtx, theMainVtx).value();
209  double dist_err = vertTool.distance(mumuTransientVtx, theMainVtx).error();
210  float compatibility = 0.;
211 
212  try {
213  compatibility = vertTool.compatibility(mumuTransientVtx, theMainVtx);
214  } catch (cms::Exception& er) {
215  LogTrace("DiMuonVertexMonitor") << "caught std::exception " << er.what() << std::endl;
216  }
217 
218  hSVCompatibility_->Fill(compatibility);
220  hSVDistErr_->Fill(dist_err * cmToum);
221  hSVDistSig_->Fill(distance / dist_err);
222 
223  // Z Vertex distance in 3D
224  VertexDistance3D vertTool3D;
225  double distance3D = vertTool3D.distance(mumuTransientVtx, theMainVtx).value();
226  double dist3D_err = vertTool3D.distance(mumuTransientVtx, theMainVtx).error();
227  float compatibility3D = 0.;
228 
229  try {
230  compatibility3D = vertTool3D.compatibility(mumuTransientVtx, theMainVtx);
231  } catch (cms::Exception& er) {
232  LogTrace("DiMuonVertexMonitor") << "caught std::exception " << er.what() << std::endl;
233  }
234 
235  hSVCompatibility3D_->Fill(compatibility3D);
236  hSVDist3D_->Fill(distance3D * cmToum);
237  hSVDist3DErr_->Fill(dist3D_err * cmToum);
238  hSVDist3DSig_->Fill(distance3D / dist3D_err);
239 
240  // cut on the PV - SV distance
241  if (distance * cmToum < maxSVdist_) {
242  double cosphi = (ZpT.x() * deltaVtx.x() + ZpT.y() * deltaVtx.y()) /
243  (sqrt(ZpT.x() * ZpT.x() + ZpT.y() * ZpT.y()) *
244  sqrt(deltaVtx.x() * deltaVtx.x() + deltaVtx.y() * deltaVtx.y()));
245 
246  double cosphi3D = (Zp.x() * deltaVtx.x() + Zp.y() * deltaVtx.y() + Zp.z() * deltaVtx.z()) /
247  (sqrt(Zp.x() * Zp.x() + Zp.y() * Zp.y() + Zp.z() * Zp.z()) *
248  sqrt(deltaVtx.x() * deltaVtx.x() + deltaVtx.y() * deltaVtx.y() + deltaVtx.z() * deltaVtx.z()));
249 
250  hCosPhi_->Fill(cosphi);
251  hCosPhi3D_->Fill(cosphi3D);
252  // inverted
253  hCosPhiInv_->Fill(-cosphi);
254  hCosPhiInv3D_->Fill(-cosphi3D);
255  }
256  } else {
257  edm::LogWarning("DiMuonVertexMonitor") << "hardest primary vertex in the event is not valid!";
258  }
259 }
260 
261 // compute the closest vertex to di-lepton ------------------------------------
263  const reco::VertexCollection* vertices) const {
264  reco::Vertex* defaultVtx = nullptr;
265 
266  if (!aTransVtx.isValid())
267  return defaultVtx;
268 
269  // find the closest vertex to the secondary vertex in 3D
270  VertexDistance3D vertTool3D;
271  float minD = 9999.;
272  int closestVtxIndex = 0;
273  int counter = 0;
274  for (const auto& vtx : *vertices) {
275  double dist3D = vertTool3D.distance(aTransVtx, vtx).value();
276  if (dist3D < minD) {
277  minD = dist3D;
278  closestVtxIndex = counter;
279  }
280  counter++;
281  }
282 
283  if ((*vertices).at(closestVtxIndex).isValid()) {
284  return &(vertices->at(closestVtxIndex));
285  } else {
286  return defaultVtx;
287  }
288 }
289 
292  desc.add<edm::InputTag>("muonTracks", edm::InputTag("ALCARECOTkAlDiMuon"));
293  desc.add<edm::InputTag>("vertices", edm::InputTag("offlinePrimaryVertices"));
294  desc.add<std::string>("FolderName", "DiMuonVertexMonitor");
295  desc.add<std::string>("decayMotherName", "Z");
296  desc.add<bool>("useClosestVertex", true);
297  desc.add<double>("maxSVdist", 50.);
298  descriptions.addWithDefaultLabel(desc);
299 }
300 
MonitorElement * hdxyErr_
const std::string MEFolderName_
void addWithDefaultLabel(ParameterSetDescription const &psetDescription)
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
float totalChiSquared() const
MonitorElement * hIP2d_
MonitorElement * hCosPhiInv_
std::pair< float, float > massLimits_
GlobalPoint position() const
MonitorElement * hSVDist3DErr_
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:36
MonitorElement * hIP2dsig_
Measurement1D distance(const GlobalPoint &vtx1Position, const GlobalError &vtx1PositionError, const GlobalPoint &vtx2Position, const GlobalError &vtx2PositionError) const override
MonitorElement * hSVProb_
T z() const
Definition: PV3DBase.h:61
static constexpr float mumass2
const Point & position() const
position
Definition: Vertex.h:127
std::pair< bool, Measurement1D > signedTransverseImpactParameter(const reco::TransientTrack &track, const GlobalVector &direction, const reco::Vertex &vertex)
Definition: IPTools.cc:57
T const * product() const
Definition: Handle.h:70
std::vector< Track > TrackCollection
collection of Tracks
Definition: TrackFwd.h:14
MonitorElement * hdz_
std::pair< bool, Measurement1D > signedImpactParameter3D(const reco::TransientTrack &track, const GlobalVector &direction, const reco::Vertex &vertex)
Definition: IPTools.cc:81
MonitorElement * hCosPhi_
MonitorElement * hSVCompatibility_
std::vector< Vertex > VertexCollection
collection of Vertex objects
Definition: VertexFwd.h:9
Log< level::Error, false > LogError
std::vector< Vertex > VertexCollection
Definition: Vertex.h:31
float degreesOfFreedom() const
MonitorElement * hIP3dsig_
const std::string motherName_
MonitorElement * hSVNormChi2_
#define LogTrace(id)
MonitorElement * hdxy_
CachingVertex< 5 > vertex(const std::vector< reco::TransientTrack > &tracks) const override
MonitorElement * hCosPhiInv3D_
reco::TransientTrack build(const reco::Track *p) const
void Fill(long long x)
MonitorElement * hSVDist3D_
T x() const
Definition: PV3DBase.h:59
T y() const
Definition: PV3DBase.h:60
MonitorElement * hSVDist3DSig_
DiMuonVertexMonitor(const edm::ParameterSet &)
int iEvent
Definition: GenABIO.cc:224
bool isValid() const
MonitorElement * hSVChi2_
T sqrt(T t)
Definition: SSEVec.h:19
const reco::Vertex * findClosestVertex(const TransientVertex aTransVtx, const reco::VertexCollection *vertices) const
const edm::EDGetTokenT< reco::TrackCollection > tracksToken_
void bookHistograms(DQMStore::IBooker &, edm::Run const &, edm::EventSetup const &) override
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
MonitorElement * hSVDistSig_
bool getData(T &iHolder) const
Definition: EventSetup.h:122
Measurement1D distance(const GlobalPoint &vtx1Position, const GlobalError &vtx1PositionError, const GlobalPoint &vtx2Position, const GlobalError &vtx2PositionError) const override
void analyze(const edm::Event &, const edm::EventSetup &) override
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
MonitorElement * hSVDist_
bool isValid() const
Definition: HandleBase.h:70
double value() const
Definition: Measurement1D.h:25
MonitorElement * hIP3d_
float compatibility(const GlobalPoint &vtx1Position, const GlobalError &vtx1PositionError, const GlobalPoint &vtx2Position, const GlobalError &vtx2PositionError) const override
MonitorElement * hSVCompatibility3D_
fixed size matrix
HLT enums.
const edm::EDGetTokenT< reco::VertexCollection > vertexToken_
static std::atomic< unsigned int > counter
MonitorElement * hSVDistErr_
double error() const
Definition: Measurement1D.h:27
MonitorElement * hCosPhi3D_
MonitorElement * hdzErr_
Log< level::Warning, false > LogWarning
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:98
char const * what() const noexcept override
Definition: Exception.cc:103
static constexpr float cmToum
bool isValid() const
Tells whether the vertex is valid.
Definition: Vertex.h:72
const edm::ESGetToken< TransientTrackBuilder, TransientTrackRecord > ttbESToken_
Definition: Run.h:45
MonitorElement * hInvMass_
float compatibility(const GlobalPoint &vtx1Position, const GlobalError &vtx1PositionError, const GlobalPoint &vtx2Position, const GlobalError &vtx2PositionError) const override
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)