CbmRoot
Loading...
Searching...
No Matches
CbmTrdModuleRec2D.cxx
Go to the documentation of this file.
1/* Copyright (C) 2018-2020 Horia Hulubei National Institute of Physics and Nuclear Engineering, Bucharest
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Alexandru Bercuci [committer] */
4
5#include "CbmTrdModuleRec2D.h"
6
7#include "CbmDigiManager.h"
8#include "CbmTrdCluster.h"
9#include "CbmTrdDigi.h"
10#include "CbmTrdDigiRec.h"
11#include "CbmTrdFASP.h"
12#include "CbmTrdHit.h"
13#include "CbmTrdParModDigi.h"
14
15#include <Logger.h>
16
17#include <TClonesArray.h>
18#include <TF1.h>
19#include <TGeoPhysicalNode.h>
20#include <TGraphErrors.h>
21
22#include <iostream>
23#include <vector>
24
25using std::cout;
26using std::endl;
27using std::vector;
28
29Double_t CbmTrdModuleRec2D::fgDT[] = {4.181e-6, 1586, 24};
30TGraphErrors* CbmTrdModuleRec2D::fgEdep = nullptr;
31TGraphErrors* CbmTrdModuleRec2D::fgT = nullptr;
32TF1* CbmTrdModuleRec2D::fgPRF = nullptr;
33//_______________________________________________________________________________
35
36//_______________________________________________________________________________
37CbmTrdModuleRec2D::CbmTrdModuleRec2D(Int_t mod, Int_t ly, Int_t rot) : CbmTrdModuleRec(mod, ly, rot)
38{
39 SetNameTitle(Form("Trd2dReco%d", mod), "Reconstructor for triangular pads.");
40 // printf("%s (%s)\n", GetName(), GetTitle()); Config(0, 1, 0);
41}
42
43//_______________________________________________________________________________
45
46//_______________________________________________________________________________
47Bool_t CbmTrdModuleRec2D::AddDigi(const CbmTrdDigi* d, Int_t id)
48{
54 int pad = d->GetAddressChannel(), col, row = GetPadRowCol(pad, col), dtime;
55 uint16_t chT = pad << 1, chR = chT + 1;
56 const CbmTrdParFaspChannel *daqFaspChT(nullptr), *daqFaspChR(nullptr);
57 if (!fAsicPar->GetFaspChannelPar(pad, daqFaspChT, daqFaspChR)) {
58 LOG(warn) << GetName() << "::AddDigi: Failed to retrieve calibration for FASP channels allocated to pad " << pad;
59 return false;
60 }
61
62 if (CWRITE(0)) {
63 cout << "\nadd @" << id << " " << d->ToString();
64 if (daqFaspChT)
65 daqFaspChT->Print();
66 else
67 cout << "\n[T] not installed.";
68 if (daqFaspChR)
69 daqFaspChR->Print();
70 else
71 cout << "\n[R] not installed.";
72 }
73
74 Double_t t, r = d->GetCharge(t, dtime);
75 Int_t tm = d->GetTimeDAQ() - fT0;
76 if (dtime < 0) tm += dtime; // correct for the difference between tilt and rect
77 if (r < 1) {
78 if (!daqFaspChR)
79 chR = 0; // TODO implement case for not installed
80 else if (!daqFaspChR->IsMasked())
81 chR = 0;
82 }
83 if (t < 1) {
84 if (!daqFaspChT)
85 chT = 0; // TODO implement case for not installed
86 else if (!daqFaspChT->IsMasked())
87 chT = 0;
88 }
89
90 if (CWRITE(0))
91 printf("row[%2d] col[%2d] tm[%2d] chT[%4d] chR[%4d]\n", row, col, tm,
92 chT * (daqFaspChT && daqFaspChT->IsMasked() ? -1 : 1),
93 chR * (daqFaspChR && daqFaspChR->IsMasked() ? -1 : 1));
94 CbmTrdCluster* cl(nullptr);
95
96 // get the link to saved clusters
97 std::map<Int_t, std::list<CbmTrdCluster*>>::iterator it = fBuffer.find(row);
98 // check for saved
99 if (it != fBuffer.end()) {
100 Bool_t kINSERT(kFALSE);
101 std::list<CbmTrdCluster*>::iterator itc = fBuffer[row].begin();
102 for (; itc != fBuffer[row].end(); itc++) {
103 //if (CWRITE(0)) cout << (*itc)->ToString();
104
105 UShort_t tc = (*itc)->GetStartTime();
106 Int_t dt = tc - tm;
107
108 if (dt < -5)
109 continue;
110 else if (dt < 5) {
111 if (CWRITE(0)) printf("match time dt=%d\n", dt);
112 if ((*itc)->IsChannelInRange(chT, chR) == 0) {
113 if (!(*itc)->AddDigi(id, chT, chR, dt)) break;
114 kINSERT = kTRUE;
115 if (CWRITE(0)) cout << " => Cl (Ad) " << (*itc)->ToString();
116 break;
117 }
118 }
119 else {
120 if (CWRITE(0)) printf("break for time dt=%d\n", dt);
121 break;
122 }
123 }
124
125 if (!kINSERT) {
126 if (itc != fBuffer[row].end() && itc != fBuffer[row].begin()) {
127 itc--;
128 fBuffer[row].insert(itc, cl = new CbmTrdCluster(fModAddress, id, chT, chR, row, tm));
129 if (CWRITE(0)) cout << " => Cl (I) ";
130 }
131 else {
132 fBuffer[row].push_back(cl = new CbmTrdCluster(fModAddress, id, chT, chR, row, tm));
133 if (CWRITE(0)) cout << " => Cl (Pb) ";
134 }
136 if (CWRITE(0)) cout << cl->ToString();
137 }
138 }
139 else {
140 fBuffer[row].push_back(cl = new CbmTrdCluster(fModAddress, id, chT, chR, row, tm));
142 if (CWRITE(0)) cout << " => Cl (Nw) " << cl->ToString();
143 }
144 fTimeLast = tm;
145
146 return kTRUE;
147}
148
149//_______________________________________________________________________________
151{
152 Int_t nch(0);
153 for (std::map<Int_t, std::list<CbmTrdCluster*>>::const_iterator ir = fBuffer.cbegin(); ir != fBuffer.cend(); ir++) {
154 for (std::list<CbmTrdCluster*>::const_iterator itc = (*ir).second.cbegin(); itc != (*ir).second.cend(); itc++)
155 nch += (*itc)->GetNCols();
156 }
157 return nch;
158}
159
160//_______________________________________________________________________________
162{
163 int faspAddress = fAsicPar->GetAsicAddress(ch);
164 const CbmTrdParFasp* p = static_cast<const CbmTrdParFasp*>(fAsicPar->GetAsicPar(faspAddress));
165 if (!p) {
166 LOG(error) << GetName() << "::GetFaspChCalibrator : Could not find FASP params for address=" << faspAddress
167 << " @ ch=" << ch;
168 return nullptr;
169 }
170 return p->GetChannel(ch / 2, ch % 2);
171}
172
173//_______________________________________________________________________________
175{
176 bool left = false, right = !left;
177 int nchRow = 2 * GetNcols(), nchAdd(0);
178
179 // check cluster is not at chmb left edge.
180 if (cl->GetStartCh() > 0 && (cl->GetStartCh() % nchRow != 0)) {
181 const CbmTrdParFaspChannel* daqCh = GetFaspChCalibrator(cl->GetStartCh() - 1);
182 if (daqCh && daqCh->IsMasked()) {
183 cl->AddChannel(left);
184 nchAdd++;
185 }
186 }
187
188 // check cluster is not at chmb right edge.
189 if (cl->GetEndCh() < NFASPMOD * NFASPCH && (cl->GetEndCh() % nchRow != nchRow - 1)) {
190 const CbmTrdParFaspChannel* daqCh = GetFaspChCalibrator(cl->GetEndCh() + 1);
191 if (daqCh && daqCh->IsMasked()) {
192 cl->AddChannel(right);
193 nchAdd++;
194 }
195 }
196 return nchAdd;
197}
198
199//_______________________________________________________________________________
201{
202 int ncl0(0), ncl(0), mcl(0);
203 std::list<CbmTrdCluster*>::iterator itc0, itc1, itc;
204 for (auto& clRow : fBuffer) {
205 if (CWRITE(0)) cout << "\nrow=" << clRow.first << " ncl=" << clRow.second.size() << endl;
206 // Phase 0 : try merge clusters if more than one on a row
207 if (clRow.second.size() > 1) {
208 itc0 = clRow.second.begin();
209 // TODO look left and right for masked channels. If they exists add them to cluster.
210 // if (AddClusterEdges(*itc0) && CWRITE(0)) cout << " edge cl[0] : " << (*itc0)->ToString();
211 itc = std::prev(clRow.second.end());
212 while (itc0 != itc) { // try merge clusters
213 if (CWRITE(0)) cout << "->BASE cl[0] : " << (*itc0)->ToString();
214
215 bool kMERGE(false);
216 itc1 = std::next(itc0);
217 while (itc1 != clRow.second.end()) {
218 if (CWRITE(0)) cout << " + cl[1] : " << (*itc1)->ToString();
219 if ((*itc0)->Merge((*itc1))) {
220 if (CWRITE(0)) cout << " SUM : " << (*itc0)->ToString();
221 kMERGE = true;
222 delete (*itc1);
223 itc1 = clRow.second.erase(itc1);
224 itc = std::prev(clRow.second.end());
225 }
226 else
227 itc1++;
228 }
229 if (!kMERGE) itc0++;
230 }
231 }
232 mcl += clRow.second.size();
233
234 // Phase 1 : copy older clusters from the buffer to the module wise storage
235 CbmTrdCluster* clDet(nullptr);
236 for (itc = clRow.second.begin(); itc != clRow.second.end();) {
237 if (!clr && fTimeLast - (*itc)->GetStartTime() < fTimeWinKeep) {
238 itc++;
239 continue;
240 }
241 clDet = new ((*fClusters)[ncl++]) CbmTrdCluster(*(*itc));
242 clDet->SetFaspDigis((*itc)->HasFaspDigis());
243 delete (*itc);
244 itc = clRow.second.erase(itc);
245 }
246 }
247 if (clr) fBuffer.clear();
248
249 for (auto clRow : fBuffer)
250 ncl0 += clRow.second.size();
251 if (CWRITE(0)) printf("FindClusters() cls_found = %d cls_write = %d cls_keep = %d\n", mcl, ncl, ncl0);
252
253 return ncl;
254}
255
256//_______________________________________________________________________________
257Bool_t CbmTrdModuleRec2D::MakeHits() { return kTRUE; }
258
259//_______________________________________________________________________________
261{
266 Int_t nhits = fHits->GetEntriesFast();
267 if (CWRITE(1)) LOG(info) << GetName() << "::PreProcessHits(" << nhits << ")";
268
269 CbmTrdHit* hit(nullptr);
270 for (Int_t ih(0); ih < nhits; ih++) {
271 hit = (CbmTrdHit*) ((*fHits)[ih]);
272 if (!CheckConvolution(hit)) continue;
273 nhits += Deconvolute(hit);
274 }
275 nhits = fHits->GetEntriesFast();
276 if (CWRITE(1)) LOG(info) << GetName() << "::Deconvolute(" << nhits << ")";
277 return kTRUE;
278}
279
280//_______________________________________________________________________________
281Bool_t CbmTrdModuleRec2D::CheckConvolution(CbmTrdHit* /*h*/) const { return kFALSE; }
282
283//_______________________________________________________________________________
284Bool_t CbmTrdModuleRec2D::Deconvolute(CbmTrdHit* /*h*/) { return kFALSE; }
285
286//_______________________________________________________________________________
288{
292 CbmTrdHit *h0(nullptr), *h1(nullptr);
293
294 Int_t a0, nhits = fHits->GetEntriesFast();
295 Float_t Dx(2 * fDigiPar->GetPadSizeX(0)), Dy(2 * fDigiPar->GetPadSizeY(0));
296 for (Int_t ih(0); ih < nhits; ih++) {
297 h0 = (CbmTrdHit*) ((*fHits)[ih]);
298 if (h0->IsUsed()) continue;
299
300 for (Int_t jh(ih + 1); jh < nhits; jh++) {
301 h1 = (CbmTrdHit*) ((*fHits)[jh]);
302 if (h1->IsUsed()) continue;
303
304 // basic check on Time
305 if (h1->GetTime() < 4000 - h0->GetTime()) continue; // TODO check with preoper time calibration
306 // skip next hits for being too far (10us) in the future
307 if (h1->GetTime() > 10000 + h0->GetTime()) break;
308
309 // basic check on Row
310 if (TMath::Abs(h1->GetY() - h0->GetY()) > Dy) continue;
311
312 // basic check on Col
313 if (TMath::Abs(h1->GetX() - h0->GetX()) > Dx) continue;
314
315 // go to topologic checks
316 if (!(a0 = CheckMerge(h0->GetRefId(), h1->GetRefId()))) continue;
317
318 ProjectDigis(a0 < 0 ? h0->GetRefId() : h1->GetRefId(), a0 < 0 ? h1->GetRefId() : h0->GetRefId());
319
320 // call the working algorithm
321 if (MergeHits(h0, a0)) h0->SetRowCross(h1);
322 if (CWRITE(1)) {
323 cout << ih << " : " << h0->ToString();
324 cout << jh << " : " << h1->ToString();
325 cout << "\n" << endl;
326 }
327 }
328 }
329 nhits = 0;
330 for (Int_t ih(0); ih < fHits->GetEntriesFast(); ih++) {
331 h0 = (CbmTrdHit*) ((*fHits)[ih]);
332 if (!h0->IsUsed()) continue;
333 fHits->RemoveAt(ih); //delete h0;
334 nhits++;
335 }
336 fHits->Compress();
337
338 // clear all calibrated digis
339 for (map<Int_t, vector<CbmTrdDigiRec*>>::iterator ic = fDigis.begin(); ic != fDigis.end(); ic++) {
340 for (vector<CbmTrdDigiRec*>::iterator id = ic->second.begin(); id != ic->second.end(); id++)
341 delete *id;
342 ic->second.clear();
343 }
344 fDigis.clear();
345
346 if (CWRITE(1)) LOG(info) << GetName() << "::MergeHits(" << nhits << ")";
347 return kTRUE;
348}
349
350
351//_______________________________________________________________________________
352Int_t CbmTrdModuleRec2D::CheckMerge(Int_t cid, Int_t cjd)
353{
359 Bool_t on(kFALSE);
360 Int_t /*row, */ col, rowMax(0), vc[2] = {-1, -1}, vm[2] = {0}, vcid[2] = {cid, cjd};
361 Double_t t(0.), r(0.), rtMax(0.), T(0.), m, d, mdMax(0.), M[2] = {-1., -1.}, S[2] = {0.};
362 vector<CbmTrdDigiRec*>::iterator id, jd, jp[2];
363 for (Int_t rowId(0); rowId < 2; rowId++) {
364 rtMax = 0.;
365 mdMax = 0.;
366 for (id = fDigis[vcid[rowId]].begin(); id != fDigis[vcid[rowId]].end(); id++) {
367 GetPadRowCol((*id)->GetAddressChannel(), col);
368 //cout<<(*id)->ToString();
369
370 // mark max position and type
371 t = (*id)->GetTiltCharge(on);
372 if (on && t > rtMax) {
373 vc[rowId] = col;
374 vm[rowId] = 0;
375 rtMax = t;
376 }
377 r = (*id)->GetRectCharge(on);
378 if (on && r > rtMax) {
379 vc[rowId] = col;
380 vm[rowId] = 1;
381 rtMax = r;
382 }
383
384 m = 0.;
385 d = 0.;
386 if (!rowId) { // compute TR pairs on the bottom row
387 m = 0.5 * (t + r);
388 d = r - t;
389 }
390 else { // compute RT pairs on the upper row
391 jd = id + 1;
392 T = 0.;
393 if (jd != fDigis[vcid[rowId]].end()) T = (*jd)->GetTiltCharge(on);
394
395 m = 0.5 * (r + T);
396 d = r - T;
397 }
398 if (TMath::Abs(m) > 0.) d = 1.e2 * d / m;
399 if (m > mdMax) {
400 mdMax = m;
401 M[rowId] = m;
402 S[rowId] = d;
403 jp[rowId] = id;
404 rowMax = rowId;
405 }
406 }
407 }
408 rowMax = M[0] > M[1] ? 0 : 1;
409
410 // basic check on col of the max signal
411 Int_t dc = vc[1] - vc[0];
412 if (dc < 0 || dc > 1) return 0;
413
414 // special care for both tilt maxima : the TT case
415 // recalculate values on the min row on neighbor column
416 if (!vm[0] && !vm[1]) {
417 if (rowMax == 0) { // modify r=1
418 r = T = 0.;
419 if (M[1] >= 0) {
420 if (jp[1] != fDigis[cjd].end()) jp[1]++;
421 if (jp[1] != fDigis[cjd].end()) {
422 r = (*jp[1])->GetRectCharge(on);
423 jp[1]++;
424 if (jp[1] != fDigis[cjd].end()) T = (*jp[1])->GetTiltCharge(on);
425 }
426 }
427 M[1] = 0.5 * (r + T);
428 S[1] = r - T;
429 }
430 else { // modify r=0
431 r = t = 0.;
432 if (M[0] >= 0) {
433 if (jp[0] != fDigis[cid].begin()) jp[0]--;
434 if (jp[0] != fDigis[cid].begin()) {
435 r = (*jp[0])->GetRectCharge(on);
436 t = (*jp[0])->GetTiltCharge(on);
437 }
438 }
439 M[0] = 0.5 * (t + r);
440 S[0] = r - t;
441 }
442 }
443 rowMax = M[0] > M[1] ? 0 : 1;
444
445 // Build the ratio of the charge
446 Float_t mM = M[rowMax ? 0 : 1] / M[rowMax];
447
448 // Float_t mM_c[] = {0.03, 0.243, 0.975}, // center of distribution for each anode hypo
449 // mM_s[] = {0., 1.7e-3, 8.8e-3}, // slope of distribution for each anode hypo
450 // mM_r[] = {0.03, 0.03, 0.01}; // range of distribution for each anode hypo in proper coordinates
451 // for(Int_t ia(0); ia<3; ia++)
452 // if(TMath::Abs(mM_s[ia] * S[rowMax] + mM_c[ia] - mM) < mM_r[ia] ) return (rowMax?1:-1) * (3-ia);
453
454 Float_t mS = TMath::Abs(S[rowMax]), mM_l[3] = {0.15, 0.5, 1}, mM_r[3] = {0, 0.28, 1}, mS_r[3] = {43, 27, 20}, dSdM[2],
455 S0[2];
456 for (Int_t i(0); i < 2; i++) {
457 dSdM[i] = (mS_r[i + 1] - mS_r[i]) / (mM_r[i + 1] - mM_r[i]);
458 S0[i] = mS_r[i] - dSdM[i] * mM_r[i];
459 }
460 Int_t irange = mM < mM_r[1] ? 0 : 1;
461 if (mS > S0[irange] + dSdM[irange] * mM) return 0;
462
463 for (Int_t ia(0); ia < 3; ia++) {
464 if (mM < mM_l[ia]) return (rowMax ? 1 : -1) * (3 - ia);
465 }
466 return 0;
467}
468
469
470//_______________________________________________________________________________
472{
473 Int_t n0(vs.size() - 2);
474 Double_t dx(0.), dy(0.);
475
476 switch (n0) {
477 case 1:
478 if (IsMaxTilt()) { // T
479 dx = -0.5;
480 dy = 0;
481 }
482 else { // R
483 dx = 0.5;
484 dy = 0;
485 }
486 break;
487 case 2:
488 if (IsOpenLeft() && IsOpenRight()) { // RT
489 dx = viM == 1 ? 0. : -1;
490 dy = -0.5;
491 }
492 else { // TR
493 dx = 0.;
494 dy = 0.5;
495 }
496 break;
497 case 3:
498 if (IsMaxTilt() && !IsSymmHit()) { // TRT asymm
499 dx = viM == 1 ? 0. : -1;
500 dy = GetYoffset();
501 }
502 else if (!IsMaxTilt() && IsSymmHit()) { // TRT symm
503 dx = 0.;
504 dy = GetYoffset();
505 }
506 else if (IsMaxTilt() && IsSymmHit()) { // RTR symm
507 dx = GetXoffset();
508 dy = 0.;
509 }
510 else if (!IsMaxTilt() && !IsSymmHit()) { // RTR asymm
511 dx = GetXoffset();
512 dy = viM == 1 ? -0.5 : 0.5;
513 }
514 break;
515 default:
516 dx = GetXoffset();
517 dy = GetYoffset();
518 break;
519 }
520
521 RecenterXoffset(dx);
522 Int_t typ(GetHitClass());
523 // get position correction [pw]
524 Double_t xcorr = GetXcorr(dx, typ, 1) / fDigiPar->GetPadSizeX(0), xcorrBias(xcorr);
525 if (IsBiasX()) {
526 typ = GetHitRcClass(a0);
527 Int_t xmap = vyM & 0xff;
528 switch (n0) {
529 case 4:
530 if (dx < 0)
531 xcorrBias += (IsBiasXleft() ? -0.12 : 0.176);
532 else
533 xcorrBias += (xmap == 53 || xmap == 80 || xmap == 113 || xmap == 117 ? -0.176 : 0.12);
534 break;
535 case 5:
536 case 7:
537 if (typ < 0) break;
538 if (xmap == 50 || xmap == 58 || xmap == 146 || xmap == 154) {
539 if (typ == 2)
540 xcorr += 0.0813;
541 else if (typ == 3) {
542 xcorr -= 0.0813;
543 typ = 2;
544 }
545 dx -= xcorr;
546 RecenterXoffset(dx);
547 xcorrBias = GetXcorr(dx, typ, 2) / fDigiPar->GetPadSizeX(0);
548 }
549 else {
550 dx -= xcorr;
551 RecenterXoffset(dx);
552 if (typ < 2)
553 xcorrBias = GetXcorr(dx, typ, 2) / fDigiPar->GetPadSizeX(0);
554 else if (typ == 2)
555 xcorrBias = 0.12;
556 else if (typ == 3)
557 xcorrBias = -0.12;
558 }
559 break;
560 default:
561 if (typ < 0)
562 break;
563 else if (typ == 2)
564 xcorr += 0.0813;
565 else if (typ == 3) {
566 xcorr -= 0.0813;
567 typ = 2;
568 }
569 dx -= xcorr;
570 RecenterXoffset(dx);
571 xcorrBias = GetXcorr(dx, typ, 2) / fDigiPar->GetPadSizeX(0);
572 break;
573 }
574 }
575 else {
576 if (typ) xcorrBias += (dx < 0 ? 1 : -1) * 0.0293;
577 }
578 dx -= xcorrBias;
579 RecenterXoffset(dx);
580 dy = dx - dy;
581 RecenterYoffset(dy);
582 if (dy < -0.5 || dy > 0.5) printf("!!! dy = %f r[%d]\n", dy, vrM);
583
584 Double_t ycorr = GetYcorr(dy) / fDigiPar->GetPadSizeY(0);
585 dy += ycorr;
586 RecenterYoffset(dy);
587 dx *= fDigiPar->GetPadSizeX(0);
588 dy *= fDigiPar->GetPadSizeY(0);
589
590 TVector3 local_pad, local_pad_err;
591 Int_t srow, sector = fDigiPar->GetSectorRow(vrM, srow);
592 fDigiPar->GetPadPosition(sector, vcM, srow, local_pad, local_pad_err);
593
594 Double_t edx(1), edy(1), edt(60), time(-21), tdrift(100), e(200);
595 Double_t local[3] = {local_pad[0] + dx, local_pad[1] + dy, local_pad[2]}, global[3];
596 // globalErr[3] = {0/*edx*/, 0/*edy*/, 0.};
597 LocalToMaster(local, global);
598 h->SetX(global[0]);
599 h->SetY(global[1]);
600 h->SetZ(global[2]);
601 h->SetDx(edx);
602 h->SetDy(edy);
603 h->SetDz(0.);
604 h->SetDxy(0.);
605 h->SetTime(CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kFASP) * (vt0 + time) - tdrift + 30.29 + fHitTimeOff, edt);
606 h->SetELoss(e);
607 h->SetClassType();
608 h->SetMaxType(IsMaxTilt());
609 h->SetOverFlow(HasOvf());
610
611 if (CWRITE(1)) {
612 printf("-> loc[%6.2f %6.2f %6.2f] err[%6.2f %6.2f %6.2f]\n", local_pad[0], local_pad[1], local_pad[2],
613 local_pad_err[0], local_pad_err[1], local_pad_err[2]);
614 printf("REC col[%2d] row[%2d] dx[%7.3f(pw) %7.3f(cm)] x[%7.2f] y[%7.2f] dy[%5.2f] t0[%llu]\n", vcM, vrM,
615 dx / fDigiPar->GetPadSizeX(0), dx, global[0], global[1], dy, vt0);
616 }
617
618 return kTRUE;
619}
620
621//_______________________________________________________________________________
623{
624 Int_t n0(vs.size() - 2);
625 Double_t dx(0.), dy(0.); //, da(0.);
626
627 switch (n0) {
628 case 1:
629 if (IsMaxTilt()) { // T
630 dx = -0.5;
631 dy = 0;
632 }
633 else { // R
634 dx = 0.5;
635 dy = 0;
636 }
637 break;
638 case 2:
639 if (IsOpenLeft() && IsOpenRight()) { // RT
640 dx = viM == 1 ? 0. : -1;
641 dy = -0.5;
642 }
643 else { // TR
644 dx = 0.;
645 dy = 0.5;
646 }
647 break;
648 case 3:
649 if (IsMaxTilt() && !IsSymmHit()) { // TRT asymm
650 dx = viM == 1 ? 0. : -1;
651 dy = GetYoffset();
652 }
653 else if (!IsMaxTilt() && IsSymmHit()) { // TRT symm
654 dx = 0.;
655 dy = GetYoffset();
656 }
657 else if (IsMaxTilt() && IsSymmHit()) { // RTR symm
658 dx = GetXoffset();
659 dy = 0.;
660 }
661 else if (!IsMaxTilt() && !IsSymmHit()) { // RTR asymm
662 dx = GetXoffset();
663 dy = viM == 1 ? -0.5 : 0.5;
664 }
665 break;
666 default:
667 dx = GetXoffset();
668 dy = GetYoffset();
669 break;
670 }
671 RecenterXoffset(dx);
672
673 // get position correction
674 Double_t xcorr = GetXcorr(dx, GetHitClass()) / fDigiPar->GetPadSizeX(0);
675 dx -= xcorr;
676 RecenterXoffset(dx);
677 dy = dx - dy;
678 RecenterYoffset(dy);
679 if (dy < -0.5 || dy > 0.5) printf("!!! dy = %f r[%d]\n", dy, vrM);
680
681 Double_t ycorr = GetYcorr(dy) / fDigiPar->GetPadSizeY(0);
682 dy += ycorr;
683 RecenterYoffset(dy);
684 dx *= fDigiPar->GetPadSizeX(0);
685 dy *= fDigiPar->GetPadSizeY(0);
686
687 // get anode wire offset
688 Int_t ia(0);
689 Float_t ya(0.); // anode position in local pad coordinates
690 for (; ia <= NANODE; ia++) {
691 ya = -1.35 + ia * 0.3;
692 if (dy > ya + 0.15) continue;
693 break;
694 }
695 // da = dy-ya;
696 // //correct inside apmlification region
697 // da*=-0.7;
698 // if(da<-0.015) da+=0.1;
699 // else if(da>0.015) da-=0.1;
700 // dy+=da;
701 // da = dy - ya;
702
703 // Error parametrization X : parabolic model on cl size
704 Double_t parX[] = {0.713724, -0.318667, 0.0366036};
705 Double_t parY[] = {0.0886413, 0., 0.0435141};
706 Int_t nex = TMath::Min(n0, 7);
707 Double_t edx = parX[0] + parX[1] * nex + parX[2] * nex * nex, edy = parY[0] + parY[2] * dy * dy,
708 edt = 26.33; // should be parametrized as function of da TODO
709 // use this trick to force larger roads on CbmLitTrackFinderBranch
710 // target code from CbmLitTrackFinderBranch::FollowTracks and CbmLitHitData::AddHit
711 // bool hitInside = (pixelHit->GetX() < (tpar.GetX() + devX)) && (pixelHit->GetX() > (tpar.GetX() - devX))
712 if (n0 < 3) {
713 edx = 1.;
714 edy = 1.;
715 edt = 60.;
716 }
717
718 TVector3 local_pad, local_pad_err;
719 Int_t srow, sector = fDigiPar->GetSectorRow(vrM, srow);
720 fDigiPar->GetPadPosition(sector, vcM, srow, local_pad, local_pad_err);
721
722 Double_t local[3] = {local_pad[0] + dx, local_pad[1] + dy, local_pad[2]}, global[3];
723 //globalErr[3] = {edx, edy, 0.};
724 LocalToMaster(local, global);
725
726 // COMPUTE TIME
727 Double_t t_avg(0.), e_avg(0.);
728 for (Int_t idx(1); idx <= n0; idx++) {
729 Double_t dtFEE =
730 fgDT[0] * (vs[idx] - fgDT[1]) * (vs[idx] - fgDT[1]) / CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kFASP);
731 if (vxe[idx] > 0) vx[idx] += dy / fDigiPar->GetPadSizeY(0);
732 if (fgT != nullptr)
733 fgT->SetPoint(idx - 1, vx[idx], vt[idx] - dtFEE);
734 else
735 t_avg += (vt[idx] - dtFEE);
736 }
737 Double_t xc(0.);
738 if (fgT != nullptr) {
739 xc = vx[n0 + 2];
740 for (Int_t ip(n0); ip < fgT->GetN(); ip++) {
741 fgT->SetPoint(ip, xc, 0);
742 xc += 0.5;
743 }
744 }
745 Double_t time(-21.), tdrift(100); // should depend on Ua
746 if (n0 > 1) {
747 if (fgT != nullptr && (fgT->Fit("pol1", "QC", "goff") == 0)) {
748 TF1* f = fgT->GetFunction("pol1");
749 time = f->GetParameter(0) - fgDT[2];
750 if (TMath::IsNaN(time)) time = -21;
751 //dtime += TMath::Abs(f->GetParameter(1)*(vx[n0+1] - vx[1]));
752 }
753 else
754 time = t_avg / n0;
755 }
756 // COMPUTE ENERGY
757 for (UInt_t idx(0); idx < vs.size(); idx++) {
758 if (fgEdep != nullptr) {
759 double x_offset = dy / fDigiPar->GetPadSizeY(0), xp = vx[idx] + (vxe[idx] > 0 ? x_offset : 0);
760 fgEdep->SetPoint(idx, xp, vs[idx]);
761 fgEdep->SetPointError(idx, vxe[idx], vse[idx]);
762 }
763 else
764 e_avg += vs[idx];
765 }
766 if (fgEdep != nullptr) {
767 xc = vx[n0 + 2];
768 for (Int_t ip(vs.size()); ip < fgEdep->GetN(); ip++) {
769 //fgEdep->RemovePoint(ip);
770 xc += 0.5;
771 fgEdep->SetPoint(ip, xc, 0);
772 fgEdep->SetPointError(ip, 0., 300);
773 }
774 //if(CWRITE(1)) fgEdep->Print();
775 }
776
777 Double_t e(0.), xlo(*vx.begin()), xhi(*vx.rbegin());
778 if (fgEdep != nullptr) {
779 fgPRF->SetParameter(0, vs[viM]);
780 fgPRF->FixParameter(1, dx / fDigiPar->GetPadSizeX(0));
781 fgPRF->SetParameter(2, 0.65);
782 fgPRF->SetParLimits(2, 0.45, 10.5);
783 fgEdep->Fit(fgPRF, "QBN", "goff", xlo - 0.5, xhi + 0.5);
784 if (!fgPRF->GetNDF()) return false;
785 //chi = fgPRF->GetChisquare()/fgPRF->GetNDF();
786 e = fgPRF->Integral(xlo - 0.5, xhi + 0.5);
787
788 // apply MC correction
789 Float_t gain0 = 210.21387; //(XeCO2 @ 1900V)
790 // Float_t grel[3] = {1., 0.98547803, 0.93164071},
791 // goff[3][3] = {
792 // {0.05714, -0.09, -0.09},
793 // {0., -0.14742, -0.14742},
794 // {0., -0.29, -0.393}
795 // };
796 // Int_t ian=0;
797 // if(TMath::Abs(dy)<=0.3) ian=0;
798 // else if(TMath::Abs(dy)<=0.6) ian=1;
799 // else if(TMath::Abs(dy)<=0.9) ian=2;
800 // Int_t isize=0;
801 // if(n0<=3) isize=0;
802 // else if(n0<=4) isize=1;
803 // else isize=2;
804 Float_t gain = gain0; //*grel[ian];
805 e /= gain; // apply effective gain
806 //e+=goff[ian][isize]; // apply missing energy offset
807 }
808 else
809 e = e_avg;
810
811 h->SetX(global[0]);
812 h->SetY(global[1]);
813 h->SetZ(global[2]);
814 h->SetDx(edx);
815 h->SetDy(edy);
816 h->SetDz(0);
817 h->SetDxy(0.);
818 h->SetTime(CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kFASP) * (vt0 + time) - tdrift + 30.29 + fHitTimeOff, edt);
819 h->SetELoss(e * 1.e-9); // conversion to GeV
820 h->SetClassType();
821 h->SetMaxType(IsMaxTilt());
822 h->SetOverFlow(HasOvf());
823
824 if (CWRITE(1)) {
825 printf("-> loc[%6.2f %6.2f %6.2f] err[%6.2f %6.2f %6.2f]\n", local_pad[0], local_pad[1], local_pad[2],
826 local_pad_err[0], local_pad_err[1], local_pad_err[2]);
827 printf("REC col[%2d] row[%2d] x[%7.2f] dx[%5.2f] y[%7.2f] dy[%5.2f] t0[%llu]\n", vcM, vrM, global[0], dx, global[1],
828 dy, vt0);
829 }
830
831 return kTRUE;
832}
833
834#include <TCanvas.h>
835#include <TH1.h>
836//_______________________________________________________________________________
837CbmTrdHit* CbmTrdModuleRec2D::MakeHit(Int_t ic, const CbmTrdCluster* cl, std::vector<const CbmTrdDigi*>* digis)
838{
839 if (!cl->HasFaspDigis()) {
840 LOG(debug) << GetName() << "::MakeHit: Hybrid cluster SPADIC/Trd2d. Skipped for the moment.";
841 // std::cout << cl->ToString();
842 return nullptr;
843 }
844 //printf("%s (%s)\n", GetName(), GetTitle()); Config(1,0);
845
846 if (CHELPERS() && fgEdep == nullptr) { // first use initialization of PRF helppers
847 LOG(info) << GetName() << "::MakeHit: Init static helpers. ";
848 fgEdep = new TGraphErrors;
849 fgEdep->SetLineColor(kBlue);
850 fgEdep->SetLineWidth(2);
851 fgT = new TGraphErrors;
852 fgT->SetLineColor(kBlue);
853 fgT->SetLineWidth(2);
854 fgPRF = new TF1("prf", "[0]*exp(-0.5*((x-[1])/[2])**2)", -10, 10);
855 fgPRF->SetLineColor(kRed);
856 fgPRF->SetParNames("E", "x", "prf");
857 }
858 TH1* hf(nullptr);
859 TCanvas* cvs(nullptr);
860 if (CDRAW()) {
861 cvs = new TCanvas("c", "TRD Anode Hypothesis", 10, 600, 1000, 500);
862 cvs->Divide(2, 1, 1.e-5, 1.e-5);
863 TVirtualPad* vp = cvs->cd(1);
864 vp->SetLeftMargin(0.06904908);
865 vp->SetRightMargin(0.009969325);
866 vp->SetTopMargin(0.01402806);
867 vp = cvs->cd(2);
868 vp->SetLeftMargin(0.06904908);
869 vp->SetRightMargin(0.009969325);
870 vp->SetTopMargin(0.01402806);
871 hf = new TH1I("hf", ";x [pw];s [ADC chs]", 100, -3, 3);
872 hf->GetYaxis()->SetRangeUser(-50, 4500);
873 hf->Draw("p");
874 }
875
876 if (CWRITE(1)) cout << cl->ToString();
877 if (!LoadDigis(digis, ic)) return nullptr;
878 if (!ProjectDigis(ic)) return nullptr;
879 Int_t nofHits = fHits->GetEntriesFast();
880 CbmTrdHit* hit = new ((*fHits)[nofHits]) CbmTrdHit();
882 hit->SetRefId(ic);
883 //hit->SetMatch();
884 BuildHit(hit);
885 if (CWRITE(1)) cout << hit->ToString();
886 if (CDRAW()) DrawHit(hit);
887 return hit;
888}
889
890//_______________________________________________________________________________
892{
898 Int_t n0(vs.size() - 2);
899 if ((n0 == 5 && ((IsMaxTilt() && IsSymmHit()) || (!IsMaxTilt() && !IsSymmHit()))) || // TRTRT symm/asymm
900 n0 == 4 || (n0 == 3 && ((IsMaxTilt() && IsSymmHit()) || (!IsMaxTilt() && !IsSymmHit()))))
901 return 1; // RTR symm/asymm
902 else if (n0 > 5 && HasOvf())
903 return 2;
904 return 0;
905}
906
907//_______________________________________________________________________________
909{
910 Int_t a0m = TMath::Abs(a0);
911 UChar_t xmap = vyM & 0xff;
912 if (a0m == 2 && IsBiasXleft() && IsBiasXright() && !IsBiasXmid())
913 return 0;
914 else if (a0m == 3 && ((IsBiasXleft() && IsBiasXright()) || xmap == 116 || xmap == 149 || xmap == 208))
915 return 1;
916 else if (!IsBiasXleft()
917 && (a0m == 2
918 || (a0m == 3 && ((!IsBiasXright() && IsBiasXmid()) || xmap == 209 || xmap == 212 || xmap == 145))))
919 return 2;
920 else if (!IsBiasXright()
921 && (a0m == 2 || (a0m == 3 && ((!IsBiasXleft() && IsBiasXmid()) || xmap == 112 || xmap == 117))))
922 return 3;
923 else
924 return -1;
925}
926
927//_______________________________________________________________________________
928Double_t CbmTrdModuleRec2D::GetXoffset(Int_t n0) const
929{
930 Double_t dx(0.), R(0.);
931 Int_t n(n0 ? n0 : vs.size());
932 for (Int_t ir(0); ir < n; ir++) {
933 if (vxe[ir] > 0) continue; // select rectangular coupling
934 R += vs[ir];
935 dx += vs[ir] * vx[ir];
936 }
937 if (TMath::Abs(R) > 0) return dx / R;
938 LOG(debug) << GetName() << "::GetXoffset : Null total charge for hit size " << n;
939 return 0.;
940}
941
942//_______________________________________________________________________________
943Double_t CbmTrdModuleRec2D::GetYoffset(Int_t n0) const
944{
945 Double_t dy(0.), T(0.);
946 Int_t n(n0 ? n0 : vs.size());
947 for (Int_t it(0); it < n; it++) {
948 if (vxe[it] > 0) { // select tilted coupling
949 T += vs[it];
950 dy += vs[it] * vx[it];
951 }
952 }
953 if (TMath::Abs(T) > 0) return dy / T;
954 LOG(debug) << GetName() << "::GetYoffset : Null total charge for hit size " << n;
955 //if (CWRITE(1))
956 return 0.;
957}
958
959//_______________________________________________________________________________
960Double_t CbmTrdModuleRec2D::GetXcorr(Double_t dxIn, Int_t typ, Int_t cls) const
961{
967 if (typ < 0 || typ > 2) {
968 //LOG(error)<< GetName() << "::GetXcorr : type in-param "<<typ<<" out of range.";
969 return 0;
970 }
971 Double_t dx = TMath::Abs(dxIn);
972 Int_t ii = TMath::Max(0, TMath::Nint(dx / fgCorrXdx) - 1), i0; // i1;
973
974 if (ii < 0 || ii > NBINSCORRX) {
975 LOG(warn) << GetName() << "::GetXcorr : LUT idx " << ii << " out of range for dx=" << dxIn;
976 return 0;
977 }
978 if (dx < fgCorrXdx * ii) {
979 i0 = TMath::Max(0, ii - 1);
980 /*i1=ii;*/
981 }
982 else {
983 i0 = ii;
984 /*i1=TMath::Min(NBINSCORRX-1,ii+1);*/
985 }
986
987 Float_t* xval = &fgCorrXval[typ][i0];
988 if (cls == 1)
989 xval = &fgCorrRcXval[typ][i0];
990 else if (cls == 2)
991 xval = &fgCorrRcXbiasXval[typ][i0];
992 Double_t DDx = (xval[1] - xval[0]), a = DDx / fgCorrXdx, b = xval[0] - DDx * (i0 + 0.5);
993 return (dxIn > 0 ? 1 : -1) * b + a * dxIn;
994}
995
996//_______________________________________________________________________________
997Double_t CbmTrdModuleRec2D::GetYcorr(Double_t dy, Int_t /* cls*/) const
998{
1002 Float_t fdy(1.), yoff(0.);
1003 Int_t n0(vs.size() - 2);
1004 switch (n0) {
1005 case 3:
1006 fdy = fgCorrYval[0][0];
1007 yoff = fgCorrYval[0][1];
1008 if (IsMaxTilt() && IsSymmHit()) {
1009 fdy = 0.;
1010 yoff = (dy > 0 ? -1 : 1) * 1.56;
1011 }
1012 else if (!IsMaxTilt() && !IsSymmHit()) {
1013 fdy = 0.;
1014 yoff = (dy > 0 ? -1 : 1) * 1.06;
1015 }
1016 else if (!IsMaxTilt() && IsSymmHit()) {
1017 fdy = 2.114532;
1018 yoff = -0.263;
1019 }
1020 else /*if(IsMaxTilt()&&!IsSymmHit())*/ {
1021 fdy = 2.8016010;
1022 yoff = -1.38391;
1023 }
1024 break;
1025 case 4:
1026 fdy = fgCorrYval[1][0];
1027 yoff = fgCorrYval[1][1];
1028 if ((!IsMaxTilt() && IsLeftHit()) || (IsMaxTilt() && !IsLeftHit())) yoff *= -1;
1029 break;
1030 case 5:
1031 case 7:
1032 case 9:
1033 case 11:
1034 fdy = fgCorrYval[2][0];
1035 yoff = fgCorrYval[2][1];
1036 break;
1037 case 6:
1038 case 8:
1039 case 10:
1040 fdy = fgCorrYval[3][0];
1041 yoff = fgCorrYval[3][1];
1042 if ((!IsMaxTilt() && IsLeftHit()) || (IsMaxTilt() && !IsLeftHit())) yoff *= -1;
1043 break;
1044 }
1045 return dy * fdy + yoff;
1046}
1047
1048//_______________________________________________________________________________
1050{
1054 if (dx >= -0.5 && dx < 0.5) return;
1055 Int_t ishift = Int_t(dx - 0.5) + (dx > 0.5 ? 1 : 0);
1056 if (vcM + ishift < 0)
1057 ishift = -vcM;
1058 else if (vcM + ishift >= GetNcols())
1059 ishift = GetNcols() - vcM - 1;
1060 LOG(debug) << GetName() << "::RecenterXoffset : shift dx offset by " << ishift << " from dx=" << dx << " to "
1061 << dx - ishift << " center col from " << (Int_t) vcM << " to " << Int_t(vcM + ishift);
1062 dx -= ishift;
1063 vcM += ishift;
1064 for (UInt_t idx(0); idx < vx.size(); idx++)
1065 vx[idx] -= ishift;
1066}
1067
1068
1069//_______________________________________________________________________________
1071{
1075 if (dy >= -0.5 && dy < 0.5) return;
1076 Int_t ishift = Int_t(dy - 0.5) + (dy > 0.5 ? 1 : 0);
1077 // if(vrM+ishift < 0) ishift = - vrM;
1078 // else if(vrM+ishift >= GetNrows()) ishift = GetNrows() - vrM -1;
1079 LOG(debug) << GetName() << "::RecenterYoffset : shift dy offset by " << ishift << " from dy=" << dy << " to "
1080 << dy - ishift;
1081 dy -= ishift;
1082 //vrM+= ishift;
1083 // if(vrM==0 && dy<-0.5) dy=-0.5;
1084 // if(vrM==GetNrows() -1 && dy>0.5) dy=0.5;
1085}
1086
1087//_______________________________________________________________________________
1088Int_t CbmTrdModuleRec2D::LoadDigis(vector<const CbmTrdDigi*>* din, Int_t cid)
1089{
1094 Int_t col(-1), /*row, */ colT(-1), colR(-1);
1095 const CbmTrdDigi *dgT(nullptr), *dgR(nullptr);
1096 for (vector<const CbmTrdDigi*>::iterator i = din->begin(), j = i + 1; i != din->end(); i++) {
1097 dgT = (*i);
1098 //row =
1099 GetPadRowCol(dgT->GetAddressChannel(), colT);
1100 // check column order for cluster
1101 if (col >= 0 && colT != col + 1) {
1102 LOG(error) << GetName() << "::LoadDigis : digis in cluster " << cid << " not in increasing order !";
1103 return 0;
1104 }
1105 col = colT;
1106 colR = -1;
1107 dgR = nullptr;
1108 if (j != din->end()) {
1109 dgR = (*j);
1110 //row =
1111 GetPadRowCol(dgR->GetAddressChannel(), colR);
1112 }
1113 if (colR == colT && dgR != NULL) {
1114 fDigis[cid].push_back(new CbmTrdDigiRec(*dgT, *dgR));
1115 j = din->erase(j);
1116 }
1117 else
1118 fDigis[cid].push_back(new CbmTrdDigiRec(*dgT));
1119
1120 if (j != din->end()) j++;
1121 }
1122 return fDigis[cid].size();
1123}
1124
1125//_______________________________________________________________________________
1126Int_t CbmTrdModuleRec2D::ProjectDigis(Int_t cid, Int_t cjd)
1127{
1133 if (fDigis.find(cid) == fDigis.end()) {
1134 LOG(warn) << GetName() << "::ProjectDigis : Request cl id " << cid << " not found.";
1135 return 0;
1136 }
1137
1138 vs.clear();
1139 vse.clear();
1140 vx.clear();
1141 vxe.clear();
1142 vt.clear();
1143 vt0 = 0;
1144 vrM = 0;
1145 vcM = 0;
1146 vyM = 0;
1147 viM = 0;
1148
1149 Bool_t on(0); // flag signal transmition
1150 Int_t n0(0), nsr(0), // no of signals in the cluster (all/rect)
1151 NR(0), nr(0), // no of rect signals/channel in case of RC
1152 NT(0), nt(0), // no of tilt signals/channel in case of RC
1153 ovf(1); // over-flow flag for at least one of the digis
1154 //dt;
1155 Char_t ddt, // signal time offset wrt prompt
1156 dt0(0); // cluster time offset wrt arbitrary t0
1157 Double_t r, re(100.), // rect signal
1158 t, te(100.), // tilt signal
1159 err, // final error parametrization for signal
1160 xc(-0.5), // running signal-pad position
1161 max(0.); // max signal
1162 Int_t j(0), col(-1), col0(0), col1(0), step(0), row1;
1163
1164 // link second row if needed
1165 vector<CbmTrdDigiRec*>::iterator i1;
1166 if (cjd >= 0) {
1167 if (fDigis.find(cjd) == fDigis.end()) {
1168 LOG(warn) << GetName() << "::ProjectDigis : Request cl id " << cjd << " not found. Skip second row.";
1169 cjd = -1;
1170 }
1171 else
1172 i1 = fDigis[cjd].begin();
1173 }
1174
1175 const CbmTrdDigiRec *dg(nullptr), *dg0(nullptr), *dg1(nullptr);
1176 for (vector<CbmTrdDigiRec*>::iterator i = fDigis[cid].begin(); i != fDigis[cid].end(); i++, j++) {
1177 dg = (*i);
1178 dg0 = nullptr;
1179 dg1 = nullptr;
1180 if (CWRITE(1)) cout << "dg0 :" << dg->ToString();
1181
1182 // initialize
1183 if (col < 0) {
1184 vrM = GetPadRowCol(dg->GetAddressChannel(), col);
1185 vt0 = dg->GetTimeDAQ(); // set arbitrary t0 to avoid double digis loop
1186 }
1187 GetPadRowCol(dg->GetAddressChannel(), col0);
1188 nr = nt = 0;
1189
1190 // read calibrated signals
1191 t = dg->GetTiltCharge(on);
1192 if (on) nt = 1;
1193 r = dg->GetRectCharge(on);
1194 if (on) nr = 1;
1195 // look for matching neighbor digis in case of pad row cross
1196 if (cjd >= 0) {
1197 if ((dg0 = (i1 != fDigis[cjd].end()) ? (*i1) : nullptr)) {
1198 row1 = GetPadRowCol(dg0->GetAddressChannel(), col1);
1199 if (!step) step = vrM - row1;
1200 if (col1 == col0) {
1201 r += dg0->GetRectCharge(on);
1202 if (on) nr++;
1203 }
1204 else
1205 dg0 = nullptr;
1206 }
1207 if (step == 1 && i1 != fDigis[cjd].begin()) {
1208 dg1 = (*(i1 - 1));
1209 GetPadRowCol(dg1->GetAddressChannel(), col1);
1210 if (col1 == col0 - 1) {
1211 t += dg1->GetTiltCharge(on);
1212 if (on) nt++;
1213 }
1214 else
1215 dg1 = nullptr;
1216 }
1217 if (step == -1 && i1 != fDigis[cjd].end() && i1 + 1 != fDigis[cjd].end()) {
1218 dg1 = (*(i1 + 1));
1219 GetPadRowCol(dg1->GetAddressChannel(), col1);
1220 if (col1 == col0 + 1) {
1221 t += dg1->GetTiltCharge(on);
1222 if (on) nt++;
1223 }
1224 else
1225 dg1 = nullptr;
1226 }
1227 if (dg0) i1++;
1228 }
1229 if (CWRITE(1)) {
1230 if (dg0) cout << "dgR :" << dg0->ToString();
1231 if (dg1) cout << "dgT :" << dg1->ToString();
1232 //cout << "-------------------------------------" << endl;
1233 }
1234
1235 // process tilt signal/time
1236 ddt = dg->GetTiltTime() - vt0;
1237 if (ddt < dt0) dt0 = ddt;
1238 if (abs(t) > 0) {
1239 if (nt > 1) t *= 0.5;
1240 err = te * (nt > 1 ? 0.707 : 1);
1241 if (dg->HasTiltOvf()) {
1242 ovf = -1;
1243 err = 150.;
1244 }
1245 if (t > max) {
1246 max = t;
1247 vcM = j;
1248 SetMaxTilt(1);
1249 viM = vs.size();
1250 }
1251 }
1252 else
1253 err = 300.;
1254 vt.push_back(ddt);
1255 vs.push_back(t);
1256 vse.push_back(err);
1257 vx.push_back(xc);
1258 vxe.push_back(0.035);
1259 xc += 0.5;
1260
1261 // process rect signal/time
1262 ddt = dg->GetRectTime() - vt0;
1263 if (ddt < dt0) dt0 = ddt;
1264 if (abs(r) > 0) {
1265 nsr++;
1266 if (nr > 1) r *= 0.5;
1267 err = re * (nr > 1 ? 0.707 : 1);
1268 if (dg->HasRectOvf()) {
1269 ovf = -1;
1270 err = 150.;
1271 }
1272 if (r > max) {
1273 max = r;
1274 vcM = j;
1275 SetMaxTilt(0);
1276 viM = vs.size();
1277 }
1278 }
1279 else
1280 err = 300.;
1281 vt.push_back(ddt);
1282 vs.push_back(r);
1283 vse.push_back(err);
1284 vx.push_back(xc);
1285 vxe.push_back(0.);
1286 xc += 0.5;
1287 NR += nr;
1288 NT += nt;
1289 }
1290
1291 // add front and back anchor points if needed
1292 if (TMath::Abs(vs[0]) > 1.e-3) {
1293 xc = vx[0];
1294 ddt = vt[0];
1295 vs.insert(vs.begin(), 0);
1296 vse.insert(vse.begin(), 300);
1297 vt.insert(vt.begin(), ddt);
1298 vx.insert(vx.begin(), xc - 0.5);
1299 vxe.insert(vxe.begin(), 0);
1300 viM++;
1301 }
1302 Int_t n(vs.size() - 1);
1303 if (TMath::Abs(vs[n]) > 1.e-3) {
1304 xc = vx[n] + 0.5;
1305 ddt = vt[n];
1306 vs.push_back(0);
1307 vse.push_back(300);
1308 vt.push_back(ddt);
1309 vx.push_back(xc);
1310 vxe.push_back(0.035);
1311 }
1312
1313 n0 = vs.size() - 2;
1314 // compute cluster asymmetry
1315 Int_t nR = n0 + 1 - viM;
1316 if (nR == viM) {
1317 SetSymmHit(1);
1318 if (vs.size() % 2) {
1319 Double_t LS(0.), RS(0.);
1320 for (UChar_t idx(0); idx < viM; idx++)
1321 LS += vs[idx];
1322 for (UInt_t idx(viM + 1); idx < vx.size(); idx++)
1323 RS += vs[idx];
1324 SetLeftSgn(LS < RS ? 0 : 1);
1325 }
1326 }
1327 else {
1328 SetSymmHit(0);
1329 if (viM < nR)
1330 SetLeftHit(0);
1331 else if (viM > nR)
1332 SetLeftHit(1);
1333 }
1334 // recenter time and space profile
1335 vt0 += dt0;
1336 for (UInt_t idx(0); idx < vx.size(); idx++) {
1337 vt[idx] -= dt0;
1338 vx[idx] -= vcM;
1339 }
1340 vcM += col;
1341
1342 // check if all signals have same significance
1343 Int_t nmiss = 2 * nsr - NR; //printf("R : nsr[%d] NR[%d] nmiss[%d]\n", nsr, NR, nmiss);
1344 if (cjd >= 0 && nmiss) {
1345 SetBiasX(1);
1346 for (UChar_t idx(1); idx < viM; idx++) {
1347 if (vxe[idx] > 0.) continue; // select rect signals
1348 if (vse[idx] > re * 0.8) SetBiasXleft(1);
1349 }
1350 if (vxe[viM] <= 0. && vse[viM] > re * 0.8) SetBiasXmid(1);
1351 for (UChar_t idx(viM + 1); idx < vs.size() - 1; idx++) {
1352 if (vxe[idx] > 0.) continue; // select rect signals
1353 if (vse[idx] > re * 0.8) SetBiasXright(1);
1354 }
1355 }
1356 else
1357 SetBiasX(0);
1358 nmiss = 2 * n0 - 2 * nsr - NT; //printf("T : n0[%d] nsr[%d] NT[%d] nmiss[%d]\n", n0, nsr, NT, nmiss);
1359 if (cjd >= 0 && nmiss) {
1360 SetBiasY();
1361 for (UChar_t idx(1); idx < viM; idx++) {
1362 if (vxe[idx] > 0. && vse[idx] > te * 0.8) SetBiasYleft(1); // select tilt signals
1363 }
1364 if (vxe[viM] > 0. && vse[viM] > te * 0.8) SetBiasYmid(1);
1365 for (UChar_t idx(viM + 1); idx < vs.size() - 1; idx++) {
1366 if (vxe[idx] > 0. && vse[idx] > te * 0.8) SetBiasYright(1); // select tilt signals
1367 }
1368 }
1369 else
1370 SetBiasY(0);
1371
1372 if (CWRITE(1)) {
1373 printf("t0[clk]=%llu col[%2d] row[%2d] sz[%d] OVF[%c] %c", vt0, vcM, vrM, Int_t(vs.size() - 2),
1374 (ovf < 0 ? 'y' : 'n'), IsOpenLeft() ? '(' : '[');
1375 if (IsSymmHit()) {
1376 if (HasLeftSgn())
1377 printf("<|");
1378 else
1379 printf("|>");
1380 }
1381 else
1382 printf("%s", IsLeftHit() ? "<<" : ">>");
1383 printf("%c bias[%c %c]\n", IsOpenRight() ? ')' : ']', IsBiasX() ? (IsBiasXleft() ? '<' : '>') : 'o',
1384 IsBiasY() ? (IsBiasYleft() ? '<' : '>') : 'o');
1385 for (UInt_t idx(0); idx < vs.size(); idx++) {
1386 printf("%2d dt[%2d] s[ADC]=%6.1f+-%6.1f x[pw]=%5.2f+-%5.2f ", idx, vt[idx], vs[idx], vse[idx], vx[idx], vxe[idx]);
1387 if (idx == viM) printf("[%s]", (IsMaxTilt() ? "//" : "||"));
1388 printf("\n");
1389 }
1390 }
1391
1392 if (ovf < 0) SetOvf(); //printf("SetOvf %d\n", vyM); }
1393 return ovf * (vs.size() - 2);
1394}
1395
1396//_______________________________________________________________________________
1397Int_t CbmTrdModuleRec2D::LoadDigis(vector<const CbmTrdDigi*>* digis, vector<CbmTrdDigi*>* vdgM, vector<Bool_t>* vmask,
1398 ULong64_t& t0, Int_t& cM)
1399{
1407 vs.clear();
1408 vse.clear();
1409 vx.clear();
1410 vxe.clear();
1411 vt.clear();
1412
1413 cM = 0; // relative position of maximum signal
1414 Int_t n0(0), // number of measured signals
1415 ovf(1), // over-flow flag for at least one of the digis
1416 dt;
1417 Char_t ddt, // signal time offset wrt prompt
1418 dt0(0); // cluster time offset wrt arbitrary t0
1419 Double_t r, re(100.), // rect signal
1420 t, te(100.), // tilt signal
1421 err, // final error parametrization for signal
1422 xc(-0.5), // running signal-pad position
1423 max(0.); // max signal
1424 Int_t j(0), col0(-1), col1(0);
1425 const CbmTrdDigi* dg(nullptr);
1426 vector<CbmTrdDigi*>::iterator idgM = vdgM->begin();
1427 for (vector<const CbmTrdDigi*>::iterator i = digis->begin(); i != digis->end(); i++, j++) {
1428 dg = (*i);
1429 if ((*vmask)[j]) {
1430 dg = (*idgM);
1431 idgM++;
1432 }
1433 if (CWRITE(1)) cout << dg->ToString();
1434 r = dg->GetCharge(t, dt);
1435 if (t0 == 0) t0 = dg->GetTimeDAQ(); // set arbitrary t0 to avoid double digis loop
1436 if (col0 < 0) GetPadRowCol(dg->GetAddressChannel(), col0); // initialilze
1437 ddt = dg->GetTimeDAQ() - t0;
1438 if (ddt < dt0) dt0 = ddt;
1439
1440 // check column wise organization
1441 GetPadRowCol(dg->GetAddressChannel(), col1);
1442 if (col0 + j != col1) {
1443 LOG(error) << GetName() << "::LoadDigis : digis in cluster not in increasing order !";
1444 return 0;
1445 }
1446
1447 // process tilt signal
1448 if (t > 0) {
1449 err = te;
1450 if (t > 4094) {
1451 ovf = -1;
1452 err = 150.;
1453 }
1455 n0++;
1456 if (t > max) {
1457 max = t;
1458 cM = j;
1459 }
1460 }
1461 else
1462 err = 300.;
1463 vt.push_back(ddt);
1464 vs.push_back(t);
1465 vse.push_back(err);
1466 vx.push_back(xc);
1467 vxe.push_back(0.035);
1468 xc += 0.5;
1469
1470 // process rect signal
1471 ddt += dt;
1472 if (ddt < dt0) dt0 = ddt;
1473 if (r > 0) {
1474 err = re;
1475 if (r > 4094) {
1476 ovf = -1;
1477 err = 150.;
1478 }
1480 n0++;
1481 if (r > max) {
1482 max = r;
1483 cM = j;
1484 }
1485 }
1486 else
1487 err = 300.;
1488 vt.push_back(ddt);
1489 vs.push_back(r);
1490 vse.push_back(err);
1491 vx.push_back(xc);
1492 vxe.push_back(0.);
1493 xc += 0.5;
1494 }
1495
1496 // remove merged digis if they were created
1497 if (idgM != vdgM->end()) LOG(warn) << GetName() << "::LoadDigis : not all merged digis have been consumed !";
1498 for (idgM = vdgM->begin(); idgM != vdgM->end(); idgM++)
1499 delete (*idgM);
1500
1501 // add front and back anchor points if needed
1502 if (TMath::Abs(vs[0]) > 1.e-3) {
1503 xc = vx[0];
1504 ddt = vt[0];
1505 vs.insert(vs.begin(), 0);
1506 vse.insert(vse.begin(), 300);
1507 vt.insert(vt.begin(), ddt);
1508 vx.insert(vx.begin(), xc - 0.5);
1509 vxe.insert(vxe.begin(), 0);
1510 }
1511 Int_t n(vs.size() - 1);
1512 if (TMath::Abs(vs[n]) > 1.e-3) {
1513 xc = vx[n] + 0.5;
1514 ddt = vt[n];
1515 vs.push_back(0);
1516 vse.push_back(300);
1517 vt.push_back(ddt);
1518 vx.push_back(xc);
1519 vxe.push_back(0.035);
1520 }
1521 // recenter time and space profile
1522 t0 += dt0;
1523 for (UInt_t idx(0); idx < vx.size(); idx++) {
1524 vt[idx] -= dt0;
1525 vx[idx] -= cM;
1526 }
1527 return ovf * n0;
1528}
1529
1530
1531//_______________________________________________________________________________
1532Int_t CbmTrdModuleRec2D::LoadDigisRC(vector<const CbmTrdDigi*>* digis, const Int_t r0, const Int_t a0,
1533 /*vector<CbmTrdDigi*> *vdgM, */ ULong64_t& t0, Int_t& cM)
1534{
1545 vs.clear();
1546 vse.clear();
1547 vx.clear();
1548 vxe.clear();
1549 vt.clear();
1550
1551 cM = 0; // relative position of maximum signal
1552 Int_t step,
1553 n0(0), // number of measured signals
1554 ovf(1), // over-flow flag for at least one of the digis
1555 dt, dT;
1556 Char_t ddt, // signal time offset wrt prompt
1557 dt0(0); // cluster time offset wrt arbitrary t0
1558 Double_t r, R, re(100.), // rect signal
1559 t, T, te(100.), // tilt signal
1560 err, // final error parametrization for signal
1561 xc(0.), // running signal-pad position
1562 max(0.); // max signal
1563 Int_t j(0), row, col, col0(-1), col1(0);
1564 //vector<CbmTrdDigi*>::iterator idgM=vdgM->begin();
1565
1566 vector<const CbmTrdDigi*>::iterator i0, i1, ix0, ix1;
1567 i0 = digis->begin();
1568 i1 = i0;
1569 do {
1570 row = GetPadRowCol((*i1)->GetAddressChannel(), col1);
1571 if (col0 < 0) col0 = col1;
1572 if (row == r0)
1573 i1++;
1574 else
1575 break;
1576 } while (i1 != digis->end());
1577 ix0 = i1;
1578 ix1 = digis->end();
1579 col = col0;
1580 step = -1;
1581 if (a0 > 0) {
1582 i0 = i1;
1583 ix0 = digis->end();
1584 ix1 = i1;
1585 i1 = digis->begin();
1586 col = col0;
1587 col0 = col1;
1588 col1 = col;
1589 col = col0;
1590 step = 1;
1591 }
1592 if (CWRITE(1)) printf("col0[%d] col1[%d] step[%2d]\n", col0, col1, step);
1593 const CbmTrdDigi *dg0(nullptr), *dg1(nullptr), *dg10(nullptr);
1594
1595 // always loop on the largest cluster
1596 for (; i0 != ix0; i0++, j++) {
1597 dg0 = (*i0);
1598 dg1 = nullptr;
1599 dg10 = nullptr;
1600 if (CWRITE(1)) cout << "dg0 :" << dg0->ToString();
1601
1602 r = dg0->GetCharge(t, dt);
1603 if (t > 0) t -= CbmTrdFASP::GetBaselineCorr();
1604 if (r > 0) r -= CbmTrdFASP::GetBaselineCorr();
1605
1606 if (t0 == 0) t0 = dg0->GetTimeDAQ(); // set arbitrary t0 to avoid double digis loop
1607 ddt = dg0->GetTimeDAQ() - t0;
1608 if (ddt < dt0) dt0 = ddt;
1609
1610 // check column wise organization
1611 row = GetPadRowCol(dg0->GetAddressChannel(), col0);
1612 if (col + j != col0) {
1613 LOG(error) << GetName() << "::LoadDigisRC : digis in cluster not in increasing order " << col0 << " !";
1614 return 0;
1615 }
1616
1617 // look for matching neighbor digis
1618 if ((dg1 = (i1 != ix1) ? (*i1) : nullptr)) {
1619 GetPadRowCol(dg1->GetAddressChannel(), col1);
1620 if (col1 == col0) {
1621 R = dg1->GetCharge(T, dT);
1622 if (R > 0.) r += R - CbmTrdFASP::GetBaselineCorr();
1623 }
1624 else
1625 dg1 = nullptr;
1626 }
1627 if (step == 1 && i1 != digis->begin()) {
1628 dg10 = (*(i1 - 1));
1629 GetPadRowCol(dg10->GetAddressChannel(), col1);
1630 if (col1 == col0 - 1) {
1631 dg10->GetCharge(T, dT);
1632 if (T > 0.) t += T - CbmTrdFASP::GetBaselineCorr();
1633 }
1634 else
1635 dg10 = nullptr;
1636 }
1637 if (step == -1 && i1 != ix1 && i1 + 1 != ix1) {
1638 dg10 = (*(i1 + 1));
1639 GetPadRowCol(dg10->GetAddressChannel(), col1);
1640 if (col1 == col0 + 1) {
1641 dg10->GetCharge(T, dT);
1642 if (T > 0.) t += T - CbmTrdFASP::GetBaselineCorr();
1643 }
1644 else
1645 dg10 = nullptr;
1646 }
1647 if (dg1) i1++;
1648
1649 if (CWRITE(1)) {
1650 if (dg1) cout << "dgR :" << dg1->ToString();
1651 if (dg10) cout << "dgT :" << dg10->ToString();
1652 cout << "-------------------------------------" << endl;
1653 }
1654
1655 // process tilt signal
1656 if (t > 0) {
1657 err = te;
1658 n0++;
1659 if (t > max) {
1660 max = t;
1661 cM = j;
1662 }
1663 }
1664 else
1665 err = 300.;
1666 vt.push_back(ddt);
1667 vs.push_back(t);
1668 vse.push_back(err);
1669 vx.push_back(xc);
1670 vxe.push_back(0.035);
1671
1672 // process rect signal
1673 ddt += dt;
1674 if (ddt < dt0) dt0 = ddt;
1675 if (r > 0) {
1676 err = re;
1677 n0++;
1678 if (r > max) {
1679 max = r;
1680 cM = j;
1681 }
1682 }
1683 else
1684 err = 300.;
1685 vt.push_back(ddt);
1686 vs.push_back(r);
1687 vse.push_back(err);
1688 vx.push_back(xc);
1689 vxe.push_back(0.);
1690 xc += 1;
1691 }
1692
1693 // // remove merged digis if they were created
1694 // if(idgM != vdgM->end()) LOG(warn) << GetName() << "::LoadDigis : not all merged digis have been consumed !";
1695 // for(idgM=vdgM->begin(); idgM!=vdgM->end(); idgM++) delete (*idgM);
1696 //
1697 // add front and back anchor points if needed
1698 if (TMath::Abs(vs[0]) > 1.e-3) {
1699 xc = vx[0];
1700 ddt = vt[0];
1701 vs.insert(vs.begin(), 0);
1702 vse.insert(vse.begin(), 300);
1703 vt.insert(vt.begin(), ddt);
1704 vx.insert(vx.begin(), xc - 1);
1705 vxe.insert(vxe.begin(), 0);
1706 }
1707 Int_t n(vs.size() - 1);
1708 if (TMath::Abs(vs[n]) > 1.e-3) {
1709 xc = vx[n] + 1;
1710 ddt = vt[n];
1711 vs.push_back(0);
1712 vse.push_back(300);
1713 vt.push_back(ddt);
1714 vx.push_back(xc);
1715 vxe.push_back(0.035);
1716 }
1717
1718 // recenter time and space profile
1719 if (cM + col >= fDigiPar->GetNofColumns())
1720 cM = fDigiPar->GetNofColumns() - col - 1;
1721 else if (cM + col < 0)
1722 cM = -col;
1723 t0 += dt0;
1724 for (UInt_t idx(0); idx < vx.size(); idx++) {
1725 vt[idx] -= dt0;
1726 vx[idx] -= cM;
1727 }
1728 cM += col;
1729 return ovf * n0;
1730}
1731
1732//_______________________________________________________________________________
1733Bool_t CbmTrdModuleRec2D::MergeDigis(vector<const CbmTrdDigi*>* digis, vector<CbmTrdDigi*>* vdgM, vector<Bool_t>* vmask)
1734{
1735 /* Merge digis in the cluster if their topology within it allows it although cuts in the
1736 * digi merger procedure (CbmTrdFASP::WriteDigi()) were not fulfilled.
1737 * Normally this are boundary signals with large time delays wrt neighbors
1738 */
1739
1740 CbmTrdDigi* dgM(nullptr);
1741 if (digis->size() < 2) { // sanity check ... just in case
1742 LOG(warn) << GetName() << "::MergeDigis : Bad digi config for cluster :";
1743 return kFALSE;
1744 }
1745
1746 Double_t r, t;
1747 Int_t colR, colT, dt, contor(0);
1748 Bool_t kFOUND(0);
1749 for (vector<const CbmTrdDigi*>::iterator idig = digis->begin(), jdig = idig + 1; jdig != digis->end();
1750 idig++, jdig++, contor++) {
1751 const CbmTrdDigi* dgT((*idig)); // tilt signal digi
1752 const CbmTrdDigi* dgR((*jdig)); // rect signal digi
1753 GetPadRowCol(dgR->GetAddressChannel(), colR);
1754 GetPadRowCol(dgT->GetAddressChannel(), colT);
1755
1756 if (colR != colT) continue;
1757
1758 dgM = new CbmTrdDigi(*dgT);
1759 r = dgR->GetCharge(t, dt);
1760 dgT->GetCharge(t, dt);
1761 dt = dgR->GetTimeDAQ() - dgT->GetTimeDAQ();
1762 dgM->SetCharge(t, r, dt);
1763 Int_t rtrg(dgR->GetTriggerType() & 2), ttrg(dgT->GetTriggerType() & 1);
1764 dgM->SetTriggerType(rtrg | ttrg); //merge the triggers
1765 if (CWRITE(1)) {
1766 cout << "MERGE" << endl;
1767 cout << dgT->ToString();
1768 cout << dgR->ToString();
1769 cout << "TO" << endl;
1770 cout << dgM->ToString();
1771 cout << "..." << endl;
1772 }
1773 kFOUND = 1;
1774
1775 vdgM->push_back(dgM);
1776 (*vmask)[contor] = 1;
1777 jdig = digis->erase(jdig);
1778 if (jdig == digis->end()) break;
1779 }
1780
1781 if (!kFOUND) {
1782 LOG(warn) << GetName() << "::MergeDigis : Digi to pads matching failed for cluster :";
1783 return kFALSE;
1784 }
1785 return kTRUE;
1786}
1787
1788Float_t CbmTrdModuleRec2D::fgCorrXdx = 0.01;
1790 {-0.001, -0.001, -0.002, -0.002, -0.003, -0.003, -0.003, -0.004, -0.004, -0.006, -0.006, -0.006, -0.007,
1791 -0.007, -0.008, -0.008, -0.008, -0.009, -0.009, -0.011, -0.011, -0.011, -0.012, -0.012, -0.012, -0.012,
1792 -0.013, -0.013, -0.013, -0.013, -0.014, -0.014, -0.014, -0.014, -0.014, -0.016, -0.016, -0.016, -0.016,
1793 -0.017, -0.017, -0.017, -0.018, -0.018, -0.018, -0.018, -0.018, 0.000, 0.000, 0.000},
1794 {0.467, 0.430, 0.396, 0.364, 0.335, 0.312, 0.291, 0.256, 0.234, 0.219, 0.207, 0.191, 0.172,
1795 0.154, 0.147, 0.134, 0.123, 0.119, 0.109, 0.122, 0.113, 0.104, 0.093, 0.087, 0.079, 0.073,
1796 0.067, 0.063, 0.058, 0.053, 0.049, 0.046, 0.042, 0.038, 0.036, 0.032, 0.029, 0.027, 0.024,
1797 0.022, 0.019, 0.017, 0.014, 0.013, 0.011, 0.009, 0.007, 0.004, 0.003, 0.001},
1798 {0.001, 0.001, 0.001, 0.001, 0.002, 0.002, 0.001, 0.002, 0.004, 0.003, 0.002, 0.002, 0.002,
1799 0.002, 0.002, 0.002, 0.003, 0.004, 0.003, 0.004, 0.004, 0.007, 0.003, 0.004, 0.002, 0.002,
1800 -0.011, -0.011, -0.012, -0.012, -0.012, -0.013, -0.013, -0.013, -0.014, -0.014, -0.014, -0.016, -0.016,
1801 -0.016, -0.017, -0.017, -0.017, -0.018, -0.018, -0.018, -0.019, 0.029, 0.018, 0.001}};
1802Float_t CbmTrdModuleRec2D::fgCorrYval[NBINSCORRY][2] = {{2.421729, 0.},
1803 {0.629389, -0.215285},
1804 {0.23958, 0.},
1805 {0.151913, 0.054404}};
1807 {-0.00050, -0.00050, -0.00150, -0.00250, -0.00250, -0.00350, -0.00450, -0.00450, -0.00550, -0.00650,
1808 -0.00650, -0.00750, -0.00850, -0.00850, -0.00850, -0.00950, -0.00950, -0.00950, -0.01050, -0.01150,
1809 -0.01150, -0.01150, -0.01250, -0.01250, -0.01250, -0.01250, -0.01350, -0.01350, -0.01350, -0.01350,
1810 -0.01450, -0.01450, -0.01450, -0.01550, -0.01550, -0.01550, -0.01550, -0.01650, -0.01650, -0.01550,
1811 -0.01650, -0.01614, -0.01620, -0.01624, -0.01626, -0.01627, -0.01626, -0.01624, -0.01620, -0.01615},
1812 {0.36412, 0.34567, 0.32815, 0.31152, 0.29574, 0.28075, 0.26652, 0.25302, 0.24020, 0.22803, 0.21647, 0.21400, 0.19400,
1813 0.18520, 0.17582, 0.16600, 0.14600, 0.13800, 0.14280, 0.14200, 0.13400, 0.12600, 0.12200, 0.11000, 0.10200, 0.09400,
1814 0.09000, 0.08600, 0.08200, 0.07400, 0.07000, 0.06600, 0.06600, 0.06200, 0.05800, 0.05400, 0.05400, 0.05000, 0.04600,
1815 0.04600, 0.04200, 0.03800, 0.03800, 0.03400, 0.03400, 0.03000, 0.03000, 0.02600, 0.02200, 0.02200}};
1817 {0.00100, 0.00260, 0.00540, 0.00740, 0.00900, 0.01060, 0.01300, 0.01460, 0.01660, 0.01900, 0.02060, 0.02260, 0.02420,
1818 0.02700, 0.02860, 0.02980, 0.03220, 0.03340, 0.03540, 0.03620, 0.03820, 0.04020, 0.04180, 0.04340, 0.04460, 0.04620,
1819 0.04740, 0.04941, 0.05088, 0.05233, 0.05375, 0.05515, 0.05653, 0.05788, 0.05921, 0.06052, 0.06180, 0.06306, 0.06430,
1820 0.06551, 0.06670, 0.06786, 0.06901, 0.07012, 0.07122, 0.07229, 0.07334, 0.07436, 0.07536, 0.07634},
1821 {0.00100, 0.00380, 0.00780, 0.00900, 0.01220, 0.01460, 0.01860, 0.01940, 0.02260, 0.02540, 0.02820, 0.03060, 0.03220,
1822 0.03660, 0.03980, 0.04094, 0.04420, 0.04620, 0.04824, 0.04980, 0.05298, 0.05532, 0.05740, 0.05991, 0.06217, 0.06500,
1823 0.06540, 0.06900, 0.07096, 0.07310, 0.07380, 0.07729, 0.07935, 0.08139, 0.08340, 0.08538, 0.08734, 0.08928, 0.08900,
1824 0.09307, 0.09493, 0.09340, 0.09858, 0.09620, 0.09740, 0.10386, 0.09980, 0.10726, 0.10892, 0.11056},
1825 {0.00011, 0.00140, 0.00340, 0.00420, 0.00500, 0.00620, 0.00820, 0.00860, 0.01060, 0.01100, 0.01220, 0.01340, 0.01500,
1826 0.01540, 0.01700, 0.01820, 0.01900, 0.02060, 0.02180, 0.02260, 0.02340, 0.02420, 0.02500, 0.02500, 0.02660, 0.02740,
1827 0.02820, 0.02900, 0.03020, 0.03180, 0.03300, 0.03260, 0.03380, 0.03460, 0.03500, 0.03580, 0.03780, 0.03820, 0.03860,
1828 0.03900, 0.04100, 0.04180, 0.04060, 0.04300, 0.04340, 0.04340, 0.04380, 0.04460, 0.04580, 0.04540}};
1829
ClassImp(CbmConverterManager)
Data Container for TRD clusters.
Class for hits in TRD detector.
#define NBINSCORRX
#define NANODE
#define NBINSCORRY
#define NBINSCORRX
friend fscal max(fscal x, fscal y)
Generates beam ions for transport simulation.
void SetAddress(int32_t address)
Definition CbmHit.h:83
double GetTime() const
Definition CbmHit.h:76
void SetRefId(int32_t refId)
Definition CbmHit.h:82
int32_t GetRefId() const
Definition CbmHit.h:73
double GetY() const
Definition CbmPixelHit.h:74
double GetX() const
Definition CbmPixelHit.h:73
Data Container for TRD clusters.
bool AddChannel(bool r=true)
Append a channel to cluster edge. The usage is to account for the masked channels....
bool HasFaspDigis() const
virtual std::string ToString() const
Extended functionality.
void SetFaspDigis(bool set=true)
uint16_t GetStartCh() const
uint16_t GetEndCh() const
Extend the TRD(2D) digi class to incorporate FEE calibration.
Double_t GetTiltCharge(Bool_t &on) const
Return calibrated tilt signal.
void SetTriggerType(const eTriggerType triggerType)
Set digi trigger type.
int32_t GetTriggerType() const
Channel trigger type. SPADIC specific see CbmTrdTriggerType.
Definition CbmTrdDigi.h:163
std::string ToString() const
String representation of a TRD digi. Account for digi type and specific information.
uint64_t GetTimeDAQ() const
Getter for global DAQ time [clk]. Differs for each ASIC. In FASP case DAQ time is already stored in f...
Definition CbmTrdDigi.h:158
int32_t GetAddressChannel() const
Getter read-out id.
static float Clk(eCbmTrdAsicType ty)
DAQ clock accessor for each ASIC.
Definition CbmTrdDigi.h:109
eCbmTrdAsicType GetType() const
Channel FEE SPADIC/FASP according to CbmTrdAsicType.
Definition CbmTrdDigi.h:173
double GetCharge() const
Common purpose charge getter.
void SetCharge(float c)
Charge setter for SPADIC ASIC.
static Float_t GetBaselineCorr()
Return the baseline value in ADC ch.
Definition CbmTrdFASP.h:44
data class for a reconstructed Energy-4D measurement in the TRD
Definition CbmTrdHit.h:40
virtual std::string ToString() const
Inherited from CbmBaseHit.
Definition CbmTrdHit.cxx:42
bool IsUsed() const
Definition CbmTrdHit.h:84
virtual Int_t GetNcols() const
Shortcut getter column size.
const CbmTrdParModDigi * fDigiPar
read-out description of module
virtual void LocalToMaster(Double_t in[3], Double_t out[3])
UShort_t fModAddress
unique identifier for current module
CbmTrdParModAsic * fAsicPar
the set of ASIC operating on the module (owned)
virtual Int_t GetPadRowCol(Int_t address, Int_t &c) const
Addressing read-out pads based on module address.
Cluster finding and hit reconstruction algorithms for the TRD(2D) module.
static Float_t fgCorrYval[NBINSCORRY][2]
discretized correction LUT
void SetSymmHit(Bool_t set=1)
void SetBiasYright(Bool_t set=1)
std::vector< Char_t > vt
working copy of signal errors from cluster
Bool_t HasOvf() const
void SetBiasXleft(Bool_t set=1)
Bool_t Deconvolute(CbmTrdHit *h)
Algorithm for cluster spliting.
int fHitTimeOff
bit map for cluster topology classification
Bool_t CWRITE(int level) const
virtual Int_t GetOverThreshold() const
Count RO channels (R or T) with data.
Bool_t MergeHits(CbmTrdHit *h, Int_t a0)
Algorithm for hit merging.
std::map< Int_t, vector< CbmTrdDigiRec * > > fDigis
Bool_t CHELPERS() const
UShort_t vyM
index of maximum signal in the projection
void SetLeftSgn(Bool_t set=1)
std::map< Int_t, std::list< CbmTrdCluster * > > fBuffer
time interval to still keep clusters in buffer [clk]
void SetMaxTilt(Bool_t set=1)
CbmTrdModuleRec2D()
Default constructor.
Bool_t IsOpenRight() const
UChar_t vrM
maximum col
Double_t GetYcorr(Double_t dy, Int_t cls=0) const
y position correction based on LUT
std::vector< Double_t > vxe
working copy of signal relative positions
Bool_t IsBiasY() const
Bool_t IsBiasXmid() const
static Float_t fgCorrXval[3][NBINSCORRX]
step of the discretized correction LUT
std::vector< Double_t > vse
working copy of signals from cluster
ULong64_t fT0
task configuration settings
void SetBiasY(Bool_t set=1)
void SetBiasYmid(Bool_t set=1)
virtual CbmTrdHit * MakeHit(Int_t cId, const CbmTrdCluster *c, std::vector< const CbmTrdDigi * > *digis)
Steering routine for converting cluster to hit.
virtual void DrawHit(CbmTrdHit *) const
void RecenterXoffset(Double_t &dx)
Shift graph representation to [-0.5, 0.5].
Bool_t CheckConvolution(CbmTrdHit *h) const
Implement cuts for hit convolution definition.
Bool_t IsLeftHit() const
Bool_t IsOpenLeft() const
Bool_t HasLeftSgn() const
Bool_t BuildHit(CbmTrdHit *h)
void SetBiasYleft(Bool_t set=1)
std::vector< Double_t > vs
hit time offset for synchronization
UInt_t fTimeLast
start time of event/time slice [clk]
UChar_t vcM
start time of current hit [clk]
static TGraphErrors * fgT
fitter for cluster PRF
UInt_t fTimeWinKeep
time of last digi processed in module [clk]
Int_t LoadDigis(vector< const CbmTrdDigi * > *din, Int_t cid)
Load RAW digis into working array of RECO digis.
Bool_t IsSymmHit() const
void SetBiasX(Bool_t set=1)
Int_t CheckMerge(Int_t cid, Int_t cjd)
Implement topologic cuts for hit merging.
void SetOvf(Bool_t set=1)
Int_t GetHitRcClass(Int_t a0) const
Hit classification wrt signal bias.
virtual Int_t FindClusters(bool clr)
Finalize clusters.
Int_t ProjectDigis(Int_t cid, Int_t cjd=-1)
ULong64_t vt0
cluster-wise organized calibrated digi
static Float_t fgCorrRcXbiasXval[3][NBINSCORRX]
discretized correction LUT
Int_t LoadDigisRC(vector< const CbmTrdDigi * > *digis, const Int_t r0, const Int_t a0, ULong64_t &t0, Int_t &cM)
virtual Bool_t PostProcessHits()
Finalize hits (merge RC hits, etc)
Bool_t IsBiasYleft() const
void RecenterYoffset(Double_t &dy)
Shift graph representation to [-0.5, 0.5].
Double_t GetXcorr(Double_t dx, Int_t typ, Int_t cls=0) const
x position correction based on LUT
static Float_t fgCorrRcXval[2][NBINSCORRX]
discretized correction params
Bool_t IsBiasX() const
Double_t GetYoffset(Int_t n0=0) const
void SetLeftHit(Bool_t set=1)
Bool_t MergeDigis(std::vector< const CbmTrdDigi * > *digis, std::vector< CbmTrdDigi * > *vdgM, std::vector< Bool_t > *vmask)
Merge R/T signals to digis if topological conditions in cluster are fulfilled.
virtual Bool_t AddDigi(const CbmTrdDigi *d, Int_t id)
Add digi to local module.
void SetBiasXmid(Bool_t set=1)
UChar_t viM
maximum row
virtual Bool_t PreProcessHits()
Check hit quality (deconvolute pile-ups, etc)
Bool_t IsBiasXleft() const
static TGraphErrors * fgEdep
FASP delay wrt signal.
Int_t GetHitClass() const
Hit classification wrt center pad.
virtual Bool_t MakeHits()
Steering routine for building hits.
static Float_t fgCorrXdx
working copy of signal relative position errors
void SetBiasXright(Bool_t set=1)
Bool_t IsMaxTilt() const
const CbmTrdParFaspChannel * GetFaspChCalibrator(uint16_t ch) const
Retrive FASP ch calibrator by RO ch number in the module.
Bool_t IsBiasXright() const
std::vector< Double_t > vx
working copy of signal relative timing
int AddClusterEdges(CbmTrdCluster *cl)
Add left and right edge channels to the cluster in case this are masked channels.
static TF1 * fgPRF
data handler for cluster PRF
static Double_t fgDT[3]
discretized correction LUT
Double_t GetXoffset(Int_t n0=0) const
Abstract class for module wise cluster finding and hit reconstruction.
TClonesArray * fHits
module wise storage of reconstructed hits
Definition of FASP channel calibration container.
bool IsMasked() const
void Print(Option_t *opt="") const
Definition of FASP parameters.
const CbmTrdParFaspChannel * GetChannel(Int_t pad_address, UChar_t pair) const
Query the calibration for one FASP RO channel.
virtual Int_t GetAsicAddress(Int_t chAddress) const
Look for the ASIC which operates on a specific channel It applies to the list of ASICs.
virtual const CbmTrdParAsic * GetAsicPar(Int_t address) const
Look for the ASIC parameters of a given DAQ id It applies to the list of ASICs.
bool GetFaspChannelPar(int pad, const CbmTrdParFaspChannel *&tilt, const CbmTrdParFaspChannel *&rect) const
Access the calibration objects describing the two FASP channels allocated to a pad....
Int_t GetSectorRow(Int_t growId, Int_t &srowId) const
Find the sector wise row given the module row. Inverse of GetModuleRow()
void GetPadPosition(const Int_t sector, const Int_t col, const Int_t row, TVector3 &padPos, TVector3 &padPosErr) const
Double_t GetPadSizeY(Int_t i) const
Double_t GetPadSizeX(Int_t i) const
Int_t GetNofColumns() const
#define NFASPCH
#define NFASPMOD