CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TMultiDimFet.cc
Go to the documentation of this file.
1 /****************************************************************************
2 *
3 * This is a part of TOTEM ofFileline software.
4 *
5 * Based on TMultiDimFet.cc (from ROOT) by Christian Holm Christense.
6 *
7 * Authors:
8 * Hubert Niewiadomski
9 * Jan Kašpar (jan.kaspar@gmail.com)
10 *
11 ****************************************************************************/
12 
13 #include "Riostream.h"
16 #include "TMath.h"
17 #include "TH1.h"
18 #include "TH2.h"
19 #include "TROOT.h"
20 #include "TDecompChol.h"
21 #include "TDatime.h"
22 #include <iostream>
23 #include <map>
24 
25 #define RADDEG (180. / TMath::Pi())
26 #define DEGRAD (TMath::Pi() / 180.)
27 #define HIST_XORIG 0
28 #define HIST_DORIG 1
29 #define HIST_XNORM 2
30 #define HIST_DSHIF 3
31 #define HIST_RX 4
32 #define HIST_RD 5
33 #define HIST_RTRAI 6
34 #define HIST_RTEST 7
35 #define PARAM_MAXSTUDY 1
36 #define PARAM_SEVERAL 2
37 #define PARAM_RELERR 3
38 #define PARAM_MAXTERMS 4
39 
40 //____________________________________________________________________
41 //static void mdfHelper(int&, double*, double&, double*, int);
42 
43 //____________________________________________________________________
45 
46 //____________________________________________________________________
47 // Static instance. Used with mdfHelper and TMinuit
48 //TMultiDimFet* TMultiDimFet::fgInstance = nullptr;
49 
50 //____________________________________________________________________
52  // Empty CTOR. Do not use
53  fMeanQuantity = 0;
54  fMaxQuantity = 0;
55  fMinQuantity = 0;
56  fSumSqQuantity = 0;
58  fPowerLimit = 1;
59 
60  fMaxAngle = 0;
61  fMinAngle = 1;
62 
63  fNVariables = 0;
64  fMaxVariables = 0;
65  fMinVariables = 0;
66  fSampleSize = 0;
67 
68  fMaxAngle = 0;
69  fMinAngle = 0;
70 
72  fShowCorrelation = kFALSE;
73 
74  fIsUserFunction = kFALSE;
75 
76  fHistograms = nullptr;
77  fHistogramMask = 0;
78 
79  //fFitter = nullptr;
80  //fgInstance = nullptr;
81 }
82 
84  if (this == &in) {
85  return in;
86  }
87 
88  fMeanQuantity = in.fMeanQuantity; // Mean of dependent quantity
89 
90  fMaxQuantity = 0.0;
91  fMinQuantity = 0.0;
92  fSumSqQuantity = 0.0;
93  fSumSqAvgQuantity = 0.0;
94 
95  fNVariables = in.fNVariables; // Number of independent variables
96 
97  fMaxVariables.ResizeTo(in.fMaxVariables.GetLwb(), in.fMaxVariables.GetUpb());
98  fMaxVariables = in.fMaxVariables; // max value of independent variables
99 
100  fMinVariables.ResizeTo(in.fMinVariables.GetLwb(), in.fMinVariables.GetUpb());
101  fMinVariables = in.fMinVariables; // min value of independent variables
102 
103  fSampleSize = 0;
104  fTestSampleSize = 0;
105  fMinAngle = 1;
106  fMaxAngle = 0.0;
107 
108  fMaxTerms = in.fMaxTerms; // Max terms expected in final expr.
109 
110  fMinRelativeError = 0.0;
111 
112  fMaxPowers.clear();
113  fPowerLimit = 1;
114 
115  fMaxFunctions = in.fMaxFunctions; // max number of functions
116 
117  fFunctionCodes.clear();
118  fMaxStudy = 0;
119 
120  fMaxPowersFinal.clear();
121 
122  fMaxFunctionsTimesNVariables = in.fMaxFunctionsTimesNVariables; // fMaxFunctionsTimesNVariables
123  fPowers = in.fPowers;
124 
125  fPowerIndex = in.fPowerIndex; // [fMaxTerms] Index of accepted powers
126 
127  fMaxResidual = 0.0;
128  fMinResidual = 0.0;
129  fMaxResidualRow = 0;
130  fMinResidualRow = 0;
131  fSumSqResidual = 0.0;
132 
133  fNCoefficients = in.fNCoefficients; // Dimension of model coefficients
134 
135  fCoefficients.ResizeTo(in.fCoefficients.GetLwb(), in.fCoefficients.GetUpb());
136  fCoefficients = in.fCoefficients; // Vector of the final coefficients
137 
138  fRMS = 0.0;
139  fChi2 = 0.0;
141  fError = 0.0;
142  fTestError = 0.0;
143  fPrecision = 0.0;
144  fTestPrecision = 0.0;
145  fCorrelationCoeff = 0.0;
146  fTestCorrelationCoeff = 0.0;
147  fHistograms = nullptr;
148  fHistogramMask = 0;
149  //fFitter = nullptr; //! Fit object (MINUIT)
150 
151  fPolyType = in.fPolyType; // Type of polynomials to use
152  fShowCorrelation = in.fShowCorrelation; // print correlation matrix
153  fIsUserFunction = in.fIsUserFunction; // Flag for user defined function
154  fIsVerbose = in.fIsVerbose; //
155  return in;
156 }
157 
158 //____________________________________________________________________
160  : TNamed("multidimfit", "Multi-dimensional fit object"),
161  fQuantity(dimension),
162  fSqError(dimension),
163  fVariables(dimension * 100),
164  fMeanVariables(dimension),
165  fMaxVariables(dimension),
166  fMinVariables(dimension) {
167  // Constructor
168  // Second argument is the type of polynomials to use in
169  // parameterisation, one of:
170  // TMultiDimFet::kMonomials
171  // TMultiDimFet::kChebyshev
172  // TMultiDimFet::kLegendre
173  //
174  // Options:
175  // K Compute (k)correlation matrix
176  // V Be verbose
177  //
178  // Default is no options.
179  //
180 
181  //fgInstance = this;
182 
183  fMeanQuantity = 0;
184  fMaxQuantity = 0;
185  fMinQuantity = 0;
186  fSumSqQuantity = 0;
187  fSumSqAvgQuantity = 0;
188  fPowerLimit = 1;
189 
190  fMaxAngle = 0;
191  fMinAngle = 1;
192 
194  fMaxVariables = 0;
196  fMinVariables = 0;
197  fSampleSize = 0;
198  fTestSampleSize = 0;
199  fMinRelativeError = 0.01;
200  fError = 0;
201  fTestError = 0;
202  fPrecision = 0;
203  fTestPrecision = 0;
205 
206  fPolyType = type;
207  fShowCorrelation = kFALSE;
208  fIsVerbose = kFALSE;
209 
210  TString opt = option;
211  opt.ToLower();
212 
213  if (opt.Contains("k"))
214  fShowCorrelation = kTRUE;
215  if (opt.Contains("v"))
216  fIsVerbose = kTRUE;
217 
218  fIsUserFunction = kFALSE;
219 
220  fHistograms = nullptr;
221  fHistogramMask = 0;
222 
223  fMaxPowers.resize(dimension);
224  fMaxPowersFinal.resize(dimension);
225  //fFitter = nullptr;
226 }
227 
228 //____________________________________________________________________
230  if (fHistograms)
231  fHistograms->Clear("nodelete");
232  delete fHistograms;
233 }
234 
235 //____________________________________________________________________
236 void TMultiDimFet::AddRow(const Double_t *x, Double_t D, Double_t E) {
237  // Add a row consisting of fNVariables independent variables, the
238  // known, dependent quantity, and optionally, the square error in
239  // the dependent quantity, to the training sample to be used for the
240  // parameterization.
241  // The mean of the variables and quantity is calculated on the fly,
242  // as outlined in TPrincipal::AddRow.
243  // This sample should be representive of the problem at hand.
244  // Please note, that if no error is given Poisson statistics is
245  // assumed and the square error is set to the value of dependent
246  // quantity. See also the
247  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
248  if (!x)
249  return;
250 
251  if (++fSampleSize == 1) {
252  fMeanQuantity = D;
253  fMaxQuantity = D;
254  fMinQuantity = D;
255  } else {
256  fMeanQuantity *= 1 - 1. / Double_t(fSampleSize);
257  fMeanQuantity += D / Double_t(fSampleSize);
258  fSumSqQuantity += D * D;
259 
260  if (D >= fMaxQuantity)
261  fMaxQuantity = D;
262  if (D <= fMinQuantity)
263  fMinQuantity = D;
264  }
265 
266  // If the vector isn't big enough to hold the new data, then
267  // expand the vector by half it's size.
268  Int_t size = fQuantity.GetNrows();
269  if (fSampleSize > size) {
270  fQuantity.ResizeTo(size + size / 2);
271  fSqError.ResizeTo(size + size / 2);
272  }
273 
274  // Store the value
275  fQuantity(fSampleSize - 1) = D;
276  fSqError(fSampleSize - 1) = (E == 0 ? D : E);
277 
278  // Store data point in internal vector
279  // If the vector isn't big enough to hold the new data, then
280  // expand the vector by half it's size
281  size = fVariables.GetNrows();
282  if (fSampleSize * fNVariables > size)
283  fVariables.ResizeTo(size + size / 2);
284 
285  // Increment the data point counter
286  Int_t i, j;
287  for (i = 0; i < fNVariables; i++) {
288  if (fSampleSize == 1) {
289  fMeanVariables(i) = x[i];
290  fMaxVariables(i) = x[i];
291  fMinVariables(i) = x[i];
292  } else {
293  fMeanVariables(i) *= 1 - 1. / Double_t(fSampleSize);
294  fMeanVariables(i) += x[i] / Double_t(fSampleSize);
295 
296  // Update the maximum value for this component
297  if (x[i] >= fMaxVariables(i))
298  fMaxVariables(i) = x[i];
299 
300  // Update the minimum value for this component
301  if (x[i] <= fMinVariables(i))
302  fMinVariables(i) = x[i];
303  }
304 
305  // Store the data.
306  j = (fSampleSize - 1) * fNVariables + i;
307  fVariables(j) = x[i];
308  }
309 }
310 
311 //____________________________________________________________________
312 void TMultiDimFet::AddTestRow(const Double_t *x, Double_t D, Double_t E) {
313  // Add a row consisting of fNVariables independent variables, the
314  // known, dependent quantity, and optionally, the square error in
315  // the dependent quantity, to the test sample to be used for the
316  // test of the parameterization.
317  // This sample needn't be representive of the problem at hand.
318  // Please note, that if no error is given Poisson statistics is
319  // assumed and the square error is set to the value of dependent
320  // quantity. See also the
321  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
322  if (fTestSampleSize++ == 0) {
323  fTestQuantity.ResizeTo(fNVariables);
324  fTestSqError.ResizeTo(fNVariables);
325  fTestVariables.ResizeTo(fNVariables * 100);
326  }
327 
328  // If the vector isn't big enough to hold the new data, then
329  // expand the vector by half it's size.
330  Int_t size = fTestQuantity.GetNrows();
331  if (fTestSampleSize > size) {
332  fTestQuantity.ResizeTo(size + size / 2);
333  fTestSqError.ResizeTo(size + size / 2);
334  }
335 
336  // Store the value
338  fTestSqError(fTestSampleSize - 1) = (E == 0 ? D : E);
339 
340  // Store data point in internal vector
341  // If the vector isn't big enough to hold the new data, then
342  // expand the vector by half it's size
343  size = fTestVariables.GetNrows();
344  if (fTestSampleSize * fNVariables > size)
345  fTestVariables.ResizeTo(size + size / 2);
346 
347  // Increment the data point counter
348  Int_t i, j;
349  for (i = 0; i < fNVariables; i++) {
350  j = fNVariables * (fTestSampleSize - 1) + i;
351  fTestVariables(j) = x[i];
352 
353  if (x[i] > fMaxVariables(i))
354  Warning("AddTestRow", "variable %d (row: %d) too large: %f > %f", i, fTestSampleSize, x[i], fMaxVariables(i));
355  if (x[i] < fMinVariables(i))
356  Warning("AddTestRow", "variable %d (row: %d) too small: %f < %f", i, fTestSampleSize, x[i], fMinVariables(i));
357  }
358 }
359 
360 //____________________________________________________________________
361 void TMultiDimFet::Clear(Option_t *option) {
362  // Clear internal structures and variables
363  Int_t i, j, n = fNVariables, m = fMaxFunctions;
364 
365  // Training sample, dependent quantity
366  fQuantity.Zero();
367  fSqError.Zero();
368  fMeanQuantity = 0;
369  fMaxQuantity = 0;
370  fMinQuantity = 0;
371  fSumSqQuantity = 0;
372  fSumSqAvgQuantity = 0;
373 
374  // Training sample, independent variables
375  fVariables.Zero();
376  fNVariables = 0;
377  fSampleSize = 0;
378  fMeanVariables.Zero();
379  fMaxVariables.Zero();
380  fMinVariables.Zero();
381 
382  // Test sample
383  fTestQuantity.Zero();
384  fTestSqError.Zero();
385  fTestVariables.Zero();
386  fTestSampleSize = 0;
387 
388  // Functions
389  fFunctions.Zero();
390  fMaxFunctions = 0;
391  fMaxStudy = 0;
393  fOrthFunctions.Zero();
394  fOrthFunctionNorms.Zero();
395 
396  // Control parameters
397  fMinRelativeError = 0;
398  fMinAngle = 0;
399  fMaxAngle = 0;
400  fMaxTerms = 0;
401 
402  // Powers
403  for (i = 0; i < n; i++) {
404  fMaxPowers[i] = 0;
405  fMaxPowersFinal[i] = 0;
406  for (j = 0; j < m; j++)
407  fPowers[i * n + j] = 0;
408  }
409  fPowerLimit = 0;
410 
411  // Residuals
412  fMaxResidual = 0;
413  fMinResidual = 0;
414  fMaxResidualRow = 0;
415  fMinResidualRow = 0;
416  fSumSqResidual = 0;
417 
418  // Fit
419  fNCoefficients = 0;
420  fOrthCoefficients = 0;
422  fRMS = 0;
423  fCorrelationMatrix.Zero();
424  fError = 0;
425  fTestError = 0;
426  fPrecision = 0;
427  fTestPrecision = 0;
428 
429  // Coefficients
430  fCoefficients.Zero();
431  fCoefficientsRMS.Zero();
432  fResiduals.Zero();
433  fHistograms->Clear(option);
434 
435  // Options
437  fShowCorrelation = kFALSE;
438  fIsUserFunction = kFALSE;
439 }
440 
441 //____________________________________________________________________
442 Double_t TMultiDimFet::Eval(const Double_t *x, const Double_t *coeff) const {
443  // Evaluate parameterization at point x. Optional argument coeff is
444  // a vector of coefficients for the parameterisation, fNCoefficients
445  // elements long.
446  // int fMaxFunctionsTimesNVariables = fMaxFunctions * fNVariables;
447  Double_t returnValue = fMeanQuantity;
448  Double_t term = 0;
449  Int_t i, j;
450 
451  for (i = 0; i < fNCoefficients; i++) {
452  // Evaluate the ith term in the expansion
453  term = (coeff ? coeff[i] : fCoefficients(i));
454  for (j = 0; j < fNVariables; j++) {
455  // Evaluate the factor (polynomial) in the j-th variable.
456  Int_t p = fPowers[fPowerIndex[i] * fNVariables + j];
457  Double_t y = 1 + 2. / (fMaxVariables(j) - fMinVariables(j)) * (x[j] - fMaxVariables(j));
458  term *= EvalFactor(p, y);
459  }
460  // Add this term to the final result
461  returnValue += term;
462  }
463  return returnValue;
464 }
465 
467  if (error == 0.0)
468  return;
469  else {
471  }
472 }
473 
475  typedef std::multimap<double, int> cmt;
476  cmt m;
477 
478  for (int i = 0; i < fNCoefficients; i++) {
479  m.insert(std::pair<double, int>(TMath::Abs(fCoefficients(i)), i));
480  }
481 
482  double del_error_abs = 0;
483  int deleted_terms_count = 0;
484 
485  for (cmt::iterator it = m.begin(); it != m.end() && del_error_abs < error; ++it) {
486  if (TMath::Abs(it->first) + del_error_abs < error) {
487  fCoefficients(it->second) = 0.0;
488  del_error_abs = TMath::Abs(it->first) + del_error_abs;
489  deleted_terms_count++;
490  } else
491  break;
492  }
493 
494  int fNCoefficients_new = fNCoefficients - deleted_terms_count;
495  TVectorD fCoefficients_new(fNCoefficients_new);
496  std::vector<Int_t> fPowerIndex_new;
497 
498  int ind = 0;
499  for (int i = 0; i < fNCoefficients; i++) {
500  if (fCoefficients(i) != 0.0) {
501  fCoefficients_new(ind) = fCoefficients(i);
502  fPowerIndex_new.push_back(fPowerIndex[i]);
503  ind++;
504  }
505  }
506  fNCoefficients = fNCoefficients_new;
507  fCoefficients.ResizeTo(fNCoefficients);
508  fCoefficients = fCoefficients_new;
509  fPowerIndex = fPowerIndex_new;
510  edm::LogInfo("TMultiDimFet") << deleted_terms_count << " terms removed"
511  << "\n";
512 }
513 
514 //____________________________________________________________________
515 Double_t TMultiDimFet::EvalControl(const Int_t *iv) {
516  // PRIVATE METHOD:
517  // Calculate the control parameter from the passed powers
518  Double_t s = 0;
519  Double_t epsilon = 1e-6; // a small number
520  for (Int_t i = 0; i < fNVariables; i++) {
521  if (fMaxPowers[i] != 1)
522  s += (epsilon + iv[i] - 1) / (epsilon + fMaxPowers[i] - 1);
523  }
524  return s;
525 }
526 
527 //____________________________________________________________________
528 Double_t TMultiDimFet::EvalFactor(Int_t p, Double_t x) const {
529  // PRIVATE METHOD:
530  // Evaluate function with power p at variable value x
531  Int_t i = 0;
532  Double_t p1 = 1;
533  Double_t p2 = 0;
534  Double_t p3 = 0;
535  Double_t r = 0;
536 
537  switch (p) {
538  case 1:
539  r = 1;
540  break;
541  case 2:
542  r = x;
543  break;
544  default:
545  p2 = x;
546  for (i = 3; i <= p; i++) {
547  p3 = p2 * x;
548  if (fPolyType == kLegendre)
549  p3 = ((2 * i - 3) * p2 * x - (i - 2) * p1) / (i - 1);
550  else if (fPolyType == kChebyshev)
551  p3 = 2 * x * p2 - p1;
552  p1 = p2;
553  p2 = p3;
554  }
555  r = p3;
556  }
557 
558  return r;
559 }
560 
561 //____________________________________________________________________
562 void TMultiDimFet::FindParameterization(double precision) {
563  // Find the parameterization
564  //
565  // Options:
566  // None so far
567  //
568  // For detailed description of what this entails, please refer to the
569  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
570  MakeNormalized();
571  MakeCandidates();
574  ReducePolynomial(precision);
575 }
576 
577 //____________________________________________________________________
578 /*
579 void TMultiDimFet::Fit(Option_t *option)
580 {
581  // Try to fit the found parameterisation to the test sample.
582  //
583  // Options
584  // M use Minuit to improve coefficients
585  //
586  // Also, refer to
587  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
588 
589  //fgInstance = this;
590 
591  Int_t i, j;
592  Double_t* x = new Double_t[fNVariables];
593  Double_t sumSqD = 0;
594  Double_t sumD = 0;
595  Double_t sumSqR = 0;
596  Double_t sumR = 0;
597 
598  // Calculate the residuals over the test sample
599  for (i = 0; i < fTestSampleSize; i++) {
600  for (j = 0; j < fNVariables; j++)
601  x[j] = fTestVariables(i * fNVariables + j);
602  Double_t res = fTestQuantity(i) - Eval(x);
603  sumD += fTestQuantity(i);
604  sumSqD += fTestQuantity(i) * fTestQuantity(i);
605  sumR += res;
606  sumSqR += res * res;
607  if (TESTBIT(fHistogramMask,HIST_RTEST))
608  ((TH1D*)fHistograms->FindObject("res_test"))->Fill(res);
609  }
610  Double_t dAvg = sumSqD - (sumD * sumD) / fTestSampleSize;
611  Double_t rAvg = sumSqR - (sumR * sumR) / fTestSampleSize;
612  fTestCorrelationCoeff = (dAvg - rAvg) / dAvg;
613  fTestError = sumSqR;
614  fTestPrecision = sumSqR / sumSqD;
615 
616  TString opt(option);
617  opt.ToLower();
618 
619  if (!opt.Contains("m"))
620  MakeChi2();
621 
622  if (fNCoefficients * 50 > fTestSampleSize)
623  Warning("Fit", "test sample is very small");
624 
625  if (!opt.Contains("m"))
626  return;
627 
628  fFitter = TVirtualFitter::Fitter(nullptr,fNCoefficients);
629  fFitter->SetFCN(mdfHelper);
630 
631  const Int_t maxArgs = 16;
632  Int_t args = 1;
633  Double_t* arglist = new Double_t[maxArgs];
634  arglist[0] = -1;
635  fFitter->ExecuteCommand("SET PRINT",arglist,args);
636 
637  for (i = 0; i < fNCoefficients; i++) {
638  Double_t startVal = fCoefficients(i);
639  Double_t startErr = fCoefficientsRMS(i);
640  fFitter->SetParameter(i, Form("coeff%02d",i),
641  startVal, startErr, 0, 0);
642  }
643 
644  args = 1;
645  fFitter->ExecuteCommand("MIGRAD",arglist,args);
646 
647  for (i = 0; i < fNCoefficients; i++) {
648  Double_t val = 0, err = 0, low = 0, high = 0;
649  fFitter->GetParameter(i, Form("coeff%02d",i),
650  val, err, low, high);
651  fCoefficients(i) = val;
652  fCoefficientsRMS(i) = err;
653  }
654 }
655 */
656 
657 //____________________________________________________________________
659  // PRIVATE METHOD:
660  // Create list of candidate functions for the parameterisation. See
661  // also
662  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
663  Int_t i = 0;
664  Int_t j = 0;
665  Int_t k = 0;
666 
667  // The temporary array to store the powers in. We don't need to
668  // initialize this array however.
669  Int_t *powers = new Int_t[fNVariables * fMaxFunctions];
670 
671  // store of `control variables'
672  Double_t *control = new Double_t[fMaxFunctions];
673 
674  // We've better initialize the variables
675  Int_t *iv = new Int_t[fNVariables];
676  for (i = 0; i < fNVariables; i++)
677  iv[i] = 1;
678 
679  if (!fIsUserFunction) {
680  // Number of funcs selected
681  Int_t numberFunctions = 0;
682 
683  // Absolute max number of functions
684  Int_t maxNumberFunctions = 1;
685  for (i = 0; i < fNVariables; i++)
686  maxNumberFunctions *= fMaxPowers[i];
687 
688  while (kTRUE) {
689  // Get the control value for this function
690  Double_t s = EvalControl(iv);
691 
692  if (s <= fPowerLimit) {
693  // Call over-loadable method Select, as to allow the user to
694  // interfere with the selection of functions.
695  if (Select(iv)) {
696  numberFunctions++;
697 
698  // If we've reached the user defined limit of how many
699  // functions we can consider, break out of the loop
700  if (numberFunctions > fMaxFunctions)
701  break;
702 
703  // Store the control value, so we can sort array of powers
704  // later on
705  control[numberFunctions - 1] = Int_t(1.0e+6 * s);
706 
707  // Store the powers in powers array.
708  for (i = 0; i < fNVariables; i++) {
709  j = (numberFunctions - 1) * fNVariables + i;
710  powers[j] = iv[i];
711  }
712  } // if (Select())
713  } // if (s <= fPowerLimit)
714 
715  for (i = 0; i < fNVariables; i++)
716  if (iv[i] < fMaxPowers[i])
717  break;
718 
719  // If all variables have reached their maximum power, then we
720  // break out of the loop
721  if (i == fNVariables) {
722  fMaxFunctions = numberFunctions;
724  break;
725  }
726 
727  // Next power in variable i
728  iv[i]++;
729 
730  for (j = 0; j < i; j++)
731  iv[j] = 1;
732  } // while (kTRUE)
733  } else {
734  // In case the user gave an explicit function
735  for (i = 0; i < fMaxFunctions; i++) {
736  // Copy the powers to working arrays
737  for (j = 0; j < fNVariables; j++) {
738  powers[i * fNVariables + j] = fPowers[i * fNVariables + j];
739  iv[j] = fPowers[i * fNVariables + j];
740  }
741 
742  control[i] = Int_t(1.0e+6 * EvalControl(iv));
743  }
744  }
745 
746  // Now we need to sort the powers according to least `control
747  // variable'
748  Int_t *order = new Int_t[fMaxFunctions];
749  for (i = 0; i < fMaxFunctions; i++)
750  order[i] = i;
751  fPowers.resize(fMaxFunctions * fNVariables);
752 
753  for (i = 0; i < fMaxFunctions; i++) {
754  Double_t x = control[i];
755  Int_t l = order[i];
756  k = i;
757 
758  for (j = i; j < fMaxFunctions; j++) {
759  if (control[j] <= x) {
760  x = control[j];
761  l = order[j];
762  k = j;
763  }
764  }
765 
766  if (k != i) {
767  control[k] = control[i];
768  control[i] = x;
769  order[k] = order[i];
770  order[i] = l;
771  }
772  }
773 
774  for (i = 0; i < fMaxFunctions; i++)
775  for (j = 0; j < fNVariables; j++)
776  fPowers[i * fNVariables + j] = powers[order[i] * fNVariables + j];
777 
778  delete[] control;
779  delete[] powers;
780  delete[] order;
781  delete[] iv;
782 }
783 
784 Double_t TMultiDimFet::MakeChi2(const Double_t *coeff) {
785  // Calculate Chi square over either the test sample. The optional
786  // argument coeff is a vector of coefficients to use in the
787  // evaluation of the parameterisation. If coeff == 0, then the found
788  // coefficients is used.
789  // Used my MINUIT for fit (see TMultDimFit::Fit)
790  fChi2 = 0;
791  Int_t i, j;
792  Double_t *x = new Double_t[fNVariables];
793  for (i = 0; i < fTestSampleSize; i++) {
794  // Get the stored point
795  for (j = 0; j < fNVariables; j++)
796  x[j] = fTestVariables(i * fNVariables + j);
797 
798  // Evaluate function. Scale to shifted values
799  Double_t f = Eval(x, coeff);
800 
801  // Calculate contribution to Chic square
802  fChi2 += 1. / TMath::Max(fTestSqError(i), 1e-20) * (fTestQuantity(i) - f) * (fTestQuantity(i) - f);
803  }
804 
805  // Clean up
806  delete[] x;
807 
808  return fChi2;
809 }
810 
811 //____________________________________________________________________
812 void TMultiDimFet::MakeCode(const char *filename, Option_t *option) {
813  // Generate the file <filename> with .C appended if argument doesn't
814  // end in .cxx or .C. The contains the implementation of the
815  // function:
816  //
817  // Double_t <funcname>(Double_t *x)
818  //
819  // which does the same as TMultiDimFet::Eval. Please refer to this
820  // method.
821  //
822  // Further, the static variables:
823  //
824  // Int_t gNVariables
825  // Int_t gNCoefficients
826  // Double_t gDMean
827  // Double_t gXMean[]
828  // Double_t gXMin[]
829  // Double_t gXMax[]
830  // Double_t gCoefficient[]
831  // Int_t gPower[]
832  //
833  // are initialized. The only ROOT header file needed is Rtypes.h
834  //
835  // See TMultiDimFet::MakeRealCode for a list of options
836 
837  TString outName(filename);
838  if (!outName.EndsWith(".C") && !outName.EndsWith(".cxx"))
839  outName += ".C";
840 
841  MakeRealCode(outName.Data(), "", option);
842 }
843 
845  // PRIVATE METHOD:
846  // Compute the errors on the coefficients. For this to be done, the
847  // curvature matrix of the non-orthogonal functions, is computed.
848  Int_t i = 0;
849  Int_t j = 0;
850  Int_t k = 0;
851  TVectorD iF(fSampleSize);
852  TVectorD jF(fSampleSize);
854 
855  TMatrixDSym curvatureMatrix(fNCoefficients);
856 
857  // Build the curvature matrix
858  for (i = 0; i < fNCoefficients; i++) {
859  iF = TMatrixDRow(fFunctions, i);
860  for (j = 0; j <= i; j++) {
861  jF = TMatrixDRow(fFunctions, j);
862  for (k = 0; k < fSampleSize; k++)
863  curvatureMatrix(i, j) += 1 / TMath::Max(fSqError(k), 1e-20) * iF(k) * jF(k);
864  curvatureMatrix(j, i) = curvatureMatrix(i, j);
865  }
866  }
867 
868  // Calculate Chi Square
869  fChi2 = 0;
870  for (i = 0; i < fSampleSize; i++) {
871  Double_t f = 0;
872  for (j = 0; j < fNCoefficients; j++)
873  f += fCoefficients(j) * fFunctions(j, i);
874  fChi2 += 1. / TMath::Max(fSqError(i), 1e-20) * (fQuantity(i) - f) * (fQuantity(i) - f);
875  }
876 
877  // Invert the curvature matrix
878  const TVectorD diag = TMatrixDDiag_const(curvatureMatrix);
879  curvatureMatrix.NormByDiag(diag);
880 
881  TDecompChol chol(curvatureMatrix);
882  if (!chol.Decompose())
883  Error("MakeCoefficientErrors", "curvature matrix is singular");
884  chol.Invert(curvatureMatrix);
885 
886  curvatureMatrix.NormByDiag(diag);
887 
888  for (i = 0; i < fNCoefficients; i++)
889  fCoefficientsRMS(i) = TMath::Sqrt(curvatureMatrix(i, i));
890 }
891 
892 //____________________________________________________________________
894  // PRIVATE METHOD:
895  // Invert the model matrix B, and compute final coefficients. For a
896  // more thorough discussion of what this means, please refer to the
897  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
898  //
899  // First we invert the lower triangle matrix fOrthCurvatureMatrix
900  // and store the inverted matrix in the upper triangle.
901 
902  Int_t i = 0, j = 0;
903  Int_t col = 0, row = 0;
904 
905  // Invert the B matrix
906  for (col = 1; col < fNCoefficients; col++) {
907  for (row = col - 1; row > -1; row--) {
908  fOrthCurvatureMatrix(row, col) = 0;
909  for (i = row; i <= col; i++)
910  fOrthCurvatureMatrix(row, col) -= fOrthCurvatureMatrix(i, row) * fOrthCurvatureMatrix(i, col);
911  }
912  }
913 
914  // Compute the final coefficients
915  fCoefficients.ResizeTo(fNCoefficients);
916 
917  for (i = 0; i < fNCoefficients; i++) {
918  Double_t sum = 0;
919  for (j = i; j < fNCoefficients; j++)
921  fCoefficients(i) = sum;
922  }
923 
924  // Compute the final residuals
925  fResiduals.ResizeTo(fSampleSize);
926  for (i = 0; i < fSampleSize; i++)
927  fResiduals(i) = fQuantity(i);
928 
929  for (i = 0; i < fNCoefficients; i++)
930  for (j = 0; j < fSampleSize; j++)
931  fResiduals(j) -= fCoefficients(i) * fFunctions(i, j);
932 
933  // Compute the max and minimum, and squared sum of the evaluated
934  // residuals
935  fMinResidual = 10e10;
936  fMaxResidual = -10e10;
937  Double_t sqRes = 0;
938  for (i = 0; i < fSampleSize; i++) {
939  sqRes += fResiduals(i) * fResiduals(i);
940  if (fResiduals(i) <= fMinResidual) {
942  fMinResidualRow = i;
943  }
944  if (fResiduals(i) >= fMaxResidual) {
946  fMaxResidualRow = i;
947  }
948  }
949 
951  fPrecision = TMath::Sqrt(sqRes / fSumSqQuantity);
952 
953  // If we use histograms, fill some more
954  if (TESTBIT(fHistogramMask, HIST_RD) || TESTBIT(fHistogramMask, HIST_RTRAI) || TESTBIT(fHistogramMask, HIST_RX)) {
955  for (i = 0; i < fSampleSize; i++) {
956  if (TESTBIT(fHistogramMask, HIST_RD))
957  ((TH2D *)fHistograms->FindObject("res_d"))->Fill(fQuantity(i), fResiduals(i));
958  if (TESTBIT(fHistogramMask, HIST_RTRAI))
959  ((TH1D *)fHistograms->FindObject("res_train"))->Fill(fResiduals(i));
960 
961  if (TESTBIT(fHistogramMask, HIST_RX))
962  for (j = 0; j < fNVariables; j++)
963  ((TH2D *)fHistograms->FindObject(Form("res_x_%d", j)))->Fill(fVariables(i * fNVariables + j), fResiduals(i));
964  }
965  } // If histograms
966 }
967 
968 //____________________________________________________________________
970  // PRIVATE METHOD:
971  // Compute the correlation matrix
972  if (!fShowCorrelation)
973  return;
974 
976 
977  Double_t d2 = 0;
978  Double_t ddotXi = 0; // G.Q. needs to be reinitialized in the loop over i fNVariables
979  Double_t xiNorm = 0; // G.Q. needs to be reinitialized in the loop over i fNVariables
980  Double_t xidotXj = 0; // G.Q. needs to be reinitialized in the loop over j fNVariables
981  Double_t xjNorm = 0; // G.Q. needs to be reinitialized in the loop over j fNVariables
982 
983  Int_t i, j, k, l, m; // G.Q. added m variable
984  for (i = 0; i < fSampleSize; i++)
985  d2 += fQuantity(i) * fQuantity(i);
986 
987  for (i = 0; i < fNVariables; i++) {
988  ddotXi = 0.; // G.Q. reinitialisation
989  xiNorm = 0.; // G.Q. reinitialisation
990  for (j = 0; j < fSampleSize; j++) {
991  // Index of sample j of variable i
992  k = j * fNVariables + i;
993  ddotXi += fQuantity(j) * (fVariables(k) - fMeanVariables(i));
994  xiNorm += (fVariables(k) - fMeanVariables(i)) * (fVariables(k) - fMeanVariables(i));
995  }
996  fCorrelationMatrix(i, 0) = ddotXi / TMath::Sqrt(d2 * xiNorm);
997 
998  for (j = 0; j < i; j++) {
999  xidotXj = 0.; // G.Q. reinitialisation
1000  xjNorm = 0.; // G.Q. reinitialisation
1001  for (k = 0; k < fSampleSize; k++) {
1002  // Index of sample j of variable i
1003  // l = j * fNVariables + k; // G.Q.
1004  l = k * fNVariables + j; // G.Q.
1005  m = k * fNVariables + i; // G.Q.
1006  // G.Q. xidotXj += (fVariables(i) - fMeanVariables(i))
1007  // G.Q. * (fVariables(l) - fMeanVariables(j));
1008  xidotXj +=
1009  (fVariables(m) - fMeanVariables(i)) * (fVariables(l) - fMeanVariables(j)); // G.Q. modified index for Xi
1010  xjNorm += (fVariables(l) - fMeanVariables(j)) * (fVariables(l) - fMeanVariables(j));
1011  }
1012  fCorrelationMatrix(i, j + 1) = xidotXj / TMath::Sqrt(xiNorm * xjNorm);
1013  }
1014  }
1015 }
1016 
1017 //____________________________________________________________________
1018 Double_t TMultiDimFet::MakeGramSchmidt(Int_t function) {
1019  // PRIVATE METHOD:
1020  // Make Gram-Schmidt orthogonalisation. The class description gives
1021  // a thorough account of this algorithm, as well as
1022  // references. Please refer to the
1023  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
1024 
1025  // calculate w_i, that is, evaluate the current function at data
1026  // point i
1027  Double_t f2 = 0;
1030  Int_t j = 0;
1031  Int_t k = 0;
1032 
1033  for (j = 0; j < fSampleSize; j++) {
1034  fFunctions(fNCoefficients, j) = 1;
1036  // First, however, we need to calculate f_fNCoefficients
1037  for (k = 0; k < fNVariables; k++) {
1038  Int_t p = fPowers[function * fNVariables + k];
1039  Double_t x = fVariables(j * fNVariables + k);
1040  fFunctions(fNCoefficients, j) *= EvalFactor(p, x);
1041  }
1042 
1043  // Calculate f dot f in f2
1045  // Assign to w_fNCoefficients f_fNCoefficients
1047  }
1048 
1049  // the first column of w is equal to f
1050  for (j = 0; j < fNCoefficients; j++) {
1051  Double_t fdw = 0;
1052  // Calculate (f_fNCoefficients dot w_j) / w_j^2
1053  for (k = 0; k < fSampleSize; k++) {
1054  fdw += fFunctions(fNCoefficients, k) * fOrthFunctions(j, k) / fOrthFunctionNorms(j);
1055  }
1056 
1057  fOrthCurvatureMatrix(fNCoefficients, j) = fdw;
1058  // and subtract it from the current value of w_ij
1059  for (k = 0; k < fSampleSize; k++)
1060  fOrthFunctions(fNCoefficients, k) -= fdw * fOrthFunctions(j, k);
1061  }
1062 
1063  for (j = 0; j < fSampleSize; j++) {
1064  // calculate squared length of w_fNCoefficients
1065  fOrthFunctionNorms(fNCoefficients) += fOrthFunctions(fNCoefficients, j) * fOrthFunctions(fNCoefficients, j);
1066 
1067  // calculate D dot w_fNCoefficients in A
1068  fOrthCoefficients(fNCoefficients) += fQuantity(j) * fOrthFunctions(fNCoefficients, j);
1069  }
1070 
1071  // First test, but only if didn't user specify
1072  if (!fIsUserFunction)
1073  if (TMath::Sqrt(fOrthFunctionNorms(fNCoefficients) / (f2 + 1e-10)) < TMath::Sin(fMinAngle * DEGRAD))
1074  return 0;
1075 
1076  // The result found by this code for the first residual is always
1077  // much less then the one found be MUDIFI. That's because it's
1078  // supposed to be. The cause is the improved precision of Double_t
1079  // over DOUBLE PRECISION!
1080  fOrthCurvatureMatrix(fNCoefficients, fNCoefficients) = 1;
1081  Double_t b = fOrthCoefficients(fNCoefficients);
1082  fOrthCoefficients(fNCoefficients) /= fOrthFunctionNorms(fNCoefficients);
1083 
1084  // Calculate the residual from including this fNCoefficients.
1085  Double_t dResidur = fOrthCoefficients(fNCoefficients) * b;
1086 
1087  return dResidur;
1088 }
1089 
1090 //____________________________________________________________________
1091 void TMultiDimFet::MakeHistograms(Option_t *option) {
1092  // Make histograms of the result of the analysis. This message
1093  // should be sent after having read all data points, but before
1094  // finding the parameterization
1095  //
1096  // Options:
1097  // A All the below
1098  // X Original independent variables
1099  // D Original dependent variables
1100  // N Normalised independent variables
1101  // S Shifted dependent variables
1102  // R1 Residuals versus normalised independent variables
1103  // R2 Residuals versus dependent variable
1104  // R3 Residuals computed on training sample
1105  // R4 Residuals computed on test sample
1106  //
1107  // For a description of these quantities, refer to
1108  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
1109  TString opt(option);
1110  opt.ToLower();
1111 
1112  if (opt.Length() < 1)
1113  return;
1114 
1115  if (!fHistograms)
1116  fHistograms = new TList;
1117 
1118  // Counter variable
1119  Int_t i = 0;
1120 
1121  // Histogram of original variables
1122  if (opt.Contains("x") || opt.Contains("a")) {
1123  SETBIT(fHistogramMask, HIST_XORIG);
1124  for (i = 0; i < fNVariables; i++)
1125  if (!fHistograms->FindObject(Form("x_%d_orig", i)))
1126  fHistograms->Add(
1127  new TH1D(Form("x_%d_orig", i), Form("Original variable # %d", i), 100, fMinVariables(i), fMaxVariables(i)));
1128  }
1129 
1130  // Histogram of original dependent variable
1131  if (opt.Contains("d") || opt.Contains("a")) {
1132  SETBIT(fHistogramMask, HIST_DORIG);
1133  if (!fHistograms->FindObject("d_orig"))
1134  fHistograms->Add(new TH1D("d_orig", "Original Quantity", 100, fMinQuantity, fMaxQuantity));
1135  }
1136 
1137  // Histograms of normalized variables
1138  if (opt.Contains("n") || opt.Contains("a")) {
1139  SETBIT(fHistogramMask, HIST_XNORM);
1140  for (i = 0; i < fNVariables; i++)
1141  if (!fHistograms->FindObject(Form("x_%d_norm", i)))
1142  fHistograms->Add(new TH1D(Form("x_%d_norm", i), Form("Normalized variable # %d", i), 100, -1, 1));
1143  }
1144 
1145  // Histogram of shifted dependent variable
1146  if (opt.Contains("s") || opt.Contains("a")) {
1147  SETBIT(fHistogramMask, HIST_DSHIF);
1148  if (!fHistograms->FindObject("d_shifted"))
1149  fHistograms->Add(
1150  new TH1D("d_shifted", "Shifted Quantity", 100, fMinQuantity - fMeanQuantity, fMaxQuantity - fMeanQuantity));
1151  }
1152 
1153  // Residual from training sample versus independent variables
1154  if (opt.Contains("r1") || opt.Contains("a")) {
1155  SETBIT(fHistogramMask, HIST_RX);
1156  for (i = 0; i < fNVariables; i++)
1157  if (!fHistograms->FindObject(Form("res_x_%d", i)))
1158  fHistograms->Add(new TH2D(Form("res_x_%d", i),
1159  Form("Computed residual versus x_%d", i),
1160  100,
1161  -1,
1162  1,
1163  35,
1166  }
1167 
1168  // Residual from training sample versus. dependent variable
1169  if (opt.Contains("r2") || opt.Contains("a")) {
1170  SETBIT(fHistogramMask, HIST_RD);
1171  if (!fHistograms->FindObject("res_d"))
1172  fHistograms->Add(new TH2D("res_d",
1173  "Computed residuals vs Quantity",
1174  100,
1177  35,
1180  }
1181 
1182  // Residual from training sample
1183  if (opt.Contains("r3") || opt.Contains("a")) {
1184  SETBIT(fHistogramMask, HIST_RTRAI);
1185  if (!fHistograms->FindObject("res_train"))
1186  fHistograms->Add(new TH1D("res_train",
1187  "Computed residuals over training sample",
1188  100,
1191  }
1192  if (opt.Contains("r4") || opt.Contains("a")) {
1193  SETBIT(fHistogramMask, HIST_RTEST);
1194  if (!fHistograms->FindObject("res_test"))
1195  fHistograms->Add(new TH1D("res_test",
1196  "Distribution of residuals from test",
1197  100,
1200  }
1201 }
1202 
1203 //____________________________________________________________________
1204 void TMultiDimFet::MakeMethod(const Char_t *classname, Option_t *option) {
1205  // Generate the file <classname>MDF.cxx which contains the
1206  // implementation of the method:
1207  //
1208  // Double_t <classname>::MDF(Double_t *x)
1209  //
1210  // which does the same as TMultiDimFet::Eval. Please refer to this
1211  // method.
1212  //
1213  // Further, the public static members:
1214  //
1215  // Int_t <classname>::fgNVariables
1216  // Int_t <classname>::fgNCoefficients
1217  // Double_t <classname>::fgDMean
1218  // Double_t <classname>::fgXMean[] //[fgNVariables]
1219  // Double_t <classname>::fgXMin[] //[fgNVariables]
1220  // Double_t <classname>::fgXMax[] //[fgNVariables]
1221  // Double_t <classname>::fgCoefficient[] //[fgNCoeffficents]
1222  // Int_t <classname>::fgPower[] //[fgNCoeffficents*fgNVariables]
1223  //
1224  // are initialized, and assumed to exist. The class declaration is
1225  // assumed to be in <classname>.h and assumed to be provided by the
1226  // user.
1227  //
1228  // See TMultiDimFet::MakeRealCode for a list of options
1229  //
1230  // The minimal class definition is:
1231  //
1232  // class <classname> {
1233  // public:
1234  // Int_t <classname>::fgNVariables; // Number of variables
1235  // Int_t <classname>::fgNCoefficients; // Number of terms
1236  // Double_t <classname>::fgDMean; // Mean from training sample
1237  // Double_t <classname>::fgXMean[]; // Mean from training sample
1238  // Double_t <classname>::fgXMin[]; // Min from training sample
1239  // Double_t <classname>::fgXMax[]; // Max from training sample
1240  // Double_t <classname>::fgCoefficient[]; // Coefficients
1241  // Int_t <classname>::fgPower[]; // Function powers
1242  //
1243  // Double_t Eval(Double_t *x);
1244  // };
1245  //
1246  // Whether the method <classname>::Eval should be static or not, is
1247  // up to the user.
1248 
1249  MakeRealCode(Form("%sMDF.cxx", classname), classname, option);
1250 }
1251 
1252 //____________________________________________________________________
1254  // PRIVATE METHOD:
1255  // Normalize data to the interval [-1;1]. This is needed for the
1256  // classes method to work.
1257 
1258  Int_t i = 0;
1259  Int_t j = 0;
1260  Int_t k = 0;
1261 
1262  for (i = 0; i < fSampleSize; i++) {
1263  if (TESTBIT(fHistogramMask, HIST_DORIG))
1264  ((TH1D *)fHistograms->FindObject("d_orig"))->Fill(fQuantity(i));
1265 
1266  fQuantity(i) -= fMeanQuantity;
1268 
1269  if (TESTBIT(fHistogramMask, HIST_DSHIF))
1270  ((TH1D *)fHistograms->FindObject("d_shifted"))->Fill(fQuantity(i));
1271 
1272  for (j = 0; j < fNVariables; j++) {
1273  Double_t range = 1. / (fMaxVariables(j) - fMinVariables(j));
1274  k = i * fNVariables + j;
1275 
1276  // Fill histograms of original independent variables
1277  if (TESTBIT(fHistogramMask, HIST_XORIG))
1278  ((TH1D *)fHistograms->FindObject(Form("x_%d_orig", j)))->Fill(fVariables(k));
1279 
1280  // Normalise independent variables
1281  fVariables(k) = 1 + 2 * range * (fVariables(k) - fMaxVariables(j));
1282 
1283  // Fill histograms of normalised independent variables
1284  if (TESTBIT(fHistogramMask, HIST_XNORM))
1285  ((TH1D *)fHistograms->FindObject(Form("x_%d_norm", j)))->Fill(fVariables(k));
1286  }
1287  }
1288  // Shift min and max of dependent variable
1291 
1292  // Shift mean of independent variables
1293  for (i = 0; i < fNVariables; i++) {
1294  Double_t range = 1. / (fMaxVariables(i) - fMinVariables(i));
1295  fMeanVariables(i) = 1 + 2 * range * (fMeanVariables(i) - fMaxVariables(i));
1296  }
1297 }
1298 
1299 //____________________________________________________________________
1301  // PRIVATE METHOD:
1302  // Find the parameterization over the training sample. A full account
1303  // of the algorithm is given in the
1304  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
1305 
1306  Int_t i = -1;
1307  Int_t j = 0;
1308  Int_t k = 0;
1309  Int_t maxPass = 3;
1310  Int_t studied = 0;
1311  Double_t squareResidual = fSumSqAvgQuantity;
1312  fNCoefficients = 0;
1314  fFunctions.ResizeTo(fMaxTerms, fSampleSize);
1316  fOrthFunctionNorms.ResizeTo(fMaxTerms);
1317  fOrthCoefficients.ResizeTo(fMaxTerms);
1319  fFunctions = 1;
1320 
1321  fFunctionCodes.resize(fMaxFunctions);
1322  fPowerIndex.resize(fMaxTerms);
1323  Int_t l;
1324  for (l = 0; l < fMaxFunctions; l++)
1325  fFunctionCodes[l] = 0;
1326  for (l = 0; l < fMaxTerms; l++)
1327  fPowerIndex[l] = 0;
1328 
1329  if (fMaxAngle != 0)
1330  maxPass = 100;
1331  if (fIsUserFunction)
1332  maxPass = 1;
1333 
1334  // Loop over the number of functions we want to study.
1335  // increment inspection counter
1336  while (kTRUE) {
1337  // Reach user defined limit of studies
1338  if (studied++ >= fMaxStudy) {
1340  break;
1341  }
1342 
1343  // Considered all functions several times
1344  if (k >= maxPass) {
1346  break;
1347  }
1348 
1349  // increment function counter
1350  i++;
1351 
1352  // If we've reached the end of the functions, restart pass
1353  if (i == fMaxFunctions) {
1354  if (fMaxAngle != 0)
1355  fMaxAngle += (90 - fMaxAngle) / 2;
1356  i = 0;
1357  studied--;
1358  k++;
1359  continue;
1360  }
1361  if (studied == 1)
1362  fFunctionCodes[i] = 0;
1363  else if (fFunctionCodes[i] >= 2)
1364  continue;
1365 
1366  // Print a happy message
1367  if (fIsVerbose && studied == 1)
1368  edm::LogInfo("TMultiDimFet") << "Coeff SumSqRes Contrib Angle QM Func"
1369  << " Value W^2 Powers"
1370  << "\n";
1371 
1372  // Make the Gram-Schmidt
1373  Double_t dResidur = MakeGramSchmidt(i);
1374 
1375  if (dResidur == 0) {
1376  // This function is no good!
1377  // First test is in MakeGramSchmidt
1378  fFunctionCodes[i] = 1;
1379  continue;
1380  }
1381 
1382  // If user specified function, assume she/he knows what he's doing
1383  if (!fIsUserFunction) {
1384  // Flag this function as considered
1385  fFunctionCodes[i] = 2;
1386 
1387  // Test if this function contributes to the fit
1388  if (!TestFunction(squareResidual, dResidur)) {
1389  fFunctionCodes[i] = 1;
1390  continue;
1391  }
1392  }
1393 
1394  // If we get to here, the function currently considered is
1395  // fNCoefficients, so we increment the counter
1396  // Flag this function as OK, and store and the number in the
1397  // index.
1398  fFunctionCodes[i] = 3;
1400  fNCoefficients++;
1401 
1402  // We add the current contribution to the sum of square of
1403  // residuals;
1404  squareResidual -= dResidur;
1405 
1406  // Calculate control parameter from this function
1407  for (j = 0; j < fNVariables; j++) {
1408  if (fNCoefficients == 1 || fMaxPowersFinal[j] <= fPowers[i * fNVariables + j] - 1)
1409  fMaxPowersFinal[j] = fPowers[i * fNVariables + j] - 1;
1410  }
1411  Double_t s = EvalControl(&fPowers[i * fNVariables]);
1412 
1413  // Print the statistics about this function
1414  if (fIsVerbose) {
1415  edm::LogVerbatim("TMultiDimFet") << std::setw(5) << fNCoefficients << " " << std::setw(10) << std::setprecision(4)
1416  << squareResidual << " " << std::setw(10) << std::setprecision(4) << dResidur
1417  << " " << std::setw(7) << std::setprecision(3) << fMaxAngle << " "
1418  << std::setw(7) << std::setprecision(3) << s << " " << std::setw(5) << i << " "
1419  << std::setw(10) << std::setprecision(4) << fOrthCoefficients(fNCoefficients - 1)
1420  << " " << std::setw(10) << std::setprecision(4)
1421  << fOrthFunctionNorms(fNCoefficients - 1) << " " << std::flush;
1422  for (j = 0; j < fNVariables; j++)
1423  edm::LogInfo("TMultiDimFet") << " " << fPowers[i * fNVariables + j] - 1 << std::flush;
1424  edm::LogInfo("TMultiDimFet") << "\n";
1425  }
1426 
1427  if (fNCoefficients >= fMaxTerms /* && fIsVerbose */) {
1429  break;
1430  }
1431 
1432  Double_t err = TMath::Sqrt(TMath::Max(1e-20, squareResidual) / fSumSqAvgQuantity);
1433  if (err < fMinRelativeError) {
1435  break;
1436  }
1437  }
1438 
1439  fError = TMath::Max(1e-20, squareResidual);
1441  fRMS = TMath::Sqrt(fError / fSampleSize);
1442 }
1443 
1444 //____________________________________________________________________
1445 void TMultiDimFet::MakeRealCode(const char *filename, const char *classname, Option_t *) {
1446  // PRIVATE METHOD:
1447  // This is the method that actually generates the code for the
1448  // evaluation the parameterization on some point.
1449  // It's called by TMultiDimFet::MakeCode and TMultiDimFet::MakeMethod.
1450  //
1451  // The options are: NONE so far
1452  Int_t i, j;
1453 
1454  Bool_t isMethod = (classname[0] == '\0' ? kFALSE : kTRUE);
1455  const char *prefix = (isMethod ? Form("%s::", classname) : "");
1456  const char *cv_qual = (isMethod ? "" : "static ");
1457 
1458  std::ofstream outFile(filename, std::ios::out | std::ios::trunc);
1459  if (!outFile) {
1460  Error("MakeRealCode", "couldn't open output file '%s'", filename);
1461  return;
1462  }
1463 
1464  if (fIsVerbose)
1465  edm::LogInfo("TMultiDimFet") << "Writing on file \"" << filename << "\" ... " << std::flush;
1466  //
1467  // Write header of file
1468  //
1469  // Emacs mode line ;-)
1470  outFile << "// -*- mode: c++ -*-"
1471  << "\n";
1472  // Info about creator
1473  outFile << "// "
1474  << "\n"
1475  << "// File " << filename << " generated by TMultiDimFet::MakeRealCode"
1476  << "\n";
1477  // Time stamp
1478  TDatime date;
1479  outFile << "// on " << date.AsString() << "\n";
1480  // ROOT version info
1481  outFile << "// ROOT version " << gROOT->GetVersion() << "\n"
1482  << "//"
1483  << "\n";
1484  // General information on the code
1485  outFile << "// This file contains the function "
1486  << "\n"
1487  << "//"
1488  << "\n"
1489  << "// double " << prefix << "MDF(double *x); "
1490  << "\n"
1491  << "//"
1492  << "\n"
1493  << "// For evaluating the parameterization obtained"
1494  << "\n"
1495  << "// from TMultiDimFet and the point x"
1496  << "\n"
1497  << "// "
1498  << "\n"
1499  << "// See TMultiDimFet class documentation for more "
1500  << "information "
1501  << "\n"
1502  << "// "
1503  << "\n";
1504  // Header files
1505  if (isMethod)
1506  // If these are methods, we need the class header
1507  outFile << "#include \"" << classname << ".h\""
1508  << "\n";
1509 
1510  //
1511  // Now for the data
1512  //
1513  outFile << "//"
1514  << "\n"
1515  << "// Static data variables"
1516  << "\n"
1517  << "//"
1518  << "\n";
1519  outFile << cv_qual << "int " << prefix << "gNVariables = " << fNVariables << ";"
1520  << "\n";
1521  outFile << cv_qual << "int " << prefix << "gNCoefficients = " << fNCoefficients << ";"
1522  << "\n";
1523  outFile << cv_qual << "double " << prefix << "gDMean = " << fMeanQuantity << ";"
1524  << "\n";
1525 
1526  // Assignment to mean vector.
1527  outFile << "// Assignment to mean vector."
1528  << "\n";
1529  outFile << cv_qual << "double " << prefix << "gXMean[] = {"
1530  << "\n";
1531  for (i = 0; i < fNVariables; i++)
1532  outFile << (i != 0 ? ", " : " ") << fMeanVariables(i) << std::flush;
1533  outFile << " };"
1534  << "\n"
1535  << "\n";
1536 
1537  // Assignment to minimum vector.
1538  outFile << "// Assignment to minimum vector."
1539  << "\n";
1540  outFile << cv_qual << "double " << prefix << "gXMin[] = {"
1541  << "\n";
1542  for (i = 0; i < fNVariables; i++)
1543  outFile << (i != 0 ? ", " : " ") << fMinVariables(i) << std::flush;
1544  outFile << " };"
1545  << "\n"
1546  << "\n";
1547 
1548  // Assignment to maximum vector.
1549  outFile << "// Assignment to maximum vector."
1550  << "\n";
1551  outFile << cv_qual << "double " << prefix << "gXMax[] = {"
1552  << "\n";
1553  for (i = 0; i < fNVariables; i++)
1554  outFile << (i != 0 ? ", " : " ") << fMaxVariables(i) << std::flush;
1555  outFile << " };"
1556  << "\n"
1557  << "\n";
1558 
1559  // Assignment to coefficients vector.
1560  outFile << "// Assignment to coefficients vector."
1561  << "\n";
1562  outFile << cv_qual << "double " << prefix << "gCoefficient[] = {" << std::flush;
1563  for (i = 0; i < fNCoefficients; i++)
1564  outFile << (i != 0 ? "," : "") << "\n"
1565  << " " << fCoefficients(i) << std::flush;
1566  outFile << "\n"
1567  << " };"
1568  << "\n"
1569  << "\n";
1570 
1571  // Assignment to powers vector.
1572  outFile << "// Assignment to powers vector."
1573  << "\n"
1574  << "// The powers are stored row-wise, that is"
1575  << "\n"
1576  << "// p_ij = " << prefix << "gPower[i * NVariables + j];"
1577  << "\n";
1578  outFile << cv_qual << "int " << prefix << "gPower[] = {" << std::flush;
1579  for (i = 0; i < fNCoefficients; i++) {
1580  for (j = 0; j < fNVariables; j++) {
1581  if (j != 0)
1582  outFile << std::flush << " ";
1583  else
1584  outFile << "\n"
1585  << " ";
1586  outFile << fPowers[fPowerIndex[i] * fNVariables + j]
1587  << (i == fNCoefficients - 1 && j == fNVariables - 1 ? "" : ",") << std::flush;
1588  }
1589  }
1590  outFile << "\n"
1591  << "};"
1592  << "\n"
1593  << "\n";
1594 
1595  //
1596  // Finally we reach the function itself
1597  //
1598  outFile << "// "
1599  << "\n"
1600  << "// The " << (isMethod ? "method " : "function ") << " double " << prefix << "MDF(double *x)"
1601  << "\n"
1602  << "// "
1603  << "\n";
1604  outFile << "double " << prefix << "MDF(double *x) {"
1605  << "\n"
1606  << " double returnValue = " << prefix << "gDMean;"
1607  << "\n"
1608  << " int i = 0, j = 0, k = 0;"
1609  << "\n"
1610  << " for (i = 0; i < " << prefix << "gNCoefficients ; i++) {"
1611  << "\n"
1612  << " // Evaluate the ith term in the expansion"
1613  << "\n"
1614  << " double term = " << prefix << "gCoefficient[i];"
1615  << "\n"
1616  << " for (j = 0; j < " << prefix << "gNVariables; j++) {"
1617  << "\n"
1618  << " // Evaluate the polynomial in the jth variable."
1619  << "\n"
1620  << " int power = " << prefix << "gPower[" << prefix << "gNVariables * i + j]; "
1621  << "\n"
1622  << " double p1 = 1, p2 = 0, p3 = 0, r = 0;"
1623  << "\n"
1624  << " double v = 1 + 2. / (" << prefix << "gXMax[j] - " << prefix << "gXMin[j]) * (x[j] - " << prefix
1625  << "gXMax[j]);"
1626  << "\n"
1627  << " // what is the power to use!"
1628  << "\n"
1629  << " switch(power) {"
1630  << "\n"
1631  << " case 1: r = 1; break; "
1632  << "\n"
1633  << " case 2: r = v; break; "
1634  << "\n"
1635  << " default: "
1636  << "\n"
1637  << " p2 = v; "
1638  << "\n"
1639  << " for (k = 3; k <= power; k++) { "
1640  << "\n"
1641  << " p3 = p2 * v;"
1642  << "\n";
1643  if (fPolyType == kLegendre)
1644  outFile << " p3 = ((2 * i - 3) * p2 * v - (i - 2) * p1)"
1645  << " / (i - 1);"
1646  << "\n";
1647  if (fPolyType == kChebyshev)
1648  outFile << " p3 = 2 * v * p2 - p1; "
1649  << "\n";
1650  outFile << " p1 = p2; p2 = p3; "
1651  << "\n"
1652  << " }"
1653  << "\n"
1654  << " r = p3;"
1655  << "\n"
1656  << " }"
1657  << "\n"
1658  << " // multiply this term by the poly in the jth var"
1659  << "\n"
1660  << " term *= r; "
1661  << "\n"
1662  << " }"
1663  << "\n"
1664  << " // Add this term to the final result"
1665  << "\n"
1666  << " returnValue += term;"
1667  << "\n"
1668  << " }"
1669  << "\n"
1670  << " return returnValue;"
1671  << "\n"
1672  << "}"
1673  << "\n"
1674  << "\n";
1675 
1676  // EOF
1677  outFile << "// EOF for " << filename << "\n";
1678 
1679  // Close the file
1680  outFile.close();
1681 
1682  if (fIsVerbose)
1683  edm::LogInfo("TMultiDimFet") << "done"
1684  << "\n";
1685 }
1686 
1687 //____________________________________________________________________
1688 void TMultiDimFet::Print(Option_t *option) const {
1689  // Print statistics etc.
1690  // Options are
1691  // P Parameters
1692  // S Statistics
1693  // C Coefficients
1694  // R Result of parameterisation
1695  // F Result of fit
1696  // K Correlation Matrix
1697  // M Pretty print formula
1698  //
1699  Int_t i = 0;
1700  Int_t j = 0;
1701 
1702  TString opt(option);
1703  opt.ToLower();
1704 
1705  if (opt.Contains("p")) {
1706  // Print basic parameters for this object
1707  edm::LogInfo("TMultiDimFet") << "User parameters:"
1708  << "\n"
1709  << "----------------"
1710  << "\n"
1711  << " Variables: " << fNVariables << "\n"
1712  << " Data points: " << fSampleSize << "\n"
1713  << " Max Terms: " << fMaxTerms << "\n"
1714  << " Power Limit Parameter: " << fPowerLimit << "\n"
1715  << " Max functions: " << fMaxFunctions << "\n"
1716  << " Max functions to study: " << fMaxStudy << "\n"
1717  << " Max angle (optional): " << fMaxAngle << "\n"
1718  << " Min angle: " << fMinAngle << "\n"
1719  << " Relative Error accepted: " << fMinRelativeError << "\n"
1720  << " Maximum Powers: " << std::flush;
1721  for (i = 0; i < fNVariables; i++)
1722  edm::LogInfo("TMultiDimFet") << " " << fMaxPowers[i] - 1 << std::flush;
1723  edm::LogInfo("TMultiDimFet") << "\n"
1724  << "\n"
1725  << " Parameterisation will be done using " << std::flush;
1726  if (fPolyType == kChebyshev)
1727  edm::LogInfo("TMultiDimFet") << "Chebyshev polynomials"
1728  << "\n";
1729  else if (fPolyType == kLegendre)
1730  edm::LogInfo("TMultiDimFet") << "Legendre polynomials"
1731  << "\n";
1732  else
1733  edm::LogInfo("TMultiDimFet") << "Monomials"
1734  << "\n";
1735  edm::LogInfo("TMultiDimFet") << "\n";
1736  }
1737 
1738  if (opt.Contains("s")) {
1739  // Print statistics for read data
1740  edm::LogInfo("TMultiDimFet") << "Sample statistics:"
1741  << "\n"
1742  << "------------------"
1743  << "\n"
1744  << " D" << std::flush;
1745  for (i = 0; i < fNVariables; i++)
1746  edm::LogInfo("TMultiDimFet") << " " << std::setw(10) << i + 1 << std::flush;
1747  edm::LogInfo("TMultiDimFet") << "\n"
1748  << " Max: " << std::setw(10) << std::setprecision(7) << fMaxQuantity << std::flush;
1749  for (i = 0; i < fNVariables; i++)
1750  edm::LogInfo("TMultiDimFet") << " " << std::setw(10) << std::setprecision(4) << fMaxVariables(i) << std::flush;
1751  edm::LogInfo("TMultiDimFet") << "\n"
1752  << " Min: " << std::setw(10) << std::setprecision(7) << fMinQuantity << std::flush;
1753  for (i = 0; i < fNVariables; i++)
1754  edm::LogInfo("TMultiDimFet") << " " << std::setw(10) << std::setprecision(4) << fMinVariables(i) << std::flush;
1755  edm::LogInfo("TMultiDimFet") << "\n"
1756  << " Mean: " << std::setw(10) << std::setprecision(7) << fMeanQuantity << std::flush;
1757  for (i = 0; i < fNVariables; i++)
1758  edm::LogInfo("TMultiDimFet") << " " << std::setw(10) << std::setprecision(4) << fMeanVariables(i) << std::flush;
1759  edm::LogInfo("TMultiDimFet") << "\n"
1760  << " Function Sum Squares: " << fSumSqQuantity << "\n"
1761  << "\n";
1762  }
1763 
1764  if (opt.Contains("r")) {
1765  edm::LogInfo("TMultiDimFet") << "Results of Parameterisation:"
1766  << "\n"
1767  << "----------------------------"
1768  << "\n"
1769  << " Total reduction of square residuals " << fSumSqResidual << "\n"
1770  << " Relative precision obtained: " << fPrecision << "\n"
1771  << " Error obtained: " << fError << "\n"
1772  << " Multiple correlation coefficient: " << fCorrelationCoeff << "\n"
1773  << " Reduced Chi square over sample: " << fChi2 / (fSampleSize - fNCoefficients)
1774  << "\n"
1775  << " Maximum residual value: " << fMaxResidual << "\n"
1776  << " Minimum residual value: " << fMinResidual << "\n"
1777  << " Estimated root mean square: " << fRMS << "\n"
1778  << " Maximum powers used: " << std::flush;
1779  for (j = 0; j < fNVariables; j++)
1780  edm::LogInfo("TMultiDimFet") << fMaxPowersFinal[j] << " " << std::flush;
1781  edm::LogInfo("TMultiDimFet") << "\n"
1782  << " Function codes of candidate functions."
1783  << "\n"
1784  << " 1: considered,"
1785  << " 2: too little contribution,"
1786  << " 3: accepted." << std::flush;
1787  for (i = 0; i < fMaxFunctions; i++) {
1788  if (i % 60 == 0)
1789  edm::LogInfo("TMultiDimFet") << "\n"
1790  << " " << std::flush;
1791  else if (i % 10 == 0)
1792  edm::LogInfo("TMultiDimFet") << " " << std::flush;
1793  edm::LogInfo("TMultiDimFet") << fFunctionCodes[i];
1794  }
1795  edm::LogInfo("TMultiDimFet") << "\n"
1796  << " Loop over candidates stopped because " << std::flush;
1797  switch (fParameterisationCode) {
1798  case PARAM_MAXSTUDY:
1799  edm::LogInfo("TMultiDimFet") << "max allowed studies reached"
1800  << "\n";
1801  break;
1802  case PARAM_SEVERAL:
1803  edm::LogInfo("TMultiDimFet") << "all candidates considered several times"
1804  << "\n";
1805  break;
1806  case PARAM_RELERR:
1807  edm::LogInfo("TMultiDimFet") << "wanted relative error obtained"
1808  << "\n";
1809  break;
1810  case PARAM_MAXTERMS:
1811  edm::LogInfo("TMultiDimFet") << "max number of terms reached"
1812  << "\n";
1813  break;
1814  default:
1815  edm::LogInfo("TMultiDimFet") << "some unknown reason"
1816  << "\n";
1817  break;
1818  }
1819  edm::LogInfo("TMultiDimFet") << "\n";
1820  }
1821 
1822  if (opt.Contains("f")) {
1823  edm::LogInfo("TMultiDimFet") << "Results of Fit:"
1824  << "\n"
1825  << "---------------"
1826  << "\n"
1827  << " Test sample size: " << fTestSampleSize << "\n"
1828  << " Multiple correlation coefficient: " << fTestCorrelationCoeff << "\n"
1829  << " Relative precision obtained: " << fTestPrecision << "\n"
1830  << " Error obtained: " << fTestError << "\n"
1831  << " Reduced Chi square over sample: " << fChi2 / (fSampleSize - fNCoefficients)
1832  << "\n"
1833  << "\n";
1834  /*
1835  if (fFitter) {
1836  fFitter->PrintResults(1,1);
1837  edm::LogInfo("TMultiDimFet") << "\n";
1838  }
1839 */
1840  }
1841 
1842  if (opt.Contains("c")) {
1843  edm::LogInfo("TMultiDimFet") << "Coefficients:"
1844  << "\n"
1845  << "-------------"
1846  << "\n"
1847  << " # Value Error Powers"
1848  << "\n"
1849  << " ---------------------------------------"
1850  << "\n";
1851  for (i = 0; i < fNCoefficients; i++) {
1852  edm::LogInfo("TMultiDimFet") << " " << std::setw(3) << i << " " << std::setw(12) << fCoefficients(i) << " "
1853  << std::setw(12) << fCoefficientsRMS(i) << " " << std::flush;
1854  for (j = 0; j < fNVariables; j++)
1855  edm::LogInfo("TMultiDimFet") << " " << std::setw(3) << fPowers[fPowerIndex[i] * fNVariables + j] - 1
1856  << std::flush;
1857  edm::LogInfo("TMultiDimFet") << "\n";
1858  }
1859  edm::LogInfo("TMultiDimFet") << "\n";
1860  }
1861  if (opt.Contains("k") && fCorrelationMatrix.IsValid()) {
1862  edm::LogInfo("TMultiDimFet") << "Correlation Matrix:"
1863  << "\n"
1864  << "-------------------";
1865  fCorrelationMatrix.Print();
1866  }
1867 
1868  if (opt.Contains("m")) {
1869  edm::LogInfo("TMultiDimFet") << std::setprecision(25);
1870  edm::LogInfo("TMultiDimFet") << "Parameterization:"
1871  << "\n"
1872  << "-----------------"
1873  << "\n"
1874  << " Normalised variables: "
1875  << "\n";
1876  for (i = 0; i < fNVariables; i++)
1877  edm::LogInfo("TMultiDimFet") << "\ty" << i << "\t:= 1 + 2 * (x" << i << " - " << fMaxVariables(i) << ") / ("
1878  << fMaxVariables(i) << " - " << fMinVariables(i) << ")"
1879  << "\n";
1880  edm::LogInfo("TMultiDimFet") << "\n"
1881  << " f[";
1882  for (i = 0; i < fNVariables; i++) {
1883  edm::LogInfo("TMultiDimFet") << "y" << i;
1884  if (i != fNVariables - 1)
1885  edm::LogInfo("TMultiDimFet") << ", ";
1886  }
1887  edm::LogInfo("TMultiDimFet") << "] := ";
1888  for (Int_t i = 0; i < fNCoefficients; i++) {
1889  if (i != 0)
1890  edm::LogInfo("TMultiDimFet") << " " << (fCoefficients(i) < 0 ? "- " : "+ ") << TMath::Abs(fCoefficients(i));
1891  else
1892  edm::LogInfo("TMultiDimFet") << fCoefficients(i);
1893  for (Int_t j = 0; j < fNVariables; j++) {
1894  Int_t p = fPowers[fPowerIndex[i] * fNVariables + j];
1895  switch (p) {
1896  case 1:
1897  break;
1898  case 2:
1899  edm::LogInfo("TMultiDimFet") << " * y" << j;
1900  break;
1901  default:
1902  switch (fPolyType) {
1903  case kLegendre:
1904  edm::LogInfo("TMultiDimFet") << " * L" << p - 1 << "(y" << j << ")";
1905  break;
1906  case kChebyshev:
1907  edm::LogInfo("TMultiDimFet") << " * C" << p - 1 << "(y" << j << ")";
1908  break;
1909  default:
1910  edm::LogInfo("TMultiDimFet") << " * y" << j << "^" << p - 1;
1911  break;
1912  }
1913  }
1914  }
1915  }
1916  edm::LogInfo("TMultiDimFet") << "\n";
1917  }
1918 }
1919 
1920 //____________________________________________________________________
1921 void TMultiDimFet::PrintPolynomialsSpecial(Option_t *option) const {
1922  // M Pretty print formula
1923  //
1924  Int_t i = 0;
1925  // Int_t j = 0;
1926 
1927  TString opt(option);
1928  opt.ToLower();
1929 
1930  if (opt.Contains("m")) {
1931  edm::LogInfo("TMultiDimFet") << std::setprecision(25);
1932  edm::LogInfo("TMultiDimFet") << "Parameterization:"
1933  << "\n"
1934  << "-----------------"
1935  << "\n"
1936  << " Normalised variables: "
1937  << "\n";
1938  for (i = 0; i < fNVariables; i++)
1939  edm::LogInfo("TMultiDimFet") << "\tdouble y" << i << "\t=1+2*(x" << i << "-" << fMaxVariables(i) << ")/("
1940  << fMaxVariables(i) << "-" << fMinVariables(i) << ");"
1941  << "\n";
1942  edm::LogInfo("TMultiDimFet") << "\n"
1943  << " f[";
1944  for (i = 0; i < fNVariables; i++) {
1945  edm::LogInfo("TMultiDimFet") << "y" << i;
1946  if (i != fNVariables - 1)
1947  edm::LogInfo("TMultiDimFet") << ", ";
1948  }
1949  edm::LogInfo("TMultiDimFet") << "] := " << fMeanQuantity << " + ";
1950  for (Int_t i = 0; i < fNCoefficients; i++) {
1951  if (i != 0)
1952  edm::LogInfo("TMultiDimFet") << " " << (fCoefficients(i) < 0 ? "-" : "+") << TMath::Abs(fCoefficients(i));
1953  else
1954  edm::LogInfo("TMultiDimFet") << fCoefficients(i);
1955  for (Int_t j = 0; j < fNVariables; j++) {
1956  Int_t p = fPowers[fPowerIndex[i] * fNVariables + j];
1957  switch (p) {
1958  case 1:
1959  break;
1960  case 2:
1961  edm::LogInfo("TMultiDimFet") << "*y" << j;
1962  break;
1963  default:
1964  switch (fPolyType) {
1965  case kLegendre:
1966  edm::LogInfo("TMultiDimFet") << "*Leg(" << p - 1 << ",y" << j << ")";
1967  break;
1968  case kChebyshev:
1969  edm::LogInfo("TMultiDimFet") << "*C" << p - 1 << "(y" << j << ")";
1970  break;
1971  default:
1972  edm::LogInfo("TMultiDimFet") << "*y" << j << "**" << p - 1;
1973  break;
1974  }
1975  }
1976  }
1977  edm::LogInfo("TMultiDimFet") << "\n";
1978  }
1979  edm::LogInfo("TMultiDimFet") << "\n";
1980  }
1981 }
1982 
1983 //____________________________________________________________________
1984 Bool_t TMultiDimFet::Select(const Int_t *) {
1985  // Selection method. User can override this method for specialized
1986  // selection of acceptable functions in fit. Default is to select
1987  // all. This message is sent during the build-up of the function
1988  // candidates table once for each set of powers in
1989  // variables. Notice, that the argument array contains the powers
1990  // PLUS ONE. For example, to De select the function
1991  // f = x1^2 * x2^4 * x3^5,
1992  // this method should return kFALSE if given the argument
1993  // { 3, 4, 6 }
1994  return kTRUE;
1995 }
1996 
1997 //____________________________________________________________________
1998 void TMultiDimFet::SetMaxAngle(Double_t ang) {
1999  // Set the max angle (in degrees) between the initial data vector to
2000  // be fitted, and the new candidate function to be included in the
2001  // fit. By default it is 0, which automatically chooses another
2002  // selection criteria. See also
2003  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
2004  if (ang >= 90 || ang < 0) {
2005  Warning("SetMaxAngle", "angle must be in [0,90)");
2006  return;
2007  }
2008 
2009  fMaxAngle = ang;
2010 }
2011 
2012 //____________________________________________________________________
2013 void TMultiDimFet::SetMinAngle(Double_t ang) {
2014  // Set the min angle (in degrees) between a new candidate function
2015  // and the subspace spanned by the previously accepted
2016  // functions. See also
2017  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
2018  if (ang > 90 || ang <= 0) {
2019  Warning("SetMinAngle", "angle must be in [0,90)");
2020  return;
2021  }
2022 
2023  fMinAngle = ang;
2024 }
2025 
2026 //____________________________________________________________________
2027 void TMultiDimFet::SetPowers(const Int_t *powers, Int_t terms) {
2028  // Define a user function. The input array must be of the form
2029  // (p11, ..., p1N, ... ,pL1, ..., pLN)
2030  // Where N is the dimension of the data sample, L is the number of
2031  // terms (given in terms) and the first number, labels the term, the
2032  // second the variable. More information is given in the
2033  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
2034  fIsUserFunction = kTRUE;
2035  fMaxFunctions = terms;
2036  fMaxTerms = terms;
2037  fMaxStudy = terms;
2039  fPowers.resize(fMaxFunctions * fNVariables);
2040  Int_t i, j;
2041  for (i = 0; i < fMaxFunctions; i++)
2042  for (j = 0; j < fNVariables; j++)
2043  fPowers[i * fNVariables + j] = powers[i * fNVariables + j] + 1;
2044 }
2045 
2046 //____________________________________________________________________
2048  // Set the user parameter for the function selection. The bigger the
2049  // limit, the more functions are used. The meaning of this variable
2050  // is defined in the
2051  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
2052  fPowerLimit = limit;
2053 }
2054 
2055 //____________________________________________________________________
2056 void TMultiDimFet::SetMaxPowers(const Int_t *powers) {
2057  // Set the maximum power to be considered in the fit for each
2058  // variable. See also
2059  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
2060  if (!powers)
2061  return;
2062 
2063  for (Int_t i = 0; i < fNVariables; i++)
2064  fMaxPowers[i] = powers[i] + 1;
2065 }
2066 
2067 //____________________________________________________________________
2069  // Set the acceptable relative error for when sum of square
2070  // residuals is considered minimized. For a full account, refer to
2071  // the
2072  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
2074 }
2075 
2076 //____________________________________________________________________
2077 Bool_t TMultiDimFet::TestFunction(Double_t squareResidual, Double_t dResidur) {
2078  // PRIVATE METHOD:
2079  // Test whether the currently considered function contributes to the
2080  // fit. See also
2081  // Begin_Html<a href="#TMultiDimFet:description">class description</a>End_Html
2082 
2083  if (fNCoefficients != 0) {
2084  // Now for the second test:
2085  if (fMaxAngle == 0) {
2086  // If the user hasn't supplied a max angle do the test as,
2087  if (dResidur < squareResidual / (fMaxTerms - fNCoefficients + 1 + 1E-10)) {
2088  return kFALSE;
2089  }
2090  } else {
2091  // If the user has provided a max angle, test if the calculated
2092  // angle is less then the max angle.
2093  if (TMath::Sqrt(dResidur / fSumSqAvgQuantity) < TMath::Cos(fMaxAngle * DEGRAD)) {
2094  return kFALSE;
2095  }
2096  }
2097  }
2098  // If we get here, the function is OK
2099  return kTRUE;
2100 }
2101 
2102 //____________________________________________________________________
2103 //void mdfHelper(int& /*npar*/, double* /*divs*/, double& chi2,
2104 // double* coeffs, int /*flag*/)
2105 /*{
2106  // Helper function for doing the minimisation of Chi2 using Minuit
2107 
2108  // Get pointer to current TMultiDimFet object.
2109  // TMultiDimFet* mdf = TMultiDimFet::Instance();
2110  //chi2 = mdf->MakeChi2(coeffs);
2111 }
2112 */
Log< level::Info, true > LogVerbatim
edm::ErrorSummaryEntry Error
Double_t fMaxQuantity
Definition: TMultiDimFet.h:44
TMatrixD fCorrelationMatrix
Multi Correlation coefficient.
Definition: TMultiDimFet.h:104
Double_t fSumSqQuantity
Min value of dependent quantity.
Definition: TMultiDimFet.h:46
Double_t fMinAngle
Size of test sample.
Definition: TMultiDimFet.h:63
TVectorD fTestVariables
Test sample, Error in quantity.
Definition: TMultiDimFet.h:59
const TMultiDimFet & operator=(const TMultiDimFet &in)
Definition: TMultiDimFet.cc:83
TVectorD fMinVariables
Definition: TMultiDimFet.h:53
Int_t fTestSampleSize
Test sample, independent variables.
Definition: TMultiDimFet.h:61
Double_t fSumSqAvgQuantity
SumSquare of dependent quantity.
Definition: TMultiDimFet.h:47
Double_t fMinQuantity
Max value of dependent quantity.
Definition: TMultiDimFet.h:45
virtual void MakeCoefficientErrors()
void ZeroDoubiousCoefficients(double error)
void SetPowerLimit(Double_t limit=1e-3)
int32_t *__restrict__ iv
Int_t fParameterisationCode
Chi square of fit.
Definition: TMultiDimFet.h:97
Double_t fMinResidual
Max redsidual value.
Definition: TMultiDimFet.h:85
EMDFPolyType fPolyType
Bit pattern of hisograms used.
Definition: TMultiDimFet.h:112
const TString p2
Definition: fwPaths.cc:13
TMatrixD fFunctions
Control parameter.
Definition: TMultiDimFet.h:70
#define HIST_RD
Definition: TMultiDimFet.cc:32
Double_t fTestCorrelationCoeff
Correlation matrix.
Definition: TMultiDimFet.h:105
void SetMaxPowers(const Int_t *powers)
virtual Double_t EvalControl(const Int_t *powers)
TMatrixD fOrthFunctions
max functions to study
Definition: TMultiDimFet.h:75
Byte_t fHistogramMask
List of histograms.
Definition: TMultiDimFet.h:108
~TMultiDimFet() override
Double_t fMaxAngle
Min angle for acepting new function.
Definition: TMultiDimFet.h:64
std::vector< Int_t > fPowers
Definition: TMultiDimFet.h:80
Double_t fPowerLimit
maximum powers, ex-array
Definition: TMultiDimFet.h:68
Double_t fPrecision
Error from test.
Definition: TMultiDimFet.h:101
#define HIST_DSHIF
Definition: TMultiDimFet.cc:30
virtual void MakeHistograms(Option_t *option="A")
TVectorD fCoefficientsRMS
Definition: TMultiDimFet.h:94
virtual void MakeParameterization()
virtual Double_t MakeGramSchmidt(Int_t function)
#define HIST_RX
Definition: TMultiDimFet.cc:31
Int_t fMaxResidualRow
Min redsidual value.
Definition: TMultiDimFet.h:86
void Print(Option_t *option="ps") const override
Double_t fTestError
Error from parameterization.
Definition: TMultiDimFet.h:100
virtual void AddTestRow(const Double_t *x, Double_t D, Double_t E=0)
void SetMinRelativeError(Double_t error)
virtual void MakeNormalized()
#define DEGRAD
Definition: TMultiDimFet.cc:26
virtual Bool_t TestFunction(Double_t squareResidual, Double_t dResidur)
const uint16_t range(const Frame &aFrame)
virtual Double_t EvalFactor(Int_t p, Double_t x) const
virtual void SetPowers(const Int_t *powers, Int_t terms)
Int_t fNVariables
Training sample, independent variables.
Definition: TMultiDimFet.h:50
#define PARAM_SEVERAL
Definition: TMultiDimFet.cc:36
virtual void MakeCandidates()
Double_t fChi2
Root mean square of fit.
Definition: TMultiDimFet.h:96
Bool_t fIsVerbose
Definition: TMultiDimFet.h:115
Bool_t fShowCorrelation
Definition: TMultiDimFet.h:113
Int_t fMinResidualRow
Row giving max residual.
Definition: TMultiDimFet.h:87
TVectorD fTestSqError
Test sample, dependent quantity.
Definition: TMultiDimFet.h:58
TVectorD fQuantity
Definition: TMultiDimFet.h:41
Double_t fMinRelativeError
Definition: TMultiDimFet.h:66
virtual void MakeCorrelation()
TVectorD fOrthCoefficients
Definition: TMultiDimFet.h:91
Double_t fRMS
Vector of RMS of coefficients.
Definition: TMultiDimFet.h:95
void Fill(HcalDetId &id, double val, std::vector< TH2F > &depth)
std::vector< Int_t > fPowerIndex
Definition: TMultiDimFet.h:81
T Abs(T a)
Definition: MathUtil.h:49
Double_t fMeanQuantity
Training sample, error in quantity.
Definition: TMultiDimFet.h:43
ClassImp(AliDaqEventHeader)
TVectorD fOrthFunctionNorms
As above, but orthogonalised.
Definition: TMultiDimFet.h:76
const TString p1
Definition: fwPaths.cc:12
#define HIST_RTRAI
Definition: TMultiDimFet.cc:33
uint16_t const *__restrict__ x
Definition: gpuClustering.h:39
virtual void MakeCode(const char *functionName="MDF", Option_t *option="")
#define PARAM_MAXTERMS
Definition: TMultiDimFet.cc:38
Double_t fSumSqResidual
Row giving min residual.
Definition: TMultiDimFet.h:88
#define PARAM_RELERR
Definition: TMultiDimFet.cc:37
virtual void AddRow(const Double_t *x, Double_t D, Double_t E=0)
virtual Double_t MakeChi2(const Double_t *coeff=nullptr)
Double_t fMaxResidual
Vector of the final residuals.
Definition: TMultiDimFet.h:84
virtual void MakeRealCode(const char *filename, const char *classname, Option_t *option="")
virtual Bool_t Select(const Int_t *iv)
#define HIST_XNORM
Definition: TMultiDimFet.cc:29
TVectorD fMaxVariables
mean value of independent variables
Definition: TMultiDimFet.h:52
virtual void FindParameterization(double precision)
Double_t fTestPrecision
Relative precision of param.
Definition: TMultiDimFet.h:102
#define HIST_DORIG
Definition: TMultiDimFet.cc:28
TList * fHistograms
Multi Correlation coefficient.
Definition: TMultiDimFet.h:107
Log< level::Info, false > LogInfo
T Max(T a, T b)
Definition: MathUtil.h:44
Int_t fMaxTerms
Max angle for acepting new function.
Definition: TMultiDimFet.h:65
TVectorD fTestQuantity
Size of training sample.
Definition: TMultiDimFet.h:57
DecomposeProduct< arg, typename Div::arg > D
Definition: Factorize.h:141
TVectorD fVariables
Sum of squares away from mean.
Definition: TMultiDimFet.h:49
Int_t fMaxFunctions
Functions evaluated over sample.
Definition: TMultiDimFet.h:71
Int_t fSampleSize
Definition: TMultiDimFet.h:55
double b
Definition: hdecay.h:118
Bool_t fIsUserFunction
Definition: TMultiDimFet.h:114
Double_t fError
Exit code of parameterisation.
Definition: TMultiDimFet.h:99
Int_t fNCoefficients
Sum of Square residuals.
Definition: TMultiDimFet.h:90
#define HIST_XORIG
Definition: TMultiDimFet.cc:27
Int_t fMaxFunctionsTimesNVariables
maximum powers from fit, ex-array
Definition: TMultiDimFet.h:79
std::vector< Int_t > fFunctionCodes
Definition: TMultiDimFet.h:72
TVectorD fSqError
Training sample, dependent quantity.
Definition: TMultiDimFet.h:42
tuple filename
Definition: lut2db_cfg.py:20
void SetMinAngle(Double_t angle=1)
#define PARAM_MAXSTUDY
Definition: TMultiDimFet.cc:35
Double_t fCorrelationCoeff
Relative precision of test.
Definition: TMultiDimFet.h:103
TMatrixD fOrthCurvatureMatrix
The model coefficients.
Definition: TMultiDimFet.h:92
virtual void MakeCoefficients()
TVectorD fResiduals
Definition: TMultiDimFet.h:83
std::vector< Int_t > fMaxPowers
Min relative error accepted.
Definition: TMultiDimFet.h:67
TVectorD fMeanVariables
Definition: TMultiDimFet.h:51
void Clear(Option_t *option="") override
virtual void MakeMethod(const Char_t *className="MDF", Option_t *option="")
void ReducePolynomial(double error)
std::vector< Int_t > fMaxPowersFinal
Norm of the evaluated functions.
Definition: TMultiDimFet.h:78
int col
Definition: cuy.py:1009
virtual void PrintPolynomialsSpecial(Option_t *option="m") const
uint32_t dimension(pat::CandKinResolution::Parametrization parametrization)
Returns the number of free parameters in a parametrization (3 or 4)
void SetMaxAngle(Double_t angle=0)
tuple size
Write out results.
TVectorD fCoefficients
Model matrix.
Definition: TMultiDimFet.h:93
Int_t fMaxStudy
acceptance code, ex-array
Definition: TMultiDimFet.h:73
#define HIST_RTEST
Definition: TMultiDimFet.cc:34
virtual Double_t Eval(const Double_t *x, const Double_t *coeff=nullptr) const