File indexing completed on 2025-01-12 23:42:12
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <iostream>
0015
0016
0017 #include "SimG4Core/Notification/interface/SimTrackManager.h"
0018 #include "SimG4Core/Notification/interface/TmpSimTrack.h"
0019 #include "SimG4Core/Notification/interface/TmpSimVertex.h"
0020 #include "SimG4Core/Notification/interface/TmpSimEvent.h"
0021 #include "SimG4Core/Notification/interface/TrackInformation.h"
0022 #include "SimDataFormats/TrackingHit/interface/PSimHit.h"
0023
0024 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0025 #include "FWCore/Utilities/interface/Exception.h"
0026
0027 #include "G4VProcess.hh"
0028 #include "G4Track.hh"
0029 #include "G4ThreeVector.hh"
0030 #include <CLHEP/Units/SystemOfUnits.h>
0031
0032
0033 namespace {
0034 const double invcm = 1.0 / CLHEP::cm;
0035 const double r_limit2 = 1.e-6;
0036 }
0037
0038 SimTrackManager::SimTrackManager(TmpSimEvent* ptr, int) : m_simEvent(ptr) {
0039 idsave.reserve(1000);
0040 ancestorList.reserve(1000);
0041 m_trackContainer.reserve(1000);
0042 m_endPoints.reserve(1000);
0043 }
0044
0045 SimTrackManager::~SimTrackManager() { reset(); }
0046
0047 void SimTrackManager::reset() {
0048 deleteTracks();
0049 cleanVertexMap();
0050 idsave.clear();
0051 ancestorList.clear();
0052 lastTrack = 0;
0053 lastHist = 0;
0054 }
0055
0056 void SimTrackManager::deleteTracks() {
0057 if (!m_trackContainer.empty()) {
0058 for (auto const& ptr : m_trackContainer) {
0059 delete ptr;
0060 }
0061 m_trackContainer.clear();
0062 m_endPoints.clear();
0063 }
0064 }
0065
0066 void SimTrackManager::cleanVertexMap() {
0067 m_vertexMap.clear();
0068 m_vertexMap.swap(m_vertexMap);
0069 m_nVertices = 0;
0070 }
0071
0072 void SimTrackManager::addTrack(TrackWithHistory* iTrack, const G4Track* track, bool inHistory, bool withAncestor) {
0073 std::pair<int, int> thePair(iTrack->trackID(), iTrack->parentID());
0074 idsave.push_back(thePair);
0075 if (inHistory) {
0076 auto info = static_cast<const TrackInformation*>(track->GetUserInformation());
0077 if (info->isInTrkFromBackscattering())
0078 iTrack->setFromBackScattering();
0079
0080
0081
0082
0083 if (not iTrack->isPrimary())
0084 iTrack->setGenParticleID(info->mcTruthID());
0085 m_trackContainer.push_back(iTrack);
0086 const auto& v = track->GetStep()->GetPostStepPoint()->GetPosition();
0087 std::pair<int, math::XYZVectorD> p(iTrack->trackID(),
0088 math::XYZVectorD(v.x() * invcm, v.y() * invcm, v.z() * invcm));
0089 m_endPoints.push_back(p);
0090 }
0091 if (withAncestor) {
0092 std::pair<int, int> thisPair(iTrack->trackID(), 0);
0093 ancestorList.push_back(thisPair);
0094 }
0095 }
0096
0097
0098 void SimTrackManager::saveTrackAndItsBranch(TrackWithHistory* trkWHist) {
0099 TrackWithHistory* trkH = trkWHist;
0100 if (trkH == nullptr) {
0101 edm::LogError("SimTrackManager") << " SimTrackManager::saveTrackAndItsBranch got 0 pointer ";
0102 throw cms::Exception("SimTrackManager::saveTrackAndItsBranch") << " cannot handle hits for tracking";
0103 }
0104 trkH->setToBeSaved();
0105 int parent = trkH->parentID();
0106
0107 auto tk_itr =
0108 std::lower_bound(m_trackContainer.begin(), m_trackContainer.end(), parent, SimTrackManager::StrictWeakOrdering());
0109
0110 if (tk_itr != m_trackContainer.end() && (*tk_itr)->trackID() == parent) {
0111 saveTrackAndItsBranch(*tk_itr);
0112 }
0113 }
0114
0115 void SimTrackManager::storeTracks() {
0116 cleanTracksWithHistory();
0117
0118
0119 idsave.swap(ancestorList);
0120 std::stable_sort(idsave.begin(), idsave.end());
0121
0122 std::vector<std::pair<int, int> >().swap(ancestorList);
0123
0124
0125 std::stable_sort(m_trackContainer.begin(), m_trackContainer.end(), trkIDLess());
0126
0127
0128 resetGenID();
0129
0130 reallyStoreTracks();
0131 }
0132
0133 void SimTrackManager::reallyStoreTracks() {
0134
0135 #ifdef DebugLog
0136 edm::LogVerbatim("SimTrackManager") << "reallyStoreTracks() NtracksWithHistory= " << m_trackContainer.size();
0137 #endif
0138
0139 int nn = m_endPoints.size();
0140 for (auto& trkH : m_trackContainer) {
0141
0142
0143 int iParentID = trkH->parentID();
0144 int ig = trkH->genParticleID();
0145 bool isBackScatter = trkH->isFromBackScattering();
0146 bool isPrimary = trkH->isPrimary();
0147 int primaryGenPartId = trkH->getPrimaryID();
0148 int ivertex = getOrCreateVertex(trkH, iParentID);
0149
0150 auto ptr = trkH;
0151 if (0 < iParentID) {
0152 for (auto& trk : m_trackContainer) {
0153 if (trk->trackID() == iParentID) {
0154 ptr = trk;
0155 break;
0156 }
0157 }
0158 }
0159
0160
0161
0162 const math::XYZVectorD& pm = ptr->momentum();
0163 math::XYZVectorD spos(0., 0., 0.);
0164 math::XYZTLorentzVectorD smom(0., 0., 0., 0.);
0165 int id = trkH->trackID();
0166 if (trkH->crossedBoundary()) {
0167 spos = trkH->getPositionAtBoundary();
0168 smom = trkH->getMomentumAtBoundary();
0169 } else {
0170 for (int i = 0; i < nn; ++i) {
0171 if (id == m_endPoints[i].first) {
0172 spos = m_endPoints[i].second;
0173 break;
0174 }
0175 }
0176 }
0177
0178 if (id >= static_cast<int>(PSimHit::k_tidOffset)) {
0179 throw cms::Exception("SimTrackManager::reallyStoreTracks")
0180 << " SimTrack ID " << id << " exceeds maximum allowed by PSimHit identifier" << PSimHit::k_tidOffset;
0181 }
0182 TmpSimTrack* g4simtrack =
0183 new TmpSimTrack(id, trkH->particleID(), trkH->momentum(), trkH->totalEnergy(), ivertex, ig, pm, spos, smom);
0184 g4simtrack->copyCrossedBoundaryVars(trkH);
0185 if (isBackScatter)
0186 g4simtrack->setFromBackScattering();
0187 if (isPrimary)
0188 g4simtrack->setIsPrimary();
0189 g4simtrack->setGenParticleID(primaryGenPartId);
0190 m_simEvent->addTrack(g4simtrack);
0191 }
0192 }
0193
0194 int SimTrackManager::getOrCreateVertex(TrackWithHistory* trkH, int iParentID) {
0195 int parent = -1;
0196 for (auto const& trk : m_trackContainer) {
0197 int id = trk->trackID();
0198 if (id == iParentID) {
0199 parent = id;
0200 break;
0201 }
0202 }
0203
0204 VertexMap::const_iterator iterator = m_vertexMap.find(parent);
0205 if (iterator != m_vertexMap.end()) {
0206
0207 for (auto const& xx : m_vertexMap[parent]) {
0208 if ((trkH->vertexPosition() - xx.second).Mag2() < r_limit2) {
0209 return xx.first;
0210 }
0211 }
0212 }
0213
0214 m_simEvent->addVertex(new TmpSimVertex(trkH->vertexPosition(), trkH->time(), parent, trkH->processType()));
0215 m_vertexMap[parent].push_back(VertexPosition(m_nVertices, trkH->vertexPosition()));
0216 ++m_nVertices;
0217 return (m_nVertices - 1);
0218 }
0219
0220 int SimTrackManager::idSavedTrack(int id) const {
0221 int idMother = id;
0222 if (id > 0) {
0223 unsigned int n = idsave.size();
0224 if (0 < n) {
0225 int jmax = n - 1;
0226 int j, id1;
0227
0228
0229 bool notFound = true;
0230 for (j = 0; j <= jmax; ++j) {
0231 if ((idsave[j]).first == idMother) {
0232 id1 = (idsave[j]).second;
0233 if (0 == id1 || id1 == idMother) {
0234 return id1;
0235 }
0236 jmax = j - 1;
0237 idMother = id1;
0238 notFound = false;
0239 break;
0240 }
0241 }
0242 if (notFound) {
0243 return 0;
0244 }
0245
0246
0247 do {
0248 notFound = true;
0249
0250 for (j = jmax; j >= 0; --j) {
0251 if ((idsave[j]).first == idMother) {
0252 id1 = (idsave[j]).second;
0253 if (0 == id1 || id1 == idMother) {
0254 return id1;
0255 }
0256 jmax = j - 1;
0257 idMother = id1;
0258 notFound = false;
0259 break;
0260 }
0261 }
0262 if (notFound) {
0263
0264 jmax = ancestorList.size() - 1;
0265 for (j = jmax; j >= 0; --j) {
0266 if ((ancestorList[j]).first == idMother) {
0267 idMother = (ancestorList[j]).second;
0268 return idMother;
0269 }
0270 }
0271 return 0;
0272 }
0273 } while (!notFound);
0274 }
0275 }
0276 return idMother;
0277 }
0278
0279 void SimTrackManager::fillMotherList() {
0280 if (!ancestorList.empty() && lastHist > ancestorList.size()) {
0281 lastHist = ancestorList.size();
0282 edm::LogError("SimTrackManager") << " SimTrackManager::fillMotherList track index corrupted";
0283 }
0284 #ifdef DebugLog
0285 edm::LogVerbatim("SimTrackManager") << "### SimTrackManager::fillMotherList: " << idsave.size()
0286 << " saved; ancestor: " << lastHist << " " << ancestorList.size();
0287 for (unsigned int i = 0; i < idsave.size(); ++i) {
0288 edm::LogVerbatim("SimTrackManager") << " ISV: Track ID = " << (idsave[i]).first
0289 << " Mother ID = " << (idsave[i]).second;
0290 }
0291 #endif
0292 for (unsigned int n = lastHist; n < ancestorList.size(); ++n) {
0293 int theMotherId = idSavedTrack((ancestorList[n]).first);
0294 ancestorList[n].second = theMotherId;
0295 #ifdef DebugLog
0296 LogDebug("SimTrackManager") << "Track ID = " << (ancestorList[n]).first
0297 << " Mother ID = " << (ancestorList[n]).second;
0298 #endif
0299 }
0300
0301 lastHist = ancestorList.size();
0302 idsave.clear();
0303 }
0304
0305 void SimTrackManager::cleanTracksWithHistory() {
0306 if (m_trackContainer.empty() && idsave.empty()) {
0307 return;
0308 }
0309
0310 #ifdef DebugLog
0311 LogDebug("SimTrackManager") << "SimTrackManager::cleanTracksWithHistory has " << idsave.size()
0312 << " mother-daughter relationships stored with lastTrack = " << lastTrack;
0313 #endif
0314
0315 if (lastTrack > 0 && lastTrack >= m_trackContainer.size()) {
0316 lastTrack = 0;
0317 edm::LogError("SimTrackManager") << " SimTrackManager::cleanTracksWithHistory track index corrupted";
0318 }
0319
0320 std::stable_sort(m_trackContainer.begin() + lastTrack, m_trackContainer.end(), trkIDLess());
0321 std::stable_sort(idsave.begin(), idsave.end());
0322
0323 #ifdef DebugLog
0324 LogDebug("SimTrackManager") << " SimTrackManager::cleanTracksWithHistory knows " << m_trackContainer.size()
0325 << " tracks with history before branching";
0326 for (unsigned int it = 0; it < m_trackContainer.size(); it++) {
0327 LogDebug("SimTrackManager") << " 1 - Track in position " << it << " G4 track number "
0328 << m_trackContainer[it]->trackID() << " mother " << m_trackContainer[it]->parentID()
0329 << " status " << m_trackContainer[it]->saved();
0330 }
0331 #endif
0332
0333 for (auto const& t : m_trackContainer) {
0334 if (t->saved()) {
0335 saveTrackAndItsBranch(t);
0336 }
0337 }
0338 unsigned int num = lastTrack;
0339 for (unsigned int it = lastTrack; it < m_trackContainer.size(); ++it) {
0340 auto t = m_trackContainer[it];
0341 int g4ID = m_trackContainer[it]->trackID();
0342 if (t->saved()) {
0343 if (it > num) {
0344 m_trackContainer[num] = t;
0345 }
0346 ++num;
0347 for (auto& xx : idsave) {
0348 if (xx.first == g4ID) {
0349 xx.second = g4ID;
0350 break;
0351 }
0352 }
0353 } else {
0354 delete t;
0355 }
0356 }
0357
0358 m_trackContainer.resize(num);
0359
0360 #ifdef DebugLog
0361 LogDebug("SimTrackManager") << " AFTER CLEANING, I GET " << m_trackContainer.size()
0362 << " tracks to be saved persistently";
0363 for (unsigned int it = 0; it < m_trackContainer.size(); ++it) {
0364 LogDebug("SimTrackManager") << " Track in position " << it << " G4 track number " << m_trackContainer[it]->trackID()
0365 << " mother " << m_trackContainer[it]->parentID() << " Status "
0366 << m_trackContainer[it]->saved() << " id " << m_trackContainer[it]->particleID()
0367 << " E(MeV)= " << m_trackContainer[it]->totalEnergy();
0368 }
0369 #endif
0370
0371 fillMotherList();
0372 lastTrack = m_trackContainer.size();
0373 }
0374
0375 void SimTrackManager::resetGenID() {
0376 if (theLHCTlink == nullptr)
0377 return;
0378
0379 for (auto const& trkH : m_trackContainer) {
0380 int genParticleID = trkH->genParticleID();
0381 if (genParticleID == -1) {
0382 continue;
0383 } else {
0384 for (auto const& xx : *theLHCTlink) {
0385 if (xx.afterHector() == genParticleID) {
0386 trkH->setGenParticleID(xx.beforeHector());
0387 continue;
0388 }
0389 }
0390 }
0391 }
0392
0393 theLHCTlink = nullptr;
0394 }
0395
0396 void SimTrackManager::ReportException(unsigned int id) const {
0397 throw cms::Exception("Unknown", "SimTrackManager::getTrackByID")
0398 << "Fail to get track " << id << " from SimTrackManager, container size= " << m_trackContainer.size();
0399 }