/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
SimG4CMS/Forward/src/TimingSD.cc
382 строки
12 KB
Fabio Cossutti
Squashed commit of the following:
08 апр 2026, 18:03
08 апр 2026, 18:03
5b2960f
Код
Авторство
О чём код?
//#define EDM_ML_DEBUG /////////////////////////////////////////////////////////////////////////////// // File: TimingSD.cc // Date: 02.2006 // Description: Sensitive Detector class for Timing // Modifications: /////////////////////////////////////////////////////////////////////////////// #include "SimG4CMS/Forward/interface/TimingSD.h" #include "SimG4Core/Notification/interface/G4TrackToParticleID.h" #include "SimG4Core/Physics/interface/G4ProcessTypeEnumerator.h" #include "SimDataFormats/SimHitMaker/interface/TrackingSlaveSD.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" #include "G4Step.hh" #include "G4StepPoint.hh" #include "G4Track.hh" #include "G4VPhysicalVolume.hh" #include "G4SDManager.hh" #include "G4VProcess.hh" #include "G4PhysicalConstants.hh" #include <CLHEP/Units/SystemOfUnits.h> #include <vector> #include <iostream> static const float invgev = 1.0 / CLHEP::GeV; static const double invns = 1.0 / CLHEP::nanosecond; static const double invdeg = 1.0 / CLHEP::deg; //------------------------------------------------------------------- TimingSD::TimingSD(const std::string& name, const SensitiveDetectorCatalog& clg, const SimTrackManager* manager) : SensitiveTkDetector(name, clg), theManager(manager), theHC(nullptr), currentHit(nullptr), theTrack(nullptr), preStepPoint(nullptr), postStepPoint(nullptr), unitID(0), previousUnitID(0), primID(-2), hcID(-1), tsID(-2), primaryID(0), tSliceID(-1), timeFactor(1.0), energyCut(1.e+9), energyHistoryCut(1.e+9), hitClassID(0) { slave = new TrackingSlaveSD(name); theEnumerator = new G4ProcessTypeEnumerator(); } TimingSD::~TimingSD() { delete slave; delete theEnumerator; } void TimingSD::Initialize(G4HCofThisEvent* HCE) { edm::LogVerbatim("TimingSim") << "TimingSD : Initialize called for " << GetName() << " time slice factor " << timeFactor << "\n MC truth cuts in are " << energyCut / CLHEP::GeV << " GeV and " << energyHistoryCut / CLHEP::GeV << " GeV"; theHC = new BscG4HitCollection(GetName(), collectionName[0]); if (hcID < 0) { hcID = G4SDManager::GetSDMpointer()->GetCollectionID(collectionName[0]); } HCE->AddHitsCollection(hcID, theHC); tsID = -2; primID = -2; } void TimingSD::setTimeFactor(double val) { if (val <= 0.0) { return; } timeFactor = val; #ifdef EDM_ML_DEBUG edm::LogVerbatim("TimingSim") << "TimingSD : for " << GetName() << " time slice factor is set to " << timeFactor; #endif } void TimingSD::setCuts(double eCut, double historyCut) { if (eCut > 0.) { energyCut = eCut; } if (historyCut > 0.) { energyHistoryCut = historyCut; } #ifdef EDM_ML_DEBUG edm::LogVerbatim("TimingSim") << "TimingSD : for " << GetName() << " MC truth cuts in are " << energyCut / CLHEP::GeV << " GeV and " << energyHistoryCut / CLHEP::GeV << " GeV"; #endif } bool TimingSD::ProcessHits(G4Step* aStep, G4TouchableHistory*) { edeposit = aStep->GetTotalEnergyDeposit(); if (edeposit > 0.f) { getStepInfo(aStep); if (!hitExists(aStep)) { createNewHit(aStep); } } return true; } void TimingSD::getStepInfo(const G4Step* aStep) { const G4Track* newTrack = aStep->GetTrack(); preStepPoint = aStep->GetPreStepPoint(); postStepPoint = aStep->GetPostStepPoint(); hitPointExit = postStepPoint->GetPosition(); setToLocal(preStepPoint, hitPointExit, hitPointLocalExit); // neutral particles deliver energy post step // charged particle start deliver energy pre step if (newTrack->GetDefinition()->GetPDGCharge() == 0.0) { hitPoint = hitPointExit; hitPointLocal = hitPointLocalExit; tof = (float)(postStepPoint->GetGlobalTime() * invns); } else { hitPoint = preStepPoint->GetPosition(); setToLocal(preStepPoint, hitPoint, hitPointLocal); tof = (float)(preStepPoint->GetGlobalTime() * invns); } #ifdef EDM_ML_DEBUG double distGlobal = std::sqrt(std::pow(hitPoint.x() - hitPointExit.x(), 2) + std::pow(hitPoint.y() - hitPointExit.y(), 2) + std::pow(hitPoint.z() - hitPointExit.z(), 2)); double distLocal = std::sqrt(std::pow(hitPointLocal.x() - hitPointLocalExit.x(), 2) + std::pow(hitPointLocal.y() - hitPointLocalExit.y(), 2) + std::pow(hitPointLocal.z() - hitPointLocalExit.z(), 2)); LogDebug("TimingSim") << "TimingSD:" << "\n Global entry point: " << hitPoint << "\n Global exit point: " << hitPointExit << "\n Global step length: " << distGlobal << "\n Local entry point: " << hitPointLocal << "\n Local exit point: " << hitPointLocalExit << "\n Local step length: " << distLocal; if (std::fabs(distGlobal - distLocal) > 1.e-6) { LogDebug("TimingSim") << "DIFFERENCE IN DISTANCE \n"; } #endif incidentEnergy = preStepPoint->GetKineticEnergy(); // should MC truth be saved if (newTrack != theTrack) { theTrack = newTrack; TrackInformation* info = cmsTrackInformation(theTrack); if (nullptr != info) { if (incidentEnergy > energyCut) { info->setStoreTrack(); if (info->idLastStoredAncestor() == theTrack->GetParentID()) info->setIdLastStoredAncestor(theTrack->GetTrackID()); } if (incidentEnergy > energyHistoryCut) { info->putInHistory(); } #ifdef EDM_ML_DEBUG LogDebug("TimingSim") << "TrackInformation for ID = " << theTrack->GetTrackID(); info->Print(); #endif } } edeposit *= invgev; if (G4TrackToParticleID::isGammaElectronPositron(theTrack)) { edepositEM = edeposit; edepositHAD = 0.f; } else { edepositEM = 0.f; edepositHAD = edeposit; } // time slice is defined for the entry point tSlice = timeFactor * preStepPoint->GetGlobalTime() * invns; tSliceID = (int)tSlice; setHitClassID(aStep); unitID = setDetUnitId(aStep); primaryID = getTrackID(theTrack); } bool TimingSD::hitExists(const G4Step* aStep) { if (!currentHit) { return false; } // Update if in the same detector and time-slice if (tSliceID == tsID && unitID == previousUnitID) { updateHit(); return true; } //look in the HitContainer whether a hit with the same primID, unitID, //tSliceID already exists: bool found = false; int thehc_entries = theHC->entries(); for (int j = 0; j < thehc_entries; ++j) { BscG4Hit* aHit = (*theHC)[j]; if (aHit->getTimeSliceID() == tSliceID && aHit->getUnitID() == unitID) { if (checkHit(aStep, aHit)) { currentHit = aHit; found = true; break; } } } if (found) { updateHit(); } return found; } bool TimingSD::checkHit(const G4Step*, BscG4Hit* hit) { // change hit info to fastest primary particle if (tof < hit->getTof()) { hit->setTrackID(primaryID); hit->setIncidentEnergy((float)incidentEnergy); hit->setPabs(float(preStepPoint->GetMomentum().mag()) * invgev); hit->setTof(tof); hit->setParticleType(theTrack->GetDefinition()->GetPDGEncoding()); float ThetaAtEntry = (float)(hitPointLocal.theta() * invdeg); float PhiAtEntry = (float)(hitPointLocal.phi() * invdeg); hit->setThetaAtEntry(ThetaAtEntry); hit->setPhiAtEntry(PhiAtEntry); hit->setEntry(hitPoint); hit->setEntryLocalP(hitPointLocal); hit->setExitLocalP(hitPointLocalExit); hit->setParentId(theTrack->GetParentID()); hit->setProcessId(theEnumerator->processId(theTrack->GetCreatorProcess())); hit->setHitProdType(hitClassID); hit->setVertexPosition(theTrack->GetVertexPosition()); } return true; } void TimingSD::storeHit(BscG4Hit* hit) { if (primID < 0) return; if (hit == nullptr) { edm::LogWarning("BscSim") << "BscSD: hit to be stored is NULL !!"; return; } theHC->insert(hit); } void TimingSD::createNewHit(const G4Step* aStep) { #ifdef EDM_ML_DEBUG const G4VPhysicalVolume* currentPV = preStepPoint->GetPhysicalVolume(); edm::LogVerbatim("TimingSim") << "TimingSD CreateNewHit for " << GetName() << " PV " << currentPV->GetName() << " PVid = " << currentPV->GetCopyNo() << " Unit " << unitID << "\n primary " << primaryID << " Tof(ns)= " << tof << " time slice " << tSliceID << " E(MeV)= " << incidentEnergy << " trackID " << theTrack->GetTrackID() << " " << theTrack->GetDefinition()->GetParticleName() << " parentID " << theTrack->GetParentID(); if (theTrack->GetCreatorProcess() != nullptr) { edm::LogVerbatim("TimingSim") << theTrack->GetCreatorProcess()->GetProcessName(); } else { edm::LogVerbatim("TimingSim") << " is primary particle"; } #endif currentHit = new BscG4Hit; currentHit->setTrackID(primaryID); currentHit->setTimeSlice(tSlice); currentHit->setUnitID(unitID); currentHit->setIncidentEnergy((float)incidentEnergy); currentHit->setPabs(float(preStepPoint->GetMomentum().mag() * invgev)); currentHit->setTof(tof); currentHit->setParticleType(theTrack->GetDefinition()->GetPDGEncoding()); float ThetaAtEntry = hitPointLocal.theta() * invdeg; float PhiAtEntry = hitPointLocal.phi() * invdeg; currentHit->setThetaAtEntry(ThetaAtEntry); currentHit->setPhiAtEntry(PhiAtEntry); currentHit->setEntry(hitPoint); currentHit->setEntryLocalP(hitPointLocal); currentHit->setExitLocalP(hitPointLocalExit); currentHit->setParentId(theTrack->GetParentID()); currentHit->setProcessId(theEnumerator->processId(theTrack->GetCreatorProcess())); currentHit->setHitProdType(hitClassID); currentHit->setVertexPosition(theTrack->GetVertexPosition()); updateHit(); storeHit(currentHit); } void TimingSD::updateHit() { currentHit->addEnergyDeposit(edepositEM, edepositHAD); #ifdef EDM_ML_DEBUG edm::LogVerbatim("TimingSim") << "updateHit: " << GetName() << " add eloss(GeV) " << edeposit << "CurrentHit=" << currentHit << ", PostStepPoint= " << postStepPoint->GetPosition(); #endif // buffer for next steps: tsID = tSliceID; primID = primaryID; previousUnitID = unitID; } void TimingSD::setToLocal(const G4StepPoint* stepPoint, const G4ThreeVector& globalPoint, G4ThreeVector& localPoint) { const G4VTouchable* touch = stepPoint->GetTouchable(); localPoint = touch->GetHistory()->GetTopTransform().TransformPoint(globalPoint); } void TimingSD::EndOfEvent(G4HCofThisEvent*) { int nhits = theHC->entries(); if (0 == nhits) { return; } // here we loop over transient hits and make them persistent for (int j = 0; j < nhits; ++j) { BscG4Hit* aHit = (*theHC)[j]; Local3DPoint locEntryPoint = ConvertToLocal3DPoint(aHit->getEntryLocalP()); Local3DPoint locExitPoint = ConvertToLocal3DPoint(aHit->getExitLocalP()); #ifdef EDM_ML_DEBUG edm::LogVerbatim("TimingSim") << "TimingSD: Hit for storage \n" << *aHit << "\n Entry point: " << locEntryPoint << "\n Exit point: " << locExitPoint; #endif slave->processHits(PSimHit(locEntryPoint, locExitPoint, aHit->getPabs(), aHit->getTof(), aHit->getEnergyLoss(), aHit->getParticleType(), aHit->getUnitID(), aHit->getTrackID(), aHit->getThetaAtEntry(), aHit->getPhiAtEntry(), aHit->getProcessId())); } } void TimingSD::PrintAll() { #ifdef EDM_ML_DEBUG edm::LogVerbatim("TimingSim") << "TimingSD: Collection " << theHC->GetName(); #endif theHC->PrintAllHits(); } void TimingSD::fillHits(edm::PSimHitContainer& cc, const std::string& hname) { if (slave->name() == hname) { cc = slave->hits(); } } void TimingSD::update(const BeginOfEvent* i) { #ifdef EDM_ML_DEBUG edm::LogVerbatim("TimingSim") << " Dispatched BeginOfEvent for " << GetName(); #endif clearHits(); } void TimingSD::clearHits() { slave->Initialize(); } int TimingSD::getTrackID(const G4Track* aTrack) { LogDebug("TimingSim") << "primary ID: " << aTrack->GetTrackID(); return aTrack->GetTrackID(); } void TimingSD::setHitClassID(const G4Step* aStep) { hitClassID = 0; }