ATLAS Offline Software
BPhysAddMuonBasedInvMass.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3 */
4 
10 // includes
15 #include "xAODMuon/MuonContainer.h"
17 #include "xAODBPhys/BPhysHelper.h"
18 // for Amg::error():
20 
21 #include <sstream>
22 #include <limits>
23 
24 namespace DerivationFramework {
25 
26 
27  struct BasedInvCache{
28  BasedInvCache(const EventContext& c = Gaudi::Hive::currentContext()) : ctx(c){}
30  typedef std::map<const xAOD::TrackParticle*, const xAOD::TrackParticle*>
34  const EventContext& ctx;
36  for (auto& p : adjTpCache) {
37  delete(p.second);
38  }
39  }
40  };
41 
42 
43  //--------------------------------------------------------------------------
45  const std::string& n,
46  const IInterface* p)
47  : AthAlgTool(t,n,p), m_trackToVertexTool("Reco::TrackToVertex") {
48 
49  declareInterface<DerivationFramework::IAugmentationTool>(this);
50 
51  // Declare branch prefix
52  declareProperty("BranchPrefix", m_branchPrefix = "_NONE_");
53  // Necessary containers
54  declareProperty("VertexContainerName" , m_vertexContainerName = "");
55  // track mass assignment
56  declareProperty("TrkMasses", m_trkMasses = std::vector<double>());
57  // track-to-vertex tool
58  declareProperty("TrackToVertexTool" , m_trackToVertexTool);
59  // adjust track from muon kinematics?
60  declareProperty("AdjustToMuonKinematics", m_adjustToMuonKinematics = false);
61  // add minChi2ToAnyPV decoration
62  declareProperty("AddMinChi2ToAnyPVMode" , m_addMinChi2ToAnyPVMode = 0);
63  // name of container for primary vertices
64  declareProperty("PrimaryVertexContainerName", m_pvContainerName = "");
65  // minimum number of tracks in PV for PV to be considered in calculation
66  // of minChi2MuToAnyPV variable
67  declareProperty("MinNTracksInPV" , m_minNTracksInPV = 0);
68  // list of primary vertex types to consider
69  declareProperty("PVTypesToConsider" , m_pvTypesToConsider = {1,3});
70  // PV-to-SV association types to be considered
71  declareProperty("DoVertexType" , m_doVertexType = 63);
72  }
73  //--------------------------------------------------------------------------
75 
76  ATH_MSG_DEBUG("BPhysAddMuonBasedInvMass::initialize() -- begin");
77 
78  // candidate vertices container
79  if ( m_vertexContainerName == "" ) {
80  ATH_MSG_ERROR("No vertex container name provided!");
81  }
82 
83  // TrackToVertexTool
84  CHECK(m_trackToVertexTool.retrieve());
85 
86  // PV container if needed
87  if ( m_addMinChi2ToAnyPVMode > 0 && m_pvContainerName == "" ) {
88  ATH_MSG_ERROR("No primary vertex container name provided!");
89  }
90 
91  // PV type list if needed
92  if ( m_addMinChi2ToAnyPVMode > 0 && m_pvTypesToConsider.size() == 0 ) {
93  ATH_MSG_ERROR("No primary vertex types to be considered provided!");
94  }
95 
96  // PV-to-SV association type if needed
97  if ( m_addMinChi2ToAnyPVMode > 1 && m_doVertexType < 1 ) {
98  ATH_MSG_ERROR("No PV-to-SV association types to be considered provided!");
99  }
100 
101  ATH_MSG_INFO("BPhysAddMuonBasedInvMass::initialize(): "
102  << "AdjustToMuonKinematics = " << m_adjustToMuonKinematics);
103 
104  ATH_MSG_INFO("BPhysAddMuonBasedInvMass::initialize(): "
105  << "AddMinChi2ToAnyPVMode = " << m_addMinChi2ToAnyPVMode);
106 
107  // initialize PV-to-SV association type vector
109 
110  ATH_MSG_DEBUG("BPhysAddMuonBasedInvMass::initialize() -- end");
111 
112  return StatusCode::SUCCESS;
113  }
114  //--------------------------------------------------------------------------
116 
117  ATH_MSG_DEBUG("BPhysAddMuonBasedInvMass::finalize()");
118 
119  // everything all right
120  return StatusCode::SUCCESS;
121  }
122  //--------------------------------------------------------------------------
124 
125  ATH_MSG_DEBUG("BPhysAddMuonBasedInvMass::addBranches() -- begin");
126  BasedInvCache cache;
127  // vertex container and its auxilliary store
128  xAOD::VertexContainer* vtxContainer = NULL;
129  xAOD::VertexAuxContainer* vtxAuxContainer = NULL;
130 
131  // retrieve from StoreGate
132  CHECK(evtStore()->retrieve(vtxContainer , m_vertexContainerName));
133  CHECK(evtStore()->retrieve(vtxAuxContainer, m_vertexContainerName+"Aux."));
134 
135  const xAOD::VertexContainer* pvContainer = NULL;
136  if ( m_addMinChi2ToAnyPVMode > 0 ) {
137  CHECK(evtStore()->retrieve(pvContainer , m_pvContainerName));
138  }
139 
140  // apply the decorations
141  std::string branchPrefix("");
142  if ( m_branchPrefix != "" && m_branchPrefix != "_NONE_" ) {
143  branchPrefix = m_branchPrefix + "_";
144  }
145 
146  // loop over secondary vertices
147  for (xAOD::VertexContainer::iterator vtxItr = vtxContainer->begin();
148  vtxItr!=vtxContainer->end(); ++vtxItr) {
149 
150  xAOD::BPhysHelper vtx(*vtxItr);
151 
153  d_mucalc_mass(branchPrefix+"MUCALC_mass");
155  d_mucalc_massErr(branchPrefix+"MUCALC_massErr");
156 
157  // TODO: check number of muons requested!
158  std::pair<double,double> MuCalcCandMass =
159  getMuCalcMass(vtx, m_trkMasses, 2, cache);
160 
161  // fill default values
162  d_mucalc_mass(**vtxItr) = MuCalcCandMass.first;
163  d_mucalc_massErr(**vtxItr) = MuCalcCandMass.second;
164 
165  // add MinChi2ToAnyPV information if requested
166  if ( m_addMinChi2ToAnyPVMode > 0 ) {
167 
168  if (m_addMinChi2ToAnyPVMode == 1) {
169  // w.r.t. to all PVs
171  d_minChi2ToAnyPV(branchPrefix+"minLogChi2ToAnyPV");
172  // fill it
173  d_minChi2ToAnyPV(**vtxItr) =
174  getMinChi2ToAnyPV(vtx, pvContainer, m_pvTypesToConsider,
176  xAOD::BPhysHelper::PV_MIN_A0, cache); // dummy
177  } else if (m_addMinChi2ToAnyPVMode > 1 && m_addMinChi2ToAnyPVMode < 4) {
178  // skip or replace associated PVs
179  for (auto pvAssocType : m_pvAssocTypes) {
181  d_minChi2ToAnyPV(branchPrefix+"minLogChi2ToAnyPV_"
182  +xAOD::BPhysHelper::pv_type_str[pvAssocType]);
183  // fill it
184  d_minChi2ToAnyPV(**vtxItr) =
185  getMinChi2ToAnyPV(vtx, pvContainer, m_pvTypesToConsider,
187  pvAssocType, cache);
188 
189  } // for pvAssocType
190  } else {
191  ATH_MSG_WARNING("BPhysAddMuonBasedInvMass::addBranches():"
192  << " Undefined AddMinChi2ToAnyPVMode value: "
194  }
195  } // if m_addMinChi2ToAnyPVMode
196  } // end of loop over vertices
197 
198 
199  ATH_MSG_DEBUG("BPhysAddMuonBasedInvMass::addBranches() -- end");
200 
201  // nothing to do here
202  return StatusCode::SUCCESS;
203  }
204  //--------------------------------------------------------------------------
205  // Calculate invariant mass based on muon system information if available.
206  //
207  std::pair<double, double>
209  const std::vector<double> &trkMasses,
210  int nMuRequested, BasedInvCache &cache) const {
211 
212  std::pair<double, double> mpe(0., -1.);
213 
214  std::pair<TrackBag, int> tracksWithMu = getTracksWithMuons(vtx, cache);
215 
216  if ( tracksWithMu.second == nMuRequested ) {
217  if ( tracksWithMu.first.size() == trkMasses.size() ) {
218  mpe = getInvariantMassWithError(tracksWithMu.first,
219  trkMasses,
220  vtx.vtx()->position(), cache);
221  } else {
222  ATH_MSG_WARNING("BPhysAddMuonBasedInvMass::getMuCalcMass:"
223  << " vector sizes disagree!"
224  << " tracksWithMu: " << tracksWithMu.first.size()
225  << " BtrkMasses: " << trkMasses.size());
226  }
227  } else {
228  mpe.second = -10 - tracksWithMu.second;
229  ATH_MSG_DEBUG("BPhysAddMuonBasedInvMass::getMuCalcMass:"
230  << " muon number mismatch:"
231  << " tracksWithMu: " << tracksWithMu.second
232  << " requested: " << nMuRequested);
233  }
234  return mpe;
235  }
236  //--------------------------------------------------------------------------
237  // Obtain a set of ID tracks for a set of muons
238  //--------------------------------------------------------------------------
240 
241  TrackBag muTracks;
242 
243  for (auto &muon : muons) {
244  if ( muon != nullptr ) {
245  const xAOD::TrackParticle* trk =
246  muon->trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
247  if ( trk != nullptr ) {
248  muTracks.push_back(trk);
249  } else {
250  ATH_MSG_WARNING("BPhysAddMuonBasedInvMass::getIdTracksForMuon:"
251  << " no ID track for muon found.");
252  }
253  } else {
254  ATH_MSG_WARNING("BPhysAddMuonBasedInvMass::getIdTracksForMuon:"
255  << " muon pointer is NULL!");
256  }
257  } // for muon
258  return muTracks;
259  }
260  //--------------------------------------------------------------------------
261  // Obtain a set of tracks with muon track information if available
262  //--------------------------------------------------------------------------
263  std::pair<TrackBag, int>
265 
266  TrackBag tracksWithMu;
267  int nMuFound = 0;
268  std::vector<int> vnMuFound;
269 
270  MuonBag muons = findAllMuonsInDecay(vtx);
271 
272  if ( muons.size() > 0 ) {
273  for (int itrk=0; itrk<vtx.nRefTrks(); ++itrk) {
274  // only charged tracks are of interest
275  if ( abs(vtx.refTrkCharge(itrk)) > 0. ) {
276  const xAOD::TrackParticle* trkParticle =
277  (xAOD::TrackParticle*)vtx.refTrkOrigin(itrk);
278  for (unsigned int imu = 0; imu<muons.size(); ++imu) {
279  if ( vtx.refTrkOrigin(itrk) ==
280  muons.at(imu)->trackParticle(xAOD::Muon::InnerDetectorTrackParticle) ) {
281  const xAOD::TrackParticle* trkMuon =
282  adjustTrackParticle(muons.at(imu), cache);
283  if ( trkMuon != NULL ) {
284  trkParticle = trkMuon;
285  nMuFound++;
286  break;
287  }
288  }
289  } // for imu
290  tracksWithMu.push_back(trkParticle);
291  vnMuFound.push_back(nMuFound);
292  } // for charged track
293  } // for itrk
294  } else {
295  ATH_MSG_DEBUG("BPhysAddMuonBasedInvMass::getTracksWithMuons: "
296  "vertex contains no muons, but "
297  << vtx.nRefTrks() << " refitted tracks ...");
298  }
299  // debug output
300  std::string svnMuFound = "[";
301  for (unsigned int i=0; i<vnMuFound.size(); ++i) {
302  svnMuFound += std::to_string(vnMuFound[i]) + ',';
303  }
304  svnMuFound.back() = ']';
305  ATH_MSG_DEBUG("BPhysAddMuonBasedInvMass::getTracksWithMuons: "
306  "nMuFound = " << nMuFound
307  << "\nvnMuFound = " << svnMuFound );
308 
309  return std::pair<TrackBag, int>(std::move(tracksWithMu), nMuFound);
310  }
311  //--------------------------------------------------------------------------
312  // adjustTrackParticle: extract primary track particle from muon
313  // if configured adjust pt, eta and phi of it before returning
314  // a pointer to it.
315  //--------------------------------------------------------------------------
317  ::adjustTrackParticle(const xAOD::Muon* muon, BasedInvCache &cache) const {
318 
319  const xAOD::TrackParticle* tp = NULL;
320  const xAOD::TrackParticle* org = muon->primaryTrackParticle();
321 
322  if ( m_adjustToMuonKinematics ) {
323  if ( org != NULL ) {
324  auto it = cache.adjTpCache.find(org);
325  if ( it != cache.adjTpCache.end() ) {
326  // copy cached link
327  tp = it->second;
328  ATH_MSG_DEBUG("adjustTrackParticle(): from cache: tp = " << tp);
329  } else {
330  // copy object -- this does not work because of seg fault later
331  // xAOD::TrackParticle* newTp = new xAOD::TrackParticle(*org);
332 
333  // create new object and copy properties
335  newTp->makePrivateStore(*org);
336 
337  // ajdust pt, eta and phi to the muon's properties
338  xAOD::IParticle::FourMom_t p4 = muon->p4();
339  float qoverp = p4.P() > 0. ? 1./p4.P() : 10.e6;
340  if ( org->qOverP() < 0. ) qoverp *= -1.;
341  newTp->setDefiningParameters(org->d0(), org->z0(),
342  p4.Phi(), p4.Theta(), qoverp);
343  // cache new TrackParticle
344  cache.adjTpCache[org] = newTp;
345  tp = newTp;
346  ATH_MSG_DEBUG("adjustTrackParticle(): new tp = " << tp
347  << " org = " << org);
348  } // if it != end()
349  } // if != NULL
350  } else {
351  // copy pointer
352  tp = org;
353  ATH_MSG_DEBUG("adjustTrackParticle(): copy: org: " << org
354  << " -> tp: " << tp);
355  }
356 
357  // debug output
358  if ( org != NULL ) {
359  ATH_MSG_DEBUG("adjustTrackParticle(): org: " << org << " ("
360  << org->d0() << "," << org->z0() << "," << org->phi0()
361  << "," << org->theta() << "," << org->qOverP() << ") pt: "
362  << org->pt());
363  } else {
364  ATH_MSG_DEBUG("adjustTrackParticle(): org = NULL");
365  }
366  if ( org != NULL ) {
367  ATH_MSG_DEBUG("adjustTrackParticle(): tp : " << tp << " ("
368  << tp->d0() << "," << tp->z0() << "," << tp->phi0()
369  << "," << tp->theta() << "," << tp->qOverP() << ") pt: "
370  << tp->pt());
371  } else {
372  ATH_MSG_DEBUG("adjustTrackParticle(): tp = NULL");
373  }
374  return tp;
375  }
376 
377  //--------------------------------------------------------------------------
378  // findAllMuonsInDecay: returns a vector of xAOD::Muon objects found
379  // in this vertex and subsequent decay vertices.
380  // Recursively calls itself if necessary.
381  //--------------------------------------------------------------------------
383  const {
384 
385  MuonBag muons = vtx.muons();
386 
387  // loop over preceeding vertices
388  for (int ivtx = 0; ivtx < vtx.nPrecedingVertices(); ++ivtx) {
389  xAOD::BPhysHelper precVtx(vtx.precedingVertex(ivtx));
390  MuonBag muonsForVtx = findAllMuonsInDecay(precVtx);
391  muons.insert(muons.end(), muonsForVtx.begin(), muonsForVtx.end());
392  }
393  return muons;
394  }
395  //--------------------------------------------------------------------------
396  // getMinChi2ToAnyPV:
397  // Find minimum chi2 distance of signal muons w.r.t any primary vertex
398  // of required types and with a minimum number of tracks cut.
399  // It also depends on the mode w.r.t. the treatment of the associated
400  // primary vertex and the type of PV-to-SV association.
401  // Returns this minimum chi2.
402  //--------------------------------------------------------------------------
403  double
405  const xAOD::VertexContainer*
406  pvContainer,
407  const std::vector<int>& pvtypes,
408  const int minNTracksInPV,
409  const int mode,
411  pvAssocType,
412  BasedInvCache &cache) const {
413 
414  MuonBag muons = findAllMuonsInDecay(vtx);
415  TrackBag tracks = getIdTracksForMuons(muons);
416  const xAOD::Vertex* origPV = nullptr;
417  const xAOD::Vertex* refPV = nullptr;
418 
419  if ( mode > 1 ) {
420  // need to obtain original PV
421  origPV = vtx.origPv(pvAssocType);
422  if ( origPV == nullptr ) {
423  ATH_MSG_WARNING("BPhysAddMuonBasedInvMass::getMinChi2ToAnyPV:"
424  << " origPV == NULL for pvAssocType = "
425  << pvAssocType);
426  }
427  if ( mode > 2 ) {
428  refPV = vtx.pv(pvAssocType);
429  if ( refPV == nullptr ) {
430  ATH_MSG_WARNING("BPhysAddMuonBasedInvMass::getMinChi2ToAnyPV:"
431  << " refPV == NULL for pvAssocType = "
432  << pvAssocType);
433  }
434  }
435  }
436 
437  double minChi2 = std::numeric_limits<double>::max();
438 
439  for (const auto pvtx : *pvContainer) {
440  if ( pvtx != nullptr ) {
441  if ( std::find(pvtypes.begin(),pvtypes.end(),pvtx->vertexType())
442  != pvtypes.end() ) {
443  const xAOD::Vertex* cvtx = pvtx;
444  // switch if PV matches original PV and replacement is requested
445  if ( mode > 1 && pvtx == origPV ) {
446  // mode 2 -- skip
447  switch(mode) {
448  case 2: // skip current PV
449  continue;
450  break;
451  case 3: // replace by refitted PV
452  if ( refPV != nullptr ) {
453  cvtx = refPV;
454  } else {
455  ATH_MSG_WARNING("BPhysAddMuonBasedInvMass::getMinChi2ToAnyPV:"
456  << " refPV == NULL!");
457  continue;
458  }
459  break;
460  }
461  }
462  if ( (int)cvtx->nTrackParticles() >= minNTracksInPV ) {
463  for (auto &track : tracks) {
464  const Amg::Vector3D pos = cvtx->position();
465  minChi2 = std::min(minChi2, getTrackPVChi2(*track, pos, cache));
466  } // for track
467  } // if minNTracksInPV
468  } // if pvTypes in pvtypes vector
469  } else {
470  ATH_MSG_WARNING("BPhysAddMuonBasedInvMass::getMinChi2ToAnyPV:"
471  << " pvtx == NULL!");
472  } // if vtx != nullptr
473  } // for pvtx
474 
475  return minChi2;
476  }
477  //--------------------------------------------------------------------------
478  // getTrackPVChi2:
479  // Calculate the chi2 ( = log((d0/d0e)^2+(z0/z0e)^2) contribution of
480  // a track at the position closest to the given PV.
481  //--------------------------------------------------------------------------
482  double
484  const Amg::Vector3D& pos, BasedInvCache &cache) const {
485 
486  double chi2 = -100.;
487 
488  auto trkPerigee =
489  m_trackToVertexTool->perigeeAtVertex(cache.ctx, track, pos);
490  if ( trkPerigee != NULL ) {
491  const AmgSymMatrix(5)* locError = trkPerigee->covariance();
492  if ( locError != NULL ) {
493  double d0 = trkPerigee->parameters()[Trk::d0];
494  double z0 = trkPerigee->parameters()[Trk::z0];
495  double d0Err = Amg::error(*locError, Trk::d0);
496  double z0Err = Amg::error(*locError, Trk::z0);
497  if (fabs(d0Err) > 0. && fabs(z0Err) > 0.) {
498  chi2 = log( pow(d0/d0Err,2.0) + pow(z0/z0Err,2.0) );
499  } else {
500  ATH_MSG_WARNING("BPhysAddMuonBasedInvMass::getTrackPVChi2():"
501  << " d0 = " << d0 << ", d0Err = " << d0Err
502  << ", z0 = " << z0 << ", z0Err = " << z0Err);
503  }
504  } // locError != NULL
505  } else {
506  ATH_MSG_WARNING("getTrackPVChi2: Could not get perigee");
507  }
508 
509  return chi2;
510 }
511  //--------------------------------------------------------------------------
512  // getInvariantMassWithError: returns invariant mass and mass error given
513  // a set of tracks, their mass hypotheses and a reference position.
514  // Each track must have a separate mass hypothesis in
515  // the vector, and they must be in the same order as the tracks in the
516  // track vector. Otherwise it will go horribly wrong.
517  //--------------------------------------------------------------------------
518  std::pair<double,double> BPhysAddMuonBasedInvMass::
520  const std::vector<double> &massHypotheses,
521  const Amg::Vector3D& pos,
522  BasedInvCache &cache) const {
523 
524  std::pair<double, double> mass(0.,0.);
525 
526  // ensure there is a mass hypothesis for each track
527  if ( trksIn.size() == massHypotheses.size() ) {
530  auto massHypItr = massHypotheses.cbegin();
531 
532  double pxTmp,pyTmp,pzTmp,massTmp,eTmp;
533 
534  std::vector<TLorentzVector> trkMom;
535  TLorentzVector totMom;
536  std::vector<const Trk::Perigee*> trkPer;
537  const auto &ctx = cache.ctx;
538  for (;trItr != trItrEnd; ++trItr,++massHypItr){
539  auto trkPerigee =
540  m_trackToVertexTool->perigeeAtVertex(ctx, *(*trItr), pos);
541 
542  if ( trkPerigee != NULL ) {
543  // try to get the correct momentum measurement
544  pxTmp = trkPerigee->momentum()[Trk::px];
545  pyTmp = trkPerigee->momentum()[Trk::py];
546  pzTmp = trkPerigee->momentum()[Trk::pz];
547  ATH_MSG_DEBUG("getInvariantMassWithError(): pvec = ("
548  << pxTmp << "," << pyTmp << "," << pzTmp << ")");
549  } else {
550  // otherwise default to this one
551  pxTmp = ((*trItr)->p4()).Px();
552  pyTmp = ((*trItr)->p4()).Py();
553  pzTmp = ((*trItr)->p4()).Pz();
554  ATH_MSG_WARNING("BPhysAddMuonBasedInvMass::getInvariantMassError: "
555  "defaulting to simple momentum!");
556  }
557  trkPer.push_back(trkPerigee.release());
558  massTmp = *massHypItr;
559  eTmp = pxTmp*pxTmp+pyTmp*pyTmp+pzTmp*pzTmp+massTmp*massTmp;
560  eTmp = eTmp > 0. ? sqrt(eTmp) : 0.;
561  TLorentzVector tmpMom(pxTmp, pyTmp, pzTmp, eTmp);
562  trkMom.push_back(tmpMom);
563  totMom += tmpMom;
564  }
565  mass.first = totMom.M();
566  double mErr2 = 0.;
567  // reset trItr
568  trItr = trksIn.begin();
569  std::vector<TLorentzVector>::iterator tmItr = trkMom.begin();
570  std::vector<const Trk::Perigee*>::iterator perItr = trkPer.begin();
571  AmgVector(3) dMdP;
572  dMdP.setZero();
573  for (; tmItr != trkMom.end(); ++tmItr, ++trItr, ++perItr) {
574  dMdP(0) = (totMom.E() * tmItr->Px()/tmItr->E() - totMom.Px())/totMom.M();
575  dMdP(1) = (totMom.E() * tmItr->Py()/tmItr->E() - totMom.Py())/totMom.M();
576  dMdP(2) = (totMom.E() * tmItr->Pz()/tmItr->E() - totMom.Pz())/totMom.M();
577  if ( *perItr != NULL ) {
578  mErr2 += (dMdP.transpose() * getMomentumCov(*perItr) * dMdP)(0,0);
579  } else {
580  mErr2 += (dMdP.transpose() * getMomentumCov(*trItr ) * dMdP)(0,0);
581  }
582  }
583  mass.second = mErr2 > 0. ? sqrt(mErr2) : 0.;
584  // clean up
585  for ( perItr = trkPer.begin(); perItr != trkPer.end(); ++perItr) {
586  delete (*perItr);
587  }
588  } else {
589  ATH_MSG_WARNING("BPhysAddMuonBasedInvMass::getInvariantMassError: "
590  "size mismatch of tracks and mass hypotheses vectors!");
591  } // if size comparison
592 
593  return mass;
594  }
595  //--------------------------------------------------------------------------
596  //
597  // Extract the 3x3 momentum covariance matrix in (x,y,z) notation
598  // from the (phi, theta, qoverp) notation from a TrackParticle.
599  //
600  //--------------------------------------------------------------------------
602  ::getMomentumCov(const xAOD::TrackParticle* track) const {
603 
604  AmgSymMatrix(3) cov;
605  cov.setZero();
606 
607  if ( track != NULL ) {
608  cov = getMomentumCov( &track->perigeeParameters() );
609  }
610  return cov;
611  }
612  //--------------------------------------------------------------------------
613  //
614  // Extract the 3x3 momentum covariance matrix in (x,y,z) notation
615  // from the (phi, theta, qoverp) notation from a Perigee.
616  //
617  //--------------------------------------------------------------------------
618  AmgSymMatrix(3) BPhysAddMuonBasedInvMass
619  ::getMomentumCov(const Trk::Perigee* perigee) const {
620 
621  AmgSymMatrix(3) cov;
622  cov.setZero();
623 
624  if ( perigee != NULL ) {
625  cov = getMomentumCov(perigee->parameters(), *perigee->covariance());
626  }
627  return cov;
628  }
629  //--------------------------------------------------------------------------
630  // Extract the 3x3 momentum covariance matrix in (x,y,z) notation
631  // from the (phi, theta, qoverp) notation from a vector of
632  // track parameters and the error matrix
633  //
634  // Coding ideas orignally taken from
635  // V0Tools::massErrorVKalVrt(...),
636  // Code converted from BPhysToolBox::getMomentumCov(...).
637  //--------------------------------------------------------------------------
638  //
639  AmgSymMatrix(3) BPhysAddMuonBasedInvMass
640  ::getMomentumCov(const AmgVector(5)& pars,
641  const AmgSymMatrix(5)& cMatrix) const {
642 
643  AmgSymMatrix(3) cov;
644  cov.setZero();
645 
646  AmgMatrix(3,3) der;
647  der.setZero();
648 
649  double phi = pars[Trk::phi];
650  double theta = pars[Trk::theta];
651  double qoverp = pars[Trk::qOverP];
652 
653  if ( qoverp != 0. ) {
654  AmgVector(3) p( cos(phi)*sin(theta)/fabs(qoverp),
655  sin(phi)*sin(theta)/fabs(qoverp),
656  cos(theta)/fabs(qoverp) );
657 
658  // d(px,py,pz)/d(phi,theta,qoverp)
659  der(0,0) = - p.y();
660  der(1,0) = p.x();
661  der(2,0) = 0.;
662  der(0,1) = cos(phi) * p.z();
663  der(1,1) = sin(phi) * p.z();
664  der(2,1) = - sin(theta) / fabs(qoverp);
665  der(0,2) = - p.x()/qoverp;
666  der(1,2) = - p.y()/qoverp;
667  der(2,2) = - p.z()/qoverp;
668 
669  for (unsigned int i=0; i<3; i++) {
670  for (unsigned int j=0; j<3; j++) {
671  for (unsigned int k=0; k<3; k++) {
672  for (unsigned int l=0; l<3; l++) {
673  cov(i,j) += der(i,k)*cMatrix(k+2,l+2)*der(j,l);
674  }
675  }
676  }
677  }
678 
679  // debug output
680  ATH_MSG_DEBUG("BPhysAddMuonBasedInvMass::getTracksWithMuons:"
681  << "\nlocalErrCov:\n"
682  << std::setprecision(10) << cMatrix
683  << "\ncov:\n"
684  << std::setprecision(10) << cov
685  << "\np: " << std::setprecision(10) << p
686  << "\nder:\n"
687  << std::setprecision(10) << der);
688  } // if qoverp
689 
690  return cov;
691  }
692  //--------------------------------------------------------------------------
693  // Initialize PV-to-SV association type vector
694  //--------------------------------------------------------------------------
696 
697  m_pvAssocTypes.clear();
698  for (unsigned int i=0; i<xAOD::BPhysHelper::n_pv_types; ++i) {
699  if ( (m_doVertexType & (1 << i)) > 0 )
701  }
702  }
703  //--------------------------------------------------------------------------
704 }
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
xAOD::BPhysHelper::refTrkCharge
float refTrkCharge(const size_t index) const
Returns charge of the i-th track.
Definition: BPhysHelper.cxx:255
DerivationFramework::BPhysAddMuonBasedInvMass::m_minNTracksInPV
int m_minNTracksInPV
Definition: BPhysAddMuonBasedInvMass.h:284
xAOD::TrackParticle_v1::pt
virtual double pt() const override final
The transverse momentum ( ) of the particle.
Definition: TrackParticle_v1.cxx:73
make_hlt_rep.pars
pars
Definition: make_hlt_rep.py:90
Trk::py
@ py
Definition: ParamDefs.h:60
xAOD::muon
@ muon
Definition: TrackingPrimitives.h:195
xAOD::Vertex_v1::nTrackParticles
size_t nTrackParticles() const
Get the number of tracks associated with this vertex.
Definition: Vertex_v1.cxx:270
xAOD::BPhysHelper
Definition: BPhysHelper.h:71
xAOD::VertexAuxContainer_v1
Temporary container used until we have I/O for AuxStoreInternal.
Definition: VertexAuxContainer_v1.h:32
xAOD::BPhysHelper::pv_type_str
static const std::string pv_type_str[]
Definition: BPhysHelper.h:605
xAOD::BPhysHelper::nRefTrks
int nRefTrks()
Returns number of stored refitted track momenta.
Definition: BPhysHelper.cxx:115
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
Base_Fragment.mass
mass
Definition: Sherpa_i/share/common/Base_Fragment.py:59
DerivationFramework::BPhysAddMuonBasedInvMass::adjustTrackParticle
const xAOD::TrackParticle * adjustTrackParticle(const xAOD::Muon *muon, BasedInvCache &cache) const
Extract TrackParticle for Muon and adjust kinematics.
Definition: BPhysAddMuonBasedInvMass.cxx:317
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
DerivationFramework::BPhysAddMuonBasedInvMass::m_pvAssocTypes
std::vector< xAOD::BPhysHelper::pv_type > m_pvAssocTypes
Definition: BPhysAddMuonBasedInvMass.h:291
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
EventPrimitivesHelpers.h
skel.it
it
Definition: skel.GENtoEVGEN.py:396
plotBeamSpotVxVal.cov
cov
Definition: plotBeamSpotVxVal.py:201
DerivationFramework::BPhysAddMuonBasedInvMass::m_pvTypesToConsider
std::vector< int > m_pvTypesToConsider
Definition: BPhysAddMuonBasedInvMass.h:285
xAOD::TrackParticle_v1::z0
float z0() const
Returns the parameter.
ParticleTest.tp
tp
Definition: ParticleTest.py:25
xAOD::TrackParticle_v1::setDefiningParameters
void setDefiningParameters(float d0, float z0, float phi0, float theta, float qOverP)
Set the defining parameters.
Definition: TrackParticle_v1.cxx:177
Trk::z0
@ z0
Definition: ParamDefs.h:64
xAOD
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Definition: ICaloAffectedTool.h:24
UploadAMITag.l
list l
Definition: UploadAMITag.larcaf.py:158
xAOD::Vertex_v1::position
const Amg::Vector3D & position() const
Returns the 3-pos.
DerivationFramework::BPhysAddMuonBasedInvMass::findAllMuonsInDecay
MuonBag findAllMuonsInDecay(xAOD::BPhysHelper &vtx) const
Find all muons associated to secondary vertex.
Definition: BPhysAddMuonBasedInvMass.cxx:382
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
InDetAccessor::qOverP
@ qOverP
perigee
Definition: InDetAccessor.h:35
const
bool const RAWDATA *ch2 const
Definition: LArRodBlockPhysicsV0.cxx:560
Trk::pz
@ pz
global momentum (cartesian)
Definition: ParamDefs.h:61
x
#define x
DerivationFramework::BPhysAddMuonBasedInvMass::initPvAssocTypeVec
void initPvAssocTypeVec()
Initialize PV-to-SV association type vector.
DerivationFramework::MuonBag
std::vector< const xAOD::Muon * > MuonBag
Definition: BPhysAddMuonBasedInvMass.h:33
xAOD::Muon_v1
Class describing a Muon.
Definition: Muon_v1.h:38
AmgMatrix
#define AmgMatrix(rows, cols)
Definition: EventPrimitives.h:49
xAOD::TrackParticle_v1::d0
float d0() const
Returns the parameter.
DerivationFramework::BPhysAddMuonBasedInvMass
Augment secondary vertices with muon-information-based mass.
Definition: BPhysAddMuonBasedInvMass.h:106
DerivationFramework::AmgSymMatrix
AmgSymMatrix(3) BPhysAddMuonBasedInvMass
Definition: BPhysAddMuonBasedInvMass.cxx:601
BPhysAddMuonBasedInvMass.h
Augmentation with muon-information based invariant mass.
xAOD::IParticle::FourMom_t
TLorentzVector FourMom_t
Definition of the 4-momentum type.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:69
xAOD::TrackParticle
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Definition: Event/xAOD/xAODTracking/xAODTracking/TrackParticle.h:13
AthCommonDataStore< AthCommonMsg< AlgTool > >::evtStore
ServiceHandle< StoreGateSvc > & evtStore()
The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:85
DerivationFramework::BPhysAddMuonBasedInvMass::getInvariantMassWithError
std::pair< double, double > getInvariantMassWithError(TrackBag trksIn, const std::vector< double > &massHypotheses, const Amg::Vector3D &pos, BasedInvCache &) const
Calculate invariant mass and uncertainty from a set of tracks.
Definition: BPhysAddMuonBasedInvMass.cxx:519
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
xAOD::BPhysHelper::pv_type
pv_type
: Enum type of the PV
Definition: BPhysHelper.h:475
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
SG::Decorator
Helper class to provide type-safe access to aux data.
Definition: Decorator.h:59
DataModel_detail::iterator
(Non-const) Iterator class for DataVector/DataList.
Definition: DVLIterator.h:184
lumiFormat.i
int i
Definition: lumiFormat.py:85
z
#define z
beamspotman.n
n
Definition: beamspotman.py:731
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
xAOD::BPhysHelper::precedingVertex
const xAOD::Vertex * precedingVertex(const size_t index)
Returns pointer to a preceding vertex.
Definition: BPhysHelper.cxx:613
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
AmgVector
AmgVector(4) T2BSTrackFilterTool
Definition: T2BSTrackFilterTool.cxx:114
DerivationFramework::BPhysAddMuonBasedInvMass::m_doVertexType
int m_doVertexType
Definition: BPhysAddMuonBasedInvMass.h:286
chi2
double chi2(TH1 *h0, TH1 *h1)
Definition: comparitor.cxx:523
TRT::Track::d0
@ d0
Definition: InnerDetector/InDetCalibEvent/TRT_CalibData/TRT_CalibData/TrackInfo.h:62
DerivationFramework::BasedInvCache::adjTpCache
TpMap_t adjTpCache
map of adjusted track particles as cache
Definition: BPhysAddMuonBasedInvMass.cxx:33
Trk::px
@ px
Definition: ParamDefs.h:59
xAOD::BPhysHelper::PV_MIN_A0
@ PV_MIN_A0
Definition: BPhysHelper.h:475
Preparation.mode
mode
Definition: Preparation.py:94
CHECK
#define CHECK(...)
Evaluate an expression and check for errors.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:422
DerivationFramework::TrackBag
std::vector< const xAOD::TrackParticle * > TrackBag
Definition: BPhysAddMuonBasedInvMass.h:32
DerivationFramework
THE reconstruction tool.
Definition: ParticleSortingAlg.h:24
xAOD::BPhysHelper::origPv
const xAOD::Vertex * origPv(const pv_type vertexType=BPhysHelper::PV_MIN_A0)
original PV
Definition: BPhysHelper.cxx:807
TRT::Track::z0
@ z0
Definition: InnerDetector/InDetCalibEvent/TRT_CalibData/TRT_CalibData/TrackInfo.h:63
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
DerivationFramework::BPhysAddMuonBasedInvMass::m_addMinChi2ToAnyPVMode
int m_addMinChi2ToAnyPVMode
Definition: BPhysAddMuonBasedInvMass.h:282
xAOD::BPhysHelper::refTrkOrigin
const xAOD::IParticle * refTrkOrigin(const size_t index) const
: Returns the original track (charged or neutral) corresponding to the i-th refitted track
Definition: BPhysHelper.cxx:171
DerivationFramework::BPhysAddMuonBasedInvMass::m_trkMasses
std::vector< double > m_trkMasses
Definition: BPhysAddMuonBasedInvMass.h:279
xAOD::TrackParticle_v1::phi0
float phi0() const
Returns the parameter, which has range to .
Definition: TrackParticle_v1.cxx:158
Trk
Ensure that the ATLAS eigen extensions are properly loaded.
Definition: FakeTrackBuilder.h:9
xAOD::TrackParticle_v1::qOverP
float qOverP() const
Returns the parameter.
Trk::d0
@ d0
Definition: ParamDefs.h:63
xAOD::BPhysHelper::vtx
const xAOD::Vertex * vtx() const
Getter method for the cached xAOD::Vertex.
Definition: BPhysHelper.h:108
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
Amg::error
double error(const Amg::MatrixX &mat, int index)
return diagonal error of the matrix caller should ensure the matrix is symmetric and the index is in ...
Definition: EventPrimitivesHelpers.h:40
DerivationFramework::BasedInvCache::ctx
const EventContext & ctx
Definition: BPhysAddMuonBasedInvMass.cxx:34
DerivationFramework::BasedInvCache::~BasedInvCache
~BasedInvCache()
Definition: BPhysAddMuonBasedInvMass.cxx:35
SG::AuxElement::makePrivateStore
void makePrivateStore()
Create a new (empty) private store for this object.
Definition: AuxElement.cxx:192
DerivationFramework::BPhysAddMuonBasedInvMass::BPhysAddMuonBasedInvMass
BPhysAddMuonBasedInvMass(const std::string &t, const std::string &n, const IInterface *p)
Main contructor.
Definition: BPhysAddMuonBasedInvMass.cxx:44
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
DerivationFramework::BPhysAddMuonBasedInvMass::getMinChi2ToAnyPV
double getMinChi2ToAnyPV(xAOD::BPhysHelper &vtx, const xAOD::VertexContainer *pvContainer, const std::vector< int > &pvtypes, const int minNTracksInPV, const int mode, const xAOD::BPhysHelper::pv_type &pvAssocType, BasedInvCache &cache) const
Determine minimum log chi2 of signal muon tracks w.r.t.
Definition: BPhysAddMuonBasedInvMass.cxx:404
DerivationFramework::BPhysAddMuonBasedInvMass::addBranches
virtual StatusCode addBranches() const
Main method called for each event.
Definition: BPhysAddMuonBasedInvMass.cxx:123
DerivationFramework::BPhysAddMuonBasedInvMass::m_pvContainerName
std::string m_pvContainerName
Definition: BPhysAddMuonBasedInvMass.h:283
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
MuonContainer.h
BPhysHelper.h
: B-physics xAOD helpers.
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
DerivationFramework::BPhysAddMuonBasedInvMass::m_adjustToMuonKinematics
bool m_adjustToMuonKinematics
Definition: BPhysAddMuonBasedInvMass.h:281
DerivationFramework::BPhysAddMuonBasedInvMass::getTrackPVChi2
double getTrackPVChi2(const xAOD::TrackParticle &track, const Amg::Vector3D &pos, BasedInvCache &cache) const
Calculate log chi2 value of a track w.r.t.
Definition: BPhysAddMuonBasedInvMass.cxx:483
DerivationFramework::BasedInvCache
Definition: BPhysAddMuonBasedInvMass.cxx:27
VertexContainer.h
y
#define y
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
DerivationFramework::BPhysAddMuonBasedInvMass::getIdTracksForMuons
TrackBag getIdTracksForMuons(MuonBag &muons) const
Obtain a set of ID tracks for a set of muons.
Definition: BPhysAddMuonBasedInvMass.cxx:239
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
DerivationFramework::BPhysAddMuonBasedInvMass::getTracksWithMuons
std::pair< TrackBag, int > getTracksWithMuons(xAOD::BPhysHelper &vtx, BasedInvCache &) const
Obtain a set of tracks with muon track information if available.
Definition: BPhysAddMuonBasedInvMass.cxx:264
xAOD::BPhysHelper::nPrecedingVertices
int nPrecedingVertices()
: Links to preceding vertices
Definition: BPhysHelper.cxx:601
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:567
xAOD::BPhysHelper::pv
const xAOD::Vertex * pv(const pv_type vertexType=BPhysHelper::PV_MIN_A0)
Get the refitted collision vertex of type pv_type.
Definition: BPhysHelper.cxx:796
DerivationFramework::BPhysAddMuonBasedInvMass::m_vertexContainerName
std::string m_vertexContainerName
Definition: BPhysAddMuonBasedInvMass.h:278
IParticleHelpers.h
xAOD::BPhysHelper::n_pv_types
static const unsigned int n_pv_types
Definition: BPhysHelper.h:613
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
DerivationFramework::BasedInvCache::TpMap_t
std::map< const xAOD::TrackParticle *, const xAOD::TrackParticle * > TpMap_t
map original -> adjusted track particles
Definition: BPhysAddMuonBasedInvMass.cxx:31
xAOD::BPhysHelper::muons
const std::vector< const xAOD::Muon * > & muons()
Returns linked muons.
Definition: BPhysHelper.cxx:468
DerivationFramework::BasedInvCache::BasedInvCache
BasedInvCache(const EventContext &c=Gaudi::Hive::currentContext())
Definition: BPhysAddMuonBasedInvMass.cxx:28
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
DerivationFramework::BPhysAddMuonBasedInvMass::m_trackToVertexTool
ToolHandle< Reco::ITrackToVertex > m_trackToVertexTool
Definition: BPhysAddMuonBasedInvMass.h:280
AthAlgTool
Definition: AthAlgTool.h:26
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
DerivationFramework::BPhysAddMuonBasedInvMass::finalize
virtual StatusCode finalize()
Finalize augmentation tool.
Definition: BPhysAddMuonBasedInvMass.cxx:115
xAOD::TrackParticle_v1::theta
float theta() const
Returns the parameter, which has range 0 to .
python.compressB64.c
def c
Definition: compressB64.py:93
DerivationFramework::BPhysAddMuonBasedInvMass::getMuCalcMass
std::pair< double, double > getMuCalcMass(xAOD::BPhysHelper &vtx, const std::vector< double > &trkMasses, int nMuRequested, BasedInvCache &cache) const
Definition: BPhysAddMuonBasedInvMass.cxx:208
TrackParticleContainer.h
DerivationFramework::BPhysAddMuonBasedInvMass::initialize
virtual StatusCode initialize()
Initialize augmentation tool.
Definition: BPhysAddMuonBasedInvMass.cxx:74
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
VertexAuxContainer.h
fitman.k
k
Definition: fitman.py:528
DerivationFramework::BPhysAddMuonBasedInvMass::m_branchPrefix
std::string m_branchPrefix
Definition: BPhysAddMuonBasedInvMass.h:277