MpdEmcDigitizerKI.cxx 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. //--------------------------------------------------------------------
  2. //
  3. // Description:
  4. // MPD EMC Digitizer - takes EmcPoints and makes digits
  5. //
  6. //
  7. // Author List:
  8. // D.Peresunko, KI, 2019
  9. //--------------------------------------------------------------------
  10. #include "MpdEmcDigitizerKI.h"
  11. #include "MpdMCTrack.h"
  12. #include "MpdEmcDigitKI.h"
  13. #include "MpdEmcGeoUtils.h"
  14. #include "MpdEmcPointKI.h"
  15. #include "MpdEmcSimParams.h"
  16. #include "FairEventHeader.h"
  17. #include "FairLogger.h"
  18. #include "FairRootManager.h"
  19. #include "FairRun.h"
  20. #include <TClonesArray.h>
  21. #include <TMath.h>
  22. #include <TRandom.h>
  23. using namespace std;
  24. using namespace TMath;
  25. // ----- Default constructor -------------------------------------------
  26. MpdEmcDigitizerKI::MpdEmcDigitizerKI()
  27. : FairTask("EMC digitizer"),
  28. fPointArray(nullptr),
  29. fDigitsArray(nullptr),
  30. fSimParams(nullptr),
  31. fGeom(nullptr),
  32. fNDigits(0)
  33. {
  34. }
  35. // ----- Destructor ----------------------------------------------------
  36. MpdEmcDigitizerKI::~MpdEmcDigitizerKI() {}
  37. // -------------------------------------------------------------------------
  38. // ----- Public method Init --------------------------------------------
  39. InitStatus MpdEmcDigitizerKI::Init()
  40. {
  41. LOG(INFO) << "******************* EMC INIT *********************" << endl;
  42. // Get RootManager
  43. FairRootManager* ioman = FairRootManager::Instance();
  44. if (!ioman) {
  45. LOG(FATAL) << "RootManager not instantiated!" << endl;
  46. return kFATAL;
  47. }
  48. // Get input array
  49. fPointArray = (TClonesArray*)ioman->GetObject("EmcPoint");
  50. if (!fPointArray) {
  51. LOG(ERROR) << "No EmcPoint array!" << endl;
  52. return kERROR;
  53. }
  54. fMcTrArray = (TClonesArray*)ioman->GetObject("MCTrack");
  55. // Create and register output array
  56. fDigitsArray = new TClonesArray(
  57. "MpdEmcDigitKI", 100); // TODO: Check, can digits with different length of primary list be in TClonesArray???
  58. ioman->Register("EmcDigit", "EMC", fDigitsArray, kTRUE);
  59. LOG(INFO) << "Intialization successfull" << endl;
  60. return kSUCCESS;
  61. }
  62. //__________________________________________________________________________
  63. void MpdEmcDigitizerKI::Finish() { LOG(INFO) << "Finish" << endl; }
  64. //__________________________________________________________________________
  65. void MpdEmcDigitizerKI::Exec(Option_t* opt)
  66. {
  67. // Add all EMCPoints with energy deposition in same tower
  68. // Simulate electronic noise
  69. // Add non-linearity, digitization of energy
  70. // Remove digits in bad map and below threshold
  71. LOG(INFO) << " Event No. " << FairRun::Instance()->GetEventHeader()->GetMCEntryNumber();
  72. // Reset output Array
  73. if (!fDigitsArray)
  74. Fatal("MpdEmcDigitizerKI::Exec", "No array of digits");
  75. // Reset output Array
  76. if (!fDigitsArray) {
  77. LOG(FATAL) << "No array of digits";
  78. }
  79. fDigitsArray->Clear();
  80. fNDigits = 0;
  81. LOG(INFO) << "ECAL: number of points in the event: " << fPointArray->GetEntriesFast();
  82. // Class with list of parameters
  83. if (!fSimParams) {
  84. fSimParams = MpdEmcSimParams::GetInstance();
  85. }
  86. if (!fGeom) {
  87. fGeom = MpdEmcGeoUtils::GetInstance();
  88. }
  89. // Find the first cell with signal
  90. int nPoints = fPointArray->GetEntriesFast();
  91. int pointIndex = 0;
  92. int nextSigId = 999999; // in case no ginal in
  93. MpdEmcPointKI* point = nullptr;
  94. if (nPoints > 0) {
  95. point = static_cast<MpdEmcPointKI*>(fPointArray->At(pointIndex));
  96. nextSigId = point->GetDetectorID();
  97. }
  98. int nTotCells = fGeom->GetTotalNCells();
  99. // go through all cells, either add noisy digit, or signal+noise
  100. for (Int_t cellId = 0; cellId < nTotCells; cellId++) {
  101. // If signal exist in this cell, add noise to it, otherwise just create noise digit
  102. if (cellId == nextSigId) {
  103. // Create new Digit
  104. MpdEmcDigitKI* digit = new ((*fDigitsArray)[fNDigits++]) MpdEmcDigitKI(point);
  105. pointIndex++;
  106. while (pointIndex < nPoints) {
  107. point = static_cast<MpdEmcPointKI*>(fPointArray->At(pointIndex));
  108. if (digit->CanAdd(point)) { // Point from the same Tower
  109. digit->AddPoint(point);
  110. pointIndex++;
  111. } else { // Points are sorted according to cellID. If no more points left, finish
  112. nextSigId = point->GetDetectorID();
  113. break;
  114. }
  115. }
  116. // Add Electroinc noise, apply non-linearity, digitize, de-calibrate, time resolution
  117. double energy = digit->GetE();
  118. // Emulate Poissonian light collection
  119. if (fSimParams->SmearLightCollection()) {
  120. energy = SimulateLightCollection(energy);
  121. }
  122. if (fSimParams->SimulateNoise()) {
  123. // Simulate electronic noise
  124. energy += SimulateNoiseEnergy();
  125. }
  126. if (fSimParams->ApplyNonLinearity()) {
  127. energy = NonLinearity(energy);
  128. }
  129. if (fSimParams->ApplyDigitization()) {
  130. energy = DigitizeEnergy(energy);
  131. }
  132. //Convert energy from GeV to ADC units - as in real data
  133. energy/=fSimParams->ADCwidth();//V
  134. digit->SetE(energy);
  135. if (fSimParams->ApplyTimeResolution()) {
  136. digit->SetTime(TimeResolution(digit->GetTime(), energy));
  137. }
  138. } else { // No signal in this cell,
  139. // Simulate noise
  140. if (fSimParams->SimulateNoise()) {
  141. double energy = SimulateNoiseEnergy();
  142. double time = SimulateNoiseTime();
  143. if (energy > fSimParams->ZSthreshold()) {
  144. energy/=fSimParams->ADCwidth();
  145. new ((*fDigitsArray)[fNDigits++])
  146. MpdEmcDigitKI(cellId, energy, time, -1); // current sellId, energy, random time, no primary
  147. }
  148. }
  149. }
  150. }
  151. LOG(INFO) << "Emc points done:" << fDigitsArray->GetEntriesFast();
  152. LOG(INFO) << system("date");
  153. }
  154. //_______________________________________________________________________
  155. double MpdEmcDigitizerKI::SimulateNoiseEnergy()
  156. {
  157. // Simulation of noise of electronics
  158. // Here we assume, that noise is independent on signal
  159. // and just Gaus with fixed width
  160. return gRandom->Gaus(0., fSimParams->ElectronicNoise());
  161. }
  162. //_______________________________________________________________________
  163. double MpdEmcDigitizerKI::NonLinearity(const double e)
  164. {
  165. double a, b, c;
  166. fSimParams->CellNonLineaityParams(a, b, c);
  167. return e * c * (1. + a * exp(-e / b));
  168. }
  169. //_______________________________________________________________________
  170. double MpdEmcDigitizerKI::DigitizeEnergy(const double e)
  171. {
  172. // distretize energy if necessary
  173. double w = fSimParams->ADCwidth();
  174. return w * ceil(e / w);
  175. }
  176. //_______________________________________________________________________
  177. double MpdEmcDigitizerKI::TimeResolution(const double time, const double e)
  178. {
  179. // apply time resolution
  180. if (e <= 0)
  181. return 0.;
  182. double a, b;
  183. fSimParams->TimeResolutionParams(a, b);
  184. double timeResolution = a + b / e;
  185. return gRandom->Gaus(time, timeResolution);
  186. }
  187. //_______________________________________________________________________
  188. double MpdEmcDigitizerKI::SimulateNoiseTime()
  189. {
  190. // Evaluate (random) time of noise digits as uniform in some ranges
  191. double a, b;
  192. fSimParams->NoiseTimeRange(a, b);
  193. return gRandom->Uniform(a, b);
  194. }
  195. //_______________________________________________________________________
  196. double MpdEmcDigitizerKI::SimulateLightCollection(const double lostenergy)
  197. {
  198. // Emulate production of scintillator light and its collection
  199. double coef = fSimParams->GetLYPerGeV();
  200. double lightYield = gRandom->Poisson(coef * lostenergy);
  201. return lightYield / coef;
  202. }
  203. ClassImp(MpdEmcDigitizerKI)