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/* Own header. */
10#include <klm/simulation/SensitiveDetector.h>
11
12/* KLM headers. */
13#include <klm/dataobjects/bklm/BKLMElementNumbers.h>
14#include <klm/dataobjects/KLMElementNumbers.h>
15#include <klm/eklm/geometry/GeometryData.h>
16
17/* Basf2 headers. */
18#include <simulation/background/BkgSensitiveDetector.h>
19
20/* Geant4 headers. */
21#include <G4Step.hh>
22#include <G4VProcess.hh>
23
24/* CLHEP headers. */
25#include <CLHEP/Units/SystemOfUnits.h>
26#include <CLHEP/Vector/ThreeVector.h>
27
28/* ROOT headers. */
29#include <TRandom3.h>
30
31using namespace Belle2::KLM;
32
34 const G4String& name, KLMSubdetectorNumber subdetector) :
35 SensitiveDetectorBase(name, Const::KLM),
36 m_Subdetector(subdetector),
37 m_FirstCall(true),
38 m_BkgSensitiveDetector(nullptr),
39 m_GeoPar(nullptr)
40{
41 if (!m_SimPar.isValid())
42 B2FATAL("BKLM simulation parameters are not available.");
43 m_HitTimeMax = m_SimPar->getHitTimeMax();
45 m_KLMSimHits.registerInDataStore();
48}
49
50bool SensitiveDetector::stepEKLM(G4Step* aStep, G4TouchableHistory* history)
51{
52 /* Once-only initializations (constructor is called too early for these). */
53 if (m_FirstCall) {
54 m_FirstCall = false;
55 const EKLM::GeometryData* geometryData = &EKLM::GeometryData::Instance();
56 if (geometryData->beamBackgroundStudy())
58 }
59
60 // Record a BeamBackHit for any particle
61 if (m_BkgSensitiveDetector != nullptr) {
62 m_BkgSensitiveDetector->step(aStep, history);
63 }
64
65 const int stripLevel = 1;
66 int section, layer, sector, plane, strip, stripGlobal;
67 HepGeom::Point3D<double> gpos, lpos;
68 G4TouchableHandle hist = aStep->GetPreStepPoint()->GetTouchableHandle();
69 section = hist->GetVolume(stripLevel + 6)->GetCopyNo();
70 layer = hist->GetVolume(stripLevel + 5)->GetCopyNo();
71 sector = hist->GetVolume(stripLevel + 4)->GetCopyNo();
72 plane = hist->GetVolume(stripLevel + 3)->GetCopyNo();
73 strip = hist->GetVolume(stripLevel)->GetCopyNo();
74 stripGlobal = m_ElementNumbers->stripNumber(
75 section, layer, sector, plane, strip);
76 const G4double eDep = aStep->GetTotalEnergyDeposit();
77 /* Do not record hits without deposited energy. */
78 if (eDep <= 0)
79 return false;
80 const G4Track& track = * aStep->GetTrack();
81 const G4double hitTime = track.GetGlobalTime();
82 if (hitTime > m_HitTimeMax)
83 return false;
84 /* Hit position. */
85 gpos = 0.5 * (aStep->GetPostStepPoint()->GetPosition() +
86 aStep->GetPreStepPoint()->GetPosition());
87 lpos = hist->GetHistory()->GetTopTransform().TransformPoint(gpos);
88 /* Create step hit and store in to DataStore */
89 KLMSimHit* hit = m_KLMSimHits.appendNew();
90 hit->setSubdetector(KLMElementNumbers::c_EKLM);
91 hit->setSection(section);
92 hit->setSector(sector);
93 hit->setLayer(layer);
94 hit->setPlane(plane);
95 hit->setStrip(strip);
96 hit->setLastStrip(strip);
97 // hit->setPropagationTime();
98 hit->setTime(hitTime);
99 hit->setEnergyDeposit(eDep);
100 CLHEP::Hep3Vector trackMomentum = track.GetMomentum();
101 hit->setMomentum(ROOT::Math::PxPyPzEVector(trackMomentum.x(), trackMomentum.y(),
102 trackMomentum.z(), track.GetTotalEnergy()));
103 hit->setTrackID(track.GetTrackID());
104 hit->setParentTrackID(track.GetParentID());
105 hit->setLocalPosition(lpos.x() / CLHEP::mm * Unit::mm,
106 lpos.y() / CLHEP::mm * Unit::mm,
107 lpos.z() / CLHEP::mm * Unit::mm);
108 hit->setPosition(gpos.x() / CLHEP::mm * Unit::mm,
109 gpos.y() / CLHEP::mm * Unit::mm,
110 gpos.z() / CLHEP::mm * Unit::mm);
111 hit->setPDG(track.GetDefinition()->GetPDGEncoding());
112 hit->setVolumeID(stripGlobal);
113 m_MCParticlesToKLMSimHits.add(track.GetTrackID(), hit->getArrayIndex());
114 return true;
115}
116
117G4bool SensitiveDetector::stepBKLM(G4Step* step, G4TouchableHistory* history)
118{
119 /* Once-only initializations (constructor is called too early for these). */
120 if (m_FirstCall) {
121 m_FirstCall = false;
125 if (!gRandom)
126 B2FATAL("gRandom is not initialized; please set up gRandom first");
127 }
128
129 // Record a BeamBackHit for any particle
130 if (m_BkgSensitiveDetector != nullptr) {
132 }
133
134 // It is not necessary to detect motion from one volume to another (or track death
135 // in the RPC gas volume). Experimentation shows that most tracks pass through the
136 // RPC gas volume in one step (although, on occasion, a delta ray will take a couple
137 // of short steps entirely within gas). Therefore, save every step in the gas
138 // instead of trying to find entry and exit points and then saving only the midpoint.
139 // Do same for scintillators.
140
141 double eDep = step->GetTotalEnergyDeposit() / CLHEP::MeV; // GEANT4: in MeV
142 G4StepPoint* preStep = step->GetPreStepPoint();
143 G4StepPoint* postStep = step->GetPostStepPoint();
144 G4Track* track = step->GetTrack();
145
146 // Record a KLMSimHit for a charged track that deposits some energy.
147 if ((eDep > 0.0) && (postStep->GetCharge() != 0.0)) {
148 const G4VTouchable* hist = preStep->GetTouchable();
149 int depth = hist->GetHistoryDepth();
150 if (depth < m_DepthPlane) {
151 B2WARNING("BKLM SensitiveDetector::step(): "
152 << LogVar("Touchable HistoryDepth", depth)
153 << LogVar("Should be at least", m_DepthPlane));
154 return false;
155 }
156 int plane = hist->GetCopyNumber(depth - m_DepthPlane);
157 int layer = hist->GetCopyNumber(depth - m_DepthLayer);
158 int sector = hist->GetCopyNumber(depth - m_DepthSector);
159 int section = hist->GetCopyNumber(depth - m_DepthSection);
160 double time = 0.5 * (preStep->GetGlobalTime() + postStep->GetGlobalTime()); // GEANT4: in ns
161 if (time > m_HitTimeMax)
162 return false;
163 const CLHEP::Hep3Vector globalPosition = 0.5 * (preStep->GetPosition() + postStep->GetPosition()) / CLHEP::cm; // in cm
164 const bklm::Module* m = m_GeoPar->findModule(section, sector, layer);
165 const CLHEP::Hep3Vector localPosition = m->globalToLocal(globalPosition);
166 int trackID = track->GetTrackID();
167 if (m->hasRPCs()) {
168 const CLHEP::Hep3Vector propagationTimes =
169 m->getPropagationTimes(localPosition);
170 int phiStripLower = -1;
171 int phiStripUpper = -1;
172 int zStripLower = -1;
173 int zStripUpper = -1;
174 convertHitToRPCStrips(localPosition, m, phiStripLower, phiStripUpper, zStripLower, zStripUpper);
175 if (zStripLower > 0) {
176 KLMSimHit* simHit = m_KLMSimHits.appendNew();
178 simHit->setSection(section);
179 simHit->setSector(sector);
180 simHit->setLayer(layer);
182 simHit->setStrip(zStripLower);
183 simHit->setLastStrip(zStripUpper);
184 simHit->setPropagationTime(propagationTimes.z());
185 simHit->setTime(time);
186 simHit->setEnergyDeposit(eDep);
187 simHit->setPosition(globalPosition.x(), globalPosition.y(),
188 globalPosition.z());
189 simHit->setPDG(track->GetDefinition()->GetPDGEncoding());
190 m_MCParticlesToKLMSimHits.add(trackID, simHit->getArrayIndex());
191 }
192 if (phiStripLower > 0) {
193 KLMSimHit* simHit = m_KLMSimHits.appendNew();
195 simHit->setSection(section);
196 simHit->setSector(sector);
197 simHit->setLayer(layer);
199 simHit->setStrip(phiStripLower);
200 simHit->setLastStrip(phiStripUpper);
201 simHit->setPropagationTime(propagationTimes.y());
202 simHit->setTime(time);
203 simHit->setEnergyDeposit(eDep);
204 simHit->setPosition(globalPosition.x(), globalPosition.y(),
205 globalPosition.z());
206 simHit->setPDG(track->GetDefinition()->GetPDGEncoding());
207 m_MCParticlesToKLMSimHits.add(trackID, simHit->getArrayIndex());
208 }
209 } else {
210 int scint = hist->GetCopyNumber(depth - m_DepthScintillator);
211 bool phiPlane = (plane == BKLM_INNER);
212 double propagationTime =
213 m->getPropagationTime(localPosition, scint, phiPlane);
214 KLMSimHit* simHit = m_KLMSimHits.appendNew();
216 simHit->setSection(section);
217 simHit->setSector(sector);
218 simHit->setLayer(layer);
219 if (phiPlane) {
221 } else {
223 }
224 simHit->setStrip(scint);
225 simHit->setLastStrip(scint);
226 simHit->setPropagationTime(propagationTime);
227 simHit->setTime(time);
228 simHit->setEnergyDeposit(eDep);
229 simHit->setPosition(globalPosition.x(), globalPosition.y(),
230 globalPosition.z());
231 simHit->setPDG(track->GetDefinition()->GetPDGEncoding());
232 m_MCParticlesToKLMSimHits.add(trackID, simHit->getArrayIndex());
233 }
234 return true;
235 }
236 return false;
237}
238
240 const CLHEP::Hep3Vector& localPosition, const bklm::Module* m,
241 int& phiStripLower, int& phiStripUpper, int& zStripLower, int& zStripUpper)
242{
243 double phiStripD = m->getPhiStrip(localPosition);
244 int phiStrip = int(phiStripD);
245 int pMin = m->getPhiStripMin();
246 if (phiStrip < pMin)
247 return;
248 int pMax = m->getPhiStripMax();
249 if (phiStrip > pMax)
250 return;
251
252 double zStripD = m->getZStrip(localPosition);
253 int zStrip = int(zStripD);
254 int zMin = m->getZStripMin();
255 if (zStrip < zMin)
256 return;
257 int zMax = m->getZStripMax();
258 if (zStrip > zMax)
259 return;
260
261 phiStripLower = phiStrip;
262 phiStripUpper = phiStrip;
263 zStripLower = zStrip;
264 zStripUpper = zStrip;
265 double phiStripDiv = fmod(phiStripD, 1.0) - 0.5; // between -0.5 and +0.5 within central phiStrip
266 double zStripDiv = fmod(zStripD, 1.0) - 0.5; // between -0.5 and +0.5 within central zStrip
267 int n = 0;
268 double rand = gRandom->Uniform();
269 for (n = 1; n < m_SimPar->getMaxMultiplicity(); ++n) {
270 if (m_SimPar->getPhiMultiplicityCDF(phiStripDiv, n) > rand)
271 break;
272 }
273 int nextStrip = (phiStripDiv > 0.0 ? 1 : -1);
274 while (--n > 0) {
275 phiStrip += nextStrip;
276 if ((phiStrip >= pMin) && (phiStrip <= pMax)) {
277 phiStripLower = std::min(phiStrip, phiStripLower);
278 phiStripUpper = std::max(phiStrip, phiStripUpper);
279 }
280 nextStrip = (nextStrip > 0 ? -(1 + nextStrip) : 1 - nextStrip);
281 }
282 rand = gRandom->Uniform();
283 for (n = 1; n < m_SimPar->getMaxMultiplicity(); ++n) {
284 if (m_SimPar->getZMultiplicityCDF(zStripDiv, n) > rand)
285 break;
286 }
287 nextStrip = (zStripDiv > 0.0 ? 1 : -1);
288 while (--n > 0) {
289 zStrip += nextStrip;
290 if ((zStrip >= zMin) && (zStrip <= zMax)) {
291 zStripLower = std::min(zStrip, zStripLower);
292 zStripUpper = std::max(zStrip, zStripUpper);
293 }
294 nextStrip = (nextStrip > 0 ? -(1 + nextStrip) : 1 - nextStrip);
295 }
296 return;
297}
298
299bool SensitiveDetector::step(G4Step* step, G4TouchableHistory* history)
300{
302 return stepBKLM(step, history);
303 else
304 return stepEKLM(step, history);
305}
The Class for BeamBackground Sensitive Detector.
This class provides a set of constants for the framework.
Definition: Const.h:34
int stripNumber(int section, int layer, int sector, int plane, int strip) const
Get strip number.
bool beamBackgroundStudy() const
Whether to perform beam-background study.
EKLM geometry data.
Definition: GeometryData.h:38
static const GeometryData & Instance(enum DataSource dataSource=c_Database, const GearDir *gearDir=nullptr)
Instantiation.
Definition: GeometryData.cc:33
KLM simulation hit.
Definition: KLMSimHit.h:31
void setPropagationTime(float propagationTime)
Set signal propagation time.
Definition: KLMSimHit.h:305
void setLastStrip(int lastStrip)
Set last strip number.
Definition: KLMSimHit.h:241
void setEnergyDeposit(float eDep)
Set EnergyDeposit.
Definition: KLMSimHit.h:269
void setSection(int Section)
Set section number.
Definition: KLMSimHit.h:143
void setStrip(int strip)
Set strip number.
Definition: KLMSimHit.h:223
void setTime(float time)
Set hit time.
Definition: KLMSimHit.h:287
void setSubdetector(int subdetector)
Set subdetector number.
Definition: KLMSimHit.h:125
void setPDG(int pdg)
Set the lund code of the (leading) particle.
Definition: KLMSimHit.h:62
void setSector(int sector)
Set sector number.
Definition: KLMSimHit.h:179
void setPlane(int plane)
Set plane number.
Definition: KLMSimHit.h:205
void setLayer(int layer)
Set layer number.
Definition: KLMSimHit.h:161
void setPosition(float x, float y, float z)
Set hit global position.
Definition: KLMSimHit.h:365
bool stepBKLM(G4Step *, G4TouchableHistory *)
Step in BKLM.
DBObjPtr< BKLMSimulationPar > m_SimPar
Simulation parameters (from DB).
bool stepEKLM(G4Step *, G4TouchableHistory *)
Step in EKLM.
SensitiveDetector(const G4String &name, KLMSubdetectorNumber subdetector)
Constructor.
bool m_FirstCall
Flag to enforce once-only initializations in Initialize().
KLMSubdetectorNumber m_Subdetector
Subdetector.
RelationArray m_MCParticlesToKLMSimHits
Relation array between MCPartices and KLMSimHits.
static constexpr int m_DepthSection
Section depth.
static constexpr int m_DepthSector
Sector depth.
bklm::GeometryPar * m_GeoPar
Pointer to GeometryPar singleton.
const EKLMElementNumbers * m_ElementNumbers
EKLM element numbers.
bool step(G4Step *, G4TouchableHistory *) override
Process each step and store KLMSimHits.
double m_HitTimeMax
Maximum permissible hit time based on overflow of LeCroy 1877 TDC.
BkgSensitiveDetector * m_BkgSensitiveDetector
Pointer to a sensitive-detector object used for beam-background steps.
static constexpr int m_DepthScintillator
Scintillator depth.
static constexpr int m_DepthPlane
Plane depth.
void convertHitToRPCStrips(const CLHEP::Hep3Vector &, const bklm::Module *, int &, int &, int &, int &)
Find the ranges of matching RPC strips for BKLM hits.
StoreArray< MCParticle > m_MCParticles
MC particles.
static constexpr int m_DepthLayer
Layer depth.
StoreArray< KLMSimHit > m_KLMSimHits
Simulation hits.
void add(index_type from, index_type to, weight_type weight=1.0)
Add a new element to the relation.
int getArrayIndex() const
Returns this object's array index (in StoreArray), or -1 if not found.
static void registerMCParticleRelation(const std::string &name, RelationArray::EConsolidationAction ignoreAction=RelationArray::c_negativeWeight)
Register an relation involving MCParticles.
bool isOptional(const std::string &name="")
Tell the DataStore about an optional input.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
static const double mm
[millimeters]
Definition: Unit.h:70
bool doBeamBackgroundStudy(void) const
Get the beam background study flag.
Definition: GeometryPar.h:51
const Module * findModule(int section, int sector, int layer) const
Get the pointer to the definition of a module.
Definition: GeometryPar.cc:721
static GeometryPar * instance(void)
Static method to get a reference to the singleton GeometryPar instance.
Definition: GeometryPar.cc:27
Define the geometry of a BKLM module Each sector [octant] contains Modules.
Definition: Module.h:76
Class to store variables with their name which were sent to the logging service.
uint16_t KLMSubdetectorNumber
Subdetector number.
bool step(G4Step *aStep, G4TouchableHistory *) override
Process each step and calculate variables defined in PXDSimHit.