Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:17:41

0001 #include "PHG4BbcSteppingAction.h"
0002 
0003 #include "PHG4BbcDetector.h"
0004 #include "PHG4StepStatusDecode.h"
0005 
0006 #include <phparameter/PHParameters.h>
0007 
0008 #include <g4main/PHG4Hit.h>
0009 #include <g4main/PHG4HitContainer.h>
0010 #include <g4main/PHG4Hitv1.h>
0011 #include <g4main/PHG4Shower.h>
0012 #include <g4main/PHG4SteppingAction.h>  // for PHG4SteppingAction
0013 #include <g4main/PHG4TrackUserInfoV1.h>
0014 
0015 #include <phool/getClass.h>
0016 
0017 #include <TSystem.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, fAtRest...
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 #include <cmath>  // for isfinite
0036 #include <iostream>
0037 #include <string>  // for operator<<, string
0038 
0039 class PHCompositeNode;
0040 
0041 //____________________________________________________________________________..
0042 PHG4BbcSteppingAction::PHG4BbcSteppingAction(PHG4BbcDetector* detector, const PHParameters* parameters)
0043   : PHG4SteppingAction(detector->GetName())
0044   , m_Detector(detector)
0045   , m_Params(parameters)
0046   , m_ActiveFlag(m_Params->get_int_param("active"))
0047   , m_BlackHoleFlag(m_Params->get_int_param("blackhole"))
0048   , m_SupportFlag(m_Params->get_int_param("supportactive"))
0049 {
0050 }
0051 
0052 PHG4BbcSteppingAction::~PHG4BbcSteppingAction()
0053 {
0054   // if the last hit was a zero energie deposit hit, it is just reset
0055   // and the memory is still allocated, so we need to delete it here
0056   // if the last hit was saved, hit is a nullptr pointer which are
0057   // legal to delete (it results in a no operation)
0058   delete m_Hit;
0059 }
0060 
0061 //____________________________________________________________________________..
0062 bool PHG4BbcSteppingAction::UserSteppingAction(const G4Step* aStep, bool /*was_used*/)
0063 {
0064   // std::cout << PHWHERE << " In PHG4BbcSteppingAction::UserSteppingAction()" << std::endl;
0065 
0066   G4TouchableHandle touch = aStep->GetPreStepPoint()->GetTouchableHandle();
0067   G4TouchableHandle touchpost = aStep->GetPostStepPoint()->GetTouchableHandle();
0068   // get volume of the current step
0069   G4VPhysicalVolume* volume = touch->GetVolume();
0070   // IsInBbc(volume) returns
0071   //  == 0 outside of bbc
0072   //  > 0 for hits in active volume
0073   //  < 0 for hits in passive material
0074   int whichactive = m_Detector->IsInBbc(volume);
0075   if (!whichactive)
0076   {
0077     return false;
0078   }
0079 
0080   // std::cout << PHWHERE << " Found Hit" << std::endl;
0081 
0082   // collect energy and track length step by step
0083   G4double edep = aStep->GetTotalEnergyDeposit() / GeV;
0084   G4double eion = (aStep->GetTotalEnergyDeposit() - aStep->GetNonIonizingEnergyDeposit()) / GeV;
0085   G4double steplen = aStep->GetStepLength() / cm;
0086   const G4Track* aTrack = aStep->GetTrack();
0087 
0088   // check steplength vs tracklength
0089   /*
0090   G4double tracklen = aTrack->GetTrackLength() / cm;
0091   if ( tracklen != steplen )
0092   {
0093     std::cout << "YYY " << tracklen << "\t" << steplen << std::endl;
0094   }
0095   */
0096 
0097   // if this detector stops everything, just put all kinetic energy into edep
0098   if (m_BlackHoleFlag)
0099   {
0100     edep = aTrack->GetKineticEnergy() / GeV;
0101     G4Track* killtrack = const_cast<G4Track*>(aTrack);
0102     killtrack->SetTrackStatus(fStopAndKill);
0103     if (!m_ActiveFlag)
0104     {
0105       return false;
0106     }
0107   }
0108   if (whichactive < 0 && !m_SupportFlag)
0109   {
0110     return false;
0111   }
0112   bool geantino = false;
0113   // the check for the pdg code speeds things up, I do not want to make
0114   // an expensive string compare for every track when we know
0115   // geantino or chargedgeantino has pid=0
0116   if (aTrack->GetParticleDefinition()->GetPDGEncoding() == 0 &&
0117       aTrack->GetParticleDefinition()->GetParticleName().find("geantino") != std::string::npos)
0118   {
0119     geantino = true;
0120   }
0121 
0122   G4StepPoint* prePoint = aStep->GetPreStepPoint();
0123   G4StepPoint* postPoint = aStep->GetPostStepPoint();
0124   //       std::cout << "track id " << aTrack->GetTrackID() << std::endl;
0125   //       std::cout << "time prepoint: " << prePoint->GetGlobalTime() << std::endl;
0126   //       std::cout << "time postpoint: " << postPoint->GetGlobalTime() << std::endl;
0127 
0128   // int detector_id = touch->GetCopyNumber(); // not used
0129   int tube_id = touch->GetCopyNumber(1);
0130 
0131   // Create a new hit if a G4 Track enters a new volume or is freshly created
0132   // For this we look at the step status of the prePoint (beginning of the G4 Step).
0133   // This should be either fGeomBoundary (G4 Track crosses into volume) or
0134   // fUndefined (G4 Track newly created)
0135 
0136   switch (prePoint->GetStepStatus())
0137   {
0138   case fPostStepDoItProc:
0139     if (m_SavePostStepStatus != fGeomBoundary)
0140     {
0141       // this is the okay case, fPostStepDoItProc called in a volume, not first thing inside
0142       // a new volume, just proceed here
0143       break;
0144     }
0145     else
0146     {
0147       // this is an impossible G4 Step print out diagnostic to help debug, not sure if
0148       // this is still with us
0149       std::cout << GetName() << ": New Hit for  " << std::endl;
0150       std::cout << "prestep status: " << PHG4StepStatusDecode::GetStepStatus(prePoint->GetStepStatus())
0151                 << ", poststep status: " << PHG4StepStatusDecode::GetStepStatus(postPoint->GetStepStatus())
0152                 << ", last pre step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePreStepStatus)
0153                 << ", last post step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePostStepStatus) << std::endl;
0154       std::cout << "last track: " << m_SaveTrackId
0155                 << ", current trackid: " << aTrack->GetTrackID() << std::endl;
0156       std::cout << "phys pre vol: " << volume->GetName()
0157                 << " post vol : " << touchpost->GetVolume()->GetName() << std::endl;
0158       std::cout << " previous phys pre vol: " << m_SaveVolPre->GetName()
0159                 << " previous phys post vol: " << m_SaveVolPost->GetName() << std::endl;
0160     }
0161     [[fallthrough]];
0162   // These are the normal cases
0163   case fGeomBoundary:
0164   case fUndefined:
0165     if (!m_Hit)
0166     {
0167       m_Hit = new PHG4Hitv1();
0168     }
0169     m_Hit->set_layer(tube_id);
0170     m_Hit->set_scint_id(tube_id);
0171 
0172     // here we set the entrance values in cm
0173     m_Hit->set_x(0, prePoint->GetPosition().x() / cm);
0174     m_Hit->set_y(0, prePoint->GetPosition().y() / cm);
0175     m_Hit->set_z(0, prePoint->GetPosition().z() / cm);
0176     // time in ns
0177     m_Hit->set_t(0, prePoint->GetGlobalTime() / ns);
0178     // set the track ID
0179     m_Hit->set_trkid(aTrack->GetTrackID());
0180     m_SaveTrackId = aTrack->GetTrackID();
0181 
0182     // set the initial energy deposit
0183     m_EdepSum = 0;
0184     if (whichactive > 0)
0185     {
0186       m_EionSum = 0;
0187       m_Hit->set_eion(0);
0188 
0189       m_PathLen = 0.;
0190       m_Hit->set_path_length(m_PathLen);
0191 
0192       m_SaveHitContainer = m_HitContainer;
0193     }
0194     else
0195     {
0196       m_SaveHitContainer = m_SupportHitContainer;
0197     }
0198 
0199     // this is for the tracking of the truth info
0200     if (G4VUserTrackInformation* p = aTrack->GetUserInformation())
0201     {
0202       if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
0203       {
0204         m_Hit->set_trkid(pp->GetUserTrackId());
0205         pp->GetShower()->add_g4hit_id(m_SaveHitContainer->GetID(), m_Hit->get_hit_id());
0206       }
0207     }
0208 
0209     break;
0210   default:
0211     break;
0212   }
0213 
0214   // some sanity checks for inconsistencies
0215   // check if this hit was created, if not print out last post step status
0216   if (!m_Hit || !std::isfinite(m_Hit->get_x(0)))
0217   {
0218     std::cout << GetName() << ": hit was not created" << std::endl;
0219     std::cout << "prestep status: " << PHG4StepStatusDecode::GetStepStatus(prePoint->GetStepStatus())
0220               << ", poststep status: " << PHG4StepStatusDecode::GetStepStatus(postPoint->GetStepStatus())
0221               << ", last pre step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePreStepStatus)
0222               << ", last post step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePostStepStatus) << std::endl;
0223     std::cout << "last track: " << m_SaveTrackId
0224               << ", current trackid: " << aTrack->GetTrackID() << std::endl;
0225     std::cout << "phys pre vol: " << volume->GetName()
0226               << " post vol : " << touchpost->GetVolume()->GetName() << std::endl;
0227     std::cout << " previous phys pre vol: " << m_SaveVolPre->GetName()
0228               << " previous phys post vol: " << m_SaveVolPost->GetName() << std::endl;
0229     gSystem->Exit(1);
0230   }
0231 
0232   // check if track id matches the initial one when the hit was created
0233   if (aTrack->GetTrackID() != m_SaveTrackId)
0234   {
0235     std::cout << GetName() << ": hits do not belong to the same track" << std::endl;
0236     std::cout << "saved track: " << m_SaveTrackId
0237               << ", current trackid: " << aTrack->GetTrackID()
0238               << ", prestep status: " << prePoint->GetStepStatus()
0239               << ", previous post step status: " << m_SavePostStepStatus
0240               << std::endl;
0241 
0242     gSystem->Exit(1);
0243   }
0244 
0245   // We need to cache a few things from one step to the next
0246   // to identify impossible hits and subsequent debugging printout
0247   m_SavePreStepStatus = prePoint->GetStepStatus();
0248   m_SavePostStepStatus = postPoint->GetStepStatus();
0249   m_SaveVolPre = volume;
0250   m_SaveVolPost = touchpost->GetVolume();
0251 
0252   // here we just update the exit values, it will be overwritten
0253   // for every step until we leave the volume or the particle
0254   // ceases to exist
0255 
0256   // Sum up the energies and lengths to get totals
0257   m_EdepSum += edep;
0258   if (whichactive > 0)
0259   {
0260     m_EionSum += eion;
0261     m_PathLen += steplen;
0262   }
0263 
0264   // if any of these conditions is true this is the last step in
0265   // this volume and we need to save the hit
0266   // postPoint->GetStepStatus() == fGeomBoundary: track leaves this volume
0267   // postPoint->GetStepStatus() == fWorldBoundary: track leaves this world
0268   // (happens when your detector goes outside world volume)
0269   // postPoint->GetStepStatus() == fAtRestDoItProc: track stops (typically
0270   // aTrack->GetTrackStatus() == fStopAndKill is also set)
0271   // aTrack->GetTrackStatus() == fStopAndKill: track ends
0272   if (postPoint->GetStepStatus() == fGeomBoundary ||
0273       postPoint->GetStepStatus() == fWorldBoundary ||
0274       postPoint->GetStepStatus() == fAtRestDoItProc ||
0275       aTrack->GetTrackStatus() == fStopAndKill)
0276   {
0277     // save only hits with energy deposit (or geantino)
0278     if (m_EdepSum > 0 || geantino)
0279     {
0280       // update values at exit coordinates and set keep flag
0281       // of track to keep
0282       m_Hit->set_x(1, postPoint->GetPosition().x() / cm);
0283       m_Hit->set_y(1, postPoint->GetPosition().y() / cm);
0284       m_Hit->set_z(1, postPoint->GetPosition().z() / cm);
0285 
0286       m_Hit->set_t(1, postPoint->GetGlobalTime() / nanosecond);
0287       if (G4VUserTrackInformation* p = aTrack->GetUserInformation())
0288       {
0289         if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
0290         {
0291           pp->SetKeep(1);  // we want to keep the track
0292         }
0293       }
0294       if (geantino)
0295       {
0296         m_Hit->set_edep(-1);  // only energy=0 g4hits get dropped, this way geantinos survive the g4hit compression
0297         if (whichactive > 0)
0298         {
0299           m_Hit->set_eion(-1);
0300           m_Hit->set_path_length(-1);
0301         }
0302       }
0303       else
0304       {
0305         m_Hit->set_edep(m_EdepSum);
0306       }
0307       if (whichactive > 0)
0308       {
0309         m_Hit->set_eion(m_EionSum);
0310         m_Hit->set_path_length(m_PathLen);
0311       }
0312       m_SaveHitContainer->AddHit(tube_id, m_Hit);
0313       // ownership has been transferred to container, set to null
0314       // so we will create a new hit for the next track
0315       m_Hit = nullptr;
0316     }
0317     else
0318     {
0319       // if this hit has no energy deposit, just reset it for reuse
0320       // this means we have to delete it in the dtor. If this was
0321       // the last hit we processed the memory is still allocated
0322       m_Hit->Reset();
0323     }
0324   }
0325   // return true to indicate the hit was used
0326   return true;
0327 }
0328 
0329 //____________________________________________________________________________..
0330 void PHG4BbcSteppingAction::SetInterfacePointers(PHCompositeNode* topNode)
0331 {
0332   m_HitContainer = findNode::getClass<PHG4HitContainer>(topNode, m_HitNodeName);
0333   m_SupportHitContainer = findNode::getClass<PHG4HitContainer>(topNode, m_SupportNodeName);
0334   // if we do not find the node it's messed up.
0335   if (!m_HitContainer)
0336   {
0337     if (!m_Params->get_int_param("blackhole"))  // not messed up if we have a black hole
0338     {
0339       std::cout << "PHG4BbcSteppingAction::SetTopNode - unable to find " << m_HitNodeName << std::endl;
0340       gSystem->Exit(1);
0341     }
0342   }
0343   // this is perfectly fine if support hits are disabled
0344   if (!m_SupportHitContainer)
0345   {
0346     if (Verbosity() > 0)
0347     {
0348       std::cout << "PHG4BbcSteppingAction::SetTopNode - unable to find " << m_SupportNodeName << std::endl;
0349     }
0350   }
0351 }
0352 
0353 void PHG4BbcSteppingAction::SetHitNodeName(const std::string& type, const std::string& name)
0354 {
0355   if (type == "G4HIT")
0356   {
0357     m_HitNodeName = name;
0358     return;
0359   }
0360   else if (type == "G4HIT_SUPPORT")
0361   {
0362     m_SupportNodeName = name;
0363     return;
0364   }
0365   std::cout << "Invalid output hit node type " << type << std::endl;
0366   gSystem->Exit(1);
0367   return;
0368 }