Logo ROOT   6.10/09
Reference Guide
UnitTesting.cxx
Go to the documentation of this file.
1 #include "TFitEditor.h"
2 
3 #include "TApplication.h"
4 #include "TROOT.h"
5 #include "TBenchmark.h"
6 
7 #include "TCanvas.h"
8 #include "TH1.h"
9 
10 #include "TPluginManager.h"
11 #include "TError.h"
12 
13 #include "TGComboBox.h"
14 
15 #include <iostream>
16 #include <exception>
17 #include <stdexcept>
18 #include <cmath>
19 using namespace std;
20 
21 #include "CommonDefs.h"
22 
23 // Function that compares to doubles up to an error limit
24 int equals(Double_t n1, Double_t n2, double ERRORLIMIT = 1.E-10)
25 {
26  return fabs( n1 - n2 ) > ERRORLIMIT * fabs(n1);
27 }
28 
29 // Selects, given a TGComboBox*, the entry whose title is name.
30 int SelectEntry(TGComboBox* cb, const char* name)
31 {
32  TGTextLBEntry* findEntry = static_cast<TGTextLBEntry*>( cb->FindEntry(name) );
33  cb->Select(findEntry->EntryId());
34 
35  return findEntry->EntryId();
36 }
37 
38 // Class to make the Unit Testing. It is important than the test
39 // methods are inside the class as this in particular is defined as a
40 // friend of the TFitEditor. This way, we can access the private
41 // methods of TFitEditor to perform several types of tests.
42 class FitEditorUnitTesting
43 {
44 private:
45  // Pointer to the current (and only one) TFitEditor opened.
46  TFitEditor* f;
47 
48  // These two variables are here to redirect the standard output to
49  // a file.
50  int old_stdout;
51  FILE *out;
52 public:
53 
54  // Exception thrown when any of the pointers managed by the
55  // FitEditorUnitTesting class are invalid
56  class InvalidPointer: public std::exception
57  {
58  private:
59  const char* _exp;
60  public:
61  InvalidPointer(const char* exp): _exp(exp) {};
62  const char* what() { return _exp; };
63  };
64 
65  // Constructor: Receives the instance of the TFitEditor
66  FitEditorUnitTesting() {
67  // Redirect the stdout to a file outputUnitTesting.txt
68  old_stdout = dup (fileno (stdout));
69  (void) freopen ("outputUnitTesting.txt", "w", stdout);
70  out = fdopen (old_stdout, "w");
71 
72  // Execute the initial script
73  gROOT->ProcessLine(".x $ROOTSYS/tutorials/fit/FittingDemo.C+");
74 
75  // Get an instance of the TFitEditor
76  TCanvas* c1 = static_cast<TCanvas*>( gROOT->FindObject("c1") );
77  TH1* h = static_cast<TH1*> ( gROOT->FindObject("histo") );
78 
79  f = TFitEditor::GetInstance(c1,h);
80 
81  if ( f == 0 )
82  throw InvalidPointer("In FitEditorUnitTesting constructor");
83  }
84 
85  // The destructor will close the TFitEditor and terminate the
86  // application. Unfortunately, the application must be run from
87  // main, otherwise, the test will make a segmentation fault while
88  // trying to retrieve the TFitEditor singleton. If the user wants
89  // to play a bit with the fitpanel once the tests have finised,
90  // then they should comment this method.
91  ~FitEditorUnitTesting() {
92  f->DoClose();
94  }
95 
96  // This is a generic method to make the output of all the tests
97  // consistent. T is a function pointer to one of the tests
98  // function. It has been implemented through templates to permit
99  // more test types than the originally designed.
100  // @ str : Name of the test
101  // @ func : Member function pointer to the real implementation of
102  // the test.
103  template <typename T>
104  int MakeTest(const char* str, T func )
105  {
106  fprintf(stdout, "\n***** %s *****\n", str);
107  int status = (this->*func)();
108 
109  fprintf(stdout, "%s..........", str);
110  fprintf(out, "%s..........", str);
111  if ( status == 0 ) {
112  fprintf(stdout, "OK\n");
113  fprintf(out, "OK\n");
114  }
115  else {
116  fprintf(stdout, "FAILED\n");
117  fprintf(out, "FAILED\n");
118  }
119  return status;
120  }
121 
122  // This is where all the tests are called. If the user wants to add
123  // new tests or avoid executing one of the existing ones, it is
124  // here where they should do it.
125  int UnitTesting() {
126  int result = 0;
127 
128  fprintf(out, "\n**STARTING TFitEditor Unit Tests**\n\n");
129 
130  result += MakeTest("TestHistogramFit...", &FitEditorUnitTesting::TestHistogramFit);
131 
132  result += MakeTest("TestGSLFit.........", &FitEditorUnitTesting::TestGSLFit);
133 
134  result += MakeTest("TestUpdate.........", &FitEditorUnitTesting::TestUpdate);
135 
136  result += MakeTest("TestGraph..........", &FitEditorUnitTesting::TestGraph);
137 
138  result += MakeTest("TestGraphError.....", &FitEditorUnitTesting::TestGraphError);
139 
140  result += MakeTest("TestGraph2D........", &FitEditorUnitTesting::TestGraph2D);
141 
142  result += MakeTest("TestGraph2DError...", &FitEditorUnitTesting::TestGraph2DError);
143 
144  result += MakeTest("TestUpdateTree.....", &FitEditorUnitTesting::TestUpdateTree);
145 
146  result += MakeTest("TestTree1D.........", &FitEditorUnitTesting::TestTree1D);
147 
148  result += MakeTest("TestTree2D.........", &FitEditorUnitTesting::TestTree2D);
149 
150  result += MakeTest("TestTreeND.........", &FitEditorUnitTesting::TestTreeND);
151 
152  fprintf(out, "\nRemember to also check outputUnitTesting.txt for "
153  "more detailed information\n\n");
154 
155  return result;
156  }
157 
158  // This is a debuggin method used to print the parameter values
159  // stored in the fitpanel. This is useful when performing a fit, to
160  // know against which values the test should be compare to.
161  void PrintFuncPars()
162  {
163  static int counter = 0;
164  fprintf(out, "Printing the Func Pars (%d)\n", ++counter);
165  for ( unsigned int i = 0; i < f->fFuncPars.size(); ++i ) {
166  fprintf(out, "%30.20f %30.20f %30.20f\n", f->fFuncPars[i][0], f->fFuncPars[i][1], f->fFuncPars[i][2]);
167  }
168  }
169 
170  // This function compares the parameters stored in the TFitEditor
171  // with the ones passed by the test functions. Normally, if the
172  // function return 0, it means all the parameters are equal up to a
173  // certain limit, thus the test was successful.
174  int CompareFuncPars(std::vector<TFitEditor::FuncParamData_t>& pars)
175  {
176  int status = 0;
177  for ( unsigned int i = 0; i < f->fFuncPars.size(); ++i ) {
178  for ( unsigned int j = 0; j < 3; ++j) {
179  int internalStatus = equals(pars[i][j], f->fFuncPars[i][j]);
180  //fprintf(out, "i: %d, j: %d, e: %d\n", i, j, internalStatus);
181  status += internalStatus;
182  }
183  }
184 
185  return status;
186  }
187 
188  // From here, the implementation of the different tests. The names
189  // of the test should be enough to know what they are testing, as
190  // these tests are mean to be as simple as possible.
191 
192  int TestHistogramFit() {
195  f->DoFit();
196 
197  std::vector<TFitEditor::FuncParamData_t> pars(6);
198  pars[0][0] = -0.86471376634076801970; pars[0][1] = pars[0][2] = 0.0;
199  pars[1][0] = 45.84337697060870908672; pars[1][1] = pars[1][2] = 0.0;
200  pars[2][0] = -13.32141783912906873866; pars[2][1] = pars[2][2] = 0.0;
201  pars[3][0] = 13.80743352672578438955; pars[3][1] = pars[3][2] = 0.0;
202  pars[4][0] = 0.17230936727526752206; pars[4][1] = pars[4][2] = 0.0;
203  pars[5][0] = 0.98728095791845293938; pars[5][1] = pars[5][2] = 0.0;
204 
205  return CompareFuncPars(pars);
206  }
207 
208  int TestGSLFit() {
210  f->fLibGSL->Toggled(kTRUE);
212  f->DoFit();
213 
214  std::vector<TFitEditor::FuncParamData_t> pars(6);
215  pars[0][0] = -0.86471376626133966692; pars[0][1] = pars[0][2] = 0.0;
216  pars[1][0] = 45.84337697042452219875; pars[1][1] = pars[1][2] = 0.0;
217  pars[2][0] = -13.32141783972060622432; pars[2][1] = pars[2][2] = 0.0;
218  pars[3][0] = 13.80743352667312962012; pars[3][1] = pars[3][2] = 0.0;
219  pars[4][0] = 0.17230936776683797307; pars[4][1] = pars[4][2] = 0.0;
220  pars[5][0] = 0.98728095212777022827; pars[5][1] = pars[5][2] = 0.0;
221 
222  return CompareFuncPars(pars);
223  }
224 
225  int TestUpdate() {
226  gROOT->ProcessLine(".x $ROOTSYS/tutorials/fit/ConfidenceIntervals.C+");
227  f->DoUpdate();
228 
229  return 0;
230  }
231 
232  int TestGraph() {
233  SelectEntry(f->fDataSet, "TGraph::GraphNoError");
234 
237 
239  SelectEntry(f->fFuncList, "fpol");
240  f->DoFit();
241 
242  std::vector<TFitEditor::FuncParamData_t> pars(2);
243  pars[0][0] = -1.07569876898511784802; pars[0][1] = pars[0][2] = 0.0;
244  pars[1][0] = 1.83337233651544084800; pars[1][1] = pars[1][2] = 0.0;
245 
246  return CompareFuncPars(pars);
247  }
248 
249  int TestGraphError() {
250  SelectEntry(f->fDataSet, "TGraphErrors::Graph");
251 
254 
256  SelectEntry(f->fFuncList, "fpol");
257  f->DoFit();
258 
259  std::vector<TFitEditor::FuncParamData_t> pars(2);
260  pars[0][0] = -1.07569876898508010044; pars[0][1] = pars[0][2] = 0.0;
261  pars[1][0] = 1.83337233651530895351; pars[1][1] = pars[1][2] = 0.0;
262 
263  return CompareFuncPars(pars);
264  }
265 
266  int TestGraph2D() {
267  SelectEntry(f->fDataSet, "TGraph2D::Graph2DNoError");
268 
271 
273  SelectEntry(f->fFuncList, "f2");
274 
275  // Set the parameters to the original ones in
276  // ConfidenceIntervals.C. Otherwise it will be using those of
277  // the last fit with fpol and will make an invalid fit.
278  f->fFuncPars[0][0] = 0.5;
279  f->fFuncPars[1][0] = 1.5;
280 
281  f->DoFit();
282 
283  std::vector<TFitEditor::FuncParamData_t> pars(2);
284  pars[0][0] = 0.57910401391086918643; pars[0][1] = pars[0][2] = 0.0;
285  pars[1][0] = 1.73731204173242681499; pars[1][1] = pars[1][2] = 0.0;
286 
287  return CompareFuncPars(pars);
288  }
289 
290  int TestGraph2DError() {
291  SelectEntry(f->fDataSet, "TGraph2DErrors::Graph2D");
292 
295 
297  SelectEntry(f->fFuncList, "f2");
298 
299  // Set the parameters to the original ones in
300  // ConfidenceIntervals.C. Otherwise it will be using those of
301  // the last fit with f2 and the fit will make no sense.
302  f->fFuncPars[0][0] = 0.5;
303  f->fFuncPars[1][0] = 1.5;
304 
305  f->DoFit();
306 
307  std::vector<TFitEditor::FuncParamData_t> pars(2);
308  pars[0][0] = 0.57911670684083915717; pars[0][1] = pars[0][2] = 0.0;
309  pars[1][0] = 1.73735012087486695442; pars[1][1] = pars[1][2] = 0.0;
310 
311  return CompareFuncPars(pars);
312  }
313 
314  int TestUpdateTree() {
315  gROOT->ProcessLine(".x ~/tmp/fitpanel/createTree.C++");
316  f->DoUpdate();
317  return 0;
318  }
319 
320  int TestTree1D() {
321  TObject* objSelected = gROOT->FindObject("tree");
322  if ( !objSelected )
323  throw InvalidPointer("In TestUpdateTree");
324 
325  Int_t selected = kFP_NOSEL + 6;
326 
327  f->ProcessTreeInput(objSelected, selected, "x", "y>1");
329  SelectEntry(f->fFuncList, "gausn");
330 
331  f->fFuncPars.resize(3);
332  f->fFuncPars[0][0] = f->fFuncPars[0][1] = f->fFuncPars[0][2] = 1;
333  f->fFuncPars[1][0] = 0;
334  f->fFuncPars[2][0] = 1;
335 
336  f->DoFit();
337 
338  std::vector<TFitEditor::FuncParamData_t> pars(3);
339  pars[0][0] = 1.0; pars[0][1] = pars[0][2] = 1.0;
340  pars[1][0] = 0.57616222565122654498; pars[1][1] = pars[1][2] = 0.0;
341  pars[2][0] = 0.90739764318839521984; pars[2][1] = pars[2][2] = 0.0;
342 
343  return CompareFuncPars(pars);
344  }
345 
346  int TestTree2D() {
347  TObject* objSelected = gROOT->FindObject("tree");
348  if ( !objSelected )
349  throw InvalidPointer("In TestUpdateTree");
350 
351  Int_t selected = kFP_NOSEL + 6;
352 
353  f->ProcessTreeInput(objSelected, selected, "x:y", "");
355  SelectEntry(f->fFuncList, "gaus2d");
356 
357  f->fFuncPars[0][0] = 1; f->fFuncPars[0][1] = f->fFuncPars[0][2] = 0;
358  f->fFuncPars[1][0] = 1; f->fFuncPars[1][1] = f->fFuncPars[1][2] = 0;
359  f->fFuncPars[2][0] = 0; f->fFuncPars[2][1] = f->fFuncPars[2][2] = 0;
360 
361  f->DoFit();
362 
363  std::vector<TFitEditor::FuncParamData_t> pars(3);
364  pars[0][0] = 1.01009862846512765699; pars[0][1] = pars[0][2] = 0.0;
365  pars[1][0] = 2.00223267618221001385; pars[1][1] = pars[1][2] = 0.0;
366  pars[2][0] = 0.49143171847344568892; pars[2][1] = pars[2][2] = 0.0;
367 
368  return CompareFuncPars(pars);
369  }
370 
371  int TestTreeND() {
372  TObject* objSelected = gROOT->FindObject("tree");
373  if ( !objSelected )
374  throw InvalidPointer("In TestUpdateTree");
375 
376  Int_t selected = kFP_NOSEL + 6;
377 
378  f->ProcessTreeInput(objSelected, selected, "x:y:z:u:v:w", "");
380  SelectEntry(f->fFuncList, "gausND");
381 
382  f->fFuncPars[ 0][0] = 1.0; f->fFuncPars[ 0][1] = f->fFuncPars[ 0][2] = 0;
383  f->fFuncPars[ 1][0] = 1.0; f->fFuncPars[ 1][1] = f->fFuncPars[ 1][2] = 0;
384  f->fFuncPars[ 2][0] = 0.1; f->fFuncPars[ 2][1] = f->fFuncPars[ 2][2] = 0;
385  f->fFuncPars[ 3][0] = 0.0; f->fFuncPars[ 3][1] = f->fFuncPars[ 3][2] = 0;
386  f->fFuncPars[ 4][0] = 2.0; f->fFuncPars[ 4][1] = f->fFuncPars[ 4][2] = 0;
387  f->fFuncPars[ 5][0] = 0.0; f->fFuncPars[ 5][1] = f->fFuncPars[ 5][2] = 0;
388  f->fFuncPars[ 6][0] = 3.0; f->fFuncPars[ 6][1] = f->fFuncPars[ 6][2] = 0;
389  f->fFuncPars[ 7][0] = 0.0; f->fFuncPars[ 7][1] = f->fFuncPars[ 7][2] = 0;
390  f->fFuncPars[ 8][0] = 4.0; f->fFuncPars[ 8][1] = f->fFuncPars[ 8][2] = 0;
391  f->fFuncPars[ 9][0] = 0.0; f->fFuncPars[ 9][1] = f->fFuncPars[ 9][2] = 0;
392  f->fFuncPars[10][0] = 9.0; f->fFuncPars[10][1] = f->fFuncPars[10][2] = 0;
393 
394  f->DoFit();
395 
396  std::vector<TFitEditor::FuncParamData_t> pars(11);
397  pars[ 0][0] = 1.01010130092504835098; pars[ 0][1] = pars[ 0][2] = 0;
398  pars[ 1][0] = 2.00223693541403102714; pars[ 1][1] = pars[ 1][2] = 0;
399  pars[ 2][0] = 0.49142981449519324011; pars[ 2][1] = pars[ 2][2] = 0;
400  pars[ 3][0] = 0.03058404503876750724; pars[ 3][1] = pars[ 3][2] = 0;
401  pars[ 4][0] = 2.98217423626109168211; pars[ 4][1] = pars[ 4][2] = 0;
402  pars[ 5][0] = 0.08458881936812148727; pars[ 5][1] = pars[ 5][2] = 0;
403  pars[ 6][0] = 3.97659923278031923743; pars[ 6][1] = pars[ 6][2] = 0;
404  pars[ 7][0] = -0.03584554242634782617; pars[ 7][1] = pars[ 7][2] = 0;
405  pars[ 8][0] = 4.96478032328273499729; pars[ 8][1] = pars[ 8][2] = 0;
406  pars[ 9][0] = 0.89557700499129078153; pars[ 9][1] = pars[ 9][2] = 0;
407  pars[10][0] = 9.92938972972320499366; pars[10][1] = pars[10][2] = 0;
408 
409 
410  return CompareFuncPars(pars);
411  }
412 };
413 
414 // Runs the basic script and pops out the fit panel. Then it will
415 // initialize the FitEditorUnitTesting class and make it run all the
416 // tests
418 {
419  FitEditorUnitTesting fUT;
420 
421  return fUT.UnitTesting();
422 }
423 
424 // The main function. It is VERY important that it is run using the
425 // TApplication.
426 int main(int argc, char** argv)
427 {
428  TApplication* theApp = 0;
429 
430  theApp = new TApplication("App",&argc,argv);
431 
432  int ret = UnitTesting();
433 
434  theApp->Run();
435  delete theApp;
436  theApp = 0;
437 
438  return ret;
439 }
int SelectEntry(TGComboBox *cb, const char *name)
Definition: UnitTesting.cxx:30
TGComboBox * fDataSet
Definition: TFitEditor.h:76
return c1
Definition: legend1.C:41
double T(double x)
Definition: ChebyshevPol.h:34
void ProcessTreeInput(TObject *objSelected, Int_t selected, TString variables, TString cuts)
virtual void Toggled(Bool_t on)
Definition: TGButton.h:136
TH1 * h
Definition: legend2.C:5
#define gROOT
Definition: TROOT.h:375
int Int_t
Definition: RtypesCore.h:41
int equals(Double_t n1, Double_t n2, double ERRORLIMIT=1.E-10)
Definition: UnitTesting.cxx:24
virtual void Terminate(Int_t status=0)
Terminate the application by call TSystem::Exit() unless application has been told to return from Run...
STL namespace.
R__EXTERN TApplication * gApplication
Definition: TApplication.h:165
TGRadioButton * fLibMinuit2
Definition: TFitEditor.h:144
TGRadioButton * fLibGSL
Definition: TFitEditor.h:146
virtual void Run(Bool_t retrn=kFALSE)
Main application eventloop. Calls system dependent eventloop via gSystem.
virtual void Select(Int_t id, Bool_t emit=kTRUE)
Make the selected item visible in the combo box window and emit signals according to the second param...
Definition: TGComboBox.cxx:443
virtual TGLBEntry * FindEntry(const char *s) const
Find entry by name.
Definition: TGComboBox.cxx:414
TGComboBox * fFuncList
Definition: TFitEditor.h:78
virtual void DoUpdate()
Easy here!
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
Int_t EntryId() const
Definition: TGListBox.h:68
TGComboBox * fMinMethodList
Definition: TFitEditor.h:148
virtual void DoClose()
Close the fit panel.
constexpr Double_t E()
Definition: TMath.h:74
The Canvas class.
Definition: TCanvas.h:31
static TFitEditor * GetInstance(TVirtualPad *pad=0, TObject *obj=0)
Static method - opens the fit panel.
Definition: TFitEditor.cxx:343
double f(double x)
double Double_t
Definition: RtypesCore.h:55
TGComboBox * fTypeFit
Definition: TFitEditor.h:77
double func(double *x, double *p)
Definition: stressTF1.cxx:213
const double ERRORLIMIT
The TH1 histogram class.
Definition: TH1.h:56
std::vector< FuncParamData_t > fFuncPars
Definition: TFitEditor.h:138
Mother of all ROOT objects.
Definition: TObject.h:37
typedef void((*Func_t)())
virtual void DoFit()
Perform a fit with current parameters&#39; settings.
int UnitTesting()
double result[121]
This class creates the ROOT Application Environment that interfaces to the windowing system eventloop...
Definition: TApplication.h:39
double exp(double)
const Bool_t kTRUE
Definition: RtypesCore.h:91
int main(int argc, char **argv)