ATLAS Offline Software
JetFitterMultiStageFit.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3  */
4 
6 
12 
13 
14 using namespace InDet;
15 
16 /*
17  * For the Hackathon, an example of a new algorithm tool
18  */
19 
20 
21 JetFitterMultiStageFit::JetFitterMultiStageFit(const std::string &t, const std::string &n, const IInterface *p)
22  : AthAlgTool(t, n, p)
23 {
24  // constructor, declare all necessary things
25  declareInterface< JetFitterMultiStageFit >(this);
26 }
27 
28 
30 
32 
33  ATH_CHECK( m_helper.retrieve() );
34  ATH_CHECK( m_initializationHelper.retrieve() );
35  ATH_CHECK( m_routines.retrieve() );
36  ATH_CHECK( m_jetFitterUtils.retrieve() );
37 
38  return StatusCode::SUCCESS;
39 }
40 
41 
43  const TLorentzVector & jetMomentum,
44  const std::vector<const Trk::ITrackLink*> & firstInputTracks,
45  const std::vector<const Trk::ITrackLink*> & secondInputTracks,
46  const Amg::Vector3D & vtxSeedDirection) const {
47 
48  Amg::Vector3D myDirection(jetMomentum.X(),jetMomentum.Y(),jetMomentum.Z());
49 
50  std::vector<std::vector<const Trk::ITrackLink*> > bunchesOfTracks; // vector of vector of tracks
51 
52  std::vector<const Trk::ITrackLink*> tracksToAdd;
53 
54  std::vector<const Trk::ITrackLink*>::const_iterator tracks2Begin=firstInputTracks.begin();
55  std::vector<const Trk::ITrackLink*>::const_iterator tracks2End=firstInputTracks.end();
56  for (std::vector<const Trk::ITrackLink*>::const_iterator tracks2Iter=tracks2Begin;
57  tracks2Iter!=tracks2End;++tracks2Iter) {
58  tracksToAdd.push_back(*tracks2Iter);
59  }
60 
61  bunchesOfTracks.push_back(tracksToAdd);
62  tracksToAdd.clear();
63 
64  std::vector<const Trk::ITrackLink*>::const_iterator tracks3Begin=secondInputTracks.begin();
65  std::vector<const Trk::ITrackLink*>::const_iterator tracks3End=secondInputTracks.end();
66  for (std::vector<const Trk::ITrackLink*>::const_iterator tracks3Iter=tracks3Begin;
67  tracks3Iter!=tracks3End;++tracks3Iter) {
68  tracksToAdd.push_back(*tracks3Iter);
69  }
70 
71  if (!tracksToAdd.empty())
72  {
73  bunchesOfTracks.push_back(tracksToAdd);
74  }
75  tracksToAdd.clear();
76 
77  //now it just uses these bunches...
78  //now I have just to make sure that no clustering is done at first iteration
79  //while it needs to be done at second iteration (there will be only two iterations)
80 
81 
82  std::vector<std::vector<const Trk::ITrackLink*> >::const_iterator BunchesBegin=bunchesOfTracks.begin();
83  std::vector<std::vector<const Trk::ITrackLink*> >::const_iterator BunchesEnd=bunchesOfTracks.end();
84 
85  std::vector<const Trk::ITrackLink*>::const_iterator tracksToAddBegin;
86  std::vector<const Trk::ITrackLink*>::const_iterator tracksToAddEnd;
87  std::vector<const Trk::ITrackLink*>::const_iterator tracksToAddIter;
88 
89 
90  Trk::VxJetCandidate* myJetCandidate=nullptr;
91 
92  for (std::vector<std::vector<const Trk::ITrackLink*> >::const_iterator BunchesIter=BunchesBegin;
93  BunchesIter!=BunchesEnd;++BunchesIter) {
94 
95  if (BunchesIter == BunchesBegin) { // this simply means we are only using tracksToUseInFirstFit
96  ATH_MSG_VERBOSE(" initial fit with " << (*BunchesIter).size() << " tracks ");
97  myJetCandidate = m_initializationHelper->initializeJetCandidate(*BunchesIter, &primaryVertex, &myDirection,
98  &vtxSeedDirection);
99  m_routines->initializeToMinDistancesToJetAxis(myJetCandidate);
100  if (!(*BunchesIter).empty()) {
101  doTheFit(myJetCandidate, true);
102  // Im confused, didnt the comment above say no clustering done in first iteration?
103  // yet performClustering = true in the call above??
104  }
105  }
106 
107  // second stage using all tracks, why is it done this way with an if-else in a for loop...
108  else {
109  ATH_MSG_VERBOSE(" other fit with " << (*BunchesIter).size() << " tracks ");
110  std::vector<Trk::VxVertexOnJetAxis*> setOfVertices=myJetCandidate->getVerticesOnJetAxis();
111  std::vector<Trk::VxTrackAtVertex*>* setOfTracks=myJetCandidate->vxTrackAtVertex();
112  tracksToAddBegin=(*BunchesIter).begin();
113  tracksToAddEnd=(*BunchesIter).end();
114 
115  for (tracksToAddIter=tracksToAddBegin;tracksToAddIter!=tracksToAddEnd;++tracksToAddIter) {
116  std::vector<Trk::VxTrackAtVertex*> temp_vector_tracksAtVertex;
117  Trk::VxTrackAtVertex* newVxTrack=new Trk::VxTrackAtVertex((*tracksToAddIter)->clone());
118  temp_vector_tracksAtVertex.push_back(newVxTrack);
119  setOfTracks->push_back(newVxTrack);
120  //add the new tracks to the candidate's track collection
121  setOfVertices.push_back(new Trk::VxVertexOnJetAxis(temp_vector_tracksAtVertex));
122  //add new vertex with all the *BunchesIter tracks attached to it
123  }
124 
125  ATH_MSG_VERBOSE(" new overall number of tracks (vertices?) to fit : " << setOfVertices.size());
126  myJetCandidate->setVerticesOnJetAxis(setOfVertices);
127  m_initializationHelper->updateTrackNumbering(myJetCandidate);
128  //question: should this be done???
129  m_routines->initializeToMinDistancesToJetAxis(myJetCandidate);
130  // we re-initialize, is this wise? We've merged vertices in the previous iteration...
131  doTheFit(myJetCandidate);
132  }
133  }
134 
135 
136 
137  ATH_MSG_DEBUG(" returning jet candidate");
138  return myJetCandidate;
139 }
140 
141 
143  bool performClustering) const {
144 
145  int numClusteringLoops=0;
146  bool noMoreVerticesToCluster(false);
147 
148  do {//regards clustering
149 
150  int numLoops = 0;
151  bool noMoreTracksToDelete(false);
152  do {//regards eliminating incompatible tracks...
153 
154  m_routines->performTheFit(myJetCandidate, 15, false, 30, 0.001);
155 
156  const std::vector<Trk::VxVertexOnJetAxis *> &vertices = myJetCandidate->getVerticesOnJetAxis();
157 
158  std::vector<Trk::VxVertexOnJetAxis *>::const_iterator verticesBegin = vertices.begin();
159  std::vector<Trk::VxVertexOnJetAxis *>::const_iterator verticesEnd = vertices.end();
160 
161 
162  //delete incompatible tracks...
163  float max_prob(1.);
164  Trk::VxVertexOnJetAxis *worseVertex(nullptr);
165  for (std::vector<Trk::VxVertexOnJetAxis *>::const_iterator verticesIter = verticesBegin;
166  verticesIter != verticesEnd; ++verticesIter) {
167  if (*verticesIter == nullptr) {
168  ATH_MSG_WARNING("One vertex is empy. Problem when trying to delete incompatible vertices. No further vertices deleted.");
169  } else {
170  const Trk::FitQuality &fitQuality = (*verticesIter)->fitQuality();
171  if (TMath::Prob(fitQuality.chiSquared(), (int) std::floor(fitQuality.numberDoF() + 0.5)) <
172  max_prob) {
173  max_prob = TMath::Prob(fitQuality.chiSquared(), (int) std::floor(fitQuality.numberDoF() + 0.5));
174  worseVertex = *verticesIter;
175  }
176  }
177  }
178  if (max_prob < m_vertexProbCut) {
179  ATH_MSG_DEBUG("Deleted vertex " << worseVertex->getNumVertex() << " with probability " << max_prob);
180  // std::cout << "Deleted vertex " << worseVertex->getNumVertex() << " with probability " << max_prob << std::endl;
181  if (worseVertex == myJetCandidate->getPrimaryVertex()) {
182  ATH_MSG_VERBOSE(" It's the primary");
183  }
184 
185  m_routines->deleteVertexFromJetCandidate(worseVertex, myJetCandidate);
186 
187  }
188  else {
189  noMoreTracksToDelete = true;
190  ATH_MSG_VERBOSE("No tracks to delete: maximum probability is " << max_prob);
191  }
192 
193  numLoops += 1;
194  } while (numLoops < m_maxNumDeleteIterations && !(noMoreTracksToDelete));
195 
196  if (!performClustering) break;
197 
198  // m_useFastClustering is false, so possibly can be removed ??
199  if (!m_useFastClustering && (int)myJetCandidate->getVerticesOnJetAxis().size()<m_maxTracksForDetailedClustering) {
200  m_routines->fillTableWithFullProbOfMerging(myJetCandidate,8,false,10,0.01);
201  }
202 
203  else {
204  m_routines->fillTableWithFastProbOfMerging(myJetCandidate);
205  }
206  const Trk::VxClusteringTable* clusteringTablePtr(myJetCandidate->getClusteringTable());
207 
208 
209  if (clusteringTablePtr==nullptr) {
210  ATH_MSG_WARNING(" No Clustering Table while it should have been calculated... no more clustering performed during vertexing ");
211  noMoreVerticesToCluster=true;
212  }
213  // why else here? why not just continue in if above?
214  else {
215  ATH_MSG_VERBOSE(" clustering table is " << *clusteringTablePtr); //suppress this?
216 
217  //now iterate over the full map and decide wether you want to do the clustering OR not...
218  float probVertex(0.);
219 
220  // probVertex is passed by reference, below function modifies it...
221  Trk::PairOfVxVertexOnJetAxis pairOfVxVertexOnJetAxis=clusteringTablePtr->getMostCompatibleVertices(probVertex);
222  //a PairOfVxVertexOnJetAxis is a std::pair<VxVertexOnJetAxis*,VxVertexOnJetAxis*>
223 
224  float probVertexExcludingPrimary(0.);
225  Trk::PairOfVxVertexOnJetAxis pairOfVxVertexOnJetAxisExcludingPrimary=clusteringTablePtr->getMostCompatibleVerticesExcludingPrimary(probVertexExcludingPrimary);
226 
227  // essentially below ask if the two vals are the same, to a tolerance of 1e-6 ...
228  bool firstProbIsWithPrimary= ( fabs(probVertex-probVertexExcludingPrimary)>1e-6 );
229  // is there a better way of establishing this?
230 
231  // merging vertex with primary (if cond satisfied
232  if (probVertex>0.&&probVertex>m_vertexClusteringProbabilityCut&&firstProbIsWithPrimary) {
233  ATH_MSG_VERBOSE(" merging vtx number " << (*pairOfVxVertexOnJetAxis.first).getNumVertex() <<
234  " and " << (*pairOfVxVertexOnJetAxis.second).getNumVertex() << " (should be PV)."); // what do these numVertex mean? e.g. -10, 0, 1, ...?
235 
236  m_helper->mergeVerticesInJetCandidate(*pairOfVxVertexOnJetAxis.first,
237  *pairOfVxVertexOnJetAxis.second,
238  *myJetCandidate);
239 
240  //now you need to update the numbering scheme
241  m_initializationHelper->updateTrackNumbering(myJetCandidate);//maybe this should be moved to a lower level...
242  continue;
243  }
244 
245  // determine whether to merge vertices that are compatible, where neither are the primary
246  if (probVertexExcludingPrimary>0.) {
247 
248  //GP suggested by Marco Battaglia, use vertex mass in order to decide wether to split or not, so derive vertex masses first
249  const Trk::VxVertexOnJetAxis *firstVertex = pairOfVxVertexOnJetAxisExcludingPrimary.first;
250  const Trk::VxVertexOnJetAxis *secondVertex = pairOfVxVertexOnJetAxisExcludingPrimary.second;
251 
252  CLHEP::HepLorentzVector massVector1 = m_jetFitterUtils->fourMomentumAtVertex(*firstVertex);//MeV
253  CLHEP::HepLorentzVector massVector2 = m_jetFitterUtils->fourMomentumAtVertex(*secondVertex);//MeV
254 
255  CLHEP::HepLorentzVector sumMassVector = massVector1 + massVector2;
256 
257  double massTwoVertex = sumMassVector.mag();//MeV
258 
259  bool doMerge(false);
260 
261  int bin = getIndexByMass(massTwoVertex);
262  double vertexClusteringProbabilityCutWithMass =
264 
265  ATH_MSG_DEBUG("m="<<massTwoVertex<<" prob="<<vertexClusteringProbabilityCutWithMass);
266 
267  if (probVertexExcludingPrimary > vertexClusteringProbabilityCutWithMass) {
268  doMerge = true; // why not just have doMerge = probVertexExcludingPrimary > vertexClusteringProbabilityCutWithMass ?
269  }
270 
271  if (doMerge)
272  {
273 
274  ATH_MSG_VERBOSE(" merging vtx number " << (*pairOfVxVertexOnJetAxis.first).getNumVertex() <<
275  " and " << (*pairOfVxVertexOnJetAxis.second).getNumVertex() << " mass merged vertex: " << massTwoVertex);
276 
277  m_helper->mergeVerticesInJetCandidate(*pairOfVxVertexOnJetAxisExcludingPrimary.first,
278  *pairOfVxVertexOnJetAxisExcludingPrimary.second,
279  *myJetCandidate);
280 
281  m_initializationHelper->updateTrackNumbering(myJetCandidate);//maybe this should be moved to a lower level...
282  continue;//go to next cycle, after a succesful merging
283  }
284  }
285 
286  noMoreVerticesToCluster=true;
287 
288  }
289 
290  numClusteringLoops+=1; // when will this ever be greater than 1?
291  // noMoreVerticesToCluster has been set to true by the time this line is reached
292  // so numClusteringLoops will equal 1 and thats the end of the while loop (see below)...
293 
294  } while (numClusteringLoops<m_maxClusteringIterations&&!(noMoreVerticesToCluster));
295 
296 
297 
298 }
299 
300 
301 
303  // Set mass to min/max value in case of under/overflow
304  double m = std::clamp(mass, m_massBins.front(), m_massBins.back());
305  const auto pVal = std::lower_bound(m_massBins.begin(), m_massBins.end(), m);
306  const int bin = std::distance(m_massBins.begin(), pVal);
307  ATH_MSG_DEBUG("Checking (m/bin) = (" << m << "," << bin << ")");
308  return bin;
309 }
InDet::JetFitterMultiStageFit::m_massBins
const std::vector< double > m_massBins
Definition: JetFitterMultiStageFit.h:83
InDet::JetFitterMultiStageFit::m_maxTracksForDetailedClustering
Gaudi::Property< int > m_maxTracksForDetailedClustering
Definition: JetFitterMultiStageFit.h:76
Trk::VxJetCandidate::getVerticesOnJetAxis
const std::vector< VxVertexOnJetAxis * > & getVerticesOnJetAxis(void) const
Definition: VxJetCandidate.cxx:543
python.SystemOfUnits.m
int m
Definition: SystemOfUnits.py:91
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
Trk::VxTrackAtVertex
The VxTrackAtVertex is a common class for all present TrkVertexFitters The VxTrackAtVertex is designe...
Definition: VxTrackAtVertex.h:77
InDet
DUMMY Primary Vertex Finder.
Definition: VP1ErrorUtils.h:36
VxVertexOnJetAxis.h
InDet::JetFitterMultiStageFit::m_initializationHelper
ToolHandle< Trk::JetFitterInitializationHelper > m_initializationHelper
Definition: JetFitterMultiStageFit.h:64
VxJetCandidate.h
bin
Definition: BinsDiffFromStripMedian.h:43
Trk::VxVertexOnJetAxis
VxVertexOnJetAxis inherits from Vertex.
Definition: VxVertexOnJetAxis.h:79
InDet::JetFitterMultiStageFit::getIndexByMass
int getIndexByMass(const double mass) const
Definition: JetFitterMultiStageFit.cxx:302
Trk::PairOfVxVertexOnJetAxis
Definition: PairOfVxVertexOnJetAxis.h:53
InDet::JetFitterMultiStageFit::m_vertexClusteringProbabilityCut
Gaudi::Property< double > m_vertexClusteringProbabilityCut
Definition: JetFitterMultiStageFit.h:78
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
InDet::JetFitterMultiStageFit::m_maxClusteringIterations
Gaudi::Property< int > m_maxClusteringIterations
Definition: JetFitterMultiStageFit.h:71
dqt_zlumi_pandas.mass
mass
Definition: dqt_zlumi_pandas.py:170
Trk::RecVertex
Trk::RecVertex inherits from Trk::Vertex.
Definition: RecVertex.h:44
InDet::JetFitterMultiStageFit::JetFitterMultiStageFit
JetFitterMultiStageFit(const std::string &t, const std::string &n, const IInterface *p)
Definition: JetFitterMultiStageFit.cxx:21
VxClusteringTable.h
InDet::JetFitterMultiStageFit::doTwoStageFit
Trk::VxJetCandidate * doTwoStageFit(const Trk::RecVertex &primaryVertex, const TLorentzVector &jetMomentum, const std::vector< const Trk::ITrackLink * > &firstInputTracks, const std::vector< const Trk::ITrackLink * > &secondInputTracks, const Amg::Vector3D &vtxSeedDirection) const
Definition: JetFitterMultiStageFit.cxx:42
Trk::VxJetCandidate::getPrimaryVertex
const VxVertexOnJetAxis * getPrimaryVertex(void) const
Definition: VxJetCandidate.cxx:551
PairOfVxVertexOnJetAxis.h
Trk::VxCandidate::vxTrackAtVertex
std::vector< Trk::VxTrackAtVertex * > * vxTrackAtVertex(void)
Unconst pointer to the vector of tracks Required by some of the vertex fitters.
Definition: VxCandidate.h:144
beamspotman.n
n
Definition: beamspotman.py:731
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
InDet::JetFitterMultiStageFit::m_helper
ToolHandle< Trk::JetFitterHelper > m_helper
Definition: JetFitterMultiStageFit.h:65
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
JetFitterMultiStageFit.h
Trk::VxClusteringTable
Definition: VxClusteringTable.h:71
VxTrackAtVertex.h
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Trk::VxVertexOnJetAxis::getNumVertex
int getNumVertex(void) const
Get Method for NumVertex.
Definition: VxVertexOnJetAxis.cxx:98
InDet::JetFitterMultiStageFit::m_vertexClusteringProbabilityCutWithMasses
DoubleArrayProperty m_vertexClusteringProbabilityCutWithMasses
Definition: JetFitterMultiStageFit.h:81
Trk::FitQuality
Class to represent and store fit qualities from track reconstruction in terms of and number of degre...
Definition: FitQuality.h:97
Trk::FitQualityOnSurface::numberDoF
int numberDoF() const
returns the number of degrees of freedom of the overall track or vertex fit as integer
Definition: FitQuality.h:60
InDet::JetFitterMultiStageFit::m_useFastClustering
Gaudi::Property< bool > m_useFastClustering
Definition: JetFitterMultiStageFit.h:73
plotBeamSpotVxVal.bin
int bin
Definition: plotBeamSpotVxVal.py:83
Trk::VxJetCandidate
Definition: VxJetCandidate.h:72
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Trk::GsfMeasurementUpdator::fitQuality
FitQualityOnSurface fitQuality(const MultiComponentState &, const MeasurementBase &)
Method for determining the chi2 of the multi-component state and the number of degrees of freedom.
Definition: GsfMeasurementUpdator.cxx:845
InDet::JetFitterMultiStageFit::m_vertexProbCut
Gaudi::Property< double > m_vertexProbCut
Definition: JetFitterMultiStageFit.h:70
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
Trk::VxJetCandidate::getClusteringTable
Trk::VxClusteringTable *& getClusteringTable(void)
Definition: VxJetCandidate.cxx:569
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
InDet::JetFitterMultiStageFit::m_routines
ToolHandle< Trk::JetFitterRoutines > m_routines
Definition: JetFitterMultiStageFit.h:66
InDet::JetFitterMultiStageFit::m_jetFitterUtils
ToolHandle< InDet::InDetJetFitterUtils > m_jetFitterUtils
Definition: JetFitterMultiStageFit.h:67
InDet::JetFitterMultiStageFit::~JetFitterMultiStageFit
~JetFitterMultiStageFit()
InDet::JetFitterMultiStageFit::doTheFit
void doTheFit(Trk::VxJetCandidate *myJetCandidate, bool performClustering=true) const
Definition: JetFitterMultiStageFit.cxx:142
Trk::VxClusteringTable::getMostCompatibleVerticesExcludingPrimary
PairOfVxVertexOnJetAxis getMostCompatibleVerticesExcludingPrimary(float &probability) const
Get pair of vertices with highest compatibility, removing cases with primary.
Definition: VxClusteringTable.cxx:134
Trk::VxJetCandidate::setVerticesOnJetAxis
void setVerticesOnJetAxis(const std::vector< VxVertexOnJetAxis * > &)
Definition: VxJetCandidate.cxx:547
AthAlgTool
Definition: AthAlgTool.h:26
doMerge
StatusCode doMerge(const std::vector< std::string > &input, const std::string &name, fbtTestToyMC_config &config, TH1F *h_lep_pt, float &lep_pt, TH1F *h_lep_eta, float &lep_eta, TH2F *h_lep_pt_eta, float &fakes, float &poserr, float &negerr, int icase)
Definition: fbtTestToyMC.cxx:1121
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
Trk::FitQualityOnSurface::chiSquared
double chiSquared() const
returns the of the overall track fit
Definition: FitQuality.h:56
InDet::JetFitterMultiStageFit::initialize
virtual StatusCode initialize() override
Definition: JetFitterMultiStageFit.cxx:31
InDet::JetFitterMultiStageFit::m_maxNumDeleteIterations
Gaudi::Property< int > m_maxNumDeleteIterations
Definition: JetFitterMultiStageFit.h:69
Trk::VxClusteringTable::getMostCompatibleVertices
PairOfVxVertexOnJetAxis getMostCompatibleVertices(float &probability) const
Get pair of tracks with highest compatibility.
Definition: VxClusteringTable.cxx:117