Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHG4InttSteppingAction.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHG4InttSteppingAction.cc
2 #include "PHG4InttDefs.h"
3 #include "PHG4InttDetector.h"
4 
5 #include <phparameter/PHParameters.h>
6 #include <phparameter/PHParametersContainer.h>
7 
8 #include <g4main/PHG4Hit.h>
10 #include <g4main/PHG4Hitv1.h>
11 #include <g4main/PHG4Shower.h>
12 #include <g4main/PHG4SteppingAction.h> // for PHG4SteppingAction
14 
15 #include <phool/getClass.h>
16 
17 #include <TSystem.h>
18 
19 #include <Geant4/G4ParticleDefinition.hh> // for G4ParticleDefinition
20 #include <Geant4/G4ReferenceCountedHandle.hh> // for G4ReferenceCountedHandle
21 #include <Geant4/G4Step.hh>
22 #include <Geant4/G4StepPoint.hh> // for G4StepPoint
23 #include <Geant4/G4StepStatus.hh> // for fGeomBoundary, fAtRes...
24 #include <Geant4/G4String.hh> // for G4String
25 #include <Geant4/G4SystemOfUnits.hh>
26 #include <Geant4/G4ThreeVector.hh>
27 #include <Geant4/G4TouchableHandle.hh>
28 #include <Geant4/G4Track.hh> // for G4Track
29 #include <Geant4/G4TrackStatus.hh> // for fStopAndKill
30 #include <Geant4/G4Types.hh> // for G4double
31 #include <Geant4/G4VPhysicalVolume.hh> // for G4VPhysicalVolume
32 #include <Geant4/G4VTouchable.hh> // for G4VTouchable
33 #include <Geant4/G4VUserTrackInformation.hh> // for G4VUserTrackInformation
34 
35 #include <cassert> // for assert
36 #include <iostream>
37 #include <set> // for set
38 #include <string> // for operator<<, string
39 #include <tuple> // for tie, tuple
40 
41 class PHCompositeNode;
42 
43 //____________________________________________________________________________..
44 PHG4InttSteppingAction::PHG4InttSteppingAction(PHG4InttDetector* detector, const PHParametersContainer* parameters, const std::pair<std::vector<std::pair<int, int>>::const_iterator, std::vector<std::pair<int, int>>::const_iterator>& layer_begin_end)
45  : PHG4SteppingAction(detector->GetName())
46  , m_Detector(detector)
47  , m_ParamsContainer(parameters)
48 {
49  // loop over layers to get laddertype nd active status for each layer
50  for (auto layeriter = layer_begin_end.first; layeriter != layer_begin_end.second; ++layeriter)
51  {
52  int layer = layeriter->second;
53  const PHParameters* par = m_ParamsContainer->GetParameters(layer);
54  m_IsActiveMap[layer] = par->get_int_param("active");
55  m_IsBlackHoleMap[layer] = par->get_int_param("blackhole");
56  m_LadderTypeMap.insert(std::make_pair(layer, par->get_int_param("laddertype")));
57  m_InttToTrackerLayerMap.insert(std::make_pair(layeriter->second, layeriter->first));
58  }
59 
60  // Get the parameters for each laddertype
62  {
63  const PHParameters* par = m_ParamsContainer->GetParameters(*iter);
64  m_StripYMap.insert(std::make_pair(*iter, par->get_double_param("strip_y") * cm));
65  m_StripZMap.insert(std::make_pair(*iter, std::make_pair(par->get_double_param("strip_z_0") * cm, par->get_double_param("strip_z_1") * cm)));
66  m_nStripsPhiCell.insert(std::make_pair(*iter, par->get_int_param("nstrips_phi_cell")));
67  m_nStripsZSensor.insert(std::make_pair(*iter, std::make_pair(par->get_int_param("nstrips_z_sensor_0"), par->get_int_param("nstrips_z_sensor_1"))));
68  }
69 }
70 
72 {
73  // if the last hit was a zero energie deposit hit, it is just reset
74  // and the memory is still allocated, so we need to delete it here
75  // if the last hit was saved, hit is a nullptr pointer which are
76  // legal to delete (it results in a no operation)
77  delete m_Hit;
78 }
79 
80 //____________________________________________________________________________..
81 bool PHG4InttSteppingAction::UserSteppingAction(const G4Step* aStep, bool)
82 {
83  G4TouchableHandle touch = aStep->GetPreStepPoint()->GetTouchableHandle();
84  // get volume of the current step
85  G4VPhysicalVolume* volume = touch->GetVolume();
86  const G4Track* aTrack = aStep->GetTrack();
87  G4StepPoint* prePoint = aStep->GetPreStepPoint();
88  G4StepPoint* postPoint = aStep->GetPostStepPoint();
89 
90  const int whichactive = m_Detector->IsInIntt(volume);
91 
92  if (!whichactive)
93  {
94  return false;
95  }
96 
97  if (Verbosity() > 0)
98  {
99  std::cout << std::endl
100  << "PHG4SilicoTrackerSteppingAction::UserSteppingAction for volume name (pre) " << touch->GetVolume()->GetName()
101  << " volume name (1) " << touch->GetVolume(1)->GetName()
102  << " volume->GetTranslation " << touch->GetVolume()->GetTranslation()
103  << std::endl;
104  }
105 
106  // set ladder index
107  int sphxlayer = 0;
108  int inttlayer = 0;
109  int ladderz = 0;
110  int ladderphi = 0;
111  int zposneg = 0;
112 
113  if (whichactive > 0) // silicon active sensor
114  {
115  // Get the layer and ladder information which is step up in the volume hierarchy
116  // the ladder also contains inactive volumes but we check in m_Detector->IsInIntt(volume)
117  // if we are in an active logical volume whioch is located in this ladder
118  auto iter = m_Detector->get_ActiveVolumeTuple(touch->GetVolume(1));
119  std::tie(inttlayer, ladderz, ladderphi, zposneg) = iter->second;
120  if (Verbosity() > 0)
121  {
122  std::cout << " inttlayer " << inttlayer << " ladderz_base " << ladderz << " ladderphi " << ladderphi << " zposneg " << zposneg << std::endl;
123  }
124  if (inttlayer < 0 || inttlayer > 7)
125  {
126  assert(!"PHG4InttSteppingAction: check Intt ladder layer.");
127  }
128  sphxlayer = m_InttToTrackerLayerMap.find(inttlayer)->second;
129  std::map<int, int>::const_iterator activeiter = m_IsActiveMap.find(inttlayer);
130  if (activeiter == m_IsActiveMap.end())
131  {
132  std::cout << "PHG4InttSteppingAction: could not find active flag for layer " << inttlayer << std::endl;
133  gSystem->Exit(1);
134  }
135  if (activeiter->second == 0)
136  {
137  return false;
138  }
139  }
140  else // whichactive < 0, silicon inactive area, FPHX, stabe etc. as absorbers
141  {
142  auto iter = m_Detector->get_PassiveVolumeTuple(touch->GetVolume(0)->GetLogicalVolume());
143  std::tie(inttlayer, ladderz) = iter->second;
144  sphxlayer = inttlayer; //for absorber we use the Intt layer, not the tracking layer in sPHENIX
145  } // end of si inactive area block
146 
147  // collect energy and track length step by step
148  G4double edep = aStep->GetTotalEnergyDeposit() / GeV;
149  G4double eion = (aStep->GetTotalEnergyDeposit() - aStep->GetNonIonizingEnergyDeposit()) / GeV;
150 
151  // if this block stops everything, just put all kinetic energy into edep
152  if ((m_IsBlackHoleMap.find(inttlayer))->second == 1)
153  {
154  edep = aTrack->GetKineticEnergy() / GeV;
155  G4Track* killtrack = const_cast<G4Track*>(aTrack);
156  killtrack->SetTrackStatus(fStopAndKill);
157  }
158 
159  bool geantino = false;
160 
161  // the check for the pdg code speeds things up, I do not want to make
162  // an expensive string compare for every track when we know
163  // geantino or chargedgeantino has pid=0
164  if (aTrack->GetParticleDefinition()->GetPDGEncoding() == 0 && aTrack->GetParticleDefinition()->GetParticleName().find("geantino") != std::string::npos)
165  {
166  geantino = true;
167  }
168 
169  if (Verbosity() > 1)
170  {
171  std::cout << " aTrack->GetTrackID " << aTrack->GetTrackID() << " aTrack->GetParentID " << aTrack->GetParentID()
172  << " Intt layer " << inttlayer
173  << " prePoint step status = " << prePoint->GetStepStatus() << " postPoint step status = " << postPoint->GetStepStatus()
174  << std::endl;
175  }
176  switch (prePoint->GetStepStatus())
177  {
178  case fGeomBoundary:
179  case fUndefined:
180 
181  if (Verbosity() > 1)
182  {
183  std::cout << " start new g4hit for: aTrack->GetParentID " << aTrack->GetParentID() << " aTrack->GetTrackID " << aTrack->GetTrackID() << " Intt layer " << inttlayer
184  << " prePoint step status = " << prePoint->GetStepStatus() << " postPoint->GetStepStatus = " << postPoint->GetStepStatus() << std::endl;
185  }
186  // if previous hit was saved, hit pointer was set to nullptr
187  // and we have to make a new one
188  if (!m_Hit)
189  {
190  m_Hit = new PHG4Hitv1();
191  }
192 
193  // set the index values needed to locate the sensor strip
194  if (zposneg == 1)
195  {
196  ladderz += 2; // ladderz = 0, 1 for negative z and = 2, 3 for positive z
197  }
198  if (Verbosity() > 0) std::cout << " ladderz = " << ladderz << std::endl;
199 
200  m_Hit->set_ladder_z_index(ladderz);
201 
202  if (whichactive > 0)
203  {
204  m_Hit->set_layer(sphxlayer);
205  m_Hit->set_ladder_phi_index(ladderphi);
206  m_Hit->set_px(0, prePoint->GetMomentum().x() / GeV);
207  m_Hit->set_py(0, prePoint->GetMomentum().y() / GeV);
208  m_Hit->set_pz(0, prePoint->GetMomentum().z() / GeV);
209  m_Hit->set_eion(0);
210  }
211 
212  //here we set the entrance values in cm
213  m_Hit->set_x(0, prePoint->GetPosition().x() / cm);
214  m_Hit->set_y(0, prePoint->GetPosition().y() / cm);
215  m_Hit->set_z(0, prePoint->GetPosition().z() / cm);
216 
217  StoreLocalCoordinate(m_Hit, aStep, true, false);
218 
219  if (Verbosity() > 0)
220  {
221  std::cout << " prePoint hit position x,y,z = " << prePoint->GetPosition().x() / cm
222  << " " << prePoint->GetPosition().y() / cm
223  << " " << prePoint->GetPosition().z() / cm
224  << std::endl;
225  }
226 
227  // time in ns
228  m_Hit->set_t(0, prePoint->GetGlobalTime() / nanosecond);
229 
230  //set the track ID
231  m_Hit->set_trkid(aTrack->GetTrackID());
232 
233  //set the initial energy deposit
234  m_Hit->set_edep(0);
235 
236  if (whichactive > 0) // return of IsInIntt, > 0 hit in si-strip, < 0 hit in absorber
237  {
238  // Now save the container we want to add this hit to
240  }
241  else
242  {
244  }
245 
246  if (G4VUserTrackInformation* p = aTrack->GetUserInformation())
247  {
248  if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
249  {
250  m_Hit->set_trkid(pp->GetUserTrackId());
251  m_Hit->set_shower_id(pp->GetShower()->get_id());
252  m_SaveShower = pp->GetShower();
253  }
254  }
255  break;
256 
257  default:
258  break;
259  }
260 
261  //std::cout << " Update exit values for prePoint->GetStepStatus = " << prePoint->GetStepStatus() << " and postPoint->GetStepStatus = " << postPoint->GetStepStatus() << std::endl;
262 
263  // here we just update the exit values, it will be overwritten
264  // for every step until we leave the volume or the particle
265  // ceases to exist
266  m_Hit->set_x(1, postPoint->GetPosition().x() / cm);
267  m_Hit->set_y(1, postPoint->GetPosition().y() / cm);
268  m_Hit->set_z(1, postPoint->GetPosition().z() / cm);
269 
270  StoreLocalCoordinate(m_Hit, aStep, false, true);
271 
272  if (whichactive > 0)
273  {
274  m_Hit->set_px(1, postPoint->GetMomentum().x() / GeV);
275  m_Hit->set_py(1, postPoint->GetMomentum().y() / GeV);
276  m_Hit->set_pz(1, postPoint->GetMomentum().z() / GeV);
277  m_Hit->set_eion(m_Hit->get_eion() + eion);
278  }
279 
280  m_Hit->set_t(1, postPoint->GetGlobalTime() / nanosecond);
281 
282  //sum up the energy to get total deposited
283  m_Hit->set_edep(m_Hit->get_edep() + edep);
284 
285  if (geantino)
286  {
287  m_Hit->set_edep(-1); // only energy=0 g4hits get dropped, this way geantinos survive the g4hit compression
288  if (whichactive > 0)
289  {
290  m_Hit->set_eion(-1);
291  }
292  }
293 
294  if (edep > 0)
295  {
296  if (G4VUserTrackInformation* p = aTrack->GetUserInformation())
297  {
298  if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
299  {
300  pp->SetKeep(1); // we want to keep the track
301  }
302  }
303  }
304 
305  // if any of these conditions is true this is the last step in
306  // this volume and we need to save the hit
307  // postPoint->GetStepStatus() == fGeomBoundary: track leaves this volume
308  // postPoint->GetStepStatus() == fWorldBoundary: track leaves this world
309  // (happens when your detector goes outside world volume)
310  // postPoint->GetStepStatus() == fAtRestDoItProc: track stops (typically
311  // aTrack->GetTrackStatus() == fStopAndKill is also set)
312  // aTrack->GetTrackStatus() == fStopAndKill: track ends
313  if (postPoint->GetStepStatus() == fGeomBoundary ||
314  postPoint->GetStepStatus() == fWorldBoundary ||
315  postPoint->GetStepStatus() == fAtRestDoItProc ||
316  aTrack->GetTrackStatus() == fStopAndKill)
317  {
318  if (Verbosity() > 0)
319  {
320  std::cout << " postPoint step status changed to " << postPoint->GetStepStatus() << " or aTrack status changed to "
321  << aTrack->GetTrackStatus() << std::endl;
322  std::cout << " end g4hit for: aTrack->GetParentID " << aTrack->GetParentID() << " aTrack->GetTrackID " << aTrack->GetTrackID() << " eion = " << eion << std::endl;
323  std::cout << " end hit position x,y,z = " << postPoint->GetPosition().x() / cm
324  << " " << postPoint->GetPosition().y() / cm
325  << " " << postPoint->GetPosition().z() / cm
326  << std::endl;
327  }
328 
329  // save only hits with energy deposit (or -1 for geantino)
330  if (m_Hit->get_edep())
331  {
332  m_SaveHitContainer->AddHit(sphxlayer, m_Hit);
333  if (m_SaveShower)
334  {
336  }
337  if (Verbosity() > 0)
338  {
339  m_Hit->print();
340  }
341  // ownership has been transferred to container, set to null
342  // so we will create a new hit for the next track
343  m_Hit = nullptr;
344  }
345  else
346  {
347  // if this hit has no energy deposit, just reset it for reuse
348  // this means we have to delete it in the dtor. If this was
349  // the last hit we processed the memory is still allocated
350  m_Hit->Reset();
351  }
352  }
353  return true;
354 }
355 
356 //____________________________________________________________________________..
358 {
359  m_HitContainer = findNode::getClass<PHG4HitContainer>(topNode, m_HitNodeName);
360  m_AbsorberHitContainer = findNode::getClass<PHG4HitContainer>(topNode, m_AbsorberNodeName);
361 
362  // if we do not find the node it's messed up.
363  if (!m_HitContainer)
364  {
365  std::cout << "PHG4InttSteppingAction::SetTopNode - unable to find " << m_HitNodeName << std::endl;
366  gSystem->Exit(1);
367  }
368 
369  if (!m_AbsorberHitContainer && Verbosity() > 1)
370  {
371  std::cout << "PHG4InttSteppingAction::SetTopNode - unable to find " << m_AbsorberNodeName << std::endl;
372  }
373 }
374 
376 {
377  if (type == "G4HIT")
378  {
380  return;
381  }
382  else if (type == "G4HIT_ABSORBER")
383  {
385  return;
386  }
387  std::cout << "Invalid output hit node type " << type << std::endl;
388  gSystem->Exit(1);
389  return;
390 }