Belle II Software  release-05-01-25
SensitiveDetector.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2010 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Leo Piilonen *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 /* Own header. */
12 #include <klm/bklm/simulation/SensitiveDetector.h>
13 
14 /* KLM headers. */
15 #include <klm/bklm/geometry/GeometryPar.h>
16 #include <klm/bklm/geometry/Module.h>
17 #include <klm/dataobjects/bklm/BKLMElementNumbers.h>
18 #include <klm/dataobjects/bklm/BKLMSimHit.h>
19 #include <klm/dataobjects/bklm/BKLMSimHitPosition.h>
20 #include <klm/dataobjects/bklm/BKLMStatus.h>
21 
22 /* Belle 2 headers. */
23 #include <framework/datastore/StoreArray.h>
24 #include <simulation/background/BkgSensitiveDetector.h>
25 #include <mdst/dataobjects/MCParticle.h>
26 
27 /* Geant4 headers. */
28 #include <G4Step.hh>
29 #include <G4VProcess.hh>
30 
31 /* CLHEP headers. */
32 #include <CLHEP/Units/SystemOfUnits.h>
33 #include <CLHEP/Vector/ThreeVector.h>
34 
35 /* ROOT headers. */
36 #include <TRandom3.h>
37 
38 #define DEPTH_SECTION 2
39 #define DEPTH_SECTOR 3
40 #define DEPTH_LAYER 5
41 #define DEPTH_PLANE 9
42 #define DEPTH_SCINT 10
43 
44 using namespace std;
45 using namespace Belle2::bklm;
46 
47 SensitiveDetector::SensitiveDetector(const G4String& name) :
48  SensitiveDetectorBase(name, Const::KLM),
49  m_FirstCall(true),
50  m_BkgSensitiveDetector(nullptr),
51  m_GeoPar(nullptr)
52 {
53  if (!m_SimPar.isValid())
54  B2FATAL("BKLM simulation parameters are not available.");
55  m_HitTimeMax = m_SimPar->getHitTimeMax();
56 
57  StoreArray<MCParticle> particles;
58  StoreArray<BKLMSimHit> simHits;
59  StoreArray<BKLMSimHitPosition> simHitPositions;
60  simHits.registerInDataStore();
61  simHitPositions.registerInDataStore();
62  particles.registerRelationTo(simHits);
63  simHitPositions.registerRelationTo(simHits);
64  RelationArray particleToSimHits(particles, simHits);
65  registerMCParticleRelation(particleToSimHits);
66 }
67 
68 //-----------------------------------------------------
69 // Method invoked for every step in sensitive detector
70 //-----------------------------------------------------
71 G4bool SensitiveDetector::step(G4Step* step, G4TouchableHistory* history)
72 {
73  // Once-only initializations (constructor is called too early for these)
74  if (m_FirstCall) {
75  m_FirstCall = false;
79  if (!m_SimPar.isValid())
80  B2FATAL("BKLM simulation parameters are not available.");
81  m_HitTimeMax = m_SimPar->getHitTimeMax();
82  if (!gRandom)
83  B2FATAL("gRandom is not initialized; please set up gRandom first");
84  }
85 
86  // Record a BeamBackHit for any particle
87  if (m_BkgSensitiveDetector != nullptr) {
88  m_BkgSensitiveDetector->step(step, history);
89  }
90 
91  StoreArray<BKLMSimHit> simHits;
92  StoreArray<BKLMSimHitPosition> simHitPositions;
93  StoreArray<MCParticle> particles;
94  RelationArray particleToSimHits(particles, simHits);
95 
96  // It is not necessary to detect motion from one volume to another (or track death
97  // in the RPC gas volume). Experimentation shows that most tracks pass through the
98  // RPC gas volume in one step (although, on occasion, a delta ray will take a couple
99  // of short steps entirely within gas). Therefore, save every step in the gas
100  // instead of trying to find entry and exit points and then saving only the midpoint.
101  // Do same for scintillators.
102 
103  double eDep = step->GetTotalEnergyDeposit() / CLHEP::MeV; // GEANT4: in MeV
104  G4StepPoint* preStep = step->GetPreStepPoint();
105  G4StepPoint* postStep = step->GetPostStepPoint();
106  G4Track* track = step->GetTrack();
107 
108  // Record a BKLMSimHit for a charged track that deposits some energy.
109  if ((eDep > 0.0) && (postStep->GetCharge() != 0.0)) {
110  const G4VTouchable* hist = preStep->GetTouchable();
111  int depth = hist->GetHistoryDepth();
112  if (depth < DEPTH_PLANE) {
113  B2WARNING("BKLM SensitiveDetector::step(): "
114  << LogVar("Touchable HistoryDepth", depth)
115  << LogVar(" should be at least", DEPTH_PLANE));
116  return false;
117  }
118  int plane = hist->GetCopyNumber(depth - DEPTH_PLANE);
119  int layer = hist->GetCopyNumber(depth - DEPTH_LAYER);
120  int sector = hist->GetCopyNumber(depth - DEPTH_SECTOR);
121  int section = hist->GetCopyNumber(depth - DEPTH_SECTION);
122  int moduleID =
123  int(BKLMElementNumbers::moduleNumber(section, sector, layer));
124  double time = 0.5 * (preStep->GetGlobalTime() + postStep->GetGlobalTime()); // GEANT4: in ns
125  if (time > m_HitTimeMax)
126  return false;
127  const CLHEP::Hep3Vector globalPosition = 0.5 * (preStep->GetPosition() + postStep->GetPosition()) / CLHEP::cm; // in cm
128  const Module* m = m_GeoPar->findModule(section, sector, layer);
129  const CLHEP::Hep3Vector localPosition = m->globalToLocal(globalPosition);
130  if (postStep->GetProcessDefinedStep() != 0) {
131  if (postStep->GetProcessDefinedStep()->GetProcessType() == fDecay) { moduleID |= BKLM_DECAYED_MASK; }
132  }
133  int trackID = track->GetTrackID();
134  if (m->hasRPCs()) {
135  const CLHEP::Hep3Vector propagationTimes =
136  m->getPropagationTimes(localPosition);
137  int phiStripLower = -1;
138  int phiStripUpper = -1;
139  int zStripLower = -1;
140  int zStripUpper = -1;
141  convertHitToRPCStrips(localPosition, m, phiStripLower, phiStripUpper, zStripLower, zStripUpper);
142  if (zStripLower > 0) {
143  int moduleIDZ = moduleID;
145  moduleIDZ, BKLMElementNumbers::c_ZPlane);
146  BKLMElementNumbers::setStripInModule(moduleIDZ, zStripLower);
147  BKLMStatus::setMaximalStrip(moduleIDZ, zStripUpper);
148  BKLMSimHit* simHit = simHits.appendNew(moduleIDZ, propagationTimes.z(), time, eDep);
149  particleToSimHits.add(trackID, simHits.getEntries() - 1);
150  BKLMSimHitPosition* simHitPosition = simHitPositions.appendNew(globalPosition.x(), globalPosition.y(), globalPosition.z());
151  simHitPosition->addRelationTo(simHit);
152  }
153  if (phiStripLower > 0) {
156  BKLMElementNumbers::setStripInModule(moduleID, phiStripLower);
157  BKLMStatus::setMaximalStrip(moduleID, phiStripUpper);
158  BKLMSimHit* simHit = simHits.appendNew(moduleID, propagationTimes.y(), time, eDep);
159  particleToSimHits.add(trackID, simHits.getEntries() - 1);
160  BKLMSimHitPosition* simHitPosition = simHitPositions.appendNew(globalPosition.x(), globalPosition.y(), globalPosition.z());
161  simHitPosition->addRelationTo(simHit);
162  }
163  } else {
164  int scint = hist->GetCopyNumber(depth - DEPTH_SCINT);
165  bool phiPlane = (plane == BKLM_INNER);
166  double propagationTime =
167  m->getPropagationTime(localPosition, scint, phiPlane);
168  BKLMElementNumbers::setStripInModule(moduleID, scint);
169  BKLMStatus::setMaximalStrip(moduleID, scint);
170  if (phiPlane) {
173  } else {
175  moduleID, BKLMElementNumbers::c_ZPlane);
176  }
177  BKLMSimHit* simHit = simHits.appendNew(moduleID, propagationTime, time,
178  eDep);
179  particleToSimHits.add(trackID, simHits.getEntries() - 1);
180  BKLMSimHitPosition* simHitPosition = simHitPositions.appendNew(globalPosition.x(), globalPosition.y(), globalPosition.z());
181  simHitPosition->addRelationTo(simHit);
182  }
183  return true;
184  }
185  return false;
186 }
187 
188 void SensitiveDetector::convertHitToRPCStrips(const CLHEP::Hep3Vector& localPosition, const Module* m,
189  int& phiStripLower, int& phiStripUpper, int& zStripLower, int& zStripUpper)
190 {
191  double phiStripD = m->getPhiStrip(localPosition);
192  int phiStrip = int(phiStripD);
193  int pMin = m->getPhiStripMin();
194  if (phiStrip < pMin) return;
195  int pMax = m->getPhiStripMax();
196  if (phiStrip > pMax) return;
197 
198  double zStripD = m->getZStrip(localPosition);
199  int zStrip = int(zStripD);
200  int zMin = m->getZStripMin();
201  if (zStrip < zMin) return;
202  int zMax = m->getZStripMax();
203  if (zStrip > zMax) return;
204 
205  phiStripLower = phiStrip;
206  phiStripUpper = phiStrip;
207  zStripLower = zStrip;
208  zStripUpper = zStrip;
209  double phiStripDiv = fmod(phiStripD, 1.0) - 0.5; // between -0.5 and +0.5 within central phiStrip
210  double zStripDiv = fmod(zStripD, 1.0) - 0.5; // between -0.5 and +0.5 within central zStrip
211  int n = 0;
212  double rand = gRandom->Uniform();
213  for (n = 1; n < m_SimPar->getMaxMultiplicity(); ++n) {
214  if (m_SimPar->getPhiMultiplicityCDF(phiStripDiv, n) > rand) break;
215  }
216  int nextStrip = (phiStripDiv > 0.0 ? 1 : -1);
217  while (--n > 0) {
218  phiStrip += nextStrip;
219  if ((phiStrip >= pMin) && (phiStrip <= pMax)) {
220  phiStripLower = min(phiStrip, phiStripLower);
221  phiStripUpper = max(phiStrip, phiStripUpper);
222  }
223  nextStrip = (nextStrip > 0 ? -(1 + nextStrip) : 1 - nextStrip);
224  }
225  rand = gRandom->Uniform();
226  for (n = 1; n < m_SimPar->getMaxMultiplicity(); ++n) {
227  if (m_SimPar->getZMultiplicityCDF(zStripDiv, n) > rand) break;
228  }
229  nextStrip = (zStripDiv > 0.0 ? 1 : -1);
230  while (--n > 0) {
231  zStrip += nextStrip;
232  if ((zStrip >= zMin) && (zStrip <= zMax)) {
233  zStripLower = min(zStrip, zStripLower);
234  zStripUpper = max(zStrip, zStripUpper);
235  }
236  nextStrip = (nextStrip > 0 ? -(1 + nextStrip) : 1 - nextStrip);
237  }
238  return;
239 }
Belle2::StoreArray::appendNew
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:256
Belle2::RelationArray
Low-level class to create/modify relations between StoreArrays.
Definition: RelationArray.h:72
Belle2::BKLMStatus::setMaximalStrip
static void setMaximalStrip(int &module, int strip)
Set maximal strip number.
Definition: BKLMStatus.h:95
Belle2::StoreArray::registerRelationTo
bool registerRelationTo(const StoreArray< TO > &toArray, DataStore::EDurability durability=DataStore::c_Event, DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut, const std::string &namedRelation="") const
Register a relation to the given StoreArray.
Definition: StoreArray.h:150
Belle2::bklm::SensitiveDetector::m_FirstCall
bool m_FirstCall
Flag to enforce once-only initializations in Initialize()
Definition: SensitiveDetector.h:64
Belle2::bklm::SensitiveDetector::m_GeoPar
GeometryPar * m_GeoPar
Pointer to GeometryPar singleton.
Definition: SensitiveDetector.h:73
Belle2::bklm::SensitiveDetector::m_SimPar
DBObjPtr< BKLMSimulationPar > m_SimPar
Simulation parameters (from DB)
Definition: SensitiveDetector.h:76
Belle2::BKLMElementNumbers::c_ZPlane
@ c_ZPlane
Z.
Definition: BKLMElementNumbers.h:81
Belle2::RelationsInterface::addRelationTo
void addRelationTo(const RelationsInterface< BASE > *object, float weight=1.0, const std::string &namedRelation="") const
Add a relation from this object to another object (with caching).
Definition: RelationsObject.h:144
Belle2::Simulation::SensitiveDetectorBase::registerMCParticleRelation
static void registerMCParticleRelation(const std::string &name, RelationArray::EConsolidationAction ignoreAction=RelationArray::c_negativeWeight)
Register an relation involving MCParticles.
Definition: SensitiveDetectorBase.cc:24
Belle2::BKLMElementNumbers::setPlaneInModule
static void setPlaneInModule(int &module, int plane)
Set plane number in module identifier.
Definition: BKLMElementNumbers.h:364
Belle2::bklm::Module
Define the geometry of a BKLM module Each sector [octant] contains Modules.
Definition: Module.h:86
Belle2::bklm::SensitiveDetector::m_HitTimeMax
double m_HitTimeMax
maximum permissible hit time (based on overflow of LeCroy 1877 TDC)
Definition: SensitiveDetector.h:67
Belle2::bklm::SensitiveDetector::step
bool step(G4Step *, G4TouchableHistory *) override
Process each step in the BKLM.
Definition: SensitiveDetector.cc:71
Belle2::BKLMSimHitPosition
Store one simulation hit's global position as a ROOT object.
Definition: BKLMSimHitPosition.h:34
Belle2::bklm::GeometryPar::instance
static GeometryPar * instance(void)
Static method to get a reference to the singleton GeometryPar instance.
Definition: GeometryPar.cc:30
LogVar
Class to store variables with their name which were sent to the logging service.
Definition: LogVariableStream.h:24
Belle2::BkgSensitiveDetector::step
bool step(G4Step *aStep, G4TouchableHistory *) override
Process each step and calculate variables defined in PXDSimHit.
Definition: BkgSensitiveDetector.cc:74
Belle2::bklm::GeometryPar::getBkgSensitiveDetector
BkgSensitiveDetector * getBkgSensitiveDetector(void) const
Get the beam background study flag.
Definition: GeometryPar.h:68
Belle2::RelationArray::add
void add(index_type from, index_type to, weight_type weight=1.0)
Add a new element to the relation.
Definition: RelationArray.h:291
Belle2::bklm::SensitiveDetector::convertHitToRPCStrips
void convertHitToRPCStrips(const CLHEP::Hep3Vector &, const Module *, int &, int &, int &, int &)
Find the ranges of matching RPC strips for each simulated hit.
Definition: SensitiveDetector.cc:188
Belle2::bklm::SensitiveDetector::m_BkgSensitiveDetector
BkgSensitiveDetector * m_BkgSensitiveDetector
Pointer to a sensitive-detector object used for beam-background steps.
Definition: SensitiveDetector.h:70
Belle2::BKLMSimHit
Store one simulation hit as a ROOT object.
Definition: BKLMSimHit.h:35
Belle2::StoreArray< MCParticle >
Belle2::Const
This class provides a set of constants for the framework.
Definition: Const.h:36
Belle2::bklm::GeometryPar::doBeamBackgroundStudy
bool doBeamBackgroundStudy(void) const
Get the beam background study flag.
Definition: GeometryPar.h:62
Belle2::bklm::GeometryPar::findModule
const Module * findModule(int section, int sector, int layer) const
Get the pointer to the definition of a module.
Definition: GeometryPar.cc:716
Belle2::StoreArray::getEntries
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:226
Belle2::BKLMElementNumbers::setStripInModule
static void setStripInModule(int &module, int strip)
Set strip number in module identifier.
Definition: BKLMElementNumbers.h:374
Belle2::BKLMElementNumbers::c_PhiPlane
@ c_PhiPlane
Phi.
Definition: BKLMElementNumbers.h:84
Belle2::BKLMElementNumbers::moduleNumber
static uint16_t moduleNumber(int section, int sector, int layer, bool fatalError=true)
Get module number.
Definition: BKLMElementNumbers.cc:71