EDepSimHitSegment.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////
2 // $Id: EDepSim::HitSegment.cc,v 1.14 2011/06/29 04:35:53 mcgrew Exp $
3 //
4 // Define an Off Axis Tracker Hit to hold information about particles that hit
5 // the Tracker sensitive detectors.
6 
8 #include "EDepSimHitSegment.hh"
10 #include "EDepSimLog.hh"
11 
12 #include <G4EventManager.hh>
13 #include <G4Event.hh>
14 #include <G4VTrajectory.hh>
15 #include <G4VTrajectoryPoint.hh>
16 #include <G4TrajectoryContainer.hh>
17 #include <G4TouchableHandle.hh>
18 #include <G4Step.hh>
19 
20 #include <G4UnitsTable.hh>
21 #include <G4VisAttributes.hh>
22 #include <G4VVisManager.hh>
23 #include <G4Polyline.hh>
24 #include <G4Color.hh>
25 
26 #include <G4SystemOfUnits.hh>
27 #include <G4PhysicalConstants.hh>
28 
29 #include <cmath>
30 #include <iostream>
31 #include <map>
32 #include <sstream>
33 
34 G4Allocator<EDepSim::HitSegment> edepHitSegmentAllocator;
35 
36 EDepSim::HitSegment::HitSegment(double maxSagitta, double maxLength)
37  : fMaxSagitta(maxSagitta), fMaxLength(maxLength),
38  fPrimaryId(0), fEnergyDeposit(0), fSecondaryDeposit(0), fTrackLength(0),
39  fStart(0,0,0,0), fStop(0,0,0,0) {
40  fPath.reserve(500);
41 }
42 
44  : G4VHit(rhs),
50  fStart(rhs.fStart), fStop(rhs.fStop) {}
51 
52 
54 
55 bool EDepSim::HitSegment::SameHit(G4Step* theStep) {
56  // Check that the hit and new step are in the same volume
57  G4TouchableHandle touchable
58  = theStep->GetPreStepPoint()->GetTouchableHandle();
59  if (fHitVolume != touchable) {
60  return false;
61  }
62 
63  int trackId = theStep->GetTrack()->GetTrackID();
64 
65  // Check that the hit and new step are close together.
66  double endToEnd
67  = (theStep->GetPostStepPoint()->GetPosition() - fPath.front()).mag();
68  if (endToEnd > fMaxLength) {
69  return false;
70  }
71 
72  const double epsilon = 0.01;
73  double deltaT = std::abs(theStep->GetPostStepPoint()->GetGlobalTime()
74  - fStop.t());
75  if (deltaT>epsilon) {
76  return false;
77  }
78 
79  if (fContributors.front() == trackId) {
80  // This is still the same track that initially created this hit.
81  // Check to see if the hit should be extended, or if we should start a
82  // new segment.
83  double sagitta = FindSagitta(theStep);
84  if (sagitta > fMaxSagitta) {
85  return false;
86  }
87  }
88  else {
89  // This is not the same track that started this hit, but check to see
90  // if it is a delta-ray that should be added to this segment.
91  double separation = FindSeparation(theStep);
92  if (separation > fMaxSagitta) {
93  return false;
94  }
95  }
96 
97  return true;
98 }
99 
100 int EDepSim::HitSegment::FindPrimaryId(G4Track *theTrack) {
101  return EDepSim::TrajectoryMap::FindPrimaryId(theTrack->GetTrackID());
102 }
103 
104 void EDepSim::HitSegment::AddStep(G4Step* theStep) {
105  G4TouchableHandle touchable
106  = theStep->GetPreStepPoint()->GetTouchableHandle();
107  G4ThreeVector prePos = theStep->GetPreStepPoint()->GetPosition();
108  G4ThreeVector postPos = theStep->GetPostStepPoint()->GetPosition();
109  G4StepStatus stepStatus = theStep->GetPostStepPoint()->GetStepStatus();
110  G4ParticleDefinition* particle = theStep->GetTrack()->GetDefinition();
111  double energyDeposit = theStep->GetTotalEnergyDeposit();
112  double stepLength = (prePos-postPos).mag();
113  double trackLength = theStep->GetStepLength();
114  double nonIonizingDeposit = theStep->GetNonIonizingEnergyDeposit();
115 
116  if (trackLength < 0.75*stepLength || trackLength < stepLength - 1*mm) {
117  EDepSimWarn("Track length shorter than step: "
118  << trackLength/mm << " mm "
119  << "<" << stepLength/mm << " mm");
120  EDepSimWarn(" Volume: "
121  << theStep->GetTrack()->GetVolume()->GetName());
122  EDepSimWarn(" Particle: " << particle->GetParticleName()
123  << " Depositing " << energyDeposit/MeV << " MeV");
124  EDepSimWarn(" Total Energy: "
125  << theStep->GetTrack()->GetTotalEnergy());
126  }
127 
128  trackLength = std::max(trackLength,stepLength);
129 
130  EDepSimTrace("Add Step with " << energyDeposit
131  << " in " << theStep->GetTrack()->GetVolume()->GetName());
132 
133  if (energyDeposit <= 0.) {
134  EDepSimWarn("EDepSim::HitSegment:: No energy deposited: " << energyDeposit);
135  }
136 
137  if (trackLength <= 0.) {
138  EDepSimWarn("EDepSim::HitSegment:: No track length: " << trackLength);
139  }
140 
141  // Occasionally, a neutral particle will produce a particle below
142  // threshold, and it will be recorded as generating the hit. All of the
143  // energy should be deposited at the stopping point of the track.
144  if (stepStatus == fPostStepDoItProc
145  && std::abs(particle->GetPDGCharge()) < 0.1) {
146  double origStep = stepLength;
147  G4ThreeVector dir = (postPos - prePos).unit();
148  stepLength = trackLength = std::min(0.5*mm,0.8*origStep);
149  prePos = postPos - stepLength*mm*dir;
150  EDepSimDebug("EDepSim::HitSegment:: " << particle->GetParticleName()
151  << " Deposited " << energyDeposit/MeV << " MeV");
152  EDepSimDebug(" Original step: " << origStep/mm << " mm");
153  EDepSimDebug(" New step: " << stepLength/mm << " mm");
154  }
155 
156  if (stepLength>fMaxLength || trackLength>fMaxLength) {
157  G4Track* trk = theStep->GetTrack();
158  EDepSimWarn("EDepSim::HitSegment:: Long step in "
159  << trk->GetVolume()->GetName());
160  EDepSimWarn(" Step Length is "
161  << stepLength/mm
162  << " mm and track length is "
163  << trackLength/mm << " mm");
164 
165  EDepSimWarn(" PID: " << particle->GetParticleName()
166  << " E: " << trk->GetTotalEnergy()/MeV << " MeV"
167  << " (kin: " << trk->GetKineticEnergy()/MeV << " MeV"
168  << " Deposit: "
169  << energyDeposit/MeV << "MeV"
170  << " Status: " << theStep->GetPreStepPoint()->GetStepStatus()
171  << " -> " << theStep->GetPostStepPoint()->GetStepStatus());
172 
173  const G4VProcess* proc = theStep->GetPostStepPoint()
174  ->GetProcessDefinedStep();
175  if (!proc) {
176  EDepSimWarn(" Step Limit Reached");
177  }
178  else {
179  EDepSimWarn(" Process: " << proc->GetProcessName()
180  <<"/"<< proc->GetProcessTypeName(proc->GetProcessType()));
181  }
182  }
183 
184  /// First make sure the step has been initialized.
185  if (!fHitVolume) {
186  fHitVolume = touchable;
187  fPrimaryId = FindPrimaryId(theStep->GetTrack());
188  fStart.set(prePos.x(),prePos.y(),prePos.z(),
189  theStep->GetPreStepPoint()->GetGlobalTime());
190  fPath.push_back(fStart.vect());
191  fStop.set(postPos.x(),postPos.y(),postPos.z(),
192  theStep->GetPostStepPoint()->GetGlobalTime());
193  fPath.push_back(fStop.vect());
194  fContributors.push_back(theStep->GetTrack()->GetTrackID());
195  }
196  else {
197  // Record the tracks that contribute to this hit.
198  int trackId = theStep->GetTrack()->GetTrackID();
199  if (trackId != fContributors.front()) fContributors.push_back(trackId);
200 
201  // Check to see if we have a new stopping point.
202  if (trackId == fContributors.front()
203  && (fPath.back()-prePos).mag()<0.1*mm) {
204  fStop.set(postPos.x(),postPos.y(),postPos.z(),
205  theStep->GetPostStepPoint()->GetGlobalTime());
206  fPath.push_back(G4ThreeVector(fStop.x(),fStop.y(),fStop.z()));
207  }
208  }
209 
210  fEnergyDeposit += energyDeposit;
211  fSecondaryDeposit += nonIonizingDeposit;
212  fTrackLength += trackLength;
213 
214  EDepSimDebug("EDepSim::HitSegment:: Deposit " << particle->GetParticleName()
215  << " adds " << energyDeposit/MeV << " MeV"
216  << " to " << fContributors.front()
217  << " w/ " << fEnergyDeposit
218  << " L " << trackLength
219  << " " << fTrackLength);
220 }
221 
222 double EDepSim::HitSegment::FindSagitta(G4Step* theStep) {
223  const G4ThreeVector& point = fPath.back();
224  const G4ThreeVector& preStep = theStep->GetPreStepPoint()->GetPosition();
225 
226  // Make sure that the step began at the end of the current segment. If
227  // not, return a ridiculously large sagitta.
228  if ((point-preStep).mag()>0.01*mm) return 10*m;
229 
230  const G4ThreeVector& postStep = theStep->GetPostStepPoint()->GetPosition();
231  // The proposed new segment direction;
232  G4ThreeVector newDir = (postStep-point).unit();
233 
234  // Initialize the maximum sagitta found.
235  double maxSagitta = 0.0;
236 
237  G4ThreeVector& front = fPath.front();
238 
239  // Loop over the existing path points and see if any would fall outside of
240  // the tolerance.
242  p != fPath.end();
243  ++p) {
244  G4ThreeVector delta = ((*p)-front);
245  double dist = (delta*newDir);
246  maxSagitta = std::max(maxSagitta,(delta - dist*newDir).mag());
247  if (maxSagitta > fMaxSagitta) break;
248  }
249 
250  return maxSagitta;
251 }
252 
253 double EDepSim::HitSegment::FindSeparation(G4Step* theStep) {
254  G4ThreeVector& front = fPath.front();
255  const G4ThreeVector& back = fPath.back();
256  const G4ThreeVector& preStep = theStep->GetPreStepPoint()->GetPosition();
257  const G4ThreeVector& postStep = theStep->GetPostStepPoint()->GetPosition();
258  G4ThreeVector dir = (back-front).unit();
259 
260  // Check to make sure the beginning of the new step isn't after the
261  // end of this segment.
262  if ((preStep-back)*dir>0.0) return 1000*m;
263 
264  // Check to make sure the beginning of the new step isn't before the
265  // beginning of this segment.
266  G4ThreeVector frontDelta = preStep-front;
267  double cosDelta = frontDelta*dir;
268  if (cosDelta<0.0) return 1000*m;
269 
270  // Find the distance from the segment center line to the initial point of
271  // the new step.
272  double s1 = (frontDelta - cosDelta*dir).mag();
273 
274 
275  // Find the distance from the segment center line to the final point of
276  // the new step.
277  G4ThreeVector rearDelta = postStep-front;
278  cosDelta = rearDelta*dir;
279  double s2 = (rearDelta - cosDelta*dir).mag();
280 
281  return std::max(s1,s2);
282 }
283 
285  G4VVisManager* pVVisManager = G4VVisManager::GetConcreteInstance();
286  if(pVVisManager) {
287  G4Polyline line;
288  line.push_back(G4Point3D(fStart.x(), fStart.y(), fStart.z()));
289  line.push_back(G4Point3D(fStop.x(), fStop.y(), fStop.z()));
290  G4Color color(1.,0.,1.);
291  G4VisAttributes attribs(color);
292  line.SetVisAttributes(attribs);
293  pVVisManager->Draw(line);
294  }
295 }
296 
298  std::cout << "Hit Energy Deposit: "
299  << G4BestUnit(fEnergyDeposit,"Energy")
300  << std::endl;
301 }
302 
304  return (fStop.vect()- fStart.vect()).mag();
305 }
G4Allocator< EDepSim::HitSegment > edepHitSegmentAllocator
intermediate_table::iterator iterator
double fEnergyDeposit
The total energy deposit in this hit.
HitSegment(double maxSagitta=1 *CLHEP::mm, double maxLength=5 *CLHEP::mm)
virtual double GetLength() const
static int FindPrimaryId(int trackId)
int fPrimaryId
The track id of the primary particle.
static constexpr double MeV
Definition: Units.h:129
string dir
std::vector< int > fContributors
virtual bool SameHit(G4Step *theStep)
T abs(T value)
G4LorentzVector fStart
The starting position of the segment.
double fMaxSagitta
The sagitta tolerance for the segment.
std::vector< G4ThreeVector > fPath
double fMaxLength
The maximum length between the start and stop points of the segment.
p
Definition: test.py:223
#define EDepSimTrace(outStream)
Definition: EDepSimLog.hh:653
#define EDepSimDebug(outStream)
Definition: EDepSimLog.hh:614
static int max(int a, int b)
double FindSeparation(G4Step *theStep)
int FindPrimaryId(G4Track *theTrack)
std::size_t color(std::string const &procname)
G4LorentzVector fStop
The stopping position of the segment.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
#define EDepSimWarn(outStream)
Definition: EDepSimLog.hh:576
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
void line(double t, double *p, double &x, double &y, double &z)
static constexpr double mm
Definition: Units.h:65
EDepSim::VolumeId fHitVolume
The G4 physical volume that contains the hit.
double FindSagitta(G4Step *theStep)
QTextStream & endl(QTextStream &s)
virtual void AddStep(G4Step *theStep)
Add the effects of a part of a step to this hit.