Belle II Software development
SensitiveDetector.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <beast/csi/simulation/SensitiveDetector.h>
10#include <beast/csi/dataobjects/CsiSimHit.h>
11#include <beast/csi/dataobjects/CsiHit.h>
12#include <framework/dataobjects/EventMetaData.h>
13#include <beast/csi/geometry/CsiGeometryPar.h>
14#include <framework/datastore/StoreArray.h>
15#include <framework/datastore/RelationArray.h>
16#include <framework/datastore/StoreObjPtr.h>
17
18#include <G4Track.hh>
19#include <G4Step.hh>
20
21namespace Belle2 {
27 namespace csi {
28
30 Simulation::SensitiveDetectorBase("CsiSensitiveDetector", Const::invalidDetector)
31 {
32 m_hitNum = 0;
33 m_EvnetNumber = 0;
35 m_trackID = 0;
36 m_startTime = 0;
37 m_endTime = 0;
38 m_WightedTime = 0;
39 m_startEnergy = 0;
41 m_trackLength = 0;
42 iECLCell = 0;
43 TimeIndex = 0;
44 local_pos = 0;
45 T_ave = 0;
46 firstcall = 0;
47 m_phiID = 0;
48 m_thetaID = 0;
49 m_cellID = 0;
50
51
52 // CsiHitIndex: array of 18 (Nb. crystals) x 80 (max time index (tof [ns]/100))
53 for (int i = 0; i < 18; i++) {for (int j = 0; j < 80; j++) { CsiHitIndex[i][j] = 0;}}
54
55 //Make sure all collections are registered
56 StoreArray<MCParticle> mcParticles;
58 StoreArray<CsiHit> csiHits;
59
60 RelationArray simHitRel(mcParticles, simHits);
61 RelationArray csiHitRel(mcParticles, csiHits);
62
63 //Register all collections we want to modify and require those we want to use
64 mcParticles.registerInDataStore();
65 simHits.registerInDataStore();
66 csiHits.registerInDataStore();
67 simHitRel.registerInDataStore();
68 csiHitRel.registerInDataStore();
69
70 //Register the Relation so that the TrackIDs get replaced by the actual
71 //MCParticle indices after simulating the events. This is needed as
72 //secondary particles might not be stored so everything relating to those
73 //particles will be attributed to the last saved mother particle
76 }
77
79 {
80
81 }
82
83
84
85 bool SensitiveDetector::step(G4Step* aStep, G4TouchableHistory*)
86 {
87
88 const G4StepPoint& preStep = *aStep->GetPreStepPoint();
89 const G4StepPoint& postStep = * aStep->GetPostStepPoint();
90
91 G4Track& track = * aStep->GetTrack();
92 if (m_trackID != track.GetTrackID()) {
93 //TrackID changed, store track informations
94 m_trackID = track.GetTrackID();
95 //Get momentum
96 m_momentum = preStep.GetMomentum() ;
97 //Get energy
98 m_startEnergy = preStep.GetKineticEnergy() ;
99 //Reset energy deposit;
100 m_energyDeposit = 0;
101 //Reset Wighted Time;
102 m_WightedTime = 0;
103 //Reset m_WightedPos;
104 m_WightedPos.set(0, 0, 0);
105
106 }
107 //Update energy deposit
108 m_energyDeposit += aStep->GetTotalEnergyDeposit() ;
109
110 m_startTime = preStep.GetGlobalTime();
111 m_endTime = postStep.GetGlobalTime();
112 m_WightedTime += (m_startTime + m_endTime) / 2 * (aStep->GetTotalEnergyDeposit());
113
114 m_startPos = preStep.GetPosition();
115 m_endPos = postStep.GetPosition();
116
117 G4ThreeVector position(0.5 * (m_startPos + m_endPos));
118 m_WightedPos += position * (aStep->GetTotalEnergyDeposit());
119
120 //Save Hit if track leaves volume or is killed
121 if (track.GetNextVolume() != track.GetVolume() || track.GetTrackStatus() >= fStopAndKill) {
122 int pdgCode = track.GetDefinition()->GetPDGEncoding();
123
124 const G4VPhysicalVolume& v = * track.GetVolume();
125
126 //Column z of the rotation matrix R is the result of R * zhat.
127 // This is what we want since G4Trap are created aligned along z
128 G4RotationMatrix rotCell = * v.GetObjectRotation();
129 // G4RotationMatrix rotCell = * v.GetRotation();
130 G4ThreeVector vecCell = rotCell.colZ();
131 G4ThreeVector posCell = v.GetTranslation();
132
133 // Get layer ID
134 if (v.GetName().find("Crystal") != std::string::npos) {
136 m_cellID = csip->CsiVolNameToCellID(v.GetName());
137
138 double dTotalEnergy = 1.0 / m_energyDeposit; //avoid the error no match for 'operator/'
139 if (m_energyDeposit > 0.) {
140 saveSimHit(m_cellID, m_trackID, pdgCode, m_WightedTime * dTotalEnergy,
141 m_energyDeposit, m_momentum, m_WightedPos * dTotalEnergy,
142 posCell, vecCell);
143 }
144 }
145
146 //Reset TrackID
147 m_trackID = 0;
148 }
149
150 return true;
151 }
152
154 const G4int cellId,
155 const G4int trackID,
156 const G4int pid,
157 const G4double tof,
158 const G4double edep,
159 G4ThreeVector mom,
160 G4ThreeVector pos,
161 G4ThreeVector PosCell,
162 G4ThreeVector VecCell)
163 {
164
165 //Get the datastore arrays
166 StoreArray<MCParticle> mcParticles;
167 StoreArray<CsiSimHit> simHits;
168
169 RelationArray simHitRel(mcParticles, simHits);
170
171 // convert Hep3Vectors to ROOT::Math::XYZVector
172 ROOT::Math::XYZVector momentum(mom.getX(), mom.getY(), mom.getZ());
173 ROOT::Math::XYZVector position(pos.getX(), pos.getY(), pos.getZ());
174
175 //Append
176 simHits.appendNew(cellId, trackID, pid, tof / CLHEP::ns, edep / CLHEP::GeV,
177 momentum * (1.0 / CLHEP::GeV), position * (1.0 / CLHEP::cm));
178
179 int simhitNumber = simHits.getEntries() - 1;
180 simHitRel.add(trackID, simhitNumber);
181 B2DEBUG(150, "Saving CsiSimHit Number: " << simhitNumber);
182
183 // Store CsiHit: total energy deposited per hit, with average time.
184
185 // Old names:
186 /*
187 StoreArray<CsiHit> eclHitArray;
188 RelationArray eclHitRel(mcParticles, eclHitArray);
189 */
190
191 // New names:
192
193 StoreArray<CsiHit> csiHits;
194
195 RelationArray csiHitRel(mcParticles, csiHits);
196
197
198 StoreObjPtr<EventMetaData> eventMetaDataPtr;
199 int m_currentEvnetNumber = eventMetaDataPtr->getEvent();
200
201
202 if (firstcall == 0 || m_currentEvnetNumber != m_oldEvnetNumber) {
203 m_oldEvnetNumber = m_currentEvnetNumber;
204 for (int iCSICell = 0; iCSICell < 18; iCSICell++) {
205 for (int TimeInd = 0; TimeInd < 80; TimeInd++) {
206 CsiHitIndex[iCSICell][TimeInd] = -1;
207 }
208 }
209 firstcall++;
210 }
211
212
213 if (m_currentEvnetNumber == m_oldEvnetNumber) {
214 if ((tof / CLHEP::ns) < 8000) {
215 TimeIndex = (int)((tof / CLHEP::ns) / 100);
216
217 // local_pos is the distance between the hit and the PIN-diode end of the crystal.
218 local_pos = (15. - (pos - PosCell) * VecCell);
219
220 // From the ECL package T_ave = 6.05 + 0.0749 * local_pos - 0.00112 * local_pos * local_pos + (tof / CLHEP::ns) ;
221
222 //For CsI: we remove the offset (I hypothetize it if from photo-sensor delay)
223 // we remove the acceleration of the light
224 // we correct the velocity term using n_CsI=1.80
225 T_ave = 0.0600 * local_pos + (tof / CLHEP::ns) ;
226
227
228 double E_cell = (edep / CLHEP::GeV);
229 if (CsiHitIndex[cellId][TimeIndex] == -1) {
230 //m_hitNum = csiHits->GetLast() + 1;
231 //new(csiHits->AddrAt(m_hitNum)) CSIHit();
232 csiHits.appendNew();
233 m_hitNum = csiHits.getEntries() - 1;
234 CsiHitIndex[cellId][TimeIndex] = m_hitNum;
235 csiHits[m_hitNum]->setCellId(cellId);
236 csiHits[m_hitNum]->setEnergyDep(E_cell);
237 csiHits[m_hitNum]->setTimeAve(T_ave);
238 csiHits[m_hitNum]->setTimeVar(0);
239 csiHitRel.add(trackID, m_hitNum);
240
241 } else {
242 m_hitNum = CsiHitIndex[cellId][TimeIndex];
243 double old_edep = csiHits[m_hitNum]->getEnergyDep();
244 double old_TimeAve = csiHits[m_hitNum]->getTimeAve();
245 double old_TimeVar = csiHits[m_hitNum]->getTimeVar();
246
247 //double new_edep = E_cell + old_edep;
248 //double new_TimeAve = (old_edep * old_TimeAve + E_cell * T_ave) / new_edep;
249
250 double temp = E_cell + old_edep;
251 double delta = T_ave - old_TimeAve;
252 double R = delta * E_cell / temp;
253 double new_TimeAve = old_TimeAve + R;
254 double new_TimeVar = old_TimeVar + old_edep * delta * R;
255 double new_edep = temp;
256
257 //Algo from Wiki:
258 /*
259 for x, weight in dataWeightPairs: # Alternatively "for x, weight in zip(data, weights):"
260 temp = weight + sumweight
261 delta = x - mean
262 R = delta * weight / temp
263 mean = mean + R
264 M2 = M2 + sumweight * delta * R # Alternatively, "M2 = M2 + weight * delta * (x−mean)"
265 sumweight = temp
266
267 variance_n = M2/sumweight
268 */
269
270 csiHits[m_hitNum]->setEnergyDep(new_edep);
271 csiHits[m_hitNum]->setTimeAve(new_TimeAve);
272 csiHits[m_hitNum]->setTimeVar(new_TimeVar);
273 csiHitRel.add(trackID, m_hitNum);
274
275 }
276 }
277 } else { B2ERROR("m_currentEvnetNumber ERROR: m_oldEvnetNumber==m_oldEvnetNumber"); }
278
279 return (simhitNumber);
280 }//saveSimHit
281 } //csi namespace
283} //Belle2 namespace
double R
typedef autogenerated by FFTW
This class provides a set of constants for the framework.
Definition: Const.h:34
Low-level class to create/modify relations between StoreArrays.
Definition: RelationArray.h:62
void add(index_type from, index_type to, weight_type weight=1.0)
Add a new element to the relation.
static void registerMCParticleRelation(const std::string &name, RelationArray::EConsolidationAction ignoreAction=RelationArray::c_negativeWeight)
Register an relation involving MCParticles.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
The Class for CSI Geometry Parameters.
static CsiGeometryPar * Instance()
Static method to get a reference to the CsiGeometryPar instance.
int CsiVolNameToCellID(const G4String VolumeName)
Get Cell Id.
bool step(G4Step *aStep, G4TouchableHistory *) override
Step processing method.
int m_thetaID
The current phi ID in an event.
double m_energyDeposit
particle energy at the entrance in volume
int m_EvnetNumber
The current number of created hits in an event.
int TimeIndex
Hit Energy of StoreArray.
int m_trackID
The current number of created hits in an event.
int m_hitNum
members of SensitiveDetector
int firstcall
flight time to diode sensor
double T_ave
position alongthe vector of crystal axis
double local_pos
Hit Time of StoreArray.
G4ThreeVector m_momentum
Wighted step Position.
int m_cellID
The current theta ID in an event.
double m_startTime
momentum of track
int CsiHitIndex[18][80]
length of the track in the volume
int iECLCell
Hit index of StoreArray.
double m_trackLength
energy deposited in volume
G4ThreeVector m_WightedPos
Position of poststep.
int m_oldEvnetNumber
The current number of created hits in an event.
G4ThreeVector m_startPos
track id
int saveSimHit(const G4int cellId, const G4int trackID, const G4int pid, const G4double tof, const G4double edep, G4ThreeVector mom, G4ThreeVector pos, G4ThreeVector PosCell, G4ThreeVector VecCell)
Save ECLSimHits of the event into datastore.
G4ThreeVector m_endPos
Position of prestep.
int m_phiID
flag of first call
Abstract base class for different kinds of events.