Coding conventions fix (Maksym Zyzak)
[u/mrichter/AliRoot.git] / STEER / 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>
f9efbbf6 14#include <TChain.h>
de34b538 15#include <TMath.h>
7c3070ec 16#include <TVectorD.h>
e30a812f 17#include <TArrayL.h>
f9efbbf6 18#include <TSystem.h>
de34b538 19#include "AliMatrixSq.h"
20#include "AliSymMatrix.h"
21#include "AliRectMatrix.h"
22#include "AliMatrixSparse.h"
e30a812f 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>
f9efbbf6 29#include <fstream>
8a9ab0eb 30
de34b538 31using namespace std;
8a9ab0eb 32
8a9ab0eb 33
8a9ab0eb 34ClassImp(AliMillePede2)
35
de34b538 36Bool_t AliMillePede2::fgInvChol = kTRUE; // Invert global matrix with Cholesky solver
37Bool_t AliMillePede2::fgWeightSigma = kTRUE; // weight local constraint by module statistics
38Bool_t AliMillePede2::fgIsMatGloSparse = kFALSE; // use faster dense matrix by default
39Int_t AliMillePede2::fgMinResCondType = 1; // Jacoby preconditioner by default
40Double_t AliMillePede2::fgMinResTol = 1.e-11; // default tolerance
41Int_t AliMillePede2::fgMinResMaxIter = 10000; // default max number of iterations
8a9ab0eb 42Int_t AliMillePede2::fgIterSol = AliMinResSolve::kSolMinRes; // default iterative solver
de34b538 43Int_t AliMillePede2::fgNKrylovV = 240; // default number of Krylov vectors to keep
8a9ab0eb 44
45//_____________________________________________________________________________________________
46AliMillePede2::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),
de34b538 56 fNLagrangeConstraints(0),
8a9ab0eb 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.),
de34b538 66 fMinPntValid(1),
8a9ab0eb 67//
de34b538 68 fNGroupsSet(0),
69 fParamGrID(0),
8a9ab0eb 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),
de34b538 86 //
87 fFillIndex(0),
88 fFillValue(0),
89 //
8a9ab0eb 90 fDataRecFName("/tmp/mp2_data_records.root"),
91 fRecord(0),
92 fDataRecFile(0),
93 fTreeData(0),
a8c5b94c 94 fRecFileStatus(0),
8a9ab0eb 95 //
96 fConstrRecFName("/tmp/mp2_constraints_records.root"),
97 fTreeConstr(0),
98 fConsRecFile(0),
99 fCurrRecDataID(0),
de34b538 100 fCurrRecConstrID(0),
e30a812f 101 fLocFitAdd(kTRUE),
102 fSelFirst(1),
103 fSelLast(-1),
104 fRejRunList(0),
105 fAccRunList(0)
8a9ab0eb 106{}
107
108//_____________________________________________________________________________________________
109AliMillePede2::AliMillePede2(const AliMillePede2& src) :
110 TObject(src),fNLocPar(0),fNGloPar(0),fNGloSize(0),fNLocEquations(0),fIter(0),
de34b538 111 fMaxIter(10),fNStdDev(3),fNGloConstraints(0),fNLagrangeConstraints(0),
112 fNLocFits(0),fNLocFitsRejected(0),
8a9ab0eb 113 fNGloFix(0),fGloSolveStatus(0),fChi2CutFactor(0),fChi2CutRef(0),fResCutInit(0),
de34b538 114 fResCut(0),fMinPntValid(1),fNGroupsSet(0),fParamGrID(0),fProcPnt(0),fVecBLoc(0),fDiagCGlo(0),fVecBGlo(0),
8a9ab0eb 115 fInitPar(0),fDeltaPar(0),fSigmaPar(0),fIsLinear(0),fConstrUsed(0),fGlo2CGlo(0),fCGlo2Glo(0),
de34b538 116 fMatCLoc(0),fMatCGlo(0),fMatCGloLoc(0),fFillIndex(0),fFillValue(0),
117 fDataRecFName(0),fRecord(0),fDataRecFile(0),
a8c5b94c 118 fTreeData(0),fRecFileStatus(0),fConstrRecFName(0),fTreeConstr(0),fConsRecFile(0),fCurrRecDataID(0),
e30a812f 119 fCurrRecConstrID(0),fLocFitAdd(kTRUE),
120 fSelFirst(1),
121 fSelLast(-1),
122 fRejRunList(0),
123 fAccRunList(0)
8a9ab0eb 124{printf("Dummy\n");}
125
126//_____________________________________________________________________________________________
127AliMillePede2::~AliMillePede2()
128{
129 CloseDataRecStorage();
130 CloseConsRecStorage();
131 //
de34b538 132 delete[] fParamGrID;
8a9ab0eb 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;
de34b538 144 delete[] fFillIndex;
145 delete[] fFillValue;
8a9ab0eb 146 //
147 delete fRecord;
148 delete fMatCLoc;
149 delete fMatCGlo;
150 delete fMatCGloLoc;
e30a812f 151 delete fRejRunList;
152 delete fAccRunList;
8a9ab0eb 153}
154
155//_____________________________________________________________________________________________
156Int_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 //
de34b538 172 fFillIndex = new Int_t[fNGloPar];
173 fFillValue = new Double_t[fNGloPar];
174 //
8a9ab0eb 175 fMatCLoc = new AliSymMatrix(fNLocPar);
de34b538 176 fMatCGloLoc = new AliRectMatrix(fNGloPar,fNLocPar);
8a9ab0eb 177 //
de34b538 178 fParamGrID = new Int_t[fNGloPar];
8a9ab0eb 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--;) {
de34b538 204 fGlo2CGlo[i] = fCGlo2Glo[i] = -1;
8a9ab0eb 205 fIsLinear[i] = kTRUE;
de34b538 206 fParamGrID[i] = -1;
8a9ab0eb 207 }
208 //
209 return 1;
210}
211
212//_____________________________________________________________________________________________
8a9ab0eb 213Bool_t AliMillePede2::ImposeDataRecFile(const char* fname)
214{
215 CloseDataRecStorage();
216 SetDataRecFName(fname);
217 return InitDataRecStorage(kTRUE); // open in read mode
218}
219
220//_____________________________________________________________________________________________
221Bool_t AliMillePede2::ImposeConsRecFile(const char* fname)
222{
223 CloseConsRecStorage();
224 SetConsRecFName(fname);
225 return InitConsRecStorage(kTRUE); // open in read mode
226}
227
228//_____________________________________________________________________________________________
229Bool_t AliMillePede2::InitDataRecStorage(Bool_t read)
230{
231 // initialize the buffer for processed measurements records
232 //
f9efbbf6 233 if (fTreeData) {AliInfo("Data Records File is already initialized"); return kFALSE;}
8a9ab0eb 234 //
235 if (!fRecord) fRecord = new AliMillePedeRecord();
236 //
f9efbbf6 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()));
8a9ab0eb 241 fTreeData = new TTree("AliMillePedeRecords_Data","Data Records for AliMillePede2");
242 fTreeData->Branch("Record_Data","AliMillePedeRecord",&fRecord,32000,99);
243 }
f9efbbf6 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;
f9efbbf6 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 }
8a9ab0eb 275 fCurrRecDataID = -1;
a8c5b94c 276 fRecFileStatus = read ? 1:2;
8a9ab0eb 277 //
278 return kTRUE;
279}
280
281//_____________________________________________________________________________________________
282Bool_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);
73bbf779 298 AliInfo(Form("Found %lld constraints records",fTreeConstr->GetEntries()));
8a9ab0eb 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//_____________________________________________________________________________________________
312void AliMillePede2::CloseDataRecStorage()
313{
314 if (fTreeData) {
f9efbbf6 315 if (fDataRecFile && fDataRecFile->IsWritable()) {
8a9ab0eb 316 fDataRecFile->cd();
317 fTreeData->Write();
318 }
319 delete fTreeData;
320 fTreeData = 0;
f9efbbf6 321 if (fDataRecFile) {
322 fDataRecFile->Close();
323 delete fDataRecFile;
324 fDataRecFile = 0;
325 }
8a9ab0eb 326 }
a8c5b94c 327 fRecFileStatus = 0;
8a9ab0eb 328 //
329}
330
331//_____________________________________________________________________________________________
332void 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//_____________________________________________________________________________________________
349Bool_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//_____________________________________________________________________________________________
358Bool_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//_____________________________________________________________________________________________
a8c5b94c 367void AliMillePede2::SetRecordWeight(double wgh)
368{
369 if (fRecFileStatus<2) InitDataRecStorage(); // create a buffer to store the data
370 fRecord->SetWeight(wgh);
371}
372
373//_____________________________________________________________________________________________
e30a812f 374void 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//_____________________________________________________________________________________________
8a9ab0eb 381void AliMillePede2::SetLocalEquation(double *dergb, double *derlc, double lMeas, double lSigma)
382{
a8c5b94c 383 if (fRecFileStatus<2) InitDataRecStorage(); // create a buffer to store the data
8a9ab0eb 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
cc9bec47 395 for (int i=0;i<fNLocPar;i++) if (!IsZero(derlc[i])) {fRecord->AddIndexValue(i,derlc[i]); derlc[i] = 0.0;}
8a9ab0eb 396 //
397 fRecord->AddWeight( 1.0/lSigma/lSigma );
398 //
399 // Idem for global parameters
cc9bec47 400 for (int i=0;i<fNGloPar;i++) if (!IsZero(dergb[i])) {
de34b538 401 fRecord->AddIndexValue(i,dergb[i]); dergb[i] = 0.0;
402 fRecord->MarkGroup(fParamGrID[i]);
403 }
8a9ab0eb 404 //
405}
406
407//_____________________________________________________________________________________________
408void 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 //
a8c5b94c 418 if (fRecFileStatus<2) InitDataRecStorage(); // create a buffer to store the data
8a9ab0eb 419 //
420 fRecord->AddResidual(lMeas);
421 //
422 // Retrieve local param interesting indices
cc9bec47 423 for (int i=0;i<nlc;i++) if (!IsZero(derlc[i])) {fRecord->AddIndexValue(indlc[i],derlc[i]); derlc[i]=0.; indlc[i]=0;}
8a9ab0eb 424 //
425 fRecord->AddWeight( 1./lSigma/lSigma );
426 //
427 // Idem for global parameters
cc9bec47 428 for (int i=0;i<ngb;i++) if (!IsZero(dergb[i])) {fRecord->AddIndexValue(indgb[i],dergb[i]); dergb[i]=0.; indgb[i]=0;}
8a9ab0eb 429 //
430}
431
de34b538 432
8a9ab0eb 433//_____________________________________________________________________________________________
de34b538 434void AliMillePede2::SetGlobalConstraint(double *dergb, double val, double sigma)
8a9ab0eb 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);
de34b538 441 fRecord->AddWeight(sigma);
cc9bec47 442 for (int i=0; i<fNGloPar; i++) if (!IsZero(dergb[i])) fRecord->AddIndexValue(i,dergb[i]);
8a9ab0eb 443 fNGloConstraints++;
cc9bec47 444 if (IsZero(sigma)) fNLagrangeConstraints++;
de34b538 445 // printf("NewConstraint:\n"); fRecord->Print(); //RRR
8a9ab0eb 446 SaveRecordConstraint();
447 //
448}
449
450//_____________________________________________________________________________________________
de34b538 451void AliMillePede2::SetGlobalConstraint(const int *indgb, double *dergb, int ngb, double val,double sigma)
8a9ab0eb 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);
de34b538 457 fRecord->AddWeight(sigma); // dummy
cc9bec47 458 for (int i=0; i<ngb; i++) if (!IsZero(dergb[i])) fRecord->AddIndexValue(indgb[i],dergb[i]);
8a9ab0eb 459 fNGloConstraints++;
cc9bec47 460 if (IsZero(sigma)) fNLagrangeConstraints++;
8a9ab0eb 461 SaveRecordConstraint();
462 //
463}
464
465//_____________________________________________________________________________________________
466Int_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 */
de34b538 474 static int nrefSize = 0;
475 // static TArrayI refLoc,refGlo,nrefLoc,nrefGlo;
476 static Int_t *refLoc=0,*refGlo=0,*nrefLoc=0,*nrefGlo=0;
8a9ab0eb 477 int nPoints = 0;
478 //
de34b538 479 AliSymMatrix &matCLoc = *fMatCLoc;
480 AliMatrixSq &matCGlo = *fMatCGlo;
481 AliRectMatrix &matCGloLoc = *fMatCGloLoc;
8a9ab0eb 482 //
483 memset(fVecBLoc,0,fNLocPar*sizeof(double));
de34b538 484 matCLoc.Reset();
8a9ab0eb 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
de34b538 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));
8a9ab0eb 499 }
500 //
de34b538 501 refLoc[nPoints] = ++cnt;
8a9ab0eb 502 int nLoc = 0;
503 while(!fRecord->IsWeight(cnt)) {nLoc++; cnt++;}
de34b538 504 nrefLoc[nPoints] = nLoc;
8a9ab0eb 505 //
de34b538 506 refGlo[nPoints] = ++cnt;
8a9ab0eb 507 int nGlo = 0;
508 while(!fRecord->IsResidual(cnt) && cnt<recSz) {nGlo++; cnt++;}
de34b538 509 nrefGlo[nPoints] = nGlo;
8a9ab0eb 510 //
511 nPoints++;
512 }
513 double vl;
514 //
a8c5b94c 515 double gloWgh = fRecord->GetWeight(); // global weight for this set
7c3070ec 516 Int_t maxLocUsed = 0;
517 //
8a9ab0eb 518 for (int ip=nPoints;ip--;) { // Transfer the measurement records to matrices
de34b538 519 double resid = fRecord->GetValue( refLoc[ip]-1 );
a8c5b94c 520 double weight = fRecord->GetValue( refGlo[ip]-1 )*gloWgh;
de34b538 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 //
a8c5b94c 526 for (int i=nrefGlo[ip];i--;) { // suppress the global part (only relevant with iterations)
8a9ab0eb 527 int iID = indGlo[i]; // Global param indice
de34b538 528 if (fSigmaPar[iID]<=0.) continue; // fixed parameter RRRCheck
8a9ab0eb 529 if (fIsLinear[iID]) resid -= derGlo[i]*(fInitPar[iID]+fDeltaPar[iID]); // linear parameter
530 else resid -= derGlo[i]*fDeltaPar[iID]; // nonlinear parameter
531 }
532 //
de34b538 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];
7c3070ec 536 if (indLoc[i]>maxLocUsed) maxLocUsed = indLoc[i];
de34b538 537 for (int j=i+1;j--;) matCLoc(indLoc[i] ,indLoc[j]) += weight*derLoc[i]*derLoc[j];
7c3070ec 538 }
8a9ab0eb 539 //
540 } // end of the transfer of the measurement record to matrices
541 //
7c3070ec 542 matCLoc.SetSizeUsed(++maxLocUsed); // data with B=0 may use less than declared nLocals
543 //
f9efbbf6 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 */
8a9ab0eb 549 // first try to solve by faster Cholesky decomposition, then by Gaussian elimination
de34b538 550 if (!matCLoc.SolveChol(fVecBLoc,kTRUE)) {
a8c5b94c 551 AliInfo("Failed to solve locals by Cholesky, trying Gaussian Elimination");
de34b538 552 if (!matCLoc.SolveSpmInv(fVecBLoc,kTRUE)) {
8a9ab0eb 553 AliInfo("Failed to solve locals by Gaussian Elimination, skip...");
de34b538 554 matCLoc.Print("d");
8a9ab0eb 555 return 0; // failed to solve
556 }
557 }
558 //
559 // If requested, store the track params and errors
f9efbbf6 560 //RRR printf("locfit: "); for (int i=0;i<fNLocPar;i++) printf("%+e |",fVecBLoc[i]); printf("\n");
561
7c3070ec 562 if (localParams) for (int i=maxLocUsed; i--;) {
8a9ab0eb 563 localParams[2*i] = fVecBLoc[i];
de34b538 564 localParams[2*i+1] = TMath::Sqrt(TMath::Abs(matCLoc.QueryDiag(i)));
8a9ab0eb 565 }
566 //
567 float lChi2 = 0;
568 int nEq = 0;
569 //
570 for (int ip=nPoints;ip--;) { // Calculate residuals
de34b538 571 double resid = fRecord->GetValue( refLoc[ip]-1 );
a8c5b94c 572 double weight = fRecord->GetValue( refGlo[ip]-1 )*gloWgh;
de34b538 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];
8a9ab0eb 577 //
578 // Suppress local and global contribution in residuals;
de34b538 579 for (int i=nrefLoc[ip];i--;) resid -= derLoc[i]*fVecBLoc[ indLoc[i] ]; // local part
8a9ab0eb 580 //
de34b538 581 for (int i=nrefGlo[ip];i--;) { // global part
8a9ab0eb 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)
de34b538 589 double absres = TMath::Abs(resid);
590 if ( (absres >= fResCutInit && fIter ==1 ) ||
591 (absres >= fResCut && fIter > 1)) {
592 if (fLocFitAdd) fNLocFitsRejected++;
cc9bec47 593 // printf("reject res %5ld %+e\n",fCurrRecDataID,resid);
8a9ab0eb 594 return 0;
595 }
596 //
597 lChi2 += weight*resid*resid ; // total chi^2
598 nEq++; // number of equations
599 } // end of Calculate residuals
600 //
a8c5b94c 601 lChi2 /= gloWgh;
7c3070ec 602 int nDoF = nEq-maxLocUsed;
8a9ab0eb 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
de34b538 606 if (fLocFitAdd) fNLocFitsRejected++;
cc9bec47 607 // printf("reject chi2 %5ld: %+e\n",fCurrRecDataID, lChi2);
8a9ab0eb 608 return 0;
609 }
610 //
de34b538 611 if (fLocFitAdd) {
612 fNLocFits++;
613 fNLocEquations += nEq;
614 }
615 else {
616 fNLocFits--;
617 fNLocEquations -= nEq;
618 }
8a9ab0eb 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
de34b538 626 double resid = fRecord->GetValue( refLoc[ip]-1 );
a8c5b94c 627 double weight = fRecord->GetValue( refGlo[ip]-1 )*gloWgh;
de34b538 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
8a9ab0eb 634 int iID = indGlo[i]; // Global param indice
635 if ( fSigmaPar[iID] <= 0.) continue; // fixed parameter RRRCheck
de34b538 636 if (fIsLinear[iID]) resid -= derGlo[i]*(fInitPar[iID]+fDeltaPar[iID]); // linear parameter
637 else resid -= derGlo[i]*fDeltaPar[iID]; // nonlinear parameter
8a9ab0eb 638 }
639 //
de34b538 640 for (int ig=nrefGlo[ip];ig--;) {
8a9ab0eb 641 int iIDg = indGlo[ig]; // Global param indice (the matrix line)
642 if ( fSigmaPar[iIDg] <= 0.) continue; // fixed parameter RRRCheck
de34b538 643 if (fLocFitAdd) fVecBGlo[ iIDg ] += weight*resid*derGlo[ig]; //!!!
644 else fVecBGlo[ iIDg ] -= weight*resid*derGlo[ig]; //!!!
8a9ab0eb 645 //
646 // First of all, the global/global terms (exactly like local matrix)
de34b538 647 int nfill = 0;
648 for (int jg=ig+1;jg--;) { // matCGlo is symmetric by construction
8a9ab0eb 649 int jIDg = indGlo[jg];
650 if ( fSigmaPar[jIDg] <= 0.) continue; // fixed parameter RRRCheck
cc9bec47 651 if ( !IsZero(vl = weight*derGlo[ig]*derGlo[jg]) ) {
de34b538 652 fFillIndex[nfill] = jIDg;
653 fFillValue[nfill++] = fLocFitAdd ? vl:-vl;
654 }
655 }
656 if (nfill) matCGlo.AddToRow(iIDg,fFillValue,fFillIndex,nfill);
8a9ab0eb 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) {
de34b538 661 Double_t *rowGL = matCGloLoc(nGloInFit);
7c3070ec 662 for (int k=maxLocUsed;k--;) rowGL[k] = 0.0; // reset the row
8a9ab0eb 663 iCIDg = fGlo2CGlo[iIDg] = nGloInFit;
664 fCGlo2Glo[nGloInFit++] = iIDg;
665 }
666 //
de34b538 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
8a9ab0eb 670 //
671 }
672 } // end of Update matrices
673 //
f9efbbf6 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 */
8a9ab0eb 681 // calculate fMatCGlo -= fMatCGloLoc * fMatCLoc * fMatCGloLoc^T
682 // and fVecBGlo -= fMatCGloLoc * fVecBLoc
683 //
de34b538 684 //-------------------------------------------------------------- >>>
8a9ab0eb 685 double vll;
686 for (int iCIDg=0; iCIDg<nGloInFit; iCIDg++) {
687 int iIDg = fCGlo2Glo[iCIDg];
688 //
689 vl = 0;
de34b538 690 Double_t *rowGLIDg = matCGloLoc(iCIDg);
7c3070ec 691 for (int kl=0;kl<maxLocUsed;kl++) if (rowGLIDg[kl]) vl += rowGLIDg[kl]*fVecBLoc[kl];
cc9bec47 692 if (!IsZero(vl)) fVecBGlo[iIDg] -= fLocFitAdd ? vl : -vl;
8a9ab0eb 693 //
de34b538 694 int nfill = 0;
8a9ab0eb 695 for (int jCIDg=0;jCIDg<=iCIDg; jCIDg++) {
696 int jIDg = fCGlo2Glo[jCIDg];
697 //
698 vl = 0;
de34b538 699 Double_t *rowGLJDg = matCGloLoc(jCIDg);
7c3070ec 700 for (int kl=0;kl<maxLocUsed;kl++) {
8a9ab0eb 701 // diag terms
cc9bec47 702 if ( (!IsZero(vll=rowGLIDg[kl]*rowGLJDg[kl])) ) vl += matCLoc.QueryDiag(kl)*vll;
8a9ab0eb 703 //
704 // off-diag terms
705 for (int ll=0;ll<kl;ll++) {
cc9bec47 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;
8a9ab0eb 708 }
709 }
cc9bec47 710 if (!IsZero(vl)) {
de34b538 711 fFillIndex[nfill] = jIDg;
712 fFillValue[nfill++] = fLocFitAdd ? -vl : vl;
713 }
8a9ab0eb 714 }
de34b538 715 if (nfill) matCGlo.AddToRow(iIDg,fFillValue,fFillIndex,nfill);
8a9ab0eb 716 }
717 //
718 // reset compressed index array
719 //
f9efbbf6 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 */
de34b538 725 for (int i=nGloInFit;i--;) {
726 fGlo2CGlo[ fCGlo2Glo[i] ] = -1;
727 fCGlo2Glo[i] = -1;
728 }
8a9ab0eb 729 //
de34b538 730 //---------------------------------------------------- <<<
8a9ab0eb 731 return 1;
732}
733
734//_____________________________________________________________________________________________
735Int_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 //
cc9bec47 749 if (!IsZero(fChi2CutFactor-fChi2CutRef)) {
8a9ab0eb 750 fChi2CutFactor = TMath::Sqrt(fChi2CutFactor);
751 if (fChi2CutFactor < 1.2*fChi2CutRef) {
752 fChi2CutFactor = fChi2CutRef;
e30a812f 753 //RRR fIter = fMaxIter - 1; // Last iteration
8a9ab0eb 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
de34b538 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;
8a9ab0eb 769 }
770 //
771 return 1;
772}
773
774//_____________________________________________________________________________________________
775Int_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 }
de34b538 785 TStopwatch sw,sws;
786 sw.Start();
787 sws.Stop();
8a9ab0eb 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
de34b538 794 AliMatrixSq& matCGlo = *fMatCGlo;
795 matCGlo.Reset();
8a9ab0eb 796 memset(fProcPnt,0,fNGloPar*sizeof(Int_t));
797 //
798 fNGloConstraints = fTreeConstr ? fTreeConstr->GetEntries() : 0;
799 //
de34b538 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);
cc9bec47 804 if ( IsZero(fRecord->GetValue(1)) ) fNLagrangeConstraints++; // exact constraint (no error) -> Lagrange multiplier
de34b538 805 }
806 //
8a9ab0eb 807 // if needed, readjust the size of the global vector (for matrices this is done automatically)
de34b538 808 if (!fVecBGlo || fNGloSize!=fNGloPar+fNLagrangeConstraints) {
8a9ab0eb 809 delete[] fVecBGlo; // in case some constraint was added between the two manual iterations
de34b538 810 fNGloSize = fNGloPar+fNLagrangeConstraints;
8a9ab0eb 811 fVecBGlo = new Double_t[fNGloSize];
812 }
813 memset(fVecBGlo,0,fNGloSize*sizeof(double));
814 //
815 fNLocFits = 0;
816 fNLocFitsRejected = 0;
de34b538 817 fNLocEquations = 0;
8a9ab0eb 818 //
819 // Process data records and build the matrices
820 Long_t ndr = fTreeData->GetEntries();
e30a812f 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 //
73bbf779 825 AliInfo(Form("Building the Global matrix from data records %ld : %ld",first,last));
e30a812f 826 if (ndr<1) return 0;
de34b538 827 //
828 TStopwatch swt; swt.Start();
829 fLocFitAdd = kTRUE; // add contributions of matching tracks
8a9ab0eb 830 for (Long_t i=0;i<ndr;i++) {
e30a812f 831 Long_t iev = i+first;
832 ReadRecordData(iev);
833 if (!IsRecordAcceptable()) continue;
8a9ab0eb 834 LocalFit();
7c3070ec 835 if ( (i%int(0.2*ndr)) == 0) printf("%.1f%% of local fits done\n", double(100.*i)/ndr);
8a9ab0eb 836 }
de34b538 837 swt.Stop();
838 printf("%ld local fits done: ", ndr);
f9efbbf6 839 /*
840 printf("MatCGlo: "); fMatCGlo->Print("l");
841 printf("BGlo: "); for (int i=0; i<fNGloPar; i++) printf("%+e |",fVecBGlo[i]); printf("\n");
de34b538 842 swt.Print();
f9efbbf6 843 */
de34b538 844 sw.Start(kFALSE);
845 //
8a9ab0eb 846 //
de34b538 847 // ---------------------- Reject parameters with low statistics ------------>>
8a9ab0eb 848 fNGloFix = 0;
de34b538 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 //
91e1aa2c 859 int grIDold = -2;
860 int oldStart = -1;
861 double oldMin = 1.e20;
862 double oldMax =-1.e20;
863 //
de34b538 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
91e1aa2c 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];
de34b538 887 //
888 }
91e1aa2c 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 //
de34b538 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++) {
e30a812f 904 Long_t iev = i+first;
905 ReadRecordData(iev);
906 if (!IsRecordAcceptable()) continue;
de34b538 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
8a9ab0eb 923 //
8a9ab0eb 924 for (int i=fNGloPar;i--;) { // // Reset row and column of fixed params and add 1/sig^2 to free ones
7c3070ec 925 // printf("#%3d : Nproc : %5d grp: %d\n",i,fProcPnt[i],fParamGrID[i]);
de34b538 926 if (fProcPnt[i]<1) {
8a9ab0eb 927 fNGloFix++;
8a9ab0eb 928 fVecBGlo[i] = 0.;
a8c5b94c 929 matCGlo.DiagElem(i) = 1.;//float(fNLocEquations*fNLocEquations);
e30a812f 930 // matCGlo.DiagElem(i) = float(fNLocEquations*fNLocEquations);
8a9ab0eb 931 }
de34b538 932 else matCGlo.DiagElem(i) += (fgWeightSigma ? fProcPnt[i] : 1.)/(fSigmaPar[i]*fSigmaPar[i]);
8a9ab0eb 933 }
934 //
de34b538 935 for (int i=fNGloPar;i--;) fDiagCGlo[i] = matCGlo.QueryDiag(i); // save the diagonal elements
936 //
8a9ab0eb 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);
de34b538 942 double sig = fRecord->GetValue(1);
8a9ab0eb 943 int *indV = fRecord->GetIndex()+2;
944 double *der = fRecord->GetValue()+2;
945 int csize = fRecord->GetSize()-2;
946 //
de34b538 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 }
8a9ab0eb 957 //
de34b538 958 if (nSuppressed==csize) {
959 // AliInfo(Form("Neglecting constraint %d of %d derivatives since no free parameters left",i,csize));
8a9ab0eb 960 //
961 // was this constraint ever created ?
de34b538 962 if ( sig==0 && fConstrUsed[i] ) { // this is needed only for constraints with Lagrange multiplier
8a9ab0eb 963 // to avoid empty row impose dummy constraint on "Lagrange multiplier"
de34b538 964 matCGlo.DiagElem(nVar) = 1.;
8a9ab0eb 965 fVecBGlo[nVar++] = 0;
966 }
967 continue;
968 }
969 //
de34b538 970 // account for already accumulated corrections
971 for (int j=csize; j--;) val -= der[j]*(fInitPar[ indV[j] ]+fDeltaPar[ indV[j] ]);
8a9ab0eb 972 //
de34b538 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;
cc9bec47 981 if (!IsZero(vl)) matCGlo(iID,jID) += vl;
de34b538 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 }
8a9ab0eb 997 }
998 //
999 AliInfo(Form("Obtained %-7ld equations from %-7ld records (%-7ld rejected). Fixed %-4d globals",
1000 fNLocEquations,fNLocFits,fNLocFitsRejected,fNGloFix));
1001
1002 //
de34b538 1003 sws.Start();
f9efbbf6 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 */
8a9ab0eb 1010 fGloSolveStatus = SolveGlobalMatEq(); // obtain solution for this step
de34b538 1011 sws.Stop();
1012 printf("Solve %d |",fIter); sws.Print();
8a9ab0eb 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 //
de34b538 1020 // PrintGlobalParameters();
8a9ab0eb 1021 return 1;
1022}
1023
1024//_____________________________________________________________________________________________
1025Int_t AliMillePede2::SolveGlobalMatEq()
1026{
1027 //
1028 // solve global matrix equation MatCGlob*X=VecBGlo and store the result in the VecBGlo
1029 //
de34b538 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 //
8a9ab0eb 1037 if (!fgIsMatGloSparse) {
1038 //
de34b538 1039 if (fNLagrangeConstraints==0) { // pos-def systems are faster to solve by Cholesky
1040 if ( ((AliSymMatrix*)fMatCGlo)->SolveChol(fVecBGlo, fgInvChol) ) return fgInvChol ? gkInvert:gkNoInversion;
8a9ab0eb 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;
e30a812f 1045 else AliInfo("Solution of Global Dense System by Gaussian Elimination failed, trying iterative methods");
8a9ab0eb 1046 }
1047 // try to solve by minres
de34b538 1048 TVectorD sol(fNGloSize);
8a9ab0eb 1049 //
1050 AliMinResSolve *slv = new AliMinResSolve(fMatCGlo,fVecBGlo);
1051 if (!slv) return gkFailed;
1052 //
1053 Bool_t res = kFALSE;
1054 if (fgIterSol == AliMinResSolve::kSolMinRes)
de34b538 1055 res = slv->SolveMinRes(sol,fgMinResCondType,fgMinResMaxIter,fgMinResTol);
8a9ab0eb 1056 else if (fgIterSol == AliMinResSolve::kSolFGMRes)
de34b538 1057 res = slv->SolveFGMRES(sol,fgMinResCondType,fgMinResMaxIter,fgMinResTol,fgNKrylovV);
8a9ab0eb 1058 else
1059 AliInfo(Form("Undefined Iteritive Solver ID=%d, only %d are defined",fgIterSol,AliMinResSolve::kNSolvers));
1060 //
e30a812f 1061 if (!res) {
1062 const char* faildump = "fgmr_failed.dat";
1063 int defout = dup(1);
c8f37c50 1064 if (defout<0) {
1065 AliInfo("Failed on dup");
1066 return gkFailed;
1067 }
642724dc 1068 int slvDump = open(faildump, O_RDWR|O_CREAT, 0666);
f9efbbf6 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);
f9efbbf6 1081 printf("#Dumped failed matrix and RHS to %s\n",faildump);
1082 }
1083 else AliInfo("Failed on file open for matrix dumping");
4c234df8 1084 close(defout);
e30a812f 1085 return gkFailed;
1086 }
de34b538 1087 for (int i=fNGloSize;i--;) fVecBGlo[i] = sol[i];
1088 return gkNoInversion;
8a9ab0eb 1089 //
1090}
1091
1092//_____________________________________________________________________________________________
1093Float_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//_____________________________________________________________________________________________
1129Int_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//_____________________________________________________________________________________________
1140Double_t AliMillePede2::GetParError(int iPar) const
1141{
1142 // return error for parameter iPar
1143 if (fGloSolveStatus==gkInvert) {
de34b538 1144 double res = fMatCGlo->QueryDiag(iPar);
8a9ab0eb 1145 if (res>=0) return TMath::Sqrt(res);
1146 }
1147 return -1.;
1148}
1149
1150
1151//_____________________________________________________________________________________________
1152Int_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;
de34b538 1169 if (fGloSolveStatus==gkInvert && TMath::Abs( (dg=fMatCGlo->QueryDiag(i)) *fDiagCGlo[i]) > 0) {
8a9ab0eb 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}
e30a812f 1181
1182//_____________________________________________________________________________________________
1183Bool_t AliMillePede2::IsRecordAcceptable() const
1184{
1185 // validate record according run lists set by the user
1a39bef4 1186 static Long_t prevRunID = kMaxInt;
e30a812f 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//_____________________________________________________________________________________________
1212void 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//_____________________________________________________________________________________________
1223void 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}