Project
Loading...
Searching...
No Matches
MillePede2.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
13#include <iostream>
15#include "Framework/Logger.h"
16#include <TStopwatch.h>
17#include <TFile.h>
18#include <TChain.h>
19#include <TMath.h>
20#include <TVectorD.h>
21#include <TArrayL.h>
22#include <TArrayF.h>
23#include <TSystem.h>
24#include <unistd.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <fcntl.h>
28#include <fstream>
29
30// #define _DUMP_EQ_BEFORE_
31// #define _DUMP_EQ_AFTER_
32
33// #define _DUMPEQ_BEFORE_
34// #define _DUMPEQ_AFTER_
35
36using std::ifstream;
37using namespace o2::fwdalign;
38
40
41bool MillePede2::fgInvChol = true; // Invert global matrix with Cholesky solver
42bool MillePede2::fgWeightSigma = true; // weight local constraint by module statistics
43bool MillePede2::fgIsMatGloSparse = false; // use faster dense matrix by default
44int MillePede2::fgMinResCondType = 1; // Jacoby preconditioner by default
45double MillePede2::fgMinResTol = 1.e-11; // default tolerance
46int MillePede2::fgMinResMaxIter = 10000; // default max number of iterations
47int MillePede2::fgIterSol = MinResSolve::kSolMinRes; // default iterative solver
48int MillePede2::fgNKrylovV = 240; // default number of Krylov vectors to keep
49
50//_____________________________________________________________________________
52 : fNLocPar(0),
53 fNGloPar(0),
54 fNGloParIni(0),
55 fNGloSize(0),
56 fNLocEquations(0),
57 fIter(0),
58 fMaxIter(10),
59 fNStdDev(3),
60 fNGloConstraints(0),
61 fNLagrangeConstraints(0),
62 fNLocFits(0),
63 fNLocFitsRejected(0),
64 fNGloFix(0),
65 fGloSolveStatus(kFailed),
66 fChi2CutFactor(1.),
67 fChi2CutRef(1.),
68 fResCutInit(100.),
69 fResCut(100.),
70 fMinPntValid(1),
71 fNGroupsSet(0),
72 fMatCLoc(nullptr),
73 fMatCGlo(nullptr),
74 fMatCGloLoc(nullptr),
75 fRecChi2File(nullptr),
76 fRecChi2FName("chi2_records.root"),
77 fRecChi2TreeName("chi2Records"),
78 fTreeChi2(nullptr),
79 fSumChi2(0.),
80 fIsChi2BelowLimit(true),
81 fRecNDoF(0),
82 fRecord(nullptr),
83 fCurrRecDataID(0),
84 fCurrRecConstrID(0),
85 fLocFitAdd(true),
86 fUseRecordWeight(true),
87 fMinRecordLength(1),
88 fSelFirst(1),
89 fSelLast(-1),
90 fRejRunList(nullptr),
91 fAccRunList(nullptr),
92 fAccRunListWgh(nullptr),
93 fRunWgh(1),
94 fRecordWriter(nullptr),
95 fConstraintsRecWriter(nullptr),
96 fRecordReader(nullptr),
97 fConstraintsRecReader(nullptr)
98{
99 fWghScl[0] = fWghScl[1] = -1;
100 LOGF(info, "MillePede2 instantiated");
101}
102
103//_____________________________________________________________________________
105 : fNLocPar(0),
106 fNGloPar(0),
107 fNGloParIni(0),
108 fNGloSize(0),
109 fNLocEquations(0),
110 fIter(0),
111 fMaxIter(10),
112 fNStdDev(3),
113 fNGloConstraints(0),
114 fNLagrangeConstraints(0),
115 fNLocFits(0),
116 fNLocFitsRejected(0),
117 fNGloFix(0),
118 fGloSolveStatus(kFailed),
119 fChi2CutFactor(1.),
120 fChi2CutRef(1.),
121 fResCutInit(100.),
122 fResCut(100.),
123 fMinPntValid(1),
124 fNGroupsSet(0),
125 fMatCLoc(nullptr),
126 fMatCGlo(nullptr),
127 fMatCGloLoc(nullptr),
128 fRecChi2File(nullptr),
129 fRecChi2FName("chi2_records.root"),
130 fRecChi2TreeName("chi2Records"),
131 fTreeChi2(nullptr),
132 fSumChi2(0.),
133 fIsChi2BelowLimit(true),
134 fRecNDoF(0),
135 fRecord(nullptr),
136 fCurrRecDataID(0),
137 fCurrRecConstrID(0),
138 fLocFitAdd(true),
139 fUseRecordWeight(true),
140 fMinRecordLength(1),
141 fSelFirst(1),
142 fSelLast(-1),
143 fRejRunList(nullptr),
144 fAccRunList(nullptr),
145 fAccRunListWgh(nullptr),
146 fRunWgh(1),
147 fRecordWriter(nullptr),
148 fConstraintsRecWriter(nullptr),
149 fRecordReader(nullptr),
150 fConstraintsRecReader(nullptr),
151 fDisableRecordWriter(false)
152{
153 fWghScl[0] = src.fWghScl[0];
154 fWghScl[1] = src.fWghScl[1];
155 printf("Dummy\n");
156}
157
158//_____________________________________________________________________________
160{
161 if (fMatCLoc) {
162 delete fMatCLoc;
163 }
164 if (fMatCGlo) {
165 delete fMatCGlo;
166 }
167 if (fMatCGloLoc) {
168 delete fMatCGloLoc;
169 }
170
171 if (fRejRunList) {
172 delete fRejRunList;
173 }
174 if (fAccRunList) {
175 delete fAccRunList;
176 }
177 if (fAccRunListWgh) {
178 delete fAccRunListWgh;
179 }
180 if (fRecChi2File) {
181 fRecChi2File->Close();
182 LOG(info) << "MillePede2 - Closed file "
183 << GetRecChi2FName();
184 delete fRecChi2File; // this should automatically delete the TTree that belongs to the file
185 }
186 LOGF(debug, "MillePede2 destroyed");
187}
188
189//_____________________________________________________________________________
190int MillePede2::InitMille(int nGlo, const int nLoc,
191 const int lNStdDev, const double lResCut,
192 const double lResCutInit, const std::vector<int>& regroup)
193{
194 fNGloParIni = nGlo;
195 if (regroup.size()) { // regrouping is requested
196 fkReGroup = regroup;
197 int ng = 0; // recalculate N globals
198 int maxPID = -1;
199 for (int i = 0; i < nGlo; i++) {
200 if (regroup[i] >= 0) {
201 ng++;
202 if (regroup[i] > maxPID) {
203 maxPID = regroup[i];
204 }
205 }
206 }
207 maxPID++;
208 LOGF(info,
209 "MillePede2 - Regrouping is requested: from %d raw to %d formal globals grouped to %d real globals",
210 nGlo, ng, maxPID);
211 nGlo = maxPID;
212 }
213 if (nLoc > 0) {
214 fNLocPar = nLoc;
215 }
216 if (nGlo > 0) {
217 fNGloPar = nGlo;
218 }
219 if (lResCutInit > 0) {
220 fResCutInit = lResCutInit;
221 }
222 if (lResCut > 0) {
223 fResCut = lResCut;
224 }
225 if (lNStdDev > 0) {
226 fNStdDev = lNStdDev;
227 }
228 LOGF(info, "MillePede2 - NLoc: %d NGlo: %d", fNLocPar, fNGloPar);
229
231
232 if (fgIsMatGloSparse) {
234 fMatCGlo->SetSymmetric(true);
235 } else {
237 }
238
239 fFillIndex = std::vector<int>(fNGloPar);
240 fFillValue = std::vector<double>(fNGloPar);
241
244
245 fParamGrID = std::vector<int>(fNGloPar);
246 fProcPnt = std::vector<int>(fNGloPar);
247 fVecBLoc = std::vector<double>(fNGloPar);
248 fDiagCGlo = std::vector<double>(fNGloPar);
249
250 fInitPar = std::vector<double>(fNGloPar);
251 fDeltaPar = std::vector<double>(fNGloPar);
252 fSigmaPar = std::vector<double>(fNGloPar);
253 fIsLinear = std::vector<bool>(fNGloPar);
254
255 fGlo2CGlo = std::vector<int>(fNGloPar);
256 fCGlo2Glo = std::vector<int>(fNGloPar);
257
258 for (int i = fNGloPar; i--;) {
259 fGlo2CGlo[i] = fCGlo2Glo[i] = -1;
260 fIsLinear[i] = true;
261 fParamGrID[i] = -1;
262 }
263
264 fWghScl[0] = -1;
265 fWghScl[1] = -1;
266 return 1;
267}
268
269//_____________________________________________________________________________
270bool MillePede2::InitChi2Storage(const int nEntriesAutoSave)
271{
272 if (fTreeChi2) {
273 LOG(warning) << "MillePede2::InitChi2Storage() - output tree already initialized";
274 return false;
275 }
276 if (fRecChi2File == nullptr) {
277 fRecChi2File = new TFile(GetRecChi2FName(), "recreate", "", 505);
278 }
279 if ((!fRecChi2File) || (fRecChi2File->IsZombie())) {
280 LOGF(error,
281 "MillePede2::InitChi2Storage() - failed to initialise chi2 storage file %s!",
283 return false;
284 }
285 if (fTreeChi2 == nullptr) {
286 fRecChi2File->cd();
287 fTreeChi2 = new TTree(fRecChi2TreeName.Data(), "Sum of chi2 per records");
288 fTreeChi2->SetAutoSave(nEntriesAutoSave); // flush the TTree to disk every N entries
289 fTreeChi2->SetImplicitMT(true);
290 fTreeChi2->Branch("sumChi2", &fSumChi2, "fSumChi2/F");
291 fTreeChi2->Branch("accepted", &fIsChi2BelowLimit, "fIsChi2BelowLimit/O");
292 fTreeChi2->Branch("nDoF", &fRecNDoF, "fRecNDoF/I");
293 }
294 if (!fTreeChi2) {
295 LOG(error) << "MillePede2::InitChi2Storage() - failed to initialise TTree !";
296 return false;
297 }
298 LOGF(info, "MillePede2::InitChi2Storage() - chi2 storage file %s",
300 return true;
301}
302
303//_____________________________________________________________________________
305{
306 if (fRecChi2File && fRecChi2File->IsWritable() && fTreeChi2) {
307 fRecChi2File->cd();
308 fTreeChi2->Write();
309 LOG(info) << "MillePede2::EndChi2Storage() - wrote tree "
310 << fRecChi2TreeName.Data();
311 }
312}
313
314//_____________________________________________________________________________
315void MillePede2::SetLocalEquation(std::vector<double>& dergb, std::vector<double>& derlc,
316 const double lMeas, const double lSigma)
317{
319 if (!fRecordWriter) {
320 LOG(fatal) << "MillePede2::SetLocalEquation() - aborted: null pointer to record writer";
321 return;
322 }
323 if (!fRecordWriter->isInitOk()) {
324 LOG(fatal) << "MillePede2::SetLocalEquation() - aborted: unintialised record writer";
325 return;
326 }
328 }
329 // write data of single measurement
330 if (lSigma <= 0.0) { // If parameter is fixed, then no equation
331 for (int i = fNLocPar; i--;) {
332 derlc[i] = 0.0;
333 }
334 for (int i = fNGloParIni; i--;) {
335 dergb[i] = 0.0;
336 }
337 return;
338 }
339
340 fRecord->AddResidual(lMeas);
341 // Retrieve local param interesting indices
342 for (int i = 0; i < fNLocPar; i++) {
343 if (!IsZero(derlc[i])) {
344 fRecord->AddIndexValue(i, derlc[i]);
345 derlc[i] = 0.0;
346 }
347 }
348
349 fRecord->AddWeight(1.0 / lSigma / lSigma);
350
351 // Idem for global parameters
352 for (int i = 0; i < fNGloParIni; i++) {
353 if (!IsZero(dergb[i])) {
354 fRecord->AddIndexValue(i, dergb[i]);
355 dergb[i] = 0.0;
356 int idrg = GetRGId(i);
357 fRecord->MarkGroup(idrg < 0 ? -1 : fParamGrID[i]);
358 }
359 }
360}
361
362//_____________________________________________________________________________
363void MillePede2::SetLocalEquation(std::vector<int>& indgb, std::vector<double>& dergb,
364 int ngb, std::vector<int>& indlc,
365 std::vector<double>& derlc, const int nlc,
366 const double lMeas, const double lSigma)
367{
369 if (!fRecordWriter) {
370 LOG(fatal) << "MillePede2::SetLocalEquation() - aborted: null pointer to record writer";
371 return;
372 }
373 if (!fRecordWriter->isInitOk()) {
374 LOG(fatal) << "MillePede2::SetLocalEquation() - aborted: unintialised record writer";
375 return;
376 }
378 }
379 if (lSigma <= 0.0) { // If parameter is fixed, then no equation
380 for (int i = nlc; i--;) {
381 derlc[i] = 0.0;
382 }
383 for (int i = ngb; i--;) {
384 dergb[i] = 0.0;
385 }
386 return;
387 }
388
389 fRecord->AddResidual(lMeas);
390
391 // Retrieve local param interesting indices
392 for (int i = 0; i < nlc; i++) {
393 if (!IsZero(derlc[i])) {
394 fRecord->AddIndexValue(indlc[i], derlc[i]);
395 derlc[i] = 0.;
396 indlc[i] = 0;
397 }
398 }
399
400 fRecord->AddWeight(1. / lSigma / lSigma);
401
402 // Idem for global parameters
403 for (int i = 0; i < ngb; i++) {
404 if (!IsZero(dergb[i])) {
405 fRecord->AddIndexValue(indgb[i], dergb[i]);
406 dergb[i] = 0.;
407 indgb[i] = 0;
408 }
409 }
410}
411
412//_____________________________________________________________________________
413void MillePede2::SetGlobalConstraint(const std::vector<double>& dergb,
414 const double val, const double sigma,
415 const bool doPrint)
416{
418 LOG(fatal) << "MillePede2::SetGlobalConstraint() - aborted: null pointer to record writer";
419 return;
420 }
422 LOG(fatal) << "MillePede2::SetGlobalConstraint() - aborted: unintialised record writer";
423 return;
424 }
426
427 fRecord->Reset();
429 fRecord->AddWeight(sigma);
430 for (int i = 0; i < fNGloParIni; i++) {
431 if (!IsZero(dergb[i])) {
432 fRecord->AddIndexValue(i, dergb[i]);
433 }
434 }
436 if (IsZero(sigma)) {
438 }
439 if (doPrint) {
440 LOG(info) << "MillePede2::SetGlobalConstraint() - new constraints added";
441 }
443}
444
445//_____________________________________________________________________________
446void MillePede2::SetGlobalConstraint(const std::vector<int>& indgb,
447 const std::vector<double>& dergb,
448 const int ngb, const double val,
449 const double sigma, const bool doPrint)
450{
452 LOG(fatal) << "MillePede2::SetGlobalConstraint() - aborted: null pointer to record writer";
453 return;
454 }
456 LOG(fatal) << "MillePede2::SetGlobalConstraint() - aborted: unintialised record writer";
457 return;
458 }
460
461 fRecord->Reset();
463 fRecord->AddWeight(sigma); // dummy
464 for (int i = 0; i < ngb; i++) {
465 if (!IsZero(dergb[i])) {
466 fRecord->AddIndexValue(indgb[i], dergb[i]);
467 }
468 }
470 if (IsZero(sigma)) {
472 }
473 if (doPrint) {
474 LOG(info) << "MillePede2::SetGlobalConstraint() - new constraints added";
475 }
477}
478
479//_____________________________________________________________________________
480void MillePede2::ReadRecordData(const long recID, bool doPrint)
481{
482 if (fRecordReader == nullptr) {
483 LOG(error) << "MillePede2::ReadRecordData() - aborted, input record reader is a null pointer";
484 return;
485 }
487 fRecordReader->readEntry(recID, doPrint);
488 fCurrRecDataID = recID;
489}
490
491//_____________________________________________________________________________
492void MillePede2::ReadRecordConstraint(const long recID, bool doPrint)
493{
494 if (fConstraintsRecReader == nullptr) {
495 LOG(error) << "MillePede2::ReadRecordConstraint() - aborted, input record reader is a null pointer";
496 return;
497 }
499 fConstraintsRecReader->readEntry(recID, doPrint);
500 fCurrRecConstrID = recID;
501}
502
503//_____________________________________________________________________________
504int MillePede2::LocalFit(std::vector<double>& localParams)
505{
506 static int nrefSize = 0;
507 // static TArrayI refLoc,refGlo,nrefLoc,nrefGlo;
508 static int *refLoc = nullptr, *refGlo = nullptr, *nrefLoc = nullptr, *nrefGlo = nullptr;
509 int nPoints = 0;
510 fIsChi2BelowLimit = true;
511
512 SymMatrix& matCLoc = *fMatCLoc;
513 MatrixSq& matCGlo = *fMatCGlo;
514 RectMatrix& matCGloLoc = *fMatCGloLoc;
515
516 std::fill(fVecBLoc.begin(), fVecBLoc.end(), 0.);
517 matCLoc.Reset();
518
519 int cnt = 0;
520 int recSz = fRecord->GetSize();
521
522 while (cnt < recSz) { // Transfer the measurement records to matrices
523 // extract addresses of residual, weight and pointers on local and global derivatives for each point
524 if (nrefSize <= nPoints) {
525 int* tmpA = nullptr;
526 nrefSize = 2 * (nPoints + 1);
527 tmpA = refLoc;
528 refLoc = new int[nrefSize];
529 if (tmpA) {
530 memcpy(refLoc, tmpA, nPoints * sizeof(int));
531 }
532 tmpA = refGlo;
533 refGlo = new int[nrefSize];
534 if (tmpA) {
535 memcpy(refGlo, tmpA, nPoints * sizeof(int));
536 }
537 tmpA = nrefLoc;
538 nrefLoc = new int[nrefSize];
539 if (tmpA) {
540 memcpy(nrefLoc, tmpA, nPoints * sizeof(int));
541 }
542 tmpA = nrefGlo;
543 nrefGlo = new int[nrefSize];
544 if (tmpA) {
545 memcpy(nrefGlo, tmpA, nPoints * sizeof(int));
546 }
547 }
548
549 refLoc[nPoints] = ++cnt;
550 int nLoc = 0;
551 while (!fRecord->IsWeight(cnt)) {
552 nLoc++;
553 cnt++;
554 }
555 nrefLoc[nPoints] = nLoc;
556
557 refGlo[nPoints] = ++cnt;
558 int nGlo = 0;
559 while (!fRecord->IsResidual(cnt) && cnt < recSz) {
560 nGlo++;
561 cnt++;
562 }
563 nrefGlo[nPoints] = nGlo;
564
565 nPoints++;
566 }
567 if (fMinRecordLength > 0 && nPoints < fMinRecordLength) {
568 return 0; // ignore
569 }
570
571 double vl;
572
573 double gloWgh = fRunWgh;
574 if (fUseRecordWeight) {
575 gloWgh *= fRecord->GetWeight(); // global weight for this set
576 }
577 int maxLocUsed = 0;
578
579 for (int ip = nPoints; ip--;) { // Transfer the measurement records to matrices
580 double resid = fRecord->GetValue(refLoc[ip] - 1);
581 double weight = fRecord->GetValue(refGlo[ip] - 1) * gloWgh;
582 int odd = (ip & 0x1);
583 if (fWghScl[odd] > 0) {
584 weight *= fWghScl[odd];
585 }
586 double* derLoc = fRecord->GetValue() + refLoc[ip];
587 double* derGlo = fRecord->GetValue() + refGlo[ip];
588 int* indLoc = fRecord->GetIndex() + refLoc[ip];
589 int* indGlo = fRecord->GetIndex() + refGlo[ip];
590
591 for (int i = nrefGlo[ip]; i--;) { // suppress the global part (only relevant with iterations)
592
593 // if regrouping was requested, do it here
594 if (fkReGroup.size()) {
595 int idtmp = fkReGroup[indGlo[i]];
596 if (idtmp == kFixParID) {
597 indGlo[i] = kFixParID; // fixed param in regrouping
598 } else {
599 indGlo[i] = idtmp;
600 }
601 }
602
603 int iID = indGlo[i]; // Global param indice
604 if (iID < 0 || fSigmaPar[iID] <= 0.) {
605 continue; // fixed parameter RRRCheck
606 }
607 if (fIsLinear[iID]) {
608 resid -= derGlo[i] * (fInitPar[iID] + fDeltaPar[iID]); // linear parameter
609 } else {
610 resid -= derGlo[i] * fDeltaPar[iID]; // nonlinear parameter
611 }
612 }
613
614 // Symmetric matrix, don't bother j>i coeffs
615 for (int i = nrefLoc[ip]; i--;) { // Fill local matrix and vector
616 fVecBLoc[indLoc[i]] += weight * resid * derLoc[i];
617 if (indLoc[i] > maxLocUsed) {
618 maxLocUsed = indLoc[i];
619 }
620 for (int j = i + 1; j--;) {
621 matCLoc(indLoc[i], indLoc[j]) += weight * derLoc[i] * derLoc[j];
622 }
623 }
624
625 } // end of the transfer of the measurement record to matrices
626
627 matCLoc.SetSizeUsed(++maxLocUsed); // data with B=0 may use less than declared nLocals
628
629 /* //RRR
630 fRecord->Print("l");
631 printf("\nBefore\nLocalMatrix: "); matCLoc.Print("l");
632 printf("RHSLoc: "); for (int i=0;i<fNLocPar;i++) printf("%+e |",fVecBLoc[i]); printf("\n");
633 */
634 // first try to solve by faster Cholesky decomposition, then by Gaussian elimination
635 double* pVecBLoc = &fVecBLoc[0];
636 if (!matCLoc.SolveChol(pVecBLoc, true)) {
637 LOG(warning) << "MillePede2 - Failed to solve locals by Cholesky, trying Gaussian Elimination";
638 if (!matCLoc.SolveSpmInv(pVecBLoc, true)) {
639 LOG(warning) << "MillePede2 - Failed to solve locals by Gaussian Elimination, skip...";
640 matCLoc.Print("d");
641 return 0; // failed to solve
642 }
643 }
644
645 // If requested, store the track params and errors
646 // RRR printf("locfit: "); for (int i=0;i<fNLocPar;i++) printf("%+e |",fVecBLoc[i]); printf("\n");
647
648 if (localParams.size()) {
649 for (int i = maxLocUsed; i--;) {
650 localParams[2 * i] = fVecBLoc[i];
651 localParams[2 * i + 1] = TMath::Sqrt(TMath::Abs(matCLoc.QueryDiag(i)));
652 }
653 }
654 float lChi2 = 0;
655 int nEq = 0;
656
657 for (int ip = nPoints; ip--;) { // Calculate residuals
658 double resid = fRecord->GetValue(refLoc[ip] - 1);
659 double weight = fRecord->GetValue(refGlo[ip] - 1) * gloWgh;
660 int odd = (ip & 0x1);
661 if (fWghScl[odd] > 0) {
662 weight *= fWghScl[odd];
663 }
664 double* derLoc = fRecord->GetValue() + refLoc[ip];
665 double* derGlo = fRecord->GetValue() + refGlo[ip];
666 int* indLoc = fRecord->GetIndex() + refLoc[ip];
667 int* indGlo = fRecord->GetIndex() + refGlo[ip];
668
669 // Suppress local and global contribution in residuals;
670 for (int i = nrefLoc[ip]; i--;) {
671 resid -= derLoc[i] * fVecBLoc[indLoc[i]];
672 } // local part
673
674 for (int i = nrefGlo[ip]; i--;) { // global part
675 int iID = indGlo[i];
676 if (iID < 0 || fSigmaPar[iID] <= 0.) {
677 continue;
678 } // fixed parameter RRRCheck
679 if (fIsLinear[iID]) {
680 resid -= derGlo[i] * (fInitPar[iID] + fDeltaPar[iID]); // linear parameter
681 } else {
682 resid -= derGlo[i] * fDeltaPar[iID]; // nonlinear parameter
683 }
684 }
685
686 // reject the track if the residual is too large (outlier)
687 double absres = TMath::Abs(resid);
688 if ((absres >= fResCutInit && fIter == 1) || (absres >= fResCut && fIter > 1)) {
689 if (fLocFitAdd) {
691 }
692 LOGF(info, "MillePede2 - reject res %+e in record %5ld ", resid, fCurrRecDataID); // A.R. comment
693 return 0;
694 }
695
696 lChi2 += weight * resid * resid; // total chi^2
697 nEq++; // number of equations
698 } // end of Calculate residuals
699
700 lChi2 /= gloWgh;
701 int nDoF = nEq - maxLocUsed;
702 lChi2 = (nDoF > 0) ? lChi2 / nDoF : 0; // Chi^2/dof
703 fSumChi2 = lChi2;
704 fRecNDoF = nDoF;
705
706 if (fNStdDev != 0 && nDoF > 0 && lChi2 > Chi2DoFLim(fNStdDev, nDoF) * fChi2CutFactor) { // check final chi2
707 fIsChi2BelowLimit = false;
708 if (GetCurrentIteration() == 1 && fTreeChi2) {
709 fTreeChi2->Fill();
710 }
711 if (fLocFitAdd) {
713 }
714 LOGF(debug, "MillePede2 - reject chi2 %+e record %5ld: (nDOF %d)", lChi2, fCurrRecDataID, nDoF); // A.R. comment
715 // fRecord->Print(); // A.R. comment
716 return 0;
717 }
718
719 if (fLocFitAdd) {
720 fNLocFits++;
721 fNLocEquations += nEq;
722 } else {
723 fNLocFits--;
724 fNLocEquations -= nEq;
725 }
726
727 // local operations are finished, track is accepted
728 // We now update the global parameters (other matrices)
729
730 int nGloInFit = 0;
731
732 for (int ip = nPoints; ip--;) { // Update matrices
733 double resid = fRecord->GetValue(refLoc[ip] - 1);
734 double weight = fRecord->GetValue(refGlo[ip] - 1) * gloWgh;
735 int odd = (ip & 0x1);
736 if (fWghScl[odd] > 0) {
737 weight *= fWghScl[odd];
738 }
739 double* derLoc = fRecord->GetValue() + refLoc[ip];
740 double* derGlo = fRecord->GetValue() + refGlo[ip];
741 int* indLoc = fRecord->GetIndex() + refLoc[ip];
742 int* indGlo = fRecord->GetIndex() + refGlo[ip];
743
744 for (int i = nrefGlo[ip]; i--;) { // suppress the global part
745 int iID = indGlo[i]; // Global param indice
746 if (iID < 0 || fSigmaPar[iID] <= 0.) {
747 continue;
748 } // fixed parameter RRRCheck
749 if (fIsLinear[iID]) {
750 resid -= derGlo[i] * (fInitPar[iID] + fDeltaPar[iID]); // linear parameter
751 } else {
752 resid -= derGlo[i] * fDeltaPar[iID]; // nonlinear parameter
753 }
754 }
755
756 for (int ig = nrefGlo[ip]; ig--;) {
757 int iIDg = indGlo[ig]; // Global param indice (the matrix line)
758 if (iIDg < 0 || fSigmaPar[iIDg] <= 0.) {
759 continue;
760 } // fixed parameter RRRCheck
761 if (fLocFitAdd) {
762 fVecBGlo[iIDg] += weight * resid * derGlo[ig];
763 } else {
764 fVecBGlo[iIDg] -= weight * resid * derGlo[ig];
765 }
766
767 // First of all, the global/global terms (exactly like local matrix)
768 int nfill = 0;
769 for (int jg = ig + 1; jg--;) { // matCGlo is symmetric by construction
770 int jIDg = indGlo[jg];
771 if (jIDg < 0 || fSigmaPar[jIDg] <= 0.) {
772 continue;
773 } // fixed parameter RRRCheck
774 if (!IsZero(vl = weight * derGlo[ig] * derGlo[jg])) {
775 fFillIndex[nfill] = jIDg;
776 fFillValue[nfill++] = fLocFitAdd ? vl : -vl;
777 }
778 }
779 if (nfill) {
780 matCGlo.AddToRow(iIDg, fFillValue.data(), fFillIndex.data(), nfill);
781 }
782
783 // Now we have also rectangular matrices containing global/local terms.
784 int iCIDg = fGlo2CGlo[iIDg]; // compressed Index of index
785 if (iCIDg == -1) {
786 double* rowGL = matCGloLoc(nGloInFit);
787 for (int k = maxLocUsed; k--;) {
788 rowGL[k] = 0.0;
789 } // reset the row
790 iCIDg = fGlo2CGlo[iIDg] = nGloInFit;
791 fCGlo2Glo[nGloInFit++] = iIDg;
792 }
793
794 double* rowGLIDg = matCGloLoc(iCIDg);
795 for (int il = nrefLoc[ip]; il--;) {
796 rowGLIDg[indLoc[il]] += weight * derGlo[ig] * derLoc[il];
797 }
798 fProcPnt[iIDg] += fLocFitAdd ? 1 : -1; // update counter
799 }
800 } // end of Update matrices
801 //
802 /*//RRR
803 LOG(info) << "MillePede2 - After GLO";
804 printf("MatCLoc: "); fMatCLoc->Print("l");
805 printf("MatCGlo: "); fMatCGlo->Print("l");
806 printf("MatCGlLc:"); fMatCGloLoc->Print("l");
807 printf("BGlo: "); for (int i=0; i<fNGloPar; i++) printf("%+e |",fVecBGlo[i]); printf("\n");
808 */
809 // calculate fMatCGlo -= fMatCGloLoc * fMatCLoc * fMatCGloLoc^T
810 // and fVecBGlo -= fMatCGloLoc * fVecBLoc
811 //
812 //-------------------------------------------------------------- >>>
813 double vll;
814 for (int iCIDg = 0; iCIDg < nGloInFit; iCIDg++) {
815 int iIDg = fCGlo2Glo[iCIDg];
816
817 vl = 0;
818 double* rowGLIDg = matCGloLoc(iCIDg);
819 for (int kl = 0; kl < maxLocUsed; kl++) {
820 if (rowGLIDg[kl]) {
821 vl += rowGLIDg[kl] * fVecBLoc[kl];
822 }
823 }
824 if (!IsZero(vl)) {
825 fVecBGlo[iIDg] -= fLocFitAdd ? vl : -vl;
826 }
827
828 int nfill = 0;
829 for (int jCIDg = 0; jCIDg <= iCIDg; jCIDg++) {
830 int jIDg = fCGlo2Glo[jCIDg];
831
832 vl = 0;
833 double* rowGLJDg = matCGloLoc(jCIDg);
834 for (int kl = 0; kl < maxLocUsed; kl++) {
835 // diag terms
836 if ((!IsZero(vll = rowGLIDg[kl] * rowGLJDg[kl]))) {
837 vl += matCLoc.QueryDiag(kl) * vll;
838 }
839 //
840 // off-diag terms
841 for (int ll = 0; ll < kl; ll++) {
842 if (!IsZero(vll = rowGLIDg[kl] * rowGLJDg[ll])) {
843 vl += matCLoc(kl, ll) * vll;
844 }
845 if (!IsZero(vll = rowGLIDg[ll] * rowGLJDg[kl])) {
846 vl += matCLoc(kl, ll) * vll;
847 }
848 }
849 }
850 if (!IsZero(vl)) {
851 fFillIndex[nfill] = jIDg;
852 fFillValue[nfill++] = fLocFitAdd ? -vl : vl;
853 }
854 }
855 if (nfill) {
856 matCGlo.AddToRow(iIDg, fFillValue.data(), fFillIndex.data(), nfill);
857 }
858 }
859
860 // reset compressed index array
861
862 /*//RRR
863 LOG(info) << "MillePede2 - After GLOLoc";
864 printf("MatCGlo: "); fMatCGlo->Print("");
865 printf("BGlo: "); for (int i=0; i<fNGloPar; i++) printf("%+e |",fVecBGlo[i]); printf("\n");
866 */
867 for (int i = nGloInFit; i--;) {
868 fGlo2CGlo[fCGlo2Glo[i]] = -1;
869 fCGlo2Glo[i] = -1;
870 }
871 //
872 //---------------------------------------------------- <<<
873 if (GetCurrentIteration() == 1 && fTreeChi2) {
874 fTreeChi2->Fill();
875 }
876 return 1;
877}
878
879//_____________________________________________________________________________
880int MillePede2::GlobalFit(std::vector<double>& par,
881 std::vector<double>& error,
882 std::vector<double>& pull)
883{
884 if (fRecordReader == nullptr) {
885 LOG(fatal) << "MillePede2::GlobalFit() - aborted, input record reader is a null pointer";
886 return 1;
887 }
888 fIter = 1;
889
890 TStopwatch sw;
891 sw.Start();
892
893 int res = 0;
894 LOG(info) << "MillePede2 - Starting Global fit.";
895 while (fIter <= fMaxIter) {
896 //
898 if (!res) {
899 break;
900 }
901 //
903 fChi2CutFactor = TMath::Sqrt(fChi2CutFactor);
904 if (fChi2CutFactor < 1.2 * fChi2CutRef) {
906 // fIter = fMaxIter - 1; // RRR // Last iteration
907 }
908 }
909 fIter++;
910 }
911
912 sw.Stop();
913 LOGF(info, "MillePede2 - Global fit %s, CPU time: %.1f", res ? "Converged" : "Failed", sw.CpuTime());
914 if (!res) {
915 return 0;
916 }
917
918 if (par.size()) {
919 for (int i = fNGloParIni; i--;) {
920 par[i] = GetFinalParam(i);
921 }
922 }
923
924 if (fGloSolveStatus == kInvert) { // errors on params are available
925 if (error.size()) {
926 for (int i = fNGloParIni; i--;) {
927 error[i] = GetFinalError(i);
928 }
929 }
930 if (pull.size()) {
931 for (int i = fNGloParIni; i--;) {
932 pull[i] = GetPull(i);
933 }
934 }
935 }
936
937 return 1;
938}
939
940//_____________________________________________________________________________
942{
943 LOGF(info, "MillePede2 - Global Fit Iteration#%2d (Local Fit Chi^2 cut factor: %.2f)", fIter, fChi2CutFactor);
944
945 if (!fRecordReader) {
946 LOG(info) << "MillePede2::GlobalFitIteration() - no record is accessible, stopping iteration";
947 return 0;
948 }
949 if (!fNGloPar) {
950 LOG(info) << "MillePede2::GlobalFitIteration() - zero global parameter, stopping iteration";
951 return 0;
952 }
953 TStopwatch sw, sws;
954 sw.Start();
955 sws.Stop();
956
957 if (!fConstrUsed.size()) {
958 fConstrUsed = std::vector<bool>(fNGloConstraints);
959 std::fill(fConstrUsed.begin(), fConstrUsed.end(), 0);
960 }
961 // Reset all info specific for this step
962 MatrixSq& matCGlo = *fMatCGlo;
963 matCGlo.Reset();
964 std::fill(fProcPnt.begin(), fProcPnt.end(), 0);
965
967
968 // count number of Lagrange constraints: they need new row/cols to be added
970 for (int i = 0; i < fNGloConstraints; i++) {
973 continue;
974 }
975 if (IsZero(fRecord->GetValue(1))) {
976 fNLagrangeConstraints++; // exact constraint (no error) -> Lagrange multiplier
977 }
978 }
979
980 // if needed, readjust the size of the global vector (for matrices this is done automatically)
981 if (!fVecBGlo.size() || fNGloSize != fNGloPar + fNLagrangeConstraints) {
982 fVecBGlo.clear(); // in case some constraint was added between the two manual iterations
984 fVecBGlo = std::vector<double>(fNGloSize);
985 }
986
987 fNLocFits = 0;
989 fNLocEquations = 0;
990
991 // Process data records and build the matrices
992 long ndr = fRecordReader->getNEntries();
993 long first = fSelFirst > 0 ? fSelFirst : 0;
994 long last = fSelLast < 1 ? ndr : (fSelLast >= ndr ? ndr : fSelLast + long(1));
995 ndr = last - first;
996
997 LOGF(info, "MillePede2 - Building the Global matrix from data records %ld : %ld", first, last);
998 if (ndr < 1) {
999 return 0;
1000 }
1001
1002 TStopwatch swt;
1003 swt.Start();
1004 fLocFitAdd = true; // add contributions of matching tracks
1005 for (long i = 0; i < ndr; i++) {
1006 long iev = i + first;
1007 ReadRecordData(iev);
1009 continue;
1010 }
1011 std::vector<double> emptyLocalParams = {};
1012 LocalFit(emptyLocalParams);
1013 if ((i % int(0.2 * ndr)) == 0) {
1014 printf("%.1f%% of local fits done\n", double(100. * i) / ndr);
1015 }
1016 }
1017 swt.Stop();
1018 LOGF(info, "MillePede2 - %ld local fits done: ", ndr);
1019 /*
1020 printf("MatCGlo: "); fMatCGlo->Print("l");
1021 printf("BGlo: "); for (int i=0; i<fNGloPar; i++) printf("%+e |",fVecBGlo[i]); printf("\n");
1022 swt.Print();
1023 */
1024 sw.Start(false);
1025
1026 // ---------------------- Reject parameters with low statistics ------------>>
1027 fNGloFix = 0;
1028 if (fMinPntValid > 1 && fNGroupsSet) {
1029 //
1030 LOGF(info, "MillePede2 - Checking parameters with statistics < %d", fMinPntValid);
1031 TStopwatch swsup;
1032 swsup.Start();
1033 // 1) build the list of parameters to fix
1034 int fixArrSize = 10;
1035 int nFixedGroups = 0;
1036 TArrayI fixGroups(fixArrSize);
1037 //
1038 int grIDold = -2;
1039 int oldStart = -1;
1040 double oldMin = 1.e20;
1041 double oldMax = -1.e20;
1042
1043 for (int i = fNGloPar; i--;) { // Reset row and column of fixed params and add 1/sig^2 to free ones
1044 int grID = fParamGrID[i];
1045 if (grID < 0) {
1046 continue; // not in the group
1047 }
1048
1049 if (grID != grIDold) { // starting new group
1050 if (grIDold >= 0) { // decide if the group has enough statistics
1051 if (oldMin < fMinPntValid && oldMax < 2 * fMinPntValid) { // suppress group
1052 for (int iold = oldStart; iold > i; iold--) {
1053 fProcPnt[iold] = 0;
1054 }
1055 bool fnd = false; // check if the group is already accounted
1056 for (int j = nFixedGroups; j--;) {
1057 if (fixGroups[j] == grIDold) {
1058 fnd = true;
1059 break;
1060 }
1061 }
1062 if (!fnd) {
1063 if (nFixedGroups >= fixArrSize) {
1064 fixArrSize *= 2;
1065 fixGroups.Set(fixArrSize);
1066 }
1067 fixGroups[nFixedGroups++] = grIDold; // add group to fix
1068 }
1069 }
1070 }
1071 grIDold = grID; // mark the start of the new group
1072 oldStart = i;
1073 oldMin = 1.e20;
1074 oldMax = -1.e20;
1075 }
1076 if (oldMin > fProcPnt[i]) {
1077 oldMin = fProcPnt[i];
1078 }
1079 if (oldMax < fProcPnt[i]) {
1080 oldMax = fProcPnt[i];
1081 }
1082 }
1083 // extra check for the last group
1084 if (grIDold >= 0 && oldMin < fMinPntValid && oldMax < 2 * fMinPntValid) { // suppress group
1085 for (int iold = oldStart; iold--;) {
1086 fProcPnt[iold] = 0;
1087 }
1088 bool fnd = false; // check if the group is already accounted
1089 for (int j = nFixedGroups; j--;) {
1090 if (fixGroups[j] == grIDold) {
1091 fnd = true;
1092 break;
1093 }
1094 }
1095 if (!fnd) {
1096 if (nFixedGroups >= fixArrSize) {
1097 fixArrSize *= 2;
1098 fixGroups.Set(fixArrSize);
1099 }
1100 fixGroups[nFixedGroups++] = grIDold; // add group to fix
1101 }
1102 }
1103
1104 // 2) loop over records and add contributions of fixed groups with negative sign
1105 fLocFitAdd = false;
1106
1107 for (long i = 0; i < ndr; i++) {
1108 long iev = i + first;
1109 ReadRecordData(iev);
1111 continue;
1112 }
1113 bool suppr = false;
1114 for (int ifx = nFixedGroups; ifx--;) {
1115 if (fRecord->IsGroupPresent(fixGroups[ifx])) {
1116 suppr = true;
1117 }
1118 }
1119 if (suppr) {
1120 std::vector<double> emptyLocalParams = {};
1121 LocalFit(emptyLocalParams);
1122 }
1123 }
1124 fLocFitAdd = true;
1125
1126 if (nFixedGroups) {
1127 LOGF(info, "MillePede2 - Suppressed contributions of groups with NPoints < %d :", fMinPntValid);
1128 for (int i = 0; i < nFixedGroups; i++) {
1129 printf("%d ", fixGroups[i]);
1130 }
1131 printf("\n");
1132 }
1133 swsup.Stop();
1134 swsup.Print();
1135 }
1136 // ---------------------- Reject parameters with low statistics ------------<<
1137
1138 // add large number to diagonal of fixed params
1139
1140 for (int i = fNGloPar; i--;) { // Reset row and column of fixed params and add 1/sig^2 to free ones
1141 // printf("#%3d : Nproc : %5d grp: %d\n",i,fProcPnt[i],fParamGrID[i]);
1142 if (fProcPnt[i] < 1) {
1143 fNGloFix++;
1144 fVecBGlo[i] = 0.;
1145 matCGlo.DiagElem(i) = 1.;
1146 // float(fNLocEquations*fNLocEquations);
1147 // matCGlo.DiagElem(i) = float(fNLocEquations*fNLocEquations);
1148 } else {
1149 matCGlo.DiagElem(i) += (fgWeightSigma ? fProcPnt[i] : 1.) / (fSigmaPar[i] * fSigmaPar[i]);
1150 }
1151 }
1152
1153 for (int i = fNGloPar; i--;) {
1154 fDiagCGlo[i] = matCGlo.QueryDiag(i); // save the diagonal elements
1155 }
1156
1157 // add constraint equations
1158 int nVar = fNGloPar; // Current size of global matrix
1159 for (int i = 0; i < fNGloConstraints; i++) {
1162 continue;
1163 }
1164 double val = fRecord->GetValue(0);
1165 double sig = fRecord->GetValue(1);
1166 int* indV = fRecord->GetIndex() + 2;
1167 double* der = fRecord->GetValue() + 2;
1168 int csize = fRecord->GetSize() - 2;
1169 //
1170 if (fkReGroup.size()) {
1171 for (int jp = csize; jp--;) {
1172 int idp = indV[jp];
1173 if (fkReGroup[idp] < 0) {
1174 LOGF(fatal, "MillePede2 - Constain is requested for suppressed parameter #%d", indV[jp]);
1175 }
1176 indV[jp] = idp;
1177 }
1178 }
1179 // check if after suppression of fixed variables there are non-0 derivatives
1180 // and determine the max statistics of involved params
1181 int nSuppressed = 0;
1182 int maxStat = 1;
1183 for (int j = csize; j--;) {
1184 if (fProcPnt[indV[j]] < 1) {
1185 nSuppressed++;
1186 } else {
1187 maxStat = TMath::Max(maxStat, fProcPnt[indV[j]]);
1188 }
1189 }
1190
1191 if (nSuppressed == csize) {
1192 // LOG(info << Form("Neglecting constraint %d of %d derivatives since no free parameters left",i,csize));
1193
1194 // was this constraint ever created ?
1195 if (sig == 0 && fConstrUsed[i]) { // this is needed only for constraints with Lagrange multiplier
1196 // to avoid empty row impose dummy constraint on "Lagrange multiplier"
1197 matCGlo.DiagElem(nVar) = 1.;
1198 fVecBGlo[nVar++] = 0;
1199 }
1200 continue;
1201 }
1202
1203 // account for already accumulated corrections
1204 for (int j = csize; j--;) {
1205 val -= der[j] * (fInitPar[indV[j]] + fDeltaPar[indV[j]]);
1206 }
1207
1208 if (sig > 0) { // this is a gaussian constriant: no Lagrange multipliers are added
1209
1210 double sig2i = (fgWeightSigma ? TMath::Sqrt(maxStat) : 1.) / sig / sig;
1211 for (int ir = 0; ir < csize; ir++) {
1212 int iID = indV[ir];
1213 for (int ic = 0; ic <= ir; ic++) { // matrix is symmetric
1214 int jID = indV[ic];
1215 double vl = der[ir] * der[ic] * sig2i;
1216 if (!IsZero(vl)) {
1217 matCGlo(iID, jID) += vl;
1218 }
1219 }
1220 fVecBGlo[iID] += val * der[ir] * sig2i;
1221 }
1222 } else { // this is exact constriant: Lagrange multipliers must be added
1223 for (int j = csize; j--;) {
1224 int jID = indV[j];
1225 if (fProcPnt[jID] < 1) { // this parameter was fixed, don't put it into constraint
1226 continue;
1227 }
1228 matCGlo(nVar, jID) = float(fNLocEquations) * der[j]; // fMatCGlo is symmetric, only lower triangle is filled
1229 }
1230
1231 if (matCGlo.QueryDiag(nVar)) {
1232 matCGlo.DiagElem(nVar) = 0.0;
1233 }
1234 fVecBGlo[nVar++] = float(fNLocEquations) * val; // RS ? should we use here fNLocFits ?
1235 fConstrUsed[i] = true;
1236 }
1237 }
1238
1239 LOGF(info, "MillePede2 - Obtained %-7ld equations from %-7ld records (%-7ld rejected). Fixed %-4d globals",
1241
1242 sws.Start();
1243
1244#ifdef _DUMP_EQ_BEFORE_
1245 const char* faildumpB = Form("mp2eq_before%d.dat", fIter);
1246 int defoutB = dup(1);
1247 if (defoutB < 0) {
1248 LOG(fatal) << "Failed on dup";
1249 exit(1);
1250 }
1251 int slvDumpB = open(faildumpB, O_RDWR | O_CREAT, 0666);
1252 if (slvDumpB >= 0) {
1253 dup2(slvDumpB, 1);
1254 printf("Solving%d for %d params\n", fIter, fNGloSize);
1255 matCGlo.Print("10");
1256 for (int i = 0; i < fNGloSize; i++)
1257 printf("b%2d : %+.10f\n", i, fVecBGlo[i]);
1258 }
1259 dup2(defoutB, 1);
1260 close(slvDumpB);
1261 close(defoutB);
1262
1263#endif
1264 /*
1265 printf("Solving:\n");
1266 matCGlo.Print("l");
1267 for (int i=0;i<fNGloSize;i++) printf("b%2d : %+e\n",i,fVecBGlo[i]);
1268 */
1269#ifdef _DUMPEQ_BEFORE_
1270 const char* faildumpB = Form("mp2eq_before%d.dat", fIter);
1271 int defoutB = dup(1);
1272 int slvDumpB = open(faildumpB, O_RDWR | O_CREAT, 0666);
1273 dup2(slvDumpB, 1);
1274 //
1275 printf("#Equation before step %d\n", fIter);
1276 fMatCGlo->Print("10");
1277 printf("#RHS/STAT : NGlo:%d NGloSize:%d\n", fNGloPar, fNGloSize);
1278 for (int i = 0; i < fNGloSize; i++) {
1279 printf("%d %+.10f %d\n", i, fVecBGlo[i], fProcPnt[i]);
1280 }
1281 //
1282 dup2(defoutB, 1);
1283 close(slvDumpB);
1284 close(defoutB);
1285#endif
1286 //
1287 fGloSolveStatus = SolveGlobalMatEq(); // obtain solution for this step
1288#ifdef _DUMPEQ_AFTER_
1289 const char* faildumpA = Form("mp2eq_after%d.dat", fIter);
1290 int defoutA = dup(1);
1291 int slvDumpA = open(faildumpA, O_RDWR | O_CREAT, 0666);
1292 dup2(slvDumpA, 1);
1293 //
1294 printf("#Matrix after step %d\n", fIter);
1295 fMatCGlo->Print("10");
1296 printf("#RHS/STAT : NGlo:%d NGloSize:%d\n", fNGloPar, fNGloSize);
1297 for (int i = 0; i < fNGloSize; i++) {
1298 printf("%d %+.10f %d\n", i, fVecBGlo[i], fProcPnt[i]);
1299 }
1300 //
1301 dup2(defoutA, 1);
1302 close(slvDumpA);
1303 close(defoutA);
1304#endif
1305 //
1306 sws.Stop();
1307 printf("Solve %d |", fIter);
1308 sws.Print();
1309 //
1310 sw.Stop();
1311 LOGF(info, "MillePede2 - Iteration#%2d %s. CPU time: %.1f", fIter, fGloSolveStatus == kFailed ? "Failed" : "Converged", sw.CpuTime());
1312 if (fGloSolveStatus == kFailed) {
1313 return 0;
1314 }
1315 //
1316 for (int i = fNGloPar; i--;) { // Update global parameters values (for iterations)
1317 fDeltaPar[i] += fVecBGlo[i];
1318 }
1319
1320#ifdef _DUMP_EQ_AFTER_
1321 const char* faildumpA = Form("mp2eq_after%d.dat", fIter);
1322 int defoutA = dup(1);
1323 if (defoutA < 0) {
1324 LOG(fatal) << "Failed on dup";
1325 exit(1);
1326 }
1327 int slvDumpA = open(faildumpA, O_RDWR | O_CREAT, 0666);
1328 if (slvDumpA >= 0) {
1329 dup2(slvDumpA, 1);
1330 printf("Solving%d for %d params\n", fIter, fNGloSize);
1331 matCGlo.Print("10");
1332 for (int i = 0; i < fNGloSize; i++) {
1333 printf("b%2d : %+.10f\n", i, fVecBGlo[i]);
1334 }
1335 }
1336 dup2(defoutA, 1);
1337 close(slvDumpA);
1338 close(defoutA);
1339#endif
1340 //
1341 /*
1342 printf("Solved:\n");
1343 matCGlo.Print("l");
1344 for (int i=0;i<fNGloSize;i++) printf("b%2d : %+e (->%+e)\n",i,fVecBGlo[i], fDeltaPar[i]);
1345 */
1346
1348 return 1;
1349}
1350
1351//_____________________________________________________________________________
1353{
1354 /*
1355 printf("GlobalMatrix\n");
1356 fMatCGlo->Print("l");
1357 printf("RHS\n");
1358 for (int i=0;i<fNGloPar;i++) printf("%d %+e\n",i,fVecBGlo[i]);
1359 */
1360
1361 if (!fgIsMatGloSparse) {
1362 if (fNLagrangeConstraints == 0) { // pos-def systems are faster to solve by Cholesky
1363 if (((SymMatrix*)fMatCGlo)->SolveChol(fVecBGlo.data(), fgInvChol)) {
1364 return fgInvChol ? kInvert : kNoInversion;
1365 } else {
1366 LOG(warning) << "MillePede2 - Solution of Global Dense System by Cholesky failed, trying Gaussian Elimiation";
1367 }
1368 }
1369 if (((SymMatrix*)fMatCGlo)->SolveSpmInv(fVecBGlo.data(), true)) {
1370 return kInvert;
1371 } else {
1372 LOG(warning) << "MillePede2 - Solution of Global Dense System by Gaussian Elimination failed, trying iterative methods";
1373 }
1374 }
1375 // try to solve by minres
1376 TVectorD sol(fNGloSize);
1377
1378 MinResSolve* slv = new MinResSolve(fMatCGlo, fVecBGlo.data());
1379 if (!slv) {
1380 return kFailed;
1381 }
1382 bool res = false;
1385 } else {
1388 } else {
1389 LOGF(warning, "MillePede2 - Undefined Iteritive Solver ID=%d, only %d are defined", fgIterSol, (int)MinResSolve::kNSolvers);
1390 }
1391 }
1392
1393 if (!res) {
1394 const char* faildump = "fgmr_failed.dat";
1395 int defout = dup(1);
1396 if (defout < 0) {
1397 LOG(warning) << "Failed on dup";
1398 return kFailed;
1399 }
1400 int slvDump = open(faildump, O_RDWR | O_CREAT, 0666);
1401 if (slvDump >= 0) {
1402 dup2(slvDump, 1);
1403 printf("#Failed to solve using solver %d with PreCond: %d MaxIter: %d Tol: %e NKrylov: %d\n",
1405 printf("#Dump of matrix:\n");
1406 fMatCGlo->Print("10");
1407 printf("#Dump of RHS:\n");
1408 for (int i = 0; i < fNGloSize; i++) {
1409 printf("%d %+.10f\n", i, fVecBGlo[i]);
1410 }
1411 dup2(defout, 1);
1412 close(slvDump);
1413 close(defout);
1414 printf("#Dumped failed matrix and RHS to %s\n", faildump);
1415 } else {
1416 LOG(warning) << "MillePede2 - Failed on file open for matrix dumping";
1417 }
1418 close(defout);
1419 return kFailed;
1420 }
1421 for (int i = fNGloSize; i--;) {
1422 fVecBGlo[i] = sol[i];
1423 }
1424
1425 return kNoInversion;
1426}
1427
1428//_____________________________________________________________________________
1429Float_t MillePede2::Chi2DoFLim(int nSig, int nDoF) const
1430{
1431 int lNSig;
1432 float sn[3] = {0.47523, 1.690140, 2.782170};
1433 float table[3][30] = {{1.0000, 1.1479, 1.1753, 1.1798, 1.1775, 1.1730, 1.1680, 1.1630,
1434 1.1581, 1.1536, 1.1493, 1.1454, 1.1417, 1.1383, 1.1351, 1.1321,
1435 1.1293, 1.1266, 1.1242, 1.1218, 1.1196, 1.1175, 1.1155, 1.1136,
1436 1.1119, 1.1101, 1.1085, 1.1070, 1.1055, 1.1040},
1437 {4.0000, 3.0900, 2.6750, 2.4290, 2.2628, 2.1415, 2.0481, 1.9736,
1438 1.9124, 1.8610, 1.8171, 1.7791, 1.7457, 1.7161, 1.6897, 1.6658,
1439 1.6442, 1.6246, 1.6065, 1.5899, 1.5745, 1.5603, 1.5470, 1.5346,
1440 1.5230, 1.5120, 1.5017, 1.4920, 1.4829, 1.4742},
1441 {9.0000, 5.9146, 4.7184, 4.0628, 3.6410, 3.3436, 3.1209, 2.9468,
1442 2.8063, 2.6902, 2.5922, 2.5082, 2.4352, 2.3711, 2.3143, 2.2635,
1443 2.2178, 2.1764, 2.1386, 2.1040, 2.0722, 2.0428, 2.0155, 1.9901,
1444 1.9665, 1.9443, 1.9235, 1.9040, 1.8855, 1.8681}};
1445
1446 if (nDoF < 1) {
1447 return 0.0;
1448 } else {
1449 lNSig = TMath::Max(1, TMath::Min(nSig, 3));
1450
1451 if (nDoF <= 30) {
1452 return table[lNSig - 1][nDoF - 1];
1453 } else { // approximation
1454 return ((sn[lNSig - 1] + TMath::Sqrt(float(2 * nDoF - 3))) *
1455 (sn[lNSig - 1] + TMath::Sqrt(float(2 * nDoF - 3)))) /
1456 float(2 * nDoF - 2);
1457 }
1458 }
1459}
1460
1461//_____________________________________________________________________________
1462int MillePede2::SetIterations(const double lChi2CutFac)
1463{
1464 fChi2CutFactor = TMath::Max(1.0, lChi2CutFac);
1465 LOGF(info, "MillePede2 - Initial cut factor is %f", fChi2CutFactor);
1466 fIter = 1; // Initializes the iteration process
1467 return 1;
1468}
1469
1470//_____________________________________________________________________________
1471double MillePede2::GetParError(int iPar) const
1472{
1473 if (fGloSolveStatus == kInvert) {
1474 if (fkReGroup.size()) {
1475 iPar = fkReGroup[iPar];
1476 }
1477 if (iPar < 0) {
1478 // LOG(debug) << Form("Parameter %d was suppressed in the regrouping",iPar));
1479 return 0;
1480 }
1481 double res = fMatCGlo->QueryDiag(iPar);
1482 if (res >= 0) {
1483 return TMath::Sqrt(res);
1484 }
1485 }
1486 return 0.;
1487}
1488
1489//_____________________________________________________________________________
1490double MillePede2::GetPull(int iPar) const
1491{
1492 if (fGloSolveStatus == kInvert) {
1493 if (fkReGroup.size()) {
1494 iPar = fkReGroup[iPar];
1495 }
1496 if (iPar < 0) {
1497 // LOG(debug) << Form("Parameter %d was suppressed in the regrouping",iPar));
1498 return 0;
1499 }
1500 return fProcPnt[iPar] > 0 && (fSigmaPar[iPar] * fSigmaPar[iPar] - fMatCGlo->QueryDiag(iPar)) > 0. && fSigmaPar[iPar] > 0
1501 ? fDeltaPar[iPar] / TMath::Sqrt(fSigmaPar[iPar] * fSigmaPar[iPar] - fMatCGlo->QueryDiag(iPar))
1502 : 0;
1503 }
1504 return 0.;
1505}
1506
1507//_____________________________________________________________________________
1509{
1510 double lError = 0.;
1511 double lGlobalCor = 0.;
1512
1513 printf("\nMillePede2 output\n");
1514 printf(" Result of fit for global parameters\n");
1515 printf(" ===================================\n");
1516 printf(" I initial final differ lastcor error gcor Npnt\n");
1517 printf("----------------------------------------------------------------------------------------------\n");
1518 //
1519 int lastPrintedId = -1;
1520 for (int i0 = 0; i0 < fNGloParIni; i0++) {
1521 int i = GetRGId(i0);
1522 if (i < 0) {
1523 continue;
1524 }
1525 if (i != i0 && lastPrintedId >= 0 && i <= lastPrintedId) { // grouped param
1526 continue;
1527 }
1528 lastPrintedId = i;
1529 lError = GetParError(i0);
1530 lGlobalCor = 0.0;
1531 double dg;
1532 if (fGloSolveStatus == kInvert && TMath::Abs((dg = fMatCGlo->QueryDiag(i)) * fDiagCGlo[i]) > 0) {
1533 lGlobalCor = TMath::Sqrt(TMath::Abs(1.0 - 1.0 / (dg * fDiagCGlo[i])));
1534 printf("%4d(%4d)\t %+.6f\t %+.6f\t %+.6f\t %.6f\t %.6f\t %.6f\t %6d\n",
1535 i, i0, fInitPar[i], fInitPar[i] + fDeltaPar[i], fDeltaPar[i], fVecBGlo[i], lError, lGlobalCor, fProcPnt[i]);
1536 } else {
1537 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],
1539 }
1540 }
1541 return 1;
1542}
1543
1544//_____________________________________________________________________________
1546{
1547 static long prevRunID = kMaxInt;
1548 static bool prevAns = true;
1549 long runID = fRecord->GetRunID();
1550 if (runID != prevRunID) {
1551 int n = 0;
1552 fRunWgh = 1.;
1553 prevRunID = runID;
1554 // is run to be rejected?
1555 if (fRejRunList && (n = fRejRunList->GetSize())) {
1556 prevAns = true;
1557 for (int i = n; i--;) {
1558 if (runID == (*fRejRunList)[i]) {
1559 prevAns = false;
1560 LOGF(info, "MillePede2 - New Run to reject: %ld", runID);
1561 break;
1562 }
1563 }
1564 } else if (fAccRunList && (n = fAccRunList->GetSize())) { // is run specifically selected
1565 prevAns = false;
1566 for (int i = n; i--;) {
1567 if (runID == (*fAccRunList)[i]) {
1568 prevAns = true;
1569 if (fAccRunListWgh) {
1570 fRunWgh = (*fAccRunListWgh)[i];
1571 }
1572 LOGF(info, "MillePede2 - New Run to accept explicitly: %ld, weight=%f", runID, fRunWgh);
1573 break;
1574 }
1575 }
1576 if (!prevAns) {
1577 LOGF(info, "New Run is not in the list to accept: %ld", runID);
1578 }
1579 }
1580 }
1581
1582 return prevAns;
1583}
1584
1585//_____________________________________________________________________________
1586void MillePede2::SetRejRunList(const int* runs, const int nruns)
1587{
1588 if (fRejRunList) {
1589 delete fRejRunList;
1590 }
1591 fRejRunList = nullptr;
1592 if (nruns < 1 || !runs) {
1593 return;
1594 }
1595 fRejRunList = new TArrayL(nruns);
1596 for (int i = 0; i < nruns; i++) {
1597 (*fRejRunList)[i] = runs[i];
1598 }
1599}
1600
1601//_____________________________________________________________________________
1602void MillePede2::SetAccRunList(const int* runs, const int nruns, const float* wghList)
1603{
1604 if (fAccRunList) {
1605 delete fAccRunList;
1606 }
1607 if (fAccRunListWgh) {
1608 delete fAccRunListWgh;
1609 }
1610 fAccRunList = nullptr;
1611 if (nruns < 1 || !runs) {
1612 return;
1613 }
1614 fAccRunList = new TArrayL(nruns);
1615 fAccRunListWgh = new TArrayF(nruns);
1616 for (int i = 0; i < nruns; i++) {
1617 (*fAccRunList)[i] = runs[i];
1618 (*fAccRunListWgh)[i] = wghList ? wghList[i] : 1.0;
1619 }
1620}
1621
1622//_____________________________________________________________________________
1623void MillePede2::SetInitPars(const double* par)
1624{
1625 for (int i = 0; i < fNGloParIni; i++) {
1626 int id = GetRGId(i);
1627 if (id < 0) {
1628 continue;
1629 }
1630 fInitPar[id] = par[i];
1631 }
1632}
1633
1634//_____________________________________________________________________________
1635void MillePede2::SetSigmaPars(const double* par)
1636{
1637 for (int i = 0; i < fNGloParIni; i++) {
1638 int id = GetRGId(i);
1639 if (id < 0) {
1640 continue;
1641 }
1642 fSigmaPar[id] = par[i];
1643 }
1644}
1645
1646//_____________________________________________________________________________
1647void MillePede2::SetInitPar(int i, double par)
1648{
1649 int id = GetRGId(i);
1650 if (id < 0) {
1651 return;
1652 }
1653 fInitPar[id] = par;
1654}
1655
1656//_____________________________________________________________________________
1657void MillePede2::SetSigmaPar(int i, double par)
1658{
1659 int id = GetRGId(i);
1660 if (id < 0) {
1661 return;
1662 }
1663 fSigmaPar[id] = par;
1664}
int32_t i
ClassImp(MillePede2)
General class for alignment with large number of degrees of freedom, adapted from AliROOT.
uint32_t j
Definition RawData.h:0
uint32_t res
Definition RawData.h:0
std::ostringstream debug
void Print(Option_t *option="") const override=0
virtual void AddToRow(Int_t r, Double_t *valc, Int_t *indc, Int_t n)=0
virtual Double_t QueryDiag(Int_t rc) const
Definition MatrixSq.h:48
virtual void Reset()=0
virtual Double_t DiagElem(Int_t r) const =0
void SetSymmetric(Bool_t v=kTRUE)
Definition MatrixSq.h:65
std::vector< bool > fIsLinear
[fNGloPar] Flag for linear parameters
Definition MillePede2.h:340
void ReadRecordConstraint(const long recID, const bool doPrint=false)
read constraint record (if any) at entry id recID
std::vector< int > fkReGroup
optional regrouping of parameters wrt ID's from the records
Definition MillePede2.h:376
std::vector< int > fCGlo2Glo
[fNGloPar] compressed ID to global ID buffer
Definition MillePede2.h:344
static int fgNKrylovV
size of Krylov vectors buffer in FGMRES
Definition MillePede2.h:385
void SetGlobalConstraint(const std::vector< double > &dergb, const double val, const double sigma=0, const bool doPrint=false)
define a constraint equation
o2::fwdalign::MilleRecordWriter * fConstraintsRecWriter
constraints record writer
Definition MillePede2.h:389
o2::fwdalign::MilleRecordReader * fConstraintsRecReader
constraints record reader
Definition MillePede2.h:391
TArrayL * fAccRunList
list of runs to select (if any)
Definition MillePede2.h:372
float fResCut
Cut in residual for other iterartiona.
Definition MillePede2.h:326
int SolveGlobalMatEq()
solve global matrix equation MatCGlob*X=VecBGlo and store the result in the VecBGlo
int fNGloPar
number of global parameters
Definition MillePede2.h:308
TString fRecChi2TreeName
Name of chi2 per record tree.
Definition MillePede2.h:355
std::vector< int > fProcPnt
[fNGloPar] N of processed points per global variable
Definition MillePede2.h:331
int fIter
Current iteration.
Definition MillePede2.h:313
static int fgMinResCondType
Type of the preconditioner for MinRes method.
Definition MillePede2.h:381
bool InitChi2Storage(const int nEntriesAutoSave=10000)
initialize the file and tree to store chi2 from LocalFit()
std::vector< int > fFillIndex
[fNGloPar] auxilary index array for fast matrix fill
Definition MillePede2.h:350
std::vector< int > fParamGrID
[fNGloPar] group id for the every parameter
Definition MillePede2.h:330
bool fLocFitAdd
Add contribution of carrent track (and not eliminate it)
Definition MillePede2.h:365
int fNGloParIni
number of global parameters before grouping
Definition MillePede2.h:309
static int fgMinResMaxIter
Max number of iterations for the MinRes method.
Definition MillePede2.h:383
void SetRejRunList(const int *runs, const int nruns)
set the list of runs to be rejected
long fNLocFitsRejected
Number of local fits rejected.
Definition MillePede2.h:319
int LocalFit(std::vector< double > &localParams)
Perform local parameters fit once all the local equations have been set.
std::vector< double > fVecBGlo
Definition MillePede2.h:334
bool fDisableRecordWriter
disable record writer for DPL process
Definition MillePede2.h:367
int GetRGId(int i) const
Definition MillePede2.h:86
int GlobalFitIteration()
perform global parameters fit once all the local equations have been fitted
static int fgIterSol
type of iterative solution: MinRes or FGMRES
Definition MillePede2.h:384
o2::fwdalign::RectMatrix * fMatCGloLoc
Rectangular matrix C g*l.
Definition MillePede2.h:349
int fNLocPar
number of local parameters
Definition MillePede2.h:307
std::vector< double > fVecBLoc
[fNLocPar] Vector B local (parameters)
Definition MillePede2.h:332
const char * GetRecChi2FName() const
return file name where is stored chi2 from LocalFit()
Definition MillePede2.h:252
long fCurrRecDataID
ID of the current data record.
Definition MillePede2.h:363
int fGloSolveStatus
Status of global solver at current step.
Definition MillePede2.h:321
o2::fwdalign::MilleRecordReader * fRecordReader
data record reader
Definition MillePede2.h:390
std::vector< double > fDiagCGlo
[fNGloPar] Initial diagonal elements of C global matrix
Definition MillePede2.h:333
long fNLocEquations
Number of local equations.
Definition MillePede2.h:312
int fMinRecordLength
ignore shorter records
Definition MillePede2.h:368
std::vector< double > fSigmaPar
[fNGloPar] Sigma of allowed variation of global parameter
Definition MillePede2.h:338
int fNLagrangeConstraints
Number of constraint equations requiring Lagrange multiplier.
Definition MillePede2.h:317
double fWghScl[2]
optional rescaling for odd/even residual weights (see its usage in LocalFit)
Definition MillePede2.h:375
int fNStdDev
Number of standard deviations for chi2 cut.
Definition MillePede2.h:315
int InitMille(int nGlo, const int nLoc, const int lNStdDev=-1, const double lResCut=-1., const double lResCutInit=-1., const std::vector< int > &regroup={})
init all
double GetFinalError(int i) const
Definition MillePede2.h:111
std::vector< double > fDeltaPar
[fNGloPar] Variation of global parameters
Definition MillePede2.h:337
static bool fgIsMatGloSparse
Type of the global matrix (sparse ...)
Definition MillePede2.h:380
int fSelFirst
event selection start
Definition MillePede2.h:369
int fNGloFix
Number of globals fixed by user.
Definition MillePede2.h:320
float fResCutInit
Cut in residual for first iterartion.
Definition MillePede2.h:325
std::vector< double > fFillValue
[fNGloPar] auxilary value array for fast matrix fill
Definition MillePede2.h:351
void EndChi2Storage()
write tree and close file where are stored chi2 from LocalFit()
double GetParError(int iPar) const
return error for parameter iPar
o2::fwdalign::MilleRecordWriter * fRecordWriter
data record writer
Definition MillePede2.h:388
std::vector< int > fGlo2CGlo
Flag for used constraints.
Definition MillePede2.h:343
void SetLocalEquation(std::vector< double > &dergb, std::vector< double > &derlc, const double lMeas, const double lSigma)
assing derivs of loc.eq.
double GetPull(int i) const
return pull for parameter iPar
bool fUseRecordWeight
force or ignore the record weight
Definition MillePede2.h:366
void ReadRecordData(const long recID, const bool doPrint=false)
read data record (if any) at entry recID
int SetIterations(const double lChi2CutFac)
Number of iterations is calculated from lChi2CutFac.
int fNGloSize
final size of the global matrix (NGloPar+NConstraints)
Definition MillePede2.h:310
int fNGroupsSet
number of groups set
Definition MillePede2.h:329
TArrayL * fRejRunList
list of runs to reject (if any)
Definition MillePede2.h:371
void SetRecord(o2::fwdalign::MillePedeRecord *aRecord)
Definition MillePede2.h:266
int PrintGlobalParameters() const
print the final results into the logfile
bool IsZero(const double v, const double eps=1e-16) const
Definition MillePede2.h:304
int fMinPntValid
min number of points for global to vary
Definition MillePede2.h:327
int GetCurrentIteration() const
Definition MillePede2.h:72
std::vector< bool > fConstrUsed
Definition MillePede2.h:341
int fNGloConstraints
Number of constraint equations.
Definition MillePede2.h:316
float fChi2CutFactor
Cut factor for chi2 cut to accept local fit.
Definition MillePede2.h:323
double fRunWgh
run weight
Definition MillePede2.h:374
int fSelLast
event selection end
Definition MillePede2.h:370
TArrayF * fAccRunListWgh
optional weights for data of accepted runs (if any)
Definition MillePede2.h:373
int GlobalFit(std::vector< double > &par, std::vector< double > &error, std::vector< double > &pull)
performs a requested number of global iterations
void SetSigmaPars(const double *par)
initialize sigmas, account for eventual grouping
void SetSigmaPar(int i, double par)
initialize sigma, account for eventual grouping
o2::fwdalign::MillePedeRecord * fRecord
Buffer of measurements records.
Definition MillePede2.h:361
void SetAccRunList(const int *runs, const int nruns, const float *wghList=nullptr)
set the list of runs to be selected
static bool fgInvChol
Invert global matrix in Cholesky solver.
Definition MillePede2.h:378
void SetInitPars(const double *par)
initialize parameters, account for eventual grouping
double GetFinalParam(int i) const
Definition MillePede2.h:106
o2::fwdalign::MatrixSq * fMatCGlo
Matrix C global.
Definition MillePede2.h:348
static double fgMinResTol
Tolerance for MinRes solution.
Definition MillePede2.h:382
o2::fwdalign::SymMatrix * fMatCLoc
Matrix C local.
Definition MillePede2.h:347
std::vector< double > fInitPar
Vector B global (parameters)
Definition MillePede2.h:336
long fCurrRecConstrID
ID of the current constraint record.
Definition MillePede2.h:364
int fMaxIter
Maximum number of iterations.
Definition MillePede2.h:314
float Chi2DoFLim(int nSig, int nDoF) const
return the limit in chi^2/nd for n sigmas stdev authorized
long fNLocFits
Number of local fits.
Definition MillePede2.h:318
static bool fgWeightSigma
weight parameter constraint by statistics
Definition MillePede2.h:379
bool IsRecordAcceptable()
validate record according run lists set by the user
float fChi2CutRef
Reference cut for chi2 cut to accept local fit.
Definition MillePede2.h:324
void SetInitPar(int i, double par)
initialize param, account for eventual grouping
void AddIndexValue(Int_t ind, Double_t val)
add new pair of index/value
void MarkGroup(Int_t id)
mark the presence of the detector group
Bool_t IsGroupPresent(Int_t id) const
check if group is defined
Bool_t IsResidual(Int_t i) const
Bool_t IsWeight(Int_t i) const
bool isReadEntryOk() const
check if the last operation readNextEntry() was ok
Long64_t getNEntries() const
return the number of entries
void readEntry(const Long_t id, const bool doPrint=false)
read the entry # id in the tree
o2::fwdalign::MillePedeRecord * getRecord()
return the record
bool isInitOk() const
check if init went well
void fillRecordTree(const bool doPrint=false)
fill tree
o2::fwdalign::MillePedeRecord * getRecord()
return the record
for solving large system of linear equations
Definition MinResSolve.h:37
Bool_t SolveMinRes(Double_t *VecSol, Int_t precon=0, int itnlim=2000, double rtol=1e-12)
MINRES method (for symmetric matrices)
Bool_t SolveFGMRES(Double_t *VecSol, Int_t precon=0, int itnlim=2000, double rtol=1e-12, int nkrylov=60)
FGMRES method (for general symmetric matrices)
Class for rectangular matrix used for millepede2 operation.
Definition RectMatrix.h:31
Fast symmetric matrix with dynamically expandable size.
Definition SymMatrix.h:38
void Print(const Option_t *option="") const override
print itself
int SolveSpmInv(double *vecB, Bool_t stabilize=kTRUE)
Obtain solution of a system of linear equations with symmetric matrix and the inverse (using 'singula...
Bool_t SolveChol(Double_t *brhs, Bool_t invert=kFALSE)
Solves the set of n linear equations A x = b.
void Reset() override
void SetSizeUsed(Int_t sz)
Definition SymMatrix.h:89
GLdouble n
Definition glcorearb.h:1982
GLenum src
Definition glcorearb.h:1767
GLint first
Definition glcorearb.h:399
GLuint GLuint GLfloat weight
Definition glcorearb.h:5477
GLuint GLfloat * val
Definition glcorearb.h:1582
GLuint id
Definition glcorearb.h:650
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)
TStopwatch sw