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