EDepSimPersistencyManager.cc
Go to the documentation of this file.
1 //
2 // Implementation for concrete G4PersistencyManager.
3 //
4 
5 #include <TPRegexp.h>
6 
9 #include "EDepSimVertexInfo.hh"
10 #include "EDepSimTrajectory.hh"
12 #include "EDepSimTrajectoryMap.hh"
13 #include "EDepSimHitSegment.hh"
14 #include "EDepSimException.hh"
15 #include "EDepSimUserRunAction.hh"
16 #include "EDepSimLog.hh"
17 
18 #include <G4ios.hh>
19 #include <G4RunManager.hh>
20 #include <G4Event.hh>
21 #include <G4Run.hh>
22 #include <G4PrimaryVertex.hh>
23 #include <G4PrimaryParticle.hh>
24 #include <G4StepStatus.hh>
25 #include <G4ProcessType.hh>
26 #include <G4EmProcessSubType.hh>
27 #include <G4UnitsTable.hh>
28 #include <G4ParticleTable.hh>
29 #include <G4SDManager.hh>
30 #include <G4HCtable.hh>
31 
32 #include <G4SystemOfUnits.hh>
33 #include <G4PhysicalConstants.hh>
34 
35 #include <memory>
36 
37 // Handle foraging the edep-sim information into convenience classes that are
38 // independent of geant4 and edep-sim internal dependencies. The classes are
39 // suitable for saving directly to root (and will be by default if this class
40 // isn't inherited). This class can be inherited, and the convenience objects
41 // can be accessed using specific getters. If this class is used directly,
42 // then it will create a simple tree that can be analyzed using root. The
43 // best way to access the tree is with the root interface to python (no
44 // headers needed), or by using ROOT TFile::MakeProject.
46  : G4VPersistencyManager(), fFilename("/dev/null"),
47  fLengthThreshold(10*mm),
48  fGammaThreshold(5*MeV), fNeutronThreshold(50*MeV),
49  fTrajectoryPointAccuracy(1.*mm), fTrajectoryPointDeposit(0*MeV),
50  fSaveAllPrimaryTrajectories(true) {
52 }
53 
54 // This is called by the G4RunManager during AnalyzeEvent.
57  delete fPersistencyMessenger;
58 }
59 
61  EDepSimSevere(" -- Open is not implimented for " << filename);
62  SetFilename(filename);
63  return false;
64 }
65 
66 /// Make sure the output file is closed.
68  EDepSimSevere(" -- Close is not implimented.");
69  return false;
70 }
71 
72 // This is called by the G4RunManager during AnalyzeEvent.
73 G4bool EDepSim::PersistencyManager::Store(const G4Event* anEvent) {
74  UpdateSummaries(anEvent);
75  return false;
76 }
77 
78 // This is called by the G4RunManager during AnalyzeEvent.
79 G4bool EDepSim::PersistencyManager::Store(const G4Run* aRun) {
80  if (!aRun) return false;
81  EDepSimSevere(" -- Run store called without a save method for "
82  << "GEANT4 run " << aRun->GetRunID());
83  return false;
84 }
85 
86 // This is called by the G4RunManager during AnalyzeEvent.
87 G4bool EDepSim::PersistencyManager::Store(const G4VPhysicalVolume* aWorld) {
88  if (!aWorld) return false;
89  EDepSimSevere(" -- Geometry store called without a save method for "
90  << aWorld->GetName());
91  return false;
92 }
93 
95  TPRegexp* bound = new TPRegexp(b.c_str());
96  fTrajectoryBoundaries.push_back(bound);
97 }
98 
101  r != fTrajectoryBoundaries.end();
102  ++r) {
103  delete (*r);
104  }
105  fTrajectoryBoundaries.clear();
106 }
107 
109  G4StepStatus status,
110  G4String currentVolume,
111  G4String prevVolume) {
112  if (status != fGeomBoundary) return false;
113  std::string particleInfo = ":" + g4Traj->GetParticleName();
114  if (std::abs(g4Traj->GetCharge())<0.1) particleInfo += ":neutral";
115  else particleInfo += ":charged";
116  std::string current = particleInfo + ":" + currentVolume;
117  std::string previous = particleInfo + ":" + prevVolume;
119  r != fTrajectoryBoundaries.end();
120  ++r) {
121  // Check if a watched volume is being entered.
122  if ((*r)->Match(current)>0 && (*r)->Match(previous)<1) {
123  EDepSimNamedDebug("boundary","Entering " << current);
124  return true;
125  }
126  // Check if a watched volume is being exited.
127  if ((*r)->Match(current)<1 && (*r)->Match(previous)>0) {
128  EDepSimNamedDebug("boundary","Exiting " << current);
129  return true;
130  }
131  }
132  return false;
133 }
134 
136 
137  const G4Run* runInfo = G4RunManager::GetRunManager()->GetCurrentRun();
138 
139  fEventSummary.RunId = runInfo->GetRunID();
140  fEventSummary.EventId = event->GetEventID();
141  EDepSimLog("Event Summary for run " << fEventSummary.RunId
142  << " event " << fEventSummary.EventId);
143 
144  // Summarize the trajectories first so that fTrackIdMap is filled.
145  MarkTrajectories(event);
146 
147  SummarizePrimaries(fEventSummary.Primaries,event->GetPrimaryVertex());
148  EDepSimLog(" Primaries " << fEventSummary.Primaries.size());
149 
151  EDepSimLog(" Trajectories " << fEventSummary.Trajectories.size());
152 
154  EDepSimLog(" Segment Detectors "
155  << fEventSummary.SegmentDetectors.size());
156 }
157 
159  std::vector<TG4PrimaryVertex>& dest,
160  const G4PrimaryVertex* src) {
161  dest.clear();
162 
163  if (!src) return;
164 
165  while (src) {
166  TG4PrimaryVertex vtx;
167 
168  vtx.Position.SetX(src->GetX0());
169  vtx.Position.SetY(src->GetY0());
170  vtx.Position.SetZ(src->GetZ0());
171  vtx.Position.SetT(src->GetT0());
172 
173  // Add the particles associated with the vertex to the summary.
174  for (int i=0; i< src->GetNumberOfParticle(); ++i) {
175  TG4PrimaryParticle prim;
176  G4PrimaryParticle *g4Prim = src->GetPrimary(i);
177  double E = 0.0;
178  if (g4Prim->GetG4code()) {
179  prim.Name = g4Prim->GetG4code()->GetParticleName();
180  E = pow(g4Prim->GetG4code()->GetPDGMass(),2);
181  }
182  else {
183  prim.Name = "unknown";
184  }
185  prim.PDGCode = g4Prim->GetPDGcode();
186  prim.TrackId = g4Prim->GetTrackID() - 1;
187  prim.Momentum.SetX(g4Prim->GetPx());
188  prim.Momentum.SetY(g4Prim->GetPy());
189  prim.Momentum.SetZ(g4Prim->GetPz());
190  E += pow(prim.Momentum.P(),2);
191  if (E>0) E = std::sqrt(E);
192  else E = 0;
193  prim.Momentum.SetE(E);
194  vtx.Particles.push_back(prim);
195  }
196 
197  // Check to see if there is anyu user information associated with the
198  // vertex.
199  EDepSim::VertexInfo* srcInfo
200  = dynamic_cast<EDepSim::VertexInfo*>(src->GetUserInformation());
201  if (srcInfo) {
202  vtx.GeneratorName = srcInfo->GetName();
203  vtx.Reaction = srcInfo->GetReaction();
204  vtx.Filename = srcInfo->GetFilename();
205  vtx.InteractionNumber = srcInfo->GetInteractionNumber();
206  vtx.CrossSection = srcInfo->GetCrossSection();
207  vtx.DiffCrossSection = srcInfo->GetDiffCrossSection();
208  vtx.Weight = srcInfo->GetWeight();
209  vtx.Probability = srcInfo->GetProbability();
210 
211  const G4PrimaryVertex* infoVertex
212  = srcInfo->GetInformationalVertex();
213  if (infoVertex) {
215  srcInfo->GetInformationalVertex());
216  }
217  }
218 
219  dest.push_back(vtx);
220  src = src->GetNext();
221  }
222 }
223 
226  const G4Event* event) {
227  dest.clear();
228  MarkTrajectories(event);
229 
230  // Build a map of the original G4 TrackID to the new relocated TrackId
231  // (not capitalization). This also uses the fact that maps are sorted as
232  // a hack to prevent writing a predicate to sort TG4Trajectories (because
233  // I'm lazy).
234  fTrackIdMap.clear();
235 
236  const G4TrajectoryContainer* trajectories = event->GetTrajectoryContainer();
237  if (!trajectories) {
238  EDepSimError("No trajectory container");
239  return;
240  }
241  if (!trajectories->GetVector()) {
242  EDepSimError("No trajectory vector in trajectory container");
243  return;
244  }
245 
246  int index = 0;
247  TG4TrajectoryContainer tempContainer;
248  for (TrajectoryVector::iterator t = trajectories->GetVector()->begin();
249  t != trajectories->GetVector()->end();
250  ++t) {
251  EDepSim::Trajectory* ndTraj = dynamic_cast<EDepSim::Trajectory*>(*t);
252 
253  // Check if the trajectory should be saved.
254  if (!ndTraj->SaveTrajectory()) continue;
255 
256  // Set the particle type information.
257  G4ParticleDefinition* part
258  = G4ParticleTable::GetParticleTable()->FindParticle(
259  ndTraj->GetParticleName());
260  if (!part) {
261  EDepSimError(std::string("EDepSim::RootPersistencyManager::")
262  + "No particle information for "
263  + ndTraj->GetParticleName());
264  }
265 
266  fTrackIdMap[ndTraj->GetTrackID()] = index++;
267 
268  TG4Trajectory traj;
269  traj.TrackId = ndTraj->GetTrackID();
270  traj.Name = ndTraj->GetParticleName();
271  traj.PDGCode = ndTraj->GetPDGEncoding();
272  traj.ParentId = ndTraj->GetParentID();
273  traj.InitialMomentum.SetXYZM(ndTraj->GetInitialMomentum().x(),
274  ndTraj->GetInitialMomentum().y(),
275  ndTraj->GetInitialMomentum().z(),
276  part->GetPDGMass());
277  CopyTrajectoryPoints(traj,ndTraj);
278  int throttle = 999999;
279  do {
280  if (traj.ParentId == 0) break;
281  EDepSim::Trajectory* pTraj
282  = dynamic_cast<EDepSim::Trajectory*>(
284  if (!pTraj) {
285  EDepSimError("Trajectory " << traj.ParentId << " does not exist");
286  throw;
287  break;
288  }
289  if (pTraj->SaveTrajectory()) break;
290  traj.ParentId = pTraj->GetParentID();
291  } while (--throttle > 0);
292  tempContainer.push_back(traj);
293  }
294 
295  // Reorder the trajectories using the sorted fTrackIdMap. This uses the
296  // fact that the map is going to have the right sort order.
297  for (TrackIdMap::iterator i = fTrackIdMap.begin();
298  i != fTrackIdMap.end(); ++i) {
299  dest.push_back(tempContainer[i->second]);
300  }
301 
302  // Now that the trajectories are reordered, reassign the mapping from the
303  // original ndTraj->GetTrackID() value to the index in the Trajectories
304  // vector.
305  index = 0;
306  for (TrackIdMap::iterator i = fTrackIdMap.begin();
307  i != fTrackIdMap.end(); ++i) {
308  i->second = index++;
309  }
310 
311  // Make double sure that TrackID zero maps to the non-existent -1.
312  fTrackIdMap[0] = -1;
313 
314  /// Rewrite the track ids so that they are consecutive.
316  t = dest.begin();
317  t != dest.end(); ++t) {
318  t->TrackId = fTrackIdMap[t->TrackId];
319  t->ParentId = fTrackIdMap[t->ParentId];
320  }
321 
322 }
323 
325  const G4TrajectoryContainer* trajectories = event->GetTrajectoryContainer();
326  if (!trajectories) {
327  EDepSimVerbose("No Trajectories ");
328  return;
329  }
330 
331  // Go through all of the trajectories and save:
332  //
333  // ** Trajectories from primary particles if
334  // 1) a daughter deposited energy in a sensitive detector
335  // 2) or, SaveAllPrimaryTrajectories() is true
336  //
337  // ** Trajectories created by a particle decay if
338  // 1) a daughter deposited energy in a sensitve detector
339  // 2) or, SaveAllPrimaryTrajectories() is true.
340  //
341  // ** Charged particle trajectories that pass through a sensitive
342  // detector.
343  //
344  // ** Gamma-rays and neutrons above a threshold which have daughters
345  // depositing energy in a sensitive detector.
346  //
347  for (TrajectoryVector::iterator t = trajectories->GetVector()->begin();
348  t != trajectories->GetVector()->end();
349  ++t) {
350  EDepSim::Trajectory* ndTraj = dynamic_cast<EDepSim::Trajectory*>(*t);
351  std::string particleName = ndTraj->GetParticleName();
352  std::string processName = ndTraj->GetProcessName();
353  double initialMomentum = ndTraj->GetInitialMomentum().mag();
354 
355  // Check if all primary particle trajectories should be saved. The
356  // primary particle should always be saved if it, or any of it's
357  // children, deposited energy in a sensitive detector. If the primary
358  // didn't deposit energy in a sensitive detector, then it will only be
359  // saved if SaveAllPrimaryTrajectories is true.
360  if (ndTraj->GetParentID() == 0) {
361  if (ndTraj->GetSDTotalEnergyDeposit()>1*eV
363  ndTraj->MarkTrajectory();
364  continue;
365  }
366  }
367 
368  // Don't save the neutrinos
369  if (particleName == "anti_nu_e") continue;
370  if (particleName == "anti_nu_mu") continue;
371  if (particleName == "anti_nu_tau") continue;
372  if (particleName == "nu_e") continue;
373  if (particleName == "nu_mu") continue;
374  if (particleName == "nu_tau") continue;
375 
376  // Save any decay product if it caused any energy deposit.
377  if (processName == "Decay") {
378  if (ndTraj->GetSDTotalEnergyDeposit()>1*eV
380  ndTraj->MarkTrajectory(false);
381  continue;
382  }
383  }
384 
385  // Save particles that produce charged track inside a sensitive
386  // detector. This doesn't automatically save, but the parents will be
387  // automatically considered for saving by the next bit of code.
388  if (ndTraj->GetSDLength() > GetLengthThreshold()) {
389  ndTraj->MarkTrajectory(false);
390  continue;
391  }
392 
393  // For the next part, only consider particles where the children have
394  // deposited energy in a sensitive detector.
395  if (ndTraj->GetSDTotalEnergyDeposit()<1*eV) {
396  continue;
397  }
398 
399  // Save higher energy gamma rays that have descendents depositing
400  // energy in a sensitive detector. This only affects secondary
401  // photons since primary photons are handled above.
402  if (particleName == "gamma" && initialMomentum > GetGammaThreshold()) {
403  ndTraj->MarkTrajectory(false);
404  continue;
405  }
406 
407  // Save higher energy neutrons that have descendents depositing energy
408  // in a sensitive detector. This only affects secondary neutrons
409  // since primary neutrons are controlled above.
410  if (particleName == "neutron"
411  && initialMomentum > GetNeutronThreshold()) {
412  ndTraj->MarkTrajectory(false);
413  continue;
414  }
415  }
416 
417  // Go through all of the event hit collections and make sure that all
418  // primary trajectories and trajectories contributing to a hit are saved.
419  // These are mostly a sub-set of the trajectories marked in the previous
420  // step, but there are a few corner cases where trajectories are not saved
421  // because of theshold issues.
422  G4HCofThisEvent* hitCollections = event->GetHCofThisEvent();
423  if (!hitCollections) return;
424  for (int i=0; i < hitCollections->GetNumberOfCollections(); ++i) {
425  G4VHitsCollection* g4Hits = hitCollections->GetHC(i);
426  if (g4Hits->GetSize()<1) continue;
427  for (unsigned int h=0; h<g4Hits->GetSize(); ++h) {
428  EDepSim::HitSegment* g4Hit
429  = dynamic_cast<EDepSim::HitSegment*>(g4Hits->GetHit(h));
430  if (!g4Hit) {
431  EDepSimError("Not a hit segment");
432  continue;
433  }
434 
435  // Make sure that the primary trajectory associated with this hit
436  // is saved. The primary trajectories are defined by
437  // EDepSim::TrajectoryMap::FindPrimaryId().
438  int primaryId = g4Hit->GetPrimaryTrajectoryId();
439  EDepSim::Trajectory* ndTraj
440  = dynamic_cast<EDepSim::Trajectory*>(
441  EDepSim::TrajectoryMap::Get(primaryId));
442  if (ndTraj) {
443  ndTraj->MarkTrajectory(false);
444  }
445  else {
446  EDepSimError("Primary trajectory not found");
447  }
448  }
449  }
450 }
451 
453  G4VTrajectory* g4Traj) {
454  std::vector<int> selected;
455 
456  // Choose the trajectory points that are going to be saved.
457  SelectTrajectoryPoints(selected, g4Traj);
458 
459  // Make sure the selected trajectory points are in order and unique.
460  std::sort(selected.begin(),selected.end());
461  selected.erase(std::unique(selected.begin(), selected.end()),
462  selected.end());
463 
464  ////////////////////////////////////
465  // Save the trajectories.
466  ////////////////////////////////////
467  for (std::vector<int>::iterator tp = selected.begin();
468  tp != selected.end(); ++tp) {
469  EDepSim::TrajectoryPoint* edepPoint
470  = dynamic_cast<EDepSim::TrajectoryPoint*>(g4Traj->GetPoint(*tp));
471  TG4TrajectoryPoint point;
472  point.Position.SetXYZT(edepPoint->GetPosition().x(),
473  edepPoint->GetPosition().y(),
474  edepPoint->GetPosition().z(),
475  edepPoint->GetTime());
476  point.Momentum.SetXYZ(edepPoint->GetMomentum().x(),
477  edepPoint->GetMomentum().y(),
478  edepPoint->GetMomentum().z());
479  point.Process = edepPoint->GetProcessType();
480  point.Subprocess = edepPoint->GetProcessSubType();
481  traj.Points.push_back(point);
482  }
483 }
484 
485 void
488  const G4Event* event) {
489  dest.clear();
490 
491  G4HCofThisEvent* HCofEvent = event->GetHCofThisEvent();
492  if (!HCofEvent) return;
493  G4SDManager *sdM = G4SDManager::GetSDMpointer();
494  G4HCtable *hcT = sdM->GetHCtable();
495  // Copy each of the hit categories into the output event.
496  for (int i=0; i<hcT->entries(); ++i) {
497  G4String SDname = hcT->GetSDname(i);
498  G4String HCname = hcT->GetHCname(i);
499  int HCId = sdM->GetCollectionID(SDname+"/"+HCname);
500  G4VHitsCollection* g4Hits = HCofEvent->GetHC(HCId);
501  if (g4Hits->GetSize()<1) continue;
502  EDepSim::HitSegment* hitSeg
503  = dynamic_cast<EDepSim::HitSegment*>(g4Hits->GetHit(0));
504  if (!hitSeg) continue;
505  SummarizeHitSegments(dest[SDname],g4Hits);
506  }
507 }
508 
509 void
511  G4VHitsCollection* g4Hits) {
512  dest.clear();
513 
514  EDepSim::HitSegment* g4Hit = dynamic_cast<EDepSim::HitSegment*>(g4Hits->GetHit(0));
515  if (!g4Hit) return;
516 
517  for (std::size_t h=0; h<g4Hits->GetSize(); ++h) {
518  g4Hit = dynamic_cast<EDepSim::HitSegment*>(g4Hits->GetHit(h));
521  hit.EnergyDeposit = g4Hit->GetEnergyDeposit();
522  hit.SecondaryDeposit = g4Hit->GetSecondaryDeposit();
523  hit.TrackLength = g4Hit->GetTrackLength();
525  hit.Start.SetXYZT(g4Hit->GetStart().x(),
526  g4Hit->GetStart().y(),
527  g4Hit->GetStart().z(),
528  g4Hit->GetStart().t());
529  hit.Stop.SetXYZT(g4Hit->GetStop().x(),
530  g4Hit->GetStop().y(),
531  g4Hit->GetStop().z(),
532  g4Hit->GetStop().t());
533  dest.push_back(hit);
534  }
535 }
536 
538  const std::vector<int>& src) {
539 
540  dest.clear();
541 
542  for (std::vector<int>::const_iterator c = src.begin();
543  c != src.end(); ++c) {
544  // Check each contributor to make sure that it is a valid
545  // trajectory. If it isn't in the trajectory map, then set it
546  // to a parent that is.
547  EDepSim::Trajectory* ndTraj
548  = dynamic_cast<EDepSim::Trajectory*>(
550  while (ndTraj && !ndTraj->SaveTrajectory()) {
551  ndTraj = dynamic_cast<EDepSim::Trajectory*>(
553  }
554  if (!ndTraj) {
555  dest.push_back(-1);
556  continue;
557  }
558  if (fTrackIdMap.find(ndTraj->GetTrackID()) != fTrackIdMap.end()) {
559  dest.push_back(fTrackIdMap[ndTraj->GetTrackID()]);
560  }
561  else {
562  EDepSimError("Contributor with unknown trajectory: "
563  << ndTraj->GetTrackID());
564  dest.push_back(-2);
565  }
566  }
567 
568  // Remove the duplicate entries.
569  std::sort(dest.begin(),dest.end());
570  dest.erase(std::unique(dest.begin(),dest.end()),dest.end());
571 }
572 
574  G4VTrajectory* g4Traj, int point1, int point2) {
575  if ((point2-point1) < 2) return 0;
576 
577  G4ThreeVector p1 = g4Traj->GetPoint(point1)->GetPosition();
578  G4ThreeVector p2 = g4Traj->GetPoint(point2)->GetPosition();
579 
580  if ( (p2-p1).mag() < fTrajectoryPointAccuracy) return 0;
581 
582  G4ThreeVector dir = (p2-p1).unit();
583 
584  int step = (point2-point1)/10 + 1;
585 
586  double approach = 0.0;
587  for (int p = point1+1; p<point2; p = p + step) {
588  p2 = g4Traj->GetPoint(p)->GetPosition() - p1;
589  approach = std::max((p2 - (dir*p2)*dir).mag(), approach);
590  }
591 
592  return approach;
593 }
594 
596  int point1, int point2) {
597 
598  int point3 = 0.5*(point1 + point2);
599  if (point3 <= point1) EDepSimThrow("Points too close to split");
600  if (point2 <= point3) EDepSimThrow("Points too close to split");
601  double bestAccuracy = FindTrajectoryAccuracy(g4Traj, point1, point3);
602 
603  bestAccuracy = std::max(FindTrajectoryAccuracy(g4Traj, point3, point2),
604  bestAccuracy);
605  for (int p = point1+1; p<point2-1; ++p) {
606  double a1 = FindTrajectoryAccuracy(g4Traj,point1, p);
607  double a2 = FindTrajectoryAccuracy(g4Traj,p, point2);
608  double accuracy = std::max(a1,a2);
609  if (accuracy < bestAccuracy) {
610  point3 = p;
611  bestAccuracy = accuracy;
612  }
613  }
614 
615  return point3;
616 }
617 
618 void
620  G4VTrajectory* g4Traj) {
621 
622  selected.clear();
623  if (g4Traj->GetPointEntries() < 1) {
624  EDepSimError("Trajectory with no points"
625  << " " << g4Traj->GetTrackID()
626  << " " << g4Traj->GetParentID()
627  << " " << g4Traj->GetParticleName());
628  return;
629  }
630 
631  ////////////////////////////////////
632  // Save the first point of the trajectory.
633  ////////////////////////////////////
634  selected.push_back(0);
635 
636  /////////////////////////////////////
637  // Save the last point of the trajectory.
638  /////////////////////////////////////
639  int lastIndex = g4Traj->GetPointEntries()-1;
640  if (lastIndex < 1) {
641  EDepSimError("Trajectory with one point"
642  << " " << g4Traj->GetTrackID()
643  << " " << g4Traj->GetParentID()
644  << " " << g4Traj->GetParticleName());
645  return;
646  }
647  selected.push_back(lastIndex);
648 
649  //////////////////////////////////////////////
650  // Short out trajectories that don't create any energy deposit in a
651  // sensitive detector. These are trajectories that disappear from the
652  // detector, so we don't need to record the extra trajectory points. The
653  // starting and stopping point of the particle are recorded in the
654  // trajectory.
655  //////////////////////////////////////////////
656  EDepSim::Trajectory* ndTraj = dynamic_cast<EDepSim::Trajectory*>(g4Traj);
657  if (ndTraj->GetSDTotalEnergyDeposit() < 1*eV) return;
658 
659  // Find the trajectory points where particles are entering and leaving the
660  // detectors.
661  EDepSim::TrajectoryPoint* edepPoint
662  = dynamic_cast<EDepSim::TrajectoryPoint*>(g4Traj->GetPoint(0));
663  G4String prevVolumeName = edepPoint->GetPhysVolName();
664  for (int tp = 1; tp < lastIndex; ++tp) {
665  edepPoint
666  = dynamic_cast<EDepSim::TrajectoryPoint*>(g4Traj->GetPoint(tp));
667  G4String volumeName = edepPoint->GetPhysVolName();
668  // Save the point on a boundary crossing for volumes where we are
669  // saving the entry and exit points.
670  if (SaveTrajectoryBoundary(g4Traj,edepPoint->GetStepStatus(),
671  volumeName,prevVolumeName)) {
672  selected.push_back(tp);
673  }
674  prevVolumeName = volumeName;
675  }
676 
677  // Save trajectory points where there is a "big" interaction.
678  for (int tp = 1; tp < lastIndex; ++tp) {
679  edepPoint
680  = dynamic_cast<EDepSim::TrajectoryPoint*>(g4Traj->GetPoint(tp));
681  // Just navigation....
682  if (edepPoint->GetProcessType() == fTransportation) continue;
683  // Not much energy deposit...
684  if (edepPoint->GetProcessDeposit() < GetTrajectoryPointDeposit())
685  continue;
686  // Don't save optical photons...
687  if (edepPoint->GetProcessType() == fOptical) continue;
688  // Not a physics step...
689  if (edepPoint->GetProcessType() == fGeneral) continue;
690  if (edepPoint->GetProcessType() == fUserDefined) continue;
691  // Don't save continuous ionization steps.
692  if (edepPoint->GetProcessType() == fElectromagnetic
693  && edepPoint->GetProcessSubType() == fIonisation) continue;
694  // Don't save multiple scattering.
695  if (edepPoint->GetProcessType() == fElectromagnetic
696  && edepPoint->GetProcessSubType() == fMultipleScattering) continue;
697  selected.push_back(tp);
698  }
699 
700  // Make sure there aren't any duplicates in the selected trajectory points.
701  std::sort(selected.begin(), selected.end());
702  selected.erase(std::unique(selected.begin(), selected.end()),
703  selected.end());
704 
705  if (ndTraj->GetSDEnergyDeposit() < 1*eV) return;
706 
707  double desiredAccuracy = GetTrajectoryPointAccuracy();
708  // Make sure that the trajectory accuracy stays in tolerance.
709  for (int throttle = 0; throttle < 1000; ++throttle) {
710  bool addPoint = false;
711  for (std::vector<int>::iterator p1 = selected.begin();
712  p1 != selected.end();
713  ++p1) {
714  std::vector<int>::iterator p2 = p1+1;
715  if (p2==selected.end()) break;
716  double trajectoryAccuracy = FindTrajectoryAccuracy(g4Traj,*p1,*p2);
717  if (trajectoryAccuracy <= desiredAccuracy) continue;
718  int split = SplitTrajectory(g4Traj,*p1,*p2);
719  if (split < 0) continue;
720  selected.push_back(split);
721  addPoint = true;
722  break;
723  }
724  std::sort(selected.begin(), selected.end());
725  selected.erase(std::unique(selected.begin(), selected.end()),
726  selected.end());
727  if (!addPoint) break;
728  }
729 }
Float_t TrackLength
#define EDepSimLog(outStream)
Definition: EDepSimLog.hh:717
TG4PrimaryVertexContainer Primaries
Definition: TG4Event.h:28
void SummarizeTrajectories(std::vector< TG4Trajectory > &trajectories, const G4Event *event)
Fill the trajectory container.
intermediate_table::iterator iterator
double GetProbability() const
Get the probability of the interaction.
std::string Filename
The name of the input file.
double GetTrackLength(void) const
#define EDepSimNamedDebug(trace, outStream)
Definition: EDepSimLog.hh:634
Float_t CrossSection
The cross section for the reaction that created this vertex.
TLorentzVector InitialMomentum
The initial momentum of the particle.
Definition: TG4Trajectory.h:82
void CopyTrajectoryPoints(TG4Trajectory &traj, G4VTrajectory *g4Traj)
int SplitTrajectory(G4VTrajectory *traj, int point1, int point2)
PrimaryParticles Particles
The PrimaryVertex points for this PrimaryVertex.
std::string string
Definition: nybbler.cc:12
G4int GetTrackID() const
Get the track id described by this trajectory.
double GetWeight() const
Get the weight of the vertex. This will be one if it&#39;s not filled.
TG4TrajectoryContainer Trajectories
Definition: TG4Event.h:35
G4double GetSDEnergyDeposit() const
Get the amount of energy deposited into a sensitive detector.
constexpr T pow(T x)
Definition: pow.h:72
bool SaveTrajectoryBoundary(G4VTrajectory *g4Traj, G4StepStatus status, G4String currentVolume, G4String prevVolume)
G4double GetTime() const
Get the time that the particle passed this trajectory point.
const G4String & GetReaction() const
Get the reaction code that created this vertex.
const G4ThreeVector GetMomentum() const
Get the 3-momentum of the particle at this trajectory point.
virtual void AddTrajectoryBoundary(const G4String &boundary)
std::vector< TG4Trajectory > TG4TrajectoryContainer
Definition: TG4Trajectory.h:13
int RunId
The run number.
Definition: TG4Event.h:16
std::map< std::string, TG4HitSegmentContainer > TG4HitSegmentDetectors
Definition: TG4HitSegment.h:18
intermediate_table::const_iterator const_iterator
#define EDepSimThrow(message)
Print an error message, and then throw an exception.
virtual bool GetSaveAllPrimaryTrajectories(void) const
static constexpr double MeV
Definition: Units.h:129
#define EDepSimSevere(outStream)
Definition: EDepSimLog.hh:539
string dir
G4ThreeVector GetInitialMomentum() const
Get the initial momentum of the particle that created this trajectory.
TLorentzVector Stop
The stopping position of the segment.
TrajectoryPoints Points
The trajectory points for this trajectory.
Definition: TG4Trajectory.h:54
void CopyHitContributors(std::vector< int > &dest, const std::vector< int > &src)
string filename
Definition: train.py:213
virtual G4double GetNeutronThreshold() const
Float_t EnergyDeposit
The total energy deposit in this hit.
Definition: TG4HitSegment.h:90
G4double GetSDLength() const
Get the total length of this trajectory that is in a sensitive detector.
std::string Name
The name of the particle.
TLorentzVector Momentum
The initial momentum of the particle.
std::vector< TG4HitSegment > TG4HitSegmentContainer
A container for the hit segment information.
Definition: TG4HitSegment.h:11
Int_t PDGCode
The PDG encoding of the particle.
Definition: TG4Trajectory.h:79
void SummarizeHitSegments(std::vector< TG4HitSegment > &segments, G4VHitsCollection *hits)
Fill a container of hit segments.
virtual double GetTrajectoryPointAccuracy(void) const
const G4LorentzVector & GetStart() const
The position of the starting point.
Int_t ParentId
The unique Id of the parent trajectory (The TrackId of the parent).
Definition: TG4Trajectory.h:73
#define a2
T abs(T value)
void MarkTrajectory(bool save=true)
Mark this trajectory as one that should be saved in the output.
static Entry * previous
Definition: pyscanner.cpp:1444
G4String GetParticleName() const
Get the particle name.
G4String GetProcessName() const
Get the interaction process that created the trajectory.
TG4HitSegmentDetectors SegmentDetectors
Definition: TG4Event.h:39
std::string Reaction
The reaction that created this vertex.
virtual double GetTrajectoryPointDeposit(void) const
double FindTrajectoryAccuracy(G4VTrajectory *traj, int point1, int point2)
static constexpr double eV
Definition: Units.h:127
TVector3 Momentum
The momentum of the particle at this trajectory point.
void SummarizeSegmentDetectors(TG4HitSegmentDetectors &segmentDetectors, const G4Event *event)
sensitive detector.
bool SaveTrajectory() const
Check if this trajectory should be saved.
void SelectTrajectoryPoints(std::vector< int > &selected, G4VTrajectory *g4Traj)
TG4Event fEventSummary
A summary of the primary vertices in the event.
p
Definition: test.py:223
G4int GetPDGEncoding() const
Get the PDG MC particle number for this particle.
int EventId
The event number.
Definition: TG4Event.h:19
static Entry * current
G4ProcessType GetProcessType() const
int GetInteractionNumber() const
Get the index of the interaction within the input interaction file.
G4double GetSDTotalEnergyDeposit() const
static int max(int a, int b)
#define EDepSimVerbose(outStream)
Definition: EDepSimLog.hh:787
const G4String & GetFilename()
Get the file that this vertex came from.
virtual G4double GetGammaThreshold() const
Float_t SecondaryDeposit
std::string Name
The name of the particle.
Definition: TG4Trajectory.h:76
double GetSecondaryDeposit(void) const
G4StepStatus GetStepStatus() const
int GetPrimaryTrajectoryId(void) const
virtual G4bool Open(G4String filename)
void SummarizePrimaries(std::vector< TG4PrimaryVertex > &primaries, const G4PrimaryVertex *event)
const G4LorentzVector & GetStop() const
The position of the stopping point.
#define EDepSimError(outStream)
Definition: EDepSimLog.hh:503
TG4PrimaryVertexContainer Informational
The informational vertices associated with this vertex.
double GetDiffCrossSection() const
virtual const G4PrimaryVertex * GetInformationalVertex(int i=0) const
std::string GeneratorName
The name of the generator that created this vertex.
Int_t PDGCode
The PDG code of the particle.
TLorentzVector Position
The initial position of the particle.
static constexpr double mm
Definition: Units.h:65
static bool * b
Definition: config.cpp:1043
Int_t TrackId
The TrackId of this trajectory.
Definition: TG4Trajectory.h:70
void split(std::string const &s, char c, OutIter dest)
Definition: split.h:35
G4String GetName() const
std::vector< int > & GetContributors()
Provide public access to the contributors for internal G4 classes.
double GetCrossSection() const
Get the cross section for the reaction that created this vertex.
void MarkTrajectories(const G4Event *event)
Mark the G4 Trajectories that should be saved.
Int_t InteractionNumber
The index (or identifier) of the interaction in the kinematics file.
Contributors Contrib
Definition: TG4HitSegment.h:70
virtual G4bool Close(void)
Make sure the output file is closed.
TLorentzVector Start
The starting position of the segment.
virtual G4bool Store(const G4Event *anEvent)
stores anEvent and the associated objects into database.
static G4VTrajectory * Get(int trackId)
Provide a map between the track id and the trajectory object.
EDepSim::PersistencyMessenger * fPersistencyMessenger
TLorentzVector Position
The position of this trajectory point.
double GetEnergyDeposit(void) const
Get the total energy deposited in this hit.
G4int GetParentID() const
std::vector< TPRegexp * > fTrajectoryBoundaries
Event finding and building.
virtual G4double GetLengthThreshold() const
Get the threshold for length in a sensitive detector.
void UpdateSummaries(const G4Event *event)
Update the event summary fields.
#define a1