Belle II Software  release-08-01-10
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 
21 namespace Belle2 {
27  namespace csi {
28 
30  Simulation::SensitiveDetectorBase("CsiSensitiveDetector", Const::invalidDetector)
31  {
32  m_hitNum = 0;
33  m_EvnetNumber = 0;
34  m_oldEvnetNumber = 0;
35  m_trackID = 0;
36  m_startTime = 0;
37  m_endTime = 0;
38  m_WightedTime = 0;
39  m_startEnergy = 0;
40  m_energyDeposit = 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;
57  StoreArray<CsiSimHit> simHits;
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
74  registerMCParticleRelation(simHitRel);
75  registerMCParticleRelation(csiHitRel);
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 TVector3
172  TVector3 momentum(mom.getX(), mom.getY(), mom.getZ());
173  TVector3 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.
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.