Belle II Software  release-05-02-19
He3DigitizerModule.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2013 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Sam de Jong *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #include <beast/he3tube/modules/He3DigitizerModule.h>
12 #include <beast/he3tube/dataobjects/He3tubeSimHit.h>
13 
14 #include <mdst/dataobjects/MCParticle.h>
15 #include <framework/datastore/RelationArray.h>
16 #include <framework/datastore/RelationIndex.h>
17 #include <framework/logging/Logger.h>
18 #include <framework/gearbox/GearDir.h>
19 
20 //c++
21 #include <cmath>
22 #include <boost/foreach.hpp>
23 #include <string>
24 #include <fstream>
25 #include <stdlib.h>
26 
27 // ROOT
28 #include <TRandom.h>
29 
30 using namespace std;
31 using namespace Belle2;
32 using namespace he3tube;
33 
34 
35 //-----------------------------------------------------------------
36 // Register the Module
37 //-----------------------------------------------------------------
38 REG_MODULE(He3Digitizer)
39 
40 //-----------------------------------------------------------------
41 // Implementation
42 //-----------------------------------------------------------------
43 
45 {
46  // Set module properties
47  setDescription("He3tube digitizer module");
48 
49  addParam("conversionFactor", m_ConversionFactor,
50  "Conversion factor for pulse heights", 0.303132019);
51  addParam("useMCParticles", m_mcpExist, "Use MCParticles to determine if neutrons are present", true);
52 
53 }
54 
55 He3DigitizerModule::~He3DigitizerModule()
56 {
57 }
58 
59 void He3DigitizerModule::initialize()
60 {
61  B2INFO("He3Digitizer: Initializing");
62  m_he3tubeHit.registerInDataStore();
63 
64  StoreArray<MCParticle> mcParticles;
66  RelationArray relMCSimHit(mcParticles, simHits);
67 
68  getXMLData();
69 }
70 
71 void He3DigitizerModule::beginRun()
72 {
73 }
74 
75 void He3DigitizerModule::event()
76 {
77  B2DEBUG(250, "Beginning of event method");
78 
79  StoreArray<He3tubeSimHit> He3SimHits;
80  StoreArray<He3tubeHit> He3Hits;
81 
82  auto peak = new double[numOfTubes]();
83  auto lowTime = new double[numOfTubes](); //earliest deposit in each tube
84  std::fill_n(lowTime, numOfTubes, 9999999999999);
85  auto edepDet = new double[numOfTubes](); //total energy deposited per tube
86  auto NbEle_tot = new double[numOfTubes]();
87 
88  //skip events with no He3SimHits, but continue the event counter
89  if (He3SimHits.getEntries() == 0) {
90  B2DEBUG(250, "Skipping event #" << Event << " since there are no sim hits");
91  Event++;
92  return;
93  }
94 
95  auto definiteNeutron = new bool[numOfTubes]();
96  //vector<int> neutronIDs;
97 
98  if (m_mcpExist) { //if the mcparticles exist, we know which simhits are from neutron events
99 
100  StoreArray<MCParticle> mcParticles;
101  RelationIndex<MCParticle, He3tubeSimHit> relMCSimHit(mcParticles, He3SimHits);
102 
103  int nMCParticles = mcParticles.getEntries();
104  for (int i = 0; i < nMCParticles; ++i) {
105  MCParticle& mcp = *mcParticles[i];
106 
107  //Find all He3tubeSimHits which point from that MCParticle using a typedef and BOOST_FOREACH
108  //The typedef is needed as BOOST_FOREACH is a macro and cannot handle anything including a comma
109  typedef RelationIndex<MCParticle, He3tubeSimHit>::Element relMCSimHit_Element;
110  BOOST_FOREACH(const relMCSimHit_Element & relation, relMCSimHit.getElementsFrom(mcp)) {
111 
112  //int processNum = mcp.getSecondaryPhysicsProcess();
113 
114  MCParticle* mom = mcp.getMother();
115 
116  if (mom == NULL) continue;
117 
118  //if(processNum==121){
119  if (mom->getPDG() == 2112) {
120  He3tubeSimHit* aHit = He3SimHits[relation.indexTo];
121  int detNB = aHit->getdetNb();
122  definiteNeutron[detNB] = true;
123  ProcessHit(aHit, lowTime, edepDet, NbEle_tot);
124  }
125  }
126  }
127 
128 
129 
130  } else { //if mcparticles don't exist, we don't know which simhits are from neutron events
131  int nentries = He3SimHits.getEntries();
132  for (int i = 0; i < nentries; i++) {
133  He3tubeSimHit* aHit = He3SimHits[i];
134  int pdg = aHit->gettkPDG();
135  if (pdg == 2212 || pdg == 1000010030) ProcessHit(aHit, lowTime, edepDet, NbEle_tot);
136  }
137 
138  }
139 
140 
141 
142  for (int i = 0; i < numOfTubes; i++) {
143  peak[i] = (double)NbEle_tot[i] * m_ConversionFactor; //convert the number of ions into a value in ADC counts
144  if (peak[i] != 0) {
145 
146  //create He3tubeHit
147  He3Hits.appendNew(He3tubeHit(edepDet[i], i, peak[i], lowTime[i], definiteNeutron[i]));
148 
149  B2DEBUG(80, "He3Digitizer: " << edepDet[i] << "MeV deposited in tube #" << i << " with waveform peak of " << peak[i]);
150  }
151  }
152 
153  Event++;
154 
155  //delete arrays
156  delete[] peak;
157  delete[] lowTime;
158  delete[] edepDet;
159  delete[] NbEle_tot;
160  delete[] definiteNeutron;
161 
162 }
163 
164 
165 void He3DigitizerModule::ProcessHit(He3tubeSimHit* aHit, double* lowTime, double* edepDet, double* NbEle_tot)
166 {
167 
168  //get various info from this
169  double edep = aHit->getEnergyDep();
170  double niel = aHit->getEnergyNiel();
171  int detNB = aHit->getdetNb();
172  double time = aHit->getGlTime();
173  if (time < lowTime[detNB]) lowTime[detNB] =
174  time; //get the earliest time for this simhit
175 
176  if (detNB >= numOfTubes) {
177  B2WARNING("He3Digitizer: Detector number of He3tubeSimHit is greater than number implemented! Ignoring He3tubeSimHit.");
178  return;
179  }
180 
181  //ionization energy
182  double ionEn = (edep - niel) * 1e3; //MeV to keV
183 
184  if ((ionEn * 1e3) < m_Workfct) return; //keV to eV
185  //if there is enough energy to ionize the gas, get the number if ions produced
186  if ((ionEn * 1e3) > m_Workfct) {
187 
188  double meanE1 = ionEn * 1e3 / m_Workfct;
189  double sigma = sqrt(m_Fanofac * meanE1);
190  const int NbEle = (int)gRandom->Gaus(meanE1,
191  sigma); //this is the number of electrons created, and the number which reach the wire, since gain is essentially 1.
192 
193  NbEle_tot[detNB] = NbEle_tot[detNB] + NbEle;
194 
195  }
196 
197  edepDet[detNB] = edepDet[detNB] + edep;
198 
199 }
200 
201 
202 void He3DigitizerModule::getXMLData()
203 {
204  GearDir content = GearDir("/Detector/DetectorComponent[@name=\"HE3TUBE\"]/Content/");
205 
206  //get the location of the tubes
207  BOOST_FOREACH(const GearDir & activeParams, content.getNodes("Active")) {
208  B2DEBUG(250, "Tubes located at x=" << activeParams.getLength("x_he3tube"));
209  numOfTubes++;
210  }
211 
212 
213  B2INFO("He3Digitizer: There are " << numOfTubes << " tubes implemented");
214 
215 }
216 
217 void He3DigitizerModule::endRun()
218 {
219 }
220 
221 void He3DigitizerModule::terminate()
222 {
223 }
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
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
Belle2::RelationIndex
Provides access to fast ( O(log n) ) bi-directional lookups on a specified relation.
Definition: RelationIndex.h:84
Belle2::He3tubeSimHit::getEnergyNiel
float getEnergyNiel() const
Return the non-ionization energy in electrons.
Definition: He3tubeSimHit.h:67
Belle2::he3tube::He3DigitizerModule
He3 tube digitizer.
Definition: He3DigitizerModule.h:43
Belle2::He3tubeSimHit::getGlTime
float getGlTime() const
Return the global time.
Definition: He3tubeSimHit.h:75
Belle2::Module
Base class for Modules.
Definition: Module.h:74
Belle2::RelationIndexContainer::Element
Element type for the index.
Definition: RelationIndexContainer.h:62
Belle2::He3tubeSimHit::getEnergyDep
float getEnergyDep() const
Return the energy deposition in electrons.
Definition: He3tubeSimHit.h:65
Belle2::RelationIndex::getElementsFrom
range_from getElementsFrom(const FROM *from) const
Return a range of all elements pointing from the given object.
Definition: RelationIndex.h:157
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::He3tubeSimHit::gettkPDG
int gettkPDG() const
Return the PDG number of the track.
Definition: He3tubeSimHit.h:69
Belle2::GearDir
GearDir is the basic class used for accessing the parameter store.
Definition: GearDir.h:41
Belle2::MCParticle::getPDG
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:123
Belle2::MCParticle::getMother
MCParticle * getMother() const
Returns a pointer to the mother particle.
Definition: MCParticle.h:593
Belle2::He3tubeSimHit
ClassHe3tubeSimHit - Geant4 simulated hit for the He3tube detector.
Definition: He3tubeSimHit.h:40
Belle2::He3tubeSimHit::getdetNb
float getdetNb() const
Return the He3tube number.
Definition: He3tubeSimHit.h:73
Belle2::gearbox::Interface::getLength
double getLength(const std::string &path="") const noexcept(false)
Get the parameter path as a double converted to the standard length unit.
Definition: Interface.h:261
Belle2::MCParticle
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:43
Belle2::StoreArray< MCParticle >
Belle2::StoreArray::getEntries
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:226
Belle2::He3tubeHit
ClassHe3Hit - digitization simulated hit for the He3tube detector.
Definition: He3tubeHit.h:36