CbmRoot
Loading...
Searching...
No Matches
CbmTrdModuleRecR.cxx
Go to the documentation of this file.
1/* Copyright (C) 2018-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Etienne Bechtel, Florian Uhlig [committer], Etienne Bechtel */
4
5#include "CbmTrdModuleRecR.h"
6
7#include "CbmDigiManager.h"
8#include "CbmTrdAddress.h"
9#include "CbmTrdCluster.h"
10#include "CbmTrdClusterFinder.h"
11#include "CbmTrdDigi.h"
12#include "CbmTrdHit.h"
13#include "CbmTrdParModDigi.h"
14#include "CbmTrdParSetDigi.h"
15#include "TGeoMatrix.h"
16
17#include <Logger.h>
18
19#include <TCanvas.h>
20#include <TClonesArray.h>
21#include <TH2F.h>
22#include <TImage.h>
23#include <TVector3.h>
24
25#include <iostream>
26
27constexpr Double_t CbmTrdModuleRecR::kxVar_Value[2][5];
28constexpr Double_t CbmTrdModuleRecR::kyVar_Value[2][5];
29
30//_______________________________________________________________________________
31CbmTrdModuleRecR::CbmTrdModuleRecR() : CbmTrdModuleRec(), fDigiCounter(0), fDigiMap(), fClusterMap()
32{
33 SetNameTitle("TrdModuleRecR", "Reconstructor for rectangular pad TRD module");
34}
35
36//_______________________________________________________________________________
37CbmTrdModuleRecR::CbmTrdModuleRecR(Int_t mod, Int_t ly, Int_t rot)
38 : CbmTrdModuleRec(mod, ly, rot)
39 , fDigiCounter(0)
40 , fDigiMap()
41 , fClusterMap()
42{
43 SetNameTitle(Form("TrdModuleRecR%02d", mod), "Reconstructor for rectangular pad TRD module");
44}
45
46//_______________________________________________________________________________
48
49//_______________________________________________________________________________
50Bool_t CbmTrdModuleRecR::AddDigi(const CbmTrdDigi* digi, Int_t id)
51{
52
53 // fill the digimap
54 fDigiMap.push_back(std::make_tuple(id, false, digi));
56 return kTRUE;
57}
58
59//_______________________________________________________________________________
60void CbmTrdModuleRecR::Clear(Option_t* opt)
61{
62 if (strcmp(opt, "cls") == 0) {
63 fDigiMap.erase(fDigiMap.begin(), fDigiMap.end());
64 fClusterMap.erase(fClusterMap.begin(), fClusterMap.end());
65 fDigiCounter = 0;
66 }
68}
69
70//_______________________________________________________________________________
72{
73
74 std::deque<std::tuple<Int_t, Bool_t, const CbmTrdDigi*>>::iterator mainit;
75 // subiterator for the deques in each module; searches for main-trigger to then add the neighbors
76 std::deque<std::tuple<Int_t, Bool_t, const CbmTrdDigi*>>::iterator FNit;
77 // last iterator to find the FN digis which correspond to the main trigger or the adjacent main triggers
78 std::deque<std::tuple<Int_t, Bool_t, const CbmTrdDigi*>>::iterator start;
79 // marker to erase already processed entries from the map to reduce the complexity of the algorithm
80 std::deque<std::tuple<Int_t, Bool_t, const CbmTrdDigi*>>::iterator stop;
81 // marker to erase already processed entries from the map to reduce the complexity of the algorithm
82
83 // reset time information; used to erase processed digis from the map
84 Double_t time = 0;
85 Double_t lasttime = 0;
86 Double_t timediff = -1000;
87
88 Int_t Clustercount = 0;
90 Bool_t print = false;
91
92 // iterator for the main trigger; searches for an unprocessed main triggered
93 // digi and then starts a subloop to directly construct the cluster
94 // while(!fDigiMap.empty()){
95 // std::cout<<fDigiMap.size()<<std::endl;
96 if (print) {
97 std::cout << fDigiMap.size() << std::endl;
98 for (mainit = fDigiMap.begin(); mainit != fDigiMap.end(); mainit++) {
99 const CbmTrdDigi* digi = (const CbmTrdDigi*) std::get<2>(*mainit);
100 Double_t ptime = digi->GetTime();
101 // Int_t digiAddress = digi->GetAddress();
102 Float_t Charge = digi->GetCharge();
103 // Int_t digiId = std::get<0>(*mainit);
104 Int_t channel = digi->GetAddressChannel();
105 Int_t ncols = fDigiPar->GetNofColumns();
106 Int_t triggerId = digi->GetTriggerType();
107
108 std::cout << " module: " << fModAddress << " time: " << ptime << " charge: " << Charge
109 << " col: " << channel % ncols << " row: " << channel / ncols << " trigger: " << triggerId
110 << " ncols: " << ncols << std::endl;
111 }
112 }
113
114 start = fDigiMap.begin();
115 for (mainit = fDigiMap.begin(); mainit != fDigiMap.end(); mainit++) {
116
117 // block to erase processed entries
118 const CbmTrdDigi* digi = (const CbmTrdDigi*) std::get<2>(*mainit);
119 if (!digi) continue;
120
121 time = digi->GetTime();
122 if (lasttime > 0) timediff = time - lasttime;
123 lasttime = time;
124 // if(timediff < -interval) start=mainit;
125 if (timediff > interval && lasttime > 0) {
126 start = mainit;
127 }
128 // if(timediff > interval) {start=mainit;stop=mainit;break;}
129 if (timediff > interval) {
130 fDigiMap.erase(fDigiMap.begin(), stop + 1);
131 start = mainit;
132 stop = mainit;
133 }
134 if (timediff < interval) stop = mainit;
135
136 Int_t triggerId = digi->GetTriggerType();
137 CbmTrdDigi::eTriggerType triggertype = static_cast<CbmTrdDigi::eTriggerType>(triggerId);
138 Bool_t marked = std::get<1>(*mainit);
139 if (triggertype != CbmTrdDigi::eTriggerType::kSelf || marked) continue;
140
141 // variety of neccessary address information; uses the "combiId" for the
142 // comparison of digi positions
143 // Int_t digiAddress = digi->GetAddress();
144 Float_t Charge = digi->GetCharge();
145 Int_t digiId = std::get<0>(*mainit);
146 Int_t channel = digi->GetAddressChannel();
147 Int_t ncols = fDigiPar->GetNofColumns();
148
149 // some logic information which is used to process and find the clusters
150 Int_t lowcol = channel;
151 Int_t highcol = channel;
152 Int_t lowrow = channel;
153 Int_t highrow = channel;
154
155 // counter which is used to easily break clusters which are at the edge and
156 // therefore do not fullfill the classical look
157 Int_t dmain = 1;
158
159 // information buffer to handle neighbor rows and cluster over two rows; the
160 // identification of adjacent rows is done by comparing their center of
161 // gravity
162 Int_t counterrow = 1;
163 Int_t countertop = 0;
164 Int_t counterbot = 0;
165 Double_t buffertop[3] = {0, 0, 0};
166 Double_t bufferbot[3] = {0, 0, 0};
167 Double_t bufferrow[3] = {Charge, 0, 0};
168 // vector<Double_t> buffertop;
169 // vector<Double_t> bufferbot;
170 // vector<Double_t> bufferrow;
171 Double_t CoGtop = 0.;
172 Double_t CoGbot = 0.;
173 Double_t CoGrow = 0.;
174 std::tuple<const CbmTrdDigi*, const CbmTrdDigi*, const CbmTrdDigi*>
175 topdigi; // used to store the necassary digis for the CoG calculation
176 // without the need to revisit those digis
177 std::tuple<const CbmTrdDigi*, const CbmTrdDigi*, const CbmTrdDigi*> botdigi;
178
179 // //some logical flags to reject unnecessary steps
180 Bool_t finished = false; // is turned true either if the implemented trigger
181 // logic is fullfilled or if there are no more
182 // adjacend pads due to edges,etc.
183 Bool_t sealtopcol = false; // the "seal" bools register when the logical end
184 // of the cluster was found
185 Bool_t sealbotcol = false;
186 Bool_t sealtoprow = false;
187 Bool_t sealbotrow = false;
188 Bool_t rowchange = false; // flags that there is a possible two row cluster
189 Bool_t addtop = false; // adds the buffered information of the second row
190 Bool_t addbot = false;
191
192 // //deque which contains the actual cluster
193 std::deque<std::pair<Int_t, const CbmTrdDigi*>> cluster;
194 cluster.push_back(std::make_pair(digiId, digi));
195 if (print)
196 std::cout << " module: " << fModAddress << " time: " << time << " charge: " << Charge
197 << " col: " << channel % ncols << " row: " << channel / ncols << " trigger: " << triggerId
198 << " ncols: " << ncols << std::endl;
199 // std::cout<<" module: " << fModAddress<<" time: " << time<<"
200 // charge: " << Charge<<" col: " << channel % ncols<<" trigger: " <<
201 // triggerId<<" ncols: " << ncols<<std::endl;
202 std::get<1>(*mainit) = true;
203
204 // already seal the cluster if the main trigger is already at the right or left padrow border
205 if (channel % ncols == ncols - 1) {
206 sealtopcol = true;
207 }
208 if (channel % ncols == 0) {
209 sealbotcol = true;
210 }
211
212 // Bool_t mergerow=CbmTrdClusterFinder::HasRowMerger();
213 Bool_t mergerow = true;
214 // loop to find the other pads corresponding to the main trigger
215 while (!finished) {
216 dmain = 0;
217
218 // for (FNit=fDigiMap.begin() ; FNit != fDigiMap.end();FNit++) {
219 for (FNit = start; FNit != fDigiMap.end(); FNit++) {
220
221 // some information to serparate the time space and to skip processed
222 // digis
223 // continue;
224
225 const CbmTrdDigi* d = (const CbmTrdDigi*) std::get<2>(*FNit);
226 Double_t newtime = d->GetTime();
227 Double_t dt = newtime - time;
228 Bool_t filled = std::get<1>(*FNit);
229 if (filled) continue;
230 if (dt < -interval) continue;
231 if (dt > interval) break;
232
233 // position information of the possible neighbor digis
234 Double_t charge = d->GetCharge();
235 // digiAddress = d->GetAddress();
236 Int_t digiid = std::get<0>(*FNit);
237 Int_t ch = d->GetAddressChannel();
238 Int_t col = ch % ncols;
239 Int_t trigger = d->GetTriggerType();
240 triggertype = static_cast<CbmTrdDigi::eTriggerType>(trigger);
241
242 if (mergerow) {
243 // multiple row processing
244 // first buffering
245
246 if (ch == channel - ncols && !rowchange && triggertype == CbmTrdDigi::eTriggerType::kSelf
247 && !std::get<1>(*FNit)) {
248 rowchange = true;
249 bufferbot[0] = charge;
250 counterbot++;
251 std::get<0>(botdigi) = d;
252 }
253 if (ch == (channel - ncols) - 1 && rowchange && !std::get<1>(*FNit) && !sealbotcol) {
254 bufferbot[1] = charge;
255 counterbot++;
256 std::get<1>(botdigi) = d;
257 }
258 if (ch == (channel - ncols) + 1 && rowchange && !std::get<1>(*FNit) && !sealtopcol) {
259 bufferbot[2] = charge;
260 counterbot++;
261 std::get<2>(botdigi) = d;
262 }
263 if (ch == channel + ncols && !rowchange && triggertype == CbmTrdDigi::eTriggerType::kSelf
264 && !std::get<1>(*FNit)) {
265 rowchange = true;
266 buffertop[0] = charge;
267 countertop++;
268 std::get<0>(topdigi) = d;
269 }
270 if (ch == (channel + ncols) - 1 && rowchange && !std::get<1>(*FNit) && !sealbotcol) {
271 buffertop[1] = charge;
272 countertop++;
273 std::get<1>(topdigi) = d;
274 }
275 if (ch == (channel + ncols) + 1 && rowchange && !std::get<1>(*FNit) && !sealtopcol) {
276 buffertop[2] = charge;
277 countertop++;
278 std::get<2>(topdigi) = d;
279 }
280
281 if (ch == channel - 1 && !sealbotcol) {
282 bufferrow[1] = charge;
283 counterrow++;
284 std::get<1>(topdigi) = d;
285 }
286 if (ch == channel + 1 && !sealtopcol) {
287 bufferrow[2] = charge;
288 counterrow++;
289 std::get<2>(topdigi) = d;
290 }
291
292 // then the calculation of the center of gravity with the
293 // identification of common CoGs
294 if (countertop == 3) {
295 CoGtop = (buffertop[2] / buffertop[0]) - (buffertop[1] / buffertop[0]);
296 }
297 if (counterbot == 3) {
298 CoGbot = (bufferbot[2] / bufferbot[0]) - (bufferbot[1] / bufferbot[0]);
299 }
300 if (counterrow == 3) {
301 CoGrow = (bufferrow[2] / bufferrow[0]) - (bufferrow[1] / bufferrow[0]);
302 }
303 if (countertop == 3 && counterrow == 3 && !addtop && TMath::Abs((CoGtop - CoGrow)) < 0.25 * CoGrow) {
304 addtop = true;
305 }
306 if (counterbot == 3 && counterrow == 3 && !addbot && TMath::Abs((CoGbot - CoGrow)) < 0.25 * CoGrow) {
307 addbot = true;
308 }
309 }
310
311 // logical implementation of the trigger logic in the same row as the
312 // main trigger
313 if (ch == lowcol - 1 && triggertype == CbmTrdDigi::eTriggerType::kSelf && !std::get<1>(*FNit) && !sealbotcol) {
314 cluster.push_back(std::make_pair(digiid, d));
315 lowcol = ch;
316 dmain++;
317 std::get<1>(*FNit) = true;
318 if (print)
319 std::cout << " time: " << newtime << " charge: " << charge << " col: " << col << " row: " << ch / ncols
320 << " trigger: " << trigger << std::endl;
321 }
322 if (ch == highcol + 1 && triggertype == CbmTrdDigi::eTriggerType::kSelf && !std::get<1>(*FNit) && !sealtopcol) {
323 cluster.push_back(std::make_pair(digiid, d));
324 highcol = ch;
325 dmain++;
326 std::get<1>(*FNit) = true;
327 if (print)
328 std::cout << " time: " << newtime << " charge: " << charge << " col: " << col << " row: " << ch / ncols
329 << " trigger: " << trigger << std::endl;
330 }
331 if (ch == highcol + 1 && triggertype == CbmTrdDigi::eTriggerType::kNeighbor && !std::get<1>(*FNit)
332 && !sealtopcol) {
333 cluster.push_back(std::make_pair(digiid, d));
334 sealtopcol = true;
335 dmain++;
336 std::get<1>(*FNit) = true;
337 if (print)
338 std::cout << " time: " << newtime << " charge: " << charge << " col: " << col << " row: " << ch / ncols
339 << " trigger: " << trigger << std::endl;
340 }
341 if (ch == lowcol - 1 && triggertype == CbmTrdDigi::eTriggerType::kNeighbor && !std::get<1>(*FNit)
342 && !sealbotcol) {
343 cluster.push_back(std::make_pair(digiid, d));
344 sealbotcol = true;
345 dmain++;
346 std::get<1>(*FNit) = true;
347 if (print)
348 std::cout << " time: " << newtime << " charge: " << charge << " col: " << col << " row: " << ch / ncols
349 << " trigger: " << trigger << std::endl;
350 }
351 if (col == ncols - 1) {
352 sealtopcol = true;
353 }
354 if (col == 0) {
355 sealbotcol = true;
356 }
357
358 if (mergerow) {
359 // adding of the neighboring row
360 if (ch == channel - ncols && addbot && !std::get<1>(*FNit)) {
361 cluster.push_back(std::make_pair(digiid, d));
362 lowrow = ch;
363 highrow = ch;
364 dmain++;
365 std::get<1>(*FNit) = true;
366 }
367 if (ch == channel + ncols && addtop && !std::get<1>(*FNit)) {
368 cluster.push_back(std::make_pair(digiid, d));
369 lowrow = ch;
370 highrow = ch;
371 dmain++;
372 std::get<1>(*FNit) = true;
373 }
374 /* apuntke, Mar 19 2024: I think it is possible that simultaneously the above and below rows get added in
375 this code and this is not taken into account in the following 4 blocks, since the two variables indicating
376 if the cluster is sealed on the sides in the added row (sealtoprow & sealbotrow) are simultaneously used
377 for both cases (top row merged (addtop==true) and bottom row merged (addbot==true)).
378 This needs to be investigated further.
379 */
380 if (rowchange && ch == lowrow - 1 && lowrow != channel && triggertype == CbmTrdDigi::eTriggerType::kSelf
381 && !std::get<1>(*FNit) && !sealbotrow) {
382 cluster.push_back(std::make_pair(digiid, d));
383 lowrow = ch;
384 dmain++;
385 std::get<1>(*FNit) = true;
386 if (lowrow % ncols == 0) sealbotrow = true;
387 }
388 if (rowchange && ch == highrow + 1 && highrow != channel && triggertype == CbmTrdDigi::eTriggerType::kSelf
389 && !std::get<1>(*FNit) && !sealtoprow) {
390 cluster.push_back(std::make_pair(digiid, d));
391 highrow = ch;
392 dmain++;
393 std::get<1>(*FNit) = true;
394 if (highrow % ncols == ncols - 1) sealtoprow = true;
395 }
396 if (rowchange && ch == highrow + 1 && highrow != channel && triggertype == CbmTrdDigi::eTriggerType::kNeighbor
397 && !std::get<1>(*FNit) && !sealtoprow) {
398 cluster.push_back(std::make_pair(digiid, d));
399 sealtoprow = true;
400 dmain++;
401 std::get<1>(*FNit) = true;
402 }
403 if (rowchange && ch == lowrow - 1 && lowrow != channel && triggertype == CbmTrdDigi::eTriggerType::kNeighbor
404 && !std::get<1>(*FNit) && !sealbotrow) {
405 cluster.push_back(std::make_pair(digiid, d));
406 sealbotrow = true;
407 dmain++;
408 std::get<1>(*FNit) = true;
409 }
410 }
411 }
412
413 // some finish criteria
414 if (((sealbotcol && sealtopcol) && !rowchange) || dmain == 0) finished = true;
415 if ((sealbotcol && sealtopcol && sealtoprow && sealbotrow) || dmain == 0) finished = true;
416 // finished=true;
417 if (print) std::cout << dmain << std::endl;
418 } // end of cluster completion
419 if (print) std::cout << dmain << std::endl;
420 if (print) std::cout << std::endl;
421 // fClusterMap.push_back(cluster);
422 Clustercount++;
423 addClusters(cluster);
424 } // end of main trigger loop
425 // fDigiMap.erase(fDigiMap.begin(),fDigiMap.end());
426 // }
427
428 // Int_t checkcount=0;
429 // for (mainit=fDigiMap.begin() ; mainit != fDigiMap.end(); mainit++) {
430 // if(!std::get<1>(*mainit)) checkcount++;
431 // }
432 // std:cout<< checkcount<<" " << fDigiMap.size()<<std::endl;
433
434 return Clustercount;
435}
436
437//_____________________________________________________________________
438void CbmTrdModuleRecR::addClusters(std::deque<std::pair<Int_t, const CbmTrdDigi*>> cluster)
439{
440 // create vector for indice matching
441 std::vector<Int_t> digiIndices(cluster.size());
442 Int_t idigi = 0;
443
445
446 for (std::deque<std::pair<Int_t, const CbmTrdDigi*>>::iterator iDigi = cluster.begin(); iDigi != cluster.end();
447 iDigi++) {
448 // add digi id to vector
449 digiIndices[idigi] = iDigi->first;
450 idigi++;
451 }
452
453 // add the clusters to the Array
454 // const CbmDigi* digi = static_cast<const
455 // CbmDigi*>(fDigis->At(digiIndices.front()));
456 Int_t size = fClusters->GetEntriesFast();
457 CbmTrdCluster* newcluster = new ((*fClusters)[size]) CbmTrdCluster();
458
459 // std::cout<<idigi<<std::endl;
460 newcluster->SetAddress(fModAddress);
461 newcluster->SetDigis(digiIndices);
462 newcluster->SetNCols(idigi);
463
464 // BuildChannelMap(cluster);
465}
466
467//_______________________________________________________________________________
468Bool_t CbmTrdModuleRecR::MakeHits() { return kTRUE; }
469
470//_______________________________________________________________________________
471CbmTrdHit* CbmTrdModuleRecR::MakeHit(Int_t clusterId, const CbmTrdCluster* cluster,
472 std::vector<const CbmTrdDigi*>* digis)
473{
474
475 TVector3 hit_posV;
476 TVector3 local_pad_posV;
477 TVector3 local_pad_dposV;
478 for (Int_t iDim = 0; iDim < 3; iDim++) {
479 hit_posV[iDim] = 0.0;
480 local_pad_posV[iDim] = 0.0;
481 local_pad_dposV[iDim] = 0.0;
482 }
483
484 Double_t xVar = 0;
485 Double_t yVar = 0;
486 Double_t totalCharge = 0;
487 // Double_t totalChargeTR = 0;
488 // Double_t momentum = 0.;
489 // Int_t moduleAddress = 0;
490 Double_t time = 0.;
491 Int_t errorclass = 0.;
492 Bool_t EB = false;
493 Bool_t EBP = false;
494 for (std::vector<const CbmTrdDigi*>::iterator id = digis->begin(); id != digis->end(); id++) {
495 const CbmTrdDigi* digi = (*id);
496 if (!digi) {
497 continue;
498 std::cout << " no digi " << std::endl;
499 }
500
501 Double_t digiCharge = digi->GetCharge();
502 errorclass = digi->GetErrorClass();
503 EB = digi->IsFlagged(0);
504 EBP = digi->IsFlagged(1);
505
506 // if (digiCharge <= 0) {std::cout<<" charge 0 " <<
507 // std::endl;continue;}
508 if (digiCharge <= 0.05) {
509 continue;
510 }
511
512 time += digi->GetTime();
513 // time += digi->GetTimeDAQ();
514
515 totalCharge += digi->GetCharge();
516
517 fDigiPar->GetPadPosition(digi->GetAddressChannel(), true, local_pad_posV, local_pad_dposV);
518
519 Double_t xMin = local_pad_posV[0] - local_pad_dposV[0];
520 Double_t xMax = local_pad_posV[0] + local_pad_dposV[0];
521 xVar += (xMax * xMax + xMax * xMin + xMin * xMin) * digiCharge;
522
523 Double_t yMin = local_pad_posV[1] - local_pad_dposV[1];
524 Double_t yMax = local_pad_posV[1] + local_pad_dposV[1];
525 yVar += (yMax * yMax + yMax * yMin + yMin * yMin) * digiCharge;
526
527 for (Int_t iDim = 0; iDim < 3; iDim++) {
528 hit_posV[iDim] += local_pad_posV[iDim] * digiCharge;
529 }
530 }
531 time /= digis->size();
532
533 if (totalCharge <= 0) return NULL;
534
535 Double_t hit_pos[3];
536 for (Int_t iDim = 0; iDim < 3; iDim++) {
537 hit_posV[iDim] /= totalCharge;
538 hit_pos[iDim] = hit_posV[iDim];
539 }
540
541 if (EB) {
542 xVar = kxVar_Value[0][errorclass];
543 yVar = kyVar_Value[0][errorclass];
544 }
545 else {
546 if (EBP) time -= 46; //due to the event time of 0 in the EB mode and the ULong in the the digi time
547 //TODO: move to parameter file
548 xVar = kxVar_Value[1][errorclass];
549 yVar = kyVar_Value[1][errorclass];
550 }
551
552 TVector3 cluster_pad_dposV(xVar, yVar, 0);
553
554 // --- If a TGeoNode is attached, transform into global coordinate system
555 Double_t global[3];
556 LocalToMaster(hit_pos, global);
557
558 if (!EB) { // preliminary correction for angle dependence in the position
559 // reconsutrction
560 global[0] = global[0] + (0.00214788 + global[0] * 0.000195394);
561 global[1] = global[1] + (0.00370566 + global[1] * 0.000213235);
562 }
563
564 fDigiPar->TransformHitError(cluster_pad_dposV);
565
566 // TODO: get momentum for more exact spacial error
567 if ((fDigiPar->GetOrientation() == 1) || (fDigiPar->GetOrientation() == 3)) {
568 cluster_pad_dposV[0] = sqrt(fDigiPar->GetPadSizeY(1));
569 }
570 else {
571 cluster_pad_dposV[1] = sqrt(fDigiPar->GetPadSizeY(1));
572 }
573
574 // Set charge of incomplete clusters (missing NTs) to -1 (not deleting them because they are still relevant for tracking)
575 if (!IsClusterComplete(cluster)) totalCharge = -1.0;
576
577 Int_t nofHits = fHits->GetEntriesFast();
578
579 // return new ((*fHits)[nofHits]) CbmTrdHit(fModAddress, global,
580 // cluster_pad_dposV, 0, clusterId,0, 0,
581 // totalCharge/1e6,time,Double_t(CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kSPADIC)));
582 return new ((*fHits)[nofHits])
583 CbmTrdHit(fModAddress, global, cluster_pad_dposV, 0, clusterId, totalCharge / 1e6, time,
584 Double_t(8.5)); // TODO: move to parameter file
585}
586
588{
589
590 std::pair<Double_t, Double_t> res[12] = {
591 std::make_pair(0.5, 0.4), std::make_pair(1, 0.35), std::make_pair(2, 0.3), std::make_pair(2.5, 0.3),
592 std::make_pair(3.5, 0.28), std::make_pair(4.5, 0.26), std::make_pair(5.5, 0.26), std::make_pair(6.5, 0.26),
593 std::make_pair(7.5, 0.26), std::make_pair(8.5, 0.26), std::make_pair(8.5, 0.26), std::make_pair(9.5, 0.26)};
594
595 Double_t selval = 0.;
596
597 for (Int_t n = 0; n < 12; n++) {
598 if (val < res[0].first) selval = res[0].second;
599 if (n == 11) {
600 selval = res[11].second;
601 break;
602 }
603 if (val >= res[n].first && val <= res[n + 1].first) {
604 Double_t dx = res[n + 1].first - res[n].first;
605 Double_t dy = res[n + 1].second - res[n].second;
606 Double_t slope = dy / dx;
607 selval = (val - res[n].first) * slope + res[n].second;
608 break;
609 }
610 }
611
612 return selval;
613}
614
616{
617 int colMin = fDigiPar->GetNofColumns();
618 int rowMin = fDigiPar->GetNofRows();
619 int colMax = 0;
620 int rowMax = 0;
621
622 for (int i = 0; i < cluster->GetNofDigis(); ++i) {
623 const CbmTrdDigi* digi = CbmDigiManager::Instance()->Get<CbmTrdDigi>(cluster->GetDigi(i));
624 int digiCol = fDigiPar->GetPadColumn(digi->GetAddressChannel());
625 int digiRow = fDigiPar->GetPadRow(digi->GetAddressChannel());
626
627 if (digiCol < colMin) colMin = digiCol;
628 if (digiRow < rowMin) rowMin = digiRow;
629 if (digiCol > colMax) colMax = digiCol;
630 if (digiRow > rowMax) rowMax = digiRow;
631 }
632
633 const UShort_t nCols = colMax - colMin + 1;
634 const UShort_t nRows = rowMax - rowMin + 1;
635
636 CbmTrdDigi* digiMap[nRows][nCols]; //create array on stack for optimal performance
637 memset(digiMap, 0, sizeof(CbmTrdDigi*) * nCols * nRows); //init with nullpointers
638
639 for (int i = 0; i < cluster->GetNofDigis(); ++i) {
640 const CbmTrdDigi* digi = CbmDigiManager::Instance()->Get<CbmTrdDigi>(cluster->GetDigi(i));
641 int digiCol = fDigiPar->GetPadColumn(digi->GetAddressChannel());
642 int digiRow = fDigiPar->GetPadRow(digi->GetAddressChannel());
643
644 if (digiMap[digiRow - rowMin][digiCol - colMin])
645 return false; // To be investigated why this sometimes happens (Redmin Issue 2914)
646
647 digiMap[digiRow - rowMin][digiCol - colMin] = const_cast<CbmTrdDigi*>(digi);
648 }
649
650 // check if each row of the cluster starts and ends with a kNeighbor digi
651 for (int iRow = 0; iRow < nRows; ++iRow) {
652 int colStart = 0;
653 while (digiMap[iRow][colStart] == nullptr)
654 ++colStart;
655 if (digiMap[iRow][colStart]->GetTriggerType() != static_cast<Int_t>(CbmTrdDigi::eTriggerType::kNeighbor))
656 return false;
657
658 int colStop = nCols - 1;
659 while (digiMap[iRow][colStop] == nullptr)
660 --colStop;
661 if (digiMap[iRow][colStop]->GetTriggerType() != static_cast<Int_t>(CbmTrdDigi::eTriggerType::kNeighbor))
662 return false;
663 }
664
665 return true;
666}
667
ClassImp(CbmConverterManager)
Helper class to convert unique channel ID back and forth.
FairTask to produce TrdCluster objects from TrdHit objects.
Data Container for TRD clusters.
Class for hits in TRD detector.
friend fvec sqrt(const fvec &a)
static constexpr size_t size()
Definition KfSimdPseudo.h:2
bool first
void SetDigis(const std::vector< int32_t > &indices)
Set array of digi to cluster. Overwrites existing array.
Definition CbmCluster.h:63
void SetAddress(int32_t address)
Definition CbmCluster.h:94
int32_t GetDigi(int32_t index) const
Get digi at position index.
Definition CbmCluster.h:76
int32_t GetNofDigis() const
Number of digis in cluster.
Definition CbmCluster.h:69
InitStatus Init()
Initialisation.
const Digi * Get(Int_t index) const
Get a digi object.
static CbmDigiManager * Instance()
Static instance.
Data Container for TRD clusters.
void SetNCols(uint16_t ncols)
int32_t GetTriggerType() const
Channel trigger type. SPADIC specific see CbmTrdTriggerType.
Definition CbmTrdDigi.h:163
int32_t GetAddressChannel() const
Getter read-out id.
bool IsFlagged(const int32_t iflag) const
Query flag status (generic)
static float Clk(eCbmTrdAsicType ty)
DAQ clock accessor for each ASIC.
Definition CbmTrdDigi.h:109
int32_t GetErrorClass() const
Channel status. SPADIC specific see LUT.
Definition CbmTrdDigi.h:133
double GetTime() const
Getter for physical time [ns]. Accounts for clock representation of each ASIC. In SPADIC case physica...
Definition CbmTrdDigi.h:153
double GetCharge() const
Common purpose charge getter.
data class for a reconstructed Energy-4D measurement in the TRD
Definition CbmTrdHit.h:40
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
Rectangular pad module; Cluster finding and hit reconstruction algorithms.
static constexpr Double_t kxVar_Value[2][5]
virtual Bool_t AddDigi(const CbmTrdDigi *d, Int_t id)
Add digi to local module.
std::deque< std::tuple< Int_t, Bool_t, const CbmTrdDigi * > > fDigiMap
static constexpr Double_t kyVar_Value[2][5]
CbmTrdModuleRecR()
Default constructor.
bool IsClusterComplete(const CbmTrdCluster *cluster)
virtual Int_t FindClusters(bool clr=true)
Steering routine for finding digits clusters.
Double_t GetSpaceResolution(Double_t val=3.0)
void addClusters(std::deque< std::pair< Int_t, const CbmTrdDigi * > > cluster)
virtual CbmTrdHit * MakeHit(Int_t cId, const CbmTrdCluster *c, std::vector< const CbmTrdDigi * > *digis)
Steering routine for converting cluster to hit.
std::deque< std::deque< std::pair< Int_t, const CbmTrdDigi * > > > fClusterMap
virtual Bool_t MakeHits()
Steering routine for building hits.
virtual void Clear(Option_t *opt="")
Clear local storage.
Abstract class for module wise cluster finding and hit reconstruction.
virtual void Clear(Option_t *opt="")
Clear local storage.
TClonesArray * fClusters
module wise storage of reconstructed cluster
TClonesArray * fHits
module wise storage of reconstructed hits
Int_t GetPadRow(const Int_t channelNumber) const
void TransformHitError(TVector3 &hitErr) const
Int_t GetOrientation() const
Int_t GetNofRows() const
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
Int_t GetPadColumn(const Int_t channelNumber) const
Int_t GetNofColumns() const