Project
Loading...
Searching...
No Matches
TrackBasedCalib.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
22#include "TRDBase/Geometry.h"
23#include "TRDBase/PadPlane.h"
25#include <fairlogger/Logger.h>
26
27using namespace o2::trd;
28using namespace o2::trd::constants;
29
31{
32 mAngResHistos.reset();
33 mGainCalibHistos.clear();
34}
35
37{
38 bz = o2::base::Propagator::Instance()->getNominalBz();
40 config.ReadConfigurableParam(config);
41 mRecoParam.init(bz, &config.configReconstruction);
42}
43
45{
46 mTracksInITSTPCTRD = input.getITSTPCTRDTracks<TrackTRD>();
47 mTracksInTPCTRD = input.getTPCTRDTracks<TrackTRD>();
48 mTrackletsRaw = input.getTRDTracklets();
49 mTrackletsCalib = input.getTRDCalibratedTracklets();
50 mTracksTPC = input.getTPCTracks();
51 mTracksITSTPC = input.getTPCITSTracks();
52}
53
55{
56 if (!mLocalGain) {
57 LOG(alarm) << "No Local gain map available. Please upload valid object to CCDB.";
58 }
59
60 int nTracksSuccessTPCTRD = filldEdx(mTracksInTPCTRD, true);
61 int nTracksSuccessITSTPCTRD = filldEdx(mTracksInITSTPCTRD, false);
62
63 LOGP(info, "Gain Calibration: Successfully processed {} tracks ({} from ITS-TPC-TRD and {} from TPC-TRD) and collected {} data points",
64 nTracksSuccessITSTPCTRD + nTracksSuccessTPCTRD, nTracksSuccessITSTPCTRD, nTracksSuccessTPCTRD, mGainCalibHistos.size());
65}
66
68{
69 if (mTrackletsRaw.size() != mTrackletsCalib.size()) {
70 LOG(error) << "TRD raw tracklet container size differs from calibrated tracklet container size";
71 return;
72 }
73
74 if (!mNoiseCalib) {
75 LOG(alarm) << "No MCM noise map available. Please upload valid object to CCDB.";
76 }
77
78 LOGF(info, "As input tracks are available: %lu ITS-TPC-TRD tracks and %lu TPC-TRD tracks", mTracksInITSTPCTRD.size(), mTracksInTPCTRD.size());
79
80 int nTracksSuccessITSTPCTRD = doTrdOnlyTrackFits(mTracksInITSTPCTRD);
81 int nTracksSuccessTPCTRD = doTrdOnlyTrackFits(mTracksInTPCTRD);
82
83 LOGF(info, "Successfully processed %i tracks (%i from ITS-TPC-TRD and %i from TPC-TRD) and collected %lu angular residuals",
84 nTracksSuccessITSTPCTRD + nTracksSuccessTPCTRD, nTracksSuccessITSTPCTRD, nTracksSuccessTPCTRD, mAngResHistos.getNEntries());
85 // mAngResHistos.print();
86}
87
88int TrackBasedCalib::filldEdx(gsl::span<const TrackTRD>& tracks, bool isTPCTRD)
89{
91 int nTracksSuccess = 0;
92 for (const auto& trkIn : tracks) {
93
94 if (trkIn.getNtracklets() < params.nTrackletsMinGainCalib) {
95 continue;
96 }
97
98 if (trkIn.getP() < params.pMin || trkIn.getP() > params.pMax) {
99 continue;
100 }
101
102 auto id = trkIn.getRefGlobalTrackId();
103 float dEdxTPC;
104 if (isTPCTRD) {
105 dEdxTPC = mTracksTPC[id].getdEdx().dEdxTotTPC;
106 } else {
107 dEdxTPC = mTracksTPC[mTracksITSTPC[id].getRefTPC()].getdEdx().dEdxTotTPC;
108 }
109 if (dEdxTPC < params.dEdxTPCMin || dEdxTPC > params.dEdxTPCMax) {
110 continue;
111 }
112
113 if (std::isnan(trkIn.getSnp())) {
114 LOG(alarm) << "Track with invalid parameters found: " << trkIn.getRefGlobalTrackId();
115 continue;
116 }
117
118 for (int iLayer = NLAYER - 1; iLayer >= 0; --iLayer) {
119 if (trkIn.getTrackletIndex(iLayer) == -1) {
120 continue;
121 }
122 if (mNoiseCalib && mNoiseCalib->isTrackletFromNoisyMCM(mTrackletsRaw[trkIn.getTrackletIndex(iLayer)])) {
123 // ignore tracklets which originate from noisy MCMs
124 continue;
125 }
126
127 // Remove split tracklets
128 if (trkIn.getIsCrossingNeighbor(iLayer)) {
129 continue;
130 }
131
132 int trkltId = trkIn.getTrackletIndex(iLayer);
133 int trkltDet = mTrackletsRaw[trkltId].getDetector();
134 int trkltSec = trkltDet / (NLAYER * NSTACK);
135
136 const auto& tracklet = mTrackletsRaw[trkltId];
137
138 auto q0 = tracklet.getQ0();
139 auto q1 = tracklet.getQ1();
140 auto q2 = tracklet.getQ2();
141 if (q0 == 0 || q1 == 0 || q2 == 0 || q0 >= 127 || q1 >= 127 || q2 >= 62) {
142 continue;
143 }
144
145 // Correction for tracklet angle
146 const auto& trackletCalib = mTrackletsCalib[trkltId];
147 float tgl = trkIn.getTgl();
148 float snp = trkIn.getSnpAt(o2::math_utils::sector2Angle(trkltSec), trackletCalib.getX(), bz);
149
150 if (abs(snp) > 1.) {
151 continue;
152 }
153
154 // This is the track length normalised to the track length at zero angle
155 // l/l0 = sqrt(dx^2 + dy^2 + dz^2)/dx = sqrt(1 + (dy/dx)^2 + (dz/dx)^2)
156 // (dz/dx)^2 = tan^2(lambda), (dy/dx)^2 = tan^2(phi) = sin^2(phi)/(1-sin^2(phi))
157 float trkLength = sqrt(1 + snp * snp / (1 - snp * snp) + tgl * tgl);
158 if (TMath::Abs(trkLength) < 1) {
159 LOGP(warn, "Invalid track length {} for angles snp {} and tgl {}", trkLength, snp, tgl);
160 continue;
161 }
162
163 float localGainCorr = 1.;
164 if (mLocalGain) {
165 localGainCorr = mLocalGain->getValue(trkltDet, tracklet.getPadCol(mApplyShift), tracklet.getPadRow());
166 }
167 if (TMath::Abs(localGainCorr) < 0.0001f) {
168 LOGP(warn, "Invalid localGainCorr {} for det {}, pad col {}, pad row {}", localGainCorr, trkltDet, tracklet.getPadCol(mApplyShift), tracklet.getPadRow());
169 continue;
170 }
171
172 unsigned int dEdx = (q0 + q1 + q2) / trkLength / localGainCorr;
173 if (dEdx >= NBINSGAINCALIB) {
174 continue;
175 }
176 int chamberOffset = trkltDet * NBINSGAINCALIB;
177 mGainCalibHistos.push_back(chamberOffset + dEdx);
178 }
179
180 // here we can count the number of successfully processed tracks
181 ++nTracksSuccess;
182 } // end of track loop
183 return nTracksSuccess;
184}
185
186int TrackBasedCalib::doTrdOnlyTrackFits(gsl::span<const TrackTRD>& tracks)
187{
189 int nTracksSuccess = 0;
190 for (const auto& trkIn : tracks) {
191 if (trkIn.getNtracklets() < params.nTrackletsMin) {
192 // with less than 3 tracklets the TRD-only refit not meaningful
193 continue;
194 }
195 auto trkWork = trkIn; // input is const, so we need to create a copy
196 bool trackFailed = false;
197
198 trkWork.setChi2(0.f);
199 trkWork.resetCovariance(20);
200
201 if (std::isnan(trkWork.getSnp())) {
202 LOG(alarm) << "Track with invalid parameters found: " << trkWork.getRefGlobalTrackId();
203 continue;
204 }
205
206 // first inward propagation (TRD track fit)
207 int currLayer = NLAYER;
208 for (int iLayer = NLAYER - 1; iLayer >= 0; --iLayer) {
209 if (trkWork.getTrackletIndex(iLayer) == -1) {
210 continue;
211 }
212 if (mNoiseCalib && mNoiseCalib->isTrackletFromNoisyMCM(mTrackletsRaw[trkWork.getTrackletIndex(iLayer)])) {
213 // ignore tracklets which originate from noisy MCMs
214 continue;
215 }
216 if (propagateAndUpdate(trkWork, iLayer, true)) {
217 trackFailed = true;
218 break;
219 }
220 currLayer = iLayer;
221 }
222 if (trackFailed) {
223 continue;
224 }
225
226 // outward propagation (smoothing)
227 for (int iLayer = currLayer + 1; iLayer < NLAYER; ++iLayer) {
228 if (trkWork.getTrackletIndex(iLayer) == -1) {
229 continue;
230 }
231 if (mNoiseCalib && mNoiseCalib->isTrackletFromNoisyMCM(mTrackletsRaw[trkWork.getTrackletIndex(iLayer)])) {
232 // ignore tracklets which originate from noisy MCMs
233 continue;
234 }
235 if (propagateAndUpdate(trkWork, iLayer, true)) {
236 trackFailed = true;
237 break;
238 }
239 currLayer = iLayer;
240 }
241 if (trackFailed) {
242 continue;
243 }
244
245 // second inward propagation (collect angular differences between tracklets + TRD track)
246 for (int iLayer = currLayer; iLayer >= 0; --iLayer) {
247 if (trkWork.getTrackletIndex(iLayer) == -1) {
248 continue;
249 }
250 if (mNoiseCalib && mNoiseCalib->isTrackletFromNoisyMCM(mTrackletsRaw[trkWork.getTrackletIndex(iLayer)])) {
251 // ignore tracklets which originate from noisy MCMs
252 continue;
253 }
254 if (propagateAndUpdate(trkWork, iLayer, false)) {
255 trackFailed = true;
256 break;
257 }
258
259 if (trkWork.getReducedChi2() > params.chi2RedMax) {
260 // set an upper bound on acceptable tracks we use for qc
261 continue;
262 }
263
264 float trkAngle = o2::math_utils::asin(trkWork.getSnp()) * TMath::RadToDeg();
265 float trkltAngle = o2::math_utils::atan(mTrackletsCalib[trkWork.getTrackletIndex(iLayer)].getDy() / Geometry::cdrHght()) * TMath::RadToDeg();
266 float angleDeviation = trkltAngle - trkAngle;
267 if (mAngResHistos.addEntry(angleDeviation, trkAngle, mTrackletsRaw[trkWork.getTrackletIndex(iLayer)].getDetector())) {
268 // track impact angle out of histogram range
269 continue;
270 }
271 }
272
273 // here we can count the number of successfully processed tracks
274 ++nTracksSuccess;
275 } // end of track loop
276 return nTracksSuccess;
277}
278
279bool TrackBasedCalib::propagateAndUpdate(TrackTRD& trk, int iLayer, bool doUpdate) const
280{
281 // Propagates the track to TRD layer iLayer and updates the track
282 // parameters (if requested)
283 // returns 0 in case of success
284
285 auto propagator = o2::base::Propagator::Instance();
286
287 int trkltId = trk.getTrackletIndex(iLayer);
288 int trkltDet = mTrackletsRaw[trkltId].getDetector();
289 int trkltSec = trkltDet / (NLAYER * NSTACK);
290
291 if (trkltSec != o2::math_utils::angle2Sector(trk.getAlpha())) {
292 if (!trk.rotate(o2::math_utils::sector2Angle(trkltSec))) {
293 LOGF(debug, "Track could not be rotated in tracklet coordinate system");
294 return 1;
295 }
296 }
297
298 if (!propagator->PropagateToXBxByBz(trk, mTrackletsCalib[trkltId].getX(), mMaxSnp, mMaxStep, mMatCorr)) {
299 LOGF(debug, "Track propagation failed in layer %i (pt=%f, xTrk=%f, xToGo=%f)", iLayer, trk.getPt(), trk.getX(), mTrackletsCalib[trkltId].getX());
300 return 1;
301 }
302
303 if (!doUpdate) {
304 // nothing more to be done
305 return 0;
306 }
307
308 const PadPlane* pad = Geometry::instance()->getPadPlane(trkltDet);
309 float tilt = tan(TMath::DegToRad() * pad->getTiltingAngle()); // tilt is signed! and returned in degrees
310 float tiltCorrUp = tilt * (mTrackletsCalib[trkltId].getZ() - trk.getZ());
311 float zPosCorrUp = mTrackletsCalib[trkltId].getZ() + mRecoParam.getZCorrCoeffNRC() * trk.getTgl();
312 float padLength = pad->getRowSize(mTrackletsRaw[trkltId].getPadRow());
313 if (!((trk.getSigmaZ2() < (padLength * padLength / 12.f)) && (std::fabs(mTrackletsCalib[trkltId].getZ() - trk.getZ()) < padLength))) {
314 tiltCorrUp = 0.f;
315 }
316
317 std::array<float, 2> trkltPosUp{mTrackletsCalib[trkltId].getY() - tiltCorrUp, zPosCorrUp};
318 std::array<float, 3> trkltCovUp;
319 mRecoParam.recalcTrkltCov(tilt, trk.getSnp(), pad->getRowSize(mTrackletsRaw[trkltId].getPadRow()), trkltCovUp);
320
321 if (!trk.update(trkltPosUp, trkltCovUp)) {
322 LOGF(info, "Failed to update track with space point in layer %i", iLayer);
323 return 1;
324 }
325 return 0;
326}
Wrapper container for different reconstructed object types.
Global TRD definitions and constants.
Definition of the GeometryManager class.
std::ostringstream debug
Definition of the Names Generator class.
Provides information required for TRD calibration which is based on the global tracking.
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
Definition Propagator.h:178
void init(float bz, const GPUSettingsRec *rec=nullptr)
Load parameterization for given magnetic field.
bool addEntry(float deltaAlpha, float impactAngle, int chamberId)
static Geometry * instance()
Definition Geometry.h:33
bool isTrackletFromNoisyMCM(const Tracklet64 &trklt) const
T getValue(int roc, int col, int row) const
void setInput(const o2::globaltracking::RecoContainer &input)
Initialize the input arrays.
int doTrdOnlyTrackFits(gsl::span< const TrackTRD > &tracks)
3-way fit to TRD tracklets
int filldEdx(gsl::span< const TrackTRD > &tracks, bool isTPCTRD)
Collect tracklet charges for given track.
void reset()
Reset the output.
void init()
Load geometry and apply magnetic field setting.
void calculateAngResHistos()
Main processing function for creating angular residual histograms for vDrift and ExB calibration.
bool propagateAndUpdate(TrackTRD &trk, int iLayer, bool doUpdate) const
Extrapolate track parameters to given layer and if requested perform update with tracklet.
GLenum const GLfloat * params
Definition glcorearb.h:272
GLuint id
Definition glcorearb.h:650
int angle2Sector(float phi)
Definition Utils.h:183
float sector2Angle(int sect)
Definition Utils.h:193
constexpr int NLAYER
the number of layers
Definition Constants.h:27
constexpr int NSTACK
the number of stacks per sector
Definition Constants.h:26
constexpr int NBINSGAINCALIB
number of bins in the charge (Q0+Q1+Q2) histogram for gain calibration
Definition Constants.h:79
gsl::span< const o2::trd::CalibratedTracklet > getTRDCalibratedTracklets() const
gsl::span< const o2::trd::Tracklet64 > getTRDTracklets() const
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"