Fixes for bug #52499: Field polarities inconsistiency
[u/mrichter/AliRoot.git] / STEER / AliMillePede2.cxx
CommitLineData
de34b538 1/**********************************************************************************************/
2/* General class for alignment with large number of degrees of freedom */
3/* Based on the original milliped2 by Volker Blobel */
4/* http://www.desy.de/~blobel/mptalks.html */
5/* */
6/* Author: ruben.shahoyan@cern.ch */
7/* */
8/**********************************************************************************************/
9
8a9ab0eb 10#include "AliMillePede2.h"
11#include "AliLog.h"
12#include <TStopwatch.h>
de34b538 13#include <TFile.h>
14#include <TMath.h>
15#include "AliMatrixSq.h"
16#include "AliSymMatrix.h"
17#include "AliRectMatrix.h"
18#include "AliMatrixSparse.h"
8a9ab0eb 19
8a9ab0eb 20
de34b538 21using namespace std;
8a9ab0eb 22
8a9ab0eb 23
8a9ab0eb 24ClassImp(AliMillePede2)
25
de34b538 26Bool_t AliMillePede2::fgInvChol = kTRUE; // Invert global matrix with Cholesky solver
27Bool_t AliMillePede2::fgWeightSigma = kTRUE; // weight local constraint by module statistics
28Bool_t AliMillePede2::fgIsMatGloSparse = kFALSE; // use faster dense matrix by default
29Int_t AliMillePede2::fgMinResCondType = 1; // Jacoby preconditioner by default
30Double_t AliMillePede2::fgMinResTol = 1.e-11; // default tolerance
31Int_t AliMillePede2::fgMinResMaxIter = 10000; // default max number of iterations
8a9ab0eb 32Int_t AliMillePede2::fgIterSol = AliMinResSolve::kSolMinRes; // default iterative solver
de34b538 33Int_t AliMillePede2::fgNKrylovV = 240; // default number of Krylov vectors to keep
8a9ab0eb 34
35//_____________________________________________________________________________________________
36AliMillePede2::AliMillePede2()
37: fNLocPar(0),
38 fNGloPar(0),
39 fNGloSize(0),
40//
41 fNLocEquations(0),
42 fIter(0),
43 fMaxIter(10),
44 fNStdDev(3),
45 fNGloConstraints(0),
de34b538 46 fNLagrangeConstraints(0),
8a9ab0eb 47 fNLocFits(0),
48 fNLocFitsRejected(0),
49 fNGloFix(0),
50 fGloSolveStatus(gkFailed),
51//
52 fChi2CutFactor(1.),
53 fChi2CutRef(1.),
54 fResCutInit(100.),
55 fResCut(100.),
de34b538 56 fMinPntValid(1),
8a9ab0eb 57//
de34b538 58 fNGroupsSet(0),
59 fParamGrID(0),
8a9ab0eb 60 fProcPnt(0),
61 fVecBLoc(0),
62 fDiagCGlo(0),
63 fVecBGlo(0),
64 fInitPar(0),
65 fDeltaPar(0),
66 fSigmaPar(0),
67 fIsLinear(0),
68 fConstrUsed(0),
69//
70 fGlo2CGlo(0),
71 fCGlo2Glo(0),
72//
73 fMatCLoc(0),
74 fMatCGlo(0),
75 fMatCGloLoc(0),
de34b538 76 //
77 fFillIndex(0),
78 fFillValue(0),
79 //
8a9ab0eb 80 fDataRecFName("/tmp/mp2_data_records.root"),
81 fRecord(0),
82 fDataRecFile(0),
83 fTreeData(0),
84 //
85 fConstrRecFName("/tmp/mp2_constraints_records.root"),
86 fTreeConstr(0),
87 fConsRecFile(0),
88 fCurrRecDataID(0),
de34b538 89 fCurrRecConstrID(0),
90 fLocFitAdd(kTRUE)
8a9ab0eb 91{}
92
93//_____________________________________________________________________________________________
94AliMillePede2::AliMillePede2(const AliMillePede2& src) :
95 TObject(src),fNLocPar(0),fNGloPar(0),fNGloSize(0),fNLocEquations(0),fIter(0),
de34b538 96 fMaxIter(10),fNStdDev(3),fNGloConstraints(0),fNLagrangeConstraints(0),
97 fNLocFits(0),fNLocFitsRejected(0),
8a9ab0eb 98 fNGloFix(0),fGloSolveStatus(0),fChi2CutFactor(0),fChi2CutRef(0),fResCutInit(0),
de34b538 99 fResCut(0),fMinPntValid(1),fNGroupsSet(0),fParamGrID(0),fProcPnt(0),fVecBLoc(0),fDiagCGlo(0),fVecBGlo(0),
8a9ab0eb 100 fInitPar(0),fDeltaPar(0),fSigmaPar(0),fIsLinear(0),fConstrUsed(0),fGlo2CGlo(0),fCGlo2Glo(0),
de34b538 101 fMatCLoc(0),fMatCGlo(0),fMatCGloLoc(0),fFillIndex(0),fFillValue(0),
102 fDataRecFName(0),fRecord(0),fDataRecFile(0),
103 fTreeData(0),fConstrRecFName(0),fTreeConstr(0),fConsRecFile(0),fCurrRecDataID(0),
104 fCurrRecConstrID(0),fLocFitAdd(kTRUE)
8a9ab0eb 105{printf("Dummy\n");}
106
107//_____________________________________________________________________________________________
108AliMillePede2::~AliMillePede2()
109{
110 CloseDataRecStorage();
111 CloseConsRecStorage();
112 //
de34b538 113 delete[] fParamGrID;
8a9ab0eb 114 delete[] fProcPnt;
115 delete[] fVecBLoc;
116 delete[] fDiagCGlo;
117 delete[] fVecBGlo;
118 delete[] fInitPar;
119 delete[] fDeltaPar;
120 delete[] fSigmaPar;
121 delete[] fGlo2CGlo;
122 delete[] fCGlo2Glo;
123 delete[] fIsLinear;
124 delete[] fConstrUsed;
de34b538 125 delete[] fFillIndex;
126 delete[] fFillValue;
8a9ab0eb 127 //
128 delete fRecord;
129 delete fMatCLoc;
130 delete fMatCGlo;
131 delete fMatCGloLoc;
132}
133
134//_____________________________________________________________________________________________
135Int_t AliMillePede2::InitMille(int nGlo, int nLoc, int lNStdDev,double lResCut, double lResCutInit)
136{
137 //
138 if (nLoc>0) fNLocPar = nLoc;
139 if (nGlo>0) fNGloPar = nGlo;
140 if (lResCutInit>0) fResCutInit = lResCutInit;
141 if (lResCut>0) fResCut = lResCut;
142 if (lNStdDev>0) fNStdDev = lNStdDev;
143 //
144 fNGloSize = fNGloPar;
145 //
146 try {
147 //
148 if (fgIsMatGloSparse) {fMatCGlo = new AliMatrixSparse(fNGloPar); fMatCGlo->SetSymmetric(kTRUE);}
149 else fMatCGlo = new AliSymMatrix(fNGloPar);
150 //
de34b538 151 fFillIndex = new Int_t[fNGloPar];
152 fFillValue = new Double_t[fNGloPar];
153 //
8a9ab0eb 154 fMatCLoc = new AliSymMatrix(fNLocPar);
de34b538 155 fMatCGloLoc = new AliRectMatrix(fNGloPar,fNLocPar);
8a9ab0eb 156 //
de34b538 157 fParamGrID = new Int_t[fNGloPar];
8a9ab0eb 158 fProcPnt = new Int_t[fNGloPar];
159 fVecBLoc = new Double_t[fNLocPar];
160 fDiagCGlo = new Double_t[fNGloPar];
161 //
162 fInitPar = new Double_t[fNGloPar];
163 fDeltaPar = new Double_t[fNGloPar];
164 fSigmaPar = new Double_t[fNGloPar];
165 fIsLinear = new Bool_t[fNGloPar];
166 //
167 fGlo2CGlo = new Int_t[fNGloPar];
168 fCGlo2Glo = new Int_t[fNGloPar];
169 }
170 catch(bad_alloc&) {
171 AliInfo(Form("Failed to allocate the memory for %d global and %d local parameters",fNGloPar,fNLocPar));
172 return 0;
173 }
174 //
175 memset(fVecBLoc ,0,fNLocPar*sizeof(Double_t));
176 memset(fDiagCGlo ,0,fNGloPar*sizeof(Double_t));
177 memset(fInitPar ,0,fNGloPar*sizeof(Double_t));
178 memset(fDeltaPar ,0,fNGloPar*sizeof(Double_t));
179 memset(fSigmaPar ,0,fNGloPar*sizeof(Double_t));
180 memset(fProcPnt ,0,fNGloPar*sizeof(Int_t));
181 //
182 for (int i=fNGloPar;i--;) {
de34b538 183 fGlo2CGlo[i] = fCGlo2Glo[i] = -1;
8a9ab0eb 184 fIsLinear[i] = kTRUE;
de34b538 185 fParamGrID[i] = -1;
8a9ab0eb 186 }
187 //
188 return 1;
189}
190
191//_____________________________________________________________________________________________
8a9ab0eb 192Bool_t AliMillePede2::ImposeDataRecFile(const char* fname)
193{
194 CloseDataRecStorage();
195 SetDataRecFName(fname);
196 return InitDataRecStorage(kTRUE); // open in read mode
197}
198
199//_____________________________________________________________________________________________
200Bool_t AliMillePede2::ImposeConsRecFile(const char* fname)
201{
202 CloseConsRecStorage();
203 SetConsRecFName(fname);
204 return InitConsRecStorage(kTRUE); // open in read mode
205}
206
207//_____________________________________________________________________________________________
208Bool_t AliMillePede2::InitDataRecStorage(Bool_t read)
209{
210 // initialize the buffer for processed measurements records
211 //
212 if (fDataRecFile) {AliInfo("Data Records File is already initialized"); return kFALSE;}
213 //
214 if (!fRecord) fRecord = new AliMillePedeRecord();
215 //
216 fDataRecFile = TFile::Open(GetDataRecFName(),read ? "":"recreate");
217 if (!fDataRecFile) {AliInfo(Form("Failed to initialize data records file %s",GetDataRecFName())); return kFALSE;}
218 //
219 AliInfo(Form("File %s used for derivatives records",GetDataRecFName()));
220 if (read) {
221 fTreeData = (TTree*)fDataRecFile->Get("AliMillePedeRecords_Data");
222 if (!fTreeData) {AliInfo(Form("Did not find data records tree in %s",GetDataRecFName())); return kFALSE;}
223 fTreeData->SetBranchAddress("Record_Data",&fRecord);
224 AliInfo(Form("Found %d derivatives records",fTreeData->GetEntries()));
225 }
226 else {
227 fTreeData = new TTree("AliMillePedeRecords_Data","Data Records for AliMillePede2");
228 fTreeData->Branch("Record_Data","AliMillePedeRecord",&fRecord,32000,99);
229 }
230 fCurrRecDataID = -1;
231 //
232 return kTRUE;
233}
234
235//_____________________________________________________________________________________________
236Bool_t AliMillePede2::InitConsRecStorage(Bool_t read)
237{
238 // initialize the buffer for processed measurements records
239 //
240 if (fConsRecFile) {AliInfo("Constraints Records File is already initialized"); return kFALSE;}
241 //
242 if (!fRecord) fRecord = new AliMillePedeRecord();
243 //
244 fConsRecFile = TFile::Open(GetConsRecFName(),read ? "":"recreate");
245 if (!fConsRecFile) {AliInfo(Form("Failed to initialize constraints records file %s",GetConsRecFName())); return kFALSE;}
246 //
247 AliInfo(Form("File %s used for constraints records",GetConsRecFName()));
248 if (read) {
249 fTreeConstr = (TTree*)fConsRecFile->Get("AliMillePedeRecords_Constraints");
250 if (!fTreeConstr) {AliInfo(Form("Did not find constraints records tree in %s",GetConsRecFName())); return kFALSE;}
251 fTreeConstr->SetBranchAddress("Record_Constraints",&fRecord);
252 AliInfo(Form("Found %d constraints records",fTreeConstr->GetEntries()));
253 //
254 }
255 else {
256 //
257 fTreeConstr = new TTree("AliMillePedeRecords_Constraints","Constraints Records for AliMillePede2");
258 fTreeConstr->Branch("Record_Constraints","AliMillePedeRecord",&fRecord,32000,99);
259 }
260 fCurrRecConstrID = -1;
261 //
262 return kTRUE;
263}
264
265//_____________________________________________________________________________________________
266void AliMillePede2::CloseDataRecStorage()
267{
268 if (fTreeData) {
269 if (fDataRecFile->IsWritable()) {
270 fDataRecFile->cd();
271 fTreeData->Write();
272 }
273 delete fTreeData;
274 fTreeData = 0;
275 fDataRecFile->Close();
276 delete fDataRecFile;
277 fDataRecFile = 0;
278 }
279 //
280}
281
282//_____________________________________________________________________________________________
283void AliMillePede2::CloseConsRecStorage()
284{
285 if (fTreeConstr) {
286 if (fConsRecFile->IsWritable()) {
287 fConsRecFile->cd();
288 fTreeConstr->Write();
289 }
290 delete fTreeConstr;
291 fTreeConstr = 0;
292 fConsRecFile->Close();
293 delete fConsRecFile;
294 fConsRecFile = 0;
295 }
296 //
297}
298
299//_____________________________________________________________________________________________
300Bool_t AliMillePede2::ReadNextRecordData()
301{
302 // read next data record (if any)
303 if (!fTreeData || ++fCurrRecDataID >= fTreeData->GetEntries()) { fCurrRecDataID--; return kFALSE;}
304 fTreeData->GetEntry(fCurrRecDataID);
305 return kTRUE;
306}
307
308//_____________________________________________________________________________________________
309Bool_t AliMillePede2::ReadNextRecordConstraint()
310{
311 // read next constraint record (if any)
312 if (!fTreeConstr || ++fCurrRecConstrID >= fTreeConstr->GetEntries()) { fCurrRecConstrID--; return kFALSE;}
313 fTreeConstr->GetEntry(fCurrRecConstrID);
314 return kTRUE;
315}
316
317//_____________________________________________________________________________________________
318void AliMillePede2::SetLocalEquation(double *dergb, double *derlc, double lMeas, double lSigma)
319{
320 if (!fDataRecFile || !fDataRecFile->IsWritable()) InitDataRecStorage(); // create a buffer to store the data
321 //
322 // write data of single measurement
323 if (lSigma<=0.0) { // If parameter is fixed, then no equation
324 for (int i=fNLocPar; i--;) derlc[i] = 0.0;
325 for (int i=fNGloPar; i--;) dergb[i] = 0.0;
326 return;
327 }
328 //
329 fRecord->AddResidual(lMeas);
330 //
331 // Retrieve local param interesting indices
332 for (int i=0;i<fNLocPar;i++) if (derlc[i]!=0.0) {fRecord->AddIndexValue(i,derlc[i]); derlc[i] = 0.0;}
333 //
334 fRecord->AddWeight( 1.0/lSigma/lSigma );
335 //
336 // Idem for global parameters
de34b538 337 for (int i=0;i<fNGloPar;i++) if (dergb[i]!=0.0) {
338 fRecord->AddIndexValue(i,dergb[i]); dergb[i] = 0.0;
339 fRecord->MarkGroup(fParamGrID[i]);
340 }
8a9ab0eb 341 //
342}
343
344//_____________________________________________________________________________________________
345void AliMillePede2::SetLocalEquation(int *indgb, double *dergb, int ngb, int *indlc,
346 double *derlc,int nlc,double lMeas,double lSigma)
347{
348 // write data of single measurement
349 if (lSigma<=0.0) { // If parameter is fixed, then no equation
350 for (int i=nlc;i--;) derlc[i] = 0.0;
351 for (int i=ngb;i--;) dergb[i] = 0.0;
352 return;
353 }
354 //
355 if (!fDataRecFile || !fDataRecFile->IsWritable()) InitDataRecStorage(); // create a buffer to store the data
356 //
357 fRecord->AddResidual(lMeas);
358 //
359 // Retrieve local param interesting indices
360 for (int i=0;i<nlc;i++) if (derlc[i]!=0.0) {fRecord->AddIndexValue(indlc[i],derlc[i]); derlc[i]=0.; indlc[i]=0;}
361 //
362 fRecord->AddWeight( 1./lSigma/lSigma );
363 //
364 // Idem for global parameters
365 for (int i=0;i<ngb;i++) if (dergb[i]!=0.0) {fRecord->AddIndexValue(indgb[i],dergb[i]); dergb[i]=0.; indgb[i]=0;}
366 //
367}
368
de34b538 369
8a9ab0eb 370//_____________________________________________________________________________________________
de34b538 371void AliMillePede2::SetGlobalConstraint(double *dergb, double val, double sigma)
8a9ab0eb 372{
373 // Define a constraint equation.
374 if (!fConsRecFile || !fConsRecFile->IsWritable()) InitConsRecStorage(); // create a buffer to store the data
375 //
376 fRecord->Reset();
377 fRecord->AddResidual(val);
de34b538 378 fRecord->AddWeight(sigma);
8a9ab0eb 379 for (int i=0; i<fNGloPar; i++) if (dergb[i]!=0) fRecord->AddIndexValue(i,dergb[i]);
380 fNGloConstraints++;
de34b538 381 if (sigma==0) fNLagrangeConstraints++;
382 // printf("NewConstraint:\n"); fRecord->Print(); //RRR
8a9ab0eb 383 SaveRecordConstraint();
384 //
385}
386
387//_____________________________________________________________________________________________
de34b538 388void AliMillePede2::SetGlobalConstraint(const int *indgb, double *dergb, int ngb, double val,double sigma)
8a9ab0eb 389{
390 // Define a constraint equation.
391 if (!fConsRecFile || !fConsRecFile->IsWritable()) InitConsRecStorage(); // create a buffer to store the data
392 fRecord->Reset();
393 fRecord->AddResidual(val);
de34b538 394 fRecord->AddWeight(sigma); // dummy
8a9ab0eb 395 for (int i=0; i<ngb; i++) if (dergb[i]!=0) fRecord->AddIndexValue(indgb[i],dergb[i]);
396 fNGloConstraints++;
de34b538 397 if (sigma==0) fNLagrangeConstraints++;
8a9ab0eb 398 SaveRecordConstraint();
399 //
400}
401
402//_____________________________________________________________________________________________
403Int_t AliMillePede2::LocalFit(double *localParams)
404{
405 /*
406 Perform local parameters fit once all the local equations have been set
407 -----------------------------------------------------------
408 localParams = (if !=0) will contain the fitted track parameters and
409 related errors
410 */
de34b538 411 static int nrefSize = 0;
412 // static TArrayI refLoc,refGlo,nrefLoc,nrefGlo;
413 static Int_t *refLoc=0,*refGlo=0,*nrefLoc=0,*nrefGlo=0;
8a9ab0eb 414 int nPoints = 0;
415 //
de34b538 416 AliSymMatrix &matCLoc = *fMatCLoc;
417 AliMatrixSq &matCGlo = *fMatCGlo;
418 AliRectMatrix &matCGloLoc = *fMatCGloLoc;
8a9ab0eb 419 //
420 memset(fVecBLoc,0,fNLocPar*sizeof(double));
de34b538 421 matCLoc.Reset();
8a9ab0eb 422 //
423 int cnt=0;
424 int recSz = fRecord->GetSize();
425 //
426 while(cnt<recSz) { // Transfer the measurement records to matrices
427 //
428 // extract addresses of residual, weight and pointers on local and global derivatives for each point
de34b538 429 if (nrefSize<=nPoints) {
430 int *tmpA = 0;
431 nrefSize = 2*(nPoints+1);
432 tmpA = refLoc; refLoc = new Int_t[nrefSize]; if (tmpA) memcpy(refLoc,tmpA,nPoints*sizeof(int));
433 tmpA = refGlo; refGlo = new Int_t[nrefSize]; if (tmpA) memcpy(refGlo,tmpA,nPoints*sizeof(int));
434 tmpA = nrefLoc; nrefLoc = new Int_t[nrefSize]; if (tmpA) memcpy(nrefLoc,tmpA,nPoints*sizeof(int));
435 tmpA = nrefGlo; nrefGlo = new Int_t[nrefSize]; if (tmpA) memcpy(nrefGlo,tmpA,nPoints*sizeof(int));
8a9ab0eb 436 }
437 //
de34b538 438 refLoc[nPoints] = ++cnt;
8a9ab0eb 439 int nLoc = 0;
440 while(!fRecord->IsWeight(cnt)) {nLoc++; cnt++;}
de34b538 441 nrefLoc[nPoints] = nLoc;
8a9ab0eb 442 //
de34b538 443 refGlo[nPoints] = ++cnt;
8a9ab0eb 444 int nGlo = 0;
445 while(!fRecord->IsResidual(cnt) && cnt<recSz) {nGlo++; cnt++;}
de34b538 446 nrefGlo[nPoints] = nGlo;
8a9ab0eb 447 //
448 nPoints++;
449 }
450 double vl;
451 //
452 for (int ip=nPoints;ip--;) { // Transfer the measurement records to matrices
de34b538 453 double resid = fRecord->GetValue( refLoc[ip]-1 );
454 double weight = fRecord->GetValue( refGlo[ip]-1 );
455 double *derLoc = fRecord->GetValue()+refLoc[ip];
456 double *derGlo = fRecord->GetValue()+refGlo[ip];
457 int *indLoc = fRecord->GetIndex()+refLoc[ip];
458 int *indGlo = fRecord->GetIndex()+refGlo[ip];
459 //
460 for (int i=nrefGlo[ip];i--;) { // suppress the global part (only relevant with iterations)
8a9ab0eb 461 int iID = indGlo[i]; // Global param indice
de34b538 462 if (fSigmaPar[iID]<=0.) continue; // fixed parameter RRRCheck
8a9ab0eb 463 if (fIsLinear[iID]) resid -= derGlo[i]*(fInitPar[iID]+fDeltaPar[iID]); // linear parameter
464 else resid -= derGlo[i]*fDeltaPar[iID]; // nonlinear parameter
465 }
466 //
de34b538 467 // Symmetric matrix, don't bother j>i coeffs
468 for (int i=nrefLoc[ip];i--;) { // Fill local matrix and vector
469 fVecBLoc[ indLoc[i] ] += weight*resid*derLoc[i];
470 for (int j=i+1;j--;) matCLoc(indLoc[i] ,indLoc[j]) += weight*derLoc[i]*derLoc[j];
8a9ab0eb 471 }
472 //
473 } // end of the transfer of the measurement record to matrices
474 //
475 // first try to solve by faster Cholesky decomposition, then by Gaussian elimination
de34b538 476 if (!matCLoc.SolveChol(fVecBLoc,kTRUE)) {
8a9ab0eb 477 AliInfo("Failed to solve locals by Cholesky, traying Gaussian Elimination");
de34b538 478 if (!matCLoc.SolveSpmInv(fVecBLoc,kTRUE)) {
8a9ab0eb 479 AliInfo("Failed to solve locals by Gaussian Elimination, skip...");
de34b538 480 matCLoc.Print("d");
8a9ab0eb 481 return 0; // failed to solve
482 }
483 }
484 //
485 // If requested, store the track params and errors
de34b538 486 // printf("locfit: "); for (int i=0;i<fNLocPar;i++) printf("%+e |",fVecBLoc[i]); printf("\n");
8a9ab0eb 487 if (localParams) for (int i=fNLocPar; i--;) {
488 localParams[2*i] = fVecBLoc[i];
de34b538 489 localParams[2*i+1] = TMath::Sqrt(TMath::Abs(matCLoc.QueryDiag(i)));
8a9ab0eb 490 }
491 //
492 float lChi2 = 0;
493 int nEq = 0;
494 //
495 for (int ip=nPoints;ip--;) { // Calculate residuals
de34b538 496 double resid = fRecord->GetValue( refLoc[ip]-1 );
497 double weight = fRecord->GetValue( refGlo[ip]-1 );
498 double *derLoc = fRecord->GetValue()+refLoc[ip];
499 double *derGlo = fRecord->GetValue()+refGlo[ip];
500 int *indLoc = fRecord->GetIndex()+refLoc[ip];
501 int *indGlo = fRecord->GetIndex()+refGlo[ip];
8a9ab0eb 502 //
503 // Suppress local and global contribution in residuals;
de34b538 504 for (int i=nrefLoc[ip];i--;) resid -= derLoc[i]*fVecBLoc[ indLoc[i] ]; // local part
8a9ab0eb 505 //
de34b538 506 for (int i=nrefGlo[ip];i--;) { // global part
8a9ab0eb 507 int iID = indGlo[i];
508 if ( fSigmaPar[iID] <= 0.) continue; // fixed parameter RRRCheck
509 if (fIsLinear[iID]) resid -= derGlo[i]*(fInitPar[iID]+fDeltaPar[iID]); // linear parameter
510 else resid -= derGlo[i]*fDeltaPar[iID]; // nonlinear parameter
511 }
512 //
513 // reject the track if the residual is too large (outlier)
de34b538 514 double absres = TMath::Abs(resid);
515 if ( (absres >= fResCutInit && fIter ==1 ) ||
516 (absres >= fResCut && fIter > 1)) {
517 if (fLocFitAdd) fNLocFitsRejected++;
8a9ab0eb 518 return 0;
519 }
520 //
521 lChi2 += weight*resid*resid ; // total chi^2
522 nEq++; // number of equations
523 } // end of Calculate residuals
524 //
8a9ab0eb 525 int nDoF = nEq-fNLocPar;
526 lChi2 = (nDoF>0) ? lChi2/nDoF : 0; // Chi^2/dof
527 //
528 if (fNStdDev != 0 && nDoF>0 && lChi2 > Chi2DoFLim(fNStdDev,nDoF)*fChi2CutFactor) { // check final chi2
de34b538 529 if (fLocFitAdd) fNLocFitsRejected++;
8a9ab0eb 530 return 0;
531 }
532 //
de34b538 533 if (fLocFitAdd) {
534 fNLocFits++;
535 fNLocEquations += nEq;
536 }
537 else {
538 fNLocFits--;
539 fNLocEquations -= nEq;
540 }
8a9ab0eb 541 //
542 // local operations are finished, track is accepted
543 // We now update the global parameters (other matrices)
544 //
545 int nGloInFit = 0;
546 //
547 for (int ip=nPoints;ip--;) { // Update matrices
de34b538 548 double resid = fRecord->GetValue( refLoc[ip]-1 );
549 double weight = fRecord->GetValue( refGlo[ip]-1 );
550 double *derLoc = fRecord->GetValue()+refLoc[ip];
551 double *derGlo = fRecord->GetValue()+refGlo[ip];
552 int *indLoc = fRecord->GetIndex()+refLoc[ip];
553 int *indGlo = fRecord->GetIndex()+refGlo[ip];
554 //
555 for (int i=nrefGlo[ip];i--;) { // suppress the global part
8a9ab0eb 556 int iID = indGlo[i]; // Global param indice
557 if ( fSigmaPar[iID] <= 0.) continue; // fixed parameter RRRCheck
de34b538 558 if (fIsLinear[iID]) resid -= derGlo[i]*(fInitPar[iID]+fDeltaPar[iID]); // linear parameter
559 else resid -= derGlo[i]*fDeltaPar[iID]; // nonlinear parameter
8a9ab0eb 560 }
561 //
de34b538 562 for (int ig=nrefGlo[ip];ig--;) {
8a9ab0eb 563 int iIDg = indGlo[ig]; // Global param indice (the matrix line)
564 if ( fSigmaPar[iIDg] <= 0.) continue; // fixed parameter RRRCheck
de34b538 565 if (fLocFitAdd) fVecBGlo[ iIDg ] += weight*resid*derGlo[ig]; //!!!
566 else fVecBGlo[ iIDg ] -= weight*resid*derGlo[ig]; //!!!
8a9ab0eb 567 //
568 // First of all, the global/global terms (exactly like local matrix)
de34b538 569 int nfill = 0;
570 for (int jg=ig+1;jg--;) { // matCGlo is symmetric by construction
8a9ab0eb 571 int jIDg = indGlo[jg];
572 if ( fSigmaPar[jIDg] <= 0.) continue; // fixed parameter RRRCheck
de34b538 573 if ( (vl = weight*derGlo[ig]*derGlo[jg])!=0 ) {
574 fFillIndex[nfill] = jIDg;
575 fFillValue[nfill++] = fLocFitAdd ? vl:-vl;
576 }
577 }
578 if (nfill) matCGlo.AddToRow(iIDg,fFillValue,fFillIndex,nfill);
8a9ab0eb 579 //
580 // Now we have also rectangular matrices containing global/local terms.
581 int iCIDg = fGlo2CGlo[iIDg]; // compressed Index of index
582 if (iCIDg == -1) {
de34b538 583 Double_t *rowGL = matCGloLoc(nGloInFit);
584 for (int k=fNLocPar;k--;) rowGL[k] = 0.0; // reset the row
8a9ab0eb 585 iCIDg = fGlo2CGlo[iIDg] = nGloInFit;
586 fCGlo2Glo[nGloInFit++] = iIDg;
587 }
588 //
de34b538 589 Double_t *rowGLIDg = matCGloLoc(iCIDg);
590 for (int il=nrefLoc[ip];il--;) rowGLIDg[ indLoc[il] ] += weight*derGlo[ig]*derLoc[il];
591 fProcPnt[iIDg] += fLocFitAdd ? 1:-1; // update counter
8a9ab0eb 592 //
593 }
594 } // end of Update matrices
595 //
596 // calculate fMatCGlo -= fMatCGloLoc * fMatCLoc * fMatCGloLoc^T
597 // and fVecBGlo -= fMatCGloLoc * fVecBLoc
598 //
de34b538 599 //-------------------------------------------------------------- >>>
8a9ab0eb 600 double vll;
601 for (int iCIDg=0; iCIDg<nGloInFit; iCIDg++) {
602 int iIDg = fCGlo2Glo[iCIDg];
603 //
604 vl = 0;
de34b538 605 Double_t *rowGLIDg = matCGloLoc(iCIDg);
606 for (int kl=0;kl<fNLocPar;kl++) if (rowGLIDg[kl]) vl += rowGLIDg[kl]*fVecBLoc[kl];
607 if (vl!=0) fVecBGlo[iIDg] -= fLocFitAdd ? vl : -vl;
8a9ab0eb 608 //
de34b538 609 int nfill = 0;
8a9ab0eb 610 for (int jCIDg=0;jCIDg<=iCIDg; jCIDg++) {
611 int jIDg = fCGlo2Glo[jCIDg];
612 //
613 vl = 0;
de34b538 614 Double_t *rowGLJDg = matCGloLoc(jCIDg);
8a9ab0eb 615 for (int kl=0;kl<fNLocPar;kl++) {
616 // diag terms
de34b538 617 if ( (vll=rowGLIDg[kl]*rowGLJDg[kl])!=0 ) vl += matCLoc.QueryDiag(kl)*vll;
8a9ab0eb 618 //
619 // off-diag terms
620 for (int ll=0;ll<kl;ll++) {
de34b538 621 if ( (vll=rowGLIDg[kl]*rowGLJDg[ll])!=0 ) vl += matCLoc(kl,ll)*vll;
622 if ( (vll=rowGLIDg[ll]*rowGLJDg[kl])!=0 ) vl += matCLoc(kl,ll)*vll;
8a9ab0eb 623 }
624 }
de34b538 625 if (vl!=0) {
626 fFillIndex[nfill] = jIDg;
627 fFillValue[nfill++] = fLocFitAdd ? -vl : vl;
628 }
8a9ab0eb 629 }
de34b538 630 if (nfill) matCGlo.AddToRow(iIDg,fFillValue,fFillIndex,nfill);
8a9ab0eb 631 }
632 //
633 // reset compressed index array
634 //
de34b538 635 for (int i=nGloInFit;i--;) {
636 fGlo2CGlo[ fCGlo2Glo[i] ] = -1;
637 fCGlo2Glo[i] = -1;
638 }
8a9ab0eb 639 //
de34b538 640 //---------------------------------------------------- <<<
8a9ab0eb 641 return 1;
642}
643
644//_____________________________________________________________________________________________
645Int_t AliMillePede2::GlobalFit(Double_t *par, Double_t *error, Double_t *pull)
646{
647 // performs a requested number of global iterations
648 fIter = 1;
649 //
650 TStopwatch sw; sw.Start();
651 //
652 int res = 0;
653 AliInfo("Starting Global fit.");
654 while (fIter<=fMaxIter) {
655 //
656 res = GlobalFitIteration();
657 if (!res) break;
658 //
659 if (fChi2CutFactor != fChi2CutRef) {
660 fChi2CutFactor = TMath::Sqrt(fChi2CutFactor);
661 if (fChi2CutFactor < 1.2*fChi2CutRef) {
662 fChi2CutFactor = fChi2CutRef;
663 fIter = fMaxIter - 1; // Last iteration
664 }
665 }
666 fIter++;
667 }
668 //
669 sw.Stop();
670 AliInfo(Form("Global fit %s, CPU time: %.1f",res ? "Converged":"Failed",sw.CpuTime()));
671 if (!res) return 0;
672 //
673 if (par) for (int i=fNGloPar;i--;) par[i] = fInitPar[i]+fDeltaPar[i];
674 //
675 if (fGloSolveStatus==gkInvert) { // errors on params are available
de34b538 676 if (error) for (int i=fNGloPar;i--;) error[i] = fProcPnt[i]>0 ? TMath::Sqrt(TMath::Abs(fMatCGlo->QueryDiag(i))) : 0.;
677 if (pull) for (int i=fNGloPar;i--;) pull[i] = fProcPnt[i]>0 && (fSigmaPar[i]*fSigmaPar[i]-fMatCGlo->QueryDiag(i))>0. && fSigmaPar[i]>0
678 ? fDeltaPar[i]/TMath::Sqrt(fSigmaPar[i]*fSigmaPar[i]-fMatCGlo->QueryDiag(i)) : 0;
8a9ab0eb 679 }
680 //
681 return 1;
682}
683
684//_____________________________________________________________________________________________
685Int_t AliMillePede2::GlobalFitIteration()
686{
687 // perform global parameters fit once all the local equations have been fitted
688 //
689 AliInfo(Form("Global Fit Iteration#%2d (Local Fit Chi^2 cut factor: %.2f)",fIter,fChi2CutFactor));
690 //
691 if (!fNGloPar || !fTreeData) {
692 AliInfo("No data was stored, aborting iteration");
693 return 0;
694 }
de34b538 695 TStopwatch sw,sws;
696 sw.Start();
697 sws.Stop();
8a9ab0eb 698 //
699 if (!fConstrUsed) {
700 fConstrUsed = new Bool_t[fNGloConstraints];
701 memset(fConstrUsed,0,fNGloConstraints*sizeof(Bool_t));
702 }
703 // Reset all info specific for this step
de34b538 704 AliMatrixSq& matCGlo = *fMatCGlo;
705 matCGlo.Reset();
8a9ab0eb 706 memset(fProcPnt,0,fNGloPar*sizeof(Int_t));
707 //
708 fNGloConstraints = fTreeConstr ? fTreeConstr->GetEntries() : 0;
709 //
de34b538 710 // count number of Lagrange constraints: they need new row/cols to be added
711 fNLagrangeConstraints = 0;
712 for (int i=0; i<fNGloConstraints; i++) {
713 ReadRecordConstraint(i);
714 if ( fRecord->GetValue(1)==0 ) fNLagrangeConstraints++; // exact constraint (no error) -> Lagrange multiplier
715 }
716 //
8a9ab0eb 717 // if needed, readjust the size of the global vector (for matrices this is done automatically)
de34b538 718 if (!fVecBGlo || fNGloSize!=fNGloPar+fNLagrangeConstraints) {
8a9ab0eb 719 delete[] fVecBGlo; // in case some constraint was added between the two manual iterations
de34b538 720 fNGloSize = fNGloPar+fNLagrangeConstraints;
8a9ab0eb 721 fVecBGlo = new Double_t[fNGloSize];
722 }
723 memset(fVecBGlo,0,fNGloSize*sizeof(double));
724 //
725 fNLocFits = 0;
726 fNLocFitsRejected = 0;
de34b538 727 fNLocEquations = 0;
8a9ab0eb 728 //
729 // Process data records and build the matrices
730 Long_t ndr = fTreeData->GetEntries();
731 AliInfo(Form("Building the Global matrix from %d data records",ndr));
de34b538 732 if (!ndr) return 0;
733 //
734 TStopwatch swt; swt.Start();
735 fLocFitAdd = kTRUE; // add contributions of matching tracks
8a9ab0eb 736 for (Long_t i=0;i<ndr;i++) {
737 ReadRecordData(i);
738 LocalFit();
de34b538 739 if ( (i%int(0.1*ndr)) == 0) printf("%.1f%% of local fits done\n", double(100.*i)/ndr);
8a9ab0eb 740 }
de34b538 741 swt.Stop();
742 printf("%ld local fits done: ", ndr);
743 swt.Print();
744 sw.Start(kFALSE);
745 //
8a9ab0eb 746 //
de34b538 747 // ---------------------- Reject parameters with low statistics ------------>>
8a9ab0eb 748 fNGloFix = 0;
de34b538 749 if (fMinPntValid>1 && fNGroupsSet) {
750 //
751 printf("Checking parameters with statistics < %d\n",fMinPntValid);
752 TStopwatch swsup;
753 swsup.Start();
754 // 1) build the list of parameters to fix
755 Int_t fixArrSize = 10;
756 Int_t nFixedGroups = 0;
757 TArrayI fixGroups(fixArrSize);
758 //
759 for (int i=fNGloPar;i--;) { // // Reset row and column of fixed params and add 1/sig^2 to free ones
760 int grID = fParamGrID[i];
761 if (grID<0) continue; // not in the group
762 if (fProcPnt[i]>=fMinPntValid) continue;
763 fProcPnt[i] = 0;
764 // check if the group is already accounted
765 Bool_t fnd = kFALSE;
766 for (int j=nFixedGroups;j--;) if (fixGroups[j]==grID) {fnd=kTRUE; break;}
767 if (fnd) continue;
768 if (nFixedGroups>=fixArrSize) {fixArrSize*=2; fixGroups.Set(fixArrSize);}
769 fixGroups[nFixedGroups++] = grID; // add group to fix
770 //
771 }
772 // 2) loop over records and add contributions of fixed groups with negative sign
773 fLocFitAdd = kFALSE;
774 //
775 for (Long_t i=0;i<ndr;i++) {
776 ReadRecordData(i);
777 Bool_t suppr = kFALSE;
778 for (int ifx=nFixedGroups;ifx--;)if (fRecord->IsGroupPresent(fixGroups[ifx])) suppr = kTRUE;
779 if (suppr) LocalFit();
780 }
781 fLocFitAdd = kTRUE;
782 //
783 if (nFixedGroups) {
784 printf("Suppressed contributions of groups with NPoints<%d :\n",fMinPntValid);
785 for (int i=0;i<nFixedGroups;i++) printf("%d ",fixGroups[i]); printf("\n");
786 }
787 swsup.Stop();
788 swsup.Print();
789 }
790 // ---------------------- Reject parameters with low statistics ------------<<
791 //
792 // add large number to diagonal of fixed params
8a9ab0eb 793 //
8a9ab0eb 794 for (int i=fNGloPar;i--;) { // // Reset row and column of fixed params and add 1/sig^2 to free ones
de34b538 795 if (fProcPnt[i]<1) {
8a9ab0eb 796 fNGloFix++;
8a9ab0eb 797 fVecBGlo[i] = 0.;
de34b538 798 matCGlo.DiagElem(i) = float(fNLocEquations*fNLocEquations);
8a9ab0eb 799 }
de34b538 800 else matCGlo.DiagElem(i) += (fgWeightSigma ? fProcPnt[i] : 1.)/(fSigmaPar[i]*fSigmaPar[i]);
8a9ab0eb 801 }
802 //
de34b538 803 for (int i=fNGloPar;i--;) fDiagCGlo[i] = matCGlo.QueryDiag(i); // save the diagonal elements
804 //
8a9ab0eb 805 // add constraint equations
806 int nVar = fNGloPar; // Current size of global matrix
807 for (int i=0; i<fNGloConstraints; i++) {
808 ReadRecordConstraint(i);
809 double val = fRecord->GetValue(0);
de34b538 810 double sig = fRecord->GetValue(1);
8a9ab0eb 811 int *indV = fRecord->GetIndex()+2;
812 double *der = fRecord->GetValue()+2;
813 int csize = fRecord->GetSize()-2;
814 //
de34b538 815 // check if after suppression of fixed variables there are non-0 derivatives
816 // and determine the max statistics of involved params
817 int nSuppressed = 0;
818 int maxStat = 1;
819 for (int j=csize;j--;) {
820 if (fProcPnt[indV[j]]<1) nSuppressed++;
821 else {
822 maxStat = TMath::Max(maxStat,fProcPnt[indV[j]]);
823 }
824 }
8a9ab0eb 825 //
de34b538 826 if (nSuppressed==csize) {
827 // AliInfo(Form("Neglecting constraint %d of %d derivatives since no free parameters left",i,csize));
8a9ab0eb 828 //
829 // was this constraint ever created ?
de34b538 830 if ( sig==0 && fConstrUsed[i] ) { // this is needed only for constraints with Lagrange multiplier
8a9ab0eb 831 // to avoid empty row impose dummy constraint on "Lagrange multiplier"
de34b538 832 matCGlo.DiagElem(nVar) = 1.;
8a9ab0eb 833 fVecBGlo[nVar++] = 0;
834 }
835 continue;
836 }
837 //
de34b538 838 // account for already accumulated corrections
839 for (int j=csize; j--;) val -= der[j]*(fInitPar[ indV[j] ]+fDeltaPar[ indV[j] ]);
8a9ab0eb 840 //
de34b538 841 if (sig > 0) { // this is a gaussian constriant: no Lagrange multipliers are added
842 //
843 double sig2i = (fgWeightSigma ? TMath::Sqrt(maxStat) : 1.)/sig/sig;
844 for (int ir=0;ir<csize;ir++) {
845 int iID = indV[ir];
846 for (int ic=0;ic<=ir;ic++) { // matrix is symmetric
847 int jID = indV[ic];
848 double vl = der[ir]*der[ic]*sig2i;
849 if (vl!=0) matCGlo(iID,jID) += vl;
850 }
851 fVecBGlo[iID] += val*der[ir]*sig2i;
852 }
853 }
854 else { // this is exact constriant: Lagrange multipliers must be added
855 for (int j=csize; j--;) {
856 int jID = indV[j];
857 if (fProcPnt[jID]<1) continue; // this parameter was fixed, don't put it into constraint
858 matCGlo(nVar,jID) = float(fNLocEquations)*der[j]; // fMatCGlo is symmetric, only lower triangle is filled
859 }
860 //
861 if (matCGlo.QueryDiag(nVar)) matCGlo.DiagElem(nVar) = 0.0;
862 fVecBGlo[nVar++] = float(fNLocEquations)*val; //RS ? should we use here fNLocFits ?
863 fConstrUsed[i] = kTRUE;
864 }
8a9ab0eb 865 }
866 //
867 AliInfo(Form("Obtained %-7ld equations from %-7ld records (%-7ld rejected). Fixed %-4d globals",
868 fNLocEquations,fNLocFits,fNLocFitsRejected,fNGloFix));
869
870 //
de34b538 871 sws.Start();
8a9ab0eb 872 fGloSolveStatus = SolveGlobalMatEq(); // obtain solution for this step
de34b538 873 sws.Stop();
874 printf("Solve %d |",fIter); sws.Print();
8a9ab0eb 875 //
876 sw.Stop();
877 AliInfo(Form("Iteration#%2d %s. CPU time: %.1f",fIter,fGloSolveStatus==gkFailed ? "Failed":"Converged",sw.CpuTime()));
878 if (fGloSolveStatus==gkFailed) return 0;
879 //
880 for (int i=fNGloPar;i--;) fDeltaPar[i] += fVecBGlo[i]; // Update global parameters values (for iterations)
881 //
de34b538 882 // PrintGlobalParameters();
8a9ab0eb 883 return 1;
884}
885
886//_____________________________________________________________________________________________
887Int_t AliMillePede2::SolveGlobalMatEq()
888{
889 //
890 // solve global matrix equation MatCGlob*X=VecBGlo and store the result in the VecBGlo
891 //
de34b538 892 /*
893 printf("GlobalMatrix\n");
894 fMatCGlo->Print();
895 printf("RHS\n");
896 for (int i=0;i<fNGloPar;i++) printf("%d %+e\n",i,fVecBGlo[i]);
897 */
898 //
8a9ab0eb 899 if (!fgIsMatGloSparse) {
900 //
de34b538 901 if (fNLagrangeConstraints==0) { // pos-def systems are faster to solve by Cholesky
902 if ( ((AliSymMatrix*)fMatCGlo)->SolveChol(fVecBGlo, fgInvChol) ) return fgInvChol ? gkInvert:gkNoInversion;
8a9ab0eb 903 else AliInfo("Solution of Global Dense System by Cholesky failed, trying Gaussian Elimiation");
904 }
905 //
906 if (((AliSymMatrix*)fMatCGlo)->SolveSpmInv(fVecBGlo, kTRUE)) return gkInvert;
907 else AliInfo("Solution of Global Dense System by Gaussian Elimiation failed, trying iterative methods");
908 }
909 // try to solve by minres
de34b538 910 TVectorD sol(fNGloSize);
8a9ab0eb 911 //
912 AliMinResSolve *slv = new AliMinResSolve(fMatCGlo,fVecBGlo);
913 if (!slv) return gkFailed;
914 //
915 Bool_t res = kFALSE;
916 if (fgIterSol == AliMinResSolve::kSolMinRes)
de34b538 917 res = slv->SolveMinRes(sol,fgMinResCondType,fgMinResMaxIter,fgMinResTol);
8a9ab0eb 918 else if (fgIterSol == AliMinResSolve::kSolFGMRes)
de34b538 919 res = slv->SolveFGMRES(sol,fgMinResCondType,fgMinResMaxIter,fgMinResTol,fgNKrylovV);
8a9ab0eb 920 else
921 AliInfo(Form("Undefined Iteritive Solver ID=%d, only %d are defined",fgIterSol,AliMinResSolve::kNSolvers));
922 //
923 if (!res) return gkFailed;
de34b538 924 for (int i=fNGloSize;i--;) fVecBGlo[i] = sol[i];
925 return gkNoInversion;
8a9ab0eb 926 //
927}
928
929//_____________________________________________________________________________________________
930Float_t AliMillePede2::Chi2DoFLim(int nSig, int nDoF) const
931{
932 /// return the limit in chi^2/nd for n sigmas stdev authorized
933 // Only n=1, 2, and 3 are expected in input
934 int lNSig;
935 float sn[3] = {0.47523, 1.690140, 2.782170};
936 float table[3][30] = {{1.0000, 1.1479, 1.1753, 1.1798, 1.1775, 1.1730, 1.1680, 1.1630,
937 1.1581, 1.1536, 1.1493, 1.1454, 1.1417, 1.1383, 1.1351, 1.1321,
938 1.1293, 1.1266, 1.1242, 1.1218, 1.1196, 1.1175, 1.1155, 1.1136,
939 1.1119, 1.1101, 1.1085, 1.1070, 1.1055, 1.1040},
940 {4.0000, 3.0900, 2.6750, 2.4290, 2.2628, 2.1415, 2.0481, 1.9736,
941 1.9124, 1.8610, 1.8171, 1.7791, 1.7457, 1.7161, 1.6897, 1.6658,
942 1.6442, 1.6246, 1.6065, 1.5899, 1.5745, 1.5603, 1.5470, 1.5346,
943 1.5230, 1.5120, 1.5017, 1.4920, 1.4829, 1.4742},
944 {9.0000, 5.9146, 4.7184, 4.0628, 3.6410, 3.3436, 3.1209, 2.9468,
945 2.8063, 2.6902, 2.5922, 2.5082, 2.4352, 2.3711, 2.3143, 2.2635,
946 2.2178, 2.1764, 2.1386, 2.1040, 2.0722, 2.0428, 2.0155, 1.9901,
947 1.9665, 1.9443, 1.9235, 1.9040, 1.8855, 1.8681}};
948
949 if (nDoF < 1) {
950 return 0.0;
951 }
952 else {
953 lNSig = TMath::Max(1,TMath::Min(nSig,3));
954
955 if (nDoF <= 30) {
956 return table[lNSig-1][nDoF-1];
957 }
958 else { // approximation
959 return ((sn[lNSig-1]+TMath::Sqrt(float(2*nDoF-3)))*
960 (sn[lNSig-1]+TMath::Sqrt(float(2*nDoF-3))))/float(2*nDoF-2);
961 }
962 }
963}
964
965//_____________________________________________________________________________________________
966Int_t AliMillePede2::SetIterations(double lChi2CutFac)
967{
968 // Number of iterations is calculated from lChi2CutFac
969 fChi2CutFactor = TMath::Max(1.0, lChi2CutFac);
970 //
971 AliInfo(Form("Initial cut factor is %f",fChi2CutFactor));
972 fIter = 1; // Initializes the iteration process
973 return 1;
974}
975
976//_____________________________________________________________________________________________
977Double_t AliMillePede2::GetParError(int iPar) const
978{
979 // return error for parameter iPar
980 if (fGloSolveStatus==gkInvert) {
de34b538 981 double res = fMatCGlo->QueryDiag(iPar);
8a9ab0eb 982 if (res>=0) return TMath::Sqrt(res);
983 }
984 return -1.;
985}
986
987
988//_____________________________________________________________________________________________
989Int_t AliMillePede2::PrintGlobalParameters() const
990{
991 /// Print the final results into the logfile
992 double lError = 0.;
993 double lGlobalCor =0.;
994
995 AliInfo("");
996 AliInfo(" Result of fit for global parameters");
997 AliInfo(" ===================================");
998 AliInfo(" I initial final differ lastcor error gcor Npnt");
999 AliInfo("----------------------------------------------------------------------------------------------");
1000 //
1001 for (int i=0; i<fNGloPar; i++) {
1002 lError = GetParError(i);
1003 lGlobalCor = 0.0;
1004 //
1005 double dg;
de34b538 1006 if (fGloSolveStatus==gkInvert && TMath::Abs( (dg=fMatCGlo->QueryDiag(i)) *fDiagCGlo[i]) > 0) {
8a9ab0eb 1007 lGlobalCor = TMath::Sqrt(TMath::Abs(1.0-1.0/(dg*fDiagCGlo[i])));
1008 AliInfo(Form("%d\t %.6f\t %.6f\t %.6f\t %.6f\t %.6f\t %.6f\t %6d",
1009 i,fInitPar[i],fInitPar[i]+fDeltaPar[i],fDeltaPar[i],fVecBGlo[i],lError,lGlobalCor,fProcPnt[i]));
1010 }
1011 else {
1012 AliInfo(Form("%d\t %.6f\t %.6f\t %.6f\t %.6f\t OFF\t OFF\t %6d",i,fInitPar[i],fInitPar[i]+fDeltaPar[i],
1013 fDeltaPar[i],fVecBGlo[i],fProcPnt[i]));
1014 }
1015 }
1016 return 1;
1017}