1212
1313#include " TGComboBox.h"
1414
15+ #include " TF2.h"
16+ #include " TMath.h"
17+ #include " TRandom2.h"
18+ #include " TTree.h"
19+
1520#include < iostream>
1621#include < exception>
1722#include < stdexcept>
1823#include < cmath>
24+ #include < cstdio>
1925
2026#include " CommonDefs.h"
2127
28+ #ifdef WIN32
29+ #include " io.h"
30+ #else
31+ #include " unistd.h"
32+ #endif
33+
2234// Function that compares to doubles up to an error limit
23- int equals (Double_t n1, Double_t n2, double ERRORLIMIT = 1 .E-10 )
35+ int equals (Double_t n1, Double_t n2, double ERRORLIMIT = 1 .E-5 )
2436{
2537 return fabs ( n1 - n2 ) > ERRORLIMIT * fabs (n1);
2638}
@@ -34,6 +46,35 @@ int SelectEntry(TGComboBox* cb, const char* name)
3446 return findEntry->EntryId ();
3547}
3648
49+ void createTree (int n = 100 )
50+ {
51+ TTree *tree = new TTree (" tree" ," 2 var gaus tree" );
52+ double x, y, z, u, v, w;
53+ tree->Branch (" x" , &x, " x/D" );
54+ tree->Branch (" y" , &y, " y/D" );
55+ tree->Branch (" z" , &z, " z/D" );
56+ tree->Branch (" u" , &u, " u/D" );
57+ tree->Branch (" v" , &v, " v/D" );
58+ tree->Branch (" w" , &w, " w/D" );
59+ TRandom2 rndm;
60+ double origPars[13 ] = {1 ,2 ,3 ,0.5 , 0.5 , 0 , 3 , 0 , 4 , 0 , 5 , 1 , 10 };
61+ TF2 f2 (" f2" , " bigaus" , -10 , 10 ,-10 , 10 );
62+ f2.FixParameter (0 , 1 . / (2 . * TMath::Pi () * origPars[1 ] * origPars[3 ] * TMath::Sqrt (origPars[4 ]))); // constant (max-value), irrelevant
63+ f2.FixParameter (1 , origPars[0 ]); // mu_x
64+ f2.FixParameter (2 , origPars[1 ]); // sigma_x
65+ f2.FixParameter (3 , origPars[2 ]); // mu_y
66+ f2.FixParameter (4 , origPars[3 ]); // sigma_y
67+ f2.FixParameter (5 , origPars[4 ]); // rho
68+ for (Int_t i = 0 ; i < n; i++) {
69+ f2.GetRandom2 (x, y, &rndm);
70+ z = rndm.Gaus (origPars[5 ],origPars[6 ]);
71+ u = rndm.Gaus (origPars[7 ],origPars[8 ]);
72+ v = rndm.Gaus (origPars[9 ],origPars[10 ]);
73+ w = rndm.Gaus (origPars[11 ],origPars[12 ]);
74+ tree->Fill ();
75+ }
76+ }
77+
3778// Class to make the Unit Testing. It is important than the test
3879// methods are inside the class as this in particular is defined as a
3980// friend of the TFitEditor. This way, we can access the private
@@ -58,22 +99,37 @@ class FitEditorUnitTesting
5899 const char * _exp;
59100 public:
60101 InvalidPointer (const char * exp): _exp(exp) {};
61- const char * what () { return _exp; };
102+ const char * what () const noexcept override { return _exp; };
62103 };
63104
64105 // Constructor: Receives the instance of the TFitEditor
65106 FitEditorUnitTesting () {
66107 // Redirect the stdout to a file outputUnitTesting.txt
108+ #ifdef WIN32
109+ old_stdout = _dup (_fileno (stdout));
110+ #else
67111 old_stdout = dup (fileno (stdout));
68- (void ) freopen (" outputUnitTesting.txt" , " w" , stdout);
112+ #endif
113+ auto res = freopen (" outputUnitTesting.txt" , " w" , stdout);
114+ if (!res) {
115+ throw InvalidPointer (" In FitEditorUnitTesting constructor cannot freopen" );
116+ }
117+ #ifdef WIN32
118+ out = _fdopen (old_stdout, " w" );
119+ #else
69120 out = fdopen (old_stdout, " w" );
121+ #endif
70122
71123 // Execute the initial script
72- gROOT ->ProcessLine (" .x $ROOTSYS/tutorials/fit/FittingDemo.C+" );
124+ TString scriptLine = TString (" .x " ) + TROOT::GetTutorialDir () + " /math/fit/FittingDemo.C+" ;
125+ gROOT ->ProcessLine (scriptLine.Data ());
73126
74127 // Get an instance of the TFitEditor
75128 TCanvas* c1 = static_cast <TCanvas*>( gROOT ->FindObject (" c1" ) );
76129 TH1* h = static_cast <TH1*> ( gROOT ->FindObject (" histo" ) );
130+ if (!c1 || !h) {
131+ throw InvalidPointer (" In c1 or h initialization" );
132+ }
77133
78134 f = TFitEditor::GetInstance (c1,h);
79135
@@ -176,7 +232,9 @@ class FitEditorUnitTesting
176232 for ( unsigned int i = 0 ; i < f->fFuncPars .size (); ++i ) {
177233 for ( unsigned int j = 0 ; j < 3 ; ++j) {
178234 int internalStatus = equals (pars[i][j], f->fFuncPars [i][j]);
179- // fprintf(out, "i: %d, j: %d, e: %d\n", i, j, internalStatus);
235+ if (internalStatus != 0 ) {
236+ fprintf (out, " i: %d, j: %d, e: %d, diff %g\n " , i, j, internalStatus, TMath::Abs (pars[i][j] - f->fFuncPars [i][j]));
237+ }
180238 status += internalStatus;
181239 }
182240 }
@@ -186,7 +244,7 @@ class FitEditorUnitTesting
186244
187245 // From here, the implementation of the different tests. The names
188246 // of the test should be enough to know what they are testing, as
189- // these tests are mean to be as simple as possible.
247+ // these tests are meant to be as simple as possible.
190248
191249 int TestHistogramFit () {
192250 f->fTypeFit ->Select (kFP_UFUNC , kTRUE );
@@ -222,7 +280,8 @@ class FitEditorUnitTesting
222280 }
223281
224282 int TestUpdate () {
225- gROOT ->ProcessLine (" .x $ROOTSYS/tutorials/fit/ConfidenceIntervals.C+" );
283+ TString scriptLine = TString (" .x " ) + TROOT::GetTutorialsDir () + " /math/fit/ConfidenceIntervals.C+" ;
284+ gROOT ->ProcessLine (scriptLine.Data ());
226285 f->DoUpdate ();
227286
228287 return 0 ;
@@ -311,7 +370,7 @@ class FitEditorUnitTesting
311370 }
312371
313372 int TestUpdateTree () {
314- gROOT -> ProcessLine ( " .x ~/tmp/fitpanel/ createTree.C++ " );
373+ createTree ( );
315374 f->DoUpdate ();
316375 return 0 ;
317376 }
@@ -326,11 +385,10 @@ class FitEditorUnitTesting
326385 f->ProcessTreeInput (objSelected, selected, " x" , " y>1" );
327386 f->fTypeFit ->Select (kFP_PRED1D , kTRUE );
328387 SelectEntry (f->fFuncList , " gausn" );
329-
330388 f->fFuncPars .resize (3 );
331389 f->fFuncPars [0 ][0 ] = f->fFuncPars [0 ][1 ] = f->fFuncPars [0 ][2 ] = 1 ;
332- f->fFuncPars [1 ][0 ] = 0 ;
333- f->fFuncPars [2 ][0 ] = 1 ;
390+ f->fFuncPars [1 ][0 ] = 0 ; f-> fFuncPars [ 1 ][ 1 ] = f-> fFuncPars [ 1 ][ 2 ] = 0 ;
391+ f->fFuncPars [2 ][0 ] = 1 ; f-> fFuncPars [ 2 ][ 1 ] = f-> fFuncPars [ 2 ][ 2 ] = 0 ;
334392
335393 f->DoFit ();
336394
0 commit comments