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/claws/simulation/SensitiveDetector.h>
10 #include <framework/gearbox/Unit.h>
11 #include <G4Track.hh>
12 #include <G4Step.hh>
13 #include <G4Version.hh>
14 
15 #include <array>
16 
17 namespace Belle2 {
23  namespace claws {
24  namespace {
25  std::array<float, 3> vecToFloat(const G4ThreeVector& vec)
26  {
27  return std::array<float, 3> {{(float)vec.x(), (float)vec.y(), (float)vec.z()}};
28  }
29  }
30 
32  Simulation::SensitiveDetectorBase("CLAWSSensitiveDetector", Const::invalidDetector)
33  {
34  //Register all collections we want to modify and require those we want to use
36  m_simHits.registerInDataStore();
38 
39  //Register the Relation so that the TrackIDs get replaced by the actual
40  //MCParticle indices after simulating the events. This is needed as
41  //secondary particles might not be stored so everything relating to those
42  //particles will be attributed to the last saved mother particle
44 
45 #if G4VERSION_NUMBER < 1010
46  m_saturationEngine = new G4EmSaturation();
47 #else
48  m_saturationEngine = new G4EmSaturation(1); // verbose level
49 #endif
50  }
51 
52  bool SensitiveDetector::step(G4Step* step, G4TouchableHistory*)
53  {
54  //Get scintilator ladder and sensor number
55  const G4TouchableHistory* touchable = dynamic_cast<const G4TouchableHistory*>(step->GetPreStepPoint()->GetTouchable());
56  int ladderID = touchable->GetVolume(2)->GetCopyNo();
57  int sensorID = touchable->GetVolume(1)->GetCopyNo();
58 
59  //Get Track information
60  const G4Track& track = *step->GetTrack();
61  const int trackID = track.GetTrackID();
62  const int pdgCode = step->GetTrack()->GetDefinition()->GetPDGEncoding();
63  // deposited Energy in Geant4 Units
64  double depEnergy = step->GetTotalEnergyDeposit();
65  // get visible energy deposition
66  double visibleEnergy = m_saturationEngine->VisibleEnergyDeposition(
67  track.GetDefinition(),
68  track.GetMaterialCutsCouple(),
69  step->GetStepLength(),
70  depEnergy, 0.
71  );
72  // convert into Belle2 Units
73  depEnergy *= Unit::GeV / CLHEP::GeV;
74  visibleEnergy *= Unit::GeV / CLHEP::GeV;
75 
76  // get pre and post step point
77  const G4StepPoint& preStep = *step->GetPreStepPoint();
78  const G4StepPoint& postStep = *step->GetPostStepPoint();
79 
80  // check if this is the same sensor traversal, otherwise add one to the stack
81  if (m_tracks.empty() || (!m_tracks.top().check(trackID, ladderID, sensorID))) {
82  m_tracks.push(SensorTraversal());
83  }
84  // get the top of the stack
85  SensorTraversal& traversal = m_tracks.top();
86 
87  //If new track, remember values
88  if (traversal.getTrackID() == 0) {
89  bool isPrimary = Simulation::TrackInfo::getInfo(track).hasStatus(MCParticle::c_PrimaryParticle);
90  //Add start position
91  const G4ThreeVector preStepPos = preStep.GetPosition() / CLHEP::mm * Unit::mm;
92  const G4ThreeVector preStepMom = preStep.GetMomentum() / CLHEP::MeV * Unit::MeV;
93  const double time = preStep.GetGlobalTime() / CLHEP::ns * Unit::ns;
94  traversal.setInitial(trackID, ladderID, sensorID, pdgCode, isPrimary, preStepPos, preStepMom, time);
95  //Remember if the track came from the outside
96  if (preStep.GetStepStatus() == fGeomBoundary) traversal.hasEntered();
97  }
98 
99  //Add current step
100  const G4ThreeVector postStepPos = postStep.GetPosition() / CLHEP::mm * Unit::mm;
101  const double length = step->GetStepLength() / CLHEP::cm * Unit::cm;
102  traversal.add(postStepPos, depEnergy, visibleEnergy, length);
103 
104  //check if we are leaving the volume
105  bool isLeaving = (postStep.GetStepStatus() == fGeomBoundary);
106  if (isLeaving) traversal.hasLeft();
107 
108  //if we are leaving or the track is stopped, finish it
109  if (isLeaving || track.GetTrackStatus() >= fStopAndKill) {
110  bool contained = traversal.isContained();
111  bool saved = finishTrack();
112  //we mark all particles as important which created a hit and entered or left the volume
113  if (saved && !contained) {
114  Simulation::TrackInfo::getInfo(track).setIgnore(false);
115  }
116  return saved;
117  }
118  // Track not finished, return false right now
119  return false;
120  }
121 
123  {
124  SensorTraversal& traversal = m_tracks.top();
125  // ignore everything below 1eV
126  bool save = traversal.getDepEnergy() > Unit::eV;
127  if (save) {
128  auto momEntry = vecToFloat(traversal.getEntryMomentum());
129  auto posEntry = vecToFloat(traversal.getEntryPosition());
130  auto posExit = vecToFloat(traversal.getExitPosition());
131  int hitIndex = m_simHits.getEntries();
132  m_simHits.appendNew(
133  traversal.getLadderID(), traversal.getSensorID(),
134  traversal.getPDGCode(), traversal.getEntryTime(),
135  traversal.getDepEnergy(), traversal.getVisibleEnergy(),
136  traversal.getLength(), posEntry.data(), posExit.data(),
137  momEntry.data()
138  );
139  m_relMCSimHit.add(traversal.getTrackID(), hitIndex, traversal.getDepEnergy());
140  }
141  //No we just need to take care of the stack of traversals
142  if (m_tracks.size() == 1) {
143  //reuse traversal to keep memory if this is the first one
144  traversal.reset();
145  } else {
146  //this should only happen if the parent track got suspended. As this
147  //rarely happens in PXD we do not care for re-usability here
148  m_tracks.pop();
149  }
150  return save;
151  }
152  } //claw namespace
154 } //Belle2 namespace
This class provides a set of constants for the framework.
Definition: Const.h:34
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
@ c_negativeWeight
Flip the sign of the weight to become negative if the original element got re-attributed.
Definition: RelationArray.h:79
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.
static Payload getInfo(Carrier &obj)
Static function to just return UserInformation attached to the obj of type Carrier.
Definition: UserInfo.h:100
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
static const double mm
[millimeters]
Definition: Unit.h:70
static const double eV
[electronvolt]
Definition: Unit.h:112
static const double MeV
[megaelectronvolt]
Definition: Unit.h:114
static const double cm
Standard units with the value = 1.
Definition: Unit.h:47
static const double ns
Standard of [time].
Definition: Unit.h:48
static const double GeV
Standard of [energy, momentum, mass].
Definition: Unit.h:51
G4EmSaturation * m_saturationEngine
needed to call Birk's law
std::stack< SensorTraversal > m_tracks
Stack of tracks to keep track of particles.
StoreArray< CLAWSSimHit > m_simHits
store array of the SimHits
RelationArray m_relMCSimHit
relation array of the MCParticle -> SimHit relation
StoreArray< MCParticle > m_mcParticles
store array of the MCParticles
bool step(G4Step *step, G4TouchableHistory *) override
Step processing method.
Class to keep track of the traversal of the sensitive volume for one track.
int getPDGCode() const
get PDG code of the particle
int getLadderID() const
get the ladder ID
const G4ThreeVector & getEntryMomentum() const
get entry momentum
double getVisibleEnergy() const
get visible energy deposition
int getSensorID() const
get the sensor ID
const G4ThreeVector & getExitPosition() const
get exit position
void hasLeft()
indicate that the track left the current volume
const G4ThreeVector & getEntryPosition() const
get entry position
int getTrackID() const
get Geant4 trackID
double getEntryTime() const
get entry time
double getDepEnergy() const
get total energy deposition
void setInitial(int trackID, int ladderID, int sensorID, int pdgCode, bool primary, const G4ThreeVector &position, const G4ThreeVector &momentum, double time)
set initial values for a new track
void add(const G4ThreeVector &position, double depEnergy, double visibleEnergy, double length)
add a new step
void reset()
reset to be used again
void hasEntered()
indicate that the track originated outisde the current volume
bool isContained() const
return whether the track was contained in the volume so far
double getLength() const
get flight length so far
Abstract base class for different kinds of events.