/**********************************************************************************************/ /* General class for alignment with large number of degrees of freedom */ /* Based on the original milliped2 by Volker Blobel */ /* and AliMillepede class by Javier */ /* Allows operations with large sparse matrices */ /* http://www.desy.de/~blobel/mptalks.html */ /* */ /* Author: ruben.shahoyan@cern.ch */ /* */ /**********************************************************************************************/ #include "AliMillePede2.h" #include "AliLog.h" #include #include #include #include #include #include #include #include #include "AliMatrixSq.h" #include "AliSymMatrix.h" #include "AliRectMatrix.h" #include "AliMatrixSparse.h" #include #include #include #include #include #include #include //#define _DUMP_EQ_BEFORE_ //#define _DUMP_EQ_AFTER_ //#define _DUMPEQ_BEFORE_ //#define _DUMPEQ_AFTER_ using std::ifstream; ClassImp(AliMillePede2) Bool_t AliMillePede2::fgInvChol = kTRUE; // Invert global matrix with Cholesky solver Bool_t AliMillePede2::fgWeightSigma = kTRUE; // weight local constraint by module statistics Bool_t AliMillePede2::fgIsMatGloSparse = kFALSE; // use faster dense matrix by default Int_t AliMillePede2::fgMinResCondType = 1; // Jacoby preconditioner by default Double_t AliMillePede2::fgMinResTol = 1.e-11; // default tolerance Int_t AliMillePede2::fgMinResMaxIter = 10000; // default max number of iterations Int_t AliMillePede2::fgIterSol = AliMinResSolve::kSolMinRes; // default iterative solver Int_t AliMillePede2::fgNKrylovV = 240; // default number of Krylov vectors to keep //_____________________________________________________________________________________________ AliMillePede2::AliMillePede2() : fNLocPar(0), fNGloPar(0), fNGloParIni(0), fNGloSize(0), // fNLocEquations(0), fIter(0), fMaxIter(10), fNStdDev(3), fNGloConstraints(0), fNLagrangeConstraints(0), fNLocFits(0), fNLocFitsRejected(0), fNGloFix(0), fGloSolveStatus(kFailed), // fChi2CutFactor(1.), fChi2CutRef(1.), fResCutInit(100.), fResCut(100.), fMinPntValid(1), // fNGroupsSet(0), fParamGrID(0), fProcPnt(0), fVecBLoc(0), fDiagCGlo(0), fVecBGlo(0), fInitPar(0), fDeltaPar(0), fSigmaPar(0), fIsLinear(0), fConstrUsed(0), // fGlo2CGlo(0), fCGlo2Glo(0), // fMatCLoc(0), fMatCGlo(0), fMatCGloLoc(0), // fFillIndex(0), fFillValue(0), // fRecDataTreeName("AliMillePedeRecords_Data"), fRecConsTreeName("AliMillePedeRecords_Consaints"), fRecDataBranchName("Record_Data"), fRecConsBranchName("Record_Consaints"), // fDataRecFName("/tmp/mp2_data_records.root"), fRecord(0), fDataRecFile(0), fTreeData(0), fRecFileStatus(0), // fConstrRecFName("/tmp/mp2_constraints_records.root"), fTreeConstr(0), fConsRecFile(0), fCurrRecDataID(0), fCurrRecConstrID(0), fLocFitAdd(kTRUE), fUseRecordWeight(kTRUE), fMinRecordLength(1), fSelFirst(1), fSelLast(-1), fRejRunList(0), fAccRunList(0), fAccRunListWgh(0), fRunWgh(1), fkReGroup(0) { fWghScl[0] = fWghScl[1] = -1; } //_____________________________________________________________________________________________ AliMillePede2::AliMillePede2(const AliMillePede2& src) : TObject(src),fNLocPar(0),fNGloPar(0),fNGloParIni(0),fNGloSize(0),fNLocEquations(0),fIter(0), fMaxIter(10),fNStdDev(3),fNGloConstraints(0),fNLagrangeConstraints(0), fNLocFits(0),fNLocFitsRejected(0), fNGloFix(0),fGloSolveStatus(0),fChi2CutFactor(0),fChi2CutRef(0),fResCutInit(0), fResCut(0),fMinPntValid(1),fNGroupsSet(0),fParamGrID(0),fProcPnt(0),fVecBLoc(0),fDiagCGlo(0),fVecBGlo(0), fInitPar(0),fDeltaPar(0),fSigmaPar(0),fIsLinear(0),fConstrUsed(0),fGlo2CGlo(0),fCGlo2Glo(0), fMatCLoc(0),fMatCGlo(0),fMatCGloLoc(0),fFillIndex(0),fFillValue(0), fRecDataTreeName(0),fRecConsTreeName(0),fRecDataBranchName(0),fRecConsBranchName(0), fDataRecFName(0),fRecord(0),fDataRecFile(0), fTreeData(0),fRecFileStatus(0),fConstrRecFName(0),fTreeConstr(0),fConsRecFile(0),fCurrRecDataID(0), fCurrRecConstrID(0),fLocFitAdd(kTRUE), fUseRecordWeight(kTRUE), fMinRecordLength(1), fSelFirst(1), fSelLast(-1), fRejRunList(0), fAccRunList(0), fAccRunListWgh(0), fRunWgh(1), fkReGroup(0) { fWghScl[0] = src.fWghScl[0]; fWghScl[1] = src.fWghScl[1]; printf("Dummy\n"); } //_____________________________________________________________________________________________ AliMillePede2::~AliMillePede2() { // destructor CloseDataRecStorage(); CloseConsRecStorage(); // delete[] fParamGrID; delete[] fProcPnt; delete[] fVecBLoc; delete[] fDiagCGlo; delete[] fVecBGlo; delete[] fInitPar; delete[] fDeltaPar; delete[] fSigmaPar; delete[] fGlo2CGlo; delete[] fCGlo2Glo; delete[] fIsLinear; delete[] fConstrUsed; delete[] fFillIndex; delete[] fFillValue; // delete fRecord; delete fMatCLoc; delete fMatCGlo; delete fMatCGloLoc; delete fRejRunList; delete fAccRunList; delete fAccRunListWgh; } //_____________________________________________________________________________________________ Int_t AliMillePede2::InitMille(int nGlo, int nLoc, int lNStdDev,double lResCut, double lResCutInit, const Int_t* regroup) { // init all // fNGloParIni = nGlo; if (regroup) { // regrouping is requested fkReGroup = regroup; int ng = 0; // recalculate N globals int maxPID = -1; for (int i=0;i=0) {ng++; if (regroup[i]>maxPID) maxPID = regroup[i];} maxPID++; AliInfo(Form("Regrouping is requested: from %d raw to %d formal globals grouped to %d real globals",nGlo,ng,maxPID)); nGlo = maxPID; } if (nLoc>0) fNLocPar = nLoc; if (nGlo>0) fNGloPar = nGlo; if (lResCutInit>0) fResCutInit = lResCutInit; if (lResCut>0) fResCut = lResCut; if (lNStdDev>0) fNStdDev = lNStdDev; // AliInfo(Form("NLoc: %d NGlo: %d",fNLocPar,fNGloPar)); fNGloSize = fNGloPar; // if (fgIsMatGloSparse) {fMatCGlo = new AliMatrixSparse(fNGloPar); fMatCGlo->SetSymmetric(kTRUE);} else fMatCGlo = new AliSymMatrix(fNGloPar); // fFillIndex = new Int_t[fNGloPar]; fFillValue = new Double_t[fNGloPar]; // fMatCLoc = new AliSymMatrix(fNLocPar); fMatCGloLoc = new AliRectMatrix(fNGloPar,fNLocPar); // fParamGrID = new Int_t[fNGloPar]; fProcPnt = new Int_t[fNGloPar]; fVecBLoc = new Double_t[fNLocPar]; fDiagCGlo = new Double_t[fNGloPar]; // fInitPar = new Double_t[fNGloPar]; fDeltaPar = new Double_t[fNGloPar]; fSigmaPar = new Double_t[fNGloPar]; fIsLinear = new Bool_t[fNGloPar]; // fGlo2CGlo = new Int_t[fNGloPar]; fCGlo2Glo = new Int_t[fNGloPar]; // memset(fVecBLoc ,0,fNLocPar*sizeof(Double_t)); memset(fDiagCGlo ,0,fNGloPar*sizeof(Double_t)); memset(fInitPar ,0,fNGloPar*sizeof(Double_t)); memset(fDeltaPar ,0,fNGloPar*sizeof(Double_t)); memset(fSigmaPar ,0,fNGloPar*sizeof(Double_t)); memset(fProcPnt ,0,fNGloPar*sizeof(Int_t)); // for (int i=fNGloPar;i--;) { fGlo2CGlo[i] = fCGlo2Glo[i] = -1; fIsLinear[i] = kTRUE; fParamGrID[i] = -1; } // fWghScl[0] = -1; fWghScl[1] = -1; return 1; } //_____________________________________________________________________________________________ Bool_t AliMillePede2::ImposeDataRecFile(const char* fname) { // set filename for records CloseDataRecStorage(); SetDataRecFName(fname); return InitDataRecStorage(kTRUE); // open in read mode } //_____________________________________________________________________________________________ Bool_t AliMillePede2::ImposeConsRecFile(const char* fname) { // set filename for constraints CloseConsRecStorage(); SetConsRecFName(fname); return InitConsRecStorage(kTRUE); // open in read mode } //_____________________________________________________________________________________________ Bool_t AliMillePede2::InitDataRecStorage(Bool_t read) { // initialize the buffer for processed measurements records // if (fTreeData) {AliInfo("Data Records File is already initialized"); return kFALSE;} // if (!fRecord) fRecord = new AliMillePedeRecord(); // if (!read) { // write mode: cannot use chain fDataRecFile = TFile::Open(GetDataRecFName(),"recreate"); if (!fDataRecFile) {AliFatal(Form("Failed to initialize data records file %s",GetDataRecFName())); return kFALSE;} AliInfo(Form("File %s used for derivatives records",GetDataRecFName())); fTreeData = new TTree(GetRecDataTreeName(),"Data Records for AliMillePede2"); fTreeData->Branch(GetRecDataBranchName(),"AliMillePedeRecord",&fRecord,32000,99); } else { // use chain TChain* ch = new TChain(GetRecDataTreeName()); // if (fDataRecFName.EndsWith(".root")) ch->AddFile(fDataRecFName); else { // assume text file with list of filenames // ifstream inpf(fDataRecFName.Data()); if (!inpf.good()) {AliInfo(Form("Failed on input records list %s\n",fDataRecFName.Data())); return kFALSE;} // TString recfName; while ( !(recfName.ReadLine(inpf)).eof() ) { recfName = recfName.Strip(TString::kBoth,' '); if (recfName.BeginsWith("//") || recfName.BeginsWith("#") || !recfName.EndsWith(".root")) { // comment AliInfo(Form("Skip %s\n",recfName.Data())); continue; } // recfName = recfName.Strip(TString::kBoth,','); recfName = recfName.Strip(TString::kBoth,'"'); gSystem->ExpandPathName(recfName); printf("Adding %s\n",recfName.Data()); ch->AddFile(recfName.Data()); } } // Long64_t nent = ch->GetEntries(); if (nent<1) { AliInfo("Obtained chain is empty"); return kFALSE;} fTreeData = ch; fTreeData->SetBranchAddress(GetRecDataBranchName(),&fRecord); AliInfo(Form("Found %lld derivatives records",nent)); } fCurrRecDataID = -1; fRecFileStatus = read ? 1:2; // return kTRUE; } //_____________________________________________________________________________________________ Bool_t AliMillePede2::InitConsRecStorage(Bool_t read) { // initialize the buffer for processed measurements records // if (fConsRecFile) {AliInfo("Constraints Records File is already initialized"); return kFALSE;} // if (!fRecord) fRecord = new AliMillePedeRecord(); // fConsRecFile = TFile::Open(GetConsRecFName(),read ? "":"recreate"); if (!fConsRecFile) {AliInfo(Form("Failed to initialize constraints records file %s",GetConsRecFName())); return kFALSE;} // AliInfo(Form("File %s used for constraints records",GetConsRecFName())); if (read) { fTreeConstr = (TTree*)fConsRecFile->Get(GetRecConsTreeName()); if (!fTreeConstr) {AliInfo(Form("Did not find constraints records tree in %s",GetConsRecFName())); return kFALSE;} fTreeConstr->SetBranchAddress(GetRecConsBranchName(),&fRecord); AliInfo(Form("Found %lld constraints records",fTreeConstr->GetEntries())); // } else { // fTreeConstr = new TTree(GetRecConsTreeName(),"Constraints Records for AliMillePede2"); fTreeConstr->Branch(GetRecConsBranchName(),"AliMillePedeRecord",&fRecord,32000,99); } fCurrRecConstrID = -1; // return kTRUE; } //_____________________________________________________________________________________________ void AliMillePede2::CloseDataRecStorage() { // close records file if (fTreeData) { if (fDataRecFile && fDataRecFile->IsWritable()) { fDataRecFile->cd(); fTreeData->Write(); } delete fTreeData; fTreeData = 0; if (fDataRecFile) { fDataRecFile->Close(); delete fDataRecFile; fDataRecFile = 0; } } fRecFileStatus = 0; // } //_____________________________________________________________________________________________ void AliMillePede2::CloseConsRecStorage() { // close constraints file if (fTreeConstr) { if (fConsRecFile->IsWritable()) { fConsRecFile->cd(); fTreeConstr->Write(); } delete fTreeConstr; fTreeConstr = 0; fConsRecFile->Close(); delete fConsRecFile; fConsRecFile = 0; } // } //_____________________________________________________________________________________________ Bool_t AliMillePede2::ReadNextRecordData() { // read next data record (if any) if (!fTreeData || ++fCurrRecDataID >= fTreeData->GetEntries()) { fCurrRecDataID--; return kFALSE;} fTreeData->GetEntry(fCurrRecDataID); return kTRUE; } //_____________________________________________________________________________________________ Bool_t AliMillePede2::ReadNextRecordConstraint() { // read next constraint record (if any) if (!fTreeConstr || ++fCurrRecConstrID >= fTreeConstr->GetEntries()) { fCurrRecConstrID--; return kFALSE;} fTreeConstr->GetEntry(fCurrRecConstrID); return kTRUE; } //_____________________________________________________________________________________________ void AliMillePede2::SetRecordWeight(double wgh) { // assign weight if (fRecFileStatus<2) InitDataRecStorage(); // create a buffer to store the data fRecord->SetWeight(wgh); } //_____________________________________________________________________________________________ void AliMillePede2::SetRecordRun(Int_t run) { // assign run if (fRecFileStatus<2) InitDataRecStorage(); // create a buffer to store the data fRecord->SetRunID(run); } //_____________________________________________________________________________________________ void AliMillePede2::SetLocalEquation(double *dergb, double *derlc, double lMeas, double lSigma) { // assing derivs of loc.eq. if (fRecFileStatus<2) InitDataRecStorage(); // create a buffer to store the data // // write data of single measurement if (lSigma<=0.0) { // If parameter is fixed, then no equation for (int i=fNLocPar; i--;) derlc[i] = 0.0; for (int i=fNGloParIni; i--;) dergb[i] = 0.0; return; } // fRecord->AddResidual(lMeas); // // Retrieve local param interesting indices for (int i=0;iAddIndexValue(i,derlc[i]); derlc[i] = 0.0;} // fRecord->AddWeight( 1.0/lSigma/lSigma ); // // Idem for global parameters for (int i=0;iAddIndexValue(i,dergb[i]); dergb[i] = 0.0; int idrg = GetRGId(i); fRecord->MarkGroup(idrg<0 ? -1 : fParamGrID[i]); } // fRecord->Print(); // } //_____________________________________________________________________________________________ void AliMillePede2::SetLocalEquation(int *indgb, double *dergb, int ngb, int *indlc, double *derlc,int nlc,double lMeas,double lSigma) { // write data of single measurement. Note: the records ignore regrouping, store direct parameters if (lSigma<=0.0) { // If parameter is fixed, then no equation for (int i=nlc;i--;) derlc[i] = 0.0; for (int i=ngb;i--;) dergb[i] = 0.0; return; } // if (fRecFileStatus<2) InitDataRecStorage(); // create a buffer to store the data // fRecord->AddResidual(lMeas); // // Retrieve local param interesting indices for (int i=0;iAddIndexValue(indlc[i],derlc[i]); derlc[i]=0.; indlc[i]=0;} // fRecord->AddWeight( 1./lSigma/lSigma ); // // Idem for global parameters for (int i=0;iAddIndexValue(indgb[i],dergb[i]); dergb[i]=0.; indgb[i]=0;} // } //_____________________________________________________________________________________________ void AliMillePede2::SetGlobalConstraint(const double *dergb, double val, double sigma) { // Define a constraint equation. if (!fConsRecFile || !fConsRecFile->IsWritable()) InitConsRecStorage(); // create a buffer to store the data // fRecord->Reset(); fRecord->AddResidual(val); fRecord->AddWeight(sigma); for (int i=0; iAddIndexValue(i,dergb[i]); fNGloConstraints++; if (IsZero(sigma)) fNLagrangeConstraints++; // printf("NewConstraint:\n"); fRecord->Print(); //RRR SaveRecordConstraint(); // } //_____________________________________________________________________________________________ void AliMillePede2::SetGlobalConstraint(const int *indgb, const double *dergb, int ngb, double val,double sigma) { // Define a constraint equation. if (!fConsRecFile || !fConsRecFile->IsWritable()) InitConsRecStorage(); // create a buffer to store the data fRecord->Reset(); fRecord->AddResidual(val); fRecord->AddWeight(sigma); // dummy for (int i=0; iAddIndexValue(indgb[i],dergb[i]); fNGloConstraints++; if (IsZero(sigma)) fNLagrangeConstraints++; SaveRecordConstraint(); // } //_____________________________________________________________________________________________ Int_t AliMillePede2::LocalFit(double *localParams) { /* Perform local parameters fit once all the local equations have been set ----------------------------------------------------------- localParams = (if !=0) will contain the fitted track parameters and related errors */ static int nrefSize = 0; // static TArrayI refLoc,refGlo,nrefLoc,nrefGlo; static Int_t *refLoc=0,*refGlo=0,*nrefLoc=0,*nrefGlo=0; int nPoints = 0; // AliSymMatrix &matCLoc = *fMatCLoc; AliMatrixSq &matCGlo = *fMatCGlo; AliRectMatrix &matCGloLoc = *fMatCGloLoc; // memset(fVecBLoc,0,fNLocPar*sizeof(double)); matCLoc.Reset(); // int cnt=0; int recSz = fRecord->GetSize(); // while(cntIsWeight(cnt)) {nLoc++; cnt++;} nrefLoc[nPoints] = nLoc; // refGlo[nPoints] = ++cnt; int nGlo = 0; while(!fRecord->IsResidual(cnt) && cnt0 && nPoints < fMinRecordLength) return 0; // ignore // double vl; // double gloWgh = fRunWgh; if (fUseRecordWeight) gloWgh *= fRecord->GetWeight(); // global weight for this set Int_t maxLocUsed = 0; // for (int ip=nPoints;ip--;) { // Transfer the measurement records to matrices double resid = fRecord->GetValue( refLoc[ip]-1 ); double weight = fRecord->GetValue( refGlo[ip]-1 )*gloWgh; int odd = (ip&0x1); if (fWghScl[odd]>0) weight *= fWghScl[odd]; double *derLoc = fRecord->GetValue()+refLoc[ip]; double *derGlo = fRecord->GetValue()+refGlo[ip]; int *indLoc = fRecord->GetIndex()+refLoc[ip]; int *indGlo = fRecord->GetIndex()+refGlo[ip]; // for (int i=nrefGlo[ip];i--;) { // suppress the global part (only relevant with iterations) // // if regrouping was requested, do it here if (fkReGroup) { int idtmp = fkReGroup[ indGlo[i] ]; if (idtmp == kFixParID) indGlo[i] = kFixParID; // fixed param in regrouping else indGlo[i] = idtmp; } // int iID = indGlo[i]; // Global param indice if (iID<0 || fSigmaPar[iID]<=0.) continue; // fixed parameter RRRCheck if (fIsLinear[iID]) resid -= derGlo[i]*(fInitPar[iID]+fDeltaPar[iID]); // linear parameter else resid -= derGlo[i]*fDeltaPar[iID]; // nonlinear parameter } // // Symmetric matrix, don't bother j>i coeffs for (int i=nrefLoc[ip];i--;) { // Fill local matrix and vector fVecBLoc[ indLoc[i] ] += weight*resid*derLoc[i]; if (indLoc[i]>maxLocUsed) maxLocUsed = indLoc[i]; for (int j=i+1;j--;) matCLoc(indLoc[i] ,indLoc[j]) += weight*derLoc[i]*derLoc[j]; } // } // end of the transfer of the measurement record to matrices // matCLoc.SetSizeUsed(++maxLocUsed); // data with B=0 may use less than declared nLocals // /* //RRR fRecord->Print("l"); printf("\nBefore\nLocalMatrix: "); matCLoc.Print("l"); printf("RHSLoc: "); for (int i=0;iGetValue( refLoc[ip]-1 ); double weight = fRecord->GetValue( refGlo[ip]-1 )*gloWgh; int odd = (ip&0x1); if (fWghScl[odd]>0) weight *= fWghScl[odd]; double *derLoc = fRecord->GetValue()+refLoc[ip]; double *derGlo = fRecord->GetValue()+refGlo[ip]; int *indLoc = fRecord->GetIndex()+refLoc[ip]; int *indGlo = fRecord->GetIndex()+refGlo[ip]; // // Suppress local and global contribution in residuals; for (int i=nrefLoc[ip];i--;) resid -= derLoc[i]*fVecBLoc[ indLoc[i] ]; // local part // for (int i=nrefGlo[ip];i--;) { // global part int iID = indGlo[i]; if ( iID<0 || fSigmaPar[iID] <= 0.) continue; // fixed parameter RRRCheck if (fIsLinear[iID]) resid -= derGlo[i]*(fInitPar[iID]+fDeltaPar[iID]); // linear parameter else resid -= derGlo[i]*fDeltaPar[iID]; // nonlinear parameter } // // reject the track if the residual is too large (outlier) double absres = TMath::Abs(resid); if ( (absres >= fResCutInit && fIter ==1 ) || (absres >= fResCut && fIter > 1)) { if (fLocFitAdd) fNLocFitsRejected++; // printf("reject res %5ld %+e\n",fCurrRecDataID,resid); return 0; } // lChi2 += weight*resid*resid ; // total chi^2 nEq++; // number of equations } // end of Calculate residuals // lChi2 /= gloWgh; int nDoF = nEq-maxLocUsed; lChi2 = (nDoF>0) ? lChi2/nDoF : 0; // Chi^2/dof // if (fNStdDev != 0 && nDoF>0 && lChi2 > Chi2DoFLim(fNStdDev,nDoF)*fChi2CutFactor) { // check final chi2 if (fLocFitAdd) fNLocFitsRejected++; // printf("reject chi2 %5ld: %+e\n",fCurrRecDataID, lChi2); return 0; } // if (fLocFitAdd) { fNLocFits++; fNLocEquations += nEq; } else { fNLocFits--; fNLocEquations -= nEq; } // // local operations are finished, track is accepted // We now update the global parameters (other matrices) // int nGloInFit = 0; // for (int ip=nPoints;ip--;) { // Update matrices double resid = fRecord->GetValue( refLoc[ip]-1 ); double weight = fRecord->GetValue( refGlo[ip]-1 )*gloWgh; int odd = (ip&0x1); if (fWghScl[odd]>0) weight *= fWghScl[odd]; double *derLoc = fRecord->GetValue()+refLoc[ip]; double *derGlo = fRecord->GetValue()+refGlo[ip]; int *indLoc = fRecord->GetIndex()+refLoc[ip]; int *indGlo = fRecord->GetIndex()+refGlo[ip]; // for (int i=nrefGlo[ip];i--;) { // suppress the global part int iID = indGlo[i]; // Global param indice if ( iID<0 || fSigmaPar[iID] <= 0.) continue; // fixed parameter RRRCheck if (fIsLinear[iID]) resid -= derGlo[i]*(fInitPar[iID]+fDeltaPar[iID]); // linear parameter else resid -= derGlo[i]*fDeltaPar[iID]; // nonlinear parameter } // for (int ig=nrefGlo[ip];ig--;) { int iIDg = indGlo[ig]; // Global param indice (the matrix line) if ( iIDg<0 || fSigmaPar[iIDg] <= 0.) continue; // fixed parameter RRRCheck if (fLocFitAdd) fVecBGlo[ iIDg ] += weight*resid*derGlo[ig]; //!!! else fVecBGlo[ iIDg ] -= weight*resid*derGlo[ig]; //!!! // // First of all, the global/global terms (exactly like local matrix) int nfill = 0; for (int jg=ig+1;jg--;) { // matCGlo is symmetric by construction int jIDg = indGlo[jg]; if ( jIDg<0 || fSigmaPar[jIDg] <= 0.) continue; // fixed parameter RRRCheck if ( !IsZero(vl = weight*derGlo[ig]*derGlo[jg]) ) { fFillIndex[nfill] = jIDg; fFillValue[nfill++] = fLocFitAdd ? vl:-vl; } } if (nfill) matCGlo.AddToRow(iIDg,fFillValue,fFillIndex,nfill); // // Now we have also rectangular matrices containing global/local terms. int iCIDg = fGlo2CGlo[iIDg]; // compressed Index of index if (iCIDg == -1) { Double_t *rowGL = matCGloLoc(nGloInFit); for (int k=maxLocUsed;k--;) rowGL[k] = 0.0; // reset the row iCIDg = fGlo2CGlo[iIDg] = nGloInFit; fCGlo2Glo[nGloInFit++] = iIDg; } // Double_t *rowGLIDg = matCGloLoc(iCIDg); for (int il=nrefLoc[ip];il--;) rowGLIDg[ indLoc[il] ] += weight*derGlo[ig]*derLoc[il]; fProcPnt[iIDg] += fLocFitAdd ? 1:-1; // update counter // } } // end of Update matrices // /*//RRR printf("After GLO\n"); printf("MatCLoc: "); fMatCLoc->Print("l"); printf("MatCGlo: "); fMatCGlo->Print("l"); printf("MatCGlLc:"); fMatCGloLoc->Print("l"); printf("BGlo: "); for (int i=0; i>> double vll; for (int iCIDg=0; iCIDgPrint(""); printf("BGlo: "); for (int i=0; iGetEntries() : 0; // // count number of Lagrange constraints: they need new row/cols to be added fNLagrangeConstraints = 0; for (int i=0; iGetValue(1)) ) fNLagrangeConstraints++; // exact constraint (no error) -> Lagrange multiplier } // // if needed, readjust the size of the global vector (for matrices this is done automatically) if (!fVecBGlo || fNGloSize!=fNGloPar+fNLagrangeConstraints) { delete[] fVecBGlo; // in case some constraint was added between the two manual iterations fNGloSize = fNGloPar+fNLagrangeConstraints; fVecBGlo = new Double_t[fNGloSize]; } memset(fVecBGlo,0,fNGloSize*sizeof(double)); // fNLocFits = 0; fNLocFitsRejected = 0; fNLocEquations = 0; // // Process data records and build the matrices Long_t ndr = fTreeData->GetEntries(); Long_t first = fSelFirst>0 ? fSelFirst : 0; Long_t last = fSelLast<1 ? ndr : (fSelLast>=ndr ? ndr : fSelLast+Long_t(1)); ndr = last - first; // AliInfo(Form("Building the Global matrix from data records %ld : %ld",first,last)); if (ndr<1) return 0; // TStopwatch swt; swt.Start(); fLocFitAdd = kTRUE; // add contributions of matching tracks for (Long_t i=0;iPrint("l"); printf("BGlo: "); for (int i=0; i> fNGloFix = 0; if (fMinPntValid>1 && fNGroupsSet) { // printf("Checking parameters with statistics < %d\n",fMinPntValid); TStopwatch swsup; swsup.Start(); // 1) build the list of parameters to fix Int_t fixArrSize = 10; Int_t nFixedGroups = 0; TArrayI fixGroups(fixArrSize); // int grIDold = -2; int oldStart = -1; double oldMin = 1.e20; double oldMax =-1.e20; // for (int i=fNGloPar;i--;) { // // Reset row and column of fixed params and add 1/sig^2 to free ones int grID = fParamGrID[i]; if (grID<0) continue; // not in the group // if (grID!=grIDold) { // starting new group if (grIDold>=0) { // decide if the group has enough statistics if (oldMini;iold--) fProcPnt[iold] = 0; Bool_t fnd = kFALSE; // check if the group is already accounted for (int j=nFixedGroups;j--;) if (fixGroups[j]==grIDold) {fnd=kTRUE; break;} if (!fnd) { if (nFixedGroups>=fixArrSize) {fixArrSize*=2; fixGroups.Set(fixArrSize);} fixGroups[nFixedGroups++] = grIDold; // add group to fix } } } grIDold = grID; // mark the start of the new group oldStart = i; oldMin = 1.e20; oldMax = -1.e20; } if (oldMin>fProcPnt[i]) oldMin = fProcPnt[i]; if (oldMax=0 && oldMin=fixArrSize) {fixArrSize*=2; fixGroups.Set(fixArrSize);} fixGroups[nFixedGroups++] = grIDold; // add group to fix } } // // 2) loop over records and add contributions of fixed groups with negative sign fLocFitAdd = kFALSE; // for (Long_t i=0;iIsGroupPresent(fixGroups[ifx])) suppr = kTRUE; if (suppr) LocalFit(); } fLocFitAdd = kTRUE; // if (nFixedGroups) { printf("Suppressed contributions of groups with NPoints<%d :\n",fMinPntValid); for (int i=0;iGetValue(0); double sig = fRecord->GetValue(1); int *indV = fRecord->GetIndex()+2; double *der = fRecord->GetValue()+2; int csize = fRecord->GetSize()-2; // if (fkReGroup) { for (int jp=csize;jp--;) { int idp = indV[jp]; if (fkReGroup[idp]<0) AliFatal(Form("Constain is requested for suppressed parameter #%d",indV[jp])); indV[jp] = idp; } } // check if after suppression of fixed variables there are non-0 derivatives // and determine the max statistics of involved params int nSuppressed = 0; int maxStat = 1; for (int j=csize;j--;) { if (fProcPnt[indV[j]]<1) nSuppressed++; else { maxStat = TMath::Max(maxStat,fProcPnt[indV[j]]); } } // if (nSuppressed==csize) { // AliInfo(Form("Neglecting constraint %d of %d derivatives since no free parameters left",i,csize)); // // was this constraint ever created ? if ( sig==0 && fConstrUsed[i] ) { // this is needed only for constraints with Lagrange multiplier // to avoid empty row impose dummy constraint on "Lagrange multiplier" matCGlo.DiagElem(nVar) = 1.; fVecBGlo[nVar++] = 0; } continue; } // // account for already accumulated corrections for (int j=csize; j--;) val -= der[j]*(fInitPar[ indV[j] ]+fDeltaPar[ indV[j] ]); // if (sig > 0) { // this is a gaussian constriant: no Lagrange multipliers are added // double sig2i = (fgWeightSigma ? TMath::Sqrt(maxStat) : 1.)/sig/sig; for (int ir=0;ir=0) { dup2(slvDumpB,1); printf("Solving%d for %d params\n",fIter,fNGloSize); matCGlo.Print("10"); for (int i=0;iPrint("10"); printf("#RHS/STAT : NGlo:%d NGloSize:%d\n",fNGloPar,fNGloSize); for (int i=0;iPrint("10"); printf("#RHS/STAT : NGlo:%d NGloSize:%d\n",fNGloPar,fNGloSize); for (int i=0;i=0) { dup2(slvDumpA,1); printf("Solving%d for %d params\n",fIter,fNGloSize); matCGlo.Print("10"); for (int i=0;i%+e)\n",i,fVecBGlo[i], fDeltaPar[i]); */ PrintGlobalParameters(); return 1; } //_____________________________________________________________________________________________ Int_t AliMillePede2::SolveGlobalMatEq() { // // solve global matrix equation MatCGlob*X=VecBGlo and store the result in the VecBGlo // /* printf("GlobalMatrix\n"); fMatCGlo->Print("l"); printf("RHS\n"); for (int i=0;iSolveChol(fVecBGlo, fgInvChol) ) return fgInvChol ? kInvert:kNoInversion; else AliInfo("Solution of Global Dense System by Cholesky failed, trying Gaussian Elimiation"); } // if (((AliSymMatrix*)fMatCGlo)->SolveSpmInv(fVecBGlo, kTRUE)) return kInvert; else AliInfo("Solution of Global Dense System by Gaussian Elimination failed, trying iterative methods"); } // try to solve by minres TVectorD sol(fNGloSize); // AliMinResSolve *slv = new AliMinResSolve(fMatCGlo,fVecBGlo); if (!slv) return kFailed; // Bool_t res = kFALSE; if (fgIterSol == AliMinResSolve::kSolMinRes) res = slv->SolveMinRes(sol,fgMinResCondType,fgMinResMaxIter,fgMinResTol); else if (fgIterSol == AliMinResSolve::kSolFGMRes) res = slv->SolveFGMRES(sol,fgMinResCondType,fgMinResMaxIter,fgMinResTol,fgNKrylovV); else AliInfo(Form("Undefined Iteritive Solver ID=%d, only %d are defined",fgIterSol,AliMinResSolve::kNSolvers)); // if (!res) { const char* faildump = "fgmr_failed.dat"; int defout = dup(1); if (defout<0) { AliInfo("Failed on dup"); return kFailed; } int slvDump = open(faildump, O_RDWR|O_CREAT, 0666); if (slvDump>=0) { dup2(slvDump,1); // printf("#Failed to solve using solver %d with PreCond: %d MaxIter: %d Tol: %e NKrylov: %d\n", fgIterSol,fgMinResCondType,fgMinResMaxIter,fgMinResTol,fgNKrylovV); printf("#Dump of matrix:\n"); fMatCGlo->Print("10"); printf("#Dump of RHS:\n"); for (int i=0;iQueryDiag(iPar); if (res>=0) return TMath::Sqrt(res); } return 0.; } //_____________________________________________________________________________________________ Double_t AliMillePede2::GetPull(int iPar) const { // return pull for parameter iPar if (fGloSolveStatus==kInvert) { if (fkReGroup) iPar = fkReGroup[iPar]; if (iPar<0) { // AliDebug(2,Form("Parameter %d was suppressed in the regrouping",iPar)); return 0; } // return fProcPnt[iPar]>0 && (fSigmaPar[iPar]*fSigmaPar[iPar]-fMatCGlo->QueryDiag(iPar))>0. && fSigmaPar[iPar]>0 ? fDeltaPar[iPar]/TMath::Sqrt(fSigmaPar[iPar]*fSigmaPar[iPar]-fMatCGlo->QueryDiag(iPar)) : 0; } return 0.; } //_____________________________________________________________________________________________ Int_t AliMillePede2::PrintGlobalParameters() const { /// Print the final results into the logfile double lError = 0.; double lGlobalCor =0.; printf("\nMillePede2 output\n"); printf(" Result of fit for global parameters\n"); printf(" ===================================\n"); printf(" I initial final differ lastcor error gcor Npnt\n"); printf("----------------------------------------------------------------------------------------------\n"); // int lastPrintedId = -1; for (int i0=0; i0=0 && i<=lastPrintedId) continue; // grouped param lastPrintedId = i; lError = GetParError(i0); lGlobalCor = 0.0; // double dg; if (fGloSolveStatus==kInvert && TMath::Abs( (dg=fMatCGlo->QueryDiag(i)) *fDiagCGlo[i]) > 0) { lGlobalCor = TMath::Sqrt(TMath::Abs(1.0-1.0/(dg*fDiagCGlo[i]))); printf("%4d(%4d)\t %+.6f\t %+.6f\t %+.6f\t %.6f\t %.6f\t %.6f\t %6d\n", i,i0,fInitPar[i],fInitPar[i]+fDeltaPar[i],fDeltaPar[i],fVecBGlo[i],lError,lGlobalCor,fProcPnt[i]); } else { printf("%4d (%4d)\t %+.6f\t %+.6f\t %+.6f\t %.6f\t OFF\t OFF\t %6d\n",i,i0,fInitPar[i],fInitPar[i]+fDeltaPar[i], fDeltaPar[i],fVecBGlo[i],fProcPnt[i]); } } return 1; } //_____________________________________________________________________________________________ Bool_t AliMillePede2::IsRecordAcceptable() { // validate record according run lists set by the user static Long_t prevRunID = kMaxInt; static Bool_t prevAns = kTRUE; Long_t runID = fRecord->GetRunID(); if (runID!=prevRunID) { int n = 0; fRunWgh = 1.; prevRunID = runID; // is run to be rejected? if (fRejRunList && (n=fRejRunList->GetSize())) { prevAns = kTRUE; for (int i=n;i--;) if (runID == (*fRejRunList)[i]) { prevAns = kFALSE; AliInfo(Form("New Run to reject: %ld",runID)); break; } } else if (fAccRunList && (n=fAccRunList->GetSize())) { // is run specifically selected prevAns = kFALSE; for (int i=n;i--;) if (runID == (*fAccRunList)[i]) { prevAns = kTRUE; if (fAccRunListWgh) fRunWgh = (*fAccRunListWgh)[i]; AliInfo(Form("New Run to accept explicitly: %ld, weight=%f",runID,fRunWgh)); break; } if (!prevAns) AliInfo(Form("New Run is not in the list to accept: %ld",runID)); } } // return prevAns; // } //_____________________________________________________________________________________________ void AliMillePede2::SetRejRunList(const UInt_t *runs, Int_t nruns) { // set the list of runs to be rejected if (fRejRunList) delete fRejRunList; fRejRunList = 0; if (nruns<1 || !runs) return; fRejRunList = new TArrayL(nruns); for (int i=0;i