Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHG4IHCalSteppingAction.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHG4IHCalSteppingAction.cc
2 
3 #include "PHG4IHCalDetector.h"
4 
6 
7 #include <phparameter/PHParameters.h>
8 
9 #include <g4main/PHG4Hit.h>
11 #include <g4main/PHG4Hitv1.h>
12 #include <g4main/PHG4Shower.h>
13 #include <g4main/PHG4SteppingAction.h> // for PHG4SteppingAction
15 
16 #include <phool/PHCompositeNode.h>
17 #include <phool/PHIODataNode.h> // for PHIODataNode
18 #include <phool/PHNode.h> // for PHNode
19 #include <phool/PHNodeIterator.h> // for PHNodeIterator
20 #include <phool/PHObject.h> // for PHObject
21 #include <phool/getClass.h>
22 
24 
25 #include <calobase/TowerInfo.h>
26 #include <calobase/TowerInfoContainer.h>
27 #include <calobase/TowerInfoContainerv1.h>
28 #include <calobase/TowerInfoDefs.h>
29 
30 #include <TSystem.h>
31 
32 // Root headers
33 #include <TFile.h>
34 #include <TH2.h>
35 
36 #include <Geant4/G4ParticleDefinition.hh> // for G4ParticleDefinition
37 #include <Geant4/G4ReferenceCountedHandle.hh> // for G4ReferenceCountedHandle
38 #include <Geant4/G4Step.hh>
39 #include <Geant4/G4StepPoint.hh> // for G4StepPoint
40 #include <Geant4/G4StepStatus.hh> // for fGeomBoundary, fAtRest...
41 #include <Geant4/G4String.hh> // for G4String
42 #include <Geant4/G4SystemOfUnits.hh>
43 #include <Geant4/G4ThreeVector.hh> // for G4ThreeVector
44 #include <Geant4/G4TouchableHandle.hh> // for G4TouchableHandle
45 #include <Geant4/G4Track.hh> // for G4Track
46 #include <Geant4/G4TrackStatus.hh> // for fStopAndKill
47 #include <Geant4/G4TransportationManager.hh>
48 #include <Geant4/G4Types.hh> // for G4double
49 #include <Geant4/G4VPhysicalVolume.hh> // for G4VPhysicalVolume
50 #include <Geant4/G4VTouchable.hh> // for G4VTouchable
51 #include <Geant4/G4VUserTrackInformation.hh> // for G4VUserTrackInformation
52 
53 #include <cmath> // for isfinite
54 #include <cstdlib> // for getenv
55 #include <filesystem>
56 #include <iostream>
57 #include <string> // for operator<<, operator+
58 #include <utility> // for pair
59 
60 class PHCompositeNode;
61 
62 //____________________________________________________________________________..
64  : PHG4SteppingAction(detector->GetName())
65  , m_Detector(detector)
66  , m_Params(parameters)
67  , m_IsActive(m_Params->get_int_param("active"))
68  , m_IsBlackHole(m_Params->get_int_param("blackhole"))
69  , m_LightScintModelFlag(m_Params->get_int_param("light_scint_model"))
70  , m_doG4Hit(m_Params->get_int_param("saveg4hit"))
71  , m_tmin(m_Params->get_double_param("tmin"))
72  , m_tmax(m_Params->get_double_param("tmax"))
73  , m_dt(m_Params->get_double_param("dt"))
74 {
75  SetLightCorrection(m_Params->get_double_param("light_balance_inner_radius") * cm,
76  m_Params->get_double_param("light_balance_inner_corr"),
77  m_Params->get_double_param("light_balance_outer_radius") * cm,
78  m_Params->get_double_param("light_balance_outer_corr"));
79 }
80 
82 {
83  // if the last hit was a zero energie deposit hit, it is just reset
84  // and the memory is still allocated, so we need to delete it here
85  // if the last hit was saved, hit is a nullptr pointer which are
86  // legal to delete (it results in a no operation)
87  delete m_Hit;
88  // since we have a copy in memory of this one - we need to delete it
89  delete m_MapCorrHist;
90 }
91 
92 //____________________________________________________________________________..
94 {
96  {
97  std::string ihcalmapname(m_Params->get_string_param("MapFileName"));
98  if (ihcalmapname.empty())
99  {
100  return 0;
101  }
102  if (!std::filesystem::exists(m_Params->get_string_param("MapFileName")))
103  {
104  std::cout << PHWHERE << " Could not locate " << m_Params->get_string_param("MapFileName") << std::endl;
105  std::cout << "use empty filename to ignore mapfile" << std::endl;
106  gSystem->Exit(1);
107  }
108  TFile* file = TFile::Open(ihcalmapname.c_str());
109  file->GetObject(m_Params->get_string_param("MapHistoName").c_str(), m_MapCorrHist);
110  if (!m_MapCorrHist)
111  {
112  std::cout << "ERROR: could not find Histogram " << m_Params->get_string_param("MapHistoName") << " in " << m_Params->get_string_param("MapFileName") << std::endl;
113  gSystem->Exit(1);
114  }
115  m_MapCorrHist->SetDirectory(nullptr); // rootism: this needs to be set otherwise histo vanished when closing the file
116  file->Close();
117  delete file;
118  }
119  if (!m_doG4Hit)
120  {
121  try
122  {
123  CreateNodeTree(topNode);
124  }
125  catch (std::exception& e)
126  {
127  std::cout << e.what() << std::endl;
129  }
130  if (Verbosity() > 1) topNode->print();
131  }
132 
133  return 0;
134 }
135 
136 //____________________________________________________________________________..
138 {
139  G4TouchableHandle touch = aStep->GetPreStepPoint()->GetTouchableHandle();
140  G4TouchableHandle touchpost = aStep->GetPostStepPoint()->GetTouchableHandle();
141  // get volume of the current step
142  G4VPhysicalVolume* volume = touch->GetVolume();
143 
144  // m_Detector->IsInIHCal(volume)
145  // returns
146  // 0 is outside of IHCal
147  // 1 is inside scintillator
148  // -1 is steel absorber
149 
150  int whichactive = m_Detector->IsInIHCal(volume);
151 
152  if (!whichactive)
153  {
154  return false;
155  }
156  int layer_id = -1;
157  int tower_id = -1;
158  // int sector_id = -1;
159  if (whichactive > 0) // scintillator
160  {
161  std::tuple<int, int, int> layer_tower = m_Detector->GetLayerTowerId(volume);
162  // sector_id = std::get<0>(layer_tower);
163  layer_id = std::get<1>(layer_tower);
164  tower_id = std::get<2>(layer_tower);
165 
166  // std::cout<<"******** Inner HCal\t"<<volume->GetName()<<"\t"<<layer_id<<"\t"<<tower_id<<std::endl;
167  }
168  else
169  {
170  // absorber hit, do nothing
171  return false;
172  }
173 
174  if (!m_IsActive) return false;
175 
176  G4StepPoint* prePoint = aStep->GetPreStepPoint();
177  G4StepPoint* postPoint = aStep->GetPostStepPoint();
178  // time window cut
179  double pretime = prePoint->GetGlobalTime() / nanosecond;
180  double posttime = postPoint->GetGlobalTime() / nanosecond;
181  if (posttime < m_tmin || pretime > m_tmax) return false;
182  if ((posttime - pretime) > m_dt) return false;
183  G4double eion = (aStep->GetTotalEnergyDeposit() - aStep->GetNonIonizingEnergyDeposit()) / GeV;
184  const G4Track* aTrack = aStep->GetTrack();
185  // we only need visible energy here
186  double light_yield = eion;
187 
188  // correct evis using light map
190  {
191  light_yield = GetVisibleEnergyDeposition(aStep);
192  if (m_MapCorrHist)
193  {
194  const G4TouchableHandle& theTouchable = prePoint->GetTouchableHandle();
195  const G4ThreeVector& worldPosition = postPoint->GetPosition();
196  G4ThreeVector localPosition = theTouchable->GetHistory()->GetTopTransform().TransformPoint(worldPosition);
197  float lx = localPosition.x() / cm;
198  float ly = localPosition.y() / cm;
199 
200  // adjust to tilemap coordinates
201  int lcx = (int) (5.0 * lx) + 1;
202  int lcy = (int) (5.0 * (ly + 2.0)) + 1;
203 
204  if ((lcy >= 1) && (lcy <= m_MapCorrHist->GetNbinsY()) &&
205  (lcx >= 1) && (lcx <= m_MapCorrHist->GetNbinsX()))
206  {
207  light_yield *= m_MapCorrHist->GetBinContent(lcx, lcy);
208  }
209  else
210  {
211  light_yield = 0.0;
212  }
213  }
214  else
215  {
216  light_yield = light_yield * GetLightCorrection(postPoint->GetPosition().x(), postPoint->GetPosition().y());
217  }
218  }
219  // find the tower index for this step, tower_id is ieta, layer_id/4 is iphi
220  unsigned int ieta = tower_id;
221  unsigned int iphi = (unsigned int) layer_id / 4;
222  unsigned int tower_key = TowerInfoDefs::encode_hcal(ieta, iphi);
224  // set keep for the track
225  if (light_yield > 0)
226  {
227  if (G4VUserTrackInformation* p = aTrack->GetUserInformation())
228  {
229  if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
230  {
231  pp->SetKeep(1); // we want to keep the track
232  }
233  }
234  }
235 
236  return true;
237 }
238 //____________________________________________________________________________..
239 bool PHG4IHCalSteppingAction::UserSteppingAction(const G4Step* aStep, bool)
240 {
241  if ((!m_doG4Hit) && (!m_IsBlackHole))
242  {
243  return NoHitSteppingAction(aStep);
244  }
245 
246  G4TouchableHandle touch = aStep->GetPreStepPoint()->GetTouchableHandle();
247  G4TouchableHandle touchpost = aStep->GetPostStepPoint()->GetTouchableHandle();
248  // get volume of the current step
249  G4VPhysicalVolume* volume = touch->GetVolume();
250 
251  // m_Detector->IsInIHCal(volume)
252  // returns
253  // 0 is outside of IHCal
254  // 1 is inside scintillator
255  // -1 is steel absorber
256 
257  int whichactive = m_Detector->IsInIHCal(volume);
258 
259  if (!whichactive)
260  {
261  return false;
262  }
263  int layer_id = -1;
264  int tower_id = -1;
265  int sector_id = -1;
266  if (whichactive > 0) // scintillator
267  {
268  std::tuple<int, int, int> layer_tower = m_Detector->GetLayerTowerId(volume);
269  sector_id = std::get<0>(layer_tower);
270  layer_id = std::get<1>(layer_tower);
271  tower_id = std::get<2>(layer_tower);
272 
273  // std::cout<<"******** Inner HCal\t"<<volume->GetName()<<"\t"<<layer_id<<"\t"<<tower_id<<std::endl;
274  }
275  else
276  {
277  layer_id = m_Detector->GetSectorId(volume); // absorber sector id
278  }
279  // collect energy and track length step by step
280  G4double edep = aStep->GetTotalEnergyDeposit() / GeV;
281  G4double eion = (aStep->GetTotalEnergyDeposit() - aStep->GetNonIonizingEnergyDeposit()) / GeV;
282  double light_yield = 0;
283  const G4Track* aTrack = aStep->GetTrack();
284 
285  // if this block stops everything, just put all kinetic energy into edep
286  if (m_IsBlackHole)
287  {
288  edep = aTrack->GetKineticEnergy() / GeV;
289  G4Track* killtrack = const_cast<G4Track*>(aTrack);
290  killtrack->SetTrackStatus(fStopAndKill);
291  }
292 
293  // make sure we are in a volume
294  if (m_IsActive)
295  {
296  bool geantino = false;
297 
298  // the check for the pdg code speeds things up, I do not want to make
299  // an expensive string compare for every track when we know
300  // geantino or chargedgeantino has pid=0
301  if (aTrack->GetParticleDefinition()->GetPDGEncoding() == 0 &&
302  aTrack->GetParticleDefinition()->GetParticleName().find("geantino") != std::string::npos)
303  {
304  geantino = true;
305  }
306  G4StepPoint* prePoint = aStep->GetPreStepPoint();
307  G4StepPoint* postPoint = aStep->GetPostStepPoint();
308  // std::cout << "track id " << aTrack->GetTrackID() << std::endl;
309  // std::cout << "time prepoint: " << prePoint->GetGlobalTime() << std::endl;
310  // std::cout << "time postpoint: " << postPoint->GetGlobalTime() << std::endl;
311  switch (prePoint->GetStepStatus())
312  {
313  case fPostStepDoItProc:
314  if (m_SavePostStepStatus != fGeomBoundary)
315  {
316  if (m_SavePostStepStatus != fAtRestDoItProc)
317  {
318  break;
319  }
320  else
321  {
322  if (aTrack->GetTrackID() == m_SaveTrackId)
323  {
324  std::cout << GetName() << ": Bad step status combination for the same track " << std::endl;
325  std::cout << "prestep status: " << PHG4StepStatusDecode::GetStepStatus(prePoint->GetStepStatus())
326  << ", poststep status: " << PHG4StepStatusDecode::GetStepStatus(postPoint->GetStepStatus())
327  << ", last pre step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePreStepStatus)
328  << ", last post step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePostStepStatus) << std::endl;
329  std::cout << "last track: " << m_SaveTrackId
330  << ", current trackid: " << aTrack->GetTrackID() << std::endl;
331  std::cout << "phys pre vol: " << volume->GetName()
332  << " post vol : " << touchpost->GetVolume()->GetName() << std::endl;
333  std::cout << " previous phys pre vol: " << m_SaveVolPre->GetName()
334  << " previous phys post vol: " << m_SaveVolPost->GetName() << std::endl;
335  gSystem->Exit(1);
336  }
337  }
338  }
339  else
340  {
341  std::cout << GetName() << ": New Hit for " << std::endl;
342  std::cout << "prestep status: " << PHG4StepStatusDecode::GetStepStatus(prePoint->GetStepStatus())
343  << ", poststep status: " << PHG4StepStatusDecode::GetStepStatus(postPoint->GetStepStatus())
344  << ", last pre step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePreStepStatus)
345  << ", last post step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePostStepStatus) << std::endl;
346  std::cout << "last track: " << m_SaveTrackId
347  << ", current trackid: " << aTrack->GetTrackID() << std::endl;
348  std::cout << "phys pre vol: " << volume->GetName()
349  << " post vol : " << touchpost->GetVolume()->GetName() << std::endl;
350  std::cout << " previous phys pre vol: " << m_SaveVolPre->GetName()
351  << " previous phys post vol: " << m_SaveVolPost->GetName() << std::endl;
352  }
353  [[fallthrough]];
354  case fGeomBoundary:
355  case fUndefined:
356  // if previous hit was saved, hit pointer was set to nullptr
357  // and we have to make a new one
358  if (!m_Hit)
359  {
360  m_Hit = new PHG4Hitv1();
361  }
362  // here we set the entrance values in cm
363  m_Hit->set_x(0, prePoint->GetPosition().x() / cm);
364  m_Hit->set_y(0, prePoint->GetPosition().y() / cm);
365  m_Hit->set_z(0, prePoint->GetPosition().z() / cm);
366  // time in ns
367  m_Hit->set_t(0, prePoint->GetGlobalTime() / nanosecond);
368  // set and save the track ID
369  m_Hit->set_trkid(aTrack->GetTrackID());
370  m_SaveTrackId = aTrack->GetTrackID();
371  // set the initial energy deposit
372  m_Hit->set_edep(0);
373  if (whichactive > 0) // return of IsInIHCalDetector, > 0 hit in scintillator, < 0 hit in absorber
374  {
375  m_Hit->set_sector(sector_id); // the slat id
376  m_Hit->set_scint_id(tower_id); // the slat id
377  m_Hit->set_eion(0); // only implemented for v5 otherwise empty
378  m_Hit->set_raw_light_yield(0); // for scintillator only, initialize light yields
379  m_Hit->set_light_yield(0); // for scintillator only, initialize light yields
380  // Now save the container we want to add this hit to
382  }
383  else
384  {
386  }
387  if (G4VUserTrackInformation* p = aTrack->GetUserInformation())
388  {
389  if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
390  {
391  m_Hit->set_trkid(pp->GetUserTrackId());
392  m_Hit->set_shower_id(pp->GetShower()->get_id());
393  m_SaveShower = pp->GetShower();
394  }
395  }
396  break;
397  default:
398  break;
399  }
400  // some sanity checks for inconsistencies
401  // check if this hit was created, if not print out last post step status
402  if (!m_Hit || !std::isfinite(m_Hit->get_x(0)))
403  {
404  std::cout << GetName() << ": hit was not created" << std::endl;
405  std::cout << "prestep status: " << PHG4StepStatusDecode::GetStepStatus(prePoint->GetStepStatus())
406  << ", poststep status: " << PHG4StepStatusDecode::GetStepStatus(postPoint->GetStepStatus())
407  << ", last pre step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePreStepStatus)
408  << ", last post step status: " << PHG4StepStatusDecode::GetStepStatus(m_SavePostStepStatus) << std::endl;
409  std::cout << "last track: " << m_SaveTrackId
410  << ", current trackid: " << aTrack->GetTrackID() << std::endl;
411  std::cout << "phys pre vol: " << volume->GetName()
412  << " post vol : " << touchpost->GetVolume()->GetName() << std::endl;
413  std::cout << " previous phys pre vol: " << m_SaveVolPre->GetName()
414  << " previous phys post vol: " << m_SaveVolPost->GetName() << std::endl;
415  gSystem->Exit(1);
416  }
417  // check if track id matches the initial one when the hit was created
418  if (aTrack->GetTrackID() != m_SaveTrackId)
419  {
420  std::cout << GetName() << ": hits do not belong to the same track" << std::endl;
421  std::cout << "saved track: " << m_SaveTrackId
422  << ", current trackid: " << aTrack->GetTrackID()
423  << ", prestep status: " << prePoint->GetStepStatus()
424  << ", previous post step status: " << m_SavePostStepStatus
425  << std::endl;
426 
427  gSystem->Exit(1);
428  }
429  m_SavePreStepStatus = prePoint->GetStepStatus();
430  m_SavePostStepStatus = postPoint->GetStepStatus();
431  m_SaveVolPre = volume;
432  m_SaveVolPost = touchpost->GetVolume();
433  // here we just update the exit values, it will be overwritten
434  // for every step until we leave the volume or the particle
435  // ceases to exist
436  m_Hit->set_x(1, postPoint->GetPosition().x() / cm);
437  m_Hit->set_y(1, postPoint->GetPosition().y() / cm);
438  m_Hit->set_z(1, postPoint->GetPosition().z() / cm);
439 
440  m_Hit->set_t(1, postPoint->GetGlobalTime() / nanosecond);
441 
442  // sum up the energy to get total deposited
443  m_Hit->set_edep(m_Hit->get_edep() + edep);
444  if (whichactive > 0) // return of IsInIHCalDetector, > 0 hit in scintillator, < 0 hit in absorber
445  {
446  m_Hit->set_eion(m_Hit->get_eion() + eion);
447  light_yield = eion;
449  {
450  light_yield = GetVisibleEnergyDeposition(aStep); // for scintillator only, calculate light yields
451  m_Hit->set_raw_light_yield(m_Hit->get_raw_light_yield() + light_yield); // save raw Birks light yield
452  if (m_MapCorrHist)
453  {
454  const G4TouchableHandle& theTouchable = prePoint->GetTouchableHandle();
455  const G4ThreeVector& worldPosition = postPoint->GetPosition();
456  G4ThreeVector localPosition = theTouchable->GetHistory()->GetTopTransform().TransformPoint(worldPosition);
457  float lx = localPosition.x() / cm;
458  float ly = localPosition.y() / cm;
459 
460  // adjust to tilemap coordinates
461  int lcx = (int) (5.0 * lx) + 1;
462  int lcy = (int) (5.0 * (ly + 2.0)) + 1;
463 
464  if ((lcy >= 1) && (lcy <= m_MapCorrHist->GetNbinsY()) &&
465  (lcx >= 1) && (lcx <= m_MapCorrHist->GetNbinsX()))
466  {
467  light_yield *= m_MapCorrHist->GetBinContent(lcx, lcy);
468  }
469  else
470  {
471  light_yield = 0.0;
472  }
473  }
474  else
475  {
476  light_yield = light_yield * GetLightCorrection(postPoint->GetPosition().x(), postPoint->GetPosition().y());
477  }
478  }
479  m_Hit->set_light_yield(m_Hit->get_light_yield() + light_yield);
480  }
481  if (geantino)
482  {
483  m_Hit->set_edep(-1); // only energy=0 g4hits get dropped, this way geantinos survive the g4hit compression
484  m_Hit->set_eion(-1);
485  }
486  if (edep > 0)
487  {
488  if (G4VUserTrackInformation* p = aTrack->GetUserInformation())
489  {
490  if (PHG4TrackUserInfoV1* pp = dynamic_cast<PHG4TrackUserInfoV1*>(p))
491  {
492  pp->SetKeep(1); // we want to keep the track
493  }
494  }
495  }
496 
497  // if any of these conditions is true this is the last step in
498  // this volume and we need to save the hit
499  // postPoint->GetStepStatus() == fGeomBoundary: track leaves this volume
500  // postPoint->GetStepStatus() == fWorldBoundary: track leaves this world
501  // (happens when your detector goes outside world volume)
502  // postPoint->GetStepStatus() == fAtRestDoItProc: track stops (typically
503  // aTrack->GetTrackStatus() == fStopAndKill is also set)
504  // aTrack->GetTrackStatus() == fStopAndKill: track ends
505  if (postPoint->GetStepStatus() == fGeomBoundary ||
506  postPoint->GetStepStatus() == fWorldBoundary ||
507  postPoint->GetStepStatus() == fAtRestDoItProc ||
508  aTrack->GetTrackStatus() == fStopAndKill)
509  {
510  // save only hits with energy deposit (or -1 for geantino)
511  if (m_Hit->get_edep() != 0)
512  {
513  m_SaveHitContainer->AddHit(layer_id, m_Hit);
514 
515  if (m_SaveShower)
516  {
518  }
519  // ownership has been transferred to container, set to null
520  // so we will create a new hit for the next track
521  m_Hit = nullptr;
522  }
523  else
524  {
525  // if this hit has no energy deposit, just reset it for reuse
526  // this means we have to delete it in the dtor. If this was
527  // the last hit we processed the memory is still allocated
528  m_Hit->Reset();
529  }
530  }
531  // return true to indicate the hit was used
532  return true;
533  }
534  else
535  {
536  return false;
537  }
538 }
539 
540 //____________________________________________________________________________..
542 {
543  m_HitContainer = findNode::getClass<PHG4HitContainer>(topNode, m_HitNodeName);
544  m_AbsorberHitContainer = findNode::getClass<PHG4HitContainer>(topNode, m_AbsorberNodeName);
545 
546  // if we do not find the node it's messed up.
547  if (!m_HitContainer)
548  {
549  std::cout << "PHG4IHCalSteppingAction::SetTopNode - unable to find " << m_HitNodeName << std::endl;
550  }
551  if (!m_AbsorberHitContainer)
552  {
553  if (Verbosity() > 1)
554  {
555  std::cout << "PHG4IHcalSteppingAction::SetTopNode - unable to find " << m_AbsorberNodeName << std::endl;
556  }
557  }
558 }
559 
561 {
562  if (type == "G4HIT")
563  {
565  return;
566  }
567  else if (type == "G4HIT_ABSORBER")
568  {
570  return;
571  }
572  std::cout << "Invalid output hit node type " << type << std::endl;
573  gSystem->Exit(1);
574  return;
575 }
576 
578 {
579  PHNodeIterator nodeItr(topNode);
580  PHCompositeNode* dst_node = dynamic_cast<PHCompositeNode*>(
581  nodeItr.findFirst("PHCompositeNode", "DST"));
582  if (!dst_node)
583  {
584  std::cout << "PHComposite node created: DST" << std::endl;
585  dst_node = new PHCompositeNode("DST");
586  topNode->addNode(dst_node);
587  }
588  PHNodeIterator dstiter(dst_node);
589  PHCompositeNode* DetNode = dynamic_cast<PHCompositeNode*>(dstiter.findFirst("PHCompositeNode", m_Detector->SuperDetector()));
590  if (!DetNode)
591  {
592  DetNode = new PHCompositeNode(m_Detector->SuperDetector());
593  dst_node->addNode(DetNode);
594  }
595  m_CaloInfoContainer = new TowerInfoContainerv1(TowerInfoContainer::DETECTOR::HCAL);
596  PHIODataNode<PHObject>* towerNode = new PHIODataNode<PHObject>(m_CaloInfoContainer, "TOWERINFO_SIM_" + m_Detector->SuperDetector(), "PHObject");
597  DetNode->addNode(towerNode);
598 }