244 cout << endl <<
"-I- " << fName <<
": executing event" << endl;
245 cout <<
"----------------------------------------------" << endl;
254 cerr <<
"-W- " << fName <<
"::Exec: No input array (STSPoint) " << endl;
255 cout <<
"- " << fName << endl;
259 cerr <<
"-W- " << fName <<
"::Exec: Number of AdcBits(" << fFNofBits
262 cout <<
"- " << fName << endl;
267 cerr <<
"-W- " << fName <<
"::Exec: Number of electrons per AdcChannel does not match Adc range " << endl;
268 cout <<
"- " << fName << endl;
273 cerr <<
"-W- " << fName <<
"::Exec: Number of electrons per AdcChannel does not match Adc range " << endl;
274 cout <<
"- " << fName << endl;
277 map<CbmStsSensor*, set<Int_t>>::iterator mapIt;
278 for (mapIt = fPointMap.begin(); mapIt != fPointMap.end(); mapIt++)
279 ((*mapIt).second).clear();
281 for (
int idet = 0; idet < 2; ++idet) {
282 TClonesArray* points = (idet == 0) ? fPointsSi : fPoints;
283 if (points ==
nullptr)
287 for (Int_t iPoint = 0; iPoint < points->GetEntriesFast(); iPoint++) {
300 Double_t xin = point->
GetXIn();
301 Double_t yin = point->
GetYIn();
302 Double_t zin = point->
GetZIn();
303 gGeoManager->FindNode(xin, yin, zin);
304 TGeoNode* curNode = gGeoManager->GetCurrentNode();
305 if (TString(curNode->GetName()).Contains(
"part")) {
309 curNode = gGeoManager->GetCurrentNode();
322 if (fPointMap.find(sensor) == fPointMap.end()) {
323 cerr <<
"-E- " << fName <<
"::Exec:: sensor " << curNode->GetName() <<
" not found in digi scheme!"
327 fPointMap[sensor].insert(iPoint);
332 for (Int_t iStation = fDigiScheme->
GetNStations(); iStation > 0;) {
334 for (Int_t iSector = station->
GetNSectors(); iSector > 0;) {
337 map<Int_t, set<Int_t>>::iterator mapCh;
339 for (mapCh = fFChannelPointsMap.begin(); mapCh != fFChannelPointsMap.end(); mapCh++)
340 ((*mapCh).second).clear();
341 for (mapCh = fBChannelPointsMap.begin(); mapCh != fBChannelPointsMap.end(); mapCh++)
342 ((*mapCh).second).clear();
350 for (Int_t iChannel = nChannels; iChannel > 0;) {
356 fStripSignalF[--iChannel] = 0;
362 for (Int_t iChannel = nChannelsB; iChannel > 0;) {
364 fStripSignalB[--iChannel] = 0;
370 for (Int_t iSensor = sector->
GetNSensors(); iSensor > 0;) {
373 if (sensor->
GetDx() < 0.02)
376 if (fPointMap.find(sensor) != fPointMap.end())
378 ->ProduceHitResponseFast(sensor, fPointMap[sensor], fStripSignalF, fStripSignalB,
379 fFChannelPointsMap, fBChannelPointsMap);
388 Double_t dx = sector->
GetDx();
390 for (Int_t ifstr = 0; ifstr < nChannels; ifstr++) {
391 if (fStripSignalF[ifstr] < 1)
404 Int_t digiFSignal = 0;
405 if (fastDig && dx > 0.02)
406 digiFSignal = fStripSignalF[ifstr] / 1.;
408 digiFSignal = 1 + (Int_t)((fStripSignalF[ifstr]) / fFNofElPerAdc);
409 if (digiFSignal >= fFNofSteps)
410 digiFSignal = fFNofSteps - 1;
411 if (digiFSignal < 13)
415 new ((*fDigis)[fNDigis])
CbmStsDigi(stationNr, sectorNr, 0, ifstr, digiFSignal, 0);
416 set<Int_t>::iterator it1;
417 set<Int_t> chPnt = fFChannelPointsMap[ifstr];
420 if (chPnt.size() == 0) {
423 for (it1 = chPnt.begin(); it1 != chPnt.end(); it1++) {
425 if (it1 == chPnt.begin())
428 match->AddPoint(pnt);
439 for (Int_t ibstr = 0; ibstr < nChannels; ibstr++) {
440 if (fStripSignalB[ibstr] < 1)
453 Int_t digiBSignal = 0;
454 if (fastDig && dx > 0.02)
455 digiBSignal = fStripSignalB[ibstr] / 1.;
457 digiBSignal = 1 + (Int_t)((fStripSignalB[ibstr]) / fBNofElPerAdc);
458 if (digiBSignal >= fBNofSteps)
459 digiBSignal = fBNofSteps - 1;
460 if (digiBSignal < 13)
464 new ((*fDigis)[fNDigis])
CbmStsDigi(stationNr, sectorNr, 1, ibstr, digiBSignal, 0);
465 set<Int_t>::iterator it1;
466 set<Int_t> chPnt = fBChannelPointsMap[ibstr];
469 if (chPnt.size() == 0) {
472 for (it1 = chPnt.begin(); it1 != chPnt.end(); it1++) {
474 if (it1 == chPnt.begin())
477 match->AddPoint(pnt);
489 cout <<
"+ " << flush;
490 cout << setw(15) << left << fName <<
": " << setprecision(4) << setw(8) << fixed << right << fTimer.RealTime()
491 <<
" s, digis " << nDigisF <<
" / " << nDigisB << endl;
494 fNPoints += Double_t(nPoints);
495 fNDigisFront += Double_t(nDigisF);
496 fNDigisBack += Double_t(nDigisB);
497 fTime += fTimer.RealTime();
556 if (fPointMap.find(sensor) == fPointMap.end()) {
557 cerr <<
"-E- " << fName <<
"::ProduceHitResponse:: sensor"
558 <<
" not found in digi scheme!" << endl;
563 set<Int_t>& pSet = fPointMap[sensor];
569 set<Int_t>::iterator it1;
571 Double_t dPitch, step = fStep;
572 if (TString(sensor->GetName()).Contains(
"Si") || sensor->
GetDx() < 0.0200)
574 TClonesArray* points = (fPointsSi ==
nullptr) ? fPoints : fPointsSi;
575 TVector3 posIn, posOut;
577 for (it1 = pSet.begin(); it1 != pSet.end(); it1++) {
602 Double_t xin = posIn.X(), yin = posIn.Y(), zin = posIn.Z();
603 Double_t xvec = posOut.X(), yvec = posOut.Y(), zvec = posOut.Z();
606 Int_t nofSteps = (Int_t)(TMath::Sqrt(xvec * xvec + yvec * yvec + zvec * zvec) / step + 1);
609 Double_t eloss = (fPointsSi ==
nullptr) ? point->GetEnergyLoss() : pointsi->GetEnergyLoss();
610 Double_t stepEL = fEnergyLossToSignal * eloss / (nofSteps + 1);
615 xvec = xvec / ((Double_t)nofSteps);
616 yvec = yvec / ((Double_t)nofSteps);
617 zvec = zvec / ((Double_t)nofSteps);
619 for (Int_t istep = 0; istep <= nofSteps; istep++) {
622 Double_t xinS = xin, yinS = yin, sigma = 0.05;
625 xinS += gRandom->Gaus(0.0, sigma);
626 yinS += gRandom->Gaus(0.0, sigma);
638 fStripSignalF[iIChan] += stepEL;
639 fFChannelPointsMap[iIChan].insert(iPoint);
650 fStripSignalB[iIChan] += stepEL;
651 fBChannelPointsMap[iIChan].insert(iPoint);
678 static Int_t ifield = -1;
680 FairRunAna*
run = FairRunAna::Instance();
681 FairField* magField =
run->GetField();
682 ifield = TMath::Nint(TMath::Abs(magField->GetBy(0, 0, 135.0)));
687 if (fPointMap.find(sensor) == fPointMap.end()) {
688 cerr <<
"-E- " << fName <<
"::ProduceHitResponse:: sensor"
689 <<
" not found in digi scheme!" << endl;
694 set<Int_t>& pSet = fPointMap[sensor];
699 set<Int_t>::iterator it1;
701 Double_t dPitch = fStep ;
703 for (it1 = pSet.begin(); it1 != pSet.end(); it1++) {
711 point = (
CbmStsPoint*)fPoints->UncheckedAt(iPoint);
713 point->Momentum(mom);
716 TParticlePDG* part = TDatabasePDG::Instance()->GetParticle(mcTr->
GetPdgCode());
717 Double_t mnoc = 1.0, mass = 3.7283999;
722 lorv.SetVectM(mom, mass);
723 Double_t beta = lorv.Beta();
724 Double_t gamma = lorv.Gamma();
725 Double_t charge = (part) ? part->Charge() / 3 : 1;
726 mnoc = GetNumberOfClusters(beta, gamma, charge, 1.787, 12.33);
732 Double_t moduleThickness = 0.3 + 0.25 + 0.2 + 0.15;
736 Double_t xin = point->
GetXIn();
737 Double_t yin = point->
GetYIn();
738 Double_t zin = point->
GetZIn();
740 Double_t xvec = point->
GetXOut() - xin;
741 Double_t yvec = point->
GetYOut() - yin;
746 Double_t zvec = point->
GetZOut() - zin;
749 Double_t track_length = TMath::Sqrt(xvec * xvec + yvec * yvec + zvec * zvec);
755 Double_t current_length = 0.0;
756 Double_t current_length_ratio = 0.0;
758 Int_t collisions_cnt = 0;
759 Double_t current_step = 0.0;
762 std::vector<std::vector<Double_t>> collision_points;
764 Double_t mcd = 1 / mnoc;
768 while (current_length < track_length) {
770 current_step = gRandom->Exp(mcd);
771 current_length += current_step;
773 if (current_length > track_length)
776 current_length_ratio = current_length / track_length;
779 Double_t current_x = xin + current_length_ratio * xvec;
780 Double_t current_y = yin + current_length_ratio * yvec;
781 Double_t current_z = zin + current_length_ratio * zvec;
783 std::vector<Double_t> collPoint;
784 collPoint.push_back(current_x);
785 collPoint.push_back(current_y);
786 collPoint.push_back(current_z);
787 collision_points.push_back(collPoint);
792 const Double_t level1 = 0.15;
793 const Double_t level2 = 0.2 + 0.15;
794 const Double_t level3 =
798 Double_t xmean, sigma;
801 Double_t p_xmean4[4] = {+4.45E-04, +0.0518626, +0.0676802, +0.00195376};
802 Double_t p_xmean5[4] = {+5.52E-04, +0.0659937, +0.0809207,
804 Double_t p_xmean6[4] = {+0.000602183, +0.0809795, +0.0918447,
806 Double_t p_xmean7[4] = {+0.000909404, +0.0896112, +0.125486,
808 Double_t p_xmean8[4] = {+0.000962017, +0.104726, +0.137705, +0.016483};
809 Double_t p_xmean9[4] = {+0.00103555, +0.117826, +0.160241, +0.0178768};
812 Double_t p_sigma4[6] = {+0.000181581, +0.120391, -0.425589, +0.887732, -0.885041, +0.332821};
813 Double_t p_sigma5[6] = {+1.87E-04, +0.12034, -0.412872, +0.830354, -0.800251, +0.292069};
814 Double_t p_sigma6[6] = {+0.000137712, +0.125844, -0.468967, +1.01775, -1.04621, +0.403336};
815 Double_t p_sigma7[6] = {+0.000179813, +0.122855, -0.442513, +0.950076, -0.978707, +0.380569};
816 Double_t p_sigma8[6] = {+1.86E-04, +0.122116, -0.435668, +0.934093, -0.963362, +0.376114};
817 Double_t p_sigma9[6] = {+0.000190609, +0.121689, -0.424431, +0.881712, -0.871142, +0.323333};
819 Double_t *p_xmean = p_xmean8, *p_sigma = p_sigma8;
824 }
else if (ifield == 5) {
827 }
else if (ifield == 6) {
830 }
else if (ifield == 7) {
833 }
else if (ifield == 9) {
840 for (
size_t icoll = 0; icoll < collision_points.size(); ++icoll) {
841 Double_t xcoll = collision_points[icoll][0];
842 Double_t ycoll = collision_points[icoll][1];
843 Double_t zcoll = collision_points[icoll][2];
852 zdist = TMath::Abs(zcoll - zin);
853 if (stationNr % 2 != 0 && point->GetPz() > 0)
854 zdist = moduleThickness - zdist;
855 else if (stationNr % 2 == 0 && point->GetPz() < 0)
856 zdist = moduleThickness - zdist;
858 Double_t zdist2 = zdist * zdist, zdist3 = zdist2 * zdist;
860 xmean = p_xmean[0] + p_xmean[1] * zdist + p_xmean[2] * zdist2 + p_xmean[3] * zdist3;
861 sigma = p_sigma[0] + p_sigma[1] * zdist + p_sigma[2] * zdist2 + p_sigma[3] * zdist3
862 + p_sigma[4] * zdist3 * zdist + p_sigma[5] * zdist3 * zdist2;
865 Int_t n_electrons_cluster = gRandom->Landau(1.027, 0.11);
866 if (n_electrons_cluster < 1)
867 n_electrons_cluster = 1;
868 if (n_electrons_cluster > 6)
869 n_electrons_cluster = 6;
871 for (Int_t ielectron = 0; ielectron < n_electrons_cluster; ++ielectron) {
877 Double_t gain_gem2 = gRandom->Exp(15);
878 Double_t gain_gem3 = gRandom->Exp(15);
886 if (zdist < level1) {
888 }
else if (zdist >= level1 && zdist < level2) {
891 total_gain = gain_gem3;
892 }
else if (zdist >= level2 && zdist < level3) {
897 total_gain = gain_gem3 * gain_gem2;
898 }
else if (zdist >= level3) {
905 total_gain = gain_gem3 * gain_gem2 * gain_gem1;
909 double x_readout, y_readout;
911 for (
int igain = 0; igain < total_gain; ++igain) {
916 if (stationNr % 2 != 0)
917 x_readout = gRandom->Gaus(xcoll - xmean, sigma);
919 x_readout = gRandom->Gaus(xcoll + xmean, sigma);
921 y_readout = gRandom->Gaus(ycoll, sigma);
923 Int_t iIChan = sensor->
GetFrontChannel(x_readout, y_readout, zcoll, dPitch);
939 fStripSignalF[iIChan] += 0.25;
940 fFChannelPointsMap[iIChan].insert(iPoint);
945 iIChan = sensor->
GetBackChannel(x_readout, y_readout, zcoll, dPitch);
957 fStripSignalB[iIChan] += 0.25;
958 fBChannelPointsMap[iIChan].insert(iPoint);
971 if (fPointMap.find(sensor) == fPointMap.end()) {
972 cerr <<
"-E- " << fName <<
"::ProduceHitResponseAZ:: sensor"
973 <<
" not found in digi scheme!" << endl;
976 pSet = fPointMap[sensor];
981 set<Int_t>::iterator it1;
983 const Int_t nclus = 25;
984 const Double_t mfpath = 1.0 / nclus;
985 const Double_t sigma = 0.05;
986 const Int_t maxClus = 102;
988 const Double_t clusSize[maxClus] = {
989 0.63403, 0.19005, 0.07334, 0.03335, 0.017906, 0.010391, 0.0066257, 0.0046042,
990 0.0034062, 0.0025641, 0.0020853, 0.001613, 0.0012888, 0.0010765, 0.00094932, 0.00087466,
991 0.00079435, 0.00072317, 0.00062637, 0.00053044, 0.00055171, 0.00053304, 0.00056429, 0.00058426,
992 0.00061465, 0.00057688, 0.00058166, 0.00050613, 0.00049571, 0.00046055, 0.00039327, 0.00035898,
993 0.00034162, 0.00030255, 0.00028475, 0.00027998, 0.00023961, 0.0002179, 0.0002153, 0.00019012,
994 0.00018188, 0.00015844, 0.000158, 0.00014368, 0.00013413, 0.00012805, 0.00011373, 0.00011112,
995 0.00011633, 0.000097666, 0.000099837, 0.000082474, 0.000095062, 0.000082474, 0.000091155, 0.000077699,
996 0.000074661, 0.000077699, 0.000074661, 0.000077699, 0.000062072, 0.000059468, 0.000054693, 0.000056429,
997 0.000049484, 0.000043407, 0.000054693, 0.000048616, 0.000044275, 0.000041237, 0.000041671, 0.000043407,
998 0.000041671, 0.000034292, 0.000033858, 0.000039501, 0.000027781, 0.000031687, 0.000029083, 0.000033424,
999 0.000030819, 0.000031253, 0.000032555, 0.000027781, 0.000024308, 0.000022138, 0.000026044, 0.000029083,
1000 0.000019099, 0.000023006, 0.000022572, 0.000020401, 0.000027781, 0.000018231, 0.000024308, 0.000026478,
1001 0.00002344, 0.000018665, 0.000018231, 0.000019099, 0.000016061, 0.0014806};
1002 static TH1D* hClSize = NULL;
1003 if (hClSize == NULL) {
1004 hClSize =
new TH1D(
"hClSize",
"", maxClus, 0, maxClus);
1005 for (Int_t
i = 0;
i < maxClus; ++
i)
1006 hClSize->Fill(
i + 0.5, clusSize[
i]);
1009 for (it1 = pSet.begin(); it1 != pSet.end(); it1++) {
1013 TVector3 posIn, posOut, posCur, vec;
1018 Double_t leng0 = vec.Mag(), leng = 0.0, dPitch;
1020 vector<TVector3> clusPos;
1021 vector<Double_t> vClusSize;
1025 Double_t step = gRandom->Exp(mfpath);
1026 posCur += step * vec;
1027 leng = posCur.Mag();
1028 if (leng <= leng0) {
1029 clusPos.push_back(posCur);
1030 vClusSize.push_back(Int_t(hClSize->GetRandom() + 1));
1038 Int_t nofSteps = clusPos.size();
1039 Double_t nEl = 0, nElGeant = fEnergyLossToSignal * point->GetEnergyLoss();
1040 for (Int_t
i = 0;
i < nofSteps; ++
i)
1041 nEl += vClusSize[
i];
1042 Double_t scale = nElGeant / nEl;
1043 for (Int_t
i = 0;
i < nofSteps; ++
i)
1044 vClusSize[
i] *= scale;
1051 for (Int_t istep = 0; istep < nofSteps; istep++) {
1052 clusPos[istep] += posIn;
1053 Double_t stepEL = vClusSize[istep];
1055 Int_t iIChan = sensor->
GetFrontChannel(clusPos[istep].X(), clusPos[istep].Y(), clusPos[istep].Z(), dPitch);
1064 for (Int_t jj = -4; jj < 5; ++jj) {
1065 Int_t ich = iIChan + jj;
1068 Double_t cx1 = TMath::Erf((-dPitch + jj * sensor->
GetDx()) / sigma);
1069 Double_t cx2 = TMath::Erf((-dPitch + (jj + 1) * sensor->
GetDx()) / sigma);
1070 Double_t frac = 0.5 * TMath::Abs(cx2 - cx1);
1073 Double_t dQ = stepEL * frac;
1074 fStripSignalF[ich] += dQ;
1075 fFChannelPointsMap[ich].insert(iPoint);
1079 iIChan = sensor->
GetBackChannel(clusPos[istep].X(), clusPos[istep].Y(), clusPos[istep].Z(), dPitch);
1088 for (Int_t jj = -4; jj < 5; ++jj) {
1089 Int_t ich = iIChan + jj;
1092 Double_t cx1 = TMath::Erf((-dPitch + jj * sensor->
GetDx()) / sigma);
1093 Double_t cx2 = TMath::Erf((-dPitch + (jj + 1) * sensor->
GetDx()) / sigma);
1094 Double_t frac = 0.5 * TMath::Abs(cx2 - cx1);
1097 Double_t dQ = stepEL * frac;
1098 fStripSignalB[ich] += dQ;
1099 fBChannelPointsMap[ich].insert(iPoint);