File indexing completed on 2025-08-05 08:17:46
0001 #include "PHG4CylinderSteppingAction.h"
0002 #include "PHG4CylinderDetector.h"
0003 #include "PHG4CylinderSubsystem.h"
0004
0005 #include "PHG4StepStatusDecode.h"
0006
0007 #include <phparameter/PHParameters.h>
0008
0009 #include <g4main/PHG4Hit.h>
0010 #include <g4main/PHG4HitContainer.h>
0011 #include <g4main/PHG4Hitv1.h>
0012 #include <g4main/PHG4Shower.h>
0013 #include <g4main/PHG4SteppingAction.h> // for PHG4SteppingAction
0014
0015 #include <g4main/PHG4TrackUserInfoV1.h>
0016
0017 #include <phool/getClass.h>
0018
0019 #include <Geant4/G4ParticleDefinition.hh> // for G4ParticleDefinition
0020 #include <Geant4/G4ReferenceCountedHandle.hh> // for G4ReferenceCountedHandle
0021 #include <Geant4/G4Step.hh>
0022 #include <Geant4/G4StepPoint.hh> // for G4StepPoint
0023 #include <Geant4/G4StepStatus.hh> // for fGeomBoundary, fPostSt...
0024 #include <Geant4/G4String.hh> // for G4String
0025 #include <Geant4/G4SystemOfUnits.hh>
0026 #include <Geant4/G4ThreeVector.hh> // for G4ThreeVector
0027 #include <Geant4/G4TouchableHandle.hh> // for G4TouchableHandle
0028 #include <Geant4/G4Track.hh> // for G4Track
0029 #include <Geant4/G4TrackStatus.hh> // for fStopAndKill
0030 #include <Geant4/G4Types.hh> // for G4double
0031 #include <Geant4/G4VPhysicalVolume.hh> // for G4VPhysicalVolume
0032 #include <Geant4/G4VTouchable.hh> // for G4VTouchable
0033 #include <Geant4/G4VUserTrackInformation.hh> // for G4VUserTrackInformation
0034
0035 #pragma GCC diagnostic push
0036 #pragma GCC diagnostic ignored "-Wshadow"
0037 #include <boost/io/ios_state.hpp>
0038 #pragma GCC diagnostic pop
0039
0040 #include <cmath> // for isfinite, copysign
0041 #include <cstdlib> // for exit
0042 #include <iomanip>
0043 #include <iostream>
0044 #include <string> // for operator<<, char_traits
0045
0046 class PHCompositeNode;
0047
0048
0049 PHG4CylinderSteppingAction::PHG4CylinderSteppingAction(PHG4CylinderSubsystem* subsys, PHG4CylinderDetector* detector, const PHParameters* parameters)
0050 : PHG4SteppingAction(detector->GetName())
0051 , m_Subsystem(subsys)
0052 , m_Detector(detector)
0053 , m_Params(parameters)
0054 , m_HitContainer(nullptr)
0055 , m_Hit(nullptr)
0056 , m_SaveShower(nullptr)
0057 , m_SaveVolPre(nullptr)
0058 , m_SaveVolPost(nullptr)
0059 , m_SaveLightYieldFlag(m_Params->get_int_param("lightyield"))
0060 , m_SaveTrackId(-1)
0061 , m_SavePreStepStatus(-1)
0062 , m_SavePostStepStatus(-1)
0063 , m_ActiveFlag(m_Params->get_int_param("active"))
0064 , m_BlackHoleFlag(m_Params->get_int_param("blackhole"))
0065 , m_UseG4StepsFlag(m_Params->get_int_param("use_g4steps"))
0066 , m_Zmin(m_Params->get_double_param("place_z") * cm - m_Params->get_double_param("length") * cm / 2.)
0067 , m_Zmax(m_Params->get_double_param("place_z") * cm + m_Params->get_double_param("length") * cm / 2.)
0068 , m_Tmin(m_Params->get_double_param("tmin") * ns)
0069 , m_Tmax(m_Params->get_double_param("tmax") * ns)
0070 {
0071
0072 m_Zmin -= copysign(m_Zmin, 1. / 1e6 * cm);
0073 m_Zmax += copysign(m_Zmax, 1. / 1e6 * cm);
0074 }
0075
0076 PHG4CylinderSteppingAction::~PHG4CylinderSteppingAction()
0077 {
0078
0079
0080
0081
0082 delete m_Hit;
0083 }
0084
0085
0086 bool PHG4CylinderSteppingAction::UserSteppingAction(const G4Step* aStep, bool )
0087 {
0088
0089 G4TouchableHandle touch = aStep->GetPreStepPoint()->GetTouchableHandle();
0090 G4TouchableHandle touchpost = aStep->GetPostStepPoint()->GetTouchableHandle();
0091
0092 G4VPhysicalVolume* volume = touch->GetVolume();
0093
0094
0095 if (!m_Detector->IsInCylinder(volume))
0096 {
0097 return false;
0098 }
0099
0100
0101 G4double edep = aStep->GetTotalEnergyDeposit() / GeV;
0102
0103 const G4Track* aTrack = aStep->GetTrack();
0104
0105
0106 if (m_BlackHoleFlag)
0107 {
0108 if ((!std::isfinite(m_Tmin) && !std::isfinite(m_Tmax)) ||
0109 aTrack->GetGlobalTime() < m_Tmin ||
0110 aTrack->GetGlobalTime() > m_Tmax)
0111 {
0112 edep = aTrack->GetKineticEnergy() / GeV;
0113 G4Track* killtrack = const_cast<G4Track*>(aTrack);
0114 killtrack->SetTrackStatus(fStopAndKill);
0115 }
0116 }
0117
0118 int layer_id = m_Detector->get_Layer();
0119
0120 if (m_ActiveFlag)
0121 {
0122 bool geantino = false;
0123
0124
0125
0126 if (aTrack->GetParticleDefinition()->GetPDGEncoding() == 0 &&
0127 aTrack->GetParticleDefinition()->GetParticleName().find("geantino") != std::string::npos)
0128 {
0129 geantino = true;
0130 }
0131 G4StepPoint* prePoint = aStep->GetPreStepPoint();
0132 G4StepPoint* postPoint = aStep->GetPostStepPoint();
0133
0134
0135
0136
0137
0138 int prepointstatus = prePoint->GetStepStatus();
0139 if (prepointstatus == fGeomBoundary ||
0140 prepointstatus == fUndefined ||
0141 (prepointstatus == fPostStepDoItProc && m_SavePostStepStatus == fGeomBoundary) ||
0142 m_UseG4StepsFlag > 0)
0143 {
0144 if (prepointstatus == fPostStepDoItProc && m_SavePostStepStatus == fGeomBoundary)
0145 {
0146 std::cout << GetName() << ": New Hit for " << std::endl;
0147 std::cout << "prestep status: " << PHG4StepStatusDecode::GetStepStatus(prePoint->GetStepStatus())
0148 << ", poststep status: " << PHG4StepStatusDecode::GetStepStatus(postPoint->GetStepStatus())
0149 << ", last pre step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePreStepStatus)
0150 << ", last post step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePostStepStatus) << std::endl;
0151 std::cout << "last track: " << m_SaveTrackId
0152 << ", current trackid: " << aTrack->GetTrackID() << std::endl;
0153 std::cout << "phys pre vol: " << volume->GetName()
0154 << " post vol : " << touchpost->GetVolume()->GetName() << std::endl;
0155 std::cout << " previous phys pre vol: " << m_SaveVolPre->GetName()
0156 << " previous phys post vol: " << m_SaveVolPost->GetName() << std::endl;
0157 }
0158
0159 if (!m_Hit)
0160 {
0161 m_Hit = new PHG4Hitv1();
0162 }
0163
0164 m_Hit->set_layer((unsigned int) layer_id);
0165
0166
0167 m_Hit->set_x(0, prePoint->GetPosition().x() / cm);
0168 m_Hit->set_y(0, prePoint->GetPosition().y() / cm);
0169 m_Hit->set_z(0, prePoint->GetPosition().z() / cm);
0170
0171 m_Hit->set_px(0, prePoint->GetMomentum().x() / GeV);
0172 m_Hit->set_py(0, prePoint->GetMomentum().y() / GeV);
0173 m_Hit->set_pz(0, prePoint->GetMomentum().z() / GeV);
0174
0175
0176 m_Hit->set_t(0, prePoint->GetGlobalTime() / nanosecond);
0177
0178 m_Hit->set_trkid(aTrack->GetTrackID());
0179 m_SaveTrackId = aTrack->GetTrackID();
0180
0181 m_Hit->set_edep(0);
0182 if (!geantino && !m_BlackHoleFlag)
0183 {
0184 m_Hit->set_eion(0);
0185 }
0186 if (m_SaveLightYieldFlag)
0187 {
0188 m_Hit->set_light_yield(0);
0189 }
0190 if (G4VUserTrackInformation* p = aTrack->GetUserInformation())
0191 {
0192 if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
0193 {
0194 m_Hit->set_trkid(pp->GetUserTrackId());
0195 m_Hit->set_shower_id(pp->GetShower()->get_id());
0196 m_SaveShower = pp->GetShower();
0197 }
0198 }
0199
0200 if (!hasMotherSubsystem() && (m_Hit->get_z(0) * cm > m_Zmax || m_Hit->get_z(0) * cm < m_Zmin))
0201 {
0202 boost::io::ios_precision_saver ips(std::cout);
0203 std::cout << m_Detector->SuperDetector() << std::setprecision(9)
0204 << " PHG4CylinderSteppingAction: Entry hit z " << m_Hit->get_z(0) * cm
0205 << " outside acceptance, zmin " << m_Zmin
0206 << ", zmax " << m_Zmax << ", layer: " << layer_id << std::endl;
0207 }
0208 }
0209
0210
0211
0212
0213
0214 if (!m_Hit || !std::isfinite(m_Hit->get_x(0)))
0215 {
0216 std::cout << GetName() << ": hit was not created" << std::endl;
0217 std::cout << "prestep status: " << PHG4StepStatusDecode::GetStepStatus(prePoint->GetStepStatus())
0218 << ", poststep status: " << PHG4StepStatusDecode::GetStepStatus(postPoint->GetStepStatus())
0219 << ", last pre step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePreStepStatus)
0220 << ", last post step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePostStepStatus) << std::endl;
0221 std::cout << "last track: " << m_SaveTrackId
0222 << ", current trackid: " << aTrack->GetTrackID() << std::endl;
0223 std::cout << "phys pre vol: " << volume->GetName()
0224 << " post vol : " << touchpost->GetVolume()->GetName() << std::endl;
0225 std::cout << " previous phys pre vol: " << m_SaveVolPre->GetName()
0226 << " previous phys post vol: " << m_SaveVolPost->GetName() << std::endl;
0227 exit(1);
0228 }
0229 m_SavePostStepStatus = postPoint->GetStepStatus();
0230
0231 if (aTrack->GetTrackID() != m_SaveTrackId)
0232 {
0233 std::cout << "hits do not belong to the same track" << std::endl;
0234 std::cout << "saved track: " << m_SaveTrackId
0235 << ", current trackid: " << aTrack->GetTrackID()
0236 << std::endl;
0237 exit(1);
0238 }
0239 m_SavePreStepStatus = prePoint->GetStepStatus();
0240 m_SavePostStepStatus = postPoint->GetStepStatus();
0241 m_SaveVolPre = volume;
0242 m_SaveVolPost = touchpost->GetVolume();
0243
0244 m_Hit->set_x(1, postPoint->GetPosition().x() / cm);
0245 m_Hit->set_y(1, postPoint->GetPosition().y() / cm);
0246 m_Hit->set_z(1, postPoint->GetPosition().z() / cm);
0247
0248 m_Hit->set_px(1, postPoint->GetMomentum().x() / GeV);
0249 m_Hit->set_py(1, postPoint->GetMomentum().y() / GeV);
0250 m_Hit->set_pz(1, postPoint->GetMomentum().z() / GeV);
0251
0252 m_Hit->set_t(1, postPoint->GetGlobalTime() / nanosecond);
0253
0254 m_Hit->set_edep(m_Hit->get_edep() + edep);
0255 if (!hasMotherSubsystem() && (m_Hit->get_z(1) * cm > m_Zmax || m_Hit->get_z(1) * cm < m_Zmin))
0256 {
0257 std::cout << m_Detector->SuperDetector() << std::setprecision(9)
0258 << " PHG4CylinderSteppingAction: Exit hit z " << m_Hit->get_z(1) * cm
0259 << " outside acceptance zmin " << m_Zmin
0260 << ", zmax " << m_Zmax << ", layer: " << layer_id << std::endl;
0261 }
0262 if (geantino)
0263 {
0264 m_Hit->set_edep(-1);
0265 }
0266 else
0267 {
0268 if (!m_BlackHoleFlag)
0269 {
0270 double eion = edep - aStep->GetNonIonizingEnergyDeposit() / GeV;
0271 m_Hit->set_eion(m_Hit->get_eion() + eion);
0272 }
0273 }
0274 if (m_SaveLightYieldFlag)
0275 {
0276 double light_yield = GetVisibleEnergyDeposition(aStep);
0277 m_Hit->set_light_yield(m_Hit->get_light_yield() + light_yield);
0278 }
0279 if (edep > 0 || m_SaveAllHitsFlag)
0280 {
0281 if (G4VUserTrackInformation* p = aTrack->GetUserInformation())
0282 {
0283 if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
0284 {
0285 pp->SetKeep(1);
0286 }
0287 }
0288 }
0289
0290
0291
0292
0293
0294
0295
0296
0297 if (postPoint->GetStepStatus() == fGeomBoundary ||
0298 postPoint->GetStepStatus() == fWorldBoundary ||
0299 postPoint->GetStepStatus() == fAtRestDoItProc ||
0300 aTrack->GetTrackStatus() == fStopAndKill ||
0301 m_UseG4StepsFlag > 0)
0302 {
0303
0304 if (m_Hit->get_edep() || m_SaveAllHitsFlag)
0305 {
0306 m_HitContainer->AddHit(layer_id, m_Hit);
0307 if (m_SaveShower)
0308 {
0309 m_SaveShower->add_g4hit_id(m_HitContainer->GetID(), m_Hit->get_hit_id());
0310 }
0311
0312
0313 m_Hit = nullptr;
0314 }
0315 else
0316 {
0317
0318
0319
0320 m_Hit->Reset();
0321 }
0322 }
0323
0324 return true;
0325 }
0326 else
0327 {
0328 return false;
0329 }
0330 }
0331
0332
0333 void PHG4CylinderSteppingAction::SetInterfacePointers(PHCompositeNode* topNode)
0334 {
0335
0336
0337 m_HitContainer = findNode::getClass<PHG4HitContainer>(topNode, m_HitNodeName);
0338
0339
0340 if (!m_HitContainer && !m_BlackHoleFlag)
0341 {
0342 std::cout << "PHG4CylinderSteppingAction::SetTopNode - unable to find " << m_HitNodeName << std::endl;
0343 }
0344 }
0345
0346 bool PHG4CylinderSteppingAction::hasMotherSubsystem() const
0347 {
0348 if (m_Subsystem->GetMotherSubsystem())
0349 {
0350 return true;
0351 }
0352 return false;
0353 }