CMS 3D CMS Logo

SimTrackManager.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Application
4 // Class : SimTrackManager
5 //
6 // Implementation:
7 // <Notes on implementation>
8 //
9 // Original Author:
10 // Created: Fri Nov 25 17:44:19 EST 2005
11 //
12 
13 // system include files
14 #include <iostream>
15 
16 // user include files
22 
25 
26 #include "G4VProcess.hh"
27 #include "G4Track.hh"
28 #include "G4ThreeVector.hh"
29 #include "G4SystemOfUnits.hh"
30 
31 //#define DebugLog
32 namespace {
33  const double invcm = 1.0 / CLHEP::cm;
34  const double r_limit2 = 1.e-6; // 10 micron in CMS units
35 } // namespace
36 
38  idsave.reserve(1000);
39  ancestorList.reserve(1000);
40  m_trackContainer.reserve(1000);
41  m_endPoints.reserve(1000);
42 }
43 
45 
47  deleteTracks();
49  idsave.clear();
50  ancestorList.clear();
51  lastTrack = 0;
52  lastHist = 0;
53 }
54 
56  if (!m_trackContainer.empty()) {
57  for (auto const& ptr : m_trackContainer) {
58  delete ptr;
59  }
60  m_trackContainer.clear();
61  m_endPoints.clear();
62  }
63 }
64 
66  m_vertexMap.clear();
68  m_nVertices = 0;
69 }
70 
71 void SimTrackManager::addTrack(TrackWithHistory* iTrack, const G4Track* track, bool inHistory, bool withAncestor) {
72  std::pair<int, int> thePair(iTrack->trackID(), iTrack->parentID());
73  idsave.push_back(thePair);
74  if (inHistory) {
75  m_trackContainer.push_back(iTrack);
76  const auto& v = track->GetStep()->GetPostStepPoint()->GetPosition();
77  std::pair<int, math::XYZVectorD> p(iTrack->trackID(),
78  math::XYZVectorD(v.x() * invcm, v.y() * invcm, v.z() * invcm));
79  m_endPoints.push_back(p);
80  }
81  if (withAncestor) {
82  std::pair<int, int> thisPair(iTrack->trackID(), 0);
83  ancestorList.push_back(thisPair);
84  }
85 }
86 
89  TrackWithHistory* trkH = trkWHist;
90  if (trkH == nullptr) {
91  edm::LogError("SimTrackManager") << " SimTrackManager::saveTrackAndItsBranch got 0 pointer ";
92  throw cms::Exception("SimTrackManager::saveTrackAndItsBranch") << " cannot handle hits for tracking";
93  }
94  trkH->setToBeSaved();
95  int parent = trkH->parentID();
96 
97  auto tk_itr =
99 
100  if (tk_itr != m_trackContainer.end() && (*tk_itr)->trackID() == parent) {
101  saveTrackAndItsBranch(*tk_itr);
102  }
103 }
104 
107 
108  // fill the map with the final mother-daughter relationship
109  idsave.swap(ancestorList);
110  std::stable_sort(idsave.begin(), idsave.end());
111 
112  std::vector<std::pair<int, int> >().swap(ancestorList);
113 
114  // to get a backward compatible order
115  std::stable_sort(m_trackContainer.begin(), m_trackContainer.end(), trkIDLess());
116 
117  // to reset the GenParticle ID of a SimTrack to its pre-LHCTransport value
118  resetGenID();
119 
121 }
122 
124  // loop over the (now ordered) vector and really save the tracks
125 #ifdef DebugLog
126  edm::LogVerbatim("SimTrackManager") << "reallyStoreTracks() NtracksWithHistory= " << m_trackContainer->size();
127 #endif
128 
129  int nn = m_endPoints.size();
130  for (auto& trkH : m_trackContainer) {
131  // at this stage there is one vertex per track,
132  // so the vertex id of track N is also N
133  int iParentID = trkH->parentID();
134  int ig = trkH->genParticleID();
135  int ivertex = getOrCreateVertex(trkH, iParentID);
136 
137  auto ptr = trkH;
138  if (0 < iParentID) {
139  for (auto& trk : m_trackContainer) {
140  if (trk->trackID() == iParentID) {
141  ptr = trk;
142  break;
143  }
144  }
145  }
146  // Track at surface is the track at intersection point between tracker and calo
147  // envelops if exist. If not exist the momentum is zero, position is the end of
148  // the track
149  const math::XYZVectorD& pm = ptr->momentum();
150  math::XYZVectorD spos(0., 0., 0.);
151  math::XYZTLorentzVectorD smom(0., 0., 0., 0.);
152  int id = trkH->trackID();
153  if (trkH->crossedBoundary()) {
154  spos = trkH->getPositionAtBoundary();
155  smom = trkH->getMomentumAtBoundary();
156  } else {
157  for (int i = 0; i < nn; ++i) {
158  if (id == m_endPoints[i].first) {
159  spos = m_endPoints[i].second;
160  break;
161  }
162  }
163  }
164 
165  TmpSimTrack* g4simtrack =
166  new TmpSimTrack(id, trkH->particleID(), trkH->momentum(), trkH->totalEnergy(), ivertex, ig, pm, spos, smom);
167  g4simtrack->copyCrossedBoundaryVars(trkH);
168  m_simEvent->add(g4simtrack);
169  }
170 }
171 
173  int parent = -1;
174  for (auto const& trk : m_trackContainer) {
175  int id = trk->trackID();
176  if (id == iParentID) {
177  parent = id;
178  break;
179  }
180  }
181 
182  VertexMap::const_iterator iterator = m_vertexMap.find(parent);
183  if (iterator != m_vertexMap.end()) {
184  // loop over saved vertices
185  for (auto const& xx : m_vertexMap[parent]) {
186  if ((trkH->vertexPosition() - xx.second).Mag2() < r_limit2) {
187  return xx.first;
188  }
189  }
190  }
191 
192  m_simEvent->add(new TmpSimVertex(trkH->vertexPosition(), trkH->time(), parent, trkH->processType()));
194  ++m_nVertices;
195  return (m_nVertices - 1);
196 }
197 
198 int SimTrackManager::idSavedTrack(int id) const {
199  int idMother = id;
200  if (id > 0) {
201  unsigned int n = idsave.size();
202  if (0 < n) {
203  int jmax = n - 1;
204  int j, id1;
205 
206  // first loop forward
207  bool notFound = true;
208  for (j = 0; j <= jmax; ++j) {
209  if ((idsave[j]).first == idMother) {
210  id1 = (idsave[j]).second;
211  if (0 == id1 || id1 == idMother) {
212  return id1;
213  }
214  jmax = j - 1;
215  idMother = id1;
216  notFound = false;
217  break;
218  }
219  }
220  if (notFound) {
221  return 0;
222  }
223 
224  // recursive loop
225  do {
226  notFound = true;
227  // search ID scan backward
228  for (j = jmax; j >= 0; --j) {
229  if ((idsave[j]).first == idMother) {
230  id1 = (idsave[j]).second;
231  if (0 == id1 || id1 == idMother) {
232  return id1;
233  }
234  jmax = j - 1;
235  idMother = id1;
236  notFound = false;
237  break;
238  }
239  }
240  if (notFound) {
241  // ID not in the list of saved track - look into ancestors
242  jmax = ancestorList.size() - 1;
243  for (j = jmax; j >= 0; --j) {
244  if ((ancestorList[j]).first == idMother) {
245  idMother = (ancestorList[j]).second;
246  return idMother;
247  }
248  }
249  return 0;
250  }
251  } while (!notFound);
252  }
253  }
254  return idMother;
255 }
256 
258  if (!ancestorList.empty() && lastHist > ancestorList.size()) {
259  lastHist = ancestorList.size();
260  edm::LogError("SimTrackManager") << " SimTrackManager::fillMotherList track index corrupted";
261  }
262 #ifdef DebugLog
263  edm::LogVerbatim("SimTrackManager") << "### SimTrackManager::fillMotherList: " << idsave.size()
264  << " saved; ancestor: " << lastHist << " " << ancestorList.size();
265  for (unsigned int i = 0; i < idsave.size(); ++i) {
266  edm::LogVerbatim("SimTrackManager") << " ISV: Track ID = " << (idsave[i]).first
267  << " Mother ID = " << (idsave[i]).second;
268  }
269 #endif
270  for (unsigned int n = lastHist; n < ancestorList.size(); ++n) {
271  int theMotherId = idSavedTrack((ancestorList[n]).first);
272  ancestorList[n].second = theMotherId;
273 #ifdef DebugLog
274  LogDebug("SimTrackManager") << "Track ID = " << (ancestorList[n]).first
275  << " Mother ID = " << (ancestorList[n]).second;
276 #endif
277  }
278 
279  lastHist = ancestorList.size();
280  idsave.clear();
281 }
282 
284  if (m_trackContainer.empty() && idsave.empty()) {
285  return;
286  }
287 
288 #ifdef DebugLog
289  LogDebug("SimTrackManager") << "SimTrackManager::cleanTracksWithHistory has " << idsave.size()
290  << " mother-daughter relationships stored with lastTrack = " << lastTrack;
291 #endif
292 
293  if (lastTrack > 0 && lastTrack >= m_trackContainer.size()) {
294  lastTrack = 0;
295  edm::LogError("SimTrackManager") << " SimTrackManager::cleanTracksWithHistory track index corrupted";
296  }
297 
298  std::stable_sort(m_trackContainer.begin() + lastTrack, m_trackContainer.end(), trkIDLess());
299  std::stable_sort(idsave.begin(), idsave.end());
300 
301 #ifdef DebugLog
302  LogDebug("SimTrackManager") << " SimTrackManager::cleanTracksWithHistory knows " << m_trksForThisEvent->size()
303  << " tracks with history before branching";
304  for (unsigned int it = 0; it < m_trackContainer.size(); it++) {
305  LogDebug("SimTrackManager") << " 1 - Track in position " << it << " G4 track number "
306  << m_trackContainer[it]->trackID() << " mother " << m_trackContainer[it]->parentID()
307  << " status " << m_trackContainer[it]->saved();
308  }
309 #endif
310 
311  for (auto const& t : m_trackContainer) {
312  if (t->saved()) {
314  }
315  }
316  unsigned int num = lastTrack;
317  for (unsigned int it = lastTrack; it < m_trackContainer.size(); ++it) {
318  auto t = m_trackContainer[it];
319  int g4ID = m_trackContainer[it]->trackID();
320  if (t->saved()) {
321  if (it > num) {
323  }
324  ++num;
325  for (auto& xx : idsave) {
326  if (xx.first == g4ID) {
327  xx.second = g4ID;
328  break;
329  }
330  }
331  } else {
332  delete t;
333  }
334  }
335 
336  m_trackContainer.resize(num);
337 
338 #ifdef DebugLog
339  LogDebug("SimTrackManager") << " AFTER CLEANING, I GET " << m_trackContainer.size()
340  << " tracks to be saved persistently";
341  for (unsigned int it = 0; it < m_trackContainer.size(); ++it) {
342  LogDebug("SimTrackManager") << " Track in position " << it << " G4 track number " << m_trackContainer[it]->trackID()
343  << " mother " << m_trackContainer[it]->parentID() << " Status "
344  << m_trackContainer[it]->saved() << " id " << m_trackContainer[it]->particleID()
345  << " E(MeV)= " << m_trackContainer[it]->totalEnergy();
346  }
347 #endif
348 
349  fillMotherList();
350  lastTrack = m_trackContainer.size();
351 }
352 
354  if (theLHCTlink == nullptr)
355  return;
356 
357  for (auto const& trkH : m_trackContainer) {
358  int genParticleID = trkH->genParticleID();
359  if (genParticleID == -1) {
360  continue;
361  } else {
362  for (auto const& xx : *theLHCTlink) {
363  if (xx.afterHector() == genParticleID) {
364  trkH->setGenParticleID(xx.beforeHector());
365  continue;
366  }
367  }
368  }
369  }
370 
371  theLHCTlink = nullptr;
372 }
373 
374 void SimTrackManager::ReportException(unsigned int id) const {
375  throw cms::Exception("Unknown", "SimTrackManager::getTrackByID")
376  << "Fail to get track " << id << " from SimTrackManager, container size= " << m_trackContainer.size();
377 }
Log< level::Info, true > LogVerbatim
std::vector< TrackWithHistory * > m_trackContainer
VertexMap m_vertexMap
SimTrackManager(TmpSimEvent *)
int parentID() const
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< double > > XYZTLorentzVectorD
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:14
std::pair< int, math::XYZVectorD > VertexPosition
const math::XYZVectorD & vertexPosition() const
void copyCrossedBoundaryVars(const TrackWithHistory *track)
Definition: TmpSimTrack.h:53
double time() const
Log< level::Error, false > LogError
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:117
unsigned int lastHist
TmpSimEvent * m_simEvent
U second(std::pair< T, U > const &p)
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double > > XYZVectorD
spatial vector with cartesian internal representation
Definition: Vector3D.h:8
void add(TmpSimTrack *t)
Definition: TmpSimEvent.h:33
void cleanTracksWithHistory()
void addTrack(TrackWithHistory *iTrack, const G4Track *track, bool inHistory, bool withAncestor)
std::vector< std::pair< int, int > > idsave
void saveTrackAndItsBranch(TrackWithHistory *)
this saves a track and all its parents looping over the non ordered vector
unsigned int lastTrack
static const GlobalPoint notFound(0, 0, 0)
int processType() const
int trackID() const
const edm::LHCTransportLinkContainer * theLHCTlink
int idSavedTrack(int) const
int getOrCreateVertex(TrackWithHistory *, int)
std::vector< std::pair< int, int > > ancestorList
void ReportException(unsigned int id) const
#define LogDebug(id)
std::vector< std::pair< int, math::XYZVectorD > > m_endPoints