Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHG4SpacalSteppingAction.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHG4SpacalSteppingAction.cc
1 
11 #include "PHG4SpacalDetector.h"
12 
13 #include "PHG4CellDefs.h"
14 #include "PHG4CylinderCellGeom.h"
17 #include "PHG4CylinderGeom.h" // for PHG4CylinderGeom
19 #include "PHG4CylinderGeom_Spacalv1.h" // for PHG4CylinderGeom_Spaca...
20 
21 #include <calobase/TowerInfo.h>
22 #include <calobase/TowerInfoContainer.h>
23 #include <calobase/TowerInfoContainerv1.h>
24 #include <calobase/TowerInfoDefs.h>
25 
26 #include <g4main/PHG4Hit.h> // for PHG4Hit
28 #include <g4main/PHG4Hitv1.h>
29 #include <g4main/PHG4Shower.h>
30 #include <g4main/PHG4SteppingAction.h> // for PHG4SteppingAction
32 
33 #include <phool/PHCompositeNode.h>
34 #include <phool/PHIODataNode.h>
35 #include <phool/PHNode.h> // for PHNode
36 #include <phool/PHNodeIterator.h>
37 #include <phool/PHObject.h> // for PHObject
38 #include <phool/getClass.h>
39 #include <phool/phool.h> // for PHWHERE
40 #include <phool/recoConsts.h>
41 
42 #include <phparameter/PHParameters.h>
43 
44 #include <Geant4/G4IonisParamMat.hh> // for G4IonisParamMat
45 #include <Geant4/G4Material.hh> // for G4Material
46 #include <Geant4/G4MaterialCutsCouple.hh>
47 #include <Geant4/G4ParticleDefinition.hh> // for G4ParticleDefinition
48 #include <Geant4/G4ReferenceCountedHandle.hh> // for G4ReferenceCountedHandle
49 #include <Geant4/G4Step.hh>
50 #include <Geant4/G4StepPoint.hh> // for G4StepPoint
51 #include <Geant4/G4StepStatus.hh> // for fGeomBoundary, fAtRestD...
52 #include <Geant4/G4String.hh> // for G4String
53 #include <Geant4/G4SystemOfUnits.hh>
54 #include <Geant4/G4ThreeVector.hh> // for G4ThreeVector
55 #include <Geant4/G4TouchableHandle.hh> // for G4TouchableHandle
56 #include <Geant4/G4Track.hh> // for G4Track
57 #include <Geant4/G4TrackStatus.hh> // for fStopAndKill
58 #include <Geant4/G4TransportationManager.hh>
59 #include <Geant4/G4Types.hh> // for G4double
60 #include <Geant4/G4VTouchable.hh> // for G4VTouchable
61 #include <Geant4/G4VUserTrackInformation.hh> // for G4VUserTrackInformation
62 
63 #include <TSystem.h>
64 
65 #include <cmath> // for isfinite
66 #include <cstdlib> // for exit
67 #include <iostream>
68 #include <string> // for operator<<, char_traits
69 
70 class G4VPhysicalVolume;
71 class PHCompositeNode;
72 
73 //____________________________________________________________________________..
75  : PHG4SteppingAction(indetector->GetName())
76  , m_Detector(indetector)
77  , m_Params(parameters)
78  , m_doG4Hit(m_Params->get_int_param("saveg4hit"))
79  , m_tmin(m_Params->get_double_param("tmin"))
80  , m_tmax(m_Params->get_double_param("tmax"))
81  , m_dt(m_Params->get_double_param("dt"))
82 {
83 }
84 
86 {
87  // if the last hit was a zero energie deposit hit, it is just reset
88  // and the memory is still allocated, so we need to delete it here
89  // if the last hit was saved, hit is a nullptr pointer which are
90  // legal to delete (it results in a no operation)
91  delete m_Hit;
92 }
93 
95 {
96  if (m_doG4Hit) return 0;
97  PHNodeIterator iter(topNode);
99  // Looking for the DST node
100  PHCompositeNode *dstNode;
101  dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
102  if (!dstNode)
103  {
104  std::cout << PHWHERE << "DST Node missing, doing nothing." << std::endl;
105  exit(1);
106  }
107 
108  // add towerinfo here
109  PHNodeIterator dstiter(dstNode);
110  PHCompositeNode *DetNode = dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", detector));
111  if (!DetNode)
112  {
113  DetNode = new PHCompositeNode(detector);
114  dstNode->addNode(DetNode);
115  }
116  m_CaloInfoContainer = new TowerInfoContainerv1(TowerInfoContainer::DETECTOR::EMCAL);
117  PHIODataNode<PHObject> *towerNode = new PHIODataNode<PHObject>(m_CaloInfoContainer, "TOWERINFO_SIM_" + detector, "PHObject");
118  DetNode->addNode(towerNode);
119 
120  return 0;
121 }
122 
124 {
125  if (m_geomsetup) return 0;
126 
127  if (m_doG4Hit) return 0;
128  PHNodeIterator iter(topNode);
130 
131  geonodename = "CYLINDERGEOM_" + detector;
132  seggeonodename = "CYLINDERCELLGEOM_" + detector;
133  // get the private layergeo
134  _layergeo = findNode::getClass<PHG4CylinderGeomContainer>(topNode, geonodename);
135  if (!_layergeo)
136  {
137  std::cout << "PHG4SpacalSteppingAction::InitWithNode - Fatal Error - Could not locate sim geometry node "
138  << geonodename << std::endl;
139  exit(1);
140  }
141 
142  _seggeo = findNode::getClass<PHG4CylinderCellGeomContainer>(topNode, seggeonodename);
143  if (!_seggeo)
144  {
145  std::cout << "PHG4FullProjSpacalCellReco::process_event - Fatal Error - could not locate cell geometry node "
146  << seggeonodename << std::endl;
147  exit(1);
148  }
150  _geo = dynamic_cast<PHG4CylinderCellGeom_Spacalv1 *>(_geo_raw);
151  assert(_geo);
152  const PHG4CylinderGeom *_layergeom_raw = _layergeo->GetFirstLayerGeom();
153  assert(_layergeom_raw);
154  // a special implimentation of PHG4CylinderGeom is required here.
155  _layergeom = dynamic_cast<const PHG4CylinderGeom_Spacalv3 *>(_layergeom_raw);
157  m_geomsetup = true;
158  return 0;
159 }
160 
162 {
163  // get volume of the current step
164  G4VPhysicalVolume *volume = aStep->GetPreStepPoint()->GetTouchableHandle()->GetVolume();
165  int isactive = m_Detector->IsInCylinderActive(volume);
166  if (isactive > PHG4SpacalDetector::INACTIVE)
167  {
168  G4StepPoint *prePoint = aStep->GetPreStepPoint();
169  G4StepPoint *postPoint = aStep->GetPostStepPoint();
170  // time window cut
171  double pretime = prePoint->GetGlobalTime() / nanosecond;
172  double posttime = postPoint->GetGlobalTime() / nanosecond;
173  if (posttime < m_tmin || pretime > m_tmax) return false;
174  if ((posttime - pretime) > m_dt) return false;
175 
176  int scint_id = -1;
177 
178  if ( //
183  )
184  {
185  // SPACAL ID that is associated with towers
186  int sector_ID = 0;
187  int tower_ID = 0;
188  int fiber_ID = 0;
189 
190  if (isactive == PHG4SpacalDetector::FIBER_CORE)
191  {
192  fiber_ID = prePoint->GetTouchable()->GetReplicaNumber(1);
193  tower_ID = prePoint->GetTouchable()->GetReplicaNumber(2);
194  sector_ID = prePoint->GetTouchable()->GetReplicaNumber(3);
195  }
196 
197  else
198  {
199  return false;
200  }
201 
202  // compact the tower/sector/fiber ID into 32 bit scint_id, so we could save some space for SPACAL hits
203  scint_id = PHG4CylinderGeom_Spacalv3::scint_id_coder(sector_ID, tower_ID, fiber_ID).scint_ID;
204  }
205  else
206  {
207  // other configuraitons
208  if (isactive == PHG4SpacalDetector::FIBER_CORE)
209  {
210  scint_id = prePoint->GetTouchable()->GetReplicaNumber(2);
211  }
212  else
213  {
214  return false;
215  }
216  }
217  // decode scint_id
219 
220  // convert to z_ID, phi_ID
221  std::pair<int, int> tower_z_phi_ID = _layergeom->get_tower_z_phi_ID(decoder.tower_ID, decoder.sector_ID);
222  const int &tower_ID_z = tower_z_phi_ID.first;
223  const int &tower_ID_phi = tower_z_phi_ID.second;
224 
225  PHG4CylinderGeom_Spacalv3::tower_map_t::const_iterator it_tower =
226  _layergeom->get_sector_tower_map().find(decoder.tower_ID);
227  assert(it_tower != _layergeom->get_sector_tower_map().end());
228 
229  // convert tower_ID_z to to eta bin number
230  int etabin = -1;
231  try
232  {
233  etabin = _geo->get_etabin_block(tower_ID_z); // block eta bin
234  }
235  catch (std::exception &e)
236  {
237  std::cout << "Print cell geometry:" << std::endl;
238  _geo->identify();
239  std::cout << "Print scint_id_coder:" << std::endl;
240  decoder.identify();
241  std::cout << "PHG4SpacalSteppingAction::UserSteppingAction::"
242  << " - Fatal Error - " << e.what() << std::endl;
243  exit(1);
244  }
245 
246  const int sub_tower_ID_x = it_tower->second.get_sub_tower_ID_x(decoder.fiber_ID);
247  const int sub_tower_ID_y = it_tower->second.get_sub_tower_ID_y(decoder.fiber_ID);
248  unsigned short etabinshort = etabin * _layergeom->get_n_subtower_eta() + sub_tower_ID_y;
249  unsigned short phibin = tower_ID_phi * _layergeom->get_n_subtower_phi() + sub_tower_ID_x;
250 
251  // get light yield
252  double light_yield = GetVisibleEnergyDeposition(aStep);
253 
255  {
256  const G4TouchableHandle &theTouchable0 = prePoint->GetTouchableHandle();
257  const G4ThreeVector &worldPosition0 = prePoint->GetPosition();
258  G4ThreeVector localPosition = theTouchable0->GetHistory()->GetTopTransform().TransformPoint(worldPosition0);
259  const double localz0 = localPosition.z();
260  // post point
261  const G4TouchableHandle &theTouchable1 = postPoint->GetTouchableHandle();
262  const G4ThreeVector &worldPosition1 = postPoint->GetPosition();
263  localPosition = theTouchable1->GetHistory()->GetTopTransform().TransformPoint(worldPosition1);
264  const double localz1 = localPosition.z();
265 
266  const double z = 0.5 * (localz0 + localz1);
267  assert(not std::isnan(z));
268 
270  }
271 
272  // light yield correction from light guide collection efficiency:
274  {
275  const double x = it_tower->second.get_position_fraction_x_in_sub_tower(decoder.fiber_ID);
276  const double y = it_tower->second.get_position_fraction_y_in_sub_tower(decoder.fiber_ID);
277 
279  }
280  unsigned int tower_key = TowerInfoDefs::encode_emcal(etabinshort, phibin);
282 
283  // set keep for the track
284  const G4Track *aTrack = aStep->GetTrack();
285  if (light_yield > 0)
286  {
287  if (G4VUserTrackInformation *p = aTrack->GetUserInformation())
288  {
289  if (PHG4TrackUserInfoV1 *pp = dynamic_cast<PHG4TrackUserInfoV1 *>(p))
290  {
291  pp->SetKeep(1); // we want to keep the track
292  }
293  }
294  }
295  return true;
296  }
297  else
298  {
299  return false;
300  }
301 }
302 
303 //____________________________________________________________________________..
304 bool PHG4SpacalSteppingAction::UserSteppingAction(const G4Step *aStep, bool)
305 {
306  if (!m_doG4Hit)
307  {
308  return NoHitSteppingAction(aStep);
309  }
310 
311  // get volume of the current step
312  G4VPhysicalVolume *volume = aStep->GetPreStepPoint()->GetTouchableHandle()->GetVolume();
313 
314  // collect energy and track length step by step
315  G4double edep = aStep->GetTotalEnergyDeposit() / GeV;
316  G4double eion = (aStep->GetTotalEnergyDeposit() - aStep->GetNonIonizingEnergyDeposit()) / GeV;
317 
318  const G4Track *aTrack = aStep->GetTrack();
319 
320  int layer_id = m_Detector->get_Layer();
321  // make sure we are in a volume
322  // IsInCylinderActive returns the number of the scintillator
323  // slat which has fired
324  int isactive = m_Detector->IsInCylinderActive(volume);
325  if (isactive > PHG4SpacalDetector::INACTIVE)
326  {
327  bool geantino = false;
328  // the check for the pdg code speeds things up, I do not want to make
329  // an expensive string compare for every track when we know
330  // geantino or chargedgeantino has pid=0
331  if (aTrack->GetParticleDefinition()->GetPDGEncoding() == 0 && aTrack->GetParticleDefinition()->GetParticleName().find("geantino") != std::string::npos)
332  {
333  geantino = true;
334  }
335  G4StepPoint *prePoint = aStep->GetPreStepPoint();
336  G4StepPoint *postPoint = aStep->GetPostStepPoint();
337  int scint_id = -1;
338 
339  if ( //
344  )
345  {
346  // SPACAL ID that is associated with towers
347  int sector_ID = 0;
348  int tower_ID = 0;
349  int fiber_ID = 0;
350 
351  if (isactive == PHG4SpacalDetector::FIBER_CORE)
352  {
353  fiber_ID = prePoint->GetTouchable()->GetReplicaNumber(1);
354  tower_ID = prePoint->GetTouchable()->GetReplicaNumber(2);
355  sector_ID = prePoint->GetTouchable()->GetReplicaNumber(3);
356  }
357 
358  else if (isactive == PHG4SpacalDetector::FIBER_CLADING)
359  {
360  fiber_ID = prePoint->GetTouchable()->GetReplicaNumber(0);
361  tower_ID = prePoint->GetTouchable()->GetReplicaNumber(1);
362  sector_ID = prePoint->GetTouchable()->GetReplicaNumber(2);
363  }
364 
365  else if (isactive == PHG4SpacalDetector::ABSORBER)
366  {
367  tower_ID = prePoint->GetTouchable()->GetReplicaNumber(0);
368  sector_ID = prePoint->GetTouchable()->GetReplicaNumber(1);
369  }
370 
371  else if (isactive == PHG4SpacalDetector::SUPPORT)
372  {
373  tower_ID = prePoint->GetTouchable()->GetReplicaNumber(0);
374  sector_ID = prePoint->GetTouchable()->GetReplicaNumber(1);
375  fiber_ID = (1 << (PHG4CylinderGeom_Spacalv3::scint_id_coder::kfiber_bit)) - 1; // use max fiber ID to flag for support strucrtures.
376 
377  // std::cout <<"PHG4SpacalSteppingAction::UserSteppingAction - SUPPORT tower_ID = "<<tower_ID<<std::endl;
378  }
379 
380  // compact the tower/sector/fiber ID into 32 bit scint_id, so we could save some space for SPACAL hits
381  scint_id = PHG4CylinderGeom_Spacalv3::scint_id_coder(sector_ID, tower_ID, fiber_ID).scint_ID;
382  }
383  else
384  {
385  // other configuraitons
386  if (isactive == PHG4SpacalDetector::FIBER_CORE)
387  {
388  scint_id = prePoint->GetTouchable()->GetReplicaNumber(2);
389  }
390  else if (isactive == PHG4SpacalDetector::FIBER_CLADING)
391  {
392  scint_id = prePoint->GetTouchable()->GetReplicaNumber(1);
393  }
394  else
395  {
396  scint_id = prePoint->GetTouchable()->GetReplicaNumber(0);
397  }
398  }
399 
400  // std::cout << "track id " << aTrack->GetTrackID() << std::endl;
401  // std::cout << "time prepoint: " << prePoint->GetGlobalTime() << std::endl;
402  // std::cout << "time postpoint: " << postPoint->GetGlobalTime() << std::endl;
403  switch (prePoint->GetStepStatus())
404  {
405  case fGeomBoundary:
406  case fUndefined:
407  // if previous hit was saved, hit pointer was set to nullptr
408  // and we have to make a new one
409  if (!m_Hit)
410  {
411  m_Hit = new PHG4Hitv1();
412  }
413  m_Hit->set_layer((unsigned int) layer_id);
414  m_Hit->set_scint_id(scint_id); // isactive contains the scintillator slat id
415  // here we set the entrance values in cm
416  m_Hit->set_x(0, prePoint->GetPosition().x() / cm);
417  m_Hit->set_y(0, prePoint->GetPosition().y() / cm);
418  m_Hit->set_z(0, prePoint->GetPosition().z() / cm);
419 
420  // time in ns
421  m_Hit->set_t(0, prePoint->GetGlobalTime() / nanosecond);
422  // set the track ID
423  m_Hit->set_trkid(aTrack->GetTrackID());
424  m_SaveTrackid = aTrack->GetTrackID();
425  // set the initial energy deposit
426  m_Hit->set_edep(0);
427  // Now add the hit
428  if (isactive == PHG4SpacalDetector::FIBER_CORE) // the slat ids start with zero
429  {
430  // store all pre local coordinates
431  StoreLocalCoordinate(m_Hit, aStep, true, false);
432  m_Hit->set_eion(0); // only implemented for v5 otherwise empty
435  }
436  else
437  {
439  }
440  if (G4VUserTrackInformation *p = aTrack->GetUserInformation())
441  {
442  if (PHG4TrackUserInfoV1 *pp = dynamic_cast<PHG4TrackUserInfoV1 *>(p))
443  {
444  m_Hit->set_trkid(pp->GetUserTrackId());
445  m_Hit->set_shower_id(pp->GetShower()->get_id());
446  m_CurrentShower = pp->GetShower();
447  }
448  }
449 
450  if (m_Hit->get_z(0) > get_zmax() || m_Hit->get_z(0) < get_zmin())
451  {
452  std::cout << "PHG4SpacalSteppingAction: hit outside acceptance, layer: "
453  << layer_id << std::endl;
454  m_Hit->identify();
455  }
456  break;
457  default:
458  break;
459  }
460  // some sanity checks for inconsistencies
461  // check if this hit was created, if not print out last post step status
462  if (!m_Hit || !std::isfinite(m_Hit->get_x(0)))
463  {
464  std::cout << GetName() << ": hit was not created" << std::endl;
465  std::cout << "prestep status: " << prePoint->GetStepStatus()
466  << ", last post step status: " << m_SavePostStepStatus << std::endl;
467  exit(1);
468  }
469  m_SavePostStepStatus = postPoint->GetStepStatus();
470  // check if track id matches the initial one when the hit was created
471  if (aTrack->GetTrackID() != m_SaveTrackid)
472  {
473  std::cout << GetName() << ": hits do not belong to the same track" << std::endl;
474  std::cout << "saved track: " << m_SaveTrackid
475  << ", current trackid: " << aTrack->GetTrackID()
476  << std::endl;
477  exit(1);
478  }
479  // here we just update the exit values, it will be overwritten
480  // for every step until we leave the volume or the particle
481  // ceases to exist
482  m_Hit->set_x(1, postPoint->GetPosition().x() / cm);
483  m_Hit->set_y(1, postPoint->GetPosition().y() / cm);
484  m_Hit->set_z(1, postPoint->GetPosition().z() / cm);
485 
486  m_Hit->set_t(1, postPoint->GetGlobalTime() / nanosecond);
487  // sum up the energy to get total deposited
488  m_Hit->set_edep(m_Hit->get_edep() + edep);
489 
490  if (isactive == PHG4SpacalDetector::FIBER_CORE) // only for active areas
491  {
492  // store all pre local coordinates
493  StoreLocalCoordinate(m_Hit, aStep, false, true);
494 
495  m_Hit->set_eion(m_Hit->get_eion() + eion);
496 
497  double light_yield = GetVisibleEnergyDeposition(aStep);
498 
499  static bool once = true;
500  if (once and edep > 0)
501  {
502  once = false;
503 
504  if (Verbosity() > 0)
505  {
506  std::cout << "PHG4SpacalSteppingAction::UserSteppingAction::"
507  //
508  << m_Detector->GetName() << " - "
509  << " use scintillating light model at each Geant4 steps. "
510  << "First step: "
511  << "Material = "
512  << aTrack->GetMaterialCutsCouple()->GetMaterial()->GetName()
513  << ", "
514  << "Birk Constant = "
515  << aTrack->GetMaterialCutsCouple()->GetMaterial()->GetIonisation()->GetBirksConstant()
516  << ","
517  << "edep = " << edep << ", "
518  << "eion = " << eion
519  << ", "
520  << "light_yield = " << light_yield << std::endl;
521  }
522  }
523 
524  m_Hit->set_light_yield(m_Hit->get_light_yield() + light_yield);
525  }
526 
527  if (m_Hit->get_z(1) > get_zmax() || m_Hit->get_z(1) < get_zmin())
528  {
529  std::cout << "PHG4SpacalSteppingAction: hit outside acceptance get_zmin() "
530  << get_zmin() << ", get_zmax() " << get_zmax() << " at exit"
531  << std::endl;
532  m_Hit->identify();
533  }
534  if (geantino)
535  {
536  m_Hit->set_edep(-1); // only energy=0 g4hits get dropped, this way geantinos survive the g4hit compression
537  // m_Hit->set_eion(-1);
538  }
539  if (edep > 0)
540  {
541  if (G4VUserTrackInformation *p = aTrack->GetUserInformation())
542  {
543  if (PHG4TrackUserInfoV1 *pp = dynamic_cast<PHG4TrackUserInfoV1 *>(p))
544  {
545  pp->SetKeep(1); // we want to keep the track
546  }
547  }
548  }
549  // if any of these conditions is true this is the last step in
550  // this volume and we need to save the hit
551  // postPoint->GetStepStatus() == fGeomBoundary: track leaves this volume
552  // postPoint->GetStepStatus() == fWorldBoundary: track leaves this world
553  // (happens when your detector goes outside world volume)
554  // aTrack->GetTrackStatus() == fStopAndKill: track ends
555  if (postPoint->GetStepStatus() == fGeomBoundary ||
556  postPoint->GetStepStatus() == fWorldBoundary ||
557  postPoint->GetStepStatus() == fAtRestDoItProc ||
558  aTrack->GetTrackStatus() == fStopAndKill)
559  {
560  // save only hits with energy deposit (or -1 for geantino)
561  if (m_Hit->get_edep())
562  {
563  m_CurrentHitContainer->AddHit(layer_id, m_Hit);
564  if (m_CurrentShower)
565  {
567  }
568  // ownership has been transferred to container, set to null
569  // so we will create a new hit for the next track
570  m_Hit = nullptr;
571  }
572  else
573  {
574  // if this hit has no energy deposit, just reset it for reuse
575  // this means we have to delete it in the dtor. If this was
576  // the last hit we processed the memory is still allocated
577  m_Hit->Reset();
578  }
579  }
580  // return true to indicate the hit was used
581  return true;
582  }
583  else
584  {
585  return false;
586  }
587 }
588 
589 //____________________________________________________________________________..
591 {
592  // we can only play with the geometry node after ConstructMe is called
593  if ((!m_geomsetup) && (!m_doG4Hit))
594  {
595  SetUpGeomNode(topNode);
596  }
597  m_HitContainer = findNode::getClass<PHG4HitContainer>(topNode, m_HitNodeName);
598  m_AbsorberHitContainer = findNode::getClass<PHG4HitContainer>(topNode, m_AbsorberNodeName);
599  // if we do not find the node it's messed up.
600  if (!m_HitContainer)
601  {
602  std::cout << "PHG4SpacalSteppingAction::SetTopNode - unable to find " << m_HitNodeName << std::endl;
603  gSystem->Exit(1);
604  }
605  // this is perfectly fine if absorber hits are disabled
606  if (!m_AbsorberHitContainer)
607  {
608  if (Verbosity() > 0)
609  {
610  std::cout << "PHG4SpacalSteppingAction::SetTopNode - unable to find " << m_AbsorberNodeName << std::endl;
611  }
612  }
613 }
614 
615 double
617 {
618  if (!m_Detector)
619  {
620  return 0;
621  }
622  else
623  {
624  return m_Detector->get_geom()->get_zmin() - .0001;
625  }
626 }
627 
628 double
630 {
631  if (!m_Detector)
632  {
633  return 0;
634  }
635  else
636  {
637  return m_Detector->get_geom()->get_zmax() + .0001;
638  }
639 }
640 
642 {
643  if (type == "G4HIT")
644  {
646  return;
647  }
648  else if (type == "G4HIT_ABSORBER")
649  {
651  return;
652  }
653  std::cout << "Invalid output hit node type " << type << std::endl;
654  gSystem->Exit(1);
655  return;
656 }
657