Project
Loading...
Searching...
No Matches
AlignmentTrack.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
16
17#include <cstdio>
19#include "Framework/Logger.h"
23#include "Align/AlignConfig.h"
24#include "Align/utils.h"
25#include <TMatrixD.h>
26#include <TVectorD.h>
27#include <TMatrixDSymEigen.h>
29#include "MathUtils/Utils.h"
30
31#define DEBUG 4
32using namespace o2::align::utils;
33using namespace o2::base;
34using namespace TMath;
35
36namespace o2
37{
38namespace align
39{
40
41// RS: this is not good: we define constants outside the class, but it is to
42// bypass the CINT limitations on static arrays initializations
43const int kRichardsonOrd = 1; // Order of Richardson extrapolation for derivative (min=1)
44const int kRichardsonN = kRichardsonOrd + 1; // N of 2-point symmetric derivatives needed for requested order
45const int kNRDClones = kRichardsonN * 2; // number of variations for derivative of requested order
46
47//____________________________________________________________________________
48void AlignmentTrack::Clear(Option_t*)
49{
50 // reset the track
51 TObject::Clear();
52 ResetBit(0xffffffff);
53 mPoints.clear();
54 mDetPoints.clear();
56 mNDF = 0;
57 mInnerPointID = -1;
58 mNeedInv[0] = mNeedInv[1] = false;
60 //
61}
62
63//____________________________________________________________________________
65{
66 // define varied DOF's (local parameters) for the track:
67 // 1) kinematic params (5 or 4 depending on Bfield)
68 // 2) mult. scattering angles (2)
69 // 3) if requested by point: energy loss
70 //
72 int np = getNPoints();
73 //
74 // the points are sorted in order opposite to track direction -> outer points come 1st,
75 // but for the 2-leg cosmic track the innermost points are in the middle (1st lower leg, then upper one)
76 //
77 // start along track direction, i.e. last point in the ordered array
78 int minPar = mNLocPar;
79 for (int ip = getInnerPointID() + 1; ip--;) { // collision track or cosmic lower leg
80 AlignmentPoint* pnt = getPoint(ip);
81 pnt->setMinLocVarID(minPar);
82 if (pnt->containsMaterial()) {
83 mNLocPar += pnt->getNMatPar();
84 }
85 pnt->setMaxLocVarID(mNLocPar); // flag up to which parameted ID this points depends on
86 }
87 //
88 if (isCosmic()) {
89 minPar = mNLocPar;
90 for (int ip = getInnerPointID() + 1; ip < np; ip++) { // collision track or cosmic lower leg
91 AlignmentPoint* pnt = getPoint(ip);
92 pnt->setMinLocVarID(minPar);
93 if (pnt->containsMaterial()) {
94 mNLocPar += pnt->getNMatPar();
95 }
96 pnt->setMaxLocVarID(mNLocPar); // flag up to which parameted ID this points depends on
97 }
98 }
99 mLocPar.clear();
100 mLocPar.resize(mNLocPar);
101 for (int i = 0; i < 2; i++) {
102 mResid[i].clear();
103 mDResDLoc[i].clear();
104 mResid[i].resize(np);
105 mDResDLoc[i].resize(mNLocPar * np);
106 }
107}
108
109//______________________________________________________
111{
112 // Propagate for given local params and calculate residuals and their derivatives.
113 // The 1st 4 or 5 elements of params vector should be the reference trackParam_t
114 // Then parameters of material corrections for each point
115 // marked as having materials should come (4 or 5 dependending if ELoss is varied or fixed).
116 // They correspond to kink parameters
117 // (trackParam_t_after_material - trackParam_t_before_material)
118 // rotated to frame where they error matrix is diagonal. Their conversion to trackParam_t
119 // increment will be done locally in the applyMatCorr routine.
120 //
121 // If params are not provided, use internal params array
122 //
123 if (!params) {
124 params = mLocPar.data();
125 }
126 //
127 if (!getResidDone()) {
129 }
130 //
131 int np = getNPoints();
132 //
133 const auto& algConf = AlignConfig::Instance();
134 // collision track or cosmic lower leg
136 if (algConf.verbose > 2) {
137 LOG(warn) << "Failed on derivatives calculation 0";
138 }
139 return false;
140 }
141 //
142 if (isCosmic()) { // cosmic upper leg
143 if (!calcResidDeriv(params, mNeedInv[1], getInnerPointID() + 1, np - 1)) {
144 if (algConf.verbose > 2) {
145 LOG(warn) << "Failed on derivatives calculation 0";
146 }
147 }
148 }
149 //
150 setDerivDone();
151 return true;
152}
153
154//______________________________________________________
155bool AlignmentTrack::calcResidDeriv(double* extendedParams, bool invert, int pFrom, int pTo)
156{
157 // Calculate derivatives of residuals vs params for points pFrom to pT. For cosmic upper leg
158 // track parameter may require inversion.
159 // The 1st 4 or 5 elements of params vector should be the reference trackParam_t
160 // Then parameters of material corrections for each point
161 // marked as having materials should come (4 or 5 dependending if ELoss is varied or fixed).
162 // They correspond to kink parameters
163 // (trackParam_t_after_material - trackParam_t_before_material)
164 // rotated to frame where they error matrix is diagonal. Their conversion to trackParam_t
165 // increment will be done locally in the applyMatCorr routine.
166 //
167 // The derivatives are calculated using Richardson extrapolation
168 // (like http://root.cern.ch/root/html/ROOT__Math__RichardsonDerivator.html)
169 //
170 const auto& algConf = AlignConfig::Instance();
171 trackParam_t probD[kNRDClones]; // use this to vary supplied param for derivative calculation
172 double varDelta[kRichardsonN];
173 const int kInvElem[kNKinParBON] = {-1, 1, 1, -1, -1};
174 //
175 const double kDelta[kNKinParBON] = {0.02, 0.02, 0.001, 0.001, 0.01}; // variations for ExtTrackParam and material effects
176 //
177 double delta[kNKinParBON]; // variations of curvature term are relative
178 for (int i = kNKinParBOFF; i--;) {
179 delta[i] = kDelta[i];
180 }
181 if (getFieldON()) {
182 delta[kParQ2Pt] = kDelta[kParQ2Pt] * Abs(getQ2Pt());
183 }
184 //
185 int pinc, signELoss = 0; // RS Validate for cosmic. Propagation is done from inner point to outer one:
186 // energy loss is applied for collision tracks and cosmic lower leg, compensated for cosmic upper leg
187 if (pTo > pFrom) { // fit in points decreasing order: cosmics upper leg
188 pTo++;
189 pinc = 1;
190 signELoss = 1; // eloss is corrected
191 } else { // fit in points increasing order: collision track or cosmics lower leg
192 pTo--;
193 pinc = -1;
194 signELoss = -1; // eloss is applied
195 }
196
197 // 1) derivative wrt trackParam_t parameters
198 for (int ipar = mNLocExtPar; ipar--;) {
199 setParams(probD, kNRDClones, getX(), getAlpha(), extendedParams, true);
200 if (invert) {
201 for (int ic = kNRDClones; ic--;) {
202 probD[ic].invert();
203 }
204 }
205 double del = delta[ipar];
206 //
207 for (int icl = 0; icl < kRichardsonN; icl++) { // calculate kRichardsonN variations with del, del/2, del/4...
208 varDelta[icl] = del;
209 modParam(probD[(icl << 1) + 0], ipar, del);
210 modParam(probD[(icl << 1) + 1], ipar, -del);
211 del *= 0.5;
212 }
213 // propagate varied tracks to each point
214 for (int ip = pFrom; ip != pTo; ip += pinc) { // points are ordered against track direction
215 AlignmentPoint* pnt = getPoint(ip);
216 // we propagate w/o mat. corrections, they will be accounted in applyMatCorr
217 if (!propagateParamToPoint(probD, kNRDClones, pnt, algConf.maxStep, algConf.maxSnp, MatCorrType::USEMatCorrNONE, signELoss)) {
218 return false;
219 }
220 if (!applyMatCorr(probD, kNRDClones, extendedParams, pnt)) {
221 return false;
222 }
223 if (pnt->containsMeasurement()) {
224 int offsDer = ip * mNLocPar + ipar;
225 richardsonDeriv(probD, varDelta, pnt, mDResDLoc[0][offsDer], mDResDLoc[1][offsDer]); // calculate derivatives
226 if (invert && kInvElem[ipar] < 0) {
227 mDResDLoc[0][offsDer] = -mDResDLoc[0][offsDer];
228 mDResDLoc[1][offsDer] = -mDResDLoc[1][offsDer];
229 }
230 }
231 } // loop over points
232 } // loop over ExtTrackParam parameters
233 // 2) now vary material effect related parameters: MS and eventually ELoss
234 for (int ip = pFrom; ip != pTo; ip += pinc) { // points are ordered against track direction
235 AlignmentPoint* pnt = getPoint(ip);
236 // global derivatives at this point
237 if (pnt->containsMeasurement() && !calcResidDerivGlo(pnt)) {
238 if (algConf.verbose > 2) {
239 LOGF(warn, "Failed on global derivatives calculation at point %d", ip);
241 }
242 return false;
243 }
244 //
245 if (!pnt->containsMaterial()) {
246 continue;
247 }
248 //
249 int nParFreeI = pnt->getNMatPar();
250 //
251 // array delta gives desired variation of parameters in trackParam_t definition,
252 // while the variation should be done for parameters in the frame where the vector
253 // of material corrections has diagonal cov. matrix -> rotate the delta to this frame
254 double deltaMatD[kNKinParBON];
255 // pnt->diagMatCorr(delta, deltaMatD);
256 for (int ipar = 0; ipar < nParFreeI; ipar++) {
257 double d = pnt->getMatCorrCov()[ipar];
258 deltaMatD[ipar] = d > 0. ? Sqrt(d) * 5 : delta[ipar];
259 }
260 //
261 // printf("Vary %d [%+.3e %+.3e %+.3e %+.3e] ",ip,deltaMatD[0],deltaMatD[1],deltaMatD[2],deltaMatD[3]); pnt->print();
262
263 int offsI = pnt->getMaxLocVarID() - nParFreeI; // the parameters for this point start with this offset
264 // they are irrelevant for the points upstream
265 for (int ipar = 0; ipar < nParFreeI; ipar++) { // loop over DOFs related to MS and ELoss are point ip
266 double del = deltaMatD[ipar];
267 //
268 // We will vary the tracks starting from the original parameters propagated to given point
269 // and stored there (before applying material corrections for this point)
270 //
271 setParams(probD, kNRDClones, pnt->getXTracking(), pnt->getAlphaSens(), pnt->getTrParamWSB(), false);
272 // no need for eventual track inversion here: if needed, this is already done in ParamWSB
273 //
274 int offsIP = offsI + ipar; // parameter entry in the extendedParams array
275 // printf(" Var:%d (%d) %e\n",ipar,offsIP, del);
276
277 for (int icl = 0; icl < kRichardsonN; icl++) { // calculate kRichardsonN variations with del, del/2, del/4...
278 varDelta[icl] = del;
279 double parOrig = extendedParams[offsIP];
280 extendedParams[offsIP] += del;
281 //
282 // apply varied material effects : incremented by delta
283 if (!applyMatCorr(probD[(icl << 1) + 0], extendedParams, pnt)) {
284 return false;
285 }
286 //
287 // apply varied material effects : decremented by delta
288 extendedParams[offsIP] = parOrig - del;
289 if (!applyMatCorr(probD[(icl << 1) + 1], extendedParams, pnt)) {
290 return false;
291 }
292 //
293 extendedParams[offsIP] = parOrig;
294 del *= 0.5;
295 }
296 if (pnt->containsMeasurement()) { // calculate derivatives at the scattering point itself
297 int offsDerIP = ip * mNLocPar + offsIP;
298 richardsonDeriv(probD, varDelta, pnt, mDResDLoc[0][offsDerIP], mDResDLoc[1][offsDerIP]); // calculate derivatives for ip
299 // printf("DR SELF: %e %e at %d (%d)\n",mDResDLoc[0][offsDerIP], mDResDLoc[1][offsDerIP],offsI, offsDerIP);
300 }
301 //
302 // loop over points whose residuals can be affected by the material effects on point ip
303 for (int jp = ip + pinc; jp != pTo; jp += pinc) {
304 AlignmentPoint* pntJ = getPoint(jp);
305
306 // printf(" DerFor:%d ",jp); pntJ->print();
307
308 if (!propagateParamToPoint(probD, kNRDClones, pntJ, algConf.maxStep, algConf.maxSnp, MatCorrType::USEMatCorrNONE, signELoss)) {
309 return false;
310 }
311 //
312 if (pntJ->containsMaterial()) { // apply material corrections
313 if (!applyMatCorr(probD, kNRDClones, extendedParams, pntJ)) {
314 return false;
315 }
316 }
317 //
318 if (pntJ->containsMeasurement()) {
319 int offsDerJ = jp * mNLocPar + offsIP;
320 // calculate derivatives
321 richardsonDeriv(probD, varDelta, pntJ, mDResDLoc[0][offsDerJ], mDResDLoc[1][offsDerJ]);
322 }
323 //
324 } // << loop over points whose residuals can be affected by the material effects on point ip
325 } // << loop over DOFs related to MS and ELoss are point ip
326 } // << loop over all points of the track
327 //
328 return true;
329}
330
331//______________________________________________________
333{
334 // calculate residuals derivatives over point's sensor and its parents global params
335 double deriv[AlignableVolume::kNDOFGeom * 3];
336 //
337 const AlignableSensor* sens = pnt->getSensor();
338 const AlignableVolume* vol = sens;
339 // precalculated track parameters
340 double snp = pnt->getTrParamWSA(kParSnp), tgl = pnt->getTrParamWSA(kParTgl);
341 // precalculate track slopes to account tracking X variation
342 // these are coeffs to translate deltaX of the point to deltaY and deltaZ of track
343 double cspi = 1. / Sqrt((1 - snp) * (1 + snp)), slpY = snp * cspi, slpZ = tgl * cspi;
344 //
345 pnt->setDGloOffs(mNGloPar); // mark 1st entry of derivatives
346 do {
347 // measurement residuals
348 int nfree = vol->getNDOFsFree();
349 if (!nfree) {
350 continue;
351 } // no free parameters?
352 sens->dPosTraDParGeom(pnt, deriv, vol == sens ? nullptr : vol);
353 //
354 checkExpandDerGloBuffer(mNGloPar + nfree); // if needed, expand derivatives buffer
355 //
356 for (int ip = 0; ip < AlignableVolume::kNDOFGeom; ip++) { // we need only free parameters
357 if (!vol->isFreeDOF(ip)) {
358 continue;
359 }
360 double* dXYZ = &deriv[ip * 3]; // tracking XYZ derivatives over this parameter
361 // residual is defined as diagonalized track_estimate - measured Y,Z in tracking frame
362 // where the track is evaluated at measured X!
363 // -> take into account modified X using track parameterization at the point (paramWSA)
364 // Attention: small simplifications(to be checked if it is ok!!!):
365 // effect of changing X is accounted neglecting track curvature to preserve linearity
366 //
367 // store diagonalized residuals in track buffer
369 (dXYZ[AlignmentPoint::kX] * slpZ - dXYZ[AlignmentPoint::kZ]),
371 // and register global ID of varied parameter
372 mGloParID[mNGloPar] = vol->getParGloID(ip);
373 mNGloPar++;
374 }
375 //
376 } while ((vol = vol->getParent()));
377 //
378 // eventual detector calibration parameters
379 const AlignableDetector* det = sens->getDetector();
380 int ndof = 0;
381 if (det && (ndof = det->getNCalibDOFs())) {
382 // if needed, expand derivatives buffer
384 for (int idf = 0; idf < ndof; idf++) {
385 if (!det->isFreeDOF(idf)) {
386 continue;
387 }
388 sens->dPosTraDParCalib(pnt, deriv, idf, nullptr);
389 pnt->diagonalizeResiduals((deriv[AlignmentPoint::kX] * slpY - deriv[AlignmentPoint::kY]),
390 (deriv[AlignmentPoint::kX] * slpZ - deriv[AlignmentPoint::kZ]),
392 // and register global ID of varied parameter
393 mGloParID[mNGloPar] = det->getParGloID(idf);
394 mNGloPar++;
395 }
396 }
397 //
398 pnt->setNGloDOFs(mNGloPar - pnt->getDGloOffs()); // mark number of global derivatives filled
399 //
400 return true;
401}
402
403//______________________________________________________
404bool AlignmentTrack::calcResiduals(const double* extendedParams)
405{
406 // Propagate for given local params and calculate residuals
407 // The 1st 4 or 5 elements of extendedParams vector should be the reference trackParam_t
408 // Then parameters of material corrections for each point
409 // marked as having materials should come (4 or 5 dependending if ELoss is varied or fixed).
410 // They correspond to kink parameters
411 // (trackParam_t_after_material - trackParam_t_before_material)
412 // rotated to frame where they error matrix is diagonal. Their conversion to trackParam_t
413 // increment will be done locally in the applyMatCorr routine.
414 //
415 // If extendedParams are not provided, use internal extendedParams array
416 //
417 if (!extendedParams) {
418 extendedParams = mLocPar.data();
419 }
420 int np = getNPoints();
421 mChi2 = 0;
422 mNDF = 0;
423 //
424 const auto& algConf = AlignConfig::Instance();
425 // collision track or cosmic lower leg
426 if (!calcResiduals(extendedParams, mNeedInv[0], getInnerPointID(), 0)) {
427 if (algConf.verbose > 2) {
428 LOG(warn) << "Failed on residuals calculation 0";
429 }
430 return false;
431 }
432 //
433 if (isCosmic()) { // cosmic upper leg
434 if (!calcResiduals(extendedParams, mNeedInv[1], getInnerPointID() + 1, np - 1)) {
435 if (algConf.verbose > 2) {
436 LOG(warn) << "Failed on residuals calculation 1";
437 }
438 return false;
439 }
440 }
441 //
442 mNDF -= mNLocExtPar;
443 setResidDone();
444 return true;
445}
446
447//______________________________________________________
448bool AlignmentTrack::calcResiduals(const double* extendedParams, bool invert, int pFrom, int pTo)
449{
450 // Calculate residuals for the single leg from points pFrom to pT
451 // The 1st 4 or 5 elements of extendedParams vector should be corrections to
452 // the reference trackParam_t
453 // Then parameters of material corrections for each point
454 // marked as having materials should come (4 or 5 dependending if ELoss is varied or fixed).
455 // They correspond to kink parameters
456 // (trackParam_t_after_material - trackParam_t_before_material)
457 // rotated to frame where they error matrix is diagonal. Their conversion to trackParam_t
458 // increment will be done locally in the applyMatCorr routine.
459 //
460 trackParam_t probe;
461 setParams(probe, getX(), getAlpha(), extendedParams, true);
462 if (invert) {
463 probe.invert();
464 }
465 int pinc, signELoss = 0; // RS Validate for cosmic. Propagation is done from inner point to outer one:
466 // energy loss is applied for collision tracks and cosmic lower leg, compensated for cosmic upper leg
467 if (pTo > pFrom) { // fit in points decreasing order: cosmics upper leg
468 pTo++;
469 pinc = 1;
470 signELoss = 1; // eloss is corrected
471 } else { // fit in points increasing order: collision track or cosmics lower leg
472 pTo--;
473 pinc = -1;
474 signELoss = -1; // eloss is applied
475 }
476 //
477 const auto& algConf = AlignConfig::Instance();
478 for (int ip = pFrom; ip != pTo; ip += pinc) { // points are ordered against track direction:
479 AlignmentPoint* pnt = getPoint(ip);
480 if (!propagateParamToPoint(probe, pnt, algConf.maxStep, algConf.maxSnp, MatCorrType::USEMatCorrNONE, signELoss)) {
481 return false;
482 }
483 //
484 // store the current track kinematics at the point BEFORE applying eventual material
485 // corrections. This kinematics will be later varied around supplied parameters (in the calcResidDeriv)
486 pnt->setTrParamWSB(probe.getParams());
487 // account for materials
488 if (!applyMatCorr(probe, extendedParams, pnt)) {
489 return false;
490 }
491 pnt->setTrParamWSA(probe.getParams());
492 //
493 if (pnt->containsMeasurement()) { // need to calculate residuals in the frame where errors are orthogonal
494 pnt->getResidualsDiag(probe.getParams(), mResid[0][ip], mResid[1][ip]);
495 mChi2 += mResid[0][ip] * mResid[0][ip] / pnt->getErrDiag(0);
496 mChi2 += mResid[1][ip] * mResid[1][ip] / pnt->getErrDiag(1);
497 mNDF += 2;
498 }
499 //
500 if (pnt->containsMaterial()) {
501 // material degrees of freedom do not contribute to NDF since they are constrained by 0 expectation
502 int nCorrPar = pnt->getNMatPar();
503 const float* corCov = pnt->getMatCorrCov(); // correction diagonalized covariance
504 auto offs = pnt->getMaxLocVarID() - nCorrPar;
505 for (int i = 0; i < nCorrPar; i++) {
506 mChi2 += mLocPar[offs + i] * mLocPar[offs + i] / corCov[i];
507 }
508 }
509 }
510 return true;
511}
512
513//______________________________________________________
514bool AlignmentTrack::propagateParamToPoint(trackParam_t* tr, int nTr, const AlignmentPoint* pnt, double maxStep, double maxSnp, MatCorrType mt, int signCorr)
515{
516 // Propagate set of tracks to the point (only parameters, no error matrix)
517 // VECTORIZE this
518 //
519 const auto& algConf = AlignConfig::Instance();
520 for (int itr = nTr; itr--;) {
521 if (!propagateParamToPoint(tr[itr], pnt, maxStep, maxSnp, mt, signCorr)) {
522 if (algConf.verbose > 2) {
523 LOG(error) << "Failed on clone " << itr << " propagation ";
524 tr[itr].print();
526 }
527 return false;
528 }
529 }
530 return true;
531}
532
533//______________________________________________________
534bool AlignmentTrack::propagateParamToPoint(trackParam_t& tr, const AlignmentPoint* pnt, double maxStep, double maxSnp, MatCorrType mt, int signCorr)
535{
536 // propagate tracks to the point (only parameters, no error matrix)
537 return propagate(tr, pnt, maxStep, maxSnp, mt, nullptr, signCorr);
538}
539
540//______________________________________________________
541bool AlignmentTrack::propagateToPoint(trackParam_t& tr, const AlignmentPoint* pnt, double maxStep, double maxSnp, MatCorrType mt, track::TrackLTIntegral* tLT, int signCorr)
542{
543 // propagate tracks to the point. If matCor is true, then material corrections will be applied.
544 // if matPar pointer is provided, it will be filled by total x2x0 and signed xrho
545 return propagate(tr, pnt, maxStep, maxSnp, mt, tLT, signCorr);
546}
547
548bool AlignmentTrack::propagate(trackParam_t& track, const AlignmentPoint* pnt, double maxStep, double maxSnp, MatCorrType mt, track::TrackLTIntegral* tLT, int signCorr)
549{
550 if (signCorr == 0) { // auto
551 // calculate the sign of the energy loss correction and ensure the upper leg of cosmics is calculated correctly.
552 double dx = pnt->getXTracking() - track.getX();
553 int dir = dx > 0.f ? 1 : -1;
554 signCorr = pnt->isInvDir() ? dir : -dir; // propagation along the track direction should have signCorr=-1
555 }
556 // do propagation in at least 2 step to reveal eventual effect of MS on the position
557 return PropagatorD::Instance()->propagateToAlphaX(track, pnt->getAlphaSens(), pnt->getXTracking(), pnt->getUseBzOnly(), maxSnp, maxStep, 2, mt, tLT, signCorr);
558}
559
560/*
561//______________________________________________________
562bool AlignmentTrack::ApplyMS(trackParam_t& trPar, double tms,double pms)
563{
564 //------------------------------------------------------------------------------
565 // Modify track par (e.g. trackParam_t) in the tracking frame
566 // (dip angle lam, az. angle phi)
567 // by multiple scattering defined by polar and azumuthal scattering angles in
568 // the track collinear frame (tms and pms resp).
569 // The updated direction vector in the tracking frame becomes
570 //
571 // | Cos[lam]*Cos[phi] Cos[phi]*Sin[lam] -Sin[phi] | | Cos[tms] |
572 // | Cos[lam]*Sin[phi] Sin[lam]*Sin[phi] Cos[phi] | x | Cos[pms]*Sin[tms]|
573 // | Sin[lam] -Cos[lam] 0 | | Sin[pms]*Sin[tms]|
574 //
575 //------------------------------------------------------------------------------
576 //
577 double *par = (double*) trPar.GetParameter();
578 //
579 if (Abs(tms)<1e-7) return true;
580 //
581 double snTms = Sin(tms), csTms = Cos(tms);
582 double snPms = Sin(pms), csPms = Cos(pms);
583 double snPhi = par[2], csPhi = Sqrt((1.-snPhi)*(1.+snPhi));
584 double csLam = 1./Sqrt(1.+par[3]*par[3]), snLam = csLam*par[3];
585 //
586 double r00 = csLam*csPhi, r01 = snLam*csPhi, &r02 = snPhi;
587 double r10 = csLam*snPhi, r11 = snLam*snPhi, &r12 = csPhi;
588 double &r20 = snLam ,&r21 = csLam;
589 //
590 double &v0 = csTms, v1 = snTms*csPms, v2 = snTms*snPms;
591 //
592 double px = r00*v0 + r01*v1 - r02*v2;
593 double py = r10*v0 + r11*v1 + r12*v2;
594 double pz = r20*v0 - r21*v1;
595 //
596 double pt = Sqrt(px*px + py*py);
597 par[2] = py/pt;
598 par[3] = pz/pt;
599 par[4]*= csLam/pt;
600 //
601 return true;
602}
603*/
604
605//______________________________________________________
606bool AlignmentTrack::applyMatCorr(trackParam_t& trPar, const double* corrPar, const AlignmentPoint* pnt)
607{
608 // Modify track param (e.g. trackParam_t) in the tracking frame
609 // by delta accounting for material effects
610 // Note: corrPar contains delta to track parameters rotated by the matrix
611 // DIAGONALIZING ITS COVARIANCE MATRIX!
612 // transform parameters from the frame diagonalizing the errors to track frame
613 double corr[kNKinParBON] = {0};
614 if (pnt->containsMaterial()) { // are there free params from materials?
615 int nCorrPar = pnt->getNMatPar();
616 const double* corrDiag = &corrPar[pnt->getMaxLocVarID() - nCorrPar]; // material corrections for this point start here
617 pnt->unDiagMatCorr(corrDiag, corr); // this is to account for MS and RANDOM Eloss (if varied)
618 }
619 // to this we should add expected parameters modification due to the deterministic eloss
620 float* detELoss = pnt->getMatCorrExp();
621 for (int i = kNKinParBON; i--;) {
622 corr[i] += detELoss[i];
623 }
624 //corr[kParQ2Pt] += detELoss[kParQ2Pt];
625 // printf("apply corr UD %+.3e %+.3e %+.3e %+.3e %+.3e\n",corr[0],corr[1],corr[2],corr[3],corr[4]);
626 // printf(" corr D %+.3e %+.3e %+.3e %+.3e\n",corrDiag[0],corrDiag[1],corrDiag[2],corrDiag[3]);
627 // printf("at point :"); pnt->print();
628 return applyMatCorr(trPar, corr);
629 //
630}
631
632//______________________________________________________
633bool AlignmentTrack::applyMatCorr(trackParam_t& trPar, const double* corr)
634{
635 // Modify track param (e.g. trackParam_t) in the tracking frame
636 // by delta accounting for material effects
637 // Note: corr contains delta to track frame, NOT in diagonalized one
638 const double snp = trPar.getSnp() + corr[kParSnp];
639 const auto& algConf = AlignConfig::Instance();
640 if (Abs(snp) > algConf.maxSnp) {
641 if (algConf.verbose > 2) {
642 LOG(error) << "Snp is too large: " << snp;
643 printf("DeltaPar: ");
644 for (int i = 0; i < kNKinParBON; i++) {
645 printf("%+.3e ", corr[i]);
646 }
647 printf("\n");
648 trPar.print();
649 }
650 return false;
651 }
652
653 trPar.updateParams(corr);
654
655 return true;
656}
657
658//______________________________________________________
659bool AlignmentTrack::applyMatCorr(trackParam_t* trSet, int ntr, const double* corrDiag, const AlignmentPoint* pnt)
660{
661 // Modify set of track params (e.g. trackParam_t) in the tracking frame
662 // by delta accounting for material effects
663 // Note: corrDiag contain delta to track parameters rotated by the matrix DIAGONALIZING ITS
664 // COVARIANCE MATRIX
665 // transform parameters from the frame diagonalizing the errors to track frame
666 const auto& algConf = AlignConfig::Instance();
667 double corr[kNKinParBON] = {0};
668 if (pnt->containsMaterial()) { // are there free params from materials?
669 int nCorrPar = pnt->getNMatPar();
670 const double* corrDiagP = &corrDiag[pnt->getMaxLocVarID() - nCorrPar]; // material corrections for this point start here
671 pnt->unDiagMatCorr(corrDiagP, corr);
672 }
673 float* detELoss = pnt->getMatCorrExp();
674 for (int i = kNKinParBON; i--;) {
675 corr[i] += detELoss[i];
676 }
677 // if (!pnt->getELossVaried()) corr[kParQ2Pt] = pnt->getMatCorrExp()[kParQ2Pt]; // fixed eloss expected effect
678 // printf("apply corr UD %+.3e %+.3e %+.3e %+.3e\n",corr[0],corr[1],corr[2],corr[3]);
679 // printf(" corr D %+.3e %+.3e %+.3e %+.3e\n",corrDiagP[0],corrDiagP[1],corrDiagP[2],corrDiagP[3]);
680 // printf("at point :"); pnt->print();
681 //
682 for (int itr = ntr; itr--;) {
683 if (!applyMatCorr(trSet[itr], corr)) {
684 if (algConf.verbose > 2) {
685 LOGP(error, "Failed on clone {} materials", itr);
686 trSet[itr].print();
687 }
688 return false;
689 }
690 }
691 return true;
692}
693
694//______________________________________________
695double AlignmentTrack::richardsonExtrap(double* val, int ord)
696{
697 // Calculate Richardson extrapolation of order ord (starting from 1)
698 // The array val should contain estimates ord+1 of derivatives with variations
699 // d, d/2 ... d/2^ord.
700 // The array val is overwritten
701 //
702 if (ord == 1) {
703 return (4. * val[1] - val[0]) * (1. / 3);
704 }
705 do {
706 for (int i = 0; i < ord; i++) {
707 val[i] = (4. * val[i + 1] - val[i]) * (1. / 3);
708 }
709 } while (--ord);
710 return val[0];
711}
712
713//______________________________________________
714double AlignmentTrack::richardsonExtrap(const double* val, int ord)
715{
716 // Calculate Richardson extrapolation of order ord (starting from 1)
717 // The array val should contain estimates ord+1 of derivatives with variations
718 // d, d/2 ... d/2^ord.
719 // The array val is not overwritten
720 //
721 if (ord == 1) {
722 return (4. * val[1] - val[0]) * (1. / 3);
723 }
724 double* buff = new double[ord + 1];
725 memcpy(buff, val, (ord + 1) * sizeof(double));
726 do {
727 for (int i = 0; i < ord; i++) {
728 buff[i] = (4. * buff[i + 1] - buff[i]) * (1. / 3);
729 }
730 } while (--ord);
731 return buff[0];
732}
733
734//______________________________________________
735void AlignmentTrack::richardsonDeriv(const trackParam_t* trSet, const double* delta, const AlignmentPoint* pnt, double& derY, double& derZ)
736{
737 // Calculate Richardson derivatives for diagonalized Y and Z from a set of kRichardsonN pairs
738 // of tracks with same parameter of i-th pair varied by +-delta[i]
739 static double derRichY[kRichardsonN], derRichZ[kRichardsonN];
740 //
741 for (int icl = 0; icl < kRichardsonN; icl++) { // calculate kRichardsonN variations with del, del/2, del/4...
742 double resYVP = 0, resYVN = 0, resZVP = 0, resZVN = 0;
743 pnt->getResidualsDiag(trSet[(icl << 1) + 0].getParams(), resYVP, resZVP); // variation with +delta
744 pnt->getResidualsDiag(trSet[(icl << 1) + 1].getParams(), resYVN, resZVN); // variation with -delta
745 derRichY[icl] = 0.5 * (resYVP - resYVN) / delta[icl]; // 2-point symmetric derivatives
746 derRichZ[icl] = 0.5 * (resZVP - resZVN) / delta[icl];
747 }
748 derY = richardsonExtrap(derRichY, kRichardsonOrd); // dY/dPar
749 derZ = richardsonExtrap(derRichZ, kRichardsonOrd); // dZ/dPar
750 if (TMath::IsNaN(derY) || TMath::IsNaN(derZ)) {
751 LOGP(error, "NAN encounterd: DerY {} : DerZ {}", derY, derZ);
752 }
753 //
754}
755
756//______________________________________________
757void AlignmentTrack::Print(Option_t* opt) const
758{
759 // print track data
760 printf("%s ", isCosmic() ? " Cosmic " : "Collision ");
761 trackParam_t::print();
762 printf("N Free Par: %d (Kinem: %d) | Npoints: %d (Inner:%d) | Chi2Ini:%.1f Chi2: %.1f/%d",
764 if (isCosmic()) {
765 int npLow = getInnerPointID();
766 int npUp = getNPoints() - npLow - 1;
767 printf(" [Low:%.1f/%d Up:%.1f/%d]", mChi2CosmDn, npLow, mChi2CosmUp, npUp);
768 }
769 printf("\n");
770 //
771 TString optS = opt;
772 optS.ToLower();
773 bool res = optS.Contains("r") && getResidDone();
774 bool der = optS.Contains("d") && getDerivDone();
775 bool par = optS.Contains("lc"); // local param corrections
776 bool paru = optS.Contains("lcu"); // local param corrections in track param frame
777 //
778 if (par) {
779 printf("Ref.track corr: ");
780 for (int i = 0; i < mNLocExtPar; i++) {
781 printf("%+.3e ", mLocPar[i]);
782 }
783 printf("\n");
784 }
785 //
786 if (optS.Contains("p") || res || der) {
787 for (int ip = 0; ip < getNPoints(); ip++) {
788 printf("#%3d ", ip);
789 auto* pnt = getPoint(ip);
790 pnt->print(AlignmentPoint::kMeasurementBit); // RS FIXME OPT
791 //
792 if (res && pnt->containsMeasurement()) {
793 printf(" Residuals : %+.3e %+.3e -> Pulls: %+7.2f %+7.2f\n",
794 getResidual(0, ip), getResidual(1, ip),
795 getResidual(0, ip) / sqrt(pnt->getErrDiag(0)), getResidual(1, ip) / sqrt(pnt->getErrDiag(1)));
796 }
797 if (der && pnt->containsMeasurement()) {
798 for (int ipar = 0; ipar < mNLocPar; ipar++) {
799 printf(" Dres/dp%03d : %+.3e %+.3e\n", ipar, getDResDLoc(0, ip)[ipar], getDResDLoc(1, ip)[ipar]);
800 }
801 }
802 //
803 if (par && pnt->containsMaterial()) { // material corrections
804 int nCorrPar = pnt->getNMatPar();
805 printf(" Corr.Diag: ");
806 for (int i = 0; i < nCorrPar; i++) {
807 printf("%+.3e ", mLocPar[i + pnt->getMaxLocVarID() - nCorrPar]);
808 }
809 printf("\n");
810 printf(" Corr.Pull: ");
811 const float* corCov = pnt->getMatCorrCov(); // correction covariance
812 // const float *corExp = pnt->getMatCorrExp(); // correction expectation
813 for (int i = 0; i < nCorrPar; i++) {
814 printf("%+.3e ", (mLocPar[i + pnt->getMaxLocVarID() - nCorrPar] /* - corExp[i]*/) / Sqrt(corCov[i]));
815 }
816 printf("\n");
817 if (paru) { // print also mat.corrections in track frame
818 double corr[5] = {0};
819 pnt->unDiagMatCorr(&mLocPar[pnt->getMaxLocVarID() - nCorrPar], corr);
820 // if (!pnt->getELossVaried()) corr[kParQ2Pt] = pnt->getMatCorrExp()[kParQ2Pt]; // fixed eloss expected effect
821 printf(" Corr.Track: ");
822 for (int i = 0; i < kNKinParBON; i++) {
823 printf("%+.3e ", corr[i]);
824 }
825 printf("\n");
826 }
827 }
828 }
829 } // print points
830}
831
832//______________________________________________
834{
835 // print various coordinates for inspection
836 printf("gpx/D:gpy/D:gpz/D:gtxb/D:gtyb/D:gtzb/D:gtxa/D:gtya/D:gtza/D:alp/D:px/D:py/D:pz/D:tyb/D:tzb/D:tya/D:tza/D:ey/D:ez/D\n");
837 for (int ip = 0; ip < getNPoints(); ip++) {
838 auto* pnt = getPoint(ip);
839 if (!pnt->containsMeasurement()) {
840 continue;
841 }
842 pnt->dumpCoordinates();
843 }
844}
845
846//______________________________________________
848{
849 // perform initial fit of the track
850 //
851 const auto& algConf = AlignConfig::Instance();
852 if (!getFieldON()) { // for field-off data impose nominal momentum
853 setQ2Pt(isCosmic() ? 1. / algConf.defPTB0Cosm : 1. / algConf.defPTB0Coll);
854 }
855 trackParam_t trc(*(trackParam_t*)this);
857 //
858 // the points are ranged from outer to inner for collision tracks,
859 // and from outer point of lower leg to outer point of upper leg for the cosmic track
860 //
861 // the fit will always start from the outgoing track in inward direction
862 if (!fitLeg(trc, 0, getInnerPointID(), mNeedInv[0])) {
863 if (algConf.verbose > 2) {
864 LOG(warn) << "Failed fitLeg 0";
865 trc.print();
866 }
867 return false; // collision track or cosmic lower leg
868 }
869 //
870 // printf("Lower leg: %d %d\n",0,getInnerPointID()); trc.print();
871 //
872 if (isCosmic()) {
874 trackParam_t trcU = trc;
875 if (!fitLeg(trcU, getNPoints() - 1, getInnerPointID() + 1, mNeedInv[1])) { //fit upper leg of cosmic track
876 if (algConf.verbose > 2) {
877 LOG(warn) << "Failed fitLeg 1";
878 trc.print();
879 }
880 return false; // collision track or cosmic lower leg
881 }
882 //
883 // propagate to reference point, which is the inner point of lower leg
884 const AlignmentPoint* refP = getPoint(getInnerPointID());
885 if (!propagateToPoint(trcU, refP, algConf.maxStep, algConf.maxSnp, MatCorrType(algConf.matCorType), nullptr, -1)) { // moving along the track: energy is lost
886 return false;
887 }
888 //
890 // printf("Upper leg: %d %d\n",getInnerPointID()+1,getNPoints()-1); trcU.print();
891 //
892 if (!combineTracks(trc, trcU)) {
893 return false;
894 }
895 //printf("Combined\n"); trc.print();
896 }
897 copyFrom(&trc);
898 //
899 mChi2Ini = mChi2;
900 return true;
901}
902
903//______________________________________________
905{
906 // Assign to trcL the combined tracks (Kalman update of trcL by trcU)
907 // The trcL and trcU MUST be defined at same X,Alpha
908 //
909 // Update equations: tracks described by vectors vL and vU and coviriances CL and CU resp.
910 // then the gain matrix K = CL*(CL+CU)^-1
911 // Updated vector and its covariance:
912 // CL' = CL - K*CL
913 // vL' = vL + K(vU-vL)
914 //
915 const auto& algConf = AlignConfig::Instance();
916 if (Abs(trcL.getX() - trcU.getX()) > TinyDist || Abs(trcL.getAlpha() - trcU.getAlpha()) > TinyDist) {
917 if (algConf.verbose > 2) {
918 LOG(error) << "Tracks must be defined at same reference X and Alpha";
919 trcL.print();
920 trcU.print();
921 }
922 return false;
923 }
924 //
925 LOGP(debug, "CosmDn: {}", trcL.asString());
926 LOGP(debug, "CosmUp: {}", trcU.asString());
927 float dsnp = trcL.getSnp() - trcU.getSnp(), dTgl = trcL.getTgl() - trcU.getTgl();
928 if (std::abs(dsnp) > algConf.cosmMaxDSnp || std::abs(dTgl) > algConf.cosmMaxDTgl) {
929 if (algConf.verbose > 2) {
930 LOGP(error, "Rejecting track with dSnp={} dTgl={}", dsnp, dTgl);
931 LOGP(error, "CosmDn: {}", trcL.asString());
932 LOGP(error, "CosmUp: {}", trcU.asString());
933 }
934 return false;
935 }
936 // const covMat_t& covU = trcU.getCov();
937 // const covMat_t& covL = trcL.getCov();
938 //
939 int mtSize = getFieldON() ? kNKinParBON : kNKinParBOFF;
940 TMatrixD matCL(mtSize, mtSize), matCLplCU(mtSize, mtSize);
941 TVectorD vl(mtSize), vUmnvL(mtSize);
942 //
943 // trcL.print();
944 // trcU.print();
945 //
946 for (int i = mtSize; i--;) {
947 vUmnvL[i] = trcU.getParam(i) - trcL.getParam(i); // y = residual of 2 tracks
948 vl[i] = trcL.getParam(i);
949 for (int j = i + 1; j--;) {
950 int indIJ = ((i * (i + 1)) >> 1) + j; // position of IJ cov element in the trackParam_t covariance array
951 matCL(i, j) = matCL(j, i) = trcL.getCovarElem(i, j);
952 matCLplCU(i, j) = matCLplCU(j, i) = trcL.getCovarElem(i, j) + trcU.getCovarElem(i, j);
953 }
954 }
955 matCLplCU.Invert(); // S^-1 = (Cl + Cu)^-1
956 if (!matCLplCU.IsValid()) {
957 if (algConf.verbose > 2) {
958 LOG(error) << "Failed to invert summed cov.matrix of cosmic track";
959 matCLplCU.Print();
960 }
961 return false; // inversion failed
962 }
963 TMatrixD matK(matCL, TMatrixD::kMult, matCLplCU); // gain K = Cl*(Cl+Cu)^-1
964 TMatrixD matKdotCL(matK, TMatrixD::kMult, matCL); // K*Cl
965 TVectorD vlUp = matK * vUmnvL; // K*(vl - vu)
966 for (int i = mtSize; i--;) {
967 trcL.updateParam(vlUp[i], i); // updated param: vL' = vL + K(vU-vL)
968 for (int j = i + 1; j--;) {
969 trcL.updateCov(-matKdotCL(i, j), i, j);
970 } // updated covariance: Cl' = Cl - K*Cl
971 }
972 //
973 // update chi2
974 double chi2 = 0;
975 for (int i = mtSize; i--;) {
976 for (int j = mtSize; j--;) {
977 chi2 += matCLplCU(i, j) * vUmnvL[i] * vUmnvL[j];
978 }
979 }
980 mChi2 += chi2;
981 //
982 LOGP(debug, "CosmCB: {}", trcL.asString());
983 LOGP(debug, "Combined: Chi2Tot:{} ChiUp:{} ChiDn:{} ChiCmb:{} DSnp:{} DTgl:{} Alp:{}", mChi2, mChi2CosmUp, mChi2CosmDn, chi2, dsnp, dTgl, trcL.getAlpha());
984
985 return true;
986}
987
988//______________________________________________
989bool AlignmentTrack::fitLeg(trackParam_t& trc, int pFrom, int pTo, bool& inv)
990{
991 // perform initial fit of the track
992 // the fit will always start from the outgoing track in inward direction (i.e. if cosmics - bottom leg)
993 const int kMinNStep = 3;
994 const double kErrSpace = 50.;
995 const double kErrAng = 0.8;
996 const double kErrRelPtI = 1.;
997 const covMat_t kIniErr{// initial error
998 kErrSpace * kErrSpace,
999 0, kErrSpace * kErrSpace,
1000 0, 0, kErrAng * kErrAng,
1001 0, 0, 0, kErrAng * kErrAng,
1002 0, 0, 0, 0, kErrRelPtI * kErrRelPtI};
1003 //
1004 static int count = 0;
1005 const auto& algConf = AlignConfig::Instance();
1006 if (algConf.verbose > 2) {
1007 LOGP(info, "FIT COUNT {}", count++);
1008 }
1009 // prepare seed at outer point
1010 AlignmentPoint* p0 = getPoint(pFrom);
1011 double phi = trc.getPhi(), alp = p0->getAlphaSens();
1014 double dphi = math_utils::detail::deltaPhiSmall(phi, alp); // abs delta angle
1015 if (dphi > Pi() / 2.) { // need to invert the track to new frame
1016 inv = true;
1017 trc.invert();
1018 }
1019 // Fit is done from outward to inward: normally against the track direction (hence e.loss is compensated) unless inversion is requested (cosmic upper leg)
1020 if (!propagateParamToPoint(trc, p0, algConf.maxStep, algConf.maxSnp, MatCorrType(algConf.matCorType), -1)) {
1021 if (algConf.verbose > 2) {
1022 LOGF(warn, "Failed on PropagateParamOnlyTo to %f", p0->getXTracking());
1023 trc.print();
1024 }
1025 return false;
1026 }
1027 trc.setCov(kIniErr);
1028 trc.setCov(16 * trc.getQ2Pt() * trc.getQ2Pt(), 4, 4); // lowest diagonal element (Q2Pt2)
1029 //
1030 int pinc, signELoss = 0; // RS Validate for cosmic. Propagation is done from inner point to outer one:
1031 // energy loss is applied for collision tracks and cosmic lower leg, compensated for cosmic upper leg
1032 if (pTo > pFrom) { // fit in points increasing order: collision track or cosmics lower leg
1033 pTo++;
1034 pinc = 1;
1035 signELoss = 1; // e.loss is compensated
1036 } else { // fit in points decreasing order: cosmics upper leg
1037 pTo--;
1038 pinc = -1;
1039 signELoss = -1; // e.loass is applied
1040 }
1041 //
1042 int pntCnt = 0;
1043 for (int ip = pFrom; ip != pTo; ip += pinc) { // inward fit from outer point
1044 AlignmentPoint* pnt = getPoint(ip);
1045 if (!propagateToPoint(trc, pnt, algConf.maxStep, algConf.maxSnp, MatCorrType(algConf.matCorType), nullptr, signELoss)) { // against track direction : e.loss is compensated
1046 if (algConf.verbose > 2) {
1047 LOGF(warn, "Failed on propagateToPoint %d (%d : %d) %f", ip, pFrom, pTo, pnt->getXTracking());
1048 trc.print();
1049 }
1050 return false;
1051 }
1052 if (pnt->containsMeasurement()) {
1053 if (pnt->getNeedUpdateFromTrack()) {
1054 pnt->updatePointByTrackInfo(&trc);
1055 }
1056 const double* yz = pnt->getYZTracking();
1057 const double* errYZ = pnt->getYZErrTracking();
1058 double chi = trc.getPredictedChi2(yz, errYZ);
1059 if (!trc.update(yz, errYZ)) {
1060 if (algConf.verbose > 2) {
1061 LOGF(warn, "Failed on Update %f,%f {%f,%f,%f}", yz[0], yz[1], errYZ[0], errYZ[1], errYZ[2]);
1062 trc.print();
1063 }
1064 return false;
1065 }
1066 mChi2 += chi;
1067 pntCnt++;
1068 }
1069 }
1070 //
1071 if (inv) {
1072 trc.invert();
1073 }
1074 if (algConf.verbose > 2) {
1075 LOGP(info, "Fitted leg with {} points, chi2: {}", pntCnt, mChi2);
1076 }
1077 //
1078 return true;
1079}
1080
1081//______________________________________________
1083{
1084 // calculate residuals from bi-directional Kalman smoother
1085 // ATTENTION: this method modifies workspaces of the points!!!
1086 //
1087 bool inv = false;
1088 const int kMinNStep = 3;
1089 const double kErrSpace = 100.;
1090 const double kErrAng = 0.7;
1091 const double kErrRelPtI = 1.;
1092 const covMat_t kIniErr = {// initial error
1093 kErrSpace * kErrSpace,
1094 0, kErrSpace * kErrSpace,
1095 0, 0, kErrAng * kErrAng,
1096 0, 0, 0, kErrAng * kErrAng,
1097 0, 0, 0, 0, kErrRelPtI * kErrRelPtI};
1098 // const double kOverShootX = 5;
1099 //
1100 trackParam_t trc = *this;
1101 const auto& algConf = AlignConfig::Instance();
1102 int pID = 0, nPnt = getNPoints();
1103 AlignmentPoint* pnt = nullptr;
1104 // get 1st measured point
1105 while (pID < nPnt && !(pnt = getPoint(pID))->containsMeasurement()) { // points are ordered from outward to inward
1106 pID++;
1107 }
1108 if (!pnt) {
1109 return false;
1110 }
1111 double phi = trc.getPhi(), alp = pnt->getAlphaSens();
1114 double dphi = math_utils::detail::deltaPhiSmall(phi, alp);
1115 if (dphi > Pi() / 2.) { // need to invert the track to new frame
1116 inv = true;
1117 trc.invert();
1118 }
1119 // prepare track seed at 1st outermost valid point
1120 if (!propagateParamToPoint(trc, pnt, algConf.maxStep, algConf.maxSnp, MatCorrType::USEMatCorrNONE, 1)) {
1121 if (algConf.verbose > 2) {
1122 LOG(warn) << "Failed on propagateParamToPoint";
1123 trc.print();
1125 }
1126 return false;
1127 }
1128 //
1129 trc.setCov(kIniErr);
1130 const double inwardQ2Pt2 = 4 * trc.getCovarElem(4, 4) * trc.getQ2Pt() * trc.getQ2Pt();
1131 trc.setCov(inwardQ2Pt2, 4, 4); // lowest diagonal element (Q2Pt2)
1132 //
1133 double chifwd = 0, chibwd = 0;
1134 // inward fit
1135 int signELoss = 1; // normally inward fit goes against track direction: eloss is compensated. // RS Check for cosmic
1136 for (int ip = pID; ip < nPnt; ip++) {
1137 pnt = getPoint(ip);
1138 if (pnt->isInvDir() != inv) { // crossing point where the track should be inverted?
1139 trc.invert();
1140 inv = !inv;
1141 }
1142 if (!propagateToPoint(trc, pnt, algConf.maxStep, algConf.maxSnp, MatCorrType(algConf.matCorType), nullptr, signELoss)) {
1143 return false;
1144 }
1145 if (!pnt->containsMeasurement()) {
1146 continue;
1147 }
1148 const double* yz = pnt->getYZTracking();
1149 const double* errYZ = pnt->getYZErrTracking();
1150 // store track position/errors before update in the point WorkSpace-A
1151 double* ws = (double*)pnt->getTrParamWSA();
1152 ws[0] = trc.getY();
1153 ws[1] = trc.getZ();
1154 ws[2] = trc.getSigmaY2();
1155 ws[3] = trc.getSigmaZY();
1156 ws[4] = trc.getSigmaZ2();
1157 double chi = trc.getPredictedChi2(yz, errYZ);
1158 if (!trc.update(yz, errYZ)) {
1159 if (algConf.verbose > 2) {
1160 LOGF(warn, "Failed on Inward Update %f,%f {%f,%f,%f}", yz[0], yz[1], errYZ[0], errYZ[1], errYZ[2]);
1161 trc.print();
1162 }
1163 return false;
1164 }
1165 // printf(">>Aft ");trc.print();
1166 chifwd += chi;
1167 // printf("KLM After update: (%f) -> %f\n",chi,chifwd); trc.print();
1168 }
1169 //
1170 // outward fit
1171 trc.setCov(kIniErr);
1172 const double outwardQ2Pt2 = 4 * trc.getCovarElem(4, 4) * trc.getQ2Pt() * trc.getQ2Pt();
1173 trc.setCov(outwardQ2Pt2, 4, 4); // lowest diagonal element (Q2Pt2)
1174 signELoss = -1; // normally outward fit goes along track direction: eloss is applied. // RS Check for cosmic
1175 for (int ip = nPnt; ip--;) {
1176 pnt = getPoint(ip);
1177 if (pnt->isInvDir() != inv) { // crossing point where the track should be inverted?
1178 trc.invert();
1179 inv = !inv;
1180 }
1181 if (!propagateToPoint(trc, pnt, algConf.maxStep, algConf.maxSnp, MatCorrType(algConf.matCorType), nullptr, signELoss)) { // we are going along track direction, e.loss is applied
1182 return false;
1183 }
1184 if (!pnt->containsMeasurement()) {
1185 continue;
1186 }
1187 const double* yz = pnt->getYZTracking();
1188 const double* errYZ = pnt->getYZErrTracking();
1189 // store track position/errors before update in the point WorkSpace-B
1190 double* ws = (double*)pnt->getTrParamWSB();
1191 ws[0] = trc.getY();
1192 ws[1] = trc.getZ();
1193 ws[2] = trc.getSigmaY2();
1194 ws[3] = trc.getSigmaZY();
1195 ws[4] = trc.getSigmaZ2();
1196 double chi = trc.getPredictedChi2(yz, errYZ);
1197 // printf("<< OUT%d (%9d): %+.2e %+.2e | %+.2e %+.2e %+.2e %+.2e %+.2e | %.2e %d \n",ip,pnt->getSensor()->getInternalID(),yz[0],yz[1], ws[0],ws[1],ws[2],ws[3],ws[4],chi,inv);
1198 // printf("<<Bef "); trc.print();
1199 if (!trc.update(yz, errYZ)) {
1200 if (algConf.verbose > 2) {
1201 LOGF(warn, "Failed on Outward Update %f,%f {%f,%f,%f}", yz[0], yz[1], errYZ[0], errYZ[1], errYZ[2]);
1202 trc.print();
1203 }
1204 return false;
1205 }
1206 chibwd += chi;
1207 // printf("<<Aft "); trc.print();
1208 }
1209 //
1210 // now compute smoothed prediction and residual
1211 for (int ip = 0; ip < nPnt; ip++) {
1212 pnt = getPoint(ip);
1213 if (!pnt->containsMeasurement()) {
1214 continue;
1215 }
1216 double* wsA = (double*)pnt->getTrParamWSA(); // inward measurement
1217 double* wsB = (double*)pnt->getTrParamWSB(); // outward measurement
1218 double &yA = wsA[0], &zA = wsA[1], &sgAYY = wsA[2], &sgAYZ = wsA[3], &sgAZZ = wsA[4];
1219 double &yB = wsB[0], &zB = wsB[1], &sgBYY = wsB[2], &sgBYZ = wsB[3], &sgBZZ = wsB[4];
1220 // compute weighted average
1221 double sgYY = sgAYY + sgBYY, sgYZ = sgAYZ + sgBYZ, sgZZ = sgAZZ + sgBZZ;
1222 double detI = sgYY * sgZZ - sgYZ * sgYZ;
1223 if (TMath::Abs(detI) < constants::math::Almost0) {
1224 return false;
1225 } else {
1226 detI = 1. / detI;
1227 }
1228 double tmp = sgYY;
1229 sgYY = sgZZ * detI;
1230 sgZZ = tmp * detI;
1231 sgYZ = -sgYZ * detI;
1232 double dy = yB - yA, dz = zB - zA;
1233 double k00 = sgAYY * sgYY + sgAYZ * sgYZ, k01 = sgAYY * sgYZ + sgAYZ * sgZZ;
1234 double k10 = sgAYZ * sgYY + sgAZZ * sgYZ, k11 = sgAYZ * sgYZ + sgAZZ * sgZZ;
1235 double sgAYZt = sgAYZ;
1236 yA += dy * k00 + dz * k01; // these are smoothed predictions, stored in WSA
1237 zA += dy * k10 + dz * k11; //
1238 sgAYY -= k00 * sgAYY + k01 * sgAYZ;
1239 sgAYZ -= k00 * sgAYZt + k01 * sgAZZ;
1240 sgAZZ -= k10 * sgAYZt + k11 * sgAZZ;
1241 // printf("|| WGH%d (%9d): | %+.2e %+.2e %+.2e %.2e %.2e\n",ip,pnt->getSensor()->getInternalID(), wsA[0],wsA[1],wsA[2],wsA[3],wsA[4]);
1242 }
1243 //
1244 mChi2 = chifwd;
1245 setKalmanDone(true);
1246 return true;
1247}
1248
1249//______________________________________________
1251{
1252 // attach material effect info to alignment points
1253 trackParam_t trc = *this;
1254 const auto& algConf = AlignConfig::Instance();
1255 // collision track or cosmic lower leg: move along track direction from last (middle for cosmic lower leg) point (inner) to 1st one (outer)
1256 if (mNeedInv[0]) {
1257 trc.invert();
1258 } // track needs to be inverted ? (should be for upper leg)
1259 if (!processMaterials(trc, getInnerPointID(), 0)) {
1260 if (algConf.verbose > 2) {
1261 LOG(error) << "Failed to process materials for leg along the track";
1262 }
1263 return false;
1264 }
1265 if (isCosmic()) {
1266 // cosmic upper leg: move againg the track direction from middle point (inner) to last one (outer)
1267 trc = *this;
1268 if (mNeedInv[1]) {
1269 trc.invert();
1270 } // track needs to be inverted ?
1271 if (!processMaterials(trc, getInnerPointID() + 1, getNPoints() - 1)) {
1272#if DEBUG > 3
1273 LOG(error) << "Failed to process materials for leg against the track";
1274#endif
1275 return false;
1276 }
1277 }
1278 return true;
1279}
1280
1281//______________________________________________
1283{
1284 // attach material effect info to alignment points
1285 const int kMinNStep = 3;
1286 const double kErrSpcT = 1e-6;
1287 const double kErrAngT = 1e-6;
1288 const double kErrPtIT = 1e-12;
1289 const covMat_t kErrTiny = {// initial tiny error
1290 kErrSpcT * kErrSpcT,
1291 0, kErrSpcT * kErrSpcT,
1292 0, 0, kErrAngT * kErrAngT,
1293 0, 0, 0, kErrAngT * kErrAngT,
1294 0, 0, 0, 0, kErrPtIT * kErrPtIT};
1295 /*
1296 const double kErrSpcH = 10.0;
1297 const double kErrAngH = 0.5;
1298 const double kErrPtIH = 0.5;
1299 const double kErrHuge[15] = { // initial tiny error
1300 kErrSpcH*kErrSpcH,
1301 0 , kErrSpcH*kErrSpcH,
1302 0 , 0, kErrAngH*kErrAngH,
1303 0 , 0, 0, kErrAngH*kErrAngH,
1304 0 , 0, 0, 0, kErrPtIH*kErrPtIH
1305 };
1306 */
1307 //
1308 // 2 copies of the track, one will be propagated accounting for materials, other - w/o
1309 trackParam_t tr0;
1311 double dpar[5] = {0};
1312 covMat_t dcov{0};
1313 matTL.setTimeNotNeeded();
1314 const auto& algConf = AlignConfig::Instance();
1315 // calculate min X/X0 to treat the point as having materials
1316 double minX2X0 = algConf.minScatteringAngleToAccount / 0.014 * trc.getPt();
1317 minX2X0 *= minX2X0;
1318
1319 //
1320 int pinc, signELoss = 0;
1321 if (pTo > pFrom) { // fit inward: cosmics upper leg
1322 pTo++;
1323 pinc = 1;
1324 signELoss = 1; // against the track direction, eloss is applied (RS Check for cosmic)
1325 } else { // fit outward collision track or cosmics lower leg: along the track direction:
1326 pTo--;
1327 pinc = -1;
1328 signELoss = -1; // eloss is applied
1329 }
1330 //
1331 for (int ip = pFrom; ip != pTo; ip += pinc) { // points are ordered against track direction
1332 AlignmentPoint* pnt = getPoint(ip);
1333 trc.setCov(kErrTiny); // assign tiny errors to both tracks
1334 tr0 = trc;
1335 //
1336 matTL.clearFast();
1337 // printf("-> ProcMat %d (%d->%d)\n",ip,pFrom,pTo);
1338 if (!propagateToPoint(trc, pnt, algConf.maxStep, algConf.maxSnp, MatCorrType(algConf.matCorType), &matTL, signELoss)) { // with material corrections
1339 if (algConf.verbose > 2) {
1340 LOG(error) << "Failed to take track to point" << ip << " (dir: " << pFrom << "->" << pTo << ") with mat.corr.";
1341 trc.print();
1343 }
1344 return false;
1345 }
1346 //
1347 // is there enough material to consider the point as a scatterer?
1348 bool hasMaterial = matTL.getX2X0() > minX2X0;
1349 if (!propagateToPoint(tr0, pnt, algConf.maxStep, algConf.maxSnp, MatCorrType::USEMatCorrNONE, nullptr, signELoss)) { // no material corrections
1350 if (algConf.verbose > 2) {
1351 LOG(error) << "Failed to take track to point" << ip << " (dir: " << pFrom << "->" << pTo << ") with mat.corr.";
1352 tr0.print();
1354 }
1355 return false;
1356 }
1357 // the difference between the params, covariance of tracks with and w/o material accounting gives
1358 // parameters and covariance of material correction. For params ONLY ELoss effect is relevant
1359 double *par0 = (double*)tr0.getParams(), *par1 = (double*)trc.getParams();
1360 const covMat_t &cov0 = tr0.getCov(), &cov1 = trc.getCov();
1361 for (int l = 15; l--;) {
1362 dcov[l] = cov1[l] - cov0[l];
1363 }
1364 for (int l = kNKinParBON; l--;) {
1365 dpar[l] = par1[l] - par0[l];
1366 } // eloss affects all parameters!
1367 pnt->setMatCorrExp(dpar);
1368 //dpar[kParQ2Pt] = par1[kParQ2Pt] - par0[kParQ2Pt]; // only e-loss expectation is non-0
1369 //
1370 if (hasMaterial) {
1371 // MP2 handles only scalar residuals hence correlated matrix of material effect need to be diagonalized
1372 bool eLossFree = pnt->getELossVaried();
1373 int nParFree = eLossFree ? kNKinParBON : kNKinParBOFF;
1374 TMatrixDSym matCov(nParFree);
1375 for (int i = nParFree; i--;) {
1376 for (int j = i + 1; j--;) {
1377 auto err2 = dcov[j + ((i * (i + 1)) >> 1)];
1378 if (i == j && err2 < 1e-20) { // meaninglessly small diagonal error
1379 LOGP(warn, "Material correction {}-th error too small: {}, declare no material despite x/X0={}", i, err2, matTL.getX2X0());
1380 hasMaterial = false;
1381 break;
1382 }
1383 matCov(i, j) = matCov(j, i) = err2;
1384 }
1385 }
1386 if (hasMaterial) {
1387 TMatrixDSymEigen matDiag(matCov); // find eigenvectors
1388 const TMatrixD& matEVec = matDiag.GetEigenVectors();
1389 if (!matEVec.IsValid()) {
1390 if (algConf.verbose > 2) {
1391 LOG(error) << "Failed to diagonalize covariance of material correction";
1392 matCov.Print();
1393 return false;
1394 }
1395 }
1396 for (int ix = 0; ix < matDiag.GetEigenValues().GetNrows(); ix++) {
1397 if (matDiag.GetEigenValues()[ix] < 1e-18) {
1398 LOG(warn) << "Too small " << ix << "-th eignevalue " << matDiag.GetEigenValues()[ix] << " for cov.matrix !!!";
1399 LOG(warn) << "Track with mat.corr: " << trc.asString();
1400 LOG(warn) << "Track w/o mat.corr: " << tr0.asString();
1401 matCov.Print();
1402 matDiag.GetEigenValues().Print();
1403 hasMaterial = false;
1404 break;
1405 }
1406 }
1407 if (hasMaterial) {
1408 pnt->setMatCovDiagonalizationMatrix(matEVec); // store diagonalization matrix
1409 pnt->setMatCovDiag(matDiag.GetEigenValues()); // store E.Values: diagonalized cov.matrix
1410 if (!eLossFree) {
1411 pnt->setMatCovDiagElem(kParQ2Pt, dcov[14]);
1412 }
1413 pnt->setX2X0(matTL.getX2X0());
1414 pnt->setXTimesRho(matTL.getXRho());
1415 }
1416 }
1417 pnt->setContainsMaterial(hasMaterial);
1418 }
1419 if (pnt->containsMeasurement()) { // update track to have best possible kinematics
1420 const double* yz = pnt->getYZTracking();
1421 const double* errYZ = pnt->getYZErrTracking();
1422 if (!trc.update(yz, errYZ)) {
1423 if (algConf.verbose > 2) {
1424 LOGF(warn, "Failed on Update %f,%f {%f,%f,%f}", yz[0], yz[1], errYZ[0], errYZ[1], errYZ[2]);
1425 trc.print();
1426 }
1427 return false;
1428 }
1429 //
1430 }
1431 //
1432 }
1433 //
1434 return true;
1435}
1436
1437//______________________________________________
1439{
1440 // sort points in order against track direction: innermost point is last
1441 // for collision tracks.
1442 // For 2-leg cosmic tracks: 1st points of outgoing (lower) leg are added from large to
1443 // small radii, then the points of incoming (upper) leg are added in increasing R direction
1444 //
1445 // The mInnerPointID will mark the id of the innermost point, i.e. the last one for collision-like
1446 // tracks and in case of cosmics - the point of lower leg with smallest R
1447 //
1448 // the mDetPoints vector will not change anymore: it is safe to work with pointers
1449 for (size_t i = 0; i < mDetPoints.size(); i++) {
1450 mPoints.push_back(&mDetPoints[i]);
1451 }
1452
1453 auto isAfter = [](const AlignmentPoint* a, const AlignmentPoint* b) {
1454 auto xa = a->getXTracking(), xb = b->getXTracking();
1455 if (!a->isInvDir()) { // lower leg: track propagates from low to large X via this point
1456 if (!b->isInvDir()) { // this one also
1457 return xa > xb;
1458 } else {
1459 return true; // any point on the lower leg has higher priority than on the upper leg
1460 }
1461 } else { // this point is from upper cosmic leg: track propagates from large to low X
1462 if (b->isInvDir()) {
1463 return xa < xb;
1464 } else {
1465 return false;
1466 }
1467 }
1468 };
1469
1470 std::sort(mPoints.begin(), mPoints.end(), isAfter);
1471 int np = getNPoints();
1472 mInnerPointID = np - 1;
1473 if (isCosmic()) {
1474 for (int ip = np; ip--;) {
1475 if (getPoint(ip)->isInvDir()) {
1476 continue;
1477 } // this is a point of upper leg
1478 mInnerPointID = ip;
1479 break;
1480 }
1481 }
1482 //
1483}
1484
1485//______________________________________________
1486void AlignmentTrack::setLocPars(const double* pars)
1487{
1488 // store loc par corrections
1489 memcpy(mLocPar.data(), pars, mNLocPar * sizeof(double));
1490}
1491
1492//______________________________________________
1493void AlignmentTrack::addLocPars(const double* pars)
1494{
1495 // store loc par corrections
1496 for (int i = 0; i < mNLocPar; i++) {
1497 mLocPar[i] += pars[i];
1498 }
1499}
1500
1501//______________________________________________
1503{
1504 // if needed, expand global derivatives buffer
1505 if (mGloParID.size() < minSize) {
1506 mGloParID.resize(minSize);
1507 mDResDGlo[0].resize(minSize);
1508 mDResDGlo[1].resize(minSize);
1509 }
1510}
1511
1512//____________________________________________
1514{
1515 // test track local solution
1516 int npnt = getNPoints();
1517 double mat[mNLocPar][mNLocPar], rhs[mNLocPar];
1518 std::memset(mat, 0, sizeof(double) * mNLocPar * mNLocPar);
1519 std::memset(rhs, 0, sizeof(double) * mNLocPar);
1520 for (int ip = npnt; ip--;) {
1521 if (mPoints[ip]->containsMeasurement()) {
1522 for (int idim = 2; idim--;) { // each point has 2 position residuals
1523 auto sg2inv = 1. / mPoints[ip]->getErrDiag(idim); // inv. error
1524 auto deriv = getDResDLoc(idim, ip); // array of Dresidual/Dparams
1525 for (int parI = 0; parI < mNLocPar; parI++) {
1526 rhs[parI] -= deriv[parI] * mResid[idim][ip] * sg2inv;
1527 for (int parJ = parI; parJ < mNLocPar; parJ++) {
1528 mat[parI][parJ] += deriv[parI] * deriv[parJ] * sg2inv;
1529 }
1530 }
1531 } // loop over 2 orthogonal measurements at the point
1532 } // derivarives at measured points
1533 // if the point contains material, consider its expected kinks, eloss as measurements
1534 if (mPoints[ip]->containsMaterial()) { // at least 4 parameters: 2 spatial + 2 angular kinks with 0 expectaction
1535 int npm = mPoints[ip]->getNMatPar();
1536 // const float* expMatCorr = mPoints[ip]->getMatCorrExp(); // expected correction (diagonalized) // RS??
1537 const auto expMatCov = mPoints[ip]->getMatCorrCov(); // its error
1538 int offs = mPoints[ip]->getMaxLocVarID() - npm;
1539 for (int ipar = 0; ipar < npm; ipar++) {
1540 int parI = offs + ipar;
1541 // expected
1542 // rhs[parI] -= expMatCorr[ipar]/expMatCov[ipar]; // consider expectation as measurement // RS??
1543 mat[parI][parI] += 1. / expMatCov[ipar]; // this measurement is orthogonal to all others
1544 }
1545 } // material effect descripotion params
1546 //
1547 }
1549 for (int i = 0; i < mNLocPar; i++) {
1550 for (int j = i; j < mNLocPar; j++) {
1551 solver.A(i, j) = mat[i][j];
1552 }
1553 solver.B(i, 0) = rhs[i];
1554 }
1555 solver.solve();
1556 // increment current params by new solution
1557 for (int i = 0; i < mNLocPar; i++) {
1558 mLocPar[i] += solver.B(i, 0);
1559 }
1560 return calcResiduals();
1561}
1562
1563//______________________________________________
1565{
1566 // remove last n points, must be called before sortPoints
1567 while (n > 0) {
1568 mDetPoints.pop_back();
1569 n--;
1570 }
1571}
1572
1573} // namespace align
1574} // namespace o2
Configuration file for global alignment.
Base class for detector: wrapper for set of volumes.
End-chain alignment volume in detector branch, where the actual measurement is done.
Base class of alignable volume.
Track model for the alignment.
Definition of SymMatrixSolver class.
General auxilliary methods.
Collection of auxillary methods.
uint32_t res
Definition RawData.h:0
std::ostringstream debug
virtual void dPosTraDParCalib(const AlignmentPoint *pnt, double *deriv, int calibID, const AlignableVolume *parent=nullptr) const
AlignableDetector * getDetector() const
virtual void dPosTraDParGeom(const AlignmentPoint *pnt, double *deriv, const AlignableVolume *parent=nullptr) const
bool isFreeDOF(int dof) const
AlignableVolume * getParent() const
float * getMatCorrCov() const
virtual void dumpCoordinates() const
void updatePointByTrackInfo(const trackParam_t *t)
double getErrDiag(int i) const
void setMatCorrExp(double *p)
double * getTrParamWSB() const
void diagonalizeResiduals(double rY, double rZ, double &resU, double &resV) const
void setContainsMaterial(bool v=true)
void setTrParamWSA(const double *param)
void setMatCovDiagElem(int i, double err2)
double * getTrParamWSA() const
void print(uint16_t opt=0) const
void setMatCovDiag(const TVectorD &v)
const AlignableSensor * getSensor() const
float * getMatCorrExp() const
void getResidualsDiag(const double *pos, double &resU, double &resV) const
const double * getYZErrTracking() const
bool getNeedUpdateFromTrack() const
void setMatCovDiagonalizationMatrix(const TMatrixD &d)
const double * getYZTracking() const
void setTrParamWSB(const double *param)
void unDiagMatCorr(const double *diag, double *nodiag) const
void addLocPars(const double *pars)
bool propagateToPoint(trackParam_t &tr, const AlignmentPoint *pnt, double maxStep, double maxSnp=0.95, MatCorrType mt=MatCorrType::USEMatCorrLUT, track::TrackLTIntegral *tLT=nullptr, int signCorr=0)
void setKalmanDone(bool v=true)
void richardsonDeriv(const trackParam_t *trSet, const double *delta, const AlignmentPoint *pnt, double &derY, double &derZ)
std::vector< AlignmentPoint * > mPoints
virtual void dumpCoordinates() const
void setParams(trackParam_t &tr, double x, double alp, const double *par, bool add)
double getResidual(int dim, int pntID) const
bool applyMatCorr(trackParam_t &trPar, const double *corrDiag, const AlignmentPoint *pnt)
AlignmentPoint * getPoint(int i)
bool calcResiduals(const double *params=nullptr)
void modParam(trackParam_t &tr, int par, double delta)
std::vector< double > mDResDGlo[2]
bool calcResidDeriv(double *params=nullptr)
bool propagateParamToPoint(trackParam_t &tr, const AlignmentPoint *pnt, double maxStep=3, double maxSnp=0.95, MatCorrType mt=MatCorrType::USEMatCorrLUT, int signCorr=0)
void checkExpandDerGloBuffer(unsigned int minSize)
bool fitLeg(trackParam_t &trc, int pFrom, int pTo, bool &inv)
std::vector< double > mDResDLoc[2]
std::vector< AlignmentPoint > mDetPoints
std::vector< double > mLocPar
void setDerivDone(bool v=true)
void setLocPars(const double *pars)
bool calcResidDerivGlo(AlignmentPoint *pnt)
void Clear(Option_t *opt="") final
bool combineTracks(trackParam_t &trcL, const trackParam_t &trcU)
std::vector< int > mGloParID
void setResidDone(bool v=true)
const double * getDResDLoc(int dim, int pntID) const
void copyFrom(const o2::track::TrackParametrizationWithError< P > &trc)
void Print(Option_t *opt="") const final
std::vector< double > mResid[2]
static double richardsonExtrap(double *val, int ord=1)
int getParGloID(int par) const
Definition DOFSet.h:49
int getNCalibDOFsFree() const
Definition DOFSet.h:47
int getNCalibDOFs() const
Definition DOFSet.h:46
int getNDOFsFree() const
Definition DOFSet.h:45
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
Definition Propagator.h:143
double & A(int i, int j)
access to A elements
double & B(int i, int j)
access to B elements
gpu::gpustd::array< value_t, kCovMatSize > covMat_t
GLdouble n
Definition glcorearb.h:1982
GLint GLsizei count
Definition glcorearb.h:399
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLenum const GLfloat * params
Definition glcorearb.h:272
GLuint GLfloat * val
Definition glcorearb.h:1582
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLboolean invert
Definition glcorearb.h:543
constexpr double TinyDist
Definition utils.h:42
const int kNRDClones
const int kRichardsonOrd
const int kRichardsonN
typename track::TrackParametrizationWithError< double > trackParam_t
Definition utils.h:29
constexpr float Almost0
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"