GEMC  1.8
Geant4 Monte-Carlo Framework
MSensitiveDetector.cc
Go to the documentation of this file.
1 // %%%%%%%%%%
2 // G4 headers
3 // %%%%%%%%%%
4 #include "G4SDManager.hh"
5 #include "G4UnitsTable.hh"
6 #include "G4ParticleTypes.hh"
7 
8 
9 // %%%%%%%%%%%%%
10 // gemc headers
11 // %%%%%%%%%%%%%
12 #include "identifier.h"
13 #include "MSensitiveDetector.h"
14 
15 
16 MSensitiveDetector::MSensitiveDetector(G4String name, gemc_opts opt):G4VSensitiveDetector(name), gemcOpt(opt), HCID(-1)
17 {
18  HCname = name;
19  collectionName.insert(HCname);
20  hitCollection = NULL;
22  minEnergy = SDID.minEnergy;
23 
24  hd_msg1 = gemcOpt.args["LOG_MSG"].args + " New Hit: <<< ";
25  hd_msg2 = gemcOpt.args["LOG_MSG"].args + " > ";
26  hd_msg3 = gemcOpt.args["LOG_MSG"].args + " End of Hit Collections >> ";
27  catch_v = gemcOpt.args["CATCH"].args;
28  HIT_VERBOSITY = gemcOpt.args["HIT_VERBOSITY"].arg;
29  RECORD_PASSBY = gemcOpt.args["RECORD_PASSBY"].arg;
30  RECORD_MIRROR = gemcOpt.args["RECORD_MIRRORS"].arg;
31 }
32 
34 
35 
36 void MSensitiveDetector::Initialize(G4HCofThisEvent* HCE)
37 {
38  Id_Set.clear();
39  hitCollection = new MHitCollection(HCname, collectionName[0]);
40  if(HCID < 0) HCID = G4SDManager::GetSDMpointer()->GetCollectionID(collectionName[0]);
41  HCE->AddHitsCollection( HCID, hitCollection );
42  ProcessHitRoutine = NULL;
43 }
44 
45 
46 
47 G4bool MSensitiveDetector::ProcessHits(G4Step* aStep, G4TouchableHistory*)
48 {
49  // First check on energy deposited
50  double depe = aStep->GetTotalEnergyDeposit();
51  // don't enter if RECORD_PASSBY is not set and it's not an optical photon
52  // Notice: a gamma will not directly release energy on a scintillator
53  // but will convert, and the pair will release energy
54  // so by default right now gammas are not recorded
55  // change this ?
56  if(depe == 0 && RECORD_PASSBY == 0 && aStep->GetTrack()->GetDefinition() != G4OpticalPhoton::OpticalPhotonDefinition()) return false;
57 
58  // do not record Mirrors unless specified
59  if(HCname == "Mirrors" && RECORD_MIRROR == 0) return false;
60 
61  G4Track *trk = aStep->GetTrack();
62  if(trk->GetDefinition()->GetParticleName().find("unknown") != string::npos) return false;
63 
64  G4StepPoint *prestep = aStep->GetPreStepPoint();
65  G4StepPoint *poststep = aStep->GetPostStepPoint();
66 
67  G4VTouchable* TH = (G4VTouchable*) aStep->GetPreStepPoint()->GetTouchable();
68 
72  double Dx = aStep->GetStepLength();
73  string name = TH->GetVolume(0)->GetName();
74  G4ThreeVector xyz = poststep->GetPosition();
75  G4ThreeVector Lxyz = prestep->GetTouchableHandle()->GetHistory()
76  ->GetTopTransform().TransformPoint(xyz);
77  G4ThreeVector vert = trk->GetVertexPosition();
78  double ctime = poststep->GetGlobalTime();
79  G4ThreeVector pxyz = prestep->GetMomentum();
80  double ene = prestep->GetTotalEnergy();
81  int tid = trk->GetTrackID();
82  int pid = trk->GetDefinition()->GetPDGEncoding();
83  int q = (int) trk->GetDefinition()->GetPDGCharge();
84  vector<identifier> VID = SetId(GetDetectorIdentifier(name), TH,
85  ctime, SDID.TimeWindow, tid);
86 
88  if(ProcessHitRoutine == NULL)
89  {
90  ProcessHitRoutine = GetMPHClass(MProcessHit_Map, GetDetectorHitType(name));
91  }
92 
93  if(!ProcessHitRoutine)
94  {
95  cout << endl << hd_msg2 << " Hit Process Routine <" << GetDetectorHitType(name) << "> not found. Exiting. " << endl;
96  exit(0);
97  }
98 
100  vector<identifier> PID = ProcessHitRoutine->ProcessID(VID, aStep, (*Hall_Map)[name], gemcOpt);
101  int singl_hit_size = VID.size();
102  int multi_hit_size = PID.size()/singl_hit_size;
103 
104  // splitting PIDs into an array
105  for(int mh = 0; mh<multi_hit_size; mh++)
106  {
107  vector<identifier> mhPID;
108 
109  for(int this_id = 0; this_id<singl_hit_size; this_id++)
110  {
111  identifier this_shit; // adding this single hit
112  this_shit.name = PID[this_id + mh*singl_hit_size].name;
113  this_shit.rule = PID[this_id + mh*singl_hit_size].rule;
114  this_shit.id = PID[this_id + mh*singl_hit_size].id;
115  this_shit.time = PID[this_id + mh*singl_hit_size].time;
116  this_shit.TimeWindow = PID[this_id + mh*singl_hit_size].TimeWindow;
117  this_shit.TrackId = PID[this_id + mh*singl_hit_size].TrackId;
118  this_shit.id_sharing = PID[this_id + mh*singl_hit_size].id_sharing;
119  mhPID.push_back(this_shit);
120  }
121 
122  if(HIT_VERBOSITY > 9 || name.find(catch_v) != string::npos)
123  cout << endl << hd_msg2 << " Before hit Process Identification:" << endl << VID
124  << hd_msg2 << " After: hit Process Identification:" << endl << mhPID << endl;
125 
127  if(HIT_VERBOSITY > 9) cout << endl << endl << " BEGIN SEARCH for same hit in Identifier Set..." << endl;
128 
129  set<vector<identifier> > :: iterator itid;
130  int hit_found = 0;
131 
132  for(itid = Id_Set.begin(); itid!= Id_Set.end() && !hit_found; itid++)
133  {
134  if(*itid == mhPID) hit_found=1;
135  if(HIT_VERBOSITY > 9 )
136  cout << " >> Current Step: " << mhPID
137  << " >> Set Hit Index: " << *itid
138  << (hit_found ? " >> FOUND at this Set Entry. " : " >> Not found yet. ") << endl;
139  }
140  if(HIT_VERBOSITY > 10) cout << " SEARCH ENDED." << (hit_found ? " 1 " : " No ") << "hit found in the Set." << endl << endl;
141 
142 
143 
144  // New Hit
145  if(!hit_found)
146  {
147  MHit *thisHit = new MHit();
148  thisHit->SetPos(xyz);
149  thisHit->SetLPos(Lxyz);
150  thisHit->SetVert(vert);
151  thisHit->SetTime(ctime);
152  thisHit->SetEdep(depe*mhPID[singl_hit_size-1].id_sharing);
153  thisHit->SetDx(Dx);
154  thisHit->SetMom(pxyz);
155  thisHit->SetE(ene);
156  thisHit->SetTrackId(tid);
157  thisHit->SetDetector((*Hall_Map)[name]);
158  thisHit->SetThreshold(SDID.minEnergy);
159  thisHit->SetId(mhPID);
160  thisHit->SetPID(pid);
161  thisHit->SetCharge(q);
162  hitCollection->insert(thisHit);
163  Id_Set.insert(mhPID);
164 
165  if(HIT_VERBOSITY > 6 || name.find(catch_v) != string::npos)
166  {
167  string pid = aStep->GetTrack()->GetDefinition()->GetParticleName();
168  cout << endl << hd_msg1 << endl
169  << " > This element was not hit yet in this event. Identity:" << endl << thisHit->GetId()
170  << " > Creating new hit by a E=" << ene/MeV << ", p=" << pxyz.mag()/MeV << " MeV " << pid
171  << ", track ID = " << tid << ", inside Hit Collection <" << HCname << ">." << endl
172  << " > Energy Deposited this step: " << depe/MeV << " MeV" << endl
173  << " > Time of this step: " << G4BestUnit(ctime, "Time") << endl
174  << " > Position of this step: " << xyz/cm << " cm" << endl
175  << " > Local Position in volume: " << Lxyz/cm << " cm" << endl;
176  }
177  }
178  else
179  {
180  // Adding hit info only if the poststeppint remains in the volume?
181  // if( aStep->GetPreStepPoint()->GetTouchable()->GetVolume(0) == aStep->GetPostStepPoint()->GetTouchable()->GetVolume(0))
182  {
183  MHit *thisHit = find_existing_hit(mhPID);
184  if(!thisHit)
185  {
186  cout << " Hit not found in collection but found in PID. This should never happen. Exiting." << endl;
187  exit(0);
188  }
189  else
190  {
191  thisHit->SetPos(xyz);
192  thisHit->SetLPos(Lxyz);
193  thisHit->SetVert(vert);
194  thisHit->SetTime(ctime);
195  thisHit->SetEdep(depe*mhPID[singl_hit_size-1].id_sharing);
196  thisHit->SetDx(Dx);
197  thisHit->SetMom(pxyz);
198  thisHit->SetE(ene);
199  thisHit->SetTrackId(tid);
200  thisHit->SetPID(pid);
201  thisHit->SetCharge(q);
202  thisHit->SetDetector((*Hall_Map)[name]);
203 
204  if(HIT_VERBOSITY > 6 || name.find(catch_v) != string::npos)
205  {
206  string pid = aStep->GetTrack()->GetDefinition()->GetParticleName();
207  cout << hd_msg2 << " Step Number " << thisHit->GetPos().size()
208  << " inside Identity: " << endl << thisHit->GetId()
209  << " > Adding hit inside Hit Collection <" << HCname << ">."
210  << " by a E=" << ene/MeV << ", p=" << pxyz.mag()/MeV << " MeV "
211  << pid << ", track ID = " << tid << endl
212  << " > Energy Deposited this step: " << depe/MeV << " MeV" << endl
213  << " > Time of this step: " << G4BestUnit(ctime, "Time")
214  << " is within this element Time Window of " << SDID.TimeWindow/ns << " ns. " << endl
215  << " > Position of this step: " << xyz/cm << " cm" << endl
216  << " > Local Position in volume: " << Lxyz/cm << " cm" << endl;
217  }
218  }
219  }
220  }
221 
222  }
223 
224 
225 
226 
227 
228 
229  return true;
230 }
231 
232 
233 void MSensitiveDetector::EndOfEvent(G4HCofThisEvent *HCE)
234 {
235  int nhitC = hitCollection->GetSize();
236  if(!nhitC) return;
237  MHit *aHit;
238  double Etot;
239  if(HIT_VERBOSITY > 2 && nhitC)
240  {
241  cout << endl;
242  cout << hd_msg3 << " Hit Collections <" << HCname << ">: " << nhitC << " hits." << endl;
243 
244  for (int i=0; i<nhitC; i++)
245  {
246  aHit = (*hitCollection)[i];
247  string vname = aHit->GetId()[aHit->GetId().size()-1].name;
248  if(HIT_VERBOSITY > 5 || vname.find(catch_v) != string::npos)
249  {
250  cout << hd_msg3 << " Hit " << i + 1 << " -- total number of steps this hit: " << aHit->GetPos().size() << endl;
251  cout << aHit->GetId();
252  Etot = 0;
253  for(unsigned int e=0; e<aHit->GetPos().size(); e++) Etot = Etot + aHit->GetEdep()[e];
254  cout << " Total energy deposited: " << Etot/MeV << " MeV" << endl;
255  }
256  }
257  }
258  delete ProcessHitRoutine; // not needed anymore
259 
260 }
261 
262 
264 {
265  for(unsigned int i=0; i<hitCollection->GetSize(); i++)
266  if((*hitCollection)[i]->GetId() == PID) return (*hitCollection)[i];
267 
268  return NULL;
269 }
270 
271 
272 
273 
274 
275 
276 
277 
278 
vector< identifier > SetId(vector< identifier > Iden, G4VTouchable *TH, double time, double TimeWindow, int TrackId)
Sets the ncopy ID accordingly to Geant4 Volumes copy number. Sets time, TimeWindow, TrackId.
Definition: identifier.cc:72
SDId get_SDId(string SD, gemc_opts gemcOpt)
Connects to DB and retrieve SDId.
SDId SDID
SDId used for identification.
virtual void EndOfEvent(G4HCofThisEvent *)
Virtual Method called at the end of each hit event.
MHit * find_existing_hit(vector< identifier >)
returns hit collection hit inside identifer
virtual void Initialize(G4HCofThisEvent *)
Virtual Method called at the beginning of each hit event.
void SetPos(G4ThreeVector xyz)
Definition: MHit.h:64
vector< identifier > GetId()
Definition: MHit.h:96
double TimeWindow
If two steps happens withing the same TimeWindow, they belong to the same Hit.
int id
manually assing ID. 0 if "ncopy" (will be set at hit processing time)
Definition: identifier.h:31
map< string, MPHB_Factory > * MProcessHit_Map
Hit Process Routine Factory Map.
G4THitsCollection< MHit > MHitCollection
Definition: MHit.h:134
string name
Name of the detector.
Definition: identifier.h:28
void SetDetector(detector det)
Definition: MHit.h:99
void SetTrackId(int tid)
Definition: MHit.h:92
map< string, detector > * Hall_Map
detector map
MSensitiveDetector(G4String, gemc_opts)
Constructor.
void SetEdep(double depe)
Definition: MHit.h:75
void SetPID(int pid)
Definition: MHit.h:106
double TimeWindow
Time Window. If abs(steptime - time) is smaller than TimeWindow, it&#39;s the same hit.
Definition: identifier.h:33
int TrackId
If Time Window is 0, it&#39;s a "flux" detector: if it&#39;s the same track, it&#39;s the same hit...
Definition: identifier.h:34
void SetMom(G4ThreeVector pxyz)
Definition: MHit.h:84
void SetDx(double Dx)
Definition: MHit.h:78
vector< G4ThreeVector > GetPos()
Definition: MHit.h:65
gemc_opts gemcOpt
gemc option class
MPHBaseClass * GetMPHClass(map< string, MPHB_Factory > *MProcessHit_Map, string HCname)
Return MPHBaseClass from the Hit Process Map.
Definition: MPHBaseClass.cc:8
virtual vector< identifier > ProcessID(vector< identifier >, G4Step *, detector, gemc_opts)=0
Virtual Method to calculate new identifier.
void SetE(double ene)
Definition: MHit.h:88
double minEnergy
Minimum energy of the hit to be recorded in the output stream.
void SetId(vector< identifier > iden)
Definition: MHit.h:97
Definition: MHit.h:29
G4String HCname
Sensitive Detector/Hit Collection Name.
void SetCharge(int Q)
Definition: MHit.h:110
map< string, opts > args
Options map.
Definition: usage.h:68
double id_sharing
A single step can generate multiple identifiers. This variable represent the percentage sharing of th...
Definition: identifier.h:35
void SetThreshold(double E)
Definition: MHit.h:103
string GetDetectorHitType(string name)
returns detector hitType
set< vector< identifier > > Id_Set
Identifier Set. Used to determine if a step is inside a new/existing element.
virtual G4bool ProcessHits(G4Step *, G4TouchableHistory *)
Virtual Method called for each step of each hit.
double time
Time of the first step.
Definition: identifier.h:32
void SetLPos(G4ThreeVector xyz)
Definition: MHit.h:68
vector< identifier > GetDetectorIdentifier(string name)
returns detector identity
void SetTime(double ctime)
Definition: MHit.h:81
vector< double > GetEdep()
Definition: MHit.h:76
void SetVert(G4ThreeVector ver)
Definition: MHit.h:71
string rule
"manual" or "ncopy"
Definition: identifier.h:30