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 trackPar_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(trackPar_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].printParam();
526 }
527 return false;
528 }
529 }
530 return true;
531}
532
533//______________________________________________________
534bool AlignmentTrack::propagateParamToPoint(trackPar_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, trackPar_t* linRef, 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, linRef, pnt, maxStep, maxSnp, mt, tLT, signCorr);
546}
547
548bool AlignmentTrack::propagate(trackParam_t& track, trackPar_t* linRef, 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, linRef, pnt->getAlphaSens(), pnt->getXTracking(), pnt->getUseBzOnly(), maxSnp, maxStep, 2, mt, tLT, signCorr);
558}
559
560bool AlignmentTrack::propagate(trackPar_t& track, const AlignmentPoint* pnt, double maxStep, double maxSnp, MatCorrType mt, track::TrackLTIntegral* tLT, int signCorr)
561{
562 if (signCorr == 0) { // auto
563 // calculate the sign of the energy loss correction and ensure the upper leg of cosmics is calculated correctly.
564 double dx = pnt->getXTracking() - track.getX();
565 int dir = dx > 0.f ? 1 : -1;
566 signCorr = pnt->isInvDir() ? dir : -dir; // propagation along the track direction should have signCorr=-1
567 }
568 // do propagation in at least 2 step to reveal eventual effect of MS on the position
569 return PropagatorD::Instance()->propagateToAlphaX(track, pnt->getAlphaSens(), pnt->getXTracking(), pnt->getUseBzOnly(), maxSnp, maxStep, 2, mt, tLT, signCorr);
570}
571
572/*
573//______________________________________________________
574bool AlignmentTrack::ApplyMS(trackParam_t& trPar, double tms,double pms)
575{
576 //------------------------------------------------------------------------------
577 // Modify track par (e.g. trackParam_t) in the tracking frame
578 // (dip angle lam, az. angle phi)
579 // by multiple scattering defined by polar and azumuthal scattering angles in
580 // the track collinear frame (tms and pms resp).
581 // The updated direction vector in the tracking frame becomes
582 //
583 // | Cos[lam]*Cos[phi] Cos[phi]*Sin[lam] -Sin[phi] | | Cos[tms] |
584 // | Cos[lam]*Sin[phi] Sin[lam]*Sin[phi] Cos[phi] | x | Cos[pms]*Sin[tms]|
585 // | Sin[lam] -Cos[lam] 0 | | Sin[pms]*Sin[tms]|
586 //
587 //------------------------------------------------------------------------------
588 //
589 double *par = (double*) trPar.GetParameter();
590 //
591 if (Abs(tms)<1e-7) return true;
592 //
593 double snTms = Sin(tms), csTms = Cos(tms);
594 double snPms = Sin(pms), csPms = Cos(pms);
595 double snPhi = par[2], csPhi = Sqrt((1.-snPhi)*(1.+snPhi));
596 double csLam = 1./Sqrt(1.+par[3]*par[3]), snLam = csLam*par[3];
597 //
598 double r00 = csLam*csPhi, r01 = snLam*csPhi, &r02 = snPhi;
599 double r10 = csLam*snPhi, r11 = snLam*snPhi, &r12 = csPhi;
600 double &r20 = snLam ,&r21 = csLam;
601 //
602 double &v0 = csTms, v1 = snTms*csPms, v2 = snTms*snPms;
603 //
604 double px = r00*v0 + r01*v1 - r02*v2;
605 double py = r10*v0 + r11*v1 + r12*v2;
606 double pz = r20*v0 - r21*v1;
607 //
608 double pt = Sqrt(px*px + py*py);
609 par[2] = py/pt;
610 par[3] = pz/pt;
611 par[4]*= csLam/pt;
612 //
613 return true;
614}
615*/
616
617//______________________________________________________
618bool AlignmentTrack::applyMatCorr(trackPar_t& trPar, const double* corrPar, const AlignmentPoint* pnt)
619{
620 // Modify track param (e.g. trackParam_t) in the tracking frame
621 // by delta accounting for material effects
622 // Note: corrPar contains delta to track parameters rotated by the matrix
623 // DIAGONALIZING ITS COVARIANCE MATRIX!
624 // transform parameters from the frame diagonalizing the errors to track frame
625 double corr[kNKinParBON] = {0};
626 if (pnt->containsMaterial()) { // are there free params from materials?
627 int nCorrPar = pnt->getNMatPar();
628 const double* corrDiag = &corrPar[pnt->getMaxLocVarID() - nCorrPar]; // material corrections for this point start here
629 pnt->unDiagMatCorr(corrDiag, corr); // this is to account for MS and RANDOM Eloss (if varied)
630 }
631 // to this we should add expected parameters modification due to the deterministic eloss
632 float* detELoss = pnt->getMatCorrExp();
633 for (int i = kNKinParBON; i--;) {
634 corr[i] += detELoss[i];
635 }
636 //corr[kParQ2Pt] += detELoss[kParQ2Pt];
637 // printf("apply corr UD %+.3e %+.3e %+.3e %+.3e %+.3e\n",corr[0],corr[1],corr[2],corr[3],corr[4]);
638 // printf(" corr D %+.3e %+.3e %+.3e %+.3e\n",corrDiag[0],corrDiag[1],corrDiag[2],corrDiag[3]);
639 // printf("at point :"); pnt->print();
640 return applyMatCorr(trPar, corr);
641 //
642}
643
644//______________________________________________________
645bool AlignmentTrack::applyMatCorr(trackPar_t& trPar, const double* corr)
646{
647 // Modify track param (e.g. trackParam_t) in the tracking frame
648 // by delta accounting for material effects
649 // Note: corr contains delta to track frame, NOT in diagonalized one
650 const double snp = trPar.getSnp() + corr[kParSnp];
651 const auto& algConf = AlignConfig::Instance();
652 if (Abs(snp) > algConf.maxSnp) {
653 if (algConf.verbose > 2) {
654 LOG(error) << "Snp is too large: " << snp;
655 printf("DeltaPar: ");
656 for (int i = 0; i < kNKinParBON; i++) {
657 printf("%+.3e ", corr[i]);
658 }
659 printf("\n");
660 trPar.printParam();
661 }
662 return false;
663 }
664
665 trPar.updateParams(corr);
666
667 return true;
668}
669
670//______________________________________________________
671bool AlignmentTrack::applyMatCorr(trackPar_t* trSet, int ntr, const double* corrDiag, const AlignmentPoint* pnt)
672{
673 // Modify set of track params (e.g. trackParam_t) in the tracking frame
674 // by delta accounting for material effects
675 // Note: corrDiag contain delta to track parameters rotated by the matrix DIAGONALIZING ITS
676 // COVARIANCE MATRIX
677 // transform parameters from the frame diagonalizing the errors to track frame
678 const auto& algConf = AlignConfig::Instance();
679 double corr[kNKinParBON] = {0};
680 if (pnt->containsMaterial()) { // are there free params from materials?
681 int nCorrPar = pnt->getNMatPar();
682 const double* corrDiagP = &corrDiag[pnt->getMaxLocVarID() - nCorrPar]; // material corrections for this point start here
683 pnt->unDiagMatCorr(corrDiagP, corr);
684 }
685 float* detELoss = pnt->getMatCorrExp();
686 for (int i = kNKinParBON; i--;) {
687 corr[i] += detELoss[i];
688 }
689 // if (!pnt->getELossVaried()) corr[kParQ2Pt] = pnt->getMatCorrExp()[kParQ2Pt]; // fixed eloss expected effect
690 // printf("apply corr UD %+.3e %+.3e %+.3e %+.3e\n",corr[0],corr[1],corr[2],corr[3]);
691 // printf(" corr D %+.3e %+.3e %+.3e %+.3e\n",corrDiagP[0],corrDiagP[1],corrDiagP[2],corrDiagP[3]);
692 // printf("at point :"); pnt->print();
693 //
694 for (int itr = ntr; itr--;) {
695 if (!applyMatCorr(trSet[itr], corr)) {
696 if (algConf.verbose > 2) {
697 LOGP(error, "Failed on clone {} materials", itr);
698 trSet[itr].printParam();
699 }
700 return false;
701 }
702 }
703 return true;
704}
705
706//______________________________________________
707double AlignmentTrack::richardsonExtrap(double* val, int ord)
708{
709 // Calculate Richardson extrapolation of order ord (starting from 1)
710 // The array val should contain estimates ord+1 of derivatives with variations
711 // d, d/2 ... d/2^ord.
712 // The array val is overwritten
713 //
714 if (ord == 1) {
715 return (4. * val[1] - val[0]) * (1. / 3);
716 }
717 do {
718 for (int i = 0; i < ord; i++) {
719 val[i] = (4. * val[i + 1] - val[i]) * (1. / 3);
720 }
721 } while (--ord);
722 return val[0];
723}
724
725//______________________________________________
726double AlignmentTrack::richardsonExtrap(const double* val, int ord)
727{
728 // Calculate Richardson extrapolation of order ord (starting from 1)
729 // The array val should contain estimates ord+1 of derivatives with variations
730 // d, d/2 ... d/2^ord.
731 // The array val is not overwritten
732 //
733 if (ord == 1) {
734 return (4. * val[1] - val[0]) * (1. / 3);
735 }
736 double* buff = new double[ord + 1];
737 memcpy(buff, val, (ord + 1) * sizeof(double));
738 do {
739 for (int i = 0; i < ord; i++) {
740 buff[i] = (4. * buff[i + 1] - buff[i]) * (1. / 3);
741 }
742 } while (--ord);
743 return buff[0];
744}
745
746//______________________________________________
747void AlignmentTrack::richardsonDeriv(const trackPar_t* trSet, const double* delta, const AlignmentPoint* pnt, double& derY, double& derZ)
748{
749 // Calculate Richardson derivatives for diagonalized Y and Z from a set of kRichardsonN pairs
750 // of tracks with same parameter of i-th pair varied by +-delta[i]
751 static double derRichY[kRichardsonN], derRichZ[kRichardsonN];
752 //
753 for (int icl = 0; icl < kRichardsonN; icl++) { // calculate kRichardsonN variations with del, del/2, del/4...
754 double resYVP = 0, resYVN = 0, resZVP = 0, resZVN = 0;
755 pnt->getResidualsDiag(trSet[(icl << 1) + 0].getParams(), resYVP, resZVP); // variation with +delta
756 pnt->getResidualsDiag(trSet[(icl << 1) + 1].getParams(), resYVN, resZVN); // variation with -delta
757 derRichY[icl] = 0.5 * (resYVP - resYVN) / delta[icl]; // 2-point symmetric derivatives
758 derRichZ[icl] = 0.5 * (resZVP - resZVN) / delta[icl];
759 }
760 derY = richardsonExtrap(derRichY, kRichardsonOrd); // dY/dPar
761 derZ = richardsonExtrap(derRichZ, kRichardsonOrd); // dZ/dPar
762 if (TMath::IsNaN(derY) || TMath::IsNaN(derZ)) {
763 LOGP(error, "NAN encounterd: DerY {} : DerZ {}", derY, derZ);
764 }
765 //
766}
767
768//______________________________________________
769void AlignmentTrack::Print(Option_t* opt) const
770{
771 // print track data
772 printf("%s ", isCosmic() ? " Cosmic " : "Collision ");
773 trackParam_t::print();
774 printf("N Free Par: %d (Kinem: %d) | Npoints: %d (Inner:%d) | Chi2Ini:%.1f Chi2: %.1f/%d",
776 if (isCosmic()) {
777 int npLow = getInnerPointID();
778 int npUp = getNPoints() - npLow - 1;
779 printf(" [Low:%.1f/%d Up:%.1f/%d]", mChi2CosmDn, npLow, mChi2CosmUp, npUp);
780 }
781 printf("\n");
782 //
783 TString optS = opt;
784 optS.ToLower();
785 bool res = optS.Contains("r") && getResidDone();
786 bool der = optS.Contains("d") && getDerivDone();
787 bool par = optS.Contains("lc"); // local param corrections
788 bool paru = optS.Contains("lcu"); // local param corrections in track param frame
789 //
790 if (par) {
791 printf("Ref.track corr: ");
792 for (int i = 0; i < mNLocExtPar; i++) {
793 printf("%+.3e ", mLocPar[i]);
794 }
795 printf("\n");
796 }
797 //
798 if (optS.Contains("p") || res || der) {
799 for (int ip = 0; ip < getNPoints(); ip++) {
800 printf("#%3d ", ip);
801 auto* pnt = getPoint(ip);
802 pnt->print(AlignmentPoint::kMeasurementBit); // RS FIXME OPT
803 //
804 if (res && pnt->containsMeasurement()) {
805 printf(" Residuals : %+.3e %+.3e -> Pulls: %+7.2f %+7.2f\n",
806 getResidual(0, ip), getResidual(1, ip),
807 getResidual(0, ip) / sqrt(pnt->getErrDiag(0)), getResidual(1, ip) / sqrt(pnt->getErrDiag(1)));
808 }
809 if (der && pnt->containsMeasurement()) {
810 for (int ipar = 0; ipar < mNLocPar; ipar++) {
811 printf(" Dres/dp%03d : %+.3e %+.3e\n", ipar, getDResDLoc(0, ip)[ipar], getDResDLoc(1, ip)[ipar]);
812 }
813 }
814 //
815 if (par && pnt->containsMaterial()) { // material corrections
816 int nCorrPar = pnt->getNMatPar();
817 printf(" Corr.Diag: ");
818 for (int i = 0; i < nCorrPar; i++) {
819 printf("%+.3e ", mLocPar[i + pnt->getMaxLocVarID() - nCorrPar]);
820 }
821 printf("\n");
822 printf(" Corr.Pull: ");
823 const float* corCov = pnt->getMatCorrCov(); // correction covariance
824 // const float *corExp = pnt->getMatCorrExp(); // correction expectation
825 for (int i = 0; i < nCorrPar; i++) {
826 printf("%+.3e ", (mLocPar[i + pnt->getMaxLocVarID() - nCorrPar] /* - corExp[i]*/) / Sqrt(corCov[i]));
827 }
828 printf("\n");
829 if (paru) { // print also mat.corrections in track frame
830 double corr[5] = {0};
831 pnt->unDiagMatCorr(&mLocPar[pnt->getMaxLocVarID() - nCorrPar], corr);
832 // if (!pnt->getELossVaried()) corr[kParQ2Pt] = pnt->getMatCorrExp()[kParQ2Pt]; // fixed eloss expected effect
833 printf(" Corr.Track: ");
834 for (int i = 0; i < kNKinParBON; i++) {
835 printf("%+.3e ", corr[i]);
836 }
837 printf("\n");
838 }
839 }
840 }
841 } // print points
842}
843
844//______________________________________________
846{
847 // print various coordinates for inspection
848 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");
849 for (int ip = 0; ip < getNPoints(); ip++) {
850 auto* pnt = getPoint(ip);
851 if (!pnt->containsMeasurement()) {
852 continue;
853 }
854 pnt->dumpCoordinates();
855 }
856}
857
858//______________________________________________
860{
861 // perform initial fit of the track
862 //
863 const auto& algConf = AlignConfig::Instance();
864 if (!getFieldON()) { // for field-off data impose nominal momentum
865 setQ2Pt(isCosmic() ? 1. / algConf.defPTB0Cosm : 1. / algConf.defPTB0Coll);
866 }
867 trackParam_t trc(*(trackParam_t*)this);
869 //
870 // the points are ranged from outer to inner for collision tracks,
871 // and from outer point of lower leg to outer point of upper leg for the cosmic track
872 //
873 // the fit will always start from the outgoing track in inward direction
874 if (!fitLeg(trc, 0, getInnerPointID(), mNeedInv[0])) {
875 if (algConf.verbose > 2) {
876 LOG(warn) << "Failed fitLeg 0";
877 trc.print();
878 }
879 return false; // collision track or cosmic lower leg
880 }
881 //
882 // printf("Lower leg: %d %d\n",0,getInnerPointID()); trc.print();
883 //
884 if (isCosmic()) {
886 trackParam_t trcU = trc;
887 if (!fitLeg(trcU, getNPoints() - 1, getInnerPointID() + 1, mNeedInv[1])) { //fit upper leg of cosmic track
888 if (algConf.verbose > 2) {
889 LOG(warn) << "Failed fitLeg 1";
890 trc.print();
891 }
892 return false; // collision track or cosmic lower leg
893 }
894 //
895 // propagate to reference point, which is the inner point of lower leg
896 const AlignmentPoint* refP = getPoint(getInnerPointID());
897 if (!propagateToPoint(trcU, nullptr, refP, algConf.maxStep, algConf.maxSnp, MatCorrType(algConf.matCorType), nullptr, -1)) { // moving along the track: energy is lost
898 return false;
899 }
900 //
902 // printf("Upper leg: %d %d\n",getInnerPointID()+1,getNPoints()-1); trcU.print();
903 //
904 if (!combineTracks(trc, trcU)) {
905 return false;
906 }
907 //printf("Combined\n"); trc.print();
908 }
909 copyFrom(&trc);
910 //
911 mChi2Ini = mChi2;
912 return true;
913}
914
915//______________________________________________
917{
918 // Assign to trcL the combined tracks (Kalman update of trcL by trcU)
919 // The trcL and trcU MUST be defined at same X,Alpha
920 //
921 // Update equations: tracks described by vectors vL and vU and coviriances CL and CU resp.
922 // then the gain matrix K = CL*(CL+CU)^-1
923 // Updated vector and its covariance:
924 // CL' = CL - K*CL
925 // vL' = vL + K(vU-vL)
926 //
927 const auto& algConf = AlignConfig::Instance();
928 if (Abs(trcL.getX() - trcU.getX()) > TinyDist || Abs(trcL.getAlpha() - trcU.getAlpha()) > TinyDist) {
929 if (algConf.verbose > 2) {
930 LOG(error) << "Tracks must be defined at same reference X and Alpha";
931 trcL.print();
932 trcU.print();
933 }
934 return false;
935 }
936 //
937 LOGP(debug, "CosmDn: {}", trcL.asString());
938 LOGP(debug, "CosmUp: {}", trcU.asString());
939 float dsnp = trcL.getSnp() - trcU.getSnp(), dTgl = trcL.getTgl() - trcU.getTgl();
940 if (std::abs(dsnp) > algConf.cosmMaxDSnp || std::abs(dTgl) > algConf.cosmMaxDTgl) {
941 if (algConf.verbose > 2) {
942 LOGP(error, "Rejecting track with dSnp={} dTgl={}", dsnp, dTgl);
943 LOGP(error, "CosmDn: {}", trcL.asString());
944 LOGP(error, "CosmUp: {}", trcU.asString());
945 }
946 return false;
947 }
948 // const covMat_t& covU = trcU.getCov();
949 // const covMat_t& covL = trcL.getCov();
950 //
951 int mtSize = getFieldON() ? kNKinParBON : kNKinParBOFF;
952 TMatrixD matCL(mtSize, mtSize), matCLplCU(mtSize, mtSize);
953 TVectorD vl(mtSize), vUmnvL(mtSize);
954 //
955 // trcL.print();
956 // trcU.print();
957 //
958 for (int i = mtSize; i--;) {
959 vUmnvL[i] = trcU.getParam(i) - trcL.getParam(i); // y = residual of 2 tracks
960 vl[i] = trcL.getParam(i);
961 for (int j = i + 1; j--;) {
962 int indIJ = ((i * (i + 1)) >> 1) + j; // position of IJ cov element in the trackParam_t covariance array
963 matCL(i, j) = matCL(j, i) = trcL.getCovarElem(i, j);
964 matCLplCU(i, j) = matCLplCU(j, i) = trcL.getCovarElem(i, j) + trcU.getCovarElem(i, j);
965 }
966 }
967 matCLplCU.Invert(); // S^-1 = (Cl + Cu)^-1
968 if (!matCLplCU.IsValid()) {
969 if (algConf.verbose > 2) {
970 LOG(error) << "Failed to invert summed cov.matrix of cosmic track";
971 matCLplCU.Print();
972 }
973 return false; // inversion failed
974 }
975 TMatrixD matK(matCL, TMatrixD::kMult, matCLplCU); // gain K = Cl*(Cl+Cu)^-1
976 TMatrixD matKdotCL(matK, TMatrixD::kMult, matCL); // K*Cl
977 TVectorD vlUp = matK * vUmnvL; // K*(vl - vu)
978 for (int i = mtSize; i--;) {
979 trcL.updateParam(vlUp[i], i); // updated param: vL' = vL + K(vU-vL)
980 for (int j = i + 1; j--;) {
981 trcL.updateCov(-matKdotCL(i, j), i, j);
982 } // updated covariance: Cl' = Cl - K*Cl
983 }
984 //
985 // update chi2
986 double chi2 = 0;
987 for (int i = mtSize; i--;) {
988 for (int j = mtSize; j--;) {
989 chi2 += matCLplCU(i, j) * vUmnvL[i] * vUmnvL[j];
990 }
991 }
992 mChi2 += chi2;
993 //
994 LOGP(debug, "CosmCB: {}", trcL.asString());
995 LOGP(debug, "Combined: Chi2Tot:{} ChiUp:{} ChiDn:{} ChiCmb:{} DSnp:{} DTgl:{} Alp:{}", mChi2, mChi2CosmUp, mChi2CosmDn, chi2, dsnp, dTgl, trcL.getAlpha());
996
997 return true;
998}
999
1000//______________________________________________
1001bool AlignmentTrack::fitLeg(trackParam_t& trc, int pFrom, int pTo, bool& inv)
1002{
1003 // perform initial fit of the track
1004 // the fit will always start from the outgoing track in inward direction (i.e. if cosmics - bottom leg)
1005 const int kMinNStep = 3;
1006 const double kErrSpace = 50.;
1007 const double kErrAng = 0.8;
1008 const double kErrRelPtI = 1.;
1009 const covMat_t kIniErr{// initial error
1010 kErrSpace * kErrSpace,
1011 0, kErrSpace * kErrSpace,
1012 0, 0, kErrAng * kErrAng,
1013 0, 0, 0, kErrAng * kErrAng,
1014 0, 0, 0, 0, kErrRelPtI * kErrRelPtI};
1015 //
1016 static int count = 0;
1017 const auto& algConf = AlignConfig::Instance();
1018 if (algConf.verbose > 2) {
1019 LOGP(info, "FIT COUNT {}", count++);
1020 }
1021 // prepare seed at outer point
1022 AlignmentPoint* p0 = getPoint(pFrom);
1023 double phi = trc.getPhi(), alp = p0->getAlphaSens();
1026 double dphi = math_utils::detail::deltaPhiSmall(phi, alp); // abs delta angle
1027 if (dphi > Pi() / 2.) { // need to invert the track to new frame
1028 inv = true;
1029 trc.invert();
1030 }
1031 // Fit is done from outward to inward: normally against the track direction (hence e.loss is compensated) unless inversion is requested (cosmic upper leg)
1032 if (!propagateParamToPoint(trc, p0, algConf.maxStep, algConf.maxSnp, MatCorrType(algConf.matCorType), -1)) {
1033 if (algConf.verbose > 2) {
1034 LOGF(warn, "Failed on PropagateParamOnlyTo to %f", p0->getXTracking());
1035 trc.print();
1036 }
1037 return false;
1038 }
1039 trackPar_t linRef(trc), *linRefP = algConf.useLinRef ? &linRef : nullptr;
1040 trc.setCov(kIniErr);
1041 trc.setCov(16 * trc.getQ2Pt() * trc.getQ2Pt(), 4, 4); // lowest diagonal element (Q2Pt2)
1042 //
1043 int pinc, signELoss = 0; // RS Validate for cosmic. Propagation is done from inner point to outer one:
1044 // energy loss is applied for collision tracks and cosmic lower leg, compensated for cosmic upper leg
1045 if (pTo > pFrom) { // fit in points increasing order: collision track or cosmics lower leg
1046 pTo++;
1047 pinc = 1;
1048 signELoss = 1; // e.loss is compensated
1049 } else { // fit in points decreasing order: cosmics upper leg
1050 pTo--;
1051 pinc = -1;
1052 signELoss = -1; // e.loass is applied
1053 }
1054 //
1055 int pntCnt = 0;
1056 for (int ip = pFrom; ip != pTo; ip += pinc) { // inward fit from outer point
1057 AlignmentPoint* pnt = getPoint(ip);
1058 if (!propagateToPoint(trc, linRefP, pnt, algConf.maxStep, algConf.maxSnp, MatCorrType(algConf.matCorType), nullptr, signELoss)) { // against track direction : e.loss is compensated
1059 if (algConf.verbose > 2) {
1060 LOGF(warn, "Failed on propagateToPoint %d (%d : %d) %f", ip, pFrom, pTo, pnt->getXTracking());
1061 trc.print();
1062 }
1063 return false;
1064 }
1065 if (pnt->containsMeasurement()) {
1066 if (pnt->getNeedUpdateFromTrack()) {
1067 pnt->updatePointByTrackInfo(&trc);
1068 }
1069 const double* yz = pnt->getYZTracking();
1070 const double* errYZ = pnt->getYZErrTracking();
1071 double chi = trc.getPredictedChi2(yz, errYZ);
1072 if (!trc.update(yz, errYZ)) {
1073 if (algConf.verbose > 2) {
1074 LOGF(warn, "Failed on Update %f,%f {%f,%f,%f}", yz[0], yz[1], errYZ[0], errYZ[1], errYZ[2]);
1075 trc.print();
1076 }
1077 return false;
1078 }
1079 mChi2 += chi;
1080 pntCnt++;
1081 }
1082 }
1083 //
1084 if (inv) {
1085 trc.invert();
1086 }
1087 if (algConf.verbose > 2) {
1088 LOGP(info, "Fitted leg with {} points, chi2: {}", pntCnt, mChi2);
1089 }
1090 //
1091 return true;
1092}
1093
1094//______________________________________________
1096{
1097 // calculate residuals from bi-directional Kalman smoother
1098 // ATTENTION: this method modifies workspaces of the points!!!
1099 //
1100 bool inv = false;
1101 const int kMinNStep = 3;
1102 const double kErrSpace = 100.;
1103 const double kErrAng = 0.7;
1104 const double kErrRelPtI = 1.;
1105 const covMat_t kIniErr = {// initial error
1106 kErrSpace * kErrSpace,
1107 0, kErrSpace * kErrSpace,
1108 0, 0, kErrAng * kErrAng,
1109 0, 0, 0, kErrAng * kErrAng,
1110 0, 0, 0, 0, kErrRelPtI * kErrRelPtI};
1111 // const double kOverShootX = 5;
1112 //
1113 trackParam_t trc = *this;
1114 const auto& algConf = AlignConfig::Instance();
1115 int pID = 0, nPnt = getNPoints();
1116 AlignmentPoint* pnt = nullptr;
1117 // get 1st measured point
1118 while (pID < nPnt && !(pnt = getPoint(pID))->containsMeasurement()) { // points are ordered from outward to inward
1119 pID++;
1120 }
1121 if (!pnt) {
1122 return false;
1123 }
1124 double phi = trc.getPhi(), alp = pnt->getAlphaSens();
1127 double dphi = math_utils::detail::deltaPhiSmall(phi, alp);
1128 if (dphi > Pi() / 2.) { // need to invert the track to new frame
1129 inv = true;
1130 trc.invert();
1131 }
1132 // prepare track seed at 1st outermost valid point
1133 if (!propagateParamToPoint(trc, pnt, algConf.maxStep, algConf.maxSnp, MatCorrType::USEMatCorrNONE, 1)) {
1134 if (algConf.verbose > 2) {
1135 LOG(warn) << "Failed on propagateParamToPoint";
1136 trc.print();
1138 }
1139 return false;
1140 }
1141 //
1142 trc.setCov(kIniErr);
1143 const double inwardQ2Pt2 = 4 * trc.getCovarElem(4, 4) * trc.getQ2Pt() * trc.getQ2Pt();
1144 trc.setCov(inwardQ2Pt2, 4, 4); // lowest diagonal element (Q2Pt2)
1145 //
1146 double chifwd = 0, chibwd = 0;
1147 // inward fit
1148 int signELoss = 1; // normally inward fit goes against track direction: eloss is compensated. // RS Check for cosmic
1149 for (int ip = pID; ip < nPnt; ip++) {
1150 pnt = getPoint(ip);
1151 if (pnt->isInvDir() != inv) { // crossing point where the track should be inverted?
1152 trc.invert();
1153 inv = !inv;
1154 }
1155 if (!propagateToPoint(trc, nullptr, pnt, algConf.maxStep, algConf.maxSnp, MatCorrType(algConf.matCorType), nullptr, signELoss)) {
1156 return false;
1157 }
1158 if (!pnt->containsMeasurement()) {
1159 continue;
1160 }
1161 const double* yz = pnt->getYZTracking();
1162 const double* errYZ = pnt->getYZErrTracking();
1163 // store track position/errors before update in the point WorkSpace-A
1164 double* ws = (double*)pnt->getTrParamWSA();
1165 ws[0] = trc.getY();
1166 ws[1] = trc.getZ();
1167 ws[2] = trc.getSigmaY2();
1168 ws[3] = trc.getSigmaZY();
1169 ws[4] = trc.getSigmaZ2();
1170 double chi = trc.getPredictedChi2(yz, errYZ);
1171 if (!trc.update(yz, errYZ)) {
1172 if (algConf.verbose > 2) {
1173 LOGF(warn, "Failed on Inward Update %f,%f {%f,%f,%f}", yz[0], yz[1], errYZ[0], errYZ[1], errYZ[2]);
1174 trc.print();
1175 }
1176 return false;
1177 }
1178 // printf(">>Aft ");trc.print();
1179 chifwd += chi;
1180 // printf("KLM After update: (%f) -> %f\n",chi,chifwd); trc.print();
1181 }
1182 //
1183 // outward fit
1184 trc.setCov(kIniErr);
1185 const double outwardQ2Pt2 = 4 * trc.getCovarElem(4, 4) * trc.getQ2Pt() * trc.getQ2Pt();
1186 trc.setCov(outwardQ2Pt2, 4, 4); // lowest diagonal element (Q2Pt2)
1187 signELoss = -1; // normally outward fit goes along track direction: eloss is applied. // RS Check for cosmic
1188 for (int ip = nPnt; ip--;) {
1189 pnt = getPoint(ip);
1190 if (pnt->isInvDir() != inv) { // crossing point where the track should be inverted?
1191 trc.invert();
1192 inv = !inv;
1193 }
1194 if (!propagateToPoint(trc, nullptr, pnt, algConf.maxStep, algConf.maxSnp, MatCorrType(algConf.matCorType), nullptr, signELoss)) { // we are going along track direction, e.loss is applied
1195 return false;
1196 }
1197 if (!pnt->containsMeasurement()) {
1198 continue;
1199 }
1200 const double* yz = pnt->getYZTracking();
1201 const double* errYZ = pnt->getYZErrTracking();
1202 // store track position/errors before update in the point WorkSpace-B
1203 double* ws = (double*)pnt->getTrParamWSB();
1204 ws[0] = trc.getY();
1205 ws[1] = trc.getZ();
1206 ws[2] = trc.getSigmaY2();
1207 ws[3] = trc.getSigmaZY();
1208 ws[4] = trc.getSigmaZ2();
1209 double chi = trc.getPredictedChi2(yz, errYZ);
1210 // 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);
1211 // printf("<<Bef "); trc.print();
1212 if (!trc.update(yz, errYZ)) {
1213 if (algConf.verbose > 2) {
1214 LOGF(warn, "Failed on Outward Update %f,%f {%f,%f,%f}", yz[0], yz[1], errYZ[0], errYZ[1], errYZ[2]);
1215 trc.print();
1216 }
1217 return false;
1218 }
1219 chibwd += chi;
1220 // printf("<<Aft "); trc.print();
1221 }
1222 //
1223 // now compute smoothed prediction and residual
1224 for (int ip = 0; ip < nPnt; ip++) {
1225 pnt = getPoint(ip);
1226 if (!pnt->containsMeasurement()) {
1227 continue;
1228 }
1229 double* wsA = (double*)pnt->getTrParamWSA(); // inward measurement
1230 double* wsB = (double*)pnt->getTrParamWSB(); // outward measurement
1231 double &yA = wsA[0], &zA = wsA[1], &sgAYY = wsA[2], &sgAYZ = wsA[3], &sgAZZ = wsA[4];
1232 double &yB = wsB[0], &zB = wsB[1], &sgBYY = wsB[2], &sgBYZ = wsB[3], &sgBZZ = wsB[4];
1233 // compute weighted average
1234 double sgYY = sgAYY + sgBYY, sgYZ = sgAYZ + sgBYZ, sgZZ = sgAZZ + sgBZZ;
1235 double detI = sgYY * sgZZ - sgYZ * sgYZ;
1236 if (TMath::Abs(detI) < constants::math::Almost0) {
1237 return false;
1238 } else {
1239 detI = 1. / detI;
1240 }
1241 double tmp = sgYY;
1242 sgYY = sgZZ * detI;
1243 sgZZ = tmp * detI;
1244 sgYZ = -sgYZ * detI;
1245 double dy = yB - yA, dz = zB - zA;
1246 double k00 = sgAYY * sgYY + sgAYZ * sgYZ, k01 = sgAYY * sgYZ + sgAYZ * sgZZ;
1247 double k10 = sgAYZ * sgYY + sgAZZ * sgYZ, k11 = sgAYZ * sgYZ + sgAZZ * sgZZ;
1248 double sgAYZt = sgAYZ;
1249 yA += dy * k00 + dz * k01; // these are smoothed predictions, stored in WSA
1250 zA += dy * k10 + dz * k11; //
1251 sgAYY -= k00 * sgAYY + k01 * sgAYZ;
1252 sgAYZ -= k00 * sgAYZt + k01 * sgAZZ;
1253 sgAZZ -= k10 * sgAYZt + k11 * sgAZZ;
1254 // printf("|| WGH%d (%9d): | %+.2e %+.2e %+.2e %.2e %.2e\n",ip,pnt->getSensor()->getInternalID(), wsA[0],wsA[1],wsA[2],wsA[3],wsA[4]);
1255 }
1256 //
1257 mChi2 = chifwd;
1258 setKalmanDone(true);
1259 return true;
1260}
1261
1262//______________________________________________
1264{
1265 // attach material effect info to alignment points
1266 trackParam_t trc = *this;
1267 const auto& algConf = AlignConfig::Instance();
1268 // collision track or cosmic lower leg: move along track direction from last (middle for cosmic lower leg) point (inner) to 1st one (outer)
1269 if (mNeedInv[0]) {
1270 trc.invert();
1271 } // track needs to be inverted ? (should be for upper leg)
1272 if (!processMaterials(trc, getInnerPointID(), 0)) {
1273 if (algConf.verbose > 2) {
1274 LOG(error) << "Failed to process materials for leg along the track";
1275 }
1276 return false;
1277 }
1278 if (isCosmic()) {
1279 // cosmic upper leg: move againg the track direction from middle point (inner) to last one (outer)
1280 trc = *this;
1281 if (mNeedInv[1]) {
1282 trc.invert();
1283 } // track needs to be inverted ?
1284 if (!processMaterials(trc, getInnerPointID() + 1, getNPoints() - 1)) {
1285#if DEBUG > 3
1286 LOG(error) << "Failed to process materials for leg against the track";
1287#endif
1288 return false;
1289 }
1290 }
1291 return true;
1292}
1293
1294//______________________________________________
1296{
1297 // attach material effect info to alignment points
1298 const int kMinNStep = 3;
1299 const double kErrSpcT = 1e-6;
1300 const double kErrAngT = 1e-6;
1301 const double kErrPtIT = 1e-12;
1302 const covMat_t kErrTiny = {// initial tiny error
1303 kErrSpcT * kErrSpcT,
1304 0, kErrSpcT * kErrSpcT,
1305 0, 0, kErrAngT * kErrAngT,
1306 0, 0, 0, kErrAngT * kErrAngT,
1307 0, 0, 0, 0, kErrPtIT * kErrPtIT};
1308 /*
1309 const double kErrSpcH = 10.0;
1310 const double kErrAngH = 0.5;
1311 const double kErrPtIH = 0.5;
1312 const double kErrHuge[15] = { // initial tiny error
1313 kErrSpcH*kErrSpcH,
1314 0 , kErrSpcH*kErrSpcH,
1315 0 , 0, kErrAngH*kErrAngH,
1316 0 , 0, 0, kErrAngH*kErrAngH,
1317 0 , 0, 0, 0, kErrPtIH*kErrPtIH
1318 };
1319 */
1320 //
1321 // 2 copies of the track, one will be propagated accounting for materials, other - w/o
1322 trackParam_t tr0;
1324 double dpar[5] = {0};
1325 covMat_t dcov{0};
1326 matTL.setTimeNotNeeded();
1327 const auto& algConf = AlignConfig::Instance();
1328 // calculate min X/X0 to treat the point as having materials
1329 double minX2X0 = algConf.minScatteringAngleToAccount / 0.014 * trc.getPt();
1330 minX2X0 *= minX2X0;
1331
1332 //
1333 int pinc, signELoss = 0;
1334 if (pTo > pFrom) { // fit inward: cosmics upper leg
1335 pTo++;
1336 pinc = 1;
1337 signELoss = 1; // against the track direction, eloss is applied (RS Check for cosmic)
1338 } else { // fit outward collision track or cosmics lower leg: along the track direction:
1339 pTo--;
1340 pinc = -1;
1341 signELoss = -1; // eloss is applied
1342 }
1343 //
1344 for (int ip = pFrom; ip != pTo; ip += pinc) { // points are ordered against track direction
1345 AlignmentPoint* pnt = getPoint(ip);
1346 trc.setCov(kErrTiny); // assign tiny errors to both tracks
1347 tr0 = trc;
1348 //
1349 matTL.clearFast();
1350 // printf("-> ProcMat %d (%d->%d)\n",ip,pFrom,pTo);
1351 if (!propagateToPoint(trc, nullptr, pnt, algConf.maxStep, algConf.maxSnp, MatCorrType(algConf.matCorType), &matTL, signELoss)) { // with material corrections
1352 if (algConf.verbose > 2) {
1353 LOG(error) << "Failed to take track to point" << ip << " (dir: " << pFrom << "->" << pTo << ") with mat.corr.";
1354 trc.print();
1356 }
1357 return false;
1358 }
1359 //
1360 // is there enough material to consider the point as a scatterer?
1361 bool hasMaterial = matTL.getX2X0() > minX2X0;
1362 if (!propagateToPoint(tr0, nullptr, pnt, algConf.maxStep, algConf.maxSnp, MatCorrType::USEMatCorrNONE, nullptr, signELoss)) { // no material corrections
1363 if (algConf.verbose > 2) {
1364 LOG(error) << "Failed to take track to point" << ip << " (dir: " << pFrom << "->" << pTo << ") with mat.corr.";
1365 tr0.print();
1367 }
1368 return false;
1369 }
1370 // the difference between the params, covariance of tracks with and w/o material accounting gives
1371 // parameters and covariance of material correction. For params ONLY ELoss effect is relevant
1372 double *par0 = (double*)tr0.getParams(), *par1 = (double*)trc.getParams();
1373 const covMat_t &cov0 = tr0.getCov(), &cov1 = trc.getCov();
1374 for (int l = 15; l--;) {
1375 dcov[l] = cov1[l] - cov0[l];
1376 }
1377 for (int l = kNKinParBON; l--;) {
1378 dpar[l] = par1[l] - par0[l];
1379 } // eloss affects all parameters!
1380 pnt->setMatCorrExp(dpar);
1381 //dpar[kParQ2Pt] = par1[kParQ2Pt] - par0[kParQ2Pt]; // only e-loss expectation is non-0
1382 //
1383 if (hasMaterial) {
1384 // MP2 handles only scalar residuals hence correlated matrix of material effect need to be diagonalized
1385 bool eLossFree = pnt->getELossVaried();
1386 int nParFree = eLossFree ? kNKinParBON : kNKinParBOFF;
1387 TMatrixDSym matCov(nParFree);
1388 for (int i = nParFree; i--;) {
1389 for (int j = i + 1; j--;) {
1390 auto err2 = dcov[j + ((i * (i + 1)) >> 1)];
1391 if (i == j && err2 < 1e-20) { // meaninglessly small diagonal error
1392 LOGP(warn, "Material correction {}-th error too small: {}, declare no material despite x/X0={}", i, err2, matTL.getX2X0());
1393 hasMaterial = false;
1394 break;
1395 }
1396 matCov(i, j) = matCov(j, i) = err2;
1397 }
1398 }
1399 if (hasMaterial) {
1400 TMatrixDSymEigen matDiag(matCov); // find eigenvectors
1401 const TMatrixD& matEVec = matDiag.GetEigenVectors();
1402 if (!matEVec.IsValid()) {
1403 if (algConf.verbose > 2) {
1404 LOG(error) << "Failed to diagonalize covariance of material correction";
1405 matCov.Print();
1406 return false;
1407 }
1408 }
1409 for (int ix = 0; ix < matDiag.GetEigenValues().GetNrows(); ix++) {
1410 if (matDiag.GetEigenValues()[ix] < 1e-18) {
1411 LOG(warn) << "Too small " << ix << "-th eignevalue " << matDiag.GetEigenValues()[ix] << " for cov.matrix !!!";
1412 LOG(warn) << "Track with mat.corr: " << trc.asString();
1413 LOG(warn) << "Track w/o mat.corr: " << tr0.asString();
1414 matCov.Print();
1415 matDiag.GetEigenValues().Print();
1416 hasMaterial = false;
1417 break;
1418 }
1419 }
1420 if (hasMaterial) {
1421 pnt->setMatCovDiagonalizationMatrix(matEVec); // store diagonalization matrix
1422 pnt->setMatCovDiag(matDiag.GetEigenValues()); // store E.Values: diagonalized cov.matrix
1423 if (!eLossFree) {
1424 pnt->setMatCovDiagElem(kParQ2Pt, dcov[14]);
1425 }
1426 pnt->setX2X0(matTL.getX2X0());
1427 pnt->setXTimesRho(matTL.getXRho());
1428 }
1429 }
1430 pnt->setContainsMaterial(hasMaterial);
1431 }
1432 if (pnt->containsMeasurement()) { // update track to have best possible kinematics
1433 const double* yz = pnt->getYZTracking();
1434 const double* errYZ = pnt->getYZErrTracking();
1435 if (!trc.update(yz, errYZ)) {
1436 if (algConf.verbose > 2) {
1437 LOGF(warn, "Failed on Update %f,%f {%f,%f,%f}", yz[0], yz[1], errYZ[0], errYZ[1], errYZ[2]);
1438 trc.print();
1439 }
1440 return false;
1441 }
1442 //
1443 }
1444 //
1445 }
1446 //
1447 return true;
1448}
1449
1450//______________________________________________
1452{
1453 // sort points in order against track direction: innermost point is last
1454 // for collision tracks.
1455 // For 2-leg cosmic tracks: 1st points of outgoing (lower) leg are added from large to
1456 // small radii, then the points of incoming (upper) leg are added in increasing R direction
1457 //
1458 // The mInnerPointID will mark the id of the innermost point, i.e. the last one for collision-like
1459 // tracks and in case of cosmics - the point of lower leg with smallest R
1460 //
1461 // the mDetPoints vector will not change anymore: it is safe to work with pointers
1462 for (size_t i = 0; i < mDetPoints.size(); i++) {
1463 mPoints.push_back(&mDetPoints[i]);
1464 }
1465
1466 auto isAfter = [](const AlignmentPoint* a, const AlignmentPoint* b) {
1467 auto xa = a->getXTracking(), xb = b->getXTracking();
1468 if (!a->isInvDir()) { // lower leg: track propagates from low to large X via this point
1469 if (!b->isInvDir()) { // this one also
1470 return xa > xb;
1471 } else {
1472 return true; // any point on the lower leg has higher priority than on the upper leg
1473 }
1474 } else { // this point is from upper cosmic leg: track propagates from large to low X
1475 if (b->isInvDir()) {
1476 return xa < xb;
1477 } else {
1478 return false;
1479 }
1480 }
1481 };
1482
1483 std::sort(mPoints.begin(), mPoints.end(), isAfter);
1484 int np = getNPoints();
1485 mInnerPointID = np - 1;
1486 if (isCosmic()) {
1487 for (int ip = np; ip--;) {
1488 if (getPoint(ip)->isInvDir()) {
1489 continue;
1490 } // this is a point of upper leg
1491 mInnerPointID = ip;
1492 break;
1493 }
1494 }
1495 //
1496}
1497
1498//______________________________________________
1499void AlignmentTrack::setLocPars(const double* pars)
1500{
1501 // store loc par corrections
1502 memcpy(mLocPar.data(), pars, mNLocPar * sizeof(double));
1503}
1504
1505//______________________________________________
1506void AlignmentTrack::addLocPars(const double* pars)
1507{
1508 // store loc par corrections
1509 for (int i = 0; i < mNLocPar; i++) {
1510 mLocPar[i] += pars[i];
1511 }
1512}
1513
1514//______________________________________________
1516{
1517 // if needed, expand global derivatives buffer
1518 if (mGloParID.size() < minSize) {
1519 mGloParID.resize(minSize);
1520 mDResDGlo[0].resize(minSize);
1521 mDResDGlo[1].resize(minSize);
1522 }
1523}
1524
1525//____________________________________________
1527{
1528 // test track local solution
1529 int npnt = getNPoints();
1530 double mat[mNLocPar][mNLocPar], rhs[mNLocPar];
1531 std::memset(mat, 0, sizeof(double) * mNLocPar * mNLocPar);
1532 std::memset(rhs, 0, sizeof(double) * mNLocPar);
1533 for (int ip = npnt; ip--;) {
1534 if (mPoints[ip]->containsMeasurement()) {
1535 for (int idim = 2; idim--;) { // each point has 2 position residuals
1536 auto sg2inv = 1. / mPoints[ip]->getErrDiag(idim); // inv. error
1537 auto deriv = getDResDLoc(idim, ip); // array of Dresidual/Dparams
1538 for (int parI = 0; parI < mNLocPar; parI++) {
1539 rhs[parI] -= deriv[parI] * mResid[idim][ip] * sg2inv;
1540 for (int parJ = parI; parJ < mNLocPar; parJ++) {
1541 mat[parI][parJ] += deriv[parI] * deriv[parJ] * sg2inv;
1542 }
1543 }
1544 } // loop over 2 orthogonal measurements at the point
1545 } // derivarives at measured points
1546 // if the point contains material, consider its expected kinks, eloss as measurements
1547 if (mPoints[ip]->containsMaterial()) { // at least 4 parameters: 2 spatial + 2 angular kinks with 0 expectaction
1548 int npm = mPoints[ip]->getNMatPar();
1549 // const float* expMatCorr = mPoints[ip]->getMatCorrExp(); // expected correction (diagonalized) // RS??
1550 const auto expMatCov = mPoints[ip]->getMatCorrCov(); // its error
1551 int offs = mPoints[ip]->getMaxLocVarID() - npm;
1552 for (int ipar = 0; ipar < npm; ipar++) {
1553 int parI = offs + ipar;
1554 // expected
1555 // rhs[parI] -= expMatCorr[ipar]/expMatCov[ipar]; // consider expectation as measurement // RS??
1556 mat[parI][parI] += 1. / expMatCov[ipar]; // this measurement is orthogonal to all others
1557 }
1558 } // material effect descripotion params
1559 //
1560 }
1562 for (int i = 0; i < mNLocPar; i++) {
1563 for (int j = i; j < mNLocPar; j++) {
1564 solver.A(i, j) = mat[i][j];
1565 }
1566 solver.B(i, 0) = rhs[i];
1567 }
1568 solver.solve();
1569 // increment current params by new solution
1570 for (int i = 0; i < mNLocPar; i++) {
1571 mLocPar[i] += solver.B(i, 0);
1572 }
1573 return calcResiduals();
1574}
1575
1576//______________________________________________
1578{
1579 // remove last n points, must be called before sortPoints
1580 while (n > 0) {
1581 mDetPoints.pop_back();
1582 n--;
1583 }
1584}
1585
1586} // namespace align
1587} // 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.
size_t minSize
Definition of SymMatrixSolver class.
General auxilliary methods.
Collection of auxillary methods.
std::ostringstream debug
uint32_t res
Definition RawData.h:0
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)
void setKalmanDone(bool v=true)
std::vector< AlignmentPoint * > mPoints
virtual void dumpCoordinates() const
double getResidual(int dim, int pntID) const
AlignmentPoint * getPoint(int i)
bool calcResiduals(const double *params=nullptr)
std::vector< double > mDResDGlo[2]
bool calcResidDeriv(double *params=nullptr)
void checkExpandDerGloBuffer(unsigned int minSize)
bool propagateToPoint(trackParam_t &tr, trackPar_t *linRef, const AlignmentPoint *pnt, double maxStep, double maxSnp=0.95, MatCorrType mt=MatCorrType::USEMatCorrLUT, track::TrackLTIntegral *tLT=nullptr, int signCorr=0)
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)
bool applyMatCorr(trackPar_t &trPar, const double *corrDiag, const AlignmentPoint *pnt)
const double * getDResDLoc(int dim, int pntID) const
void copyFrom(const o2::track::TrackParametrizationWithError< P > &trc)
void setParams(trackPar_t &tr, double x, double alp, const double *par, bool add)
void Print(Option_t *opt="") const final
void modParam(trackPar_t &tr, int par, double delta)
bool propagateParamToPoint(trackPar_t &tr, const AlignmentPoint *pnt, double maxStep=3, double maxSnp=0.95, MatCorrType mt=MatCorrType::USEMatCorrLUT, int signCorr=0)
std::vector< double > mResid[2]
static double richardsonExtrap(double *val, int ord=1)
void richardsonDeriv(const trackPar_t *trSet, const double *delta, const AlignmentPoint *pnt, double &derY, double &derZ)
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:178
double & A(int i, int j)
access to A elements
double & B(int i, int j)
access to B elements
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"