Belle II Software  release-08-01-10
ARICHDigitizerModule.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 // Own header.
9 #include <arich/modules/arichDigitizer/ARICHDigitizerModule.h>
10 
11 // Hit classes
12 #include <arich/dataobjects/ARICHSimHit.h>
13 #include <arich/dataobjects/ARICHDigit.h>
14 
15 // framework - DataStore
16 #include <framework/datastore/DataStore.h>
17 
18 // framework aux
19 #include <framework/logging/Logger.h>
20 
21 // magnetic field manager
22 #include <framework/geometry/BFieldManager.h>
23 
24 #include <framework/dataobjects/BackgroundInfo.h>
25 
26 
27 // ROOT
28 #include <TVector2.h>
29 #include <TVector3.h>
30 #include <TRandom3.h>
31 
32 using namespace boost;
33 
34 namespace Belle2 {
40  //-----------------------------------------------------------------
42  //-----------------------------------------------------------------
43 
44  REG_MODULE(ARICHDigitizer);
45 
46 
47  //-----------------------------------------------------------------
48  // Implementation
49  //-----------------------------------------------------------------
50 
51  ARICHDigitizerModule::ARICHDigitizerModule() : Module(),
52  m_maxQE(0)
53  {
54 
55  // Set description()
56  setDescription("This module creates ARICHDigits from ARICHSimHits. Here spatial digitization is done, channel-by-channel QE is applied, and readout time window cut is applied.");
57 
58  // Set property flags
60 
61  // Add parameters
62  addParam("TimeWindow", m_timeWindow, "Readout time window width in ns", 250.0);
63  addParam("TimeWindowStart", m_timeWindowStart, "Shift of the readout time window with respect to the global zero in ns", -50.0);
64  addParam("BackgroundHits", m_bkgLevel, "Number of background hits per hapd per readout (electronics noise)", 0.066);
65  addParam("MagneticFieldDistorsion", m_bdistort, "Apply image distortion due to non-perp. magnetic field", 0);
66  }
67 
69  {
70 
71  }
72 
74  {
75  // QE at 400nm (3.1eV) applied in SensitiveDetector
76  m_maxQE = m_simPar->getQE(3.1);
77 
78  m_ARICHSimHits.isRequired();
79  m_ARICHDigits.registerInDataStore();
80 
81  m_bgOverlay = false;
83  if (bgInfo.isValid()) {
84  if (bgInfo->getMethod() == BackgroundInfo::c_Overlay) m_bgOverlay = true;
85  }
86 
87  }
88 
90  {
91  if (m_simPar->getNBkgHits() > 0) m_bkgLevel = m_simPar->getNBkgHits();
92  }
93 
95  {
96 
97  //---------------------------------------------------------------------
98  // Convert SimHits one by one to digitizer hits.
99  //---------------------------------------------------------------------
100 
101  // We try to include the effect of opposite-polarity crosstalk among channels
102  // on each chip, which depend on number of p.e. on chip
103 
104  std::map<std::pair<int, int>, int> photoElectrons; // this contains number of photoelectrons falling on each channel
105  std::map<std::pair<int, int>, int> chipHits; // this contains number of photoelectrons on each chip
106 
107  // Loop over all photon hits
108  for (const ARICHSimHit& aSimHit : m_ARICHSimHits) {
109 
110  // check for time window
111  double time = aSimHit.getGlobalTime() - m_timeWindowStart;
112 
113  if (time < 0 || time > m_timeWindow) continue;
114 
115  TVector2 locpos(aSimHit.getLocalPosition().X(), aSimHit.getLocalPosition().Y());
116 
117  // Get id of module
118  int moduleID = aSimHit.getModuleID();
119 
120  if (m_bdistort) magFieldDistorsion(locpos, moduleID);
121 
122  // skip if not active
123  if (!m_modInfo->isActive(moduleID)) continue;
124 
125  // Get id number of hit channel
126  int chX, chY;
127  m_geoPar->getHAPDGeometry().getXYChannel(locpos.X(), locpos.Y(), chX, chY);
128 
129  if (chX < 0 && chY < 0) continue;
130 
131  int asicChannel = m_chnMap->getAsicFromXY(chX, chY);
132 
133 
134  // eliminate un-active channels
135  if (asicChannel < 0 || !m_chnMask->isActive(moduleID, asicChannel)) continue;
136 
137  // apply channel dependent QE scale factor
138  //double qe_scale = 0.27 / m_maxQE;
139  //double qe_scale = m_modInfo->getChannelQE(moduleID, asicChannel) * m_simPar->getColEff() / m_maxQE; // eventually move collection efficiency to here!
140  double qe_scale = m_modInfo->getChannelQE(moduleID, asicChannel) / m_maxQE;
141 
142  if (qe_scale > 1.) B2ERROR("Channel QE is higher than QE applied in SensitiveDetector");
143  if (gRandom->Uniform(1.) > qe_scale) continue;
144 
145  // photon was converted to photoelectron
146  chipHits[std::make_pair(moduleID, asicChannel / 36)] += 1;
147  photoElectrons[std::make_pair(moduleID, asicChannel)] += 1;
148 
149  }
150 
151  // loop over produced photoelectrons. Apply suppression due to the reverse polarization crosstalk
152  // among channels on the same chip, and produce hit bitmap (4 bits).
153 
154  for (std::map<std::pair<int, int>, int>::iterator it = photoElectrons.begin(); it != photoElectrons.end(); ++it) {
155 
156  std::pair<int, int> modch = it->first;
157  double npe = double(it->second);
158 
159  // reduce efficiency
160  npe /= (1.0 + m_simPar->getChipNegativeCrosstalk() * (double(chipHits[std::make_pair(modch.first, modch.second / 36)]) - 1.0));
161  if (npe < 1.0 && gRandom->Uniform(1) > npe) continue;
162 
163  // Make hit bitmap (depends on number of p.e. on channel). For now bitmap is 0001 for single p.e., 0011 for 2 p.e., ...
164  // More proper implementation is to be done ...
165  uint8_t bitmap = 0;
166  for (int i = 0; i < npe; i++) {
167  bitmap |= 1 << i;
168  if (i == 3) break;
169  }
170 
171  // make new digit!
172  m_ARICHDigits.appendNew(modch.first, modch.second, bitmap);
173 
174  }
175 
176  //--- if background not overlayed add electronic noise hits
177  if (m_bgOverlay) return;
178  uint8_t bitmap = 1;
179  unsigned nSlots = m_geoPar->getDetectorPlane().getNSlots();
180  for (unsigned id = 1; id < nSlots + 1; id++) {
181  if (!m_modInfo->isActive(id)) continue;
182  int nbkg = gRandom->Poisson(m_bkgLevel);
183  for (int i = 0; i < nbkg; i++) {
184  m_ARICHDigits.appendNew(id, gRandom->Integer(144), bitmap);
185  }
186  }
187 
188  }
189 
190  void ARICHDigitizerModule::magFieldDistorsion(TVector2& hit, int copyno)
191  {
192 
193  TVector2 hitGlob;
194  double phi = m_geoPar->getDetectorPlane().getSlotPhi(copyno);
195  double r = m_geoPar->getDetectorPlane().getSlotR(copyno);
196  double z = m_geoPar->getDetectorZPosition() + m_geoPar->getHAPDGeometry().getWinThickness();
197  hitGlob.SetMagPhi(r, phi);
198  TVector2 shift = hit;
199  hitGlob += shift.Rotate(phi);
200  ROOT::Math::XYZVector Bfield = BFieldManager::getField(ROOT::Math::XYZVector(m_geoPar->getMasterVolume().pointToGlobal(TVector3(
201  hitGlob.X(), hitGlob.Y(), z))));
202  double cc = m_geoPar->getHAPDGeometry().getPhotocathodeApdDistance() / abs(Bfield.Z());
203  shift.SetX(cc * Bfield.X());
204  shift.SetY(cc * Bfield.Y());
205  shift = shift.Rotate(-phi);
206  hit.SetX(hit.X() + shift.X());
207  hit.SetY(hit.Y() + shift.Y());
208  }
209 
211 } // end Belle2 namespace
double m_maxQE
QE at 400nm (from QE curve applied in SensitveDetector)
double m_bkgLevel
Number of background hits ped hapd per readout (electronics noise)
DBObjPtr< ARICHSimulationPar > m_simPar
simulation parameters from the DB
StoreArray< ARICHSimHit > m_ARICHSimHits
StoreArray containing the ARICHSimHits.
DBObjPtr< ARICHModulesInfo > m_modInfo
information on installed modules from the DB (QEs etc.)
DBObjPtr< ARICHGeometryConfig > m_geoPar
geometry configuration parameters from the DB
bool m_bgOverlay
True if BG overlay detected.
double m_timeWindow
Readout time window width in ns.
StoreArray< ARICHDigit > m_ARICHDigits
StoreArray containing the ARICHDigits.
int m_bdistort
apply distorsion due to magnetic field
DBObjPtr< ARICHChannelMapping > m_chnMap
HAPD (x,y) to asic channel mapping.
double m_timeWindowStart
Readout time window shift w.r.t.
Class ARICHSimHit - Geant4 simulated hit for ARICH.
Definition: ARICHSimHit.h:29
@ c_Persistent
Object is available during entire execution time.
Definition: DataStore.h:60
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
bool isValid() const
Check whether the object was created.
Definition: StoreObjPtr.h:111
virtual void initialize() override
Initialize the Module.
virtual void event() override
Event processor.
virtual ~ARICHDigitizerModule()
Destructor.
virtual void beginRun() override
Called when entering a new run.
void magFieldDistorsion(TVector2 &hit, int copyno)
Apply correction to hit position due to non-perpendicular component of magnetic field.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
static void getField(const double *pos, double *field)
return the magnetic field at a given position.
Definition: BFieldManager.h:91
Abstract base class for different kinds of events.
record to be used to store ASIC info