CbmRoot
Loading...
Searching...
No Matches
HitFinder2D.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], Alexandru Bercuci */
4
5#include "HitFinder2D.h"
6
8
9#include <numeric>
10
11using std::endl;
12using std::vector;
13
14namespace cbm::algo::trd
15{
16
18 double HitFinder2D::fgDT[] = {4.181e-6, 1586, 24};
19
20 //_______________________________________________________________________________
21 HitFinder2D::HitFinder2D(HitFinder2DModPar params) : fParams(params) {}
22
23 //_______________________________________________________________________________
24 std::vector<trd::HitFinder2D::resultType> HitFinder2D::operator()(std::vector<Cluster2D>* clusters)
25 {
26 const int nclusters = clusters->size();
27 std::vector<resultType> hitData;
28
29 for (int icluster = 0; icluster < nclusters; icluster++) {
30 auto& cluster = clusters->at(icluster);
31 auto hit = MakeHit(icluster, &cluster);
32 if (hit.Address() == -1) continue;
33 hitData.emplace_back(hit, cluster.GetRecDigis());
34 }
35 return hitData;
36 }
37
38 //_______________________________________________________________________________
39 Hit HitFinder2D::MakeHit(int ic, const Cluster2D* cluster)
40 {
41 Hit hit;
42 if (cluster->GetRecDigis().size() == 0) return hit;
43
44 auto [hitFlag, hitF] = ProjectDigis(cluster);
45 if (!hitFlag) return hit;
46
48 hit.SetRefId(ic);
49 BuildHit(&hit, hitF);
50 return hit;
51 }
52
53
54 //_______________________________________________________________________________
56 {
57 const int n0 = hitF.fSignal.size() - 2;
58 auto [dx, dy] = hitF.GetDxDy(n0);
59
60 // get position correction
61 const double xcorr = hitF.GetXcorr(dx, hitF.GetHitClass()) / fParams.padSizeX;
62 std::tie(dx, dy) = hitF.CorrectPosition(dx, dy, xcorr, fParams.padSizeX, fParams.padSizeY);
63
64 // get anode wire offset
65 for (int ia = 0; ia <= NANODE; ia++) {
66 const float ya = -1.35 + ia * 0.3; //anode position in local pad coordinates
67 if (dy > ya + 0.15) continue;
68 break;
69 }
70
71 // Error parametrization X : parabolic model on cl size
72 const double parX[] = {0.713724, -0.318667, 0.0366036};
73 const double parY[] = {0.0886413, 0., 0.0435141};
74 const int nex = std::min(n0, 7);
75 const double edx = (n0 < 3) ? 1. : parX[0] + parX[1] * nex + parX[2] * nex * nex;
76 const double edy = (n0 < 3) ? 1. : parY[0] + parY[2] * dy * dy;
77 const double edt = (n0 < 3) ? 60. : 26.33; // should be parametrized as function of da TODO
78
79 // COMPUTE TIME
80 double t_avg = 0.;
81 for (int idx = 1; idx <= n0; idx++) {
82 HitFactory2D::signal& sig = hitF.fSignal[idx];
83 const double dtFEE = fgDT[0] * (sig.s - fgDT[1]) * (sig.s - fgDT[1]) / fClk;
84 t_avg += (sig.t - dtFEE);
85 if (sig.xe > 0) sig.x += dy / fParams.padSizeY;
86 }
87
88 const double time = (n0 > 1) ? t_avg / n0 : -21.;
89 const double tdrift = 100.; // should depend on Ua
90
91 // COMPUTE ENERGY (conversion to GeV)
92 const double e_avg = 1.e-9
93 * std::accumulate(hitF.fSignal.begin(), hitF.fSignal.end(), 0,
94 [](int sum, const auto& sig) { return sum + sig.s; });
95
96 CalibrateHit(h, dx, dy, edx, edy, edt, time, tdrift, e_avg, hitF);
97 return kTRUE;
98 }
99
100 //_______________________________________________________________________________
101 void HitFinder2D::CalibrateHit(Hit* h, const double dx, const double dy, const double edx, const double edy,
102 const double edt, const double time, const double tdrift, const double eloss,
103 const HitFactory2D& hitF)
104 {
105 const ROOT::Math::XYZVector& local_pad = fParams.rowPar[hitF.vrM].padPar[hitF.vcM].pos;
106 const ROOT::Math::XYZVector local(local_pad.X() + dx, local_pad.Y() + dy, local_pad.Z());
107 const ROOT::Math::XYZVector global = fParams.translation + fParams.rotation(local);
108 h->SetX(global.X());
109 h->SetY(global.Y());
110 h->SetZ(global.Z());
111 h->SetDx(edx);
112 h->SetDy(edy);
113 h->SetDz(0.);
114 h->SetDxy(0.);
115 h->SetTime(fClk * (hitF.vt0 + time) - tdrift + 30.29 + fHitTimeOff, edt);
116 h->SetELoss(eloss);
117 h->SetClassType();
118 h->SetMaxType(hitF.IsMaxTilt());
119 h->SetOverFlow(hitF.HasOvf());
120 }
121
122 //_______________________________________________________________________________
123 std::pair<int, HitFactory2D> HitFinder2D::ProjectDigis(const Cluster2D* cluster)
124 {
130 if (cluster->GetRecDigis().empty()) {
131 L_(debug) << "TrdModuleRec2D::ProjectDigis : Requested cluster not found.";
132 return std::make_pair(0, HitFactory2D(0));
133 }
134 HitFactory2D hitF(fParams.rowPar[0].padPar.size());
135
136 std::vector<HitFactory2D::signal>& hitSig = hitF.fSignal;
137 hitF.reset();
138
139 bool on(0); // flag signal transmition
140 int n0(0), nsr(0), // no of signals in the cluster (all/rect)
141 NR(0), // no of rect signals/channel in case of RC
142 NT(0), // no of tilt signals/channel in case of RC
143 ovf(1); // over-flow flag for at least one of the digis
144 Char_t dt0(0); // cluster time offset wrt arbitrary t0
145 double err, // final error parametrization for signal
146 xc(-0.5), // running signal-pad position
147 max(0.); // max signal
148 const double re = 100.; // rect signal
149 const double te = 100.; // tilt signal
150
151 int j(0), col(-1), col0(0);
152
153 for (auto i = cluster->GetRecDigis().begin(); i != cluster->GetRecDigis().end(); i++, j++) {
154 const DigiRec* dg = &(*i);
155
156 // initialize
157 if (col < 0) {
158 hitF.vrM = GetPadRowCol(dg->GetAddressChannel(), col);
159 hitF.vt0 = dg->GetTimeDAQ(); // set arbitrary t0 to avoid double digis loop
160 }
161 GetPadRowCol(dg->GetAddressChannel(), col0);
162 int nt = 0; // no of tilt signals/channel in case of RC
163 int nr = 0; // no of rect signals/channel in case of RC
164
165 // read calibrated signals
166 double t = dg->GetTiltCharge(on);
167 if (on) nt = 1;
168 double r = dg->GetRectCharge(on);
169 if (on) nr = 1;
170
171 //TO DO: two blocks below might be mergable
172 // process tilt signal/time
173 char ddt = dg->GetTiltTime() - hitF.vt0; // signal time offset wrt prompt
174 if (ddt < dt0) dt0 = ddt;
175 if (abs(t) > 0) {
176 if (nt > 1) t *= 0.5;
177 err = te * (nt > 1 ? 0.707 : 1);
178 if (dg->HasTiltOvf()) {
179 ovf = -1;
180 err = 150.;
181 }
182 if (t > max) {
183 max = t;
184 hitF.vcM = j;
185 hitF.SetMaxTilt(1);
186 hitF.viM = hitSig.size();
187 }
188 }
189 else
190 err = 300.;
191
192 hitSig.emplace_back(t, err, ddt, xc, 0.035);
193 xc += 0.5;
194
195 // process rect signal/time
196 ddt = dg->GetRectTime() - hitF.vt0; // signal time offset wrt prompt
197 if (ddt < dt0) dt0 = ddt;
198 if (abs(r) > 0) {
199 nsr++;
200 if (nr > 1) r *= 0.5;
201 err = re * (nr > 1 ? 0.707 : 1);
202 if (dg->HasRectOvf()) {
203 ovf = -1;
204 err = 150.;
205 }
206 if (r > max) {
207 max = r;
208 hitF.vcM = j;
209 hitF.SetMaxTilt(0);
210 hitF.viM = hitSig.size();
211 }
212 }
213 else
214 err = 300.;
215
216 hitSig.emplace_back(r, err, ddt, xc, 0.);
217 xc += 0.5;
218 NR += nr;
219 NT += nt;
220 }
221
222 //TO DO: two blocks below might be mergable
223 // add front and back anchor points if needed
224 if (std::abs(hitSig[0].s) > 1.e-3) {
225 xc = hitSig[0].x;
226 char ddt = hitSig[0].t;
227 hitSig.emplace(hitSig.begin(), 0., 300., ddt, xc - 0.5, 0.);
228 hitF.viM++;
229 }
230 int n(hitSig.size() - 1);
231 if (std::abs(hitSig[n].s) > 1.e-3) {
232 xc = hitSig[n].x + 0.5;
233 char ddt = hitSig[n].t;
234 hitSig.emplace_back(0., 300., ddt, xc, 0.035);
235 }
236
237 n0 = hitSig.size() - 2;
238 // compute cluster asymmetry
239 int nR = n0 + 1 - hitF.viM;
240 if (nR == hitF.viM) {
241 hitF.SetSymmHit(1);
242 if (hitSig.size() % 2) {
243 double LS(0.), RS(0.);
244 for (UChar_t idx(0); idx < hitF.viM; idx++)
245 LS += hitSig[idx].s;
246 for (uint idx(hitF.viM + 1); idx < hitSig.size(); idx++)
247 RS += hitSig[idx].s;
248 hitF.SetLeftSgn(LS < RS ? 0 : 1);
249 }
250 }
251 else {
252 hitF.SetSymmHit(0);
253 if (hitF.viM < nR)
254 hitF.SetLeftHit(0);
255 else if (hitF.viM > nR)
256 hitF.SetLeftHit(1);
257 }
258 // recenter time and space profile
259 hitF.vt0 += dt0;
260 for (auto& sig : hitSig) {
261 sig.t -= dt0;
262 sig.x -= hitF.vcM;
263 }
264 hitF.vcM += col;
265
266 hitF.SetBiasX(0);
267 hitF.SetBiasY(0);
268
269 if (ovf < 0) hitF.SetOvf();
270 return std::make_pair(ovf * (hitSig.size() - 2), hitF);
271 }
272
273
274 int HitFinder2D::GetPadRowCol(int address, int& c)
275 {
276 c = address % fParams.rowPar[0].padPar.size();
277 return address / fParams.rowPar[0].padPar.size();
278 }
279
280} // namespace cbm::algo::trd
#define L_(level)
#define NANODE
Definition HitFinder2D.h:21
friend fscal max(fscal x, fscal y)
Data class with information on a STS local track.
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.
Data Container for TRD clusters.
Definition Cluster2D.h:22
const std::vector< DigiRec > & GetRecDigis() const
Get array of calibrated digis.
Definition Cluster2D.h:106
bool HasRectOvf() const
Definition DigiRec.h:58
double GetTiltCharge(bool &on) const
Return calibrated tilt signal.
Definition DigiRec.h:41
double GetTiltTime() const
Return calibrated tilt time [ns].
Definition DigiRec.h:43
bool HasTiltOvf() const
Definition DigiRec.h:59
double GetRectCharge(bool &on) const
Return calibrated rect signal.
Definition DigiRec.h:46
double GetRectTime() const
Return calibrated rect time [ns].
Definition DigiRec.h:48
std::pair< double, double > GetDxDy(const int n0)
std::pair< double, double > CorrectPosition(double dx, double dy, const double xcorr, const double padSizeX, const double padSizeY)
Shift graph representation to [-0.5, 0.5].
void SetMaxTilt(bool set=1)
void SetSymmHit(bool set=1)
std::vector< signal > fSignal
void SetLeftSgn(bool set=1)
uint8_t vcM
start time of current hit [clk]
int GetHitClass() const
Hit classification wrt center pad.
double GetXcorr(double dx, int typ, int cls=0) const
void SetLeftHit(bool set=1)
static Double_t fgDT[3]
hit time offset for synchronization
Definition HitFinder2D.h:89
HitFinder2DModPar fParams
Parameter container.
Definition HitFinder2D.h:76
Hit MakeHit(int cId, const Cluster2D *cluster)
void CalibrateHit(Hit *h, const double dx, const double dy, const double edx, const double edy, const double edt, const double time, const double tdrift, const double eloss, const HitFactory2D &hitF)
int GetPadRowCol(int address, int &c)
Addressing ASIC on module based on id.
std::vector< resultType > operator()(std::vector< Cluster2D > *clusters)
Steering routine for building hits.
HitFinder2D()
Default constructor.
Definition HitFinder2D.h:47
std::pair< int, HitFactory2D > ProjectDigis(const Cluster2D *cluster)
bool BuildHit(Hit *h, HitFactory2D &hitF)
Implement topologic cuts for hit merging.
A light-weight TRD hit class for online reconstruction, based on CbmTrdHit. .
void SetRefId(int32_t refId)
void SetAddress(int32_t address)
char t
working copy of signal errors from cluster
double xe
working copy of signal relative positions
double x
working copy of signal relative timing
ROOT::Math::Rotation3D rotation
std::vector< HitFinder2DRowPar > rowPar
ROOT::Math::XYZVector translation