CbmRoot
Loading...
Searching...
No Matches
trd/HitFinder.cxx
Go to the documentation of this file.
1/* Copyright (C) 2024 Facility for Antiproton and Ion Research in Europe, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Dominik Smith [committer], Etienne Bechtel, Florian Uhlig */
4
5#include "HitFinder.h"
6
8#include "CbmTrdDigi.h"
9
10namespace cbm::algo::trd
11{
12 constexpr double HitFinder::kxVar_Value[2][5];
13 constexpr double HitFinder::kyVar_Value[2][5];
14
15 //_______________________________________________________________________________
16 HitFinder::HitFinder(HitFinderModPar params) : fParams(params) {}
17
18 //_______________________________________________________________________________
19 std::vector<trd::HitFinder::resultType> HitFinder::operator()(std::vector<Cluster>* clusters)
20 {
21 const int nclusters = clusters->size();
22 std::vector<resultType> hitData;
23
24 for (int icluster = 0; icluster < nclusters; icluster++) {
25 Cluster* cluster = &clusters->at(icluster);
26 auto hit = MakeHit(icluster, cluster, &cluster->GetDigis(), nclusters);
27 if (hit.Address() == -1) continue;
28 hitData.emplace_back(hit, std::vector<DigiRec>()); //DigiRec currently not used in 1D but in 2D
29 }
30 return hitData;
31 }
32
33 //_______________________________________________________________________________
34 Hit HitFinder::MakeHit(int clusterId, const Cluster* cluster, const std::vector<const CbmTrdDigi*>* digis, size_t)
35 {
36 ROOT::Math::XYZVector hit_posV(0.0, 0.0, 0.0);
37
38 double xVar = 0;
39 double yVar = 0;
40 double totalCharge = 0;
41 double time = 0.;
42 int errorclass = 0.;
43 bool EB = false;
44 bool EBP = false;
45
46 size_t skipped = 0;
47 for (auto& digi : *digis) {
48 if (!digi) {
49 skipped++;
50 continue;
51 L_(debug) << " no digi " << std::endl;
52 }
53
54 const double digiCharge = digi->GetCharge();
55
56 // D.Smith 15.4.24: These get overwritten for each digi. Should be OR?
57 errorclass = digi->GetErrorClass();
58 EB = digi->IsFlagged(0);
59 EBP = digi->IsFlagged(1);
60
61 if (digiCharge <= 0.05) {
62 skipped++;
63 continue;
64 }
65
66 time += digi->GetTime();
67 totalCharge += digiCharge;
68
69 int digiCol;
70 int digiRow = GetPadRowCol(digi->GetAddressChannel(), digiCol);
71
72 const ROOT::Math::XYZVector& local_pad_posV = fParams.rowPar[digiRow].padPar[digiCol].pos;
73 const ROOT::Math::XYZVector& local_pad_dposV = fParams.rowPar[digiRow].padPar[digiCol].pos;
74
75 double xMin = local_pad_posV.X() - local_pad_dposV.X();
76 double xMax = local_pad_posV.X() + local_pad_dposV.X();
77 xVar += (xMax * xMax + xMax * xMin + xMin * xMin) * digiCharge;
78
79 double yMin = local_pad_posV.Y() - local_pad_dposV.Y();
80 double yMax = local_pad_posV.Y() + local_pad_dposV.Y();
81 yVar += (yMax * yMax + yMax * yMin + yMin * yMin) * digiCharge;
82
83 hit_posV.SetX(hit_posV.X() + local_pad_posV.X() * digiCharge);
84 hit_posV.SetY(hit_posV.Y() + local_pad_posV.Y() * digiCharge);
85 hit_posV.SetZ(hit_posV.Z() + local_pad_posV.Z() * digiCharge);
86 }
87 time /= digis->size() - skipped;
88
89 if (totalCharge <= 0) return Hit();
90
91 hit_posV.SetX(hit_posV.X() / totalCharge);
92 hit_posV.SetY(hit_posV.Y() / totalCharge);
93 hit_posV.SetZ(hit_posV.Z() / totalCharge);
94
95 if (EB) {
96 xVar = kxVar_Value[0][errorclass];
97 yVar = kyVar_Value[0][errorclass];
98 }
99 else {
100 if (EBP) time -= 46; //due to the event time of 0 in the EB mode and the ULong in the the digi time
101 //TODO: move to parameter file
102 xVar = kxVar_Value[1][errorclass];
103 yVar = kyVar_Value[1][errorclass];
104 }
105
106 ROOT::Math::XYZVector global = fParams.translation + fParams.rotation(hit_posV);
107
108 // TO DO: REMOVE MAGIC NUMBERS!
109 if (!EB) { // preliminary correction for angle dependence in the position
110 // reconsutrction
111 global.SetX(global.X() + (0.00214788 + global.X() * 0.000195394));
112 global.SetY(global.Y() + (0.00370566 + global.Y() * 0.000213235));
113 }
114
115 ROOT::Math::XYZVector cluster_pad_dposV(xVar, yVar, 0);
116 TransformHitError(cluster_pad_dposV); //Gets overwritten below?
117
118 // TODO: get momentum for more exact spacial error
119 if ((fParams.orientation == 1) || (fParams.orientation == 3)) {
120 cluster_pad_dposV.SetX(sqrt(fParams.padSizeErrY)); // Original version uses padSizeErrY here for some reason
121 //cluster_pad_dposV.SetX( sqrt(fParams.padSizeErrX ) ); // x-component correct?
122 }
123 else {
124 cluster_pad_dposV.SetY(sqrt(fParams.padSizeErrY));
125 }
126
127 // Set charge of incomplete clusters (missing NTs) to -1 (not deleting them because they are still relevant for tracking)
128 if (!IsClusterComplete(cluster)) totalCharge = -1.0;
129
130 return Hit(fParams.address, global, cluster_pad_dposV, 0, clusterId, totalCharge / 1e6, time,
131 double(8.5)); // TODO: move to parameter file
132 }
133
134 void HitFinder::TransformHitError(ROOT::Math::XYZVector& hitErr) const
135 {
136 double x, y;
137 x = hitErr.X();
138 y = hitErr.Y();
139
140 if ((fParams.orientation == 1) || (fParams.orientation == 3)) { // for orientations 1 or 3
141 hitErr.SetX(y); // swap errors
142 hitErr.SetY(x); // swap errors
143 }
144 }
145
146
148 {
149
150 std::pair<double, double> res[12] = {
151 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),
152 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),
153 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)};
154
155 double selval = 0.;
156
157 for (int n = 0; n < 12; n++) {
158 if (val < res[0].first) selval = res[0].second;
159 if (n == 11) {
160 selval = res[11].second;
161 break;
162 }
163 if (val >= res[n].first && val <= res[n + 1].first) {
164 double dx = res[n + 1].first - res[n].first;
165 double dy = res[n + 1].second - res[n].second;
166 double slope = dy / dx;
167 selval = (val - res[n].first) * slope + res[n].second;
168 break;
169 }
170 }
171
172 return selval;
173 }
174
176 {
177 int colMin = fParams.rowPar[0].padPar.size(); //numCols
178 int rowMin = fParams.rowPar.size(); //numRows
179 int colMax = 0;
180 int rowMax = 0;
181
182 for (auto& digi : cluster->GetDigis()) {
183 int digiCol;
184 int digiRow = GetPadRowCol(digi->GetAddressChannel(), digiCol);
185
186 if (digiCol < colMin) colMin = digiCol;
187 if (digiRow < rowMin) rowMin = digiRow;
188 if (digiCol > colMax) colMax = digiCol;
189 if (digiRow > rowMax) rowMax = digiRow;
190 }
191
192 const uint16_t nCols = colMax - colMin + 1;
193 const uint16_t nRows = rowMax - rowMin + 1;
194
195 CbmTrdDigi* digiMap[nRows][nCols]; //create array on stack for optimal performance
196 memset(digiMap, 0, sizeof(CbmTrdDigi*) * nCols * nRows); //init with nullpointers
197
198 for (auto& digi : cluster->GetDigis()) {
199 int digiCol;
200 int digiRow = GetPadRowCol(digi->GetAddressChannel(), digiCol);
201
202 if (digiMap[digiRow - rowMin][digiCol - colMin])
203 return false; // To be investigated why this sometimes happens (Redmin Issue 2914)
204
205 digiMap[digiRow - rowMin][digiCol - colMin] = const_cast<CbmTrdDigi*>(digi);
206 }
207
208 // check if each row of the cluster starts and ends with a kNeighbor digi
209 for (int iRow = 0; iRow < nRows; ++iRow) {
210 int colStart = 0;
211 while (digiMap[iRow][colStart] == nullptr)
212 ++colStart;
213 if (digiMap[iRow][colStart]->GetTriggerType() != static_cast<int>(CbmTrdDigi::eTriggerType::kNeighbor))
214 return false;
215
216 int colStop = nCols - 1;
217 while (digiMap[iRow][colStop] == nullptr)
218 --colStop;
219 if (digiMap[iRow][colStop]->GetTriggerType() != static_cast<int>(CbmTrdDigi::eTriggerType::kNeighbor))
220 return false;
221 }
222
223 return true;
224 }
225
226 int HitFinder::GetPadRowCol(int address, int& c)
227 {
228 c = address % fParams.rowPar[0].padPar.size();
229 return address / fParams.rowPar[0].padPar.size();
230 }
231
232} // namespace cbm::algo::trd
#define L_(level)
friend fvec sqrt(const fvec &a)
bool first
Data container for TRD clusters.
const std::vector< const CbmTrdDigi * > & GetDigis() const
Get array of digi pointers.
int GetPadRowCol(int address, int &c)
Addressing ASIC on module based on id.
static constexpr double kyVar_Value[2][5]
bool IsClusterComplete(const Cluster *cluster)
std::vector< resultType > operator()(std::vector< Cluster > *clusters)
HitFinderModPar fParams
Parameter container.
Hit MakeHit(int cId, const Cluster *c, const std::vector< const CbmTrdDigi * > *digis, size_t)
double GetSpaceResolution(double val=3.0)
static constexpr double kxVar_Value[2][5]
void TransformHitError(ROOT::Math::XYZVector &hitErr) const
A light-weight TRD hit class for online reconstruction, based on CbmTrdHit. .
ROOT::Math::XYZVector translation
ROOT::Math::Rotation3D rotation
std::vector< HitFinderRowPar > rowPar