Project
Loading...
Searching...
No Matches
CalibLaserTracks.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
15
16#include "MathUtils/Utils.h"
21#include "TLinearFitter.h"
22#include <chrono>
23#include <algorithm>
24#include <string_view>
25
26using namespace o2::tpc;
27void CalibLaserTracks::fill(std::vector<TrackTPC> const& tracks)
28{
29 fill(gsl::span(tracks.data(), tracks.size()));
30}
31
32//______________________________________________________________________________
33void CalibLaserTracks::fill(const gsl::span<const TrackTPC> tracks)
34{
35 // ===| clean up TF data |===
36 mZmatchPairsTFA.clear();
37 mZmatchPairsTFC.clear();
38 mCalibDataTF.reset();
39
40 if (!tracks.size()) {
41 return;
42 }
43
44 mCalibData.nTrackTF.emplace_back();
45 mCalibDataTF.nTrackTF.emplace_back();
46
47 // ===| associate tracks with ideal laser track positions |===
48 for (const auto& track : tracks) {
49 processTrack(track);
50 }
51
52 // ===| set TF start and end times |===
53 if (mCalibData.firstTime == 0 && mCalibData.lastTime == 0) {
54 mCalibData.firstTime = mTFstart;
55 }
56
57 auto tfEnd = mTFend;
58 if (tfEnd == 0) {
59 tfEnd = mTFstart;
60 }
61 mCalibData.lastTime = tfEnd;
62
63 mCalibDataTF.firstTime = mTFstart;
64 mCalibDataTF.lastTime = tfEnd;
65
66 // ===| TF counters |===
67 ++mCalibData.processedTFs;
68 ++mCalibDataTF.processedTFs;
69
70 // ===| finalize TF processing |===
71 endTF();
72}
73
74//______________________________________________________________________________
76{
77 if (track.hasBothSidesClusters()) {
78 return;
79 }
80
81 // use outer parameters which are closest to the laser mirrors
82 auto parOutAtLtr = track.getOuterParam();
83
84 // track should have been alreay propagated close to the laser mirrors
85 if (parOutAtLtr.getX() < 220) {
86 return;
87 }
88
89 // recalculate z position based on trigger or CE position if needed
90 float zTrack = parOutAtLtr.getZ();
91
92 // TODO: calculation has to be improved
93 if (mTriggerPos < 0) {
94 // use CE for time 0
95 const float zOffset = (track.getTime0() + mTriggerPos) * mZbinWidth * mDriftV + 250;
96 // printf("time0: %.2f, trigger pos: %d, zTrack: %.2f, zOffset: %.2f\n", track.getTime0(), mTriggerPos, zTrack, zOffset);
97 zTrack += zOffset;
98 parOutAtLtr.setZ(zTrack);
99 } else if (mTriggerPos > 0) {
100 const float zOffset = mTriggerPos;
101 }
102
103 if (std::abs(zTrack) > 300) {
104 return;
105 }
106
107 // try association with ideal laser track and rotate parameters
108 const int side = track.hasCSideClusters();
109 const int laserTrackID = findLaserTrackID(parOutAtLtr, side);
110
111 if (laserTrackID < 0 || laserTrackID >= LaserTrack::NumberOfTracks) {
112 return;
113 }
114
115 auto ltr = mLaserTracks.getTrack(laserTrackID);
116 parOutAtLtr.rotateParam(ltr.getAlpha());
117 parOutAtLtr.propagateParamTo(ltr.getX(), mBz);
118
119 if (ltr.getSide() == 0) {
120 mZmatchPairsA.emplace_back(TimePair{ltr.getZ(), parOutAtLtr.getZ(), mTFstart});
121 mZmatchPairsTFA.emplace_back(TimePair{ltr.getZ(), parOutAtLtr.getZ(), mTFstart});
122 } else {
123 mZmatchPairsC.emplace_back(TimePair{ltr.getZ(), parOutAtLtr.getZ(), mTFstart});
124 mZmatchPairsTFC.emplace_back(TimePair{ltr.getZ(), parOutAtLtr.getZ(), mTFstart});
125 }
126
127 mCalibData.matchedLtrIDs.emplace_back(laserTrackID);
128 mCalibDataTF.matchedLtrIDs.emplace_back(laserTrackID);
129
130 const auto dEdx = track.getdEdx().dEdxTotTPC;
131 mCalibData.dEdx.emplace_back(dEdx);
132 mCalibDataTF.dEdx.emplace_back(dEdx);
133
134 ++mCalibData.nTrackTF.back();
135 ++mCalibDataTF.nTrackTF.back();
136
137 // ===| debug output |========================================================
138 if (mWriteDebugTree) {
139 if (!mDebugStream) {
140 mDebugStream = std::make_unique<o2::utils::TreeStreamRedirector>(mDebugOutputName.data(), "recreate");
141 }
142
143 auto writeTrack = track;
144 *mDebugStream << "ltrMatch"
145 << "tfStart=" << mTFstart
146 << "tfEnd=" << mTFend
147 << "ltr=" << ltr // matched ideal laser track
148 << "trOutLtr=" << parOutAtLtr // track rotated and propagated to ideal track position
149 << "TPCTracks=" << writeTrack // original TPC track
150 << "\n";
151 }
152}
153
154//______________________________________________________________________________
155int CalibLaserTracks::findLaserTrackID(TrackPar outerParam, int side)
156{
157 // ===| rotate outer param to closes laser rod |===
158 const auto phisec = getPhiNearbyLaserRod(outerParam, side);
159 if (!outerParam.rotateParam(phisec)) {
160 return -1;
161 }
162
163 if (side < 0) {
164 side = outerParam.getZ() < 0;
165 }
166
167 // ===| laser rod |===
168 const int rod = std::nearbyint((phisec - LaserTrack::FirstRodPhi[side]) / LaserTrack::RodDistancePhi);
169
170 // ===| laser bundle |===
171 float mindist = 1000;
172
173 const auto outerParamZ = std::abs(outerParam.getZ());
174
175 int bundle = -1;
176 for (size_t i = 0; i < LaserTrack::CoarseBundleZPos.size(); ++i) {
177 const float dist = std::abs(outerParamZ - LaserTrack::CoarseBundleZPos[i]);
178 if (dist < mindist) {
179 mindist = dist;
180 bundle = i;
181 }
182 }
183
184 if (bundle < 0) {
185 return -1;
186 }
187
188 // ===| laser beam |===
189 const auto outerParamsInBundle = mLaserTracks.getTracksInBundle(side, rod, bundle);
190 mindist = 1000;
191
192 int beam = -1;
193 for (int i = 0; i < outerParamsInBundle.size(); ++i) {
194 const auto louterParam = outerParamsInBundle[i];
195 if (i == 0) {
196 outerParam.propagateParamTo(louterParam.getX(), mBz);
197 }
198 const float dist = std::abs(outerParam.getSnp() - louterParam.getSnp());
199 if (dist < mindist) {
200 mindist = dist;
201 beam = i;
202 }
203 }
204
205 if (mindist > 0.01) {
206 return -1;
207 }
208
209 // ===| track ID from side, rod, bundle and beam |===
210 const int trackID = LaserTrack::NumberOfTracks / 2 * side +
213 beam;
214
215 return trackID;
216}
217
218//______________________________________________________________________________
220{
221 const auto xyzGlo = param.getXYZGlo();
222 const auto phiTrack = o2::math_utils::to02PiGen(std::atan2(xyzGlo.Y(), xyzGlo.X()) - LaserTrack::FirstRodPhi[side % 2]);
224
225 return phiRod;
226}
227
228//______________________________________________________________________________
230{
231 const auto xyzGlo = param.getXYZGlo();
232 const auto phiTrack = o2::math_utils::to02PiGen(std::atan2(xyzGlo.Y(), xyzGlo.X()) - LaserTrack::FirstRodPhi[side % 2]);
233 const auto phiRod = o2::math_utils::to02PiGen(std::nearbyint(phiTrack / LaserTrack::RodDistancePhi) * LaserTrack::RodDistancePhi);
234
235 return std::abs(phiRod - phiTrack) < LaserTrack::SectorSpanRad / 4.;
236}
237
238//______________________________________________________________________________
239void CalibLaserTracks::updateParameters()
240{
241 const auto& gasParam = ParameterGas::Instance();
242 const auto& electronicsParam = ParameterElectronics::Instance();
243 const auto& detpar = o2::tpc::ParameterDetector::Instance();
244 mDriftV = gasParam.DriftV;
245 mZbinWidth = electronicsParam.ZbinWidth;
246 mTOffsetMUS = detpar.DriftTimeOffset * mZbinWidth;
247}
248
249//______________________________________________________________________________
251{
252 if (!other) {
253 return;
254 }
255 mCalibData.processedTFs += other->mCalibData.processedTFs;
256
257 const auto sizeAthis = mZmatchPairsA.size();
258 const auto sizeCthis = mZmatchPairsC.size();
259 const auto sizeAother = other->mZmatchPairsA.size();
260 const auto sizeCother = other->mZmatchPairsC.size();
261
262 mZmatchPairsA.insert(mZmatchPairsA.end(), other->mZmatchPairsA.begin(), other->mZmatchPairsA.end());
263 mZmatchPairsC.insert(mZmatchPairsC.end(), other->mZmatchPairsC.begin(), other->mZmatchPairsC.end());
264
265 auto& ltrIDs = mCalibData.matchedLtrIDs;
266 auto& ltrIDsOther = other->mCalibData.matchedLtrIDs;
267 ltrIDs.insert(ltrIDs.end(), ltrIDsOther.begin(), ltrIDsOther.end());
268
269 auto& nTrk = mCalibData.nTrackTF;
270 auto& nTrkOther = other->mCalibData.nTrackTF;
271 nTrk.insert(nTrk.end(), nTrkOther.begin(), nTrkOther.end());
272
273 auto& dEdx = mCalibData.dEdx;
274 auto& dEdxOther = other->mCalibData.dEdx;
275 dEdx.insert(dEdx.end(), dEdxOther.begin(), dEdxOther.end());
276
277 mCalibData.firstTime = std::min(mCalibData.firstTime, other->mCalibData.firstTime);
278 mCalibData.lastTime = std::max(mCalibData.lastTime, other->mCalibData.lastTime);
279
280 sort(mZmatchPairsA);
281 sort(mZmatchPairsC);
282
283 LOGP(info, "Merged CalibLaserTracks with mached pairs {} / {} + {} / {} = {} / {} (this +_other A- / C-Side)", sizeAthis, sizeCthis, sizeAother, sizeCother, mZmatchPairsA.size(), mZmatchPairsC.size());
284}
285
286//______________________________________________________________________________
288{
289 LOGP(info, "Ending time frame {} - {} with {} / {} matched laser tracks (total: {} / {}) on the A / C-Side", mTFstart, mTFend, mZmatchPairsTFA.size(), mZmatchPairsTFC.size(), mZmatchPairsA.size(), mZmatchPairsC.size());
290 fillCalibData(mCalibDataTF, mZmatchPairsTFA, mZmatchPairsTFC);
291
292 if (mDebugStream) {
293 (*mDebugStream) << "tfData"
294 << "tfStart=" << mTFstart
295 << "tfEnf=" << mTFend
296 << "zPairsA=" << mZmatchPairsTFA
297 << "zPairsC=" << mZmatchPairsTFC
298 << "calibData=" << mCalibDataTF
299 << "\n";
300 }
301}
302
303//______________________________________________________________________________
305{
306 mFinalized = true;
307 sort(mZmatchPairsA);
308 sort(mZmatchPairsC);
309
310 fillCalibData(mCalibData, mZmatchPairsA, mZmatchPairsC);
311
312 // auto& ltrIDs = mCalibData.matchedLtrIDs;
313 // std::sort(ltrIDs.begin(), ltrIDs.end());
314 // ltrIDs.erase(std::unique(ltrIDs.begin(), ltrIDs.end()), ltrIDs.end());
315
316 if (mDebugStream) {
317 (*mDebugStream) << "finalData"
318 << "zPairsA=" << mZmatchPairsA
319 << "zPairsC=" << mZmatchPairsC
320 << "calibData=" << mCalibData
321 << "\n";
322
323 mDebugStream->Close();
324 }
325}
326
327//______________________________________________________________________________
328void CalibLaserTracks::fillCalibData(LtrCalibData& calibData, const std::vector<TimePair>& pairsA, const std::vector<TimePair>& pairsC)
329{
330 auto dvA = fit(pairsA, "A-Side");
331 auto dvC = fit(pairsC, "C-Side");
332 calibData.creationTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
333 calibData.refVDrift = mDriftV;
334 calibData.dvOffsetA = dvA.x1;
335 calibData.dvCorrectionA = dvA.x2;
336 calibData.nTracksA = uint16_t(pairsA.size());
337
338 calibData.dvOffsetC = dvC.x1;
339 calibData.dvCorrectionC = dvC.x2;
340 calibData.nTracksC = uint16_t(pairsC.size());
341
342 calibData.refTimeOffset = mTOffsetMUS;
343}
344
345//______________________________________________________________________________
346TimePair CalibLaserTracks::fit(const std::vector<TimePair>& trackMatches, std::string_view info) const
347{
348 if (!trackMatches.size()) {
349 return TimePair();
350 }
351
352 static TLinearFitter fit(2, "pol1");
353 fit.StoreData(false);
354 fit.ClearPoints();
355
356 uint64_t meanTime = 0;
357 double minZrec = 1000;
358 double maxZrec = -1000;
359 for (const auto& point : trackMatches) {
360 double x = point.x1;
361 double y = point.x2;
362 fit.AddPoint(&x, y);
363
364 meanTime += point.time;
365
366 minZrec = std::min(y, minZrec);
367 maxZrec = std::max(y, maxZrec);
368 }
369
370 meanTime /= uint64_t(trackMatches.size());
371
372 const float robustFraction = 0.9;
373 const int minPoints = 6;
374
375 if (trackMatches.size() < size_t(minPoints / robustFraction)) {
376 LOGP(warning, "{} - Not enough points to perform the fit: {} < {}", info, trackMatches.size(), size_t(minPoints / robustFraction));
377 return TimePair({0, 0, meanTime});
378 }
379 if (std::abs(maxZrec - minZrec) < 50) {
380 LOGP(warning, "{} - All points seem to be from one Layer: abs({}cm - {}cm) < 50cm, will not do fitting", info, trackMatches.size(), maxZrec, minZrec);
381 return TimePair({0, 0, meanTime});
382 }
383
384 // fit.EvalRobust(robustFraction);
385 fit.Eval();
386
388 retVal.x1 = float(fit.GetParameter(0));
389 retVal.x2 = float(fit.GetParameter(1));
390 retVal.time = meanTime;
391
392 return retVal;
393}
394
395//______________________________________________________________________________
396void CalibLaserTracks::sort(std::vector<TimePair>& trackMatches)
397{
398 std::sort(trackMatches.begin(), trackMatches.end(), [](const auto& first, const auto& second) { return first.time < second.time; });
399}
400
401//______________________________________________________________________________
403{
404 if (mFinalized) {
405 LOGP(info,
406 "Processed {} TFs from {} - {}; found tracks: {} / {}; fit offsets (cm): {} / {}; T0s (us): {} / {}; dv correction factors: {} / {} for A- / C-Side, reference: {}",
407 mCalibData.processedTFs,
408 mCalibData.firstTime,
409 mCalibData.lastTime,
410 mCalibData.nTracksA,
411 mCalibData.nTracksC,
412 mCalibData.dvOffsetA,
413 mCalibData.dvOffsetC,
414 mCalibData.getT0A(),
415 mCalibData.getT0C(),
416 mCalibData.dvCorrectionA,
417 mCalibData.dvCorrectionC,
418 mCalibData.refVDrift);
419 } else {
420 LOGP(info,
421 "Processed {} TFs from {} - {}; **Not finalized**",
422 mCalibData.processedTFs,
423 mCalibData.firstTime,
424 mCalibData.lastTime);
425
426 LOGP(info,
427 "Last processed TF from {} - {}; found tracks: {} / {}; fit offsets (cm): {} / {}; T0s (us): {} / {}; dv correction factors: {} / {} for A- / C-Side, reference: {}",
428 mCalibDataTF.firstTime,
429 mCalibDataTF.lastTime,
430 mCalibDataTF.nTracksA,
431 mCalibDataTF.nTracksC,
432 mCalibDataTF.dvOffsetA,
433 mCalibDataTF.dvOffsetC,
434 mCalibDataTF.getT0A(),
435 mCalibDataTF.getT0C(),
436 mCalibDataTF.dvCorrectionA,
437 mCalibDataTF.dvCorrectionC,
438 mCalibDataTF.refVDrift);
439 }
440}
calibration using laser tracks
General auxilliary methods.
int32_t i
int32_t retVal
Definition of the parameter class for the detector.
Definition of the parameter class for the detector electronics.
Definition of the parameter class for the detector gas.
uint32_t side
Definition RawData.h:0
void finalize()
Finalize full processing.
static float getPhiNearbyLaserRod(const TrackPar &param, int side)
calculate phi of nearest laser rod
void endTF()
End processing of this TF.
void fill(const gsl::span< const TrackTPC > tracks)
process all tracks of one TF
static bool hasNearbyLaserRod(const TrackPar &param, int side)
check if param is closer to a laser rod than 1/4 of a sector width
void processTrack(const TrackTPC &track)
process single track
void print() const
print information
void merge(const CalibLaserTracks *other)
merge data with other calibration object
void sort(std::vector< TimePair > &trackMatches)
sort TimePoint vectors
int findLaserTrackID(TrackPar track, int side=-1)
TimePair fit(const std::vector< TimePair > &trackMatches, std::string_view info) const
extract DV correction and T0 offset
LaserTrack const & getTrack(int id) const
Definition LaserTrack.h:82
gsl::span< const LaserTrack > getTracksInBundle(int side, int rod, int bundle)
get span with tracks in one bundle
Definition LaserTrack.h:92
static constexpr float SectorSpanRad
secotor width in rad
Definition LaserTrack.h:33
static constexpr int BundlesPerRod
number of micro-mirror bundle per laser rod
Definition LaserTrack.h:31
static constexpr int NumberOfTracks
Total number of laser tracks.
Definition LaserTrack.h:29
static constexpr float RodDistancePhi
phi distance of laser Rods
Definition LaserTrack.h:35
static constexpr int TracksPerBundle
number of micro-mirrors per bundle
Definition LaserTrack.h:32
static constexpr std::array< float, 4 > CoarseBundleZPos
coarse z-position of the laser bundles
Definition LaserTrack.h:36
static constexpr std::array< float, 2 > FirstRodPhi
phi pos of first laser rod, A-, C-Side
Definition LaserTrack.h:34
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum GLfloat param
Definition glcorearb.h:271
float to02PiGen(float phi)
Definition Utils.h:70
Global TPC definitions and constants.
Definition SimTraits.h:167
std::vector< uint16_t > nTrackTF
number of laser tracks per TF
float dvCorrectionA
drift velocity correction factor A-Side (inverse multiplicative)
float dvOffsetC
drift velocity trigger offset C-Side
float dvOffsetA
drift velocity trigger offset A-Side
float dvCorrectionC
drift velocity correction factor C-Side (inverse multiplicative)
std::vector< uint16_t > matchedLtrIDs
matched laser track IDs
std::vector< float > dEdx
dE/dx of each track
size_t processedTFs
number of processed TFs with laser track candidates
uint64_t lastTime
last time stamp of processed TFs
uint16_t nTracksC
number of tracks used for C-Side fit
long creationTime
time of creation
uint16_t nTracksA
number of tracks used for A-Side fit
float refTimeOffset
additive time offset reference (\mus)
float refVDrift
reference vdrift for which factor was extracted
uint64_t firstTime
first time stamp of processed TFs
VectorOfTObjectPtrs other