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