CMS 3D CMS Logo

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