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"
71#include <TGeoManager.h>
85using std::setprecision;
124 , fTotalDriftTime(-1)
147 fPerPadNoiseRate(10e-9)
148 , fGenerateElectronicsNoise(kFALSE)
149 , fNoiseCharge(nullptr)
152 fSigma[0] =
new TF1(
"sigma_e",
"pol6", -5, 10);
155 fSigma[1] =
new TF1(
"sigma_mu",
"pol6", -5, 10);
158 fSigma[2] =
new TF1(
"sigma_p",
"pol6", -5, 10);
161 fMPV[0] =
new TF1(
"mpv_e",
"pol6", -5, 10);
164 fMPV[1] =
new TF1(
"mpv_mu",
"pol6", -5, 10);
167 fMPV[2] =
new TF1(
"mpv_p",
"pol6", -5, 10);
183 , fDigiFile(digiFileName)
211 , fTotalDriftTime(-1)
234 , fPerPadNoiseRate(10e-9)
235 , fGenerateElectronicsNoise(kFALSE)
236 , fNoiseCharge(nullptr)
239 fSigma[0] =
new TF1(
"sigma_e",
"pol6", -5, 10);
242 fSigma[1] =
new TF1(
"sigma_mu",
"pol6", -5, 10);
245 fSigma[2] =
new TF1(
"sigma_p",
"pol6", -5, 10);
248 fMPV[0] =
new TF1(
"mpv_e",
"pol6", -5, 10);
251 fMPV[1] =
new TF1(
"mpv_mu",
"pol6", -5, 10);
254 fMPV[2] =
new TF1(
"mpv_p",
"pol6", -5, 10);
302 auto DriftVolumeWidth =
module->GetSize().Z();
315 auto DriftVolumeWidth =
module->GetSize().Z();
329 std::cout << std::endl;
330 LOG(info) <<
"==========================================================";
331 LOG(info) << GetName() <<
": Initialisation\n";
333 FairRootManager* ioman = FairRootManager::Instance();
334 if (!ioman) Fatal(
"Init",
"No FairRootManager");
337 LOG(info) << fName <<
": Using event-by-event mode";
350 gGeoManager->CdTop();
351 TGeoNode* cave = gGeoManager->GetCurrentNode();
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()));
360 geoTag = TString(name(5, name.Length() - 5));
364 LOG(info) << fName <<
": MUCH geometry tag is " << geoTag;
373 <<
": no parameter file specified and no MUCH node found in "
375 fDigiFile = gSystem->Getenv(
"VMCWORKDIR");
378 if (geoTag.Contains(
"mcbm", TString::kIgnoreCase)) {
379 fDigiFile +=
"/parameters/much/much_" + geoTag +
"_digi_sector.root";
382 fDigiFile +=
"/parameters/much/much_" + geoTag(0, 4) +
"_digi_sector.root";
387 LOG(info) << fName <<
": Using parameter file " <<
fDigiFile;
389 fFlag = (geoTag.Contains(
"mcbm", TString::kIgnoreCase) ? 1 : 0);
390 LOG(info) << fName <<
": Using flag " <<
fFlag << (
fFlag ?
" (mcbm) " :
"(standard)");
395 TFile* oldFile = gFile;
396 TDirectory* oldDir = gDirectory;
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;
467 fPoints = (TClonesArray*) ioman->GetObject(
"MuchPoint");
471 fMCTracks = (TClonesArray*) ioman->GetObject(
"MCTrack");
514 if (!result.second) {
515 LOG(error) << GetName() <<
": Error in reading from file! Task will be inactive.";
518 LOG(info) << GetName() <<
": " << std::get<0>(result) <<
" lines read from file, " <<
fInactiveChannels.size()
519 <<
" channels set inactive";
525 LOG(info) << GetName() <<
": Initialisation successful";
526 LOG(info) <<
"==========================================================";
527 std::cout << std::endl;
548 for (
Int_t iPoint = 0; iPoint <
fPoints->GetEntriesFast(); iPoint++) {
550 LOG(debug1) << GetName() <<
": Processing MCPoint " << iPoint;
563 LOG(info) <<
"+ " << setw(20) << GetName() <<
": Generated " << nNoise
566 LOG(debug3) <<
"+ " << setw(20) << GetName() <<
": Generated " <<
fNofNoiseSignals
578 LOG(info) <<
"+ " << setw(15) << GetName() <<
": Event " << setw(6) << right <<
fCurrentEvent <<
" at " << fixed
580 <<
", digis: " <<
fNofDigis <<
". Exec time " << setprecision(6) <<
fTimer.RealTime() <<
" s.";
595 LOG(debug) <<
"+ " << setw(20) << GetName() <<
": Previous event time " << t1 <<
" Current event time " << t2
599 <<
": Previous event time " << t1 <<
" is greater than Current event time " << t2
600 <<
". No electronics noise signal generated for " <<
fCurrentEvent <<
" event.";
604 auto StationNoise = 0;
605 for (
Int_t i = 0; i < numberofstations; i++) {
608 if (numberoflayers <= 0)
continue;
611 for (
Int_t j = 0; j < numberoflayers; j++) {
614 if (numberofmodules <= 0)
continue;
616 auto FrontModuleNoise = 0;
617 for (
auto k = 0; k < numberofmodules; k++) {
624 if (numberofmodules <= 0)
continue;
625 auto BackModuleNoise = 0;
626 for (
auto k = 0; k < numberofmodules; k++) {
631 LayerNoise += FrontModuleNoise + BackModuleNoise;
633 LOG(debug1) <<
"+ " << setw(20) << GetName() <<
": Generated " << LayerNoise <<
" noise signals in station " << i
635 StationNoise += LayerNoise;
645 auto NumberOfPad =
module->GetNPads();
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)));
652 Double_t NoiseTime = gRandom->Uniform(t1, t2);
667 LOG(debug3) << GetName() <<
": Receiving signal " << charge <<
" in channel " << pad->
GetAddress() <<
" at time "
679 LOG(debug3) <<
"+ " << setw(20) << GetName()
680 <<
": Registered a Noise CbmMuchSignal into the "
681 "CbmMuchReadoutBuffer. Number of Noise Signal generated "
692 std::vector<CbmMuchSignal*> SignalList;
700 LOG(debug) << GetName() <<
": Number of Signals read out from Buffer " << ReadOutSignal <<
" and SignalList contain "
701 << SignalList.size() <<
" entries.";
703 for (std::vector<CbmMuchSignal*>::iterator LoopOver = SignalList.begin(); LoopOver != SignalList.end(); LoopOver++) {
708 LOG(debug2) << GetName() <<
": Digi not created as signal is below threshold.";
719 LOG(debug) << GetName() <<
": " <<
fNofDigis << (
fNofDigis == 1 ?
" digi " :
" digis ") <<
"created and sent to DAQ ";
726 for (
auto signal : SignalList) {
773 digi->
SetAdc(adcValue + 1);
806 LOG(fatal) << fName <<
": Readout buffer is not empty at end of run "
807 <<
"in event-by-event mode!";
813 std::cout << std::endl;
814 LOG(info) << GetName() <<
": Finish run";
818 LOG(info) << setw(15) << GetName() <<
": Finish, points " <<
fNofPoints <<
", signals: " <<
fNofSignals
819 <<
", digis: " <<
fNofDigis <<
". Exec time " << setprecision(6) <<
fTimer.RealTime() <<
" s.";
828 std::cout << std::endl;
829 LOG(info) <<
"=====================================";
830 LOG(info) << GetName() <<
": Run summary";
831 LOG(info) <<
"Events processed : " <<
fNofEvents;
842 LOG(info) <<
"=====================================";
846 TFile* oldFile = gFile;
847 TDirectory* oldDir = gDirectory;
848 TFile *f1 =new TFile ("pri_el_info.root","RECREATE");
849 hPriElAfterDriftpathgem->Write();
850 hPriElAfterDriftpathrpc->Write();
873 Int_t detectorId = point->GetDetectorID();
877 int detectortype =
module->GetDetectorType();
880 TVector3
v = 0.5 * (v1 + v2);
885 if (pad) printf(
"x0=%f,y0=%f\n", pad->
GetX(), pad->
GetY());
891 if (!pad)
return kFALSE;
898 if (nElectrons < 0)
return kFALSE;
910 Double_t time = point->GetTime();
914 map<CbmMuchSector*, Int_t> firedSectors;
915 for (
Int_t i = 0; i < nElectrons; i++) {
916 Double_t aL = gRandom->Rndm();
918 TVector3 ve = v1 + dv * aL;
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++) {
933 if (!sector)
continue;
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);
951 firedSectors.clear();
959 LOG(debug) << GetName() <<
": Not Processing MCPoint " << iPoint <<
" because it is not on any GEM module.";
964 LOG(debug) << GetName() <<
": Not Processing MCPoint " << iPoint <<
" because it is on the module " << module3
965 <<
" but not the first sector. " << sFirst;
972 LOG(debug) << GetName() <<
": Not Processing MCPoint " << iPoint
973 <<
" because it is not the last sector of module." << module3;
976 Double_t rMin = sFirst->
GetR1();
977 Double_t rMax = sLast->
GetR2();
984 Double_t driftTime = -1;
985 while (driftTime < 0) {
987 Double_t aL = gRandom->Gaus(0.5, 0.133);
993 for (
Int_t i = 0; i < nElectrons; i++) {
994 Double_t RandomNumberForPrimaryElectronPosition = gRandom->Rndm();
995 TVector3 ve = v1 + dv * RandomNumberForPrimaryElectronPosition;
999 Double_t r = 0.0, phi = 0.0;
1003 ve.SetX(ve.X() -
fGemTX);
1004 ve.SetY(ve.Y() -
fGemTY);
1008 ve.SetX(ve.X() -
fRpcTX);
1009 ve.SetY(ve.Y() -
fRpcTY);
1012 LOG(error) <<
"Unknown detector type";
1024 if (r1 < rMin && r2 > rMin) {
1025 Status =
AddCharge(sFirst, UInt_t(ne * (r2 - rMin) / (r2 - r1)), iPoint, time, driftTime, phi1, phi2);
1027 LOG(debug) << GetName() <<
": Processing MCPoint " << iPoint <<
" in which Primary Electron : " << i
1028 <<
" not contributed charge. ";
1031 if (r1 < rMax && r2 > rMax) {
1032 Status =
AddCharge(sLast, UInt_t(ne * (rMax - r1) / (r2 - r1)), iPoint, time, driftTime, phi1, phi2);
1034 LOG(debug) << GetName() <<
": Processing MCPoint " << iPoint <<
" in which Primary Electron : " << i
1035 <<
" not contributed charge. ";
1038 if (r1 < rMin && r2 < rMin)
continue;
1039 if (r1 > rMax && r2 > rMax)
continue;
1045 Status =
AddCharge(s1, ne, iPoint, time, driftTime, phi1, phi2);
1047 LOG(debug3) << GetName() <<
": Processing MCPoint " << iPoint <<
" in which Primary Electron : " << i
1048 <<
" not contributed charge. ";
1051 Status =
AddCharge(s1, UInt_t(ne * (s1->
GetR2() - r1) / (r2 - r1)), iPoint, time, driftTime, phi1, phi2);
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);
1057 LOG(debug3) << GetName() <<
": Processing MCPoint " << iPoint <<
" in which Primary Electron : " << i
1058 <<
" not contributed charge. ";
1065 LOG(debug3) << GetName() <<
": Processing MCPoint " << iPoint <<
" nothing is buffered. ";
1067 LOG(debug1) << GetName() <<
": fAddressCharge size is " <<
fAddressCharge.size() <<
" Cleared fAddressCharge. ";
1078 Double_t gasGain = -
fMeanGasGain * TMath::Log(1 - gRandom->Rndm());
1079 if (gasGain < 0.) gasGain = 1e6;
1080 return (
Int_t) gasGain;
1089 logT =
log(Tkin * 0.511 / mass);
1090 if (logT > 9.21034) logT = 9.21034;
1092 return fSigma[0]->Eval(logT);
1094 else if (mass >= 0.1 && mass < 0.2) {
1095 logT =
log(Tkin * 105.658 / mass);
1096 if (logT > 9.21034) logT = 9.21034;
1098 return fSigma[1]->Eval(logT);
1101 logT =
log(Tkin * 938.272 / mass);
1102 if (logT > 9.21034) logT = 9.21034;
1104 return fSigma[2]->Eval(logT);
1114 logT =
log(Tkin * 0.511 / mass);
1115 if (logT > 9.21034) logT = 9.21034;
1117 return fMPV[0]->Eval(logT);
1119 else if (mass >= 0.1 && mass < 0.2) {
1120 logT =
log(Tkin * 105.658 / mass);
1121 if (logT > 9.21034) logT = 9.21034;
1123 return fMPV[1]->Eval(logT);
1126 logT =
log(Tkin * 938.272 / mass);
1127 if (logT > 9.21034) logT = 9.21034;
1129 return fMPV[2]->Eval(logT);
1137 Int_t trackId = point->GetTrackID();
1139 if (trackId < 0)
return -1;
1147 if (!mcTrack)
return -1;
1150 TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(pdgCode);
1152 if (!particle) particle = TDatabasePDG::Instance()->GetParticle(2212);
1153 if (TMath::Abs(particle->Charge()) < 0.1)
return -1;
1155 Double_t m = particle->Mass();
1157 p.SetXYZM(point->GetPx(), point->GetPy(), point->GetPz(), m);
1158 Double_t Tkin = p.E() - m;
1162 Double_t mpvRpc = 50.0;
1164 Double_t sigmaRpc = 12.0;
1166 if (detectortype == 3)
1168 n = gRandom->Landau(mpv, sigma);
1170 n = gRandom->Landau(mpv, sigma);
1173 if (detectortype == 4)
1175 n = gRandom->Landau(mpvRpc, sigmaRpc);
1177 n = gRandom->Landau(mpvRpc, sigmaRpc);
1186 Double_t , Double_t phi1, Double_t phi2)
1193 for (Double_t phi = phi1; phi < (phi1 + phi2) / 2.0; phi += 0.1)
1199 if (!pad1)
return kFALSE;
1206 for (Double_t phi = phi2; phi > (phi1 + phi2) / 2.0; phi -= 0.1)
1213 if (!pad2)
return kFALSE;
1219 std::map<UInt_t, UInt_t>::iterator it =
fAddressCharge.find(address);
1221 it->second = it->second + ne;
1227 Double_t phi = pad1 ? pad1->
GetPhi2() : pad2 ? pad2->
GetPhi1() : 0;
1228 UInt_t pad1_ne = UInt_t(ne * (phi - phi1) / (phi2 - phi1));
1233 std::map<UInt_t, UInt_t>::iterator it =
fAddressCharge.find(address);
1235 it->second = it->second + pad1_ne;
1237 fAddressCharge.insert(std::pair<UInt_t, UInt_t>(address, pad1_ne));
1246 it->second = it->second + ne - pad1_ne;
1248 fAddressCharge.insert(std::pair<UInt_t, UInt_t>(address, ne - pad1_ne));
1274 (signal->
GetMatch())->AddLink(link);
1280 LOG(debug4) <<
" Registered the CbmMuchSignal into the CbmMuchReadoutBuffer ";
1289 LOG(debug2) <<
"Buffering MC Point " << iPoint <<
" but fAddressCharge size is " <<
fAddressCharge.size()
1290 <<
"so nothing to Buffer for this MCPoint.";
1301 UInt_t address = it->first;
1310 (signal->
GetMatch())->AddLink(link);
1315 LOG(debug3) <<
" Registered the CbmMuchSignal into the CbmMuchReadoutBuffer ";
1318 LOG(debug2) << GetName() <<
": For MC Point " << iPoint <<
" buffered " <<
fAddressCharge.size()
1319 <<
" 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
static const Int_t fDeadTime
friend fvec log(const fvec &a)
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.
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 *)
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
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)