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