Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:22:06

0001 #include "PHG4Prototype2OuterHcalSteppingAction.h"
0002 #include "PHG4Prototype2OuterHcalDetector.h"
0003 
0004 #include <phparameter/PHParameters.h>
0005 
0006 #include <g4main/PHG4Hit.h>
0007 #include <g4main/PHG4HitContainer.h>
0008 #include <g4main/PHG4Hitv1.h>
0009 #include <g4main/PHG4Shower.h>
0010 #include <g4main/PHG4SteppingAction.h>         // for PHG4SteppingAction
0011 #include <g4main/PHG4TrackUserInfoV1.h>
0012 
0013 #include <phool/getClass.h>
0014 
0015 #include <Geant4/G4ParticleDefinition.hh>      // for G4ParticleDefinition
0016 #include <Geant4/G4ReferenceCountedHandle.hh>  // for G4ReferenceCountedHandle
0017 #include <Geant4/G4Step.hh>
0018 #include <Geant4/G4StepPoint.hh>               // for G4StepPoint
0019 #include <Geant4/G4StepStatus.hh>              // for fGeomBoundary, fAtRest...
0020 #include <Geant4/G4String.hh>                  // for G4String
0021 #include <Geant4/G4SystemOfUnits.hh>
0022 #include <Geant4/G4ThreeVector.hh>             // for G4ThreeVector
0023 #include <Geant4/G4TouchableHandle.hh>         // for G4TouchableHandle
0024 #include <Geant4/G4Track.hh>                   // for G4Track
0025 #include <Geant4/G4TrackStatus.hh>             // for fStopAndKill
0026 #include <Geant4/G4Types.hh>                   // for G4double
0027 #include <Geant4/G4VPhysicalVolume.hh>         // for G4VPhysicalVolume
0028 #include <Geant4/G4VTouchable.hh>              // for G4VTouchable
0029 #include <Geant4/G4VUserTrackInformation.hh>   // for G4VUserTrackInformation
0030 
0031 #include <cmath>                               // for isfinite, sqrt
0032 #include <iostream>
0033 #include <string>                              // for string, operator+, ope...
0034 
0035 class PHCompositeNode;
0036 
0037 using namespace std;
0038 //____________________________________________________________________________..
0039 PHG4Prototype2OuterHcalSteppingAction::PHG4Prototype2OuterHcalSteppingAction(PHG4Prototype2OuterHcalDetector* detector, const PHParameters* parameters)
0040   :   PHG4SteppingAction(detector->GetName())
0041   , m_Detector(detector)
0042   , m_Hits(nullptr)
0043   , m_AbsorberHits(nullptr)
0044   , m_Hit(nullptr)
0045   , m_Params(parameters)
0046   , m_SaveHitContainer(nullptr)
0047   , m_SaveShower(nullptr)
0048   , m_AbsorberTruthFlag(m_Params->get_int_param("absorbertruth"))
0049   , m_IsActiveFlag(m_Params->get_int_param("active"))
0050   , m_IsBlackHoleFlag(m_Params->get_int_param("blackhole"))
0051   , m_LightScintModelFlag(m_Params->get_int_param("light_scint_model"))
0052   , m_LightBalanceInnerCorr(m_Params->get_double_param("light_balance_inner_corr"))
0053   , m_LightBalanceInnerRadius(m_Params->get_double_param("light_balance_inner_radius") * cm)
0054   , m_LightBalanceOuterCorr(m_Params->get_double_param("light_balance_outer_corr"))
0055   , m_LightBalanceOuterRadius(m_Params->get_double_param("light_balance_outer_radius") * cm)
0056 {
0057 }
0058 
0059 PHG4Prototype2OuterHcalSteppingAction::~PHG4Prototype2OuterHcalSteppingAction()
0060 {
0061   // if the last hit was a zero energie deposit hit, it is just reset
0062   // and the memory is still allocated, so we need to delete it here
0063   // if the last hit was saved, hit is a nullptr pointer which are
0064   // legal to delete (it results in a no operation)
0065   delete m_Hit;
0066 }
0067 
0068 //____________________________________________________________________________..
0069 bool PHG4Prototype2OuterHcalSteppingAction::UserSteppingAction(const G4Step* aStep, bool)
0070 {
0071   G4TouchableHandle touch = aStep->GetPreStepPoint()->GetTouchableHandle();
0072   // get volume of the current step
0073   G4VPhysicalVolume* volume = touch->GetVolume();
0074 
0075   // m_Detector->IsInPrototype2OuterHcal(volume)
0076   // returns
0077   //  0 is outside of Prototype2OuterHcal
0078   //  1 is inside scintillator
0079   // -1 is steel absorber
0080 
0081   int whichactive = m_Detector->IsInPrototype2OuterHcal(volume);
0082 
0083   if (!whichactive)
0084   {
0085     return false;
0086   }
0087   int row_id = -1;
0088   int slat_id = -1;
0089   if (whichactive > 0)  // scintillator
0090   {
0091     G4VPhysicalVolume* mothervolume = touch->GetVolume(1);
0092     slat_id = volume->GetCopyNo();
0093     row_id = m_Detector->get_scinti_row_id(mothervolume->GetName());
0094      // cout << "mother volume: " <<  mothervolume->GetName()
0095      //      << ", volume name " << volume->GetName() << ", row: " << row_id
0096      //        << ", column: " << slat_id 
0097   }
0098   else
0099   {
0100     row_id = m_Detector->get_steel_plate_id(volume->GetName());  // steel plate id
0101   }
0102   // collect energy and track length step by step
0103   G4double edep = aStep->GetTotalEnergyDeposit() / GeV;
0104   G4double eion = (aStep->GetTotalEnergyDeposit() - aStep->GetNonIonizingEnergyDeposit()) / GeV;
0105   G4double light_yield = 0;
0106   const G4Track* aTrack = aStep->GetTrack();
0107 
0108   // if this block stops everything, just put all kinetic energy into edep
0109   if (m_IsBlackHoleFlag)
0110   {
0111     edep = aTrack->GetKineticEnergy() / GeV;
0112     G4Track* killtrack = const_cast<G4Track*>(aTrack);
0113     killtrack->SetTrackStatus(fStopAndKill);
0114   }
0115   int layer_id = m_Detector->get_Layer();
0116 
0117   // make sure we are in a volume
0118   if (m_IsActiveFlag)
0119   {
0120     bool geantino = false;
0121 
0122     // the check for the pdg code speeds things up, I do not want to make
0123     // an expensive string compare for every track when we know
0124     // geantino or chargedgeantino has pid=0
0125     if (aTrack->GetParticleDefinition()->GetPDGEncoding() == 0 &&
0126         aTrack->GetParticleDefinition()->GetParticleName().find("geantino") != string::npos)
0127     {
0128       geantino = true;
0129     }
0130     G4StepPoint* prePoint = aStep->GetPreStepPoint();
0131     G4StepPoint* postPoint = aStep->GetPostStepPoint();
0132     //       cout << "track id " << aTrack->GetTrackID() << endl;
0133     //       cout << "time prepoint: " << prePoint->GetGlobalTime() << endl;
0134     //       cout << "time postpoint: " << postPoint->GetGlobalTime() << endl;
0135     switch (prePoint->GetStepStatus())
0136     {
0137     case fGeomBoundary:
0138     case fUndefined:
0139       if (!m_Hit)
0140       {
0141         m_Hit = new PHG4Hitv1();
0142       }
0143       m_Hit->set_row(row_id);  // this is the row
0144       if (whichactive > 0)   // only for scintillators
0145       {
0146         m_Hit->set_scint_id(slat_id);  // the slat id in the mother volume (or steel plate id), the column
0147       }
0148       //here we set the entrance values in cm
0149       m_Hit->set_x(0, prePoint->GetPosition().x() / cm);
0150       m_Hit->set_y(0, prePoint->GetPosition().y() / cm);
0151       m_Hit->set_z(0, prePoint->GetPosition().z() / cm);
0152       // time in ns
0153       m_Hit->set_t(0, prePoint->GetGlobalTime() / nanosecond);
0154       //set the track ID
0155       m_Hit->set_trkid(aTrack->GetTrackID());
0156       if (G4VUserTrackInformation* p = aTrack->GetUserInformation())
0157       {
0158         if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
0159         {
0160           m_Hit->set_trkid(pp->GetUserTrackId());
0161           m_Hit->set_shower_id(pp->GetShower()->get_id());
0162         }
0163       }
0164 
0165       //set the initial energy deposit
0166       m_Hit->set_edep(0);
0167 
0168       m_Hit->set_hit_type(0);
0169       if ((aTrack->GetParticleDefinition()->GetParticleName().find("e+") != string::npos) ||
0170           (aTrack->GetParticleDefinition()->GetParticleName().find("e-") != string::npos))
0171         m_Hit->set_hit_type(1);
0172 
0173       // here we do things which are different between scintillator and absorber hits
0174       if (whichactive > 0)  // return of IsInPrototype2OuterHcalDetector, > 0 hit in scintillator, < 0 hit in absorber
0175       {
0176         m_SaveHitContainer = m_Hits;
0177         m_Hit->set_light_yield(0);  // for scintillator only, initialize light yields
0178         m_Hit->set_eion(0);
0179       }
0180       else
0181       {
0182         m_SaveHitContainer = m_AbsorberHits;
0183       }
0184       if (G4VUserTrackInformation* p = aTrack->GetUserInformation())
0185       {
0186         if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
0187         {
0188           m_Hit->set_trkid(pp->GetUserTrackId());
0189           m_Hit->set_shower_id(pp->GetShower()->get_id());
0190           m_SaveShower = pp->GetShower();
0191         }
0192       }
0193       break;
0194     default:
0195       break;
0196     }
0197     // here we just update the exit values, it will be overwritten
0198     // for every step until we leave the volume or the particle
0199     // ceases to exist
0200     m_Hit->set_x(1, postPoint->GetPosition().x() / cm);
0201     m_Hit->set_y(1, postPoint->GetPosition().y() / cm);
0202     m_Hit->set_z(1, postPoint->GetPosition().z() / cm);
0203 
0204     m_Hit->set_t(1, postPoint->GetGlobalTime() / nanosecond);
0205 
0206     if (whichactive > 0)  // return of IsInPrototype2OuterHcalDetector, > 0 hit in scintillator, < 0 hit in absorber
0207     {
0208       m_Hit->set_eion(m_Hit->get_eion() + eion);
0209       light_yield = eion;
0210       if (m_LightScintModelFlag)
0211       {
0212         light_yield = GetVisibleEnergyDeposition(aStep);  // for scintillator only, calculate light yields
0213       }
0214       if (isfinite(m_LightBalanceOuterRadius) &&
0215           isfinite(m_LightBalanceInnerRadius) &&
0216           isfinite(m_LightBalanceOuterCorr) &&
0217           isfinite(m_LightBalanceInnerCorr))
0218       {
0219         double r = sqrt(postPoint->GetPosition().x() * postPoint->GetPosition().x() + postPoint->GetPosition().y() * postPoint->GetPosition().y());
0220         double cor = GetLightCorrection(r);
0221         light_yield = light_yield * cor;
0222       }
0223       m_Hit->set_light_yield(m_Hit->get_light_yield() + light_yield);
0224     }
0225 
0226     //sum up the energy to get total deposited
0227     m_Hit->set_edep(m_Hit->get_edep() + edep);
0228     if (geantino)
0229     {
0230       m_Hit->set_edep(-1);  // only energy=0 g4hits get dropped, this way geantinos survive the g4hit compression
0231       if (whichactive > 0)
0232       {
0233         m_Hit->set_light_yield(-1);
0234         m_Hit->set_eion(-1);
0235       }
0236     }
0237     if (edep > 0 && (whichactive > 0 || m_AbsorberTruthFlag > 0))
0238     {
0239       if (G4VUserTrackInformation* p = aTrack->GetUserInformation())
0240       {
0241         if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
0242         {
0243           pp->SetKeep(1);  // we want to keep the track
0244         }
0245       }
0246     }
0247 
0248     // if any of these conditions is true this is the last step in
0249     // this volume and we need to save the hit
0250     // postPoint->GetStepStatus() == fGeomBoundary: track leaves this volume
0251     // postPoint->GetStepStatus() == fWorldBoundary: track leaves this world
0252     // (happens when your detector goes outside world volume)
0253     // postPoint->GetStepStatus() == fAtRestDoItProc: track stops (typically
0254     // aTrack->GetTrackStatus() == fStopAndKill is also set)
0255     // aTrack->GetTrackStatus() == fStopAndKill: track ends
0256     if (postPoint->GetStepStatus() == fGeomBoundary ||
0257         postPoint->GetStepStatus() == fWorldBoundary ||
0258         postPoint->GetStepStatus() == fAtRestDoItProc ||
0259         aTrack->GetTrackStatus() == fStopAndKill)
0260     {
0261       // save only hits with energy deposit (or -1 for geantino)
0262       if (m_Hit->get_edep())
0263       {
0264         m_SaveHitContainer->AddHit(layer_id, m_Hit);
0265         if (m_SaveShower)
0266         {
0267           m_SaveShower->add_g4hit_id(m_SaveHitContainer->GetID(), m_Hit->get_hit_id());
0268         }
0269         // ownership has been transferred to container, set to null
0270         // so we will create a new hit for the next track
0271         m_Hit = nullptr;
0272       }
0273       else
0274       {
0275         // if this hit has no energy deposit, just reset it for reuse
0276         // this means we have to delete it in the dtor. If this was
0277         // the last hit we processed the memory is still allocated
0278         m_Hit->Reset();
0279       }
0280     }
0281     //       m_Hit->identify();
0282     // return true to indicate the hit was used
0283     return true;
0284   }
0285   else
0286   {
0287     return false;
0288   }
0289 }
0290 
0291 //____________________________________________________________________________..
0292 void PHG4Prototype2OuterHcalSteppingAction::SetInterfacePointers(PHCompositeNode* topNode)
0293 {
0294   string hitnodename;
0295   string absorbernodename;
0296   if (m_Detector->SuperDetector() != "NONE")
0297   {
0298     hitnodename = "G4HIT_" + m_Detector->SuperDetector();
0299     absorbernodename = "G4HIT_ABSORBER_" + m_Detector->SuperDetector();
0300   }
0301   else
0302   {
0303     hitnodename = "G4HIT_" + m_Detector->GetName();
0304     absorbernodename = "G4HIT_ABSORBER_" + m_Detector->GetName();
0305   }
0306 
0307   //now look for the map and grab a pointer to it.
0308   m_Hits = findNode::getClass<PHG4HitContainer>(topNode, hitnodename.c_str());
0309   m_AbsorberHits = findNode::getClass<PHG4HitContainer>(topNode, absorbernodename.c_str());
0310 
0311   // if we do not find the node it's messed up.
0312   if (!m_Hits)
0313   {
0314     std::cout << "PHG4Prototype2OuterHcalSteppingAction::SetTopNode - unable to find " << hitnodename << std::endl;
0315   }
0316   if (!m_AbsorberHits)
0317   {
0318     if (Verbosity() > 1)
0319     {
0320       cout << "PHG4HcalSteppingAction::SetTopNode - unable to find " << absorbernodename << endl;
0321     }
0322   }
0323 }
0324 
0325 double
0326 PHG4Prototype2OuterHcalSteppingAction::GetLightCorrection(const double r) const
0327 {
0328   double m = (m_LightBalanceOuterCorr - m_LightBalanceInnerCorr) / (m_LightBalanceOuterRadius - m_LightBalanceInnerRadius);
0329   double b = m_LightBalanceInnerCorr - m * m_LightBalanceInnerRadius;
0330   double value = m * r + b;
0331   if (value > 1.0) return 1.0;
0332   if (value < 0.0) return 0.0;
0333 
0334   return value;
0335 }