CbmRoot
Loading...
Searching...
No Matches
CbmStsAlgoFindHitsOrtho.cxx
Go to the documentation of this file.
1/* Copyright (C) 2013-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Volker Friese [committer] */
4
10
11#include "CbmDigiManager.h"
12#include "CbmStsCluster.h"
13#include "CbmStsDigi.h"
14#include "CbmStsHit.h"
15#include "CbmStsParSensor.h"
16#include "CbmStsParSensorCond.h"
17
18#include <TGeoMatrix.h>
19#include <TMath.h>
20
21#include <iostream>
22
23using std::pair;
24using std::vector;
25
26
27// ----- Constructor ---------------------------------------------------
29// -------------------------------------------------------------------------
30
31
32// ----- Create a new hit ----------------------------------------------
33void CbmStsAlgoFindHitsOrtho::CreateHit(Double_t xLocal, Double_t yLocal, Double_t varX, Double_t varY, Double_t varXY,
34 const CbmStsCluster& clusterF, const CbmStsCluster& clusterB, UInt_t indexF,
35 UInt_t indexB, Double_t du, Double_t dv)
36{
37
38 // --- Check output array
39 assert(fHits);
40
41 // --- Transform into global coordinate system
42 Double_t local[3] = {xLocal, yLocal, 0.};
43 Double_t global[3];
44 if (fMatrix)
45 fMatrix->LocalToMaster(local, global);
46 else {
47 global[0] = local[0];
48 global[1] = local[1];
49 global[2] = local[2];
50 } //? no transformation matrix available
51
52 // We assume here that the local-to-global transformations is only translation
53 // plus maybe rotation upside down or front-side back. In that case, the
54 // global covariance matrix is the same as the local one.
55 // TODO: Proper transformation of covariance matrix
56 Double_t error[3] = {TMath::Sqrt(varX), TMath::Sqrt(varY), 0.};
57
58 // --- Calculate hit time (average of cluster times)
59 Double_t hitTime = 0.5 * (clusterF.GetTime() + clusterB.GetTime());
60 Double_t etF = clusterF.GetTimeError();
61 Double_t etB = clusterB.GetTimeError();
62 Double_t hitTimeError = 0.5 * TMath::Sqrt(etF * etF + etB * etB);
63
64 // --- Create hit
65 fHits->emplace_back(fAddress, global, error, varXY, indexF, indexB, hitTime, hitTimeError, du, dv);
66
67 return;
68}
69// -------------------------------------------------------------------------
70
71
72// ----- Algorithm execution -------------------------------------------
73Long64_t CbmStsAlgoFindHitsOrtho::Exec(const vector<CbmStsCluster>& clustersF, const vector<CbmStsCluster>& clustersB,
74 vector<CbmStsHit>& hits, UInt_t address, Double_t timeCutSig,
75 Double_t timeCutAbs, UInt_t nStripsF, UInt_t nStripsB, Double_t pitchF,
76 Double_t pitchB, Double_t lorentzF, Double_t lorentzB, TGeoHMatrix* matrix)
77{
78
79 // Assert validity of parameters
80 assert(nStripsF > 0);
81 assert(nStripsB > 0);
82 assert(pitchF > 0.);
83 assert(pitchB > 0.);
84
85 // Set internal parameters
86 fAddress = address;
87 fNofStripsF = nStripsF;
88 fNofStripsB = nStripsB;
89 fPitchF = pitchF;
90 fPitchB = pitchB;
91 fLorentzF = lorentzF;
92 fLorentzB = lorentzB;
93 fMatrix = matrix;
94 fHits = &hits;
95 fHits->clear();
96 fDx = Double_t(fNofStripsF) * fPitchF;
97 fDy = Double_t(fNofStripsB) * fPitchB;
98
99 // Determine the maximum cluster time errors
100 Double_t maxTerrF = 0.;
101 for (auto& cluster : clustersF) {
102 if (cluster.GetTimeError() > maxTerrF) maxTerrF = cluster.GetTimeError();
103 }
104 Double_t maxTerrB = 0.;
105 for (auto& cluster : clustersB) {
106 if (cluster.GetTimeError() > maxTerrB) maxTerrB = cluster.GetTimeError();
107 }
108 const Double_t maxTerrF2 = maxTerrF * maxTerrF;
109 const Double_t maxTerrB2 = maxTerrB * maxTerrB;
110 const Double_t max_sigma_both = 4. * TMath::Sqrt(maxTerrF2 + maxTerrB2);
111
112 // --- Loop over front and back side clusters
113 Long64_t nHits = 0;
114 Int_t startB = 0;
115 for (UInt_t iClusterF = 0; iClusterF < clustersF.size(); iClusterF++) {
116 const CbmStsCluster& clusterF = clustersF[iClusterF];
117
118 Double_t tF = clusterF.GetTime();
119 Double_t tFerr2 = clusterF.GetTimeError() * clusterF.GetTimeError();
120 Double_t max_sigma = 4. * TMath::Sqrt(tFerr2 + maxTerrB2);
121
122 for (UInt_t iClusterB = startB; iClusterB < clustersB.size(); iClusterB++) {
123 const CbmStsCluster& clusterB = clustersB[iClusterB];
124
125 Double_t timeDiff = tF - clusterB.GetTime();
126 if ((timeDiff > 0) && (timeDiff > max_sigma_both)) {
127 startB++;
128 continue;
129 }
130 else if ((timeDiff > 0) && (timeDiff > max_sigma)) {
131 continue;
132 }
133 else if ((timeDiff < 0) && (fabs(timeDiff) > max_sigma))
134 break;
135
136 // Cut on time difference of the two clusters
137 Double_t timeCut = -1.;
138 if (timeCutAbs > 0.)
139 timeCut = timeCutAbs; // absolute cut value
140 else {
141 if (timeCutSig > 0.) {
142 Double_t eF = clusterF.GetTimeError();
143 Double_t eB = clusterB.GetTimeError();
144 timeCut = timeCutSig * TMath::Sqrt(eF * eF + eB * eB);
145 } //? cut calculated from cluster errors
146 }
147 if (fabs(clusterF.GetTime() - clusterB.GetTime()) > timeCut) continue;
148
149 // --- Calculate intersection points
150 Int_t nOfHits = IntersectClusters(clusterF, clusterB, iClusterF, iClusterB);
151 nHits += nOfHits;
152
153 } //# clusters back side
154
155 } //# clusters front side
156
157 return nHits;
158}
159// -------------------------------------------------------------------------
160
161
162// ----- Get cluster position at read-out edge -------------------------
163void CbmStsAlgoFindHitsOrtho::GetClusterPosition(Double_t centre, Double_t& xCluster, Int_t& side)
164{
165
166 // Take integer channel
167 Int_t iChannel = Int_t(centre);
168 Double_t xDif = centre - Double_t(iChannel);
169
170 // Calculate corresponding strip on sensor
171 Int_t iStrip = -1;
172 pair<Int_t, Int_t> stripSide = GetStrip(iChannel);
173 iStrip = stripSide.first;
174 side = stripSide.second;
175 assert(side == 0 || side == 1);
176
177 // Re-add difference to integer channel. Convert channel to
178 // coordinate
179 if (side == 0)
180 xCluster = (Double_t(iStrip) + xDif + 0.5) * fPitchF;
181 else
182 xCluster = (Double_t(iStrip) + xDif + 0.5) * fPitchB;
183
184 // Correct for Lorentz-Shift
185 // Simplification: The correction uses only the y component of the
186 // magnetic field. The shift is calculated using the mid-plane of the
187 // sensor, which is not correct for tracks not traversing the entire
188 // sensor thickness (i.e., are created or stopped somewhere in the sensor).
189 // However, this is the best one can do in reconstruction.
190 if (side == 0)
191 xCluster -= fLorentzF;
192 else
193 xCluster -= fLorentzB;
194
195 return;
196}
197// -------------------------------------------------------------------------
198
199
200// ----- Get strip and side from channel number ------------------------
201pair<Int_t, Int_t> CbmStsAlgoFindHitsOrtho::GetStrip(UInt_t channel) const
202{
203
204 Int_t stripNr = -1;
205 Int_t side = -1;
206
207 // --- Determine front or back side
208 if (channel < fNofStripsF) { // front side
209 side = 0;
210 stripNr = channel;
211 }
212 else { // back side
213 side = 1;
214 stripNr = channel - fNofStripsF;
215 }
216
217 return (pair<Int_t, Int_t>(stripNr, side));
218}
219// -------------------------------------------------------------------------
220
221
222// ----- Intersect two clusters ----------------------------------------
224 UInt_t indexF, UInt_t indexB)
225{
226
227 // --- Calculate cluster centre position on readout edge
228 Int_t side = -1;
229 Double_t xF = -1.;
230 Double_t xB = -1.;
231 GetClusterPosition(clusterF.GetPosition(), xF, side);
232 assert(side == 0);
233 Double_t exF = clusterF.GetPositionError() * fPitchF;
234 Double_t du = exF;
235 GetClusterPosition(clusterB.GetPosition(), xB, side);
236 assert(side == 1);
237 Double_t exB = clusterB.GetPositionError() * fPitchB;
238 Double_t dv = exB;
239
240 // --- Should be inside active area
241 if (!(xF >= 0. || xF <= fDx)) return 0;
242 if (!(xB >= 0. || xB <= fDy)) return 0;
243
244 // --- Hit counter
245 Int_t nHits = 0;
246
247 // In orthogonal sensor, all pairs of (front, back) cluster have
248 // a single intersection
249 // => exactly one hit!
250
251 // --- Prepare hit coordinates and errors
252 // In the coordinate system with origin at the bottom left corner,
253 // the coordinates in the orthogonal sensor are straightforward.
254 Double_t xC = xF; // x coordinate of intersection point
255 Double_t yC = xB; // y coordinate of intersection point
256 Double_t varX = exF * exF; // variance of xC
257 Double_t varY = exB * exB; // variance of yC
258 Double_t varXY = 0.; // covariance xC-yC => independent variables!
259
260 // --- Transform into sensor system with origin at sensor centre
261 xC -= 0.5 * fDx;
262 yC -= 0.5 * fDy;
263
264 // --- Create the hit
265 CreateHit(xC, yC, varX, varY, varXY, clusterF, clusterB, indexF, indexB, du, dv);
266 nHits++;
267
268 return nHits;
269}
270// -------------------------------------------------------------------------
271
272
273// ----- Check whether a point is inside the active area ---------------
274Bool_t CbmStsAlgoFindHitsOrtho::IsInside(Double_t x, Double_t y)
275{
276 if (x < -fDx / 2.) return kFALSE;
277 if (x > fDx / 2.) return kFALSE;
278 if (y < -fDy / 2.) return kFALSE;
279 if (y > fDy / 2.) return kFALSE;
280 return kTRUE;
281}
282// -------------------------------------------------------------------------
283
284
ClassImp(CbmConverterManager)
Data class for STS clusters.
Data class for a reconstructed hit in the STS.
static vector< vector< QAHit > > hits
Algorithm for hit finding in sensors with orthogonal strips.
Double_t fLorentzB
Lorentz shift correction back side [cm].
Double_t fDy
Active size in y [cm].
std::pair< Int_t, Int_t > GetStrip(UInt_t channel) const
Get strip and side from module channel.
void GetClusterPosition(Double_t ClusterCentre, Double_t &xCluster, Int_t &side)
Int_t IntersectClusters(const CbmStsCluster &clusterF, const CbmStsCluster &clusterB, UInt_t indexF, UInt_t indexB)
Find the intersection points of two clusters.
void CreateHit(Double_t xLocal, Double_t yLocal, Double_t varX, Double_t varY, Double_t varXY, const CbmStsCluster &clusterF, const CbmStsCluster &clusterB, UInt_t indexF, UInt_t indexB, Double_t du=0., Double_t dv=0.)
Create a new hit in the output array.
Double_t fPitchB
Strip pitch back side [cm].
UInt_t fNofStripsB
Number of strips backs side.
Double_t fPitchF
Strip pitch front side [cm].
std::vector< CbmStsHit > * fHits
///< Transformation matrix to global C.S.
UInt_t fAddress
Unique address for hits (sensor)
Double_t fLorentzF
Lorentz shift correction front side [cm].
Double_t fDx
Active size in x [cm].
UInt_t fNofStripsF
Number of strips front side.
Long64_t Exec(const std::vector< CbmStsCluster > &clustersF, const std::vector< CbmStsCluster > &clustersB, std::vector< CbmStsHit > &hits, UInt_t address, Double_t timeCutSig, Double_t timeCutAbs, UInt_t nStripsF, UInt_t nStripsB, Double_t pitchF, Double_t pitchB, Double_t lorentzF, Double_t lorentzB, TGeoHMatrix *matrix)
Execute algorithm.
Bool_t IsInside(Double_t x, Double_t y)
Check whether a point (x,y) is inside the active area.
Data class for STS clusters.
double GetPositionError() const
Cluster position error @value Error (r.m.s.) of cluster position in channel number units.
double GetTime() const
Get cluster time.
double GetPosition() const
Cluster position @value Cluster position in channel number units.
double GetTimeError() const
Get error of cluster time.