CbmRoot
Loading...
Searching...
No Matches
CbmMuchDigitizeGem.cxx
Go to the documentation of this file.
1/* Copyright (C) 2009-2021 St. Petersburg Polytechnic University, St. Petersburg
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Apar Agarwal, Vikas Singhal, Ekata Nandy, Volker Friese, Evgeny Kryshen [committer] */
4
34// Includes from MUCH
35#include "CbmMuchDigitizeGem.h"
36
37#include "CbmMuchDigi.h"
38#include "CbmMuchModuleGem.h"
41#include "CbmMuchPad.h"
42#include "CbmMuchPadRadial.h"
44#include "CbmMuchPoint.h"
46#include "CbmMuchRecoDefs.h"
47#include "CbmMuchSector.h"
48#include "CbmMuchSectorRadial.h"
50#include "CbmMuchStation.h"
51
52// Includes from base
53#include "FairEventHeader.h"
54#include "FairMCEventHeader.h"
55#include "FairMCPoint.h"
56#include "FairRootManager.h"
57#include "FairRunAna.h"
58#include "FairRunSim.h"
59#include <Logger.h>
60
61// Includes from Cbm
62#include "CbmMCTrack.h"
63
64#include "TCanvas.h"
65#include "TChain.h"
66#include "TDatabasePDG.h"
67#include "TFile.h"
68#include "TH1D.h"
69#include "TObjArray.h"
70#include "TRandom.h"
71#include <TGeoManager.h>
72
73#include <cassert>
74#include <cstring>
75#include <iomanip>
76#include <iostream>
77#include <sstream>
78#include <vector>
79
80using std::cout;
81using std::endl;
82using std::fixed;
83using std::map;
84using std::right;
85using std::setprecision;
86using std::setw;
87using std::string;
88
89// ----- Default constructor -------------------------------------------
91 : CbmDigitize<CbmMuchDigi>("MuchDigitizeGem")
92 ,
93 // fgDeltaResponse(),
94 fAlgorithm(1)
95 , fGeoScheme(CbmMuchGeoScheme::Instance())
96 , fDigiFile()
97 , fPoints(NULL)
98 , fMCTracks(NULL)
99 ,
100 // fDigis(NULL),
101 // fDigiMatches(NULL),
102 fNFailed(0)
103 , fNOutside(0)
104 , fNMulti(0)
105 , fFlag(0)
106 , fNADCChannels(-1)
107 , fQMax(-1)
108 , fQThreshold(-1)
109 , fMeanNoise(1500)
110 , fSpotRadius(-1)
111 , fMeanGasGain(-1)
112 , fDTime(-1)
113 , fDeadPadsFrac(-1)
114 , fTimer()
115 , fMcChain(NULL)
116 , fDeadTime(400)
117 , fDriftVelocity(-1)
118 ,
119 // fPeakingTime(20),
120 // fRemainderTime(40),
121 fTimeBinWidth(1)
122 , fNTimeBins(200)
123 , fTOT(0)
124 , fTotalDriftTime(-1)
125 ,
126 // fTotalDriftTime(0.3/fDriftVelocity*10000), // 40 ns
127 fSigma()
128 , fMPV()
129 , fIsLight(1)
130 ,
131 // fIsLight = 1 (default) Store Light CbmMuchDigiMatch in
132 // output branch, fIsLight = 0 Create Heavy CbmMuchDigiMatch
133 // with fSignalShape info.
134 fTimePointLast(-1)
135 , fTimeDigiFirst(-1)
136 , fTimeDigiLast(-1)
137 , fNofPoints(0)
138 , fNofSignals(0)
139 , fNofDigis(0)
140 , fNofEvents(0)
141 , fNofPointsTot(0.)
142 , fNofSignalsTot(0.)
143 , fNofDigisTot(0.)
144 , fTimeTot()
145 ,
146 // hPriElAfterDriftpath(NULL),
147 fPerPadNoiseRate(10e-9)
148 , fGenerateElectronicsNoise(kFALSE)
149 , fNoiseCharge(nullptr)
150 , fAddressCharge()
151{
152 fSigma[0] = new TF1("sigma_e", "pol6", -5, 10);
153 fSigma[0]->SetParameters(sigma_e);
154
155 fSigma[1] = new TF1("sigma_mu", "pol6", -5, 10);
156 fSigma[1]->SetParameters(sigma_mu);
157
158 fSigma[2] = new TF1("sigma_p", "pol6", -5, 10);
159 fSigma[2]->SetParameters(sigma_p);
160
161 fMPV[0] = new TF1("mpv_e", "pol6", -5, 10);
162 fMPV[0]->SetParameters(mpv_e);
163
164 fMPV[1] = new TF1("mpv_mu", "pol6", -5, 10);
165 fMPV[1]->SetParameters(mpv_mu);
166
167 fMPV[2] = new TF1("mpv_p", "pol6", -5, 10);
168 fMPV[2]->SetParameters(mpv_p);
169 Reset();
170 fNoiseCharge = new TF1("Noise Charge", "TMath::Gaus(x, [0], [1])", fQThreshold,
171 fQMax / 10); // noise function to calculate charge for noise hit.
172 // mean=fQThreashold(10000),fQMax=500000
173}
174// -------------------------------------------------------------------------
175
176// -------------------------------------------------------------------------
177CbmMuchDigitizeGem::CbmMuchDigitizeGem(const char* digiFileName, Int_t flag)
178 : CbmDigitize<CbmMuchDigi>("MuchDigitizeGem")
179 ,
180 // fgDeltaResponse(),
181 fAlgorithm(1)
182 , fGeoScheme(CbmMuchGeoScheme::Instance())
183 , fDigiFile(digiFileName)
184 , fPoints(NULL)
185 , fMCTracks(NULL)
186 ,
187 // fDigis(NULL),
188 // fDigiMatches(NULL),
189 fNFailed(0)
190 , fNOutside(0)
191 , fNMulti(0)
192 , fFlag(flag)
193 , fNADCChannels(-1)
194 , fQMax(-1)
195 , fQThreshold(-1)
196 , fMeanNoise(1500)
197 , fSpotRadius(-1)
198 , fMeanGasGain(-1)
199 , fDTime(-1)
200 , fDeadPadsFrac(-1)
201 , fTimer()
202 , fMcChain(NULL)
203 , fDeadTime(400)
204 , fDriftVelocity(-1)
205 ,
206 // fPeakingTime(20),
207 // fRemainderTime(40),
208 fTimeBinWidth(1)
209 , fNTimeBins(200)
210 , fTOT(0)
211 , fTotalDriftTime(-1)
212 ,
213 // fTotalDriftTime(0.3/fDriftVelocity*10000), // 40 ns
214 fSigma()
215 , fMPV()
216 , fIsLight(1)
217 ,
218 // fIsLight = 1 (default) Store Light CbmMuchDigiMatch in
219 // output branch, fIsLight = 0 Create Heavy CbmMuchDigiMatch
220 // with fSignalShape info.
221 fTimePointLast(-1)
222 , fTimeDigiFirst(-1)
223 , fTimeDigiLast(-1)
224 , fNofPoints(0)
225 , fNofSignals(0)
226 , fNofDigis(0)
227 , fNofEvents(0)
228 , fNofPointsTot(0.)
229 , fNofSignalsTot(0.)
230 , fNofDigisTot(0.)
231 ,
232 // hPriElAfterDriftpath(NULL),
233 fTimeTot()
234 , fPerPadNoiseRate(10e-9)
235 , fGenerateElectronicsNoise(kFALSE)
236 , fNoiseCharge(nullptr)
237 , fAddressCharge()
238{
239 fSigma[0] = new TF1("sigma_e", "pol6", -5, 10);
240 fSigma[0]->SetParameters(sigma_e);
241
242 fSigma[1] = new TF1("sigma_mu", "pol6", -5, 10);
243 fSigma[1]->SetParameters(sigma_mu);
244
245 fSigma[2] = new TF1("sigma_p", "pol6", -5, 10);
246 fSigma[2]->SetParameters(sigma_p);
247
248 fMPV[0] = new TF1("mpv_e", "pol6", -5, 10);
249 fMPV[0]->SetParameters(mpv_e);
250
251 fMPV[1] = new TF1("mpv_mu", "pol6", -5, 10);
252 fMPV[1]->SetParameters(mpv_mu);
253
254 fMPV[2] = new TF1("mpv_p", "pol6", -5, 10);
255 fMPV[2]->SetParameters(mpv_p);
256 Reset();
257 fNoiseCharge = new TF1("Noise Charge", "TMath::Gaus(x, [0], [1])", fQThreshold,
258 fQMax / 10); // noise function to calculate charge for noise hit.
259 // mean=fQThreashold(10000),fQMax=500000
260}
261// -------------------------------------------------------------------------
262
263// ----- Destructor ----------------------------------------------------
265{
266
267 delete fSigma[0];
268 delete fSigma[1];
269 delete fSigma[2];
270 delete fMPV[0];
271 delete fMPV[1];
272 delete fMPV[2];
273}
274// -------------------------------------------------------------------------
275
276// ----- Private method Reset -------------------------------------------
282// -------------------------------------------------------------------------
283
284// ----- Setting Detector related parameters
285// -------------------------------------------
287{
288 Int_t DetectorType = module->GetDetectorType();
289 // cout<<" dec type "<<DetectorType<<endl;
290 switch (DetectorType) {
291 case 3: // For GEM
292 {
293 fNADCChannels = 32; // Total ADC Channels
294 fQMax = 500000; // Maximum charge = 80 fC for GEM
295 fQThreshold = 12500; // Minimum charge threshold = 2fC for GEM
296 fMeanNoise = 1500; // mean noise
297 fSpotRadius = 0.05; // Spot radius = 500 um for GEM
298 fMeanGasGain = 5000; // Mean gas gain = 5000 for GEM
299 fDTime = 3;
300 fDeadPadsFrac = 0;
301 fDriftVelocity = 100; // Drift Velocity = 100 um/ns
302 auto DriftVolumeWidth = module->GetSize().Z(); // Drift gap
303 fTotalDriftTime = DriftVolumeWidth / fDriftVelocity * 10000; // Drift time (ns)
304 } break;
305 case 4: { // For RPC
306 fNADCChannels = 32; // Total ADC Channels
307 fQMax = 812500; // Maximum charge = 130 fC for RPC
308 fQThreshold = 187500; // Minimum charge threshold = 30 fC for RPC
309 fMeanNoise = 1500; // mean noise
310 fSpotRadius = 0.2; // Spot radius = 2 mm for RPC
311 fMeanGasGain = 3e4; // Mean gas gain = 3e4 for RPC
312 fDTime = 3;
313 fDeadPadsFrac = 0;
314 fDriftVelocity = 120; // Drift velocity = 120 um/ns
315 auto DriftVolumeWidth = module->GetSize().Z(); // Drift gap
316 fTotalDriftTime = DriftVolumeWidth / fDriftVelocity * 10000; // Drift time (ns)
317
318 } break;
319 }
320 // set parameters for GEM
321}
322// -------------------------------------------------------------------------
323
324// ----- Private method Init -------------------------------------------
326{
327
328 // Screen output
329 std::cout << std::endl;
330 LOG(info) << "==========================================================";
331 LOG(info) << GetName() << ": Initialisation\n";
332
333 FairRootManager* ioman = FairRootManager::Instance();
334 if (!ioman) Fatal("Init", "No FairRootManager");
335
336 if (fEventMode) {
337 LOG(info) << fName << ": Using event-by-event mode";
338 }
339
340 // hPriElAfterDriftpathgem = new TH1D("hPriElAfterDriftpathgem"," GEM:primary
341 // electron ",300,0,300); hPriElAfterDriftpathrpc = new
342 // TH1D("hPriElAfterDriftpathrpc"," RPC:primary electron ",300,0,300);
343 // hadcGEM = new TH1F("hadcGEM","GEM:ADC",70,-0.5,69.5);
344 // hadcRPC = new TH1F("hadcRPC","RPC:ADC",70,-0.5,69.5);
345
346 // hdrifttimegem = new TH1D("hdrifttimegem"," GEM ",100,0,50);
347 // hdrifttimerpc = new TH1D("hdrifttimerpc"," RPC ",100,0,50);
348
349 // Get geometry version tag
350 gGeoManager->CdTop();
351 TGeoNode* cave = gGeoManager->GetCurrentNode(); // cave
352 TString geoTag;
353 for (Int_t iNode = 0; iNode < cave->GetNdaughters(); iNode++) {
354 TString name = cave->GetDaughter(iNode)->GetVolume()->GetName();
355 if (name.Contains("much", TString::kIgnoreCase)) {
356 if (name.Contains("mcbm", TString::kIgnoreCase)) {
357 geoTag = TString(name(5, name.Length()));
358 }
359 else {
360 geoTag = TString(name(5, name.Length() - 5));
361 }
362 // geoTag = "v17b"; // modified ekata
363 // cout << " geo tag " << geoTag << endl;
364 LOG(info) << fName << ": MUCH geometry tag is " << geoTag;
365 break;
366 } //? node is MUCH
367 } //# top level nodes
368
369 // Set the parameter file and the flag, if not done in constructor
370 if (fDigiFile.IsNull()) {
371 if (geoTag.IsNull())
372 LOG(fatal) << fName
373 << ": no parameter file specified and no MUCH node found in "
374 "geometry!";
375 fDigiFile = gSystem->Getenv("VMCWORKDIR");
376 // TODO: (VF) A better naming convention for the geometry tag and the
377 // corresponding parameter file is surely desirable.
378 if (geoTag.Contains("mcbm", TString::kIgnoreCase)) {
379 fDigiFile += "/parameters/much/much_" + geoTag + "_digi_sector.root";
380 }
381 else {
382 fDigiFile += "/parameters/much/much_" + geoTag(0, 4) + "_digi_sector.root";
383 }
384 // fDigiFile
385 // ="/home/ekata/CbmRoot/AUG18/parameters/much/much_v17b_digi_sector.root";
386
387 LOG(info) << fName << ": Using parameter file " << fDigiFile;
388
389 fFlag = (geoTag.Contains("mcbm", TString::kIgnoreCase) ? 1 : 0);
390 LOG(info) << fName << ": Using flag " << fFlag << (fFlag ? " (mcbm) " : "(standard)");
391 }
392
393 // Initialize GeoScheme
395 TFile* oldFile = gFile;
396 TDirectory* oldDir = gDirectory;
397 TFile* file = new TFile(fDigiFile);
398 LOG_IF(fatal, !file->IsOpen()) << fName << ": parameter file " << fDigiFile << " does not exist!";
399 TObjArray* stations = file->Get<TObjArray>("stations");
400 LOG_IF(fatal, !stations) << "No TObjArray stations found in file " << fDigiFile;
401 file->Close();
402 file->Delete();
404 gFile = oldFile;
405 gDirectory = oldDir;
406 fGeoScheme->Init(stations, fFlag);
407
408 // For X, Y position correction according to different geometry file and its
409 // tag.
410 if (fDigiFile.Contains("mcbm")) {
411 if (fDigiFile.Contains("v19a")) {
412 fGemTX = 18.5;
413 fGemTY = 80.5;
414 }
415 else if (fDigiFile.Contains("v20a")) {
416 fGemTX = 18.5;
417 fGemTY = 80.0;
418 }
419 else if (fDigiFile.Contains("v22j")) { // for high intensity runs during
420 // June 2022 mMuCh in acceptance
421 fGemTX = 8.0;
422 fGemTY = 81.5;
423 fRpcTX = 66.25; // RPC introduced during 2022 data taking
424 fRpcTY = -70.5;
425 }
426 else if (fDigiFile.Contains("v22k")) { // during benchmark runs. mMuCh is
427 // out of acceptance
428 fGemTX = -44.5;
429 fGemTY = 81.5;
430 fRpcTX = 48.0;
431 fRpcTY = -70.0;
432 }
433 }
434
435 // Determine drift volume width
436 // Double_t driftVolumeWidth = 0.4; // cm - default and will over written by
437 // Detector Parameters function.
438
439 // Double_t DriftVolumeWidth;
440 for (Int_t i = 0; i < fGeoScheme->GetNStations(); i++) {
441 CbmMuchStation* station = fGeoScheme->GetStation(i);
442 // CbmMuchStation* station = fGeoScheme->GetStation(3);
443 if (station->GetNLayers() <= 0) continue;
444 CbmMuchLayerSide* side = station->GetLayer(0)->GetSide(0);
445 if (side->GetNModules() <= 0) continue;
446 CbmMuchModule* module = side->GetModule(0);
447 // if (module->GetDetectorType()!=4)continue;
448 if (module->GetDetectorType() != 3 && module->GetDetectorType() != 4) continue;
449 DetectorParameters(module);
450 // cout<<" dec type "<<module->GetDetectorType()<<" drift width
451 // "<<DriftVolumeWidth<<endl;
452 }
453
454 // cout<<" dec type "<<module->GetDetectorType()<<" drift width
455 // "<<driftVolumeWidth<<endl;
456 /*
457 driftVolumeWidth = module->GetSize().Z();
458 cout<<"driftVolumeWidth "<<driftVolumeWidth<<endl;
459 break;
460
461 }
462 fTotalDriftTime = driftVolumeWidth/fDriftVelocity*10000; // [ns];
463*/
464
465 // Reading MC point as Event by event for time based digi generation also.
466 // Get input array of MuchPoints
467 fPoints = (TClonesArray*) ioman->GetObject("MuchPoint");
468 assert(fPoints);
469
470 // Get input array of MC tracks
471 fMCTracks = (TClonesArray*) ioman->GetObject("MCTrack");
472 assert(fMCTracks);
473
474 // Register output arrays in vector
475 /*
476 fDigis = new std::vector<CbmMuchDigi>();
477 ioman->RegisterAny("MuchDigi",fDigis, IsOutputBranchPersistent("MuchDigi"));
478 if ( fCreateMatches ) {
479 fDigiMatches = new std::vector<CbmMatch>();
480 ioman->RegisterAny("MuchDigiMatch",fDigiMatches,
481 IsOutputBranchPersistent("MuchDigiMatch"));
482 }
483 */
485
486 // Register output arrays in TClonesArray which is replaced with vector
487 /*fDigis = new TClonesArray("CbmMuchDigi", 1000);
488 ioman->Register("MuchDigi", "Digital response in MUCH", fDigis, kTRUE);
489 if ( fCreateMatches ) {
490 fDigiMatches = new TClonesArray("CbmMatch", 1000);
491 ioman->Register("MuchDigiMatch", "Digi Match in MUCH", fDigiMatches, kTRUE);
492 }*/
493 // fgDeltaResponse is used in the CbmMuchSignal for analysing the Signal
494 // Shape, it is generated once in the digitizer and then be used by each
495 // CbmMuchSignal. For reducing the time therefore generated once in the
496 // CbmMuchDigitize Gem and not generated in the CbmMuchSignal
497 // Set response on delta function
498
499 // Not using fSignalShape as consuming memory. Commening all the field
500 // related.
501
502 // Int_t nShapeTimeBins=Int_t(gkResponsePeriod/gkResponseBin);
503 // fgDeltaResponse.Set(nShapeTimeBins);
504 // for (Int_t i=0;i<fgDeltaResponse.GetSize();i++){
505 // Double_t time = i*gkResponseBin;
506 // if (time<=fPeakingTime) fgDeltaResponse[i]=time/fPeakingTime;
507 // else fgDeltaResponse[i] = exp(-(time-fPeakingTime)/fRemainderTime);
508 //}
509
510 // --- Read list of inactive channels
511 if (!fInactiveChannelFileName.IsNull()) {
512 LOG(info) << GetName() << ": Reading inactive channels from " << fInactiveChannelFileName;
513 auto result = ReadInactiveChannels();
514 if (!result.second) {
515 LOG(error) << GetName() << ": Error in reading from file! Task will be inactive.";
516 return kFATAL;
517 }
518 LOG(info) << GetName() << ": " << std::get<0>(result) << " lines read from file, " << fInactiveChannels.size()
519 << " channels set inactive";
520 }
521
522 // --- Enable histogram if want to enalyze Noise spectrum.
523 // noise = new TH1D("noise", "Noise Generated per Event NoiseRate 10e-8", 100
524 // , 0 , 200);
525 LOG(info) << GetName() << ": Initialisation successful";
526 LOG(info) << "==========================================================";
527 std::cout << std::endl;
528
529 return kSUCCESS;
530}
531// -------------------------------------------------------------------------
532
533// ----- Public method Exec --------------------------------------------
535{
536
537 // --- Start timer and reset counters
538 fTimer.Start();
539 Reset();
540
541 // --- Event number and time
542 GetEventInfo();
543 LOG(debug) << GetName() << ": Processing event " << fCurrentEvent << " from input " << fCurrentInput
544 << " at t = " << fCurrentEventTime << " ns with " << fPoints->GetEntriesFast() << " MuchPoints ";
545
546 // ReadAndRegister(fCurrentEventTime);
547
548 for (Int_t iPoint = 0; iPoint < fPoints->GetEntriesFast(); iPoint++) {
549 const CbmMuchPoint* point = (const CbmMuchPoint*) fPoints->At(iPoint);
550 LOG(debug1) << GetName() << ": Processing MCPoint " << iPoint;
551 assert(point);
552 ExecPoint(point, iPoint);
553 fNofPoints++;
554 } // MuchPoint loop
555
556 // --------------------NOISE Generated before
557 // ReadAndRegister---------------------- //
561 fNofNoiseTot += nNoise;
562 // noise->Fill(nNoise);
563 LOG(info) << "+ " << setw(20) << GetName() << ": Generated " << nNoise
564 << " noise signals from t = " << fPreviousEventTime << " ns to " << fCurrentEventTime << " ns and "
565 << fNofNoiseTot << " total noise generated till now.";
566 LOG(debug3) << "+ " << setw(20) << GetName() << ": Generated " << fNofNoiseSignals
567 << " noise signals for this time slice from t = " << fPreviousEventTime << " ns to "
568 << fCurrentEventTime << "ns";
570 }
571
572 if (fEventMode)
573 ReadAndRegister(-1);
574 else
576
577 // --- Event log
578 LOG(info) << "+ " << setw(15) << GetName() << ": Event " << setw(6) << right << fCurrentEvent << " at " << fixed
579 << setprecision(3) << fCurrentEventTime << " ns, points: " << fNofPoints << ", signals: " << fNofSignals
580 << ", digis: " << fNofDigis << ". Exec time " << setprecision(6) << fTimer.RealTime() << " s.";
581
582 fTimer.Stop();
583 fNofEvents++;
587 fTimeTot += fTimer.RealTime();
588
589} // -----------------------------------------------------------------------------------------
590
591//================================Generate
592// Noise==============================================//
594{
595 LOG(debug) << "+ " << setw(20) << GetName() << ": Previous event time " << t1 << " Current event time " << t2
596 << " ns.";
597 if (t1 > t2) {
598 LOG(debug) << "+ "
599 << ": Previous event time " << t1 << " is greater than Current event time " << t2
600 << ". No electronics noise signal generated for " << fCurrentEvent << " event.";
601 return 0;
602 };
603 Int_t numberofstations = fGeoScheme->GetNStations();
604 auto StationNoise = 0;
605 for (Int_t i = 0; i < numberofstations; i++) {
606 CbmMuchStation* station = fGeoScheme->GetStation(i);
607 auto numberoflayers = station->GetNLayers();
608 if (numberoflayers <= 0) continue;
609
610 auto LayerNoise = 0;
611 for (Int_t j = 0; j < numberoflayers; j++) {
612 CbmMuchLayerSide* side = station->GetLayer(j)->GetSide(0);
613 auto numberofmodules = side->GetNModules();
614 if (numberofmodules <= 0) continue;
615
616 auto FrontModuleNoise = 0;
617 for (auto k = 0; k < numberofmodules; k++) {
618 CbmMuchModuleGem* module = (CbmMuchModuleGem*) (side->GetModule(k));
619 if (module->GetDetectorType() != 4 && module->GetDetectorType() != 3) continue;
620 FrontModuleNoise += GenerateNoisePerModule(module, t1, t2);
621 }
622 side = station->GetLayer(j)->GetSide(1);
623 numberofmodules = side->GetNModules();
624 if (numberofmodules <= 0) continue;
625 auto BackModuleNoise = 0;
626 for (auto k = 0; k < numberofmodules; k++) {
627 CbmMuchModuleGem* module = (CbmMuchModuleGem*) side->GetModule(k);
628 if (module->GetDetectorType() != 4 && module->GetDetectorType() != 3) continue;
629 BackModuleNoise += GenerateNoisePerModule(module, t1, t2);
630 }
631 LayerNoise += FrontModuleNoise + BackModuleNoise;
632 }
633 LOG(debug1) << "+ " << setw(20) << GetName() << ": Generated " << LayerNoise << " noise signals in station " << i
634 << " from t = " << fPreviousEventTime << " ns to " << fCurrentEventTime << " ns";
635 StationNoise += LayerNoise;
636 }
637 return StationNoise;
638}
639
640//================================Generate
641// Noise==============================================//
642
644{
645 auto NumberOfPad = module->GetNPads();
646 Double_t nNoiseMean = fPerPadNoiseRate * NumberOfPad * (t2 - t1);
647 Int_t nNoise = gRandom->Poisson(nNoiseMean);
648 LOG(debug) << "+ " << setw(20) << GetName() << ": Number of noise signals : " << nNoise << " in one module. ";
649 for (Int_t iNoise = 0; iNoise <= nNoise; iNoise++) {
650 Int_t padnumber = Int_t(gRandom->Uniform(Double_t(NumberOfPad)));
651 CbmMuchPad* pad = module->GetPad(padnumber);
652 Double_t NoiseTime = gRandom->Uniform(t1, t2);
653 Double_t charge = fNoiseCharge->GetRandom();
654 while (charge < 0)
655 charge = fNoiseCharge->GetRandom();
656 AddNoiseSignal(pad, NoiseTime, charge);
657 }
658 // noise->Fill(nNoise);
659 return nNoise;
660}
661
662//=================Add a signal to the buffer=====================//
663
664void CbmMuchDigitizeGem::AddNoiseSignal(CbmMuchPad* pad, Double_t time, Double_t charge)
665{
666 assert(pad);
667 LOG(debug3) << GetName() << ": Receiving signal " << charge << " in channel " << pad->GetAddress() << " at time "
668 << time << "ns";
669 // LOG(debug) << GetName() << ": discarding signal in dead channel "
670 // << channel;
671 // return;
672 CbmMuchSignal* signal = new CbmMuchSignal(pad->GetAddress(), time);
673 // signal->SetTimeStart(time);
674 // signal->SetTimeStop(time+fDeadTime);
675 signal->SetCharge((UInt_t) charge);
676 UInt_t address = pad->GetAddress();
677 CbmMuchReadoutBuffer::Instance()->Fill(address, signal);
679 LOG(debug3) << "+ " << setw(20) << GetName()
680 << ": Registered a Noise CbmMuchSignal into the "
681 "CbmMuchReadoutBuffer. Number of Noise Signal generated "
683}
684//====================End of Noise part=================//
685
686// -------------------------------------------------------------------------
687// Read all the Signal from CbmMuchReadoutBuffer, convert the analog signal into
688// the digital response and register Output according to event by event mode
689// and Time based mode.
691{
692 std::vector<CbmMuchSignal*> SignalList;
693 // Event Time should be passed with the Call
694 /*Double_t eventTime = -1.;
695 if(fDaq){
696 eventTime = FairRun::Instance()->GetEventHeader()->GetEventTime();
697 }*/
698
699 Int_t ReadOutSignal = CbmMuchReadoutBuffer::Instance()->ReadOutData(eventTime, SignalList);
700 LOG(debug) << GetName() << ": Number of Signals read out from Buffer " << ReadOutSignal << " and SignalList contain "
701 << SignalList.size() << " entries.";
702
703 for (std::vector<CbmMuchSignal*>::iterator LoopOver = SignalList.begin(); LoopOver != SignalList.end(); LoopOver++) {
704 CbmMuchDigi* digi = ConvertSignalToDigi(*LoopOver);
705 CbmMatch* digiMatch = new CbmMatch(*(*LoopOver)->GetMatch()); // must be copied from signal
706 // assert(digi);
707 if (!digi) {
708 LOG(debug2) << GetName() << ": Digi not created as signal is below threshold.";
709 }
710 else {
711 LOG(debug2) << GetName() << ": New digi: sector = " << CbmMuchAddress::GetSectorIndex(digi->GetAddress())
712 << " channel= " << CbmMuchAddress::GetChannelIndex(digi->GetAddress());
713
714 SendData(digi->GetTime(), digi, digiMatch);
715 fNofDigis++;
716 }
717 }
718
719 LOG(debug) << GetName() << ": " << fNofDigis << (fNofDigis == 1 ? " digi " : " digis ") << "created and sent to DAQ ";
720 if (fNofDigis)
721 LOG(debug) << "( from " << fixed << setprecision(3) << fTimeDigiFirst << " ns to " << fTimeDigiLast << " ns )";
722 LOG(debug);
723
724 // After digis are created from signals the signals have to be removed
725 // Otherwise there is a huge memeory leak
726 for (auto signal : SignalList) {
727 delete (signal);
728 }
729
730} //----ReadAndRegister -------
731
732// Convert Signal into the Digi with appropriate methods.
733
735{
736
737 // Setting Parameters for RPC or GEM (10 lines)
738 auto address = signal->GetAddress();
739 auto StationIndex = CbmMuchAddress::GetStationIndex(address);
740 CbmMuchStation* station = fGeoScheme->GetStation(StationIndex);
741 auto LayerIndex = CbmMuchAddress::GetLayerIndex(address);
742 auto SideIndex = CbmMuchAddress::GetLayerSideIndex(address);
743 CbmMuchLayerSide* side = station->GetLayer(LayerIndex)->GetSide(SideIndex);
744 auto ModuleIndex = CbmMuchAddress::GetLayerSideIndex(address);
745 CbmMuchModule* module = side->GetModule(ModuleIndex);
746 assert(module);
747 DetectorParameters(module);
748
749 // cout<<"Det Type: "<<module->GetDetectorType()<<" fQThreshold
750 // "<<fQThreshold<<" fqmax "<<fQMax<<" drift time "<<fTotalDriftTime<<" drift
751 // vel "<<fDriftVelocity<<" spot radius "<<fSpotRadius<<endl;
752 // cout<<"fQThreshold "<<fQThreshold<<" fqmax "<<fQMax<<endl;
753 // signal below threshold should be discarded.
754 if (signal->GetCharge() < 0)
755 return (NULL); // Before type casting signed int into unsigned int need to
756 // check for -ve value otherwise after casing -ve int value
757 // will become a large +ve value.
758 else if ((unsigned int) signal->GetCharge() < fQThreshold)
759 return (NULL);
760
761 Long64_t TimeStamp = signal->GetTimeStamp();
762 // Int_t TimeStamp = signal->GetTimeStamp(fQThreshold);
763 // if (TimeStamp < 0) return (NULL);//entire signal is below threshold, no
764 // digi generation.
765
766 CbmMuchDigi* digi = new CbmMuchDigi();
767 digi->SetAddress(signal->GetAddress());
768 // Charge in number of electrons, need to be converted in ADC value
769 // digi->SetAdc((signal->GetCharge())*fNADCChannels/fQMax);//Charge should
770 // be computed as per Electronics Response.
771 Float_t adcValue;
772 adcValue = ((signal->GetCharge() - fQThreshold) * fNADCChannels) / (fQMax - fQThreshold);
773 digi->SetAdc(adcValue + 1); // Charge should be computed as per Electronics
774 // Response. *** modified by Ekata Nandy***
775 // ADC channels number is 32.GEM & RPC has different charge threshold value
776 // and dynamic range, so SetAdc has been changed accordingly. ADC value starts
777 // from 1 to 32. ADC 0 has been excluded as it gives wrong x,y,t in Hit
778 // finder.@modified by Ekata Nandy
779
780 // cout<<" dynamic range "<<(fQMax -fQThreshold)<<" adc "<<digi->GetAdc()<<"
781 // channels "<<fNADCChannels<< "charge "<<signal->GetCharge()<<endl;
782 /* if(module->GetDetectorType()==3)
783 {hadcGEM->Fill(digi->GetAdc());}
784 if(module->GetDetectorType()==4)
785 {hadcRPC->Fill(digi->GetAdc());}
786 */
787 digi->SetTime(TimeStamp);
788
789 // Update times of first and last digi
790 fTimeDigiFirst = fNofDigis ? TMath::Min(fTimeDigiFirst, Double_t(TimeStamp)) : TimeStamp;
791 fTimeDigiLast = TMath::Max(fTimeDigiLast, Double_t(TimeStamp));
792
793 // digi->SetPileUp();
794 // digi->SetDiffEvent();
795 return (digi);
796}
797
798// -------------------------------------------------------------------------
800{
801
802 // --- In event-by-event mode, the analogue buffer should be empty.
803 if (fEventMode) {
804 if (CbmMuchReadoutBuffer::Instance()->GetNData()) {
805 LOG(info) << fName << ": " << CbmMuchReadoutBuffer::Instance()->GetNData() << " signals in readout buffer";
806 LOG(fatal) << fName << ": Readout buffer is not empty at end of run "
807 << "in event-by-event mode!";
808 } //? non-empty buffer
809 } //? event-by-event mode
810
811 else { // time-based mode
812 fTimer.Start();
813 std::cout << std::endl;
814 LOG(info) << GetName() << ": Finish run";
815 Reset();
816 LOG(info) << fName << ": " << CbmMuchReadoutBuffer::Instance()->GetNData() << " signals in readout buffer";
817 ReadAndRegister(-1.); // -1 means process all data
818 LOG(info) << setw(15) << GetName() << ": Finish, points " << fNofPoints << ", signals: " << fNofSignals
819 << ", digis: " << fNofDigis << ". Exec time " << setprecision(6) << fTimer.RealTime() << " s.";
820 LOG(info) << fName << ": " << CbmMuchReadoutBuffer::Instance()->GetNData() << " signals in readout buffer";
821 fTimer.Stop();
825 fTimeTot += fTimer.RealTime();
826 } //? time-based mode
827 // noise->Draw();
828 std::cout << std::endl;
829 LOG(info) << "=====================================";
830 LOG(info) << GetName() << ": Run summary";
831 LOG(info) << "Events processed : " << fNofEvents;
832 LOG(info) << "MuchPoint / event : " << setprecision(1) << fNofPointsTot / Double_t(fNofEvents);
833 LOG(info) << "MuchSignal / event : " << fNofSignalsTot / Double_t(fNofEvents);
834 //<< " / " << fNofSignalsBTot / Double_t(fNofEvents)
835 LOG(info) << "MuchDigi / event : " << fNofDigisTot / Double_t(fNofEvents);
836 LOG(info) << "Digis per point : " << setprecision(6) << fNofDigisTot / fNofPointsTot;
837 LOG(info) << "Digis per signal : " << fNofDigisTot / fNofSignalsTot;
838 LOG(info) << "Noise digis / event : " << fNofNoiseTot / Double_t(fNofEvents);
839 LOG(info) << "Noise fraction : " << fNofNoiseTot / fNofDigisTot;
840
841 LOG(info) << "Real time per event : " << fTimeTot / Double_t(fNofEvents) << " s";
842 LOG(info) << "=====================================";
843
844 /*
846 TFile* oldFile = gFile;
847 TDirectory* oldDir = gDirectory;
848 TFile *f1 =new TFile ("pri_el_info.root","RECREATE");
849 hPriElAfterDriftpathgem->Write();
850 hPriElAfterDriftpathrpc->Write();
851 hadcGEM->Write();
852 hadcRPC->Write();
853 f1->Close();
855 gFile = oldFile;
856 gDirectory = oldDir;
857 */
858 // if (fDaq) ReadAndRegister(-1.);
859}
860// -------------------------------------------------------------------------
861
862// ------- Private method ExecAdvanced -------------------------------------
864{
865
866 // std::cout<<" start execution "<<iPoint<<std::endl;
867 TVector3 v1, v2, dv;
868 point->PositionIn(v1);
869 point->PositionOut(v2);
870 dv = v2 - v1;
871
872 Bool_t Status;
873 Int_t detectorId = point->GetDetectorID();
874 CbmMuchModule* module = fGeoScheme->GetModuleByDetId(detectorId);
875 DetectorParameters(module);
876
877 int detectortype = module->GetDetectorType();
878 // cout<<" dec type === "<<detectortype<<endl;
879 if (fAlgorithm == 0) { // Simple digitization
880 TVector3 v = 0.5 * (v1 + v2);
881 CbmMuchPad* pad = 0;
882 if (module->GetDetectorType() == 1) {
884 pad = module1->GetPad(v[0], v[1]);
885 if (pad) printf("x0=%f,y0=%f\n", pad->GetX(), pad->GetY());
886 }
887 else if (module->GetDetectorType() == 3 || module->GetDetectorType() == 4) {
889 pad = module3->GetPad(v[0], v[1]);
890 }
891 if (!pad) return kFALSE;
892 AddCharge(pad, fQMax, iPoint, point->GetTime(), 0);
893 return kTRUE;
894 }
895
896 // Start of advanced digitization
897 Int_t nElectrons = Int_t(GetNPrimaryElectronsPerCm(point, detectortype) * dv.Mag());
898 if (nElectrons < 0) return kFALSE;
899 // cout<<" nElectrons "<<nElectrons<<endl;
900 /*
901if(detectortype==3)
902{//cout<<" nElectrons "<<nElectrons<<endl;
903hPriElAfterDriftpathgem->Fill(nElectrons);}
904
905if(detectortype==4)
906{//cout<<" nElectrons "<<nElectrons<<endl;
907hPriElAfterDriftpathrpc->Fill(nElectrons);}
908*/
909
910 Double_t time = point->GetTime();
911
912 if (module->GetDetectorType() == 1) {
914 map<CbmMuchSector*, Int_t> firedSectors;
915 for (Int_t i = 0; i < nElectrons; i++) {
916 Double_t aL = gRandom->Rndm();
917 Double_t driftTime = (1 - aL) * fTotalDriftTime;
918 TVector3 ve = v1 + dv * aL;
919 UInt_t ne = GasGain();
920 Double_t x = ve.X();
921 Double_t y = ve.Y();
922 Double_t x1 = x - fSpotRadius;
923 Double_t x2 = x + fSpotRadius;
924 Double_t y1 = y - fSpotRadius;
925 Double_t y2 = y + fSpotRadius;
926 Double_t s = 4 * fSpotRadius * fSpotRadius;
927 firedSectors[module1->GetSector(x1, y1)] = 0;
928 firedSectors[module1->GetSector(x1, y2)] = 0;
929 firedSectors[module1->GetSector(x2, y1)] = 0;
930 firedSectors[module1->GetSector(x2, y2)] = 0;
931 for (map<CbmMuchSector*, Int_t>::iterator it = firedSectors.begin(); it != firedSectors.end(); it++) {
932 CbmMuchSector* sector = (*it).first;
933 if (!sector) continue;
934 for (Int_t iPad = 0; iPad < sector->GetNChannels(); iPad++) {
935 CbmMuchPad* pad = sector->GetPadByChannelIndex(iPad);
936 Double_t xp0 = pad->GetX();
937 Double_t xpd = pad->GetDx() / 2.;
938 Double_t xp1 = xp0 - xpd;
939 Double_t xp2 = xp0 + xpd;
940 if (x1 > xp2 || x2 < xp1) continue;
941 Double_t yp0 = pad->GetY();
942 Double_t ypd = pad->GetDy() / 2.;
943 Double_t yp1 = yp0 - ypd;
944 Double_t yp2 = yp0 + ypd;
945 if (y1 > yp2 || y2 < yp1) continue;
946 Double_t lx = x1 > xp1 ? (x2 < xp2 ? x2 - x1 : xp2 - x1) : x2 - xp1;
947 Double_t ly = y1 > yp1 ? (y2 < yp2 ? y2 - y1 : yp2 - y1) : y2 - yp1;
948 AddCharge(pad, UInt_t(ne * lx * ly / s), iPoint, time, driftTime);
949 }
950 } // loop fired sectors
951 firedSectors.clear();
952 }
953 }
954
955 if (module->GetDetectorType() == 3 || module->GetDetectorType() == 4) {
956 fAddressCharge.clear();
958 if (!module3) {
959 LOG(debug) << GetName() << ": Not Processing MCPoint " << iPoint << " because it is not on any GEM module.";
960 return 1;
961 }
962 CbmMuchSectorRadial* sFirst = (CbmMuchSectorRadial*) module3->GetSectorByIndex(0); // First sector
963 if (!sFirst) {
964 LOG(debug) << GetName() << ": Not Processing MCPoint " << iPoint << " because it is on the module " << module3
965 << " but not the first sector. " << sFirst;
966 return 1;
967 }
968 CbmMuchSectorRadial* sLast =
969 (CbmMuchSectorRadial*) module3->GetSectorByIndex(module3->GetNSectors() - 1); // Last sector
970
971 if (!sLast) {
972 LOG(debug) << GetName() << ": Not Processing MCPoint " << iPoint
973 << " because it is not the last sector of module." << module3;
974 return 1;
975 }
976 Double_t rMin = sFirst->GetR1(); // Mimimum radius of the Sector//5
977 Double_t rMax = sLast->GetR2(); // Maximum radius of the Sector//35
978
979 // cout<<rMin<<" Yeah "<<rMax<<endl;
980 // std::cout<<"min Rad "<<rMin<<" max Rad "<<rMax<<std::endl;
981 // Calculating drifttime once for one track or one MCPoint, not for all the
982 // Primary Electrons generated during DriftGap.
983
984 Double_t driftTime = -1;
985 while (driftTime < 0) {
986
987 Double_t aL = gRandom->Gaus(0.5, 0.133); // Generting random number for calculating Drift Time.
988 // cout<<"Det Type "<<detectortype<<"fTotalDriftTime
989 // "<<fTotalDriftTime<<endl;
990 driftTime = (1 - aL) * fTotalDriftTime;
991 }
992
993 for (Int_t i = 0; i < nElectrons; i++) { // Looping over all the primary electrons
994 Double_t RandomNumberForPrimaryElectronPosition = gRandom->Rndm();
995 TVector3 ve = v1 + dv * RandomNumberForPrimaryElectronPosition;
996
997 //------------------------Added by O. Singh 11.12.2017 for
998 // mCbm-------------------------
999 Double_t r = 0.0, phi = 0.0;
1000 if (fFlag == 1) { // mCbm
1001 if (module->GetDetectorType() == 3) // GEM
1002 {
1003 ve.SetX(ve.X() - fGemTX);
1004 ve.SetY(ve.Y() - fGemTY);
1005 }
1006 else if (module->GetDetectorType() == 4) // RPC
1007 {
1008 ve.SetX(ve.X() - fRpcTX);
1009 ve.SetY(ve.Y() - fRpcTY);
1010 }
1011 else {
1012 LOG(error) << "Unknown detector type";
1013 }
1014 }
1015 r = ve.Perp();
1016 phi = ve.Phi();
1017 //--------------------------------------------------------------------------
1018 UInt_t ne = GasGain(); // Number of secondary electrons
1019 Double_t r1 = r - fSpotRadius;
1020 Double_t r2 = r + fSpotRadius;
1021 Double_t phi1 = phi - fSpotRadius / r;
1022 Double_t phi2 = phi + fSpotRadius / r;
1023 // cout<<" fSpotRadius "<<fSpotRadius<<endl;
1024 if (r1 < rMin && r2 > rMin) { // Adding charge to the pad which is on Lower Boundary
1025 Status = AddCharge(sFirst, UInt_t(ne * (r2 - rMin) / (r2 - r1)), iPoint, time, driftTime, phi1, phi2);
1026 if (!Status)
1027 LOG(debug) << GetName() << ": Processing MCPoint " << iPoint << " in which Primary Electron : " << i
1028 << " not contributed charge. ";
1029 continue;
1030 }
1031 if (r1 < rMax && r2 > rMax) { // Adding charge to the pad which is on Upper Boundary
1032 Status = AddCharge(sLast, UInt_t(ne * (rMax - r1) / (r2 - r1)), iPoint, time, driftTime, phi1, phi2);
1033 if (!Status)
1034 LOG(debug) << GetName() << ": Processing MCPoint " << iPoint << " in which Primary Electron : " << i
1035 << " not contributed charge. ";
1036 continue;
1037 }
1038 if (r1 < rMin && r2 < rMin) continue;
1039 if (r1 > rMax && r2 > rMax) continue;
1040
1041 CbmMuchSectorRadial* s1 = module3->GetSectorByRadius(r1);
1042 CbmMuchSectorRadial* s2 = module3->GetSectorByRadius(r2);
1043
1044 if (s1 == s2) {
1045 Status = AddCharge(s1, ne, iPoint, time, driftTime, phi1, phi2);
1046 if (!Status)
1047 LOG(debug3) << GetName() << ": Processing MCPoint " << iPoint << " in which Primary Electron : " << i
1048 << " not contributed charge. ";
1049 }
1050 else { // Adding praportionate charge to both the pad
1051 Status = AddCharge(s1, UInt_t(ne * (s1->GetR2() - r1) / (r2 - r1)), iPoint, time, driftTime, phi1, phi2);
1052 if (!Status)
1053 LOG(debug3) << GetName() << ": Processing MCPoint " << iPoint << " in which Primary Electron : " << i
1054 << " not contributed charge. ";
1055 Status = AddCharge(s2, UInt_t(ne * (r2 - s2->GetR1()) / (r2 - r1)), iPoint, time, driftTime, phi1, phi2);
1056 if (!Status)
1057 LOG(debug3) << GetName() << ": Processing MCPoint " << iPoint << " in which Primary Electron : " << i
1058 << " not contributed charge. ";
1059 }
1060 }
1061
1062 // Generate CbmMuchSignal for each entry of fAddressCharge and store in the
1063 // CbmMuchReadoutBuffer
1064 if (!BufferSignals(iPoint, time, driftTime))
1065 LOG(debug3) << GetName() << ": Processing MCPoint " << iPoint << " nothing is buffered. ";
1066 fAddressCharge.clear();
1067 LOG(debug1) << GetName() << ": fAddressCharge size is " << fAddressCharge.size() << " Cleared fAddressCharge. ";
1068 }
1069 // std::cout<<" Execution completed for point # "<<iPoint<<std::endl;
1070 return kTRUE;
1071}
1072// -------------------------------------------------------------------------
1073
1074// -------------------------------------------------------------------------
1076{
1077 // cout<<" mean gain "<<fMeanGasGain<<endl;
1078 Double_t gasGain = -fMeanGasGain * TMath::Log(1 - gRandom->Rndm());
1079 if (gasGain < 0.) gasGain = 1e6;
1080 return (Int_t) gasGain;
1081}
1082// -------------------------------------------------------------------------
1083
1084// -------------------------------------------------------------------------
1085Double_t CbmMuchDigitizeGem::Sigma_n_e(Double_t Tkin, Double_t mass)
1086{
1087 Double_t logT;
1088 if (mass < 0.1) {
1089 logT = log(Tkin * 0.511 / mass);
1090 if (logT > 9.21034) logT = 9.21034;
1091 if (logT < min_logT_e) logT = min_logT_e;
1092 return fSigma[0]->Eval(logT);
1093 }
1094 else if (mass >= 0.1 && mass < 0.2) {
1095 logT = log(Tkin * 105.658 / mass);
1096 if (logT > 9.21034) logT = 9.21034;
1097 if (logT < min_logT_mu) logT = min_logT_mu;
1098 return fSigma[1]->Eval(logT);
1099 }
1100 else {
1101 logT = log(Tkin * 938.272 / mass);
1102 if (logT > 9.21034) logT = 9.21034;
1103 if (logT < min_logT_p) logT = min_logT_p;
1104 return fSigma[2]->Eval(logT);
1105 }
1106}
1107// -------------------------------------------------------------------------
1108
1109// -------------------------------------------------------------------------
1110Double_t CbmMuchDigitizeGem::MPV_n_e(Double_t Tkin, Double_t mass)
1111{
1112 Double_t logT;
1113 if (mass < 0.1) {
1114 logT = log(Tkin * 0.511 / mass);
1115 if (logT > 9.21034) logT = 9.21034;
1116 if (logT < min_logT_e) logT = min_logT_e;
1117 return fMPV[0]->Eval(logT);
1118 }
1119 else if (mass >= 0.1 && mass < 0.2) {
1120 logT = log(Tkin * 105.658 / mass);
1121 if (logT > 9.21034) logT = 9.21034;
1122 if (logT < min_logT_mu) logT = min_logT_mu;
1123 return fMPV[1]->Eval(logT);
1124 }
1125 else {
1126 logT = log(Tkin * 938.272 / mass);
1127 if (logT > 9.21034) logT = 9.21034;
1128 if (logT < min_logT_p) logT = min_logT_p;
1129 return fMPV[2]->Eval(logT);
1130 }
1131}
1132// -------------------------------------------------------------------------
1133
1134// -------------------------------------------------------------------------
1135Double_t CbmMuchDigitizeGem::GetNPrimaryElectronsPerCm(const CbmMuchPoint* point, int detectortype)
1136{
1137 Int_t trackId = point->GetTrackID();
1138 // Int_t eventId = point->GetEventID();
1139 if (trackId < 0) return -1;
1140 /* Commented out on request of A. Senger from 22.01.2014
1141 if (fDaq &&
1142 eventId!=FairRootManager::Instance()->GetInTree()->GetBranch("MCTrack")->GetReadEntry())
1143 FairRootManager::Instance()->GetInTree()->GetBranch("MCTrack")->GetEntry(eventId);
1144 */
1145 CbmMCTrack* mcTrack = (CbmMCTrack*) fMCTracks->At(trackId);
1146
1147 if (!mcTrack) return -1;
1148 Int_t pdgCode = mcTrack->GetPdgCode();
1149
1150 TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(pdgCode);
1151 // Assign proton hypothesis for unknown particles
1152 if (!particle) particle = TDatabasePDG::Instance()->GetParticle(2212);
1153 if (TMath::Abs(particle->Charge()) < 0.1) return -1;
1154
1155 Double_t m = particle->Mass();
1156 TLorentzVector p;
1157 p.SetXYZM(point->GetPx(), point->GetPy(), point->GetPz(), m);
1158 Double_t Tkin = p.E() - m; // kinetic energy of the particle
1159 Double_t sigma = CbmMuchDigitizeGem::Sigma_n_e(Tkin, m); // sigma for Landau distribution
1160 Double_t mpv = CbmMuchDigitizeGem::MPV_n_e(Tkin, m); // most probable value for Landau distr.
1161 Double_t n;
1162 Double_t mpvRpc = 50.0; // For RPC MPV and sigma is taken to produce final
1163 // landau in accordance with experimental value
1164 Double_t sigmaRpc = 12.0;
1165 // cout<<" dec type function "<<detectortype<<endl;
1166 if (detectortype == 3)
1167 {
1168 n = gRandom->Landau(mpv, sigma);
1169 while (n > 5e4)
1170 n = gRandom->Landau(mpv, sigma); // restrict Landau tail to increase performance
1171 return m < 0.1 ? n / l_e : n / l_not_e;
1172 }
1173 if (detectortype == 4)
1174 {
1175 n = gRandom->Landau(mpvRpc, sigmaRpc);
1176 while (n > 5e4)
1177 n = gRandom->Landau(mpvRpc, sigmaRpc); // restrict Landau tail to increase performance
1178 return n;
1179 }
1180 // for all other cases will return -1.
1181 return -1;
1182}
1183// -------------------------------------------------------------------------
1184// -------------------------------------------------------------------------
1185Bool_t CbmMuchDigitizeGem::AddCharge(CbmMuchSectorRadial* s, UInt_t ne, Int_t /*iPoint*/, Double_t /*time*/,
1186 Double_t /*driftTime*/, Double_t phi1, Double_t phi2)
1187{
1188 CbmMuchPadRadial* pad1 = s->GetPadByPhi(phi1);
1189 if (!pad1)
1190 pad1 = s->GetPadByPhi((phi1 + phi2) / 2.0); // This condition helps us deal with boundary pads
1191 else // Special case if pad size is smaller than spot radius
1192 {
1193 for (Double_t phi = phi1; phi < (phi1 + phi2) / 2.0; phi += 0.1) // This may potentially slow down the code
1194 {
1195 pad1 = s->GetPadByPhi(phi);
1196 if (pad1) break;
1197 }
1198 }
1199 if (!pad1) return kFALSE;
1200 // assert(pad1); has to check if any pad address is NULL
1201 CbmMuchPadRadial* pad2 = s->GetPadByPhi(phi2);
1202 if (!pad2)
1203 pad2 = s->GetPadByPhi((phi1 + phi2) / 2.0); // This condition helps us deal with boundary pads
1204 else // Special case if pad size is smaller than spot radius
1205 {
1206 for (Double_t phi = phi2; phi > (phi1 + phi2) / 2.0; phi -= 0.1) // This may potentially slow down the code
1207 {
1208 pad2 = s->GetPadByPhi(phi);
1209 if (pad2) break;
1210 }
1211 }
1212
1213 if (!pad2) return kFALSE;
1214 // assert(pad2); has to check if any pad address is NULL
1215 if (pad1 == pad2) {
1216 UInt_t address = pad1->GetAddress();
1217 // Finding that if for the same address if already charge stored then add
1218 // the charge.
1219 std::map<UInt_t, UInt_t>::iterator it = fAddressCharge.find(address);
1220 if (it != fAddressCharge.end())
1221 it->second = it->second + ne;
1222 else
1223 fAddressCharge.insert(std::pair<UInt_t, UInt_t>(address, ne));
1224 // AddChargePerMC(pad1,ne,iPoint,time,driftTime);
1225 }
1226 else {
1227 Double_t phi = pad1 ? pad1->GetPhi2() : pad2 ? pad2->GetPhi1() : 0;
1228 UInt_t pad1_ne = UInt_t(ne * (phi - phi1) / (phi2 - phi1));
1229
1230 UInt_t address = pad1->GetAddress();
1231 // Finding that if for the same address if already charge stored then add
1232 // the charge.
1233 std::map<UInt_t, UInt_t>::iterator it = fAddressCharge.find(address);
1234 if (it != fAddressCharge.end())
1235 it->second = it->second + pad1_ne;
1236 else
1237 fAddressCharge.insert(std::pair<UInt_t, UInt_t>(address, pad1_ne));
1238 // AddChargePerMC(pad1,pad1_ne ,iPoint,time,driftTime);
1239
1240 // Getting some segmentation fault a
1241 address = pad2->GetAddress();
1242 // Finding that if for the same address if already charge stored then add
1243 // the charge.
1244 it = fAddressCharge.find(address);
1245 if (it != fAddressCharge.end())
1246 it->second = it->second + ne - pad1_ne;
1247 else
1248 fAddressCharge.insert(std::pair<UInt_t, UInt_t>(address, ne - pad1_ne));
1249 // AddChargePerMC(pad2,ne-pad1_ne,iPoint,time,driftTime);
1250 }
1251 return kTRUE;
1252}
1253// -------------------------------------------------------------------------
1254
1255// -------------------------------------------------------------------------
1256// Will remove this AddCharge, only used for simple and Rectangular Geometry.
1257void CbmMuchDigitizeGem::AddCharge(CbmMuchPad* pad, UInt_t charge, Int_t iPoint, Double_t time, Double_t driftTime)
1258{
1259 if (!pad) return;
1260
1261 Long_t AbsTime = fCurrentEventTime + time + driftTime;
1262
1263 // Creating a new Signal, it will be deleted by CbmReadoutBuffer()
1264 CbmMuchSignal* signal = new CbmMuchSignal(pad->GetAddress(), AbsTime);
1265 // signal->SetTimeStart(AbsTime);
1266 // signal->SetTimeStop(AbsTime+fDeadTime);
1267 signal->SetCharge(charge);
1268 // signal->MakeSignalShape(charge,fgDeltaResponse);
1269 signal->AddNoise(fMeanNoise);
1270 UInt_t address = pad->GetAddress();
1271 // match->AddCharge(iPoint,charge,time+driftTime,fgDeltaResponse,time,eventNr,inputNr);
1272 CbmLink link(charge, iPoint, fCurrentMCEntry, fCurrentInput);
1273 // std::cout<<"Before AddLink"<< endl;
1274 (signal->GetMatch())->AddLink(link);
1275 // std::cout<<"After AddLink"<< endl;
1276 // Adding all these temporary signal into the CbmMuchReadoutBuffer
1277 CbmMuchReadoutBuffer::Instance()->Fill(address, signal);
1278 // Increasing number of signal by one.
1279 fNofSignals++;
1280 LOG(debug4) << " Registered the CbmMuchSignal into the CbmMuchReadoutBuffer ";
1281
1282} // end of AddCharge
1283
1284//----------------------------------------------------------
1285Bool_t CbmMuchDigitizeGem::BufferSignals(Int_t iPoint, Double_t time, Double_t driftTime)
1286{
1287
1288 if (!fAddressCharge.size()) {
1289 LOG(debug2) << "Buffering MC Point " << iPoint << " but fAddressCharge size is " << fAddressCharge.size()
1290 << "so nothing to Buffer for this MCPoint.";
1291 return kFALSE;
1292 }
1293 UInt_t AbsTime = fCurrentEventTime + time + driftTime;
1294 LOG(debug2) << GetName() << ": Processing event " << fCurrentEvent << " from input " << fCurrentInput
1295 << " at t = " << fCurrentEventTime << " ns with " << fPoints->GetEntriesFast() << " MuchPoints "
1296 << " and Number of pad hit is " << fAddressCharge.size() << ".";
1297 // Loop on the fAddressCharge to store all the Signals into the
1298 // CbmReadoutBuffer() Generate one by one CbmMuchSignal from the
1299 // fAddressCharge and store them into the CbmMuchReadoutBuffer.
1300 for (auto it = fAddressCharge.begin(); it != fAddressCharge.end(); ++it) {
1301 UInt_t address = it->first;
1302 // Creating a new Signal, it will be deleted by CbmReadoutBuffer()
1303 CbmMuchSignal* signal = new CbmMuchSignal(address, AbsTime);
1304 // signal->SetTimeStart(AbsTime);
1305 // signal->SetTimeStop(AbsTime+fDeadTime);
1306 // signal->MakeSignalShape(it->second,fgDeltaResponse);
1307 signal->SetCharge(it->second);
1308 signal->AddNoise(fMeanNoise);
1309 CbmLink link(signal->GetCharge(), iPoint, fCurrentMCEntry, fCurrentInput);
1310 (signal->GetMatch())->AddLink(link);
1311 // Adding all these temporary signal into the CbmMuchReadoutBuffer
1312 CbmMuchReadoutBuffer::Instance()->Fill(address, signal);
1313 // Increasing number of signal by one.
1314 fNofSignals++;
1315 LOG(debug3) << " Registered the CbmMuchSignal into the CbmMuchReadoutBuffer ";
1316 }
1317
1318 LOG(debug2) << GetName() << ": For MC Point " << iPoint << " buffered " << fAddressCharge.size()
1319 << " CbmMuchSignal into the CbmReadoutBuffer.";
1320 return kTRUE;
1321} // end of BufferSignals
1322// -------------------------------------------------------------------------
1323
ClassImp(CbmConverterManager)
constexpr double min_logT_e
constexpr double sigma_mu[]
constexpr double l_e
constexpr double sigma_p[]
constexpr double l_not_e
constexpr double mpv_e[]
constexpr double mpv_p[]
constexpr double min_logT_p
constexpr double sigma_e[]
constexpr double mpv_mu[]
constexpr double min_logT_mu
static const Int_t fDeadTime
fscal v[fmask::Size]
Definition KfSimdPseudo.h:4
friend fvec log(const fvec &a)
float Float_t
int Int_t
bool Bool_t
virtual std::pair< size_t, bool > ReadInactiveChannels()
Set of inactive channels, indicated by CbmAddress.
Int_t fCurrentEvent
Number of current input.
TString fInactiveChannelFileName
Time of current MC event [ns].
std::set< uint32_t > fInactiveChannels
Name of file with inactive channels.
void GetEventInfo()
Get event information.
Int_t fCurrentInput
Start time of run [ns].
Double_t fCurrentEventTime
Number of current MC entry.
Int_t fCurrentMCEntry
Number of current MC event.
Base class template for CBM digitisation tasks.
Definition CbmDigitize.h:44
void SendData(Double_t time, CbmMuchDigi *digi, CbmMatch *match=nullptr)
int32_t GetPdgCode() const
Definition CbmMCTrack.h:68
static int32_t GetSectorIndex(int32_t address)
static int32_t GetChannelIndex(int32_t address)
static int32_t GetLayerIndex(int32_t address)
static int32_t GetLayerSideIndex(int32_t address)
static int32_t GetStationIndex(int32_t address)
void SetAddress(int32_t address)
void SetTime(uint64_t time)
int32_t GetAddress() const
Definition CbmMuchDigi.h:93
void SetAdc(int32_t adc)
double GetTime() const
Definition CbmMuchDigi.h:94
Int_t fNofDigis
Number of created digis in Exec.
Double_t MPV_n_e(Double_t Tkin, Double_t mass)
Int_t fNofEvents
Total number of events processed.
Int_t fNofSignals
Number of signals.
void DetectorParameters(CbmMuchModule *module)
CbmMuchGeoScheme * fGeoScheme
Double_t fTimeDigiLast
Time of last digi sent to DAQ.
Int_t GenerateNoisePerModule(CbmMuchModuleGem *, Double_t, Double_t)
Double_t fTimeTot
Total execution time.
void AddNoiseSignal(CbmMuchPad *, Double_t, Double_t)
Bool_t ExecPoint(const CbmMuchPoint *point, Int_t)
Double_t fTimeDigiFirst
Time of first digi sent to DAQ.
virtual void Exec(Option_t *opt)
Bool_t BufferSignals(Int_t, Double_t, Double_t)
Bool_t AddCharge(CbmMuchSectorRadial *s, UInt_t ne, Int_t iPoint, Double_t time, Double_t driftTime, Double_t phi1, Double_t phi2)
Double_t GetNPrimaryElectronsPerCm(const CbmMuchPoint *point, int detectortype)
Int_t fNofNoiseTot
Set this boolean variable to True if want to generated Elecronics Noise.
Int_t fNofPoints
Number of points processed in Exec.
Double_t Sigma_n_e(Double_t Tkin, Double_t mass)
Bool_t fGenerateElectronicsNoise
Previous Event Time.
std::map< UInt_t, UInt_t > fAddressCharge
Function to sample the noise charge.
Double_t fNofSignalsTot
Total Number of signals.
Double_t fNofDigisTot
Total number of digis created.
Double_t fNofPointsTot
Total number of points processed.
Int_t GenerateNoise(Double_t, Double_t)
virtual InitStatus Init()
CbmMuchDigi * ConvertSignalToDigi(CbmMuchSignal *)
CbmMuchStation * GetStation(Int_t iStation) const
void Init(TObjArray *stations, Int_t flag)
Int_t GetNStations() const
CbmMuchModule * GetModuleByDetId(Int_t detId) const
Int_t GetNModules() const
CbmMuchModule * GetModule(Int_t iModule) const
CbmMuchLayerSide * GetSide(Bool_t side)
CbmMuchPadRadial * GetPad(Double_t x, Double_t y)
CbmMuchSectorRadial * GetSectorByRadius(Double_t r)
CbmMuchSectorRectangular * GetSector(Double_t x, Double_t y)
CbmMuchPadRectangular * GetPad(Double_t x, Double_t y)
CbmMuchSector * GetSectorByIndex(Int_t iSector)
Int_t GetNSectors() const
Int_t GetDetectorType() const
Double_t GetPhi2() const
Double_t GetPhi1() const
Double_t GetX() const
Definition CbmMuchPad.h:32
Double_t GetDy() const
Definition CbmMuchPad.h:35
Int_t GetAddress() const
Definition CbmMuchPad.h:31
Double_t GetDx() const
Definition CbmMuchPad.h:34
Double_t GetY() const
Definition CbmMuchPad.h:33
void PositionIn(TVector3 &pos) const
void PositionOut(TVector3 &pos) const
static CbmMuchReadoutBuffer * Instance()
CbmMuchPadRadial * GetPadByPhi(Double_t phi)
Int_t GetNChannels() const
CbmMuchPad * GetPadByChannelIndex(Int_t iChannel) const
Data class for an analog signal in the MUCH Simple data class used in the digitisation process of the...
void AddNoise(UInt_t)
UInt_t GetCharge() const
Long64_t GetTimeStamp()
CbmMatch * GetMatch() const
Int_t GetAddress() const
void SetCharge(UInt_t charge)
CbmMuchLayer * GetLayer(Int_t iLayer) const
Int_t GetNLayers() const
Int_t ReadOutData(Double_t time, std::vector< Data * > &dataList)
void Fill(UInt_t address, Data *data)
virtual Int_t GetNData()