ATLAS Offline Software
Loading...
Searching...
No Matches
CascadeUtils.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
11#include <array>
12#include <cmath>
13#include <iostream>
15#include <algorithm>
16
17namespace Trk {
18
19// Add to system matrix the derivatives due to pseudotrack constraints
20int fixPseudoTrackPt(long int NPar, double * fullMtx, double * LSide, CascadeEvent & cascadeEvent_)
21{
22
23 int iv,it,ivnext;
24 //Deliberately not make_unique to bypass inititalization
25 std::unique_ptr<double[]> DerivC( new double[NPar] );
26 std::unique_ptr<double[]> DerivP( new double[NPar] );
27 std::unique_ptr<double[]> DerivT( new double[NPar] );
28//
29 std::vector<double> vMagFld; double vBx,vBy,vBz;
30 for( iv=0; iv<cascadeEvent_.cascadeNV; iv++){
31 VKVertex * vk = cascadeEvent_.cascadeVertexList[iv].get();
32 Trk::vkalMagFld::getMagFld(vk->refIterV[0]+vk->iniV[0], vk->refIterV[1]+vk->iniV[1], vk->refIterV[2]+vk->iniV[2],vBx,vBy,vBz,(vk->vk_fitterControl).get());
33 vMagFld.push_back(vBz); // fill mag.fields for all vertices
34 }
35//
36 for( iv=0; iv<cascadeEvent_.cascadeNV; iv++){
37 int indCombTrk=-1;
38 int iniPosTrk=0; /* Start of track part of vertex in global matrix */
39 int posCombTrk=0; /* Conbined track position in global matrix */
40 VKVertex* vk = cascadeEvent_.cascadeVertexList[iv].get();
41 if(vk->nextCascadeVrt){ //next vertex exists
42 ivnext=-1; //index of next vertex in common structure
43 for(int ivt=0;ivt<cascadeEvent_.cascadeNV;ivt++)if(vk->nextCascadeVrt==cascadeEvent_.cascadeVertexList[ivt].get())ivnext=ivt;
44 if(ivnext<0){return -1;}; //error in cascade
45//
46 int NV=vk->nextCascadeVrt->includedVrt.size();
47 if(NV>0){
48 for(it=0; it<NV; it++)
49 if(vk->nextCascadeVrt->includedVrt[it] == vk)
50 indCombTrk=vk->nextCascadeVrt->TrackList.size() - NV + it; // index of combined track in next vertex track list
51 }
52 if(indCombTrk>=0){
53 iniPosTrk =cascadeEvent_.matrixPnt[iv]+3; /*Start of track part of vertex in global matrix */
54 posCombTrk =cascadeEvent_.matrixPnt[ivnext]+3+3*indCombTrk; /*Get position in global matrix */
55 }
56 if(posCombTrk==0 || iniPosTrk==0) {return -1;} //ERROR in cascade structure somewhere....
57//
58// Momentum of pseudo track in next vertex
59 for(int ivt=0; ivt<NPar; ivt++)DerivC[ivt]=DerivP[ivt]=DerivT[ivt]=0.;
60 DerivC[posCombTrk+2]=-1.;
61 DerivT[posCombTrk+0]=-1.;
62 DerivP[posCombTrk+1]=-1.;
63 std::array<double, 4> ppsum = getIniParticleMom( vk->nextCascadeVrt->TrackList[indCombTrk].get(), vMagFld[ivnext] ); // INI for pseudo
64 double csum=vk->nextCascadeVrt->TrackList[indCombTrk]->iniP[2]; // INI for pseudo
65 double ptsum=sqrt(ppsum[0]*ppsum[0] + ppsum[1]*ppsum[1]);
66 double sinth2sum=(ppsum[0]*ppsum[0] + ppsum[1]*ppsum[1])/(ppsum[0]*ppsum[0] + ppsum[1]*ppsum[1] + ppsum[2]*ppsum[2]);
67
68//
69// Momenta+Derivatives of tracks in vertex itself
70 for(it=0; it<(int)vk->TrackList.size(); it++){
71 std::array<double, 4> pp = getIniParticleMom( vk->TrackList[it].get(), vMagFld[iv]);
72 double curv=vk->TrackList[it]->iniP[2];
73 double pt=sqrt(pp[0]*pp[0] + pp[1]*pp[1]);
74 double cth=pp[2]/pt;
75 double sinth2=(pp[0]*pp[0] + pp[1]*pp[1])/(pp[0]*pp[0] + pp[1]*pp[1] + pp[2]*pp[2]);
76 DerivC[iniPosTrk+it*3+1] = csum/ptsum/ptsum*(ppsum[0]*pp[1]-ppsum[1]*pp[0]); // dC/dPhi_i
77 DerivC[iniPosTrk+it*3+2] = csum/ptsum/ptsum*(ppsum[0]*pp[0]+ppsum[1]*pp[1])/curv; // dC/dC_i
78 DerivP[iniPosTrk+it*3+1] = (ppsum[0]*pp[0]+ppsum[1]*pp[1])/ptsum/ptsum; // dPhi/dPhi_i
79 DerivP[iniPosTrk+it*3+2] = (ppsum[1]*pp[0]-ppsum[0]*pp[1])/ptsum/ptsum/curv; // dPhi/dC_i
80 DerivT[iniPosTrk+it*3+0] = (sinth2sum*pt)/(sinth2*ptsum); // dTheta/dTheta_i
81 DerivT[iniPosTrk+it*3+2] = (sinth2sum*pt*cth)/(curv*ptsum); // dTheta/dC_i
82 }
83// double iniV0Curv=myMagFld.getCnvCst()*vMagFld[iv]/sqrt(tpx*tpx+tpy*tpy); //initial PseudoTrack Curvature
84// if(csum<0)iniV0Curv *= -1.;
85// iniV0Curv *= vMagFld[ivnext]/vMagFld[iv]; //magnetic field correction
86//
87//fill Full Matrix and left side vector
88//
89//---- Momentum only
90// for(it=0; it<NPar; it++) fullMtx[ (NPar-1*(cascadeEvent_.cascadeNV-1)+1*iv )*NPar + it] = DerivC[it];
91// for(it=0; it<NPar; it++) fullMtx[ (NPar-1*(cascadeEvent_.cascadeNV-1)+1*iv ) + it*NPar] = DerivC[it];
92// LSide[ NPar-1*(cascadeEvent_.cascadeNV-1)+1*iv] = -iniV0Curv+csum;
93//---- Momentum+phi+theta //VK seems overshooting because direction is fixed by vertex-vertex pointing. Returns wrong error matrix
94 for(it=0; it<NPar; it++) fullMtx[ (NPar-3*(cascadeEvent_.cascadeNV-1)+3*iv )*NPar + it] = DerivT[it];
95 for(it=0; it<NPar; it++) fullMtx[ (NPar-3*(cascadeEvent_.cascadeNV-1)+3*iv+1)*NPar + it] = DerivP[it];
96 for(it=0; it<NPar; it++) fullMtx[ (NPar-3*(cascadeEvent_.cascadeNV-1)+3*iv+2)*NPar + it] = DerivC[it];
97 for(it=0; it<NPar; it++) fullMtx[ (NPar-3*(cascadeEvent_.cascadeNV-1)+3*iv ) + it*NPar] = DerivT[it];
98 for(it=0; it<NPar; it++) fullMtx[ (NPar-3*(cascadeEvent_.cascadeNV-1)+3*iv+1) + it*NPar] = DerivP[it];
99 for(it=0; it<NPar; it++) fullMtx[ (NPar-3*(cascadeEvent_.cascadeNV-1)+3*iv+2) + it*NPar] = DerivC[it];
100 VKTrack* cmbt=vk->nextCascadeVrt->TrackList[indCombTrk].get();
101 LSide[ NPar-3*(cascadeEvent_.cascadeNV-1)+3*iv ] = cmbt->iniP[0]-cmbt->Perig[2];
102 LSide[ NPar-3*(cascadeEvent_.cascadeNV-1)+3*iv+1] = cmbt->iniP[1]-cmbt->Perig[3];
103 LSide[ NPar-3*(cascadeEvent_.cascadeNV-1)+3*iv+2] = cmbt->iniP[2]-cmbt->Perig[4];
104 }
105
106 } //end of vertex cycle
107 return 0; //All ok
108}
109//---------------------------------------------------------------------------
110// Returns address of VTrack of combined track for given vertex
111//
113{
114 if(!vk->nextCascadeVrt) return nullptr; //nonpointing vertex
115 int NV=vk->nextCascadeVrt->includedVrt.size();
116 if(NV==0) return nullptr; //Error in structure
117
118 int itv=-1;
119 for(int it=0; it<NV; it++) if(vk->nextCascadeVrt->includedVrt[it] == vk) {itv=it; break;};
120 if(itv<0) return nullptr; // Not found in list
121
122 int totNT = vk->nextCascadeVrt->TrackList.size();
123 return vk->nextCascadeVrt->TrackList[totNT - NV + itv].get(); // pointer to combined track in next vertex
124}
125
126
127//---------------------------------------------------------------------------
128// Returns dimension of full matrix for cascade fit
129// At the end the place for pseudotrack(all!) momenta(3) constraints
130// By default (Type=0) return full cascade NPar.
131// For Type=1 returns amount of physics parameters only (without all constraints)
132//
133// MUST BE CONSISTENT WITH fixPseudoTrackPt(...)!!!
134//
135int getCascadeNPar(CascadeEvent & cascadeEvent_, int Type/*=0*/)
136{
137 int NV=cascadeEvent_.cascadeNV;
138 int NTrk=0;
139 int NCnst=0;
140 for( int iv=0; iv<cascadeEvent_.cascadeNV; iv++){
141 VKVertex *vk = cascadeEvent_.cascadeVertexList[iv].get();
142 NTrk += vk->TrackList.size();
143 for(int ic=0; ic<(int)vk->ConstraintList.size();ic++) NCnst += vk->ConstraintList[ic]->NCDim;
144 }
145 if(Type==1) return 3*(NV+NTrk); // Return amount of physics parameters
146 return 3*(NV+NTrk)+NCnst + 3*(cascadeEvent_.cascadeNV-1); //additional 3 momentum constraints
147 //return 3*(NV+NTrk)+NCnst + 1*(cascadeEvent_.cascadeNV-1); //additional 1 momentum constraints
148}
149
150//
151// Track parameters are translated at each iteration so iniV==(0,0,0)
152//
153void setFittedParameters(const double * result, std::vector<int> & matrixPnt, CascadeEvent & cascadeEvent_)
154{
155 int iv,it,Pnt;
156 for( iv=0; iv<cascadeEvent_.cascadeNV; iv++){
157 VKVertex *vk = cascadeEvent_.cascadeVertexList[iv].get();
158 Pnt=matrixPnt[iv]; // start of vertex parameters
159 vk->fitV[0]=result[Pnt]; vk->fitV[1]=result[Pnt+1]; vk->fitV[2]=result[Pnt+2];
160 for( it=0; it<(int)vk->TrackList.size(); it++){
161 VKTrack * trk=vk->TrackList[it].get();
162 trk->fitP[0]=trk->iniP[0]+result[Pnt+3+it*3 + 0];
163 trk->fitP[1]=trk->iniP[1]+result[Pnt+3+it*3 + 1];
164 trk->fitP[2]=trk->iniP[2]+result[Pnt+3+it*3 + 2];
165 trk->Chi2 = cfchi2(vk->fitV, trk->fitP, trk );
166 }
167 }
168}
169
170void setFittedMatrices(const double * COVFIT, long int MATRIXSIZE,
171 std::vector<int> & matrixPnt,
172 std::vector< std::vector<double> > & covarCascade,
173 CascadeEvent & cascadeEvent_)
174{
175 int iv, Pnt, ic, ir, vrtMtxSize, count;
176 for( iv=0; iv<cascadeEvent_.cascadeNV; iv++){
177 VKVertex *vk = cascadeEvent_.cascadeVertexList[iv].get();
178 Pnt=matrixPnt[iv]; // start of vertex parameters
179 vrtMtxSize=3+vk->TrackList.size()*3; //size of matrix for given vertex
180 std::vector<double> Res(vrtMtxSize*(vrtMtxSize+1)/2);
181 count=0;
182 for (int col=0; col<vrtMtxSize; col++){
183 for (int row=0; row<=col; row++){
184 ic=Pnt+col; ir=Pnt+row;
185 Res[count]=COVFIT[ic*MATRIXSIZE + ir]; count++;
186 }
187 }
188 covarCascade.emplace_back(std::move(Res));
189 }
190}
191
192//
193// Symmetrical indexing (I*(I+1)/2+J) is valid ONLY if I>=J
194std::vector<double> transformCovar(int NPar, double **Deriv, const std::vector<double> &covarI)
195{
196 std::vector<double> covarO(NPar * (NPar + 1) / 2, 0.0);
197 int indexO = 0;
198
199 for (int oi = 0; oi < NPar; ++oi) {
200 const double* der_oi = Deriv[oi];
201
202 for (int oj = 0; oj <= oi; ++oj) {
203 const double* der_oj = Deriv[oj];
204 double sum = 0.0;
205
206 for (int ii = 0; ii < NPar; ++ii) {
207 const double der_oi_ii = der_oi[ii];
208
209 // Segment 1: ij <= ii -> indexI = ii*(ii+1)/2 + ij (contiguous memory walk)
210 int indexI = ii * (ii + 1) / 2;
211 for (int ij = 0; ij <= ii; ++ij) {
212 sum += der_oi_ii * covarI[indexI++] * der_oj[ij];
213 }
214
215 // Segment 2: ij > ii -> indexI = ij*(ij+1)/2 + ii (strided memory walk)
216 indexI += ii;
217 int stride = ii + 2;
218 for (int ij = ii + 1; ij < NPar; ++ij) {
219 sum += der_oi_ii * covarI[indexI] * der_oj[ij];
220 indexI += stride;
221 ++stride;
222 }
223 }
224
225 covarO[indexO++] = sum;
226 }
227 }
228
229 return covarO;
230}
231
232void addCrossVertexDeriv(CascadeEvent & cascadeEvent_, double * ader, long int MATRIXSIZE, const std::vector<int> & matrixPnt)
233{
234 int iv,ivn;
235 //for( iv=0; iv<cascadeEvent_.cascadeNV; iv++)std::cout<<matrixPnt[iv]<<", ";std::cout<<'\n';
236
237 for( iv=0; iv<cascadeEvent_.cascadeNV; iv++){
238 VKVertex *vk = cascadeEvent_.cascadeVertexList[iv].get();
239 if(!vk->nextCascadeVrt)continue; //no pointing
240 for( ivn=iv; ivn<cascadeEvent_.cascadeNV; ivn++){
241 if(vk->nextCascadeVrt == cascadeEvent_.cascadeVertexList[ivn].get()) break; //vertex found
242 }
243 if( ivn == cascadeEvent_.cascadeNV ) continue; // no found vertex
244//
245// Now we have vertex pair "from"(iv) "to"(ivn)
246 int From=matrixPnt[iv]; // start of "from" information
247 int Next=matrixPnt[iv+1]; // start of "next vertex" information. Pnt.constraints are 2 prevous param.!!!
248 int Into=matrixPnt[ivn]; // start of "to" information
249//
250// The same constraints, but derivatives are with respect to other ("to") vertex
251 ader[(0+Into) + (Next-1)*MATRIXSIZE] = - ader[(0+From) + (Next-1)*MATRIXSIZE];
252 ader[(1+Into) + (Next-1)*MATRIXSIZE] = - ader[(1+From) + (Next-1)*MATRIXSIZE];
253 ader[(2+Into) + (Next-1)*MATRIXSIZE] = - ader[(2+From) + (Next-1)*MATRIXSIZE];
254 ader[(0+Into) + (Next-2)*MATRIXSIZE] = - ader[(0+From) + (Next-2)*MATRIXSIZE];
255 ader[(1+Into) + (Next-2)*MATRIXSIZE] = - ader[(1+From) + (Next-2)*MATRIXSIZE];
256 ader[(2+Into) + (Next-2)*MATRIXSIZE] = - ader[(2+From) + (Next-2)*MATRIXSIZE];
257 ader[(0+Into)*MATRIXSIZE + (Next-1)] = - ader[(0+From) + (Next-1)*MATRIXSIZE];
258 ader[(1+Into)*MATRIXSIZE + (Next-1)] = - ader[(1+From) + (Next-1)*MATRIXSIZE];
259 ader[(2+Into)*MATRIXSIZE + (Next-1)] = - ader[(2+From) + (Next-1)*MATRIXSIZE];
260 ader[(0+Into)*MATRIXSIZE + (Next-2)] = - ader[(0+From) + (Next-2)*MATRIXSIZE];
261 ader[(1+Into)*MATRIXSIZE + (Next-2)] = - ader[(1+From) + (Next-2)*MATRIXSIZE];
262 ader[(2+Into)*MATRIXSIZE + (Next-2)] = - ader[(2+From) + (Next-2)*MATRIXSIZE];
263 }
264}
265
266
267//--------------------------------------------------------------------
268// Copy matrix Input with dimension IDIM to predefined place(TStart)
269// into matrix Target with dimension TDIM
270//
271void copyFullMtx(const double * Input, long int IPar, long int IDIM,
272 double * VKAL_RESTRICT Target, long int TStart, long int TDIM) noexcept
273{
274 for (long int i = 0; i < IPar; ++i) {
275 const double* srcRow = Input + i * IDIM;
276 double* VKAL_RESTRICT dstRow = Target + (i + TStart) * TDIM + TStart;
277
278 std::copy(srcRow, srcRow + IPar, dstRow);
279 }
280}
281
282//--------------------------------------------------------------------
283// Make the convolution Cov=D*OldCov*Dt
284//
285void getNewCov(const double *OldCov, const double* Der, double* VKAL_RESTRICT Cov, long int DIM)
286{
287for (long int i = 0; i < DIM; ++i) {
288 const double* der_i = Der + i * DIM;
289 for (long int j = 0; j < DIM; ++j) {
290 const double* der_j = Der + j * DIM;
291 double sum = 0.0; // Register accumulation avoids constant memory writes
292
293 for (long int it = 0; it < DIM; ++it) {
294 const double der_i_it = der_i[it];
295 const double* oldcov_it = OldCov + it * DIM;
296
297 for (long int jt = 0; jt < DIM; ++jt) {
298 sum += der_i_it * oldcov_it[jt] * der_j[jt];
299 }
300 }
301 Cov[i * DIM + j] = sum;
302 }
303 }
304
305}
306
307} /* End of namespace Trk*/
NswErrorCalibData::Input Input
#define VKAL_RESTRICT
Definition Restrict.h:30
std::vector< int > matrixPnt
std::vector< std::unique_ptr< VKVertex > > cascadeVertexList
std::vector< VKVertex * > includedVrt
std::vector< std::unique_ptr< VKTrack > > TrackList
std::vector< std::unique_ptr< VKConstraintBase > > ConstraintList
VKVertex * nextCascadeVrt
std::unique_ptr< VKalVrtControl > vk_fitterControl
static void getMagFld(const double, const double, const double, double &, double &, double &, const VKalVrtControlBase *)
int ir
counter of the current depth
Definition fastadd.cxx:49
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:148
Ensure that the ATLAS eigen extensions are properly loaded.
double cfchi2(double *xyzt, const long int ich, double *part, const double *par0, double *wgt, double *rmnd)
void setFittedParameters(const double *result, std::vector< int > &matrixPnt, CascadeEvent &cascadeEvent_)
void getNewCov(const double *OldCov, const double *Der, double *VKAL_RESTRICT Cov, long int DIM)
int fixPseudoTrackPt(long int NPar, double *fullMtx, double *LSide, CascadeEvent &cascadeEvent_)
std::array< double, 4 > getIniParticleMom(const VKTrack *trk, const VKVertex *vk)
void setFittedMatrices(const double *COVFIT, long int MATRIXSIZE, std::vector< int > &matrixPnt, std::vector< std::vector< double > > &covarCascade, CascadeEvent &cascadeEvent_)
void copyFullMtx(const double *Input, long int IPar, long int IDIM, double *VKAL_RESTRICT Target, long int TStart, long int TDIM) noexcept
int getCascadeNPar(CascadeEvent &cascadeEvent_, int Type)
VKTrack * getCombinedVTrack(VKVertex *vk)
void addCrossVertexDeriv(CascadeEvent &cascadeEvent_, double *ader, long int MATRIXSIZE, const std::vector< int > &matrixPnt)
std::vector< double > transformCovar(int NPar, double **Deriv, const std::vector< double > &covarI)