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