53#include "FairEventHeader.h"
54#include "FairMCEventHeader.h"
55#include "FairMCPoint.h"
56#include "FairRootManager.h"
57#include "FairRunAna.h"
58#include "FairRunSim.h"
66#include "TDatabasePDG.h"
72#include <TGeoManager.h>
86using std::setprecision;
153 fSigma[0] =
new TF1(
"sigma_e",
"pol6", -5, 10);
156 fSigma[1] =
new TF1(
"sigma_mu",
"pol6", -5, 10);
159 fSigma[2] =
new TF1(
"sigma_p",
"pol6", -5, 10);
162 fMPV[0] =
new TF1(
"mpv_e",
"pol6", -5, 10);
165 fMPV[1] =
new TF1(
"mpv_mu",
"pol6", -5, 10);
168 fMPV[2] =
new TF1(
"mpv_p",
"pol6", -5, 10);
240 fSigma[0] =
new TF1(
"sigma_e",
"pol6", -5, 10);
243 fSigma[1] =
new TF1(
"sigma_mu",
"pol6", -5, 10);
246 fSigma[2] =
new TF1(
"sigma_p",
"pol6", -5, 10);
249 fMPV[0] =
new TF1(
"mpv_e",
"pol6", -5, 10);
252 fMPV[1] =
new TF1(
"mpv_mu",
"pol6", -5, 10);
255 fMPV[2] =
new TF1(
"mpv_p",
"pol6", -5, 10);
303 auto DriftVolumeWidth =
module->GetSize().Z();
316 auto DriftVolumeWidth =
module->GetSize().Z();
330 std::cout << std::endl;
331 LOG(info) <<
"==========================================================";
332 LOG(info) << GetName() <<
": Initialisation\n";
334 FairRootManager* ioman = FairRootManager::Instance();
335 if (!ioman) Fatal(
"Init",
"No FairRootManager");
338 LOG(info) << fName <<
": Using event-by-event mode";
351 gGeoManager->CdTop();
352 TGeoNode* cave = gGeoManager->GetCurrentNode();
354 for (
Int_t iNode = 0; iNode < cave->GetNdaughters(); iNode++) {
355 TString name = cave->GetDaughter(iNode)->GetVolume()->GetName();
356 if (name.Contains(
"much", TString::kIgnoreCase)) {
357 if (name.Contains(
"mcbm", TString::kIgnoreCase)) {
358 geoTag = TString(name(5, name.Length()));
361 geoTag = TString(name(5, name.Length() - 5));
365 LOG(info) << fName <<
": MUCH geometry tag is " << geoTag;
374 <<
": no parameter file specified and no MUCH node found in "
376 fDigiFile = gSystem->Getenv(
"VMCWORKDIR");
379 if (geoTag.Contains(
"mcbm", TString::kIgnoreCase)) {
380 fDigiFile +=
"/parameters/much/much_" + geoTag +
"_digi_sector.root";
383 fDigiFile +=
"/parameters/much/much_" + geoTag(0, 4) +
"_digi_sector.root";
388 LOG(info) << fName <<
": Using parameter file " <<
fDigiFile;
390 fFlag = (geoTag.Contains(
"mcbm", TString::kIgnoreCase) ? 1 : 0);
391 LOG(info) << fName <<
": Using flag " <<
fFlag << (
fFlag ?
" (mcbm) " :
"(standard)");
396 TFile* oldFile = gFile;
397 TDirectory* oldDir = gDirectory;
399 LOG_IF(fatal, !file->IsOpen()) << fName <<
": parameter file " <<
fDigiFile <<
" does not exist!";
400 TObjArray* stations = file->Get<TObjArray>(
"stations");
401 LOG_IF(fatal, !stations) <<
"No TObjArray stations found in file " <<
fDigiFile;
476 fPoints = (TClonesArray*) ioman->GetObject(
"MuchPoint");
480 fMCTracks = (TClonesArray*) ioman->GetObject(
"MCTrack");
523 if (!result.second) {
524 LOG(error) << GetName() <<
": Error in reading from file! Task will be inactive.";
527 LOG(info) << GetName() <<
": " << std::get<0>(result) <<
" lines read from file, " <<
fInactiveChannels.size()
528 <<
" channels set inactive";
534 LOG(info) << GetName() <<
": Initialisation successful";
535 LOG(info) <<
"==========================================================";
536 std::cout << std::endl;
557 for (
Int_t iPoint = 0; iPoint <
fPoints->GetEntriesFast(); iPoint++) {
559 LOG(debug1) << GetName() <<
": Processing MCPoint " << iPoint;
572 LOG(info) <<
"+ " << setw(20) << GetName() <<
": Generated " << nNoise
575 LOG(debug3) <<
"+ " << setw(20) << GetName() <<
": Generated " <<
fNofNoiseSignals
587 LOG(info) <<
"+ " << setw(15) << GetName() <<
": Event " << setw(6) << right <<
fCurrentEvent <<
" at " << fixed
589 <<
", digis: " <<
fNofDigis <<
". Exec time " << setprecision(6) <<
fTimer.RealTime() <<
" s.";
604 LOG(debug) <<
"+ " << setw(20) << GetName() <<
": Previous event time " << t1 <<
" Current event time " << t2
608 <<
": Previous event time " << t1 <<
" is greater than Current event time " << t2
609 <<
". No electronics noise signal generated for " <<
fCurrentEvent <<
" event.";
613 auto StationNoise = 0;
614 for (
Int_t i = 0; i < numberofstations; i++) {
617 if (numberoflayers <= 0)
continue;
620 for (
Int_t j = 0; j < numberoflayers; j++) {
623 if (numberofmodules <= 0)
continue;
625 auto FrontModuleNoise = 0;
626 for (
auto k = 0; k < numberofmodules; k++) {
633 if (numberofmodules <= 0)
continue;
634 auto BackModuleNoise = 0;
635 for (
auto k = 0; k < numberofmodules; k++) {
640 LayerNoise += FrontModuleNoise + BackModuleNoise;
642 LOG(debug1) <<
"+ " << setw(20) << GetName() <<
": Generated " << LayerNoise <<
" noise signals in station " << i
644 StationNoise += LayerNoise;
654 auto NumberOfPad =
module->GetNPads();
656 Int_t nNoise = gRandom->Poisson(nNoiseMean);
657 LOG(debug) <<
"+ " << setw(20) << GetName() <<
": Number of noise signals : " << nNoise <<
" in one module. ";
658 for (
Int_t iNoise = 0; iNoise <= nNoise; iNoise++) {
659 Int_t padnumber =
Int_t(gRandom->Uniform(Double_t(NumberOfPad)));
661 Double_t NoiseTime = gRandom->Uniform(t1, t2);
676 LOG(debug3) << GetName() <<
": Receiving signal " << charge <<
" in channel " << pad->
GetAddress() <<
" at time "
688 LOG(debug3) <<
"+ " << setw(20) << GetName()
689 <<
": Registered a Noise CbmMuchSignal into the "
690 "CbmMuchReadoutBuffer. Number of Noise Signal generated "
701 std::vector<CbmMuchSignal*> SignalList;
709 LOG(debug) << GetName() <<
": Number of Signals read out from Buffer " << ReadOutSignal <<
" and SignalList contain "
710 << SignalList.size() <<
" entries.";
712 for (std::vector<CbmMuchSignal*>::iterator LoopOver = SignalList.begin(); LoopOver != SignalList.end(); LoopOver++) {
716 LOG(debug2) << GetName() <<
": Digi not created as signal is below threshold.";
733 LOG(debug) << GetName() <<
": " <<
fNofDigis << (
fNofDigis == 1 ?
" digi " :
" digis ") <<
"created and sent to DAQ ";
740 for (
auto signal : SignalList) {
787 digi->
SetAdc(adcValue + 1);
820 LOG(fatal) << fName <<
": Readout buffer is not empty at end of run "
821 <<
"in event-by-event mode!";
827 std::cout << std::endl;
828 LOG(info) << GetName() <<
": Finish run";
832 LOG(info) << setw(15) << GetName() <<
": Finish, points " <<
fNofPoints <<
", signals: " <<
fNofSignals
833 <<
", digis: " <<
fNofDigis <<
". Exec time " << setprecision(6) <<
fTimer.RealTime() <<
" s.";
842 std::cout << std::endl;
843 LOG(info) <<
"=====================================";
844 LOG(info) << GetName() <<
": Run summary";
845 LOG(info) <<
"Events processed : " <<
fNofEvents;
856 LOG(info) <<
"=====================================";
860 TFile* oldFile = gFile;
861 TDirectory* oldDir = gDirectory;
862 TFile *f1 =new TFile ("pri_el_info.root","RECREATE");
863 hPriElAfterDriftpathgem->Write();
864 hPriElAfterDriftpathrpc->Write();
887 Int_t detectorId = point->GetDetectorID();
891 int detectortype =
module->GetDetectorType();
894 TVector3
v = 0.5 * (v1 + v2);
899 if (pad) printf(
"x0=%f,y0=%f\n", pad->
GetX(), pad->
GetY());
905 if (!pad)
return kFALSE;
912 if (nElectrons < 0)
return kFALSE;
924 Double_t time = point->GetTime();
928 map<CbmMuchSector*, Int_t> firedSectors;
929 for (
Int_t i = 0; i < nElectrons; i++) {
930 Double_t aL = gRandom->Rndm();
932 TVector3 ve = v1 + dv * aL;
941 firedSectors[module1->
GetSector(x1, y1)] = 0;
942 firedSectors[module1->
GetSector(x1, y2)] = 0;
943 firedSectors[module1->
GetSector(x2, y1)] = 0;
944 firedSectors[module1->
GetSector(x2, y2)] = 0;
945 for (map<CbmMuchSector*, Int_t>::iterator it = firedSectors.begin(); it != firedSectors.end(); it++) {
947 if (!sector)
continue;
950 Double_t xp0 = pad->
GetX();
951 Double_t xpd = pad->
GetDx() / 2.;
952 Double_t xp1 = xp0 - xpd;
953 Double_t xp2 = xp0 + xpd;
954 if (x1 > xp2 || x2 < xp1)
continue;
955 Double_t yp0 = pad->
GetY();
956 Double_t ypd = pad->
GetDy() / 2.;
957 Double_t yp1 = yp0 - ypd;
958 Double_t yp2 = yp0 + ypd;
959 if (y1 > yp2 || y2 < yp1)
continue;
960 Double_t lx = x1 > xp1 ? (x2 < xp2 ? x2 - x1 : xp2 - x1) : x2 - xp1;
961 Double_t ly = y1 > yp1 ? (y2 < yp2 ? y2 - y1 : yp2 - y1) : y2 - yp1;
962 AddCharge(pad, UInt_t(ne * lx * ly / s), iPoint, time, driftTime);
965 firedSectors.clear();
973 LOG(debug) << GetName() <<
": Not Processing MCPoint " << iPoint <<
" because it is not on any GEM module.";
978 LOG(debug) << GetName() <<
": Not Processing MCPoint " << iPoint <<
" because it is on the module " << module3
979 <<
" but not the first sector. " << sFirst;
986 LOG(debug) << GetName() <<
": Not Processing MCPoint " << iPoint
987 <<
" because it is not the last sector of module." << module3;
990 Double_t rMin = sFirst->
GetR1();
991 Double_t rMax = sLast->
GetR2();
998 Double_t driftTime = -1;
999 while (driftTime < 0) {
1001 Double_t aL = gRandom->Gaus(0.5, 0.133);
1007 for (
Int_t i = 0; i < nElectrons; i++) {
1008 Double_t RandomNumberForPrimaryElectronPosition = gRandom->Rndm();
1009 TVector3 ve = v1 + dv * RandomNumberForPrimaryElectronPosition;
1013 Double_t r = 0.0, phi = 0.0;
1017 ve.SetX(ve.X() -
fGemTX);
1018 ve.SetY(ve.Y() -
fGemTY);
1023 ve.SetX(ve.X() -
fGemTX + 24.0);
1024 ve.SetY(ve.Y() -
fGemTY);
1030 ve.SetX(ve.X() -
fRpcTX);
1031 ve.SetY(ve.Y() -
fRpcTY);
1034 LOG(error) <<
"Unknown detector type";
1046 if (r1 < rMin && r2 > rMin) {
1047 Status =
AddCharge(sFirst, UInt_t(ne * (r2 - rMin) / (r2 - r1)), iPoint, time, driftTime, phi1, phi2);
1049 LOG(debug) << GetName() <<
": Processing MCPoint " << iPoint <<
" in which Primary Electron : " << i
1050 <<
" not contributed charge. ";
1053 if (r1 < rMax && r2 > rMax) {
1054 Status =
AddCharge(sLast, UInt_t(ne * (rMax - r1) / (r2 - r1)), iPoint, time, driftTime, phi1, phi2);
1056 LOG(debug) << GetName() <<
": Processing MCPoint " << iPoint <<
" in which Primary Electron : " << i
1057 <<
" not contributed charge. ";
1060 if (r1 < rMin && r2 < rMin)
continue;
1061 if (r1 > rMax && r2 > rMax)
continue;
1067 Status =
AddCharge(s1, ne, iPoint, time, driftTime, phi1, phi2);
1069 LOG(debug3) << GetName() <<
": Processing MCPoint " << iPoint <<
" in which Primary Electron : " << i
1070 <<
" not contributed charge. ";
1073 Status =
AddCharge(s1, UInt_t(ne * (s1->
GetR2() - r1) / (r2 - r1)), iPoint, time, driftTime, phi1, phi2);
1075 LOG(debug3) << GetName() <<
": Processing MCPoint " << iPoint <<
" in which Primary Electron : " << i
1076 <<
" not contributed charge. ";
1077 Status =
AddCharge(s2, UInt_t(ne * (r2 - s2->
GetR1()) / (r2 - r1)), iPoint, time, driftTime, phi1, phi2);
1079 LOG(debug3) << GetName() <<
": Processing MCPoint " << iPoint <<
" in which Primary Electron : " << i
1080 <<
" not contributed charge. ";
1087 LOG(debug3) << GetName() <<
": Processing MCPoint " << iPoint <<
" nothing is buffered. ";
1089 LOG(debug1) << GetName() <<
": fAddressCharge size is " <<
fAddressCharge.size() <<
" Cleared fAddressCharge. ";
1100 Double_t gasGain = -
fMeanGasGain * TMath::Log(1 - gRandom->Rndm());
1101 if (gasGain < 0.) gasGain = 1e6;
1102 return (
Int_t) gasGain;
1111 logT =
log(Tkin * 0.511 / mass);
1112 if (logT > 9.21034) logT = 9.21034;
1114 return fSigma[0]->Eval(logT);
1116 else if (mass >= 0.1 && mass < 0.2) {
1117 logT =
log(Tkin * 105.658 / mass);
1118 if (logT > 9.21034) logT = 9.21034;
1120 return fSigma[1]->Eval(logT);
1123 logT =
log(Tkin * 938.272 / mass);
1124 if (logT > 9.21034) logT = 9.21034;
1126 return fSigma[2]->Eval(logT);
1136 logT =
log(Tkin * 0.511 / mass);
1137 if (logT > 9.21034) logT = 9.21034;
1139 return fMPV[0]->Eval(logT);
1141 else if (mass >= 0.1 && mass < 0.2) {
1142 logT =
log(Tkin * 105.658 / mass);
1143 if (logT > 9.21034) logT = 9.21034;
1145 return fMPV[1]->Eval(logT);
1148 logT =
log(Tkin * 938.272 / mass);
1149 if (logT > 9.21034) logT = 9.21034;
1151 return fMPV[2]->Eval(logT);
1159 Int_t trackId = point->GetTrackID();
1161 if (trackId < 0)
return -1;
1169 if (!mcTrack)
return -1;
1172 TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(pdgCode);
1174 if (!particle) particle = TDatabasePDG::Instance()->GetParticle(2212);
1175 if (TMath::Abs(particle->Charge()) < 0.1)
return -1;
1177 Double_t m = particle->Mass();
1179 p.SetXYZM(point->GetPx(), point->GetPy(), point->GetPz(), m);
1180 Double_t Tkin = p.E() - m;
1184 Double_t mpvRpc = 50.0;
1186 Double_t sigmaRpc = 12.0;
1188 if (detectortype == 3)
1190 n = gRandom->Landau(mpv, sigma);
1192 n = gRandom->Landau(mpv, sigma);
1195 if (detectortype == 4)
1197 n = gRandom->Landau(mpvRpc, sigmaRpc);
1199 n = gRandom->Landau(mpvRpc, sigmaRpc);
1208 Double_t , Double_t phi1, Double_t phi2)
1215 for (Double_t phi = phi1; phi < (phi1 + phi2) / 2.0; phi += 0.1)
1221 if (!pad1)
return kFALSE;
1228 for (Double_t phi = phi2; phi > (phi1 + phi2) / 2.0; phi -= 0.1)
1235 if (!pad2)
return kFALSE;
1241 std::map<UInt_t, UInt_t>::iterator it =
fAddressCharge.find(address);
1243 it->second = it->second + ne;
1249 Double_t phi = pad1 ? pad1->
GetPhi2() : pad2 ? pad2->
GetPhi1() : 0;
1250 UInt_t pad1_ne = UInt_t(ne * (phi - phi1) / (phi2 - phi1));
1255 std::map<UInt_t, UInt_t>::iterator it =
fAddressCharge.find(address);
1257 it->second = it->second + pad1_ne;
1259 fAddressCharge.insert(std::pair<UInt_t, UInt_t>(address, pad1_ne));
1268 it->second = it->second + ne - pad1_ne;
1270 fAddressCharge.insert(std::pair<UInt_t, UInt_t>(address, ne - pad1_ne));
1296 (signal->
GetMatch())->AddLink(link);
1302 LOG(debug4) <<
" Registered the CbmMuchSignal into the CbmMuchReadoutBuffer ";
1311 LOG(debug2) <<
"Buffering MC Point " << iPoint <<
" but fAddressCharge size is " <<
fAddressCharge.size()
1312 <<
"so nothing to Buffer for this MCPoint.";
1323 UInt_t address = it->first;
1332 (signal->
GetMatch())->AddLink(link);
1337 LOG(debug3) <<
" Registered the CbmMuchSignal into the CbmMuchReadoutBuffer ";
1340 LOG(debug2) << GetName() <<
": For MC Point " << iPoint <<
" buffered " <<
fAddressCharge.size()
1341 <<
" CbmMuchSignal into the CbmReadoutBuffer.";
ClassImp(CbmConverterManager)
constexpr double min_logT_e
constexpr double sigma_mu[]
constexpr double sigma_p[]
constexpr double min_logT_p
constexpr double sigma_e[]
constexpr double mpv_mu[]
constexpr double min_logT_mu
friend fvec log(const fvec &a)
virtual std::pair< size_t, bool > ReadInactiveChannels()
TString fInactiveChannelFileName
std::set< uint32_t > fInactiveChannels
Double_t fCurrentEventTime
void SendData(Double_t time, CbmMuchDigi *digi, CbmMatch *match=nullptr)
int32_t GetPdgCode() const
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
Double_t fPerPadNoiseRate
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.
Double_t fPreviousEventTime
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.
virtual ~CbmMuchDigitizeGem()
Double_t Sigma_n_e(Double_t Tkin, Double_t mass)
Bool_t fGenerateElectronicsNoise
Previous Event Time.
void ReadAndRegister(Long_t)
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 *)
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 GetDetectorId() const
Int_t GetDetectorType() const
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...
CbmMatch * GetMatch() const
void SetCharge(UInt_t charge)
CbmMuchLayer * GetLayer(Int_t iLayer) const
Int_t ReadOutData(Double_t time, std::vector< Data * > &dataList)
void Fill(UInt_t address, Data *data)