File indexing completed on 2025-08-05 08:17:49
0001 #include "PHG4InnerHcalSteppingAction.h"
0002
0003 #include "PHG4InnerHcalDetector.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 <ffamodules/CDBInterface.h>
0016
0017 #include <fun4all/Fun4AllReturnCodes.h>
0018
0019 #include <calobase/TowerInfo.h>
0020 #include <calobase/TowerInfoContainer.h>
0021 #include <calobase/TowerInfoContainerv1.h>
0022 #include <calobase/TowerInfoDefs.h>
0023
0024 #include <phool/PHCompositeNode.h>
0025 #include <phool/PHIODataNode.h> // for PHIODataNode
0026 #include <phool/PHNode.h> // for PHNode
0027 #include <phool/PHNodeIterator.h> // for PHNodeIterator
0028 #include <phool/PHObject.h> // for PHObject
0029 #include <phool/getClass.h>
0030
0031 #include <TSystem.h>
0032
0033
0034 #include <TFile.h>
0035 #include <TH2.h>
0036 #include <TSystem.h>
0037
0038 #include <Geant4/G4ParticleDefinition.hh> // for G4ParticleDefinition
0039 #include <Geant4/G4ReferenceCountedHandle.hh> // for G4ReferenceCountedHandle
0040 #include <Geant4/G4Step.hh>
0041 #include <Geant4/G4StepPoint.hh> // for G4StepPoint
0042 #include <Geant4/G4StepStatus.hh> // for fGeomBoundary, fAtRest...
0043 #include <Geant4/G4String.hh> // for G4String
0044 #include <Geant4/G4SystemOfUnits.hh>
0045 #include <Geant4/G4ThreeVector.hh> // for G4ThreeVector
0046 #include <Geant4/G4TouchableHandle.hh> // for G4TouchableHandle
0047 #include <Geant4/G4Track.hh> // for G4Track
0048 #include <Geant4/G4TrackStatus.hh> // for fStopAndKill
0049 #include <Geant4/G4TransportationManager.hh>
0050 #include <Geant4/G4Types.hh> // for G4double
0051 #include <Geant4/G4VPhysicalVolume.hh> // for G4VPhysicalVolume
0052 #include <Geant4/G4VTouchable.hh> // for G4VTouchable
0053 #include <Geant4/G4VUserTrackInformation.hh> // for G4VUserTrackInformation
0054
0055 #include <cmath> // for isfinite
0056 #include <cstdlib>
0057 #include <filesystem>
0058 #include <iostream>
0059 #include <string> // for operator<<, operator+
0060 #include <utility> // for pair
0061
0062 class PHCompositeNode;
0063
0064
0065 PHG4InnerHcalSteppingAction::PHG4InnerHcalSteppingAction(PHG4InnerHcalDetector* detector, const PHParameters* parameters)
0066 : PHG4SteppingAction(detector->GetName())
0067 , m_Detector(detector)
0068 , m_Params(parameters)
0069 , m_IsActive(m_Params->get_int_param("active"))
0070 , m_IsBlackHole(m_Params->get_int_param("blackhole"))
0071 , m_LightScintModelFlag(m_Params->get_int_param("light_scint_model"))
0072 , m_doG4Hit(m_Params->get_int_param("saveg4hit"))
0073 , m_tmin(m_Params->get_double_param("tmin"))
0074 , m_tmax(m_Params->get_double_param("tmax"))
0075 , m_dt(m_Params->get_double_param("dt"))
0076 {
0077 SetLightCorrection(m_Params->get_double_param("light_balance_inner_radius") * cm,
0078 m_Params->get_double_param("light_balance_inner_corr"),
0079 m_Params->get_double_param("light_balance_outer_radius") * cm,
0080 m_Params->get_double_param("light_balance_outer_corr"));
0081 }
0082
0083 PHG4InnerHcalSteppingAction::~PHG4InnerHcalSteppingAction()
0084 {
0085
0086
0087
0088
0089 delete m_Hit;
0090
0091 delete m_MapCorrHist;
0092 }
0093
0094
0095 int PHG4InnerHcalSteppingAction::InitWithNode(PHCompositeNode* topNode)
0096 {
0097 if (m_LightScintModelFlag)
0098 {
0099 std::string ihcalmapname(m_Params->get_string_param("MapFileName"));
0100 if (ihcalmapname.empty())
0101 {
0102 return 0;
0103 }
0104 std::string url = CDBInterface::instance()->getUrl("OLD_INNER_HCAL_TILEMAP", ihcalmapname);
0105 if (!std::filesystem::exists(url))
0106 {
0107 std::cout << PHWHERE << " Could not locate " << url << std::endl;
0108 std::cout << "use empty filename to ignore mapfile" << std::endl;
0109 gSystem->Exit(1);
0110 }
0111 TFile* file = TFile::Open(url.c_str());
0112 file->GetObject(m_Params->get_string_param("MapHistoName").c_str(), m_MapCorrHist);
0113 if (!m_MapCorrHist)
0114 {
0115 std::cout << "ERROR: could not find Histogram " << m_Params->get_string_param("MapHistoName") << " in " << m_Params->get_string_param("MapFileName") << std::endl;
0116 gSystem->Exit(1);
0117 exit(1);
0118 }
0119 m_MapCorrHist->SetDirectory(nullptr);
0120 file->Close();
0121 delete file;
0122 }
0123 if (!m_doG4Hit)
0124 {
0125 try
0126 {
0127 CreateNodeTree(topNode);
0128 }
0129 catch (std::exception& e)
0130 {
0131 std::cout << e.what() << std::endl;
0132 return Fun4AllReturnCodes::ABORTRUN;
0133 }
0134 if (Verbosity() > 1)
0135 {
0136 topNode->print();
0137 }
0138 }
0139
0140 return 0;
0141 }
0142
0143
0144 bool PHG4InnerHcalSteppingAction::NoHitSteppingAction(const G4Step* aStep)
0145 {
0146 G4TouchableHandle touch = aStep->GetPreStepPoint()->GetTouchableHandle();
0147 G4TouchableHandle touchpost = aStep->GetPostStepPoint()->GetTouchableHandle();
0148
0149 G4VPhysicalVolume* volume = touch->GetVolume();
0150
0151
0152
0153
0154
0155
0156
0157 int whichactive = m_Detector->IsInInnerHcal(volume);
0158
0159 if (!whichactive)
0160 {
0161 return false;
0162 }
0163 int layer_id = -1;
0164 int tower_id = -1;
0165 if (whichactive > 0)
0166 {
0167 std::pair<int, int> layer_tower = m_Detector->GetLayerTowerId(volume);
0168 layer_id = layer_tower.first;
0169 tower_id = layer_tower.second;
0170
0171
0172 }
0173 else
0174 {
0175
0176 return false;
0177 }
0178
0179 if (!m_IsActive)
0180 {
0181 return false;
0182 }
0183
0184 G4StepPoint* prePoint = aStep->GetPreStepPoint();
0185 G4StepPoint* postPoint = aStep->GetPostStepPoint();
0186
0187 double pretime = prePoint->GetGlobalTime() / nanosecond;
0188 double posttime = postPoint->GetGlobalTime() / nanosecond;
0189 if (posttime < m_tmin || pretime > m_tmax)
0190 {
0191 return false;
0192 }
0193 if ((posttime - pretime) > m_dt)
0194 {
0195 return false;
0196 }
0197 G4double eion = (aStep->GetTotalEnergyDeposit() - aStep->GetNonIonizingEnergyDeposit()) / GeV;
0198 const G4Track* aTrack = aStep->GetTrack();
0199
0200 double light_yield = eion;
0201
0202
0203 if (m_LightScintModelFlag)
0204 {
0205 light_yield = GetVisibleEnergyDeposition(aStep);
0206 if (m_MapCorrHist)
0207 {
0208 const G4TouchableHandle& theTouchable = prePoint->GetTouchableHandle();
0209 const G4ThreeVector& worldPosition = postPoint->GetPosition();
0210 G4ThreeVector localPosition = theTouchable->GetHistory()->GetTopTransform().TransformPoint(worldPosition);
0211 float lx = (localPosition.x() / cm);
0212 float lz = fabs(localPosition.z() / cm);
0213
0214 int lcz = (int) (5.0 * lz) + 1;
0215 int lcx = (int) (5.0 * (lx + 12.1)) + 1;
0216
0217 if ((lcx >= 1) && (lcx <= m_MapCorrHist->GetNbinsY()) &&
0218 (lcz >= 1) && (lcz <= m_MapCorrHist->GetNbinsX()))
0219 {
0220 light_yield *= (double) (m_MapCorrHist->GetBinContent(lcz, lcx));
0221 }
0222 else
0223 {
0224 light_yield = 0.0;
0225 }
0226 }
0227 else
0228 {
0229
0230 light_yield = light_yield * GetLightCorrection(postPoint->GetPosition().x(), postPoint->GetPosition().y());
0231 }
0232 }
0233
0234 unsigned int ieta = tower_id;
0235 unsigned int iphi = (unsigned int) layer_id / 4;
0236 unsigned int tower_key = TowerInfoDefs::encode_hcal(ieta, iphi);
0237 m_CaloInfoContainer->get_tower_at_key(tower_key)->set_energy(m_CaloInfoContainer->get_tower_at_key(tower_key)->get_energy() + light_yield);
0238
0239 if (light_yield > 0)
0240 {
0241 if (G4VUserTrackInformation* p = aTrack->GetUserInformation())
0242 {
0243 if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
0244 {
0245 pp->SetKeep(1);
0246 }
0247 }
0248 }
0249
0250 return true;
0251 }
0252
0253
0254 bool PHG4InnerHcalSteppingAction::UserSteppingAction(const G4Step* aStep, bool )
0255 {
0256 if ((!m_doG4Hit) && (!m_IsBlackHole))
0257 {
0258 return NoHitSteppingAction(aStep);
0259 }
0260 G4TouchableHandle touch = aStep->GetPreStepPoint()->GetTouchableHandle();
0261 G4TouchableHandle touchpost = aStep->GetPostStepPoint()->GetTouchableHandle();
0262
0263 G4VPhysicalVolume* volume = touch->GetVolume();
0264
0265
0266
0267
0268
0269
0270
0271 int whichactive = m_Detector->IsInInnerHcal(volume);
0272
0273 if (!whichactive)
0274 {
0275 return false;
0276 }
0277 int layer_id = -1;
0278 int tower_id = -1;
0279 if (whichactive > 0)
0280 {
0281 std::pair<int, int> layer_tower = m_Detector->GetLayerTowerId(volume);
0282 layer_id = layer_tower.first;
0283 tower_id = layer_tower.second;
0284
0285
0286 }
0287 else
0288 {
0289 layer_id = touch->GetCopyNumber();
0290 }
0291
0292 G4double edep = aStep->GetTotalEnergyDeposit() / GeV;
0293 G4double eion = (aStep->GetTotalEnergyDeposit() - aStep->GetNonIonizingEnergyDeposit()) / GeV;
0294 G4double light_yield = 0;
0295 const G4Track* aTrack = aStep->GetTrack();
0296
0297
0298 if (m_IsBlackHole)
0299 {
0300 edep = aTrack->GetKineticEnergy() / GeV;
0301 G4Track* killtrack = const_cast<G4Track*>(aTrack);
0302 killtrack->SetTrackStatus(fStopAndKill);
0303 }
0304
0305
0306 if (m_IsActive)
0307 {
0308 bool geantino = false;
0309
0310
0311
0312
0313 if (aTrack->GetParticleDefinition()->GetPDGEncoding() == 0 &&
0314 aTrack->GetParticleDefinition()->GetParticleName().find("geantino") != std::string::npos)
0315 {
0316 geantino = true;
0317 }
0318 G4StepPoint* prePoint = aStep->GetPreStepPoint();
0319 G4StepPoint* postPoint = aStep->GetPostStepPoint();
0320
0321
0322
0323 switch (prePoint->GetStepStatus())
0324 {
0325 case fPostStepDoItProc:
0326 if (m_SavePostStepStatus != fGeomBoundary)
0327 {
0328 break;
0329 }
0330 else
0331 {
0332 std::cout << GetName() << ": New Hit for " << std::endl;
0333 std::cout << "prestep status: " << PHG4StepStatusDecode::GetStepStatus(prePoint->GetStepStatus())
0334 << ", poststep status: " << PHG4StepStatusDecode::GetStepStatus(postPoint->GetStepStatus())
0335 << ", last pre step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePreStepStatus)
0336 << ", last post step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePostStepStatus) << std::endl;
0337 std::cout << "last track: " << m_SaveTrackId
0338 << ", current trackid: " << aTrack->GetTrackID() << std::endl;
0339 std::cout << "phys pre vol: " << volume->GetName()
0340 << " post vol : " << touchpost->GetVolume()->GetName() << std::endl;
0341 std::cout << " previous phys pre vol: " << m_SaveVolPre->GetName()
0342 << " previous phys post vol: " << m_SaveVolPost->GetName() << std::endl;
0343 }
0344 [[fallthrough]];
0345 case fGeomBoundary:
0346 case fUndefined:
0347
0348
0349 if (!m_Hit)
0350 {
0351 m_Hit = new PHG4Hitv1();
0352 }
0353
0354 m_Hit->set_x(0, prePoint->GetPosition().x() / cm);
0355 m_Hit->set_y(0, prePoint->GetPosition().y() / cm);
0356 m_Hit->set_z(0, prePoint->GetPosition().z() / cm);
0357
0358 m_Hit->set_t(0, prePoint->GetGlobalTime() / nanosecond);
0359
0360 m_Hit->set_trkid(aTrack->GetTrackID());
0361 m_SaveTrackId = aTrack->GetTrackID();
0362
0363 m_Hit->set_edep(0);
0364 if (whichactive > 0)
0365 {
0366 m_Hit->set_scint_id(tower_id);
0367 m_Hit->set_eion(0);
0368 m_Hit->set_raw_light_yield(0);
0369 m_Hit->set_light_yield(0);
0370
0371 m_SaveHitContainer = m_Hits;
0372 }
0373 else
0374 {
0375 m_SaveHitContainer = m_AbsorberHits;
0376 }
0377 if (G4VUserTrackInformation* p = aTrack->GetUserInformation())
0378 {
0379 if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
0380 {
0381 m_Hit->set_trkid(pp->GetUserTrackId());
0382 m_Hit->set_shower_id(pp->GetShower()->get_id());
0383 m_SaveShower = pp->GetShower();
0384 }
0385 }
0386 break;
0387 default:
0388 break;
0389 }
0390
0391
0392 if (!m_Hit || !isfinite(m_Hit->get_x(0)))
0393 {
0394 std::cout << GetName() << ": hit was not created" << std::endl;
0395 std::cout << "prestep status: " << PHG4StepStatusDecode::GetStepStatus(prePoint->GetStepStatus())
0396 << ", poststep status: " << PHG4StepStatusDecode::GetStepStatus(postPoint->GetStepStatus())
0397 << ", last pre step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePreStepStatus)
0398 << ", last post step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePostStepStatus) << std::endl;
0399 std::cout << "last track: " << m_SaveTrackId
0400 << ", current trackid: " << aTrack->GetTrackID() << std::endl;
0401 std::cout << "phys pre vol: " << volume->GetName()
0402 << " post vol : " << touchpost->GetVolume()->GetName() << std::endl;
0403 std::cout << " previous phys pre vol: " << m_SaveVolPre->GetName()
0404 << " previous phys post vol: " << m_SaveVolPost->GetName() << std::endl;
0405 gSystem->Exit(1);
0406 }
0407
0408 if (aTrack->GetTrackID() != m_SaveTrackId)
0409 {
0410 std::cout << GetName() << ": hits do not belong to the same track" << std::endl;
0411 std::cout << "saved track: " << m_SaveTrackId
0412 << ", current trackid: " << aTrack->GetTrackID()
0413 << ", prestep status: " << prePoint->GetStepStatus()
0414 << ", previous post step status: " << m_SavePostStepStatus
0415 << std::endl;
0416
0417 gSystem->Exit(1);
0418 }
0419 m_SavePreStepStatus = prePoint->GetStepStatus();
0420 m_SavePostStepStatus = postPoint->GetStepStatus();
0421 m_SaveVolPre = volume;
0422 m_SaveVolPost = touchpost->GetVolume();
0423
0424
0425
0426 m_Hit->set_x(1, postPoint->GetPosition().x() / cm);
0427 m_Hit->set_y(1, postPoint->GetPosition().y() / cm);
0428 m_Hit->set_z(1, postPoint->GetPosition().z() / cm);
0429
0430 m_Hit->set_t(1, postPoint->GetGlobalTime() / nanosecond);
0431
0432
0433 m_Hit->set_edep(m_Hit->get_edep() + edep);
0434 if (whichactive > 0)
0435 {
0436 m_Hit->set_eion(m_Hit->get_eion() + eion);
0437 light_yield = eion;
0438 if (m_LightScintModelFlag)
0439 {
0440 light_yield = GetVisibleEnergyDeposition(aStep);
0441 m_Hit->set_raw_light_yield(m_Hit->get_raw_light_yield() + light_yield);
0442 if (m_MapCorrHist)
0443 {
0444 const G4TouchableHandle& theTouchable = prePoint->GetTouchableHandle();
0445 const G4ThreeVector& worldPosition = postPoint->GetPosition();
0446 G4ThreeVector localPosition = theTouchable->GetHistory()->GetTopTransform().TransformPoint(worldPosition);
0447 float lx = (localPosition.x() / cm);
0448 float lz = fabs(localPosition.z() / cm);
0449
0450 int lcz = (int) (5.0 * lz) + 1;
0451 int lcx = (int) (5.0 * (lx + 12.1)) + 1;
0452
0453 if ((lcx >= 1) && (lcx <= m_MapCorrHist->GetNbinsY()) &&
0454 (lcz >= 1) && (lcz <= m_MapCorrHist->GetNbinsX()))
0455 {
0456 light_yield *= (double) (m_MapCorrHist->GetBinContent(lcz, lcx));
0457 }
0458 else
0459 {
0460 light_yield = 0.0;
0461 }
0462 }
0463 else
0464 {
0465
0466 light_yield = light_yield * GetLightCorrection(postPoint->GetPosition().x(), postPoint->GetPosition().y());
0467 }
0468 }
0469 m_Hit->set_light_yield(m_Hit->get_light_yield() + light_yield);
0470 }
0471 if (geantino)
0472 {
0473 m_Hit->set_edep(-1);
0474 m_Hit->set_eion(-1);
0475 }
0476 if (edep > 0)
0477 {
0478 if (G4VUserTrackInformation* p = aTrack->GetUserInformation())
0479 {
0480 if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
0481 {
0482 pp->SetKeep(1);
0483 }
0484 }
0485 }
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495 if (postPoint->GetStepStatus() == fGeomBoundary ||
0496 postPoint->GetStepStatus() == fWorldBoundary ||
0497 postPoint->GetStepStatus() == fAtRestDoItProc ||
0498 aTrack->GetTrackStatus() == fStopAndKill)
0499 {
0500
0501 if (m_Hit->get_edep() != 0)
0502 {
0503 m_SaveHitContainer->AddHit(layer_id, m_Hit);
0504
0505 if (m_SaveShower)
0506 {
0507 m_SaveShower->add_g4hit_id(m_SaveHitContainer->GetID(), m_Hit->get_hit_id());
0508 }
0509
0510
0511 m_Hit = nullptr;
0512 }
0513 else
0514 {
0515
0516
0517
0518 m_Hit->Reset();
0519 }
0520 }
0521
0522 return true;
0523 }
0524 else
0525 {
0526 return false;
0527 }
0528 }
0529
0530
0531 void PHG4InnerHcalSteppingAction::SetInterfacePointers(PHCompositeNode* topNode)
0532 {
0533 std::string hitnodename;
0534 std::string absorbernodename;
0535 if (m_Detector->SuperDetector() != "NONE")
0536 {
0537 hitnodename = "G4HIT_" + m_Detector->SuperDetector();
0538 absorbernodename = "G4HIT_ABSORBER_" + m_Detector->SuperDetector();
0539 }
0540 else
0541 {
0542 hitnodename = "G4HIT_" + m_Detector->GetName();
0543 absorbernodename = "G4HIT_ABSORBER_" + m_Detector->GetName();
0544 }
0545
0546
0547 m_Hits = findNode::getClass<PHG4HitContainer>(topNode, hitnodename);
0548 m_AbsorberHits = findNode::getClass<PHG4HitContainer>(topNode, absorbernodename);
0549
0550
0551 if (!m_Hits)
0552 {
0553 std::cout << "PHG4InnerHcalSteppingAction::SetTopNode - unable to find " << hitnodename << std::endl;
0554 }
0555 if (!m_AbsorberHits)
0556 {
0557 if (Verbosity() > 1)
0558 {
0559 std::cout << "PHG4HcalSteppingAction::SetTopNode - unable to find " << absorbernodename << std::endl;
0560 }
0561 }
0562 }
0563
0564 void PHG4InnerHcalSteppingAction::CreateNodeTree(PHCompositeNode* topNode)
0565 {
0566 PHNodeIterator nodeItr(topNode);
0567 PHCompositeNode* dst_node = dynamic_cast<PHCompositeNode*>(
0568 nodeItr.findFirst("PHCompositeNode", "DST"));
0569 if (!dst_node)
0570 {
0571 std::cout << "PHComposite node created: DST" << std::endl;
0572 dst_node = new PHCompositeNode("DST");
0573 topNode->addNode(dst_node);
0574 }
0575 PHNodeIterator dstiter(dst_node);
0576 PHCompositeNode* DetNode = dynamic_cast<PHCompositeNode*>(dstiter.findFirst("PHCompositeNode", m_Detector->SuperDetector()));
0577 if (!DetNode)
0578 {
0579 DetNode = new PHCompositeNode(m_Detector->SuperDetector());
0580 dst_node->addNode(DetNode);
0581 }
0582 m_CaloInfoContainer = new TowerInfoContainerv1(TowerInfoContainer::DETECTOR::HCAL);
0583 PHIODataNode<PHObject>* towerNode = new PHIODataNode<PHObject>(m_CaloInfoContainer, "TOWERINFO_SIM_" + m_Detector->SuperDetector(), "PHObject");
0584 DetNode->addNode(towerNode);
0585 }