Belle II Software  release-08-01-10
SensitivePMT.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 <top/simulation/SensitivePMT.h>
10 
11 #include <simulation/kernel/UserInfo.h>
12 #include <G4Step.hh>
13 #include <G4Track.hh>
14 #include <G4UnitsTable.hh>
15 #include <G4ParticleDefinition.hh>
16 #include <G4ParticleTypes.hh>
17 
18 #include <framework/logging/Logger.h>
19 #include <framework/gearbox/Unit.h>
20 
21 #include <Math/Vector3D.h>
22 #include <Math/Point3D.h>
23 #include <TRandom.h>
24 
25 using namespace std;
26 
27 namespace Belle2 {
32  namespace TOP {
33 
34  SensitivePMT::SensitivePMT():
35  Simulation::SensitiveDetectorBase("TOP", Const::TOP)
36  {
37 
38  m_simHits.registerInDataStore();
40 
41  m_simPhotons.registerInDataStore(DataStore::c_DontWriteOut);
42  m_simHits.registerRelationTo(m_simPhotons, DataStore::c_Event,
44 
46 
47  }
48 
49 
50  G4bool SensitivePMT::step(G4Step* aStep, G4TouchableHistory*)
51  {
52  // photon track
53  G4Track& photon = *aStep->GetTrack();
54 
55  // check if the track is an optical photon
56  if (photon.GetDefinition() != G4OpticalPhoton::OpticalPhotonDefinition()) return false;
57 
58  // photon energy in [eV]
59  double energy = photon.GetKineticEnergy() * Unit::MeV / Unit::eV;
60 
61  // pmt and module ID
62  int pmtID = photon.GetTouchableHandle()->GetReplicaNumber(m_pmtReplicaDepth);
63  int moduleID = photon.GetTouchableHandle()->GetReplicaNumber(m_moduleReplicaDepth);
64 
65  // hit position in local frame, converted to Basf units
66  G4ThreeVector localPosition = photon.GetTouchableHandle()->GetHistory()->GetTopTransform().TransformPoint(photon.GetPosition());
67  double xLocal = localPosition.x() * Unit::mm;
68  double yLocal = localPosition.y() * Unit::mm;
69 
70  // apply quantum efficiency if not yet done
71  bool applyQE = true;
72  double fraction = 1;
73  auto* info = dynamic_cast<Simulation::TrackInfo*>(photon.GetUserInformation());
74  if (info) {
75  applyQE = info->getStatus() < 3;
76  fraction = info->getFraction();
77  }
78  if (applyQE) {
79  double qeffi = m_topgp->getPMTEfficiency(energy, moduleID, pmtID, xLocal, yLocal);
80  if (qeffi == 0 or gRandom->Uniform() * fraction > qeffi) {
81  photon.SetTrackStatus(fStopAndKill);
82  return false;
83  }
84  info->setStatus(3);
85  info->setFraction(qeffi);
86  }
87 
88  // photon at detection
89  const G4ThreeVector& g_detPoint = photon.GetPosition();
90  const G4ThreeVector& g_detMomDir = photon.GetMomentumDirection();
91  ROOT::Math::XYZPoint detPoint(g_detPoint.x(), g_detPoint.y(), g_detPoint.z());
92  ROOT::Math::XYZVector detMomDir(g_detMomDir.x(), g_detMomDir.y(), g_detMomDir.z());
93  double detTime = photon.GetGlobalTime();
94  double length = photon.GetTrackLength();
95 
96  // photon at emission
97  const G4ThreeVector& g_emiPoint = photon.GetVertexPosition();
98  const G4ThreeVector& g_emiMomDir = photon.GetVertexMomentumDirection();
99  ROOT::Math::XYZPoint emiPoint(g_emiPoint.x(), g_emiPoint.y(), g_emiPoint.z());
100  ROOT::Math::XYZVector emiMomDir(g_emiMomDir.x(), g_emiMomDir.y(), g_emiMomDir.z());
101  double emiTime = photon.GetGlobalTime() - photon.GetLocalTime();
102 
103  // convert to basf2 units
104  emiPoint = emiPoint * Unit::mm;
105  detPoint = detPoint * Unit::mm;
106  length = length * Unit::mm;
107 
108  // write to store arrays; add relations
109 
110  auto* simHit = m_simHits.appendNew(moduleID, pmtID, xLocal, yLocal,
111  detTime, energy);
112 
113  int parentID = photon.GetParentID();
114  if (parentID == 0) parentID = photon.GetTrackID();
115  m_relParticleHit.add(parentID, simHit->getArrayIndex());
116 
117  const auto* geo = m_topgp->getGeometry();
118  if (geo->isModuleIDValid(moduleID)) {
119  // transform to local frame
120  const auto& module = geo->getModule(moduleID);
121  emiPoint = module.pointToLocal(emiPoint);
122  detPoint = module.pointToLocal(detPoint);
123  emiMomDir = module.momentumToLocal(emiMomDir);
124  detMomDir = module.momentumToLocal(detMomDir);
125  } else {
126  B2ERROR("TOP::SensitivePMT: undefined module ID."
127  << LogVar("moduleID", moduleID));
128  }
129  auto* simPhoton = m_simPhotons.appendNew(moduleID,
130  emiPoint, emiMomDir, emiTime,
131  detPoint, detMomDir, detTime,
132  length, energy);
133 
134  simHit->addRelationTo(simPhoton);
135 
136  // kill photon after detection
137  photon.SetTrackStatus(fStopAndKill);
138 
139  return true;
140  }
141 
142 
143  } // end of namespace top
145 } // end of namespace Belle2
This class provides a set of constants for the framework.
Definition: Const.h:34
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
Definition: DataStore.h:71
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
Definition: DataStore.h:59
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.
UserInfo class which is used to attach additional information to Geant4 particles and tracks.
Definition: UserInfo.h:36
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:140
RelationArray m_relParticleHit
relations
Definition: SensitivePMT.h:67
int m_pmtReplicaDepth
replica depth of PMT volume
Definition: SensitivePMT.h:60
TOPGeometryPar * m_topgp
geometry parameters
Definition: SensitivePMT.h:62
int m_moduleReplicaDepth
replica depth of module volume
Definition: SensitivePMT.h:61
StoreArray< MCParticle > m_mcParticles
collection of MC particles
Definition: SensitivePMT.h:64
bool step(G4Step *aStep, G4TouchableHistory *) override
Process each step, fill TOPSimHits and TOPSimPhotons.
Definition: SensitivePMT.cc:50
StoreArray< TOPSimPhoton > m_simPhotons
collection of simulated photons
Definition: SensitivePMT.h:66
StoreArray< TOPSimHit > m_simHits
collection of simulated hits
Definition: SensitivePMT.h:65
const TOPGeometry * getGeometry() const
Returns pointer to geometry object using basf2 units.
double getPMTEfficiency(double energy, int moduleID, int pmtID, double x, double y) const
Returns PMT pixel efficiency, a product of quantum and collection efficiency.
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
Class to store variables with their name which were sent to the logging service.
Abstract base class for different kinds of events.