42 #include "FairEventHeader.h"
43 #include "FairLogger.h"
44 #include "FairMCEventHeader.h"
45 #include "FairMCPoint.h"
46 #include "FairRootManager.h"
47 #include "FairRunAna.h"
48 #include "FairRunSim.h"
53 #include "TDatabasePDG.h"
56 #include "TObjArray.h"
58 #include <TGeoManager.h>
73 using std::setprecision;
113 , fTotalDriftTime(-1)
133 fPerPadNoiseRate(10e-9)
134 , fGenerateElectronicsNoise(kFALSE)
135 , fNoiseCharge(nullptr)
137 fSigma[0] =
new TF1(
"sigma_e",
"pol6", -5, 10);
140 fSigma[1] =
new TF1(
"sigma_mu",
"pol6", -5, 10);
143 fSigma[2] =
new TF1(
"sigma_p",
"pol6", -5, 10);
146 fMPV[0] =
new TF1(
"mpv_e",
"pol6", -5, 10);
149 fMPV[1] =
new TF1(
"mpv_mu",
"pol6", -5, 10);
152 fMPV[2] =
new TF1(
"mpv_p",
"pol6", -5, 10);
157 "TMath::Gaus(x, [0], [1])",
172 , fDigiFile(digiFileName)
200 , fTotalDriftTime(-1)
220 , fPerPadNoiseRate(10e-9)
221 , fGenerateElectronicsNoise(kFALSE)
222 , fNoiseCharge(nullptr)
224 fSigma[0] =
new TF1(
"sigma_e",
"pol6", -5, 10);
227 fSigma[1] =
new TF1(
"sigma_mu",
"pol6", -5, 10);
230 fSigma[2] =
new TF1(
"sigma_p",
"pol6", -5, 10);
233 fMPV[0] =
new TF1(
"mpv_e",
"pol6", -5, 10);
236 fMPV[1] =
new TF1(
"mpv_mu",
"pol6", -5, 10);
239 fMPV[2] =
new TF1(
"mpv_p",
"pol6", -5, 10);
244 "TMath::Gaus(x, [0], [1])",
288 auto DriftVolumeWidth = module->
GetSize().Z();
302 auto DriftVolumeWidth = module->
GetSize().Z();
318 std::cout << std::endl;
319 LOG(info) <<
"==========================================================";
320 LOG(info) << GetName() <<
": Initialisation\n";
322 FairRootManager* ioman = FairRootManager::Instance();
323 if (!ioman) Fatal(
"Init",
"No FairRootManager");
325 if (
fEventMode) { LOG(info) << fName <<
": Using event-by-event mode"; }
336 gGeoManager->CdTop();
337 TGeoNode* cave = gGeoManager->GetCurrentNode();
339 for (Int_t iNode = 0; iNode < cave->GetNdaughters(); iNode++) {
340 TString name = cave->GetDaughter(iNode)->GetVolume()->GetName();
341 if (name.Contains(
"much", TString::kIgnoreCase)) {
342 if (name.Contains(
"mcbm", TString::kIgnoreCase)) {
343 geoTag = TString(name(5, name.Length()));
345 geoTag = TString(name(5, name.Length() - 5));
348 cout <<
" geo tag " << geoTag << endl;
349 LOG(info) << fName <<
": MUCH geometry tag is " << geoTag;
360 <<
": no parameter file specified and no MUCH node found in geometry!";
361 fDigiFile = gSystem->Getenv(
"VMCWORKDIR");
364 if (geoTag.Contains(
"mcbm", TString::kIgnoreCase)) {
365 fDigiFile +=
"/parameters/much/much_" + geoTag +
"_digi_sector.root";
368 "/parameters/much/much_" + geoTag(0, 4) +
"_digi_sector.root";
372 LOG(info) << fName <<
": Using parameter file " <<
fDigiFile;
374 fFlag = (geoTag.Contains(
"mcbm", TString::kIgnoreCase) ? 1 : 0);
375 LOG(info) << fName <<
": Using flag " <<
fFlag
376 << (
fFlag ?
" (mcbm) " :
"(standard)");
381 TFile* oldfile = gFile;
384 LOG(fatal) << fName <<
": parameter file " <<
fDigiFile
385 <<
" does not exist!";
386 TObjArray* stations = (TObjArray*) file->Get(
"stations");
423 fPoints = (TClonesArray*) ioman->GetObject(
"MuchPoint");
427 fMCTracks = (TClonesArray*) ioman->GetObject(
"MCTrack");
466 LOG(info) << GetName() <<
": Initialisation successful";
467 LOG(info) <<
"==========================================================";
468 std::cout << std::endl;
484 LOG(debug) << GetName() <<
": Processing event " <<
fCurrentEvent
487 <<
fPoints->GetEntriesFast() <<
" MuchPoints ";
491 for (Int_t iPoint = 0; iPoint <
fPoints->GetEntriesFast(); iPoint++) {
493 LOG(debug1) << GetName() <<
": Processing MCPoint " << iPoint;
505 LOG(info) <<
"+ " << setw(20) << GetName() <<
": Generated " << nNoise
508 <<
" total noise generated till now.";
509 LOG(debug3) <<
"+ " << setw(20) << GetName() <<
": Generated "
511 <<
" noise signals for this time slice from t = "
523 LOG(info) <<
"+ " << setw(15) << GetName() <<
": Event " << setw(6) << right
527 <<
". Exec time " << setprecision(6) <<
fTimer.RealTime() <<
" s.";
542 LOG(debug) <<
"+ " << setw(20) << GetName() <<
": Previous event time " << t1
543 <<
" Current event time " << t2 <<
" ns.";
546 <<
": Previous event time " << t1
547 <<
" is greater than Current event time " << t2
548 <<
". No electronics noise signal generated for "
553 auto StationNoise = 0;
554 for (Int_t
i = 0;
i < numberofstations;
i++) {
557 if (numberoflayers <= 0)
continue;
560 for (Int_t j = 0; j < numberoflayers; j++) {
563 if (numberofmodules <= 0)
continue;
565 auto FrontModuleNoise = 0;
566 for (
auto k = 0; k < numberofmodules; k++) {
574 if (numberofmodules <= 0)
continue;
575 auto BackModuleNoise = 0;
576 for (
auto k = 0; k < numberofmodules; k++) {
582 LayerNoise += FrontModuleNoise + BackModuleNoise;
584 LOG(debug1) <<
"+ " << setw(20) << GetName() <<
": Generated "
585 << LayerNoise <<
" noise signals in station " <<
i
588 StationNoise += LayerNoise;
598 auto NumberOfPad = module->
GetNPads();
600 Int_t nNoise = gRandom->Poisson(nNoiseMean);
601 LOG(debug) <<
"+ " << setw(20) << GetName()
602 <<
": Number of noise signals : " << nNoise <<
" in one module. ";
603 for (Int_t iNoise = 0; iNoise <= nNoise; iNoise++) {
604 Int_t padnumber = Int_t(gRandom->Uniform(Double_t(NumberOfPad)));
606 Double_t NoiseTime = gRandom->Uniform(t1, t2);
622 LOG(debug3) << GetName() <<
": Receiving signal " << charge <<
" in channel "
623 << pad->
GetAddress() <<
" at time " << time <<
"ns";
634 LOG(debug3) <<
"+ " << setw(20) << GetName()
635 <<
": Registered a Noise CbmMuchSignal into the "
636 "CbmMuchReadoutBuffer. Number of Noise Signal generated "
644 std::vector<CbmMuchSignal*> SignalList;
651 Int_t ReadOutSignal =
653 LOG(debug) << GetName() <<
": Number of Signals read out from Buffer "
654 << ReadOutSignal <<
" and SignalList contain " << SignalList.size()
657 for (std::vector<CbmMuchSignal*>::iterator LoopOver = SignalList.begin();
658 LoopOver != SignalList.end();
662 new CbmMatch(*(*LoopOver)->GetMatch());
665 LOG(debug2) << GetName()
666 <<
": Digi not created as signal is below threshold.";
668 LOG(debug2) << GetName() <<
": New digi: sector = "
678 LOG(debug) << GetName() <<
": " <<
fNofDigis
679 << (
fNofDigis == 1 ?
" digi " :
" digis ")
680 <<
"created and sent to DAQ ";
682 LOG(debug) <<
"( from " << fixed << setprecision(3) <<
fTimeDigiFirst
688 for (
auto signal : SignalList) {
763 <<
" signals in readout buffer";
764 LOG(fatal) << fName <<
": Readout buffer is not empty at end of run "
765 <<
"in event-by-event mode!";
771 std::cout << std::endl;
772 LOG(info) << GetName() <<
": Finish run";
775 <<
" signals in readout buffer";
777 LOG(info) << setw(15) << GetName() <<
": Finish, points " <<
fNofPoints
779 <<
". Exec time " << setprecision(6) <<
fTimer.RealTime()
782 <<
" signals in readout buffer";
790 std::cout << std::endl;
791 LOG(info) <<
"=====================================";
792 LOG(info) << GetName() <<
": Run summary";
793 LOG(info) <<
"Events processed : " <<
fNofEvents;
794 LOG(info) <<
"MuchPoint / event : " << setprecision(1)
796 LOG(info) <<
"MuchSignal / event : "
800 LOG(info) <<
"Digis per point : " << setprecision(6)
808 LOG(info) <<
"=====================================";
832 Int_t detectorId = point->GetDetectorID();
839 TVector3
v = 0.5 * (v1 + v2);
845 if (pad) printf(
"x0=%f,y0=%f\n", pad->
GetX(), pad->
GetY());
851 if (!pad)
return kFALSE;
859 if (nElectrons < 0)
return kFALSE;
871 Double_t time = point->GetTime();
876 map<CbmMuchSector*, Int_t> firedSectors;
877 for (Int_t
i = 0;
i < nElectrons;
i++) {
878 Double_t aL = gRandom->Rndm();
880 TVector3 ve = v1 + dv * aL;
889 firedSectors[module1->
GetSector(x1, y1)] = 0;
890 firedSectors[module1->
GetSector(x1, y2)] = 0;
891 firedSectors[module1->
GetSector(x2, y1)] = 0;
892 firedSectors[module1->
GetSector(x2, y2)] = 0;
893 for (map<CbmMuchSector*, Int_t>::iterator it = firedSectors.begin();
894 it != firedSectors.end();
897 if (!sector)
continue;
898 for (Int_t iPad = 0; iPad < sector->
GetNChannels(); iPad++) {
900 Double_t xp0 = pad->
GetX();
901 Double_t xpd = pad->
GetDx() / 2.;
902 Double_t xp1 = xp0 - xpd;
903 Double_t xp2 = xp0 + xpd;
904 if (x1 > xp2 || x2 < xp1)
continue;
905 Double_t yp0 = pad->
GetY();
906 Double_t ypd = pad->
GetDy() / 2.;
907 Double_t yp1 = yp0 - ypd;
908 Double_t yp2 = yp0 + ypd;
909 if (y1 > yp2 || y2 < yp1)
continue;
910 Double_t lx = x1 > xp1 ? (x2 < xp2 ? x2 - x1 : xp2 - x1) : x2 - xp1;
911 Double_t ly = y1 > yp1 ? (y2 < yp2 ? y2 - y1 : yp2 - y1) : y2 - yp1;
912 AddCharge(pad, UInt_t(ne * lx * ly / s), iPoint, time, driftTime);
915 firedSectors.clear();
923 LOG(debug) << GetName() <<
": Not Processing MCPoint " << iPoint
924 <<
" because it is not on any GEM module.";
930 LOG(debug) << GetName() <<
": Not Processing MCPoint " << iPoint
931 <<
" because it is on the module " << module3
932 <<
" but not the first sector. " << sFirst;
940 LOG(debug) << GetName() <<
": Not Processing MCPoint " << iPoint
941 <<
" because it is not the last sector of module." << module3;
944 Double_t rMin = sFirst->
GetR1();
945 Double_t rMax = sLast->
GetR2();
951 Double_t driftTime = -1;
952 while (driftTime < 0) {
954 Double_t aL = gRandom->Gaus(
960 for (Int_t
i = 0;
i < nElectrons;
962 Double_t RandomNumberForPrimaryElectronPosition = gRandom->Rndm();
963 TVector3 ve = v1 + dv * RandomNumberForPrimaryElectronPosition;
966 Double_t r = 0.0, phi = 0.0;
969 Double_t XX = ve.X();
970 Double_t YY = ve.Y();
971 Double_t ZZ = ve.Z();
978 Double_t nXX = XX - tX;
979 Double_t nYY = YY - tY;
1003 UInt_t(ne * (r2 - rMin) / (r2 - r1)),
1010 LOG(debug) << GetName() <<
": Processing MCPoint " << iPoint
1011 <<
" in which Primary Electron : " <<
i
1012 <<
" not contributed charge. ";
1018 UInt_t(ne * (rMax - r1) / (r2 - r1)),
1025 LOG(debug) << GetName() <<
": Processing MCPoint " << iPoint
1026 <<
" in which Primary Electron : " <<
i
1027 <<
" not contributed charge. ";
1030 if (r1 < rMin && r2 < rMin)
continue;
1031 if (r1 > rMax && r2 > rMax)
continue;
1038 Status =
AddCharge(s1, ne, iPoint, time, driftTime, phi1, phi2);
1040 LOG(debug3) << GetName() <<
": Processing MCPoint " << iPoint
1041 <<
" in which Primary Electron : " <<
i
1042 <<
" not contributed charge. ";
1045 UInt_t(ne * (s1->
GetR2() - r1) / (r2 - r1)),
1052 LOG(debug3) << GetName() <<
": Processing MCPoint " << iPoint
1053 <<
" in which Primary Electron : " <<
i
1054 <<
" not contributed charge. ";
1056 UInt_t(ne * (r2 - s2->
GetR1()) / (r2 - r1)),
1063 LOG(debug3) << GetName() <<
": Processing MCPoint " << iPoint
1064 <<
" in which Primary Electron : " <<
i
1065 <<
" not contributed charge. ";
1071 LOG(debug3) << GetName() <<
": Processing MCPoint " << iPoint
1072 <<
" nothing is buffered. ";
1074 LOG(debug1) << GetName() <<
": fAddressCharge size is "
1085 Double_t gasGain = -
fMeanGasGain * TMath::Log(1 - gRandom->Rndm());
1086 if (gasGain < 0.) gasGain = 1e6;
1087 return (Int_t) gasGain;
1095 logT =
log(Tkin * 0.511 / mass);
1096 if (logT > 9.21034) logT = 9.21034;
1098 return fSigma[0]->Eval(logT);
1099 }
else if (mass >= 0.1 && mass < 0.2) {
1100 logT =
log(Tkin * 105.658 / mass);
1101 if (logT > 9.21034) logT = 9.21034;
1103 return fSigma[1]->Eval(logT);
1105 logT =
log(Tkin * 938.272 / mass);
1106 if (logT > 9.21034) logT = 9.21034;
1108 return fSigma[2]->Eval(logT);
1117 logT =
log(Tkin * 0.511 / mass);
1118 if (logT > 9.21034) logT = 9.21034;
1120 return fMPV[0]->Eval(logT);
1121 }
else if (mass >= 0.1 && mass < 0.2) {
1122 logT =
log(Tkin * 105.658 / mass);
1123 if (logT > 9.21034) logT = 9.21034;
1125 return fMPV[1]->Eval(logT);
1127 logT =
log(Tkin * 938.272 / mass);
1128 if (logT > 9.21034) logT = 9.21034;
1130 return fMPV[2]->Eval(logT);
1140 Int_t trackId = point->GetTrackID();
1142 if (trackId < 0)
return -1;
1149 if (!mcTrack)
return -1;
1152 TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(pdgCode);
1154 if (!particle) particle = TDatabasePDG::Instance()->GetParticle(2212);
1155 if (TMath::Abs(particle->Charge()) < 0.1)
return -1;
1157 Double_t
m = particle->Mass();
1159 p.SetXYZM(point->GetPx(), point->GetPy(), point->GetPz(),
m);
1160 Double_t Tkin = p.E() -
m;
1168 Double_t sigmaRpc = 12.0;
1170 if (detectortype == 3)
1172 n = gRandom->Landau(mpv, sigma);
1174 n = gRandom->Landau(
1178 if (detectortype == 4)
1180 n = gRandom->Landau(mpvRpc, sigmaRpc);
1182 n = gRandom->Landau(
1199 if (!pad1)
return kFALSE;
1202 if (!pad2)
return kFALSE;
1207 std::map<UInt_t, UInt_t>::iterator it =
fAddressCharge.find(address);
1209 it->second = it->second + ne;
1214 Double_t phi = pad1 ? pad1->
GetPhi2() : pad2 ? pad2->
GetPhi1() : 0;
1215 UInt_t pad1_ne = UInt_t(ne * (phi - phi1) / (phi2 - phi1));
1219 std::map<UInt_t, UInt_t>::iterator it =
fAddressCharge.find(address);
1221 it->second = it->second + pad1_ne;
1223 fAddressCharge.insert(std::pair<UInt_t, UInt_t>(address, pad1_ne));
1232 it->second = it->second + ne - pad1_ne;
1234 fAddressCharge.insert(std::pair<UInt_t, UInt_t>(address, ne - pad1_ne));
1248 Double_t driftTime) {
1264 (signal->
GetMatch())->AddLink(link);
1270 LOG(debug4) <<
" Registered the CbmMuchSignal into the CbmMuchReadoutBuffer ";
1278 Double_t driftTime) {
1281 LOG(debug2) <<
"Buffering MC Point " << iPoint
1283 <<
"so nothing to Buffer for this MCPoint.";
1287 LOG(debug2) << GetName() <<
": Processing event " <<
fCurrentEvent
1290 <<
fPoints->GetEntriesFast() <<
" MuchPoints "
1295 UInt_t address = it->first;
1304 (signal->
GetMatch())->AddLink(link);
1310 <<
" Registered the CbmMuchSignal into the CbmMuchReadoutBuffer ";
1313 LOG(debug2) << GetName() <<
": For MC Point " << iPoint <<
" buffered "
1315 <<
" CbmMuchSignal into the CbmReadoutBuffer.";