75 printf(
"CbmTrdModuleSim2D::MakeDigi @ T[ns] = ev[%10.2f]+hit[%5.2f] ...\n", time, point->GetTime());
86 gGeoManager->MasterToLocal(gin, lin);
87 gGeoManager->MasterToLocal(gout, lout);
90 printf(
" ModPos : in[%7.4f %7.4f %7.4f] out[%7.4f %7.4f %7.4f]\n", lin[0], lin[1], lin[2], lout[0], lout[1],
94 Double_t ELossTR(0.), ELossdEdX(point->GetEnergyLoss());
100 ELossTR = gRandom->Uniform() > 0.89 ? 6.492 : 5.895;
106 printf(
"CbmTrdModuleSim2D::MakeDigi for %s ...\n", (
IsFeCalib() ?
"55Fe" :
"X-rays"));
107 if (ELossTR > 0) LOG(info) <<
" Ex " << ELossTR <<
" keV";
118 else if (gout[2] >= gin[2]) {
120 point->Momentum(mom);
127 Double_t trackLength(0.), txy(0.);
128 for (
Int_t i = 0; i < 3; i++) {
129 dd[i] = (lout[i] - lin[i]);
130 if (i == 2) txy = trackLength;
131 trackLength += dd[i] * dd[i];
133 if (trackLength > 0.) trackLength = TMath::Sqrt(trackLength);
135 LOG(warn) << GetName()
136 <<
"::MakeDigi: NULL track length for"
138 << std::setprecision(5) << ELossdEdX * 1e6 <<
") keV ";
141 if (txy > 0.) txy = TMath::Sqrt(txy);
143 LOG(warn) << GetName()
144 <<
"::MakeDigi: NULL xy track length projection for"
146 << std::setprecision(5) << ELossdEdX * 1e6 <<
") keV ";
150 Double_t dzdy = dd[2] / dd[1];
151 if (
VERBOSE) printf(
" dzdy[%f]\n", dzdy);
154 memcpy(ain, lin, 3 *
sizeof(Double_t));
155 fDigiPar->ProjectPositionToNextAnodeWire(ain);
157 memcpy(aout, lout, 3 *
sizeof(Double_t));
158 fDigiPar->ProjectPositionToNextAnodeWire(aout);
161 Double_t dw(
fDigiPar->GetAnodeWireSpacing());
162 Int_t ncls = TMath::Nint(TMath::Abs(aout[1] - ain[1]) / dw + 1.);
164 printf(
" WireHit(s): %d\n", ncls);
165 printf(
" AnodePos : win[%7.4f / %7.4f] wout[%7.4f / %7.4f]\n", ain[1], lin[1], aout[1], lout[1]);
169 Int_t sgnx(1), sgny(1);
170 if (lout[0] < lin[0]) sgnx = -1;
171 if (lout[1] < lin[1]) sgny = -1;
172 Double_t dy[] = {TMath::Min((ain[1] + 0.5 * sgny * dw - lin[1]) * sgny, (lout[1] - lin[1]) * sgny),
173 TMath::Min((lout[1] - (aout[1] - 0.5 * sgny * dw)) * sgny, (lout[1] - lin[1]) * sgny)},
174 dxw(TMath::Abs(dd[0] * dw / dd[1])),
175 dx[] = {TMath::Abs(dy[0] * dd[0] / dd[1]), TMath::Abs(dy[1] * dd[0] / dd[1])};
177 Double_t DX(dx[0]), DY(dy[0]);
178 for (
Int_t ic(1); ic < ncls - 1; ic++) {
187 printf(
" DX[%7.4f] = dx0[%7.4f] + dx1[%7.4f] dwx[%7.4f] checkDX[%7.4f]\n"
188 " DY[%7.4f] = dy0[%7.4f] + dy1[%7.4f] dwy[%7.4f] checkDY[%7.4f]\n",
189 dd[0], dx[0], dx[1], dxw, sgnx * DX, dd[1], dy[0], dy[1], dw, sgny * DY);
192 Double_t
pos[3] = {ain[0], ain[1], ain[2]}, ldx(0.), ldy(0.), dxy(0.), e(0.),
193 tdrift, y0 = lin[1] - ain[1], z0 = lin[2];
194 for (
Int_t icl(0); icl < ncls; icl++) {
199 else if (icl == ncls - 1) {
208 dxy = ldx * ldx + ldy * ldy;
210 LOG(error) << GetName() <<
"::MakeDigi: NULL projected track length in cluster " << icl
211 <<
" for track length[cm] (" << std::setprecision(5) << ldx <<
", " << std::setprecision(2) << ldy
214 << std::setprecision(5) << ELossdEdX * 1e6 <<
") keV ";
217 dxy = TMath::Sqrt(dxy);
218 if (
VERBOSE) printf(
" %d ldx[%7.4f] ldy[%7.4f] xy[%7.4f] frac=%7.2f%%\n", icl, ldx, ldy, dxy, 1.e2 * dxy / txy);
220 Double_t dEdx(dxy / txy),
221 cELoss(ELossdEdX * dEdx);
225 printf(
" y0[%7.4f] z0[%7.4f] y1[%7.4f] z1[%7.4f]\n", y0, z0, y0 + ldy * sgny, z0 + dzdy * ldy * sgny);
226 tdrift =
fChmbPar->ScanDriftTime(y0, z0, dzdy, ldy * sgny);
228 z0 += dzdy * ldy * sgny;
229 pos[0] += 0.5 * ldx * sgnx;
230 if (
VERBOSE) printf(
" time_hit[ns]=%10.2f time_drift[ns]=%6.2f\n", time + point->GetTime(), tdrift);
233 cELoss =
fChmbPar->EkevFC(1e6 * cELoss);
235 pos[0] += 0.5 * ldx * sgnx;
242 if (TMath::Abs(ELossdEdX - e) > 1.e-3) {
243 LOG(warn) << GetName() <<
"::MakeDigi: dEdx partition to anode wires error : E[keV] = " << std::setprecision(5)
244 << ELossdEdX * 1e6 <<
" Sum(Ei)[keV]=" << std::setprecision(5) << e * 1e6;
249 Double_t lambda(0.3), diffx(0.1);
250 Double_t dist = gRandom->Exp(lambda);
251 if (
VERBOSE) printf(
" %d PE effect @ %7.4fcm trackLength=%7.4fcm\n", ncls, dist, trackLength);
252 if (dist > trackLength)
return kTRUE;
255 lin[0] += dd[0] * dist / trackLength;
256 lin[1] += dd[1] * dist / trackLength;
257 lin[2] += dd[2] * dist / trackLength;
259 memcpy(ain, lin, 3 *
sizeof(Double_t));
260 fDigiPar->ProjectPositionToNextAnodeWire(ain);
262 y0 = lin[1] - ain[1];
263 tdrift =
fChmbPar->GetDriftTime(y0, ain[2]);
264 Char_t peShell =
fChmbPar->GetPEshell(ELossTR);
268 if (gRandom->Uniform() <
fChmbPar->GetNonIonizingBR(peShell)) {
269 ELossTR -=
fChmbPar->GetBindingEnergy(peShell, 0);
271 printf(
" yM[%7.4f] zM[%7.4f] -> yA[%7.4f] y0[%7.4f] "
272 "tDrift[ns]=%3d PE=%c EscPeak Edep=%5.3f [keV]\n",
273 lin[1], lin[2], ain[1], y0,
Int_t(tdrift), peShell, ELossTR);
277 ELossTR -= 2 *
fChmbPar->GetBindingEnergy(peShell, 1);
279 printf(
" yM[%7.4f] zM[%7.4f] -> yA[%7.4f] y0[%7.4f] "
280 "tDrift[ns]=%3d PE=%c MainPeak Edep=%5.3f [keV]\n",
281 lin[1], lin[2], ain[1], y0,
Int_t(tdrift), peShell, ELossTR);
285 printf(
" yM[%7.4f] zM[%7.4f] -> yA[%7.4f] y0[%7.4f] tDrift[ns]=%3d "
287 lin[1], lin[2], ain[1], y0,
Int_t(tdrift), peShell);
289 ELossTR =
fChmbPar->EkevFC(ELossTR);
310 printf(
" WirePlane : xy[%7.4f %7.4f] D[%7.4f] S[fC]=%7.4f "
312 point[0], point[1], DX, ELoss, toff);
315 point[0] += (gRandom->Rndm() - 0.5) * DX * 0.1;
317 Int_t sec(-1), col(-1), row(-1);
318 fDigiPar->GetPadInfo(point, sec, col, row);
319 if (sec < 0 || col < 0 || row < 0) {
320 LOG(warn) <<
"CbmTrdModuleSim2D::ScanPadPlane: Hit to pad matching failed for [" << std::setprecision(5) << point[0]
321 <<
", " << std::setprecision(5) << point[1] <<
", " << std::setprecision(5) << point[2] <<
"].";
324 for (
Int_t is(0); is < sec; is++)
325 row +=
fDigiPar->GetNofRowsInSector(is);
328 fDigiPar->TransformToLocalPad(point, dx, dy);
329 if (
VERBOSE) printf(
" PadPlane : col[%d] row[%d] x[%7.4f] y[%7.4f]\n", col, row, dx, dy);
334 LOG(warn) <<
"CbmTrdModuleSim2D::ScanPadPlane: Hit outside integration limits [" << std::setprecision(5) << dx
335 <<
", " << std::setprecision(5) << dy <<
"].";
346 Double_t array[nc][nr][2] = {{{0.}}}, prf(0.);
347 Int_t colOff, rowOff, up ;
358 if (colOff < 0 || colOff >= nc || rowOff < 0 || rowOff >= nr) {
359 printf(
"CbmTrdModuleSim2D::ScanPadPlane: Bin outside mapped array : "
366 if (up) array[colOff][rowOff][(up > 0 ? 0 : 1)] += prf;
368 array[colOff][rowOff][0] += 0.5 * prf;
369 array[colOff][rowOff][1] += 0.5 * prf;
382 if (colOff < 0 || colOff >= nc || rowOff < 0 || rowOff >= nr) {
383 printf(
"CbmTrdModuleSim2D::ScanPadPlaneTriangleAB: Bin outside mapped "
384 "array : col[%d] row[%d]\n",
390 if (up) array[colOff][rowOff][(up > 0 ? 0 : 1)] += prf;
392 array[colOff][rowOff][0] += 0.5 * prf;
393 array[colOff][rowOff][1] += 0.5 * prf;
413 if (colOff < 0 || colOff >= nc || rowOff < 0 || rowOff >= nr) {
414 printf(
"CbmTrdModuleSim2D::ScanPadPlane: Bin outside mapped array : "
421 if (up) array[colOff][rowOff][(up > 0 ? 0 : 1)] += prf;
423 array[colOff][rowOff][0] += 0.5 * prf;
424 array[colOff][rowOff][1] += 0.5 * prf;
436 if (colOff < 0 || colOff >= nc || rowOff < 0 || rowOff >= nr) {
437 printf(
"CbmTrdModuleSim2D::ScanPadPlane: Bin outside mapped array : "
444 if (up) array[colOff][rowOff][(up > 0 ? 0 : 1)] += prf;
446 array[colOff][rowOff][0] += 0.5 * prf;
447 array[colOff][rowOff][1] += 0.5 * prf;
459 for (
Int_t ic(0); ic < nc; ic++)
460 printf(
"%7d[u/d] ", ic);
462 for (
Int_t ir(nr); ir--;) {
463 printf(
" r[%d] ", ir);
464 for (
Int_t ic(0); ic < nc; ic++)
465 printf(
"%6.4f/%6.4f ", 1.e2 * array[ic][ir][0], 1.e2 * array[ic][ir][1]);
475 Double_t Emeasure(0.);
476 for (
Int_t ir(nr); ir--;) {
477 for (
Int_t ic(nc); (--ic) >= 0;) {
478 for (
Int_t iup(0); iup < 2; iup++) {
481 Emeasure += array[ic][ir][iup];
488 if (ic < nc - 1) array[ic + 1][ir][0] += array[ic][ir][1];
489 array[ic][ir][1] += array[ic][ir][0];
493 printf(
" Sth[fC]=%6.4f Sdigi[fC]=%6.4f\n", ELoss, Emeasure);
495 for (
Int_t ic(0); ic < nc; ic++)
496 printf(
"%7d[T/R] ", ic);
498 for (
Int_t ir(nr); ir--;) {
499 printf(
" r[%d] ", ir);
500 for (
Int_t ic(0); ic < nc; ic++)
501 printf(
"%6.2f/%6.2f ", array[ic][ir][0], array[ic][ir][1]);
507 for (
Int_t ir(0); ir < nr; ir++) {
508 for (
Int_t ic(0); ic < nc; ic++) {
511 if (wcol < 0 || wcol >=
fDigiPar->GetNofColumns())
continue;
515 if (wrow < 0 || wrow >=
fDigiPar->GetNofRows())
continue;
518 Double_t dch[2] = {0.};
520 for (
Int_t iup(0); iup < 2; iup++) {
521 if (array[ic][ir][iup] < 0.1)
continue;
522 dch[iup] = TMath::Nint(array[ic][ir][iup] * 10.);
531 AddDigi(address, &dch[0], toff);
546 if (!
fAsicPar->GetFaspChannelPar(pad, daqFaspChT, daqFaspChR)) {
547 LOG(warn) << GetName() <<
"::AddDigi: Failed to retrieve calibration for FASP channels allocated to pad " << pad;
551 if (!daqFaspChT) charge[0] = 0;
552 else if (daqFaspChT->IsMasked())
556 if (!daqFaspChR) charge[1] = 0;
564 digi =
new CbmTrdDigi(pad, charge[0], charge[1], uint64_t(time));
567 Double_t weighting =
fChmbPar->EfCkeV(charge[0] * 0.1);
572 std::map<Int_t, std::vector<pair<CbmTrdDigi*, CbmMatch*>>>::iterator it =
fBuffer.find(pad);
577 for (std::vector<pair<CbmTrdDigi*, CbmMatch*>>::iterator itv =
fBuffer[pad].begin(); itv !=
fBuffer[pad].end();
580 if (sdigi->
GetTime() <= digi->GetTime())
continue;
581 fBuffer[pad].insert(itv, make_pair(digi, digiMatch));
582 if (
VERBOSE) cout <<
" => Save(I) " << digi->ToString();
587 fBuffer[pad].push_back(make_pair(digi, digiMatch));
588 if (
VERBOSE) cout <<
" => Save(B) " << digi->ToString();
592 if (
VERBOSE) cout <<
" => Add " << digi->ToString();
593 fBuffer[pad].push_back(make_pair(digi, digiMatch));
607 fFASP->SetNeighbourTrigger(0);
608 fFASP->SetLGminLength(31);
612 LOG(warn) << GetName() <<
"::FlushBuffer: Module operated with SPADIC. Development in progress.";
616 FairRootManager* ioman = FairRootManager::Instance();
622 if (!time) closeTS =
true;
627 if (time > 0 && !
fFASP->Go(time) && !closeTS)
return 0;
632 printf(
"CbmTrdModuleSim2D::FlushBuffer(%llu) FASP start[%llu] end[%llu] "
634 time,
fFASP->GetStartTime(),
fFASP->GetEndTime(), (closeTS ?
'y' :
'n'));
637 cout <<
"\nPHYS DIGITS : \n";
640 Int_t asicId, asicOld(-1);
647 Int_t padAddress(0), ndigi(0);
648 std::map<Int_t, std::vector<std::pair<CbmTrdDigi*, CbmMatch*>>>::iterator it =
fBuffer.begin();
649 for (; it !=
fBuffer.end(); it++) {
650 padAddress = it->first;
651 ndigi =
fBuffer[padAddress].size();
661 int chId[] = {-1, -1},
662 localAddress[] = {2 * padAddress, 2 * padAddress + 1},
664 fAsicPar->GetAsicAddress(localAddress[0]),
fAsicPar->GetAsicAddress(localAddress[1])};
666 if (faspIdOnMod[0] < 0 && faspIdOnMod[1] < 0) {
667 LOG(debug) << GetName() <<
"::FlushBuffer: FASP Calibration for pad " << padAddress <<
" at r/c=" << row <<
"/"
668 << col <<
" in module " <<
fModAddress <<
" missing.";
670 for (
auto iv =
fBuffer[padAddress].begin(); iv !=
fBuffer[padAddress].end(); iv++)
675 for (
int ifasp(0); ifasp < 2; ifasp++) {
676 asicId = faspIdOnMod[ifasp];
679 fFASP->InitChannel(ifasp,
nullptr);
683 if (asicId != asicOld) {
686 LOG(debug) << GetName() <<
"::FlushBuffer: Found FASP " << asicId % 1000 <<
" for module " <<
fModAddress
687 <<
" local " << localAddress[ifasp];
692 chFasp[ifasp] = fasp->
GetChannel(chId[ifasp]);
693 fFASP->InitChannel(ifasp, chFasp[ifasp], asicId, chId[ifasp]);
695 fFASP->PhysToRaw(&(it->second));
700 cout <<
"\nFEE DIGITS : \n";
702 cout <<
"\nRAW DIGITS : \n";
706 Int_t n(0), nDigiLeft(0);
707 double timeMin(-1), timeMax(0),
711 padAddress = it->first;
718 Int_t col(-1), row(-1), srow, sec;
719 auto iv =
fBuffer[padAddress].begin();
720 while (iv !=
fBuffer[padAddress].end()) {
723 if (digi->
GetTime() < newStartTime) newStartTime = digi->
GetTime();
726 iv =
fBuffer[padAddress].erase(iv);
735 digiMatch->
AddLink(iv->second->GetLink(0));
738 iv =
fBuffer[padAddress].erase(iv);
744 sec =
fDigiPar->GetSector(row, srow);
746 printf(
"CbmTrdModuleSim2D::FlushBuffer : request ly[%d] mod[%d] "
747 "sec[%d] srow[%d] col[%d]\n",
751 if (timeMin < 0 || digi->GetTime() < timeMin) timeMin = digi->
GetTime();
755 digiMatch = iv->second;
759 double t, r = digi->
GetCharge(t, dt), noise[2];
760 gRandom->RndmArray(2, noise);
767 iv =
fBuffer[padAddress].erase(iv);
771 nDigiLeft +=
fBuffer[padAddress].size();
779 printf(
"CbmTrdModuleSim2D::FlushBuffer : write %d digis in [%d - "
780 "%d]ns. Digits still in buffer %d\n",
781 n, TMath::Nint(timeMin), TMath::Nint(timeMax), nDigiLeft);
783 if (newStartTime > 0)
fFASP->SetStartTime(newStartTime);
787 if (time > 0)
fFASP->SetProcTime();
793 fFASP->SetStartTime(0);