ATLAS Offline Software
Loading...
Searching...
No Matches
CFitCascade.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
23#include <array>
24#include <cmath>
25#include <iostream>
26
27
28namespace Trk {
29
30//--------------------------------------------------------------------
31//
32// Set up masses of combined particles
33//
35{
36 double vBx,vBy,vBz,effectiveField;
37 int it, NTRK;
38 VectMOM totP{};
39
40 if(!vk->nextCascadeVrt)return 0; // nonpointing vertex
41
42 Trk::vkalMagFld::getMagFld(vk->refIterV[0]+vk->fitV[0], vk->refIterV[1]+vk->fitV[1], vk->refIterV[2]+vk->fitV[2],
43 vBx,vBy,vBz,(vk->vk_fitterControl).get());
44
45 NTRK = vk->TrackList.size(); // Number of tracks at vertex
46 totP.Px=0.;totP.Py=0.;totP.Pz=0.;totP.E=0.;
47 for(it=0; it<NTRK; it++){
48 effectiveField = Trk::vkalMagFld::getEffField(vBx, vBy, vBz, vk->TrackList[it]->fitP[1], vk->TrackList[it]->fitP[0]);
49 std::array<double, 4> pp = getFitParticleMom( vk->TrackList[it].get(), effectiveField );
50 totP.Px += pp[0];
51 totP.Py += pp[1];
52 totP.Pz += pp[2];
53 totP.E += pp[3];
54 }
55 VKTrack * target_trk = getCombinedVTrack(vk);
56 if( target_trk == nullptr ) {
57 std::cout<<" ERROR in CASCADE STRUCTURE"<<'\n';
58 return -1;
59 }
60 double Pt=sqrt(totP.Px*totP.Px + totP.Py*totP.Py);
61 double Mass;
62 if(Pt > std::abs(totP.Pz)){
63 Mass = sqrt( (totP.E-Pt)*(totP.E+Pt) - totP.Pz*totP.Pz);
64 }else{
65 Mass = sqrt( (totP.E-totP.Pz)*(totP.E+totP.Pz) - Pt*Pt);
66 }
67 target_trk->setMass(Mass);
68
69 return 0;
70}
71
72long int getVertexCharge( VKVertex * vk){
73 long int tCharge=0;
74 for(int it=0; it<(int)vk->TrackList.size(); it++) tCharge += vk->TrackList[it]->Charge;
75 return tCharge;
76}
77
78double cascadeCnstRemnants(CascadeEvent & cascadeEvent_){
79 double cnstRemnants=0.;
80 for(int iv=0; iv<cascadeEvent_.cascadeNV; iv++){
81 VKVertex * vk = cascadeEvent_.cascadeVertexList[iv].get();
82 for(int ii=0; ii<(int)vk->ConstraintList.size();ii++){
83 for(int ic=0; ic<(int)vk->ConstraintList[ii]->NCDim; ic++){
84 cnstRemnants += std::abs( vk->ConstraintList[ii]->aa[ic] );
85 } }
86 }
87 return cnstRemnants;
88}
89
90int fitVertexCascade( VKVertex * vk, int Pointing)
91{
92//-------------------------------------------------------------------------
93// Fits single vertex in cascade (no iterations , just a single fit!!!)
94// creates summary track after it and fills corresponding track parameters
95// in next vertex in cascade
96//
97// Procedure assumes that "included tracks"(from vertices) are already
98// recalculated in predecessor vertices fits.
99//
100// Pointing=0 (false) - for combined track FITTED at vertex parameters are used
101// ^^^^^^ better convergence
102// Pointing=1 (true) - for combined track GUESSED(ini) at GUESSED(ini) vertex
103// parameters are used together with afterfit error matrix.
104// It's needed for correct treatment of pointing
105//-------------------------------------------------------------------------
106//
107// Fit itself. First get magnetic field at iteration reference point
108//
109 vk->vk_fitterControl->vk_forcft.localbmag=Trk::vkalMagFld::getMagFld(vk->refIterV,(vk->vk_fitterControl).get());
110
111
112//
113//-------- Check if pointing constraint exists
114//
115 bool existPointingCnst=false;
116 for(int ic=0; ic<(int)vk->ConstraintList.size(); ic++){
117 if(vk->ConstraintList[ic]->getType() == VKConstraintType::Point) { existPointingCnst=true; break; }
118 }
119//
120//-------- Then fit
121//
122 applyConstraints(vk); //apply all constraints in vertex
123 int IERR = vtcfit( vk );
124 if(IERR) return IERR;
125 if(vk->Chi2 > 1.e4) return -1; //Protection against bad input vertex candididate
126//
127//fit vertex once more with resolved constraints to prevent oscillations
128// if(Pointing){
129// double targVrt[3]={vk->refIterV[0] + vk->fitV[0],vk->refIterV[1] + vk->fitV[1],vk->refIterV[2] + vk->fitV[2]};
130// vk->vk_fitterControl->vk_forcft.localbmag=myMagFld.getMagFld(vk->targVrt,(vk->vk_fitterControl).get());
131// vk->setRefIterV(targVrt);
132// vk->iniV[0]=vk->fitV[0]=vk->cnstV[0]=vk->iniV[1]=vk->fitV[1]=vk->cnstV[1]=vk->iniV[2]=vk->fitV[2]=vk->cnstV[2]=0.;
133// for(int it=0; it<(int)vk->TrackList.size(); it++){
134// VKTrack * trk = vk->TrackList[it];
135// trk->cnstP[0] = trk->iniP[0] = trk->fitP[0]; // for constraint calculation on next step
136// trk->cnstP[1] = trk->iniP[1] = trk->fitP[1];
137// trk->cnstP[2] = trk->iniP[2] = trk->fitP[2];
138// }
139// applyConstraints(vk); //apply all constraints in vertex
140// int IERR = vtcfit( vk );
141// if(IERR) return IERR;
142// }
143//
144// Fill fitted combined track in next vertex (if needed)
145//
146 if(vk->nextCascadeVrt){
147 FullMTXfill(vk, vk->ader);
148 VKTrack * target_trk = getCombinedVTrack(vk); // get address of combined track
149 if( target_trk == nullptr ) return -12;
150
151 long int Charge=getVertexCharge(vk);
152 if(Charge!=0) Charge=std::copysign(1,Charge);
153 target_trk->Charge=Charge;
154
155 double dptot[4],VrtMomCov[21];
156 double parV0[5],covParV0[15],tmpCov[15],fittedVrt[3];
157 if(Pointing){
158 IERR = afterFitWithIniPar( vk, vk->ader, vk->FVC.dcv, dptot, VrtMomCov, (vk->vk_fitterControl).get());
159 fittedVrt[0]=vk->refIterV[0]+vk->iniV[0];
160 fittedVrt[1]=vk->refIterV[1]+vk->iniV[1];
161 fittedVrt[2]=vk->refIterV[2]+vk->iniV[2];
162 }
163 else{
164 IERR = afterFit( vk, vk->ader, vk->FVC.dcv, dptot, VrtMomCov, (vk->vk_fitterControl).get());
165 fittedVrt[0]=vk->refIterV[0]+vk->fitV[0];
166 fittedVrt[1]=vk->refIterV[1]+vk->fitV[1];
167 fittedVrt[2]=vk->refIterV[2]+vk->fitV[2];
168 }
169 if (IERR) return -13; /* NONINVERTIBLE COV.MATRIX */
170 cfdcopy( dptot, vk->fitMom, 3); //save Momentum
171 cfdcopy(VrtMomCov, vk->fitCovXYZMom, 21); //save XYZMom covariance
172//
173//-- Solution (not ideal!) of cascade covariance problem.
174//-- Covariance of pseudo-particle must be calculated WITHOUT pointing constraint ALWAYS!.
175//
176// if(existPointingCnst){ // use saved matrix without pointing constraint
177// cfdcopy( vk->savedVrtMomCov, VrtMomCov, 21);
178// }else{ // save computed matrix for further use
179// cfdcopy( VrtMomCov, vk->savedVrtMomCov, 21);
180// }
181 if(existPointingCnst){ // add pointed vertex covariance to track
182 for(int km=0; km<6; km++) VrtMomCov[km] += vk->nextCascadeVrt->fitCovXYZMom[km];
183 if(vk->nextCascadeVrt->TrackList[0]->Id>0){ //There is at least one real track in this vertex
184 VrtMomCov[0] *= 1000.;
185 VrtMomCov[2] *= 1000.;
186 VrtMomCov[5] *= 1000.;
187 VrtMomCov[9] *= 1000.;
188 VrtMomCov[14] *= 1000.;
189 VrtMomCov[20] *= 1000.;
190 }
191 }
192//
193// Particle creation and propagation
194 double vBx,vBy,vBz;
195 Trk::vkalMagFld::getMagFld(fittedVrt[0], fittedVrt[1], fittedVrt[2],vBx,vBy,vBz,(vk->vk_fitterControl).get());
196 double lPhi = atan2(dptot[1], dptot[0]);
197 double lTheta = acos(dptot[2] / sqrt(dptot[0]*dptot[0]+dptot[1]*dptot[1]+dptot[2]*dptot[2]));
198 double effectiveField = Trk::vkalMagFld::getEffField(vBx, vBy, vBz, lPhi, lTheta);
199 combinedTrack( Charge, dptot, VrtMomCov, effectiveField, parV0, covParV0);
200 covParV0[0]=std::abs(covParV0[0]); covParV0[2]=std::abs(covParV0[2]); covParV0[5]=std::abs(covParV0[5]);
201 covParV0[9]=std::abs(covParV0[9]); covParV0[14]=std::abs(covParV0[14]); //VK protection against numerical problems
202 Trk::vkalPropagator::Propagate(-999, Charge, parV0, covParV0, fittedVrt,
203 vk->nextCascadeVrt->refIterV, target_trk->Perig, tmpCov, (vk->vk_fitterControl).get());
204// IERR=cfInv5(tmpCov, target_trk->WgtM); if (IERR) IERR=cfdinv(tmpCov, target_trk->WgtM, 5);
205// target_trk->iniP[0]=target_trk->cnstP[0]=target_trk->fitP[0]=target_trk->Perig[2]; //initial guess
206// target_trk->iniP[1]=target_trk->cnstP[1]=target_trk->fitP[1]=target_trk->Perig[3];
207// target_trk->iniP[2]=target_trk->cnstP[2]=target_trk->fitP[2]=target_trk->Perig[4];
208 if( target_trk->fitP[2] == 0.){
209 target_trk->iniP[0]=target_trk->cnstP[0]=target_trk->Perig[2]; //initial guess
210 target_trk->iniP[1]=target_trk->cnstP[1]=target_trk->Perig[3];
211 target_trk->iniP[2]=target_trk->cnstP[2]=target_trk->Perig[4];
212 }else if(Pointing){
213 target_trk->iniP[0]=target_trk->cnstP[0]=target_trk->fitP[0]; //initial guess
214 target_trk->iniP[1]=target_trk->cnstP[1]=target_trk->fitP[1];
215 target_trk->iniP[2]=target_trk->cnstP[2]=target_trk->fitP[2];
216 }else{
217 target_trk->iniP[0]=target_trk->cnstP[0]=(target_trk->fitP[0]+target_trk->Perig[2])/2.; //initial guess
218 target_trk->iniP[1]=target_trk->cnstP[1]=(target_trk->fitP[1]+target_trk->Perig[3])/2.;
219 target_trk->iniP[2]=target_trk->cnstP[2]=(target_trk->fitP[2]+target_trk->Perig[4])/2.;
220 }
221 if(tmpCov[0]>1.e12 || tmpCov[2]>1.e12) return -18; //Something is wrong in combined track creation
222 if(Pointing){tmpCov[0] += target_trk->Perig[0]*target_trk->Perig[0]; tmpCov[2] += target_trk->Perig[1]*target_trk->Perig[1];}
223 tmpCov[0] += 0.0001*0.0001; tmpCov[2] += 0.0002*0.0002; //numerical accuracy protection
224
225 IERR=cfInv5(tmpCov, target_trk->WgtM); if (IERR) IERR=cfdinv(tmpCov, target_trk->WgtM, 5);
226 if (IERR) return -15; /* NONINVERTIBLE COV.MATRIX */
227 }
228//
229// For passing near vertex constraint. Normally first(mother) vertex of cascade
230// Now used also for "close to vertex" mode for cascade
231// For last in structure (mother in cascade...) always calculate it - needed for pointing
232//
233 CascadeEvent & cascadeEvent_ = *(vk->vk_fitterControl->getCascadeEvent());
234 if( vk->passNearVertex || vk==cascadeEvent_.cascadeVertexList[cascadeEvent_.cascadeNV-1].get()){
235 double dptot[4],VrtMomCov[21];
236 IERR = afterFit( vk, vk->ader, vk->FVC.dcv, dptot, VrtMomCov, (vk->vk_fitterControl).get());
237 if (IERR) return -13; /* NONINVERTIBLE COV.MATRIX */
238 cfdcopy( dptot, vk->fitMom, 3); //save Momentum
239 cfdcopy(VrtMomCov, vk->fitCovXYZMom, 21); //save XYZMom covariance
240 }
241 return 0;
242}
243//==============================
244// int processCascadeScale( );
245// int processCascade( ) { int IERR=processCascadeScale(); std::cout<<IERR<<'\n'; return IERR;}
246//-----------------------------------------------------------------------------------
247//
248// Iteration over complete cascade
249//
250int processCascade(CascadeEvent & cascadeEvent_ )
251{
252 int translateToFittedPos(CascadeEvent &, double Step=1.);
253 int restorePreviousPos(CascadeEvent &, std::vector<VKVertex> & );
254
255 VKVertex * vk;
256 long int Iter, IERR, iv, i;
257//============================================================================================
258//
259// First without pointing to get initial estimations and resolve mass constraints
260// This initial step is needed to get initial estimation for "passing near constraint
261//
262 for(iv=0; iv<cascadeEvent_.cascadeNV; iv++){
263 vk = cascadeEvent_.cascadeVertexList[iv].get();
264 IERR = fitVertexCascade( vk, 0); if(IERR)return IERR; //fit
265 IERR = setVTrackMass(vk); if(IERR)return IERR; //mass of combined particle
266 }
267 IERR = translateToFittedPos(cascadeEvent_); if(IERR)return IERR;
268//
269// Now standard fit without pointing in cascade but WITH pointing to PV if present
270//
271
272 double Chi2Old=0.,Chi2Cur=0.;
273 for(Iter=0; Iter<100; Iter++){
274 Chi2Cur=0.;
275 for(iv=0; iv<cascadeEvent_.cascadeNV; iv++){
276 vk = cascadeEvent_.cascadeVertexList[iv].get();
277//
278//Calculate derivatives for "passing near" cnst. Initial vertex position is used for derivatives.
279//Results are saved in ForVRTClose structure
280 if(cascadeEvent_.nearPrmVertex && iv==(cascadeEvent_.cascadeNV-1)){ //only last vertex in cascade may have it
281 double dparst[6]={vk->refIterV[0]+vk->iniV[0], vk->refIterV[1]+vk->iniV[1], vk->refIterV[2]+vk->iniV[2],
282 vk->fitMom[0], vk->fitMom[1], vk->fitMom[2] };
283 vk->FVC.Charge=getVertexCharge(vk);
284 if(vk->FVC.Charge!=0)vk->FVC.Charge=std::copysign(1,vk->FVC.Charge);
285 vpderiv(true, vk->FVC.Charge, dparst, vk->fitCovXYZMom, vk->FVC.vrt, vk->FVC.covvrt,
286 vk->FVC.cvder, vk->FVC.ywgt, vk->FVC.rv0, (vk->vk_fitterControl).get());
287 }
288 IERR = fitVertexCascade( vk, 0); if(IERR)return IERR; //fit
289 IERR = setVTrackMass(vk); if(IERR)return IERR; //mass of combined particle
290 Chi2Cur += vk->Chi2;
291//std::cout<<iv<<"---Chi2="<<vk->Chi2<<", "<<vk->refIterV[0]+vk->fitV[0]<<", "<<vk->refIterV[1]+vk->fitV[1]<<", "<<vk->refIterV[2]+vk->fitV[2]<<'\n';
292 }
293 if(Chi2Cur>1.e6) return -1; //Too bad iteration. Drop fit
294 if( Chi2Cur-Chi2Old > 1. && Iter){ IERR = translateToFittedPos(cascadeEvent_,0.8);} //step limitation is case of divergence
295 else { IERR = translateToFittedPos(cascadeEvent_,1.0);} if(IERR)return IERR;
296
297//std::cout<<" free iter="<<Iter<<", "<<Chi2Cur<<", "<<Chi2Old-Chi2Cur<<"; "<<cascadeEvent_.cascadeNV<<'\n';
298 if(std::abs(Chi2Cur-Chi2Old)<0.01)break; //stable cascade position
299 if(Iter>10 && (Chi2Cur-Chi2Old)>0.)break; //oscillations. Stop preliminary fit
300 Chi2Old=Chi2Cur;
301 }
302// if(Chi2Cur>3000.) return -1; // Initial solution is too bad!!!
303//-------------------------------- Check constraints status
304 double cnstRemnants=cascadeCnstRemnants(cascadeEvent_);
305 if( cnstRemnants > 10000.e0) return -2; /* Constraints are not resolved. Stop fit */
306 if(cnstRemnants==0. && Chi2Cur>3000. ) return -1; // Initial solution is too bad!!!
307 if( Chi2Cur>50000.) return -1; // Initial solution is too bad!!!
308//-------------------------------------------------------------------------
309// Attach pointing constraint to affected vertices and create working arrays
310// of correct size
311//
312 for(iv=0; iv<cascadeEvent_.cascadeNV; iv++){
313 vk = cascadeEvent_.cascadeVertexList[iv].get();
314 if(vk->nextCascadeVrt){
315 long int NTRK = vk->TrackList.size();
316 vk->ConstraintList.emplace_back(new VKPointConstraint( NTRK, vk->nextCascadeVrt->refIterV , vk, false));
317 }
318 }
319 long int fullNPar = getCascadeNPar(cascadeEvent_);
320 if (fullNPar<0) return -1;
321 double * fullMatrix = new double[fullNPar*fullNPar];
322 double * iniCovMatrix = new double[fullNPar*fullNPar];for(int ss=0; ss<fullNPar*fullNPar; ss++) iniCovMatrix[ss]=0.;
323 double * fullLSide = new double[fullNPar];
324 double * tmpLSide = new double[fullNPar];
325 //std::unique_ptr<double[]> tmpLSide = std::unique_ptr<double[]>(new double[fullNPar])
326 std::vector<VKVertex> listVCopy(cascadeEvent_.cascadeNV);
327//-------------------------------------------------------
328// Now fit with pointing constraint
329//
330 cascadeEvent_.matrixPnt.resize(cascadeEvent_.cascadeNV);
331 long int NParCur, NStart;
332 int getBack=0; // counter of oscillations
333 int fullSTOP=0; // immediate stop iteration flag
334 double Chi2Diff=0.;
335
336 int NFitIterationMax=100; // Maximal amount of iterations
337 int badStepCountMax=5; // Maximal amount of bad steps
338
339 cnstRemnants=100000.; double cnstProgr=1.; double minCnstRemnants=100000.;
340 int badStepCount=0;
341
342 for(Iter=0; Iter<=NFitIterationMax; Iter++){
343 Chi2Cur=0.;
344 NStart=0;
345 for( iv=0; iv<fullNPar*fullNPar; iv++)fullMatrix[iv]=0.; // zero full matrix
346 for( iv=0; iv<cascadeEvent_.cascadeNV; iv++){
347 vk = cascadeEvent_.cascadeVertexList[iv].get();
348//
349//Calculate derivatives for "passing near" cnst. Initial vertex position is used for derivatives.
350//Results are saved in ForVRTClose structure
351 if(cascadeEvent_.nearPrmVertex && iv==(cascadeEvent_.cascadeNV-1)){ //only last vertex in cascade may have it
352 double dparst[6]={vk->refIterV[0]+vk->iniV[0], vk->refIterV[1]+vk->iniV[1], vk->refIterV[2]+vk->iniV[2],
353 vk->fitMom[0], vk->fitMom[1], vk->fitMom[2] };
354 vk->FVC.Charge=getVertexCharge(vk);
355 if(vk->FVC.Charge!=0)vk->FVC.Charge=std::copysign(1,vk->FVC.Charge);
356 vpderiv(vk->passWithTrkCov, vk->FVC.Charge, dparst, vk->fitCovXYZMom,
357 vk->FVC.vrt, vk->FVC.covvrt, vk->FVC.cvder, vk->FVC.ywgt, vk->FVC.rv0, (vk->vk_fitterControl).get());
358 }
359 if (vk->vk_fitterControl->vk_forcft.irob != 0) {robtest(vk, 0, Iter);} // ROBUSTIFICATION new data structure
360 if (vk->vk_fitterControl->vk_forcft.irob != 0) {robtest(vk, 1, Iter);} // ROBUSTIFICATION new data structure
361 IERR = fitVertexCascade( vk, 1 ); if(IERR) break; //with passNear for last vertex in cascade if needed
362 IERR = setVTrackMass(vk); if(IERR) break; //mass of combined particle
363//
364//Get full constraint matrix and left side for vertex
365 cascadeEvent_.matrixPnt[iv]=NStart;
366 NParCur = FullMCNSTfill( vk, vk->ader, tmpLSide);
367//
368//Move them to cascade full matrix and left side
369 copyFullMtx( vk->ader, NParCur, NParCur, fullMatrix, NStart, fullNPar);
370//
371//Copy error matrix for left side vector (measured part T,U1,..,Un - see Billoir)
372// to correct place in iniCovMatrix matrix. Only at last step and without constraint part!!! CHECK IT!!!
373 if(Iter==NFitIterationMax || fullSTOP || badStepCount>=badStepCountMax)
374 copyFullMtx( vk->ader, 3+3*vk->TrackList.size(), NParCur, iniCovMatrix, NStart, fullNPar);
375//
376// Fill left part of the system
377 for(i=0; i<NParCur; i++) fullLSide[i+NStart] = tmpLSide[i];
378 NStart += NParCur;
379 Chi2Cur += vk->Chi2;
380//std::cout<<iv<<"--------Chi2="<<vk->Chi2<<", "<<cascadeEvent_.nearPrmVertex<<" nstart="<<NStart<<'\n';
381 }
382 if( (Chi2Cur>1.e8 && Iter>0) || IERR){
383 delete[] fullMatrix; delete[] fullLSide; delete[] tmpLSide; delete[] iniCovMatrix;
384 if(Chi2Cur>1.e8) return -1;
385 return IERR;
386 }
387//
388//--- Attempt to dump oscillations by returning to good position
389 cnstProgr=cascadeCnstRemnants(cascadeEvent_)/cnstRemnants;
390 if( Iter>3 && cnstProgr>4. && getBack<5 && fullSTOP==0 ) { //------ Bad previous step discovered.
391 //std::cout<<" oscillation discovered="<<Iter<<" progr="<<cnstProgr<<'\n';
392 IERR=restorePreviousPos(cascadeEvent_, listVCopy );
393 if(IERR){ delete[] fullMatrix; delete[] fullLSide; delete[] tmpLSide; delete[] iniCovMatrix; return IERR;}
394 cnstRemnants=100000.; Chi2Old+=10000; // to skip restoring on next iteration
395 if(Iter==NFitIterationMax )Iter-=2; // to give time to converge after this operation
396 if(Iter==NFitIterationMax-1)Iter-=1; // to give time to converge after this operation
397 getBack++; badStepCount=0;
398 continue;
399 } //--------- Make some copy of vertices for safety
400 cnstRemnants*=cnstProgr; cnstRemnants += 1.e-6*cascadeEvent_.getAccuracyConstraint(); //VK Protection against 0
401 if(cnstRemnants<minCnstRemnants)minCnstRemnants=cnstRemnants;
402 if(minCnstRemnants==cnstRemnants){ //--------- Make copy of vertices for safety at best point
403 for( iv=0; iv<cascadeEvent_.cascadeNV; iv++){
404 listVCopy.at(iv)=*(cascadeEvent_.cascadeVertexList[iv]); // vertex list copy
405 }
406 }
407//--------------------------------------------------------------------------
408//for( iv=0; iv<fullNPar; iv++)std::cout<<fullLSide[iv]<<", ";std::cout<<'\n';
409// std::cout<<fullLSide[3+3*2]<<", "<<fullLSide[3+3*2+1]<<", "<<
410// fullLSide[20]<<", "<<fullLSide[21]<<", "<<fullLSide[22]<<'\n';
411//---------------------------------------------------------------------------
412//
413// Add cross vertices derivatives
414 addCrossVertexDeriv(cascadeEvent_, fullMatrix, fullNPar, cascadeEvent_.matrixPnt);
415//
416// Add pseudotrack momentum fix
417//
418 int tstRet=fixPseudoTrackPt(fullNPar, fullMatrix, fullLSide, cascadeEvent_ );
419 if( tstRet ){ delete[] fullMatrix; delete[] fullLSide; delete[] tmpLSide; delete[] iniCovMatrix; return -1; }
420//
421// Resolve full cascade with constraints system
422//
423 if( Iter<NFitIterationMax && fullSTOP==0 && badStepCount<badStepCountMax){ //Normal step. Solution of system only
424 IERR = vkMSolve(fullMatrix, fullLSide, fullNPar);
425 if(IERR){ delete[] fullMatrix; delete[] fullLSide; delete[] tmpLSide; delete[] iniCovMatrix;return IERR;}
426 }else{ //Last step. Solution+full error matrix
427 cascadeEvent_.fullCovMatrix.reset( new double[fullNPar*fullNPar] ); //Create fresh matrix
428 IERR = vkMSolve(fullMatrix, fullLSide, fullNPar, cascadeEvent_.fullCovMatrix.get());
429 if(IERR){ delete[] fullMatrix; delete[] fullLSide; delete[] tmpLSide; delete[] iniCovMatrix;
430 cascadeEvent_.fullCovMatrix.reset(); return IERR;}
431//std::cout<<"fulcov="; for(int tt=0; tt<fullNPar; tt++)std::cout<<cascadeEvent_.fullCovMatrix[tt*fullNPar+tt]<<", "; std::cout<<'\n';
432 std::unique_ptr<double[]> newCov(new double[fullNPar*fullNPar]); //Check via error transfer from left side (measured values). Gives exactly the same errors - correct!!!
433 getNewCov(iniCovMatrix, cascadeEvent_.fullCovMatrix.get(), newCov.get(), fullNPar);
434 cascadeEvent_.fullCovMatrix=std::move(newCov); //Unique_ptr will handle deletion automatically
435 }
436//
437// Set fitted parameters
438//
439 setFittedParameters( fullLSide, cascadeEvent_.matrixPnt, cascadeEvent_ );
440//
441// Update pointing constraints and calculate real cascade Chi2
442//
443 double Chi2Full=0.;
444 for(iv=0; iv<cascadeEvent_.cascadeNV; iv++){
445 vk = cascadeEvent_.cascadeVertexList[iv].get();
446 for(int it=0; it<(int)vk->TrackList.size(); it++){
447 VKTrack * trk=vk->TrackList[it].get(); if(trk->Id >= 0)Chi2Full+=trk->Chi2; // real track in cascade
448 }
449 if(cascadeEvent_.nearPrmVertex && iv==(cascadeEvent_.cascadeNV-1)){ //only last vertex in cascade may have it
450 double signift = cfVrtDstSig( vk, vk->passWithTrkCov);
451 Chi2Full += signift*signift;
452 }
453 }
454 Chi2Diff=Chi2Old-Chi2Full;
455 if(Chi2Diff<0. && cnstProgr>0.99) badStepCount++;
456 if(cnstRemnants==minCnstRemnants || cnstProgr<0.9) badStepCount=0;
457//std::cout.precision(5); std::cout<<" iter="<<Iter<<" separ="<<Chi2Cur<<" full="<<Chi2Full<<" iter diff="<<Chi2Full/Chi2Cur<<
458//" cnstrem="<<cnstRemnants<<" progr="<<cnstProgr<<" lim="<<cnstRemnants/minCnstRemnants<<" bstep="<<badStepCount<<'\n';
459 bool badFullStep=false;
460 if( Iter>5 && Chi2Full/Chi2Cur>1.2) badFullStep=true; //VK 16.04.2013 New strategy
461 if( Iter==NFitIterationMax || fullSTOP ) badFullStep=false; //VK 16.04.2013 No step limitation on last iteration
462//
463// Prepare next iteration
464//
465 if(badFullStep) IERR = translateToFittedPos(cascadeEvent_,0.3);
466 else IERR = translateToFittedPos(cascadeEvent_);
467 if(IERR){ delete[] fullMatrix; delete[] fullLSide; delete[] tmpLSide; delete[] iniCovMatrix; return IERR;}
468
469 for(iv=0; iv<cascadeEvent_.cascadeNV; iv++){
470 vk = cascadeEvent_.cascadeVertexList[iv].get();
471 if(vk->nextCascadeVrt){
472 int pntCnst = vk->ConstraintList.size() - 1; // pointing constraint is always last in the list
473 VKPointConstraint * pcnst = dynamic_cast<VKPointConstraint*>(vk->ConstraintList[pntCnst].get());
475 }
476 }
477//
478
479 if(fullSTOP) break;
480 if(cnstRemnants>1.e4&&Iter>10) //no way to fulfil constraints
481 { delete[] fullMatrix; delete[] fullLSide; delete[] tmpLSide; delete[] iniCovMatrix; return -2;}
482//
483 if( Iter<NFitIterationMax && Iter>2){
484 if(std::abs(Chi2Diff)<0.001 && cnstRemnants/minCnstRemnants<10.){ //stable cascade position before end of cycling
485 NFitIterationMax=Iter+1; //then makes additional iteration to get the full error matrix
486 }
487 if(cnstRemnants<cascadeEvent_.getAccuracyConstraint()) fullSTOP++; //Good constraint accuracy is reached
488 }
489 if ( Iter>NFitIterationMax+50 ) break; //Protection - too many iterations due to whatever reason.
490 if(badStepCount>badStepCountMax)break; //Divergence discovered (in both cases the full error matrix is ready!!!)
491
492 Chi2Old=Chi2Full;
493 }
494
495 //if(tmpc0)std::cout<<(*tmpc0)<<'\n';
496 //if(tmpc1)std::cout<<(*tmpc1)<<'\n';
497
498 delete[] fullMatrix; delete[] fullLSide; delete[] tmpLSide; delete[] iniCovMatrix;
499//-------------------------------- Check constraints status
500 cnstRemnants=cascadeCnstRemnants(cascadeEvent_);
501//std::cout<<"fullcnst="<<cnstRemnants<<" lim="<<cnstRemnants/minCnstRemnants<<'\n';
502 if( cnstRemnants > 1.e0) return -2; /* Constraints are not resolved. Stop fit */
503 return 0;
504}
505
506//-----------------------------------------------------------------------------------
507//
508// Iteration over complete cascade with first cascade vertex in Primary Vertex
509//
510 int processCascadePV(CascadeEvent & cascadeEvent_, const double *primVrt, const double *primVrtCov )
511{
512 double aermd[6],tmpd[6]; // temporary arrays
513 VKVertex * vk = cascadeEvent_.cascadeVertexList[cascadeEvent_.cascadeNV-1].get(); //Main vertex
514
515 vk->vk_fitterControl->vk_forcft.vrt[0] = primVrt[0];
516 vk->vk_fitterControl->vk_forcft.vrt[1] = primVrt[1];
517 vk->vk_fitterControl->vk_forcft.vrt[2] = primVrt[2];
518 vk->vk_fitterControl->vk_forcft.covvrt[0] = primVrtCov[0];
519 vk->vk_fitterControl->vk_forcft.covvrt[1] = primVrtCov[1];
520 vk->vk_fitterControl->vk_forcft.covvrt[2] = primVrtCov[2];
521 vk->vk_fitterControl->vk_forcft.covvrt[3] = primVrtCov[3];
522 vk->vk_fitterControl->vk_forcft.covvrt[4] = primVrtCov[4];
523 vk->vk_fitterControl->vk_forcft.covvrt[5] = primVrtCov[5];
524
525 vk->useApriorVertex = 1;
526 cfdcopy(vk->vk_fitterControl->vk_forcft.covvrt, tmpd, 6);
527 int IERR=cfdinv(tmpd, aermd, -3); if (IERR) { IERR = -4; return IERR; }
528 cfdcopy(vk->vk_fitterControl->vk_forcft.vrt, vk->apriorV, 3);
529 cfdcopy( aermd, vk->apriorVWGT,6);
530
531 return processCascade(cascadeEvent_);
532}
533
534//-----------------------------------------------------------------------------------
535//
536// Iteration over complete cascade with "close to primary vertex" Chi2 term
537//
538 int processCascade(CascadeEvent & cascadeEvent_, const double *primVrt, const double *primVrtCov )
539{
540 cascadeEvent_.nearPrmVertex=1; //setting up additional Chi2 term
541 VKVertex * vk = cascadeEvent_.cascadeVertexList[cascadeEvent_.cascadeNV-1].get(); //Main vertex
542 vk->passNearVertex =true; // For fitting machinery
543 vk->passWithTrkCov =true; // For fitting machinery
544 std::copy(primVrt, primVrt+3, vk->FVC.vrt);
545 std::copy(primVrtCov, primVrtCov+6, vk->FVC.covvrt);
546 return processCascade(cascadeEvent_);
547}
548//-----------------------------------------------------------------------------------
549//
550// Iteration over complete cascade with exact pointing to primary vertex
551//
552 int processCascade(CascadeEvent & cascadeEvent_, double *primVrt )
553{
554 VKVertex * vk = cascadeEvent_.cascadeVertexList[cascadeEvent_.cascadeNV-1].get(); //Main vertex
555 long int NTRK = vk->TrackList.size();
556 vk->ConstraintList.emplace_back(new VKPointConstraint( NTRK, primVrt, vk, false));
557 cascadeEvent_.nearPrmVertex=0; //explicitly turn off additional Chi2 term
558 return processCascade(cascadeEvent_);
559}
560
561
562//----------------------------------------------------------------------
563// Translate all external (physics) tracks to fitted vertices positions
564// Step limitation is needed to break positive feedback
565//
566 int translateToFittedPos(CascadeEvent & cascadeEvent_, double Step )
567{
568 int iv,it;
569 long int IERR,NTRK;
570 double vShift, tmpPer[5], tmpWgt[15], tmpCov[15], targetVertex[3];
571 VKTrack * trk; VKVertex * vk;
572 if(Step>1.)Step=1.;
573
574 for( iv=0; iv<cascadeEvent_.cascadeNV; iv++){
575 vk=cascadeEvent_.cascadeVertexList[iv].get();
576 NTRK = vk->TrackList.size(); // Number of tracks at vertex
577 targetVertex[0]=vk->refIterV[0] + vk->fitV[0]*Step; // target vertex for extrapolation
578 targetVertex[1]=vk->refIterV[1] + vk->fitV[1]*Step;
579 targetVertex[2]=vk->refIterV[2] + vk->fitV[2]*Step;
580 vShift = sqrt( (vk->refV[0]-targetVertex[0])*(vk->refV[0]-targetVertex[0])
581 +(vk->refV[1]-targetVertex[1])*(vk->refV[1]-targetVertex[1])
582 +(vk->refV[2]-targetVertex[2])*(vk->refV[2]-targetVertex[2]) );
583 for(auto *pvx : vk->includedVrt){ //Check space position of internal vertex
584 double dirMom=(pvx->refIterV[0]-targetVertex[0])*pvx->fitMom[0]+
585 (pvx->refIterV[1]-targetVertex[1])*pvx->fitMom[1]+
586 (pvx->refIterV[2]-targetVertex[2])*pvx->fitMom[2];
587 if(dirMom<0.)cfdcopy(pvx->refIterV,targetVertex,3);
588 }
589 bool insideGoodVolume=false;
590 if(vk->vk_fitterControl && vk->vk_fitterControl->vk_objProp)
591 { insideGoodVolume = vk->vk_fitterControl->vk_objProp->checkTarget(targetVertex, *vk->vk_fitterControl->vk_istate);}
592 else { insideGoodVolume = Trk::vkalPropagator::checkTarget(targetVertex); }
593 if(!insideGoodVolume) { return -16; } //Vertex is definitely outside working volume
594 for(it=0; it<NTRK; it++){
595 trk=vk->TrackList[it].get();
596 if(trk->Id < 0){ // pseudo-track from cascade vertex
597 trk->fitP[0] =trk->iniP[0]+ Step*(trk->fitP[0]-trk->iniP[0]);
598 trk->fitP[1] =trk->iniP[1]+ Step*(trk->fitP[1]-trk->iniP[1]);
599 trk->fitP[2] =trk->iniP[2]+ Step*(trk->fitP[2]-trk->iniP[2]);
600 continue;
601 }
602 Trk::vkalPropagator::Propagate(trk, vk->refV, targetVertex, tmpPer, tmpCov, (vk->vk_fitterControl).get());
603 //Check!!!And protection if needed.
604 double eig5=cfSmallEigenvalue(tmpCov,5 );
605 if(eig5<1.e-15 || tmpCov[0]>1.e7) { //Bad propagation with material. Try without it.
606 Trk::vkalPropagator::Propagate(-999, trk->Charge,trk->refPerig,trk->refCovar, vk->refV, targetVertex, tmpPer, tmpCov, (vk->vk_fitterControl).get());
607 if(cfSmallEigenvalue(tmpCov,5 )<1.e-15){ //Final protection
608 tmpCov[1]=0.;tmpCov[3]=0.;tmpCov[6]=0.;tmpCov[10]=0.;
609 tmpCov[4]=0.;tmpCov[7]=0.;tmpCov[11]=0.;
610 tmpCov[8]=0.;tmpCov[12]=0.;
611 tmpCov[13]=0.;
612 tmpCov[0]=std::abs(tmpCov[0]); tmpCov[2]=std::abs(tmpCov[2]);tmpCov[5]=std::abs(tmpCov[5]);
613 tmpCov[9]=std::abs(tmpCov[9]); tmpCov[14]=std::abs(tmpCov[14]);
614 }
615 }
616 if(tmpCov[0]>1.e7){ IERR=-7; return IERR; } //extremely big A0 error !!!
617 IERR=cfInv5(tmpCov, tmpWgt); if (IERR) IERR=cfdinv(tmpCov, tmpWgt, 5); if(IERR)return -8;
618 trk->setCurrent(tmpPer,tmpWgt);
619 if ( vShift > 100. ) trk->setReference( tmpPer, tmpCov ); //Change reference for big shift
620 }
621 vk->setRefIterV(targetVertex);
622 if ( vShift > 100. )vk->setRefV(targetVertex); // Change reference vertex for big shift
623 vk->iniV[0] = vk->fitV[0] = vk->cnstV[0]=0.;
624 vk->iniV[1] = vk->fitV[1] = vk->cnstV[1]=0.;
625 vk->iniV[2] = vk->fitV[2] = vk->cnstV[2]=0.;
626 for(it=0; it<NTRK; it++){
627 trk=vk->TrackList[it].get();
628 if(Step<1.){ // Step limitation for constraint calculation on next step
629 trk->cnstP[0] = trk->iniP[0] =trk->iniP[0]+ Step*(trk->fitP[0]-trk->iniP[0]);
630 trk->cnstP[1] = trk->iniP[1] =trk->iniP[1]+ Step*(trk->fitP[1]-trk->iniP[1]);
631 trk->cnstP[2] = trk->iniP[2] =trk->iniP[2]+ Step*(trk->fitP[2]-trk->iniP[2]);
632 }else{
633 trk->cnstP[0] = trk->iniP[0] = trk->fitP[0]; // for constraint calculation on next step
634 trk->cnstP[1] = trk->iniP[1] = trk->fitP[1];
635 trk->cnstP[2] = trk->iniP[2] = trk->fitP[2];
636 }
637 }
638 }
639 return 0;
640}
641
642//----------------------------------------------------------------------
643// Translate all external (physics) tracks to fitted vertices positions
644// Step limitation is needed to break positive feedback
645//
646int restorePreviousPos(CascadeEvent & cascadeEvent_, std::vector<VKVertex> & SV )
647{
648 int iv,it;
649 long int NTRK;
650 VKTrack * trk; VKTrack * trks; VKVertex * vk; VKVertex * vks;
651
652 for( iv=0; iv<cascadeEvent_.cascadeNV; iv++){
653 vk=cascadeEvent_.cascadeVertexList[iv].get();
654 vks=&SV[iv];
655 NTRK = vk->TrackList.size(); // Number of tracks at vertex
656 vk->refIterV[0]=vks->refIterV[0];
657 vk->refIterV[1]=vks->refIterV[1];
658 vk->refIterV[2]=vks->refIterV[2];
659 vk->iniV[0] = vk->fitV[0] = vk->cnstV[0]=0.;
660 vk->iniV[1] = vk->fitV[1] = vk->cnstV[1]=0.;
661 vk->iniV[2] = vk->fitV[2] = vk->cnstV[2]=0.;
662 cfdcopy(vks->fitMom, vk->fitMom, 3); //saved Momentum
663 cfdcopy(vks->fitCovXYZMom, vk->fitCovXYZMom, 21); //saved XYZMom covariance
664 for(it=0; it<NTRK; it++){
665 trk =vk ->TrackList[it].get(); // working track
666 trks=vks->TrackList[it].get(); // track from saved copy
667 if(trk->Id < 0) { // pseudo-track from cascade vertex
668 //trk->fitP[2]=0.; // reset the pseudo-track parameters
669 trk->fitP[0] =(trks->iniP[0]+trks->fitP[0])/2.;
670 trk->fitP[1] = trks->iniP[1];
671 trk->fitP[2] =(trks->iniP[2]+trks->fitP[2])/2.;
672 continue;
673 }
674 cfdcopy(trks->Perig, trk->Perig, 5);
675 cfdcopy(trks->WgtM, trk->WgtM, 15);
676 cfdcopy(trks->fitP, trk->fitP, 3);
677 cfdcopy(trks->iniP, trk->iniP, 3);
678 cfdcopy(trks->cnstP, trk->cnstP, 3);
679 }
680 }
681 for(iv=0; iv<cascadeEvent_.cascadeNV; iv++){
682 vk = cascadeEvent_.cascadeVertexList[iv].get();
683 if(vk->nextCascadeVrt){
684 int pntCnst = vk->ConstraintList.size() - 1; // pointing constraint is always last in the list
685 if(vk->ConstraintList[pntCnst]->getType() != VKConstraintType::Point) return -1;
686 static_cast< VKPointConstraint* >(vk->ConstraintList[pntCnst].get())->setTargetVertex(vk->nextCascadeVrt->refIterV);
687 }
688 }
689 return 0;
690}
691
692void getFittedCascade( CascadeEvent & cascadeEvent_,
693 std::vector< Vect3DF > & cVertices,
694 std::vector< std::vector<double> > & covVertices,
695 std::vector< std::vector< VectMOM> > & fittedParticles,
696 std::vector< std::vector<double> > & cascadeCovar,
697 std::vector<double> & particleChi2,
698 std::vector<double> & fullCovar)
699{
700 cVertices.clear();
701 covVertices.clear();
702 fittedParticles.clear();
703 particleChi2.clear();
704//
705// Split common covariance matrix into pieces
706//
707 std::vector< std::vector<double> > cascadeCovarFit;
708 setFittedMatrices(cascadeEvent_.fullCovMatrix.get(), getCascadeNPar(cascadeEvent_), cascadeEvent_.matrixPnt, cascadeCovarFit, cascadeEvent_);
709//
710 double vBx,vBy,vBz,pp2,pt,invR,effectiveField;
711 int iv,it,jt, NTRK, pnt;
712//
713 int PDIM=getCascadeNPar(cascadeEvent_, 1); // number of physics parametrs
714 int ADIM=getCascadeNPar(cascadeEvent_, 0); // number of ALL parametrs
715 double **DPhys = new double*[PDIM]; for(it=0; it<PDIM; it++) DPhys[it] = new double[ADIM];
716 for(it=0;it<PDIM;it++) for(jt=0;jt<ADIM;jt++)DPhys[it][jt]=0.;
717//
718//
719 Vect3DF vrtPos;
720 VectMOM prtMom{};
721 VKVertex * vk;
722 std::vector<VectMOM> momCollector;
723 std::vector<double> tmpCov(6);
724//
725 int pntPhys=0; // Counter for physics cascade parameters
726 for( iv=0; iv<cascadeEvent_.cascadeNV; iv++){
727 vk=cascadeEvent_.cascadeVertexList[iv].get();
728 vrtPos.X=vk->refIterV[0] + vk->fitV[0]; // target vertex for extrapolation
729 vrtPos.Y=vk->refIterV[1] + vk->fitV[1];
730 vrtPos.Z=vk->refIterV[2] + vk->fitV[2];
731 cVertices.push_back(vrtPos);
732 NTRK = vk->TrackList.size(); // Number of tracks at vertex
733 momCollector.clear();
734 int DIM=3*(NTRK+1);
735 double **Deriv = new double*[DIM]; for(it=0; it<DIM; it++) Deriv[it] = new double[DIM];
736 for(it=0;it<DIM;it++) for(jt=0;jt<DIM;jt++)Deriv[it][jt]=0.;
737 Deriv[0][0]=1.;Deriv[1][1]=1.;Deriv[2][2]=1.;
738 DPhys[pntPhys+0][cascadeEvent_.matrixPnt[iv]+0]=1.;
739 DPhys[pntPhys+1][cascadeEvent_.matrixPnt[iv]+1]=1.;
740 DPhys[pntPhys+2][cascadeEvent_.matrixPnt[iv]+2]=1.;
741 Trk::vkalMagFld::getMagFld(vk->refIterV[0]+vk->fitV[0], vk->refIterV[1]+vk->fitV[1], vk->refIterV[2]+vk->fitV[2],
742 vBx,vBy,vBz,(vk->vk_fitterControl).get());
743 for(it=0; it<NTRK; it++){
744 effectiveField = Trk::vkalMagFld::getEffField(vBx, vBy, vBz, vk->TrackList[it]->fitP[1], vk->TrackList[it]->fitP[0]);
745 std::array<double, 4> pp = getFitParticleMom( vk->TrackList[it].get(), effectiveField );
746 prtMom.Px=pp[0]; prtMom.Py=pp[1]; prtMom.Pz=pp[2]; prtMom.E=pp[3];
747 momCollector.push_back( prtMom );
748 if(vk->TrackList[it]->Id >= 0) particleChi2.push_back( vk->TrackList[it]->Chi2 ); //Only real tracks
749 pp2 = pp[0]*pp[0] + pp[1]*pp[1] +pp[2]*pp[2];
750 pt = sqrt(pp[0]*pp[0] + pp[1]*pp[1]);
751 invR = vk->TrackList[it]->fitP[2];
752
753 pnt = it*3+3;
754 DPhys[pntPhys+pnt+0][cascadeEvent_.matrixPnt[iv]+pnt+0]= Deriv[pnt+0][pnt+0]= 0 ; //dPx/dTheta
755 DPhys[pntPhys+pnt+0][cascadeEvent_.matrixPnt[iv]+pnt+1]= Deriv[pnt+0][pnt+1]= -pp[1]; //dPx/dPhi
756 DPhys[pntPhys+pnt+0][cascadeEvent_.matrixPnt[iv]+pnt+2]= Deriv[pnt+0][pnt+2]= -pp[0]/invR; //dPx/dinvR
757
758 DPhys[pntPhys+pnt+1][cascadeEvent_.matrixPnt[iv]+pnt+0]= Deriv[pnt+1][pnt+0]= 0 ; //dPy/dTheta
759 DPhys[pntPhys+pnt+1][cascadeEvent_.matrixPnt[iv]+pnt+1]= Deriv[pnt+1][pnt+1]= pp[0]; //dPy/dPhi
760 DPhys[pntPhys+pnt+1][cascadeEvent_.matrixPnt[iv]+pnt+2]= Deriv[pnt+1][pnt+2]= -pp[1]/invR; //dPy/dinvR
761
762 DPhys[pntPhys+pnt+2][cascadeEvent_.matrixPnt[iv]+pnt+0]= Deriv[pnt+2][pnt+0]= -pp2/pt; //dPz/dTheta
763 DPhys[pntPhys+pnt+2][cascadeEvent_.matrixPnt[iv]+pnt+1]= Deriv[pnt+2][pnt+1]= 0 ; //dPz/dPhi
764 DPhys[pntPhys+pnt+2][cascadeEvent_.matrixPnt[iv]+pnt+2]= Deriv[pnt+2][pnt+2]= -pp[2]/invR; //dPz/dinvR
765 }
766 pntPhys += DIM;
767 fittedParticles.push_back(momCollector);
768 cascadeCovar.push_back( transformCovar(DIM, Deriv, cascadeCovarFit[iv] ) ); //Transform covariance and save it
769 for(int kk=0; kk<6; kk++) tmpCov[kk]=cascadeCovar[iv][kk];
770 covVertices.push_back(tmpCov);
771 for(it=0; it<DIM; it++) delete[]Deriv[it];
772 delete[]Deriv;
773 }
774//
775// Get full physics covariance
776 int itn,jtn;
777 fullCovar.resize(PDIM*(PDIM+1)/2);
778 for(it=0; it<PDIM; it++){
779 for(jt=0; jt<=it; jt++){
780 double tmp=0.;
781 for(itn=0; itn<ADIM; itn++) for(jtn=0; jtn<ADIM; jtn++) tmp += DPhys[it][itn]*DPhys[jt][jtn]*cascadeEvent_.fullCovMatrix[itn*ADIM+jtn];
782 fullCovar[it*(it+1)/2+jt]=tmp; // symmetrical index formula works ONLY if it>=jt!!!
783 }
784 }
785 for(it=0; it<PDIM; it++) delete[]DPhys[it];
786 delete[]DPhys;
787}
788
789
790
791} /* End of VKalVrtCore namespace */
static Double_t ss
double getAccuracyConstraint() const
std::vector< int > matrixPnt
std::unique_ptr< double[]> fullCovMatrix
std::vector< std::unique_ptr< VKVertex > > cascadeVertexList
void setTargetVertex(double VRT[3])
Definition Derivt.h:95
double refCovar[15]
void setReference(const double[], const double[])
void setCurrent(const double[], const double[])
void setMass(double M)
void setRefIterV(double v[]) noexcept
std::vector< VKVertex * > includedVrt
std::vector< std::unique_ptr< VKTrack > > TrackList
double ader[(3 *vkalNTrkM+3) *(3 *vkalNTrkM+3)]
std::vector< std::unique_ptr< VKConstraintBase > > ConstraintList
double fitCovXYZMom[21]
void setRefV(double v[3]) noexcept
VKVertex * nextCascadeVrt
std::unique_ptr< VKalVrtControl > vk_fitterControl
static void getMagFld(const double, const double, const double, double &, double &, double &, const VKalVrtControlBase *)
static double getEffField(double bx, double by, double bz, double phi, double theta)
Definition VKalVrtBMag.h:60
static bool checkTarget(double *RefEnd)
static void Propagate(long int TrkID, long int Charge, double *ParOld, double *CovOld, double *RefStart, double *RefEnd, double *ParNew, double *CovNew, VKalVrtControlBase *FitControl=0)
Ensure that the ATLAS eigen extensions are properly loaded.
void vpderiv(bool UseTrackErr, long int Charge, const double *pari0, double *covi, double *vrtref, double *covvrtref, double *drdpar, double *dwgt, double *rv0, VKalVrtControl *FitCONTROL)
Definition VtDeriv.cxx:16
void cfdcopy(double *source, double *target, int n)
void FullMTXfill(VKVertex *vk, double *ader)
Definition FullMtx.cxx:19
void getNewCov(const double *OldCov, const double *Der, double *Cov, long int DIM) noexcept
int translateToFittedPos(CascadeEvent &cascadeEvent_, double Step)
void setFittedParameters(const double *result, std::vector< int > &matrixPnt, CascadeEvent &cascadeEvent_)
void getFittedCascade(CascadeEvent &cascadeEvent_, std::vector< Vect3DF > &cVertices, std::vector< std::vector< double > > &covVertices, std::vector< std::vector< VectMOM > > &fittedParticles, std::vector< std::vector< double > > &cascadeCovar, std::vector< double > &particleChi2, std::vector< double > &fullCovar)
int fixPseudoTrackPt(long int NPar, double *fullMtx, double *LSide, CascadeEvent &cascadeEvent_)
int cfInv5(double *cov, double *wgt)
int processCascade(CascadeEvent &cascadeEvent_)
double cascadeCnstRemnants(CascadeEvent &cascadeEvent_)
int cfdinv(double *cov, double *wgt, long int NI)
void copyFullMtx(const double *Input, long int IPar, long int IDIM, double *Target, long int TStart, long int TDIM)
int setVTrackMass(VKVertex *vk)
void setFittedMatrices(const double *COVFIT, long int MATRIXSIZE, std::vector< int > &matrixPnt, std::vector< std::vector< double > > &covarCascade, CascadeEvent &cascadeEvent_)
int getCascadeNPar(CascadeEvent &cascadeEvent_, int Type)
int afterFitWithIniPar(VKVertex *vk, double *ader, double *dcv, double *ptot, double *VrtMomCov, const VKalVrtControlBase *CONTROL)
Definition cfTotCov.cxx:83
void combinedTrack(long int ICH, double *pv0, double *covi, double effectiveBMAG, double *par, double *covo)
Definition XYZtrp.cxx:113
VKTrack * getCombinedVTrack(VKVertex *vk)
int FullMCNSTfill(VKVertex *vk, double *ader, double *LSide)
Definition FullMtx.cxx:81
void addCrossVertexDeriv(CascadeEvent &cascadeEvent_, double *ader, long int MATRIXSIZE, const std::vector< int > &matrixPnt)
int fitVertexCascade(VKVertex *vk, int Pointing)
std::vector< double > transformCovar(int NPar, double **Deriv, const std::vector< double > &covarI)
int vtcfit(VKVertex *vk)
Definition VtCFit.cxx:287
long int getVertexCharge(VKVertex *vk)
int restorePreviousPos(CascadeEvent &cascadeEvent_, std::vector< VKVertex > &SV)
double cfVrtDstSig(VKVertex *vk, bool UseTrkErr)
Definition cfVrtDst.cxx:33
std::array< double, 4 > getFitParticleMom(const VKTrack *trk, const VKVertex *vk)
void applyConstraints(VKVertex *vk)
Definition stCnst.cxx:22
void robtest(VKVertex *vk, int ifl, int nIteration)
Definition RobTest.cxx:14
int processCascadePV(CascadeEvent &cascadeEvent_, const double *primVrt, const double *primVrtCov)
int vkMSolve(double *a, double *b, long int n, double *ainv)
int afterFit(VKVertex *vk, double *ader, double *dcv, double *ptot, double *VrtMomCov, const VKalVrtControlBase *CONTROL)
Definition cfTotCov.cxx:26
double cfSmallEigenvalue(double *cov, long int n)
double covvrt[6]
Definition ForVrtClose.h:23
double cvder[12]
Definition ForVrtClose.h:30
double dcv[6 *(vkalNTrkM *3+3)]
Definition ForVrtClose.h:31