UnitTesting.cxx

Go to the documentation of this file.
00001 #include "TFitEditor.h"
00002 
00003 #include "TApplication.h"
00004 #include "TROOT.h"
00005 #include "TBenchmark.h"
00006 
00007 #include "TCanvas.h"
00008 #include "TH1.h"
00009 
00010 #include "TPluginManager.h"
00011 #include "TError.h"
00012 
00013 #include "TGComboBox.h"
00014 
00015 #include <iostream>
00016 #include <exception>
00017 #include <stdexcept>
00018 #include <cmath>
00019 using namespace std;
00020 
00021 #include "CommonDefs.h"
00022 
00023 // Function that compares to doubles up to an error limit
00024 int equals(Double_t n1, Double_t n2, double ERRORLIMIT = 1.E-10)
00025 {
00026    return fabs( n1 - n2 ) > ERRORLIMIT * fabs(n1);
00027 }
00028 
00029 // Selects, given a TGComboBox*, the entry whose title is name.
00030 int SelectEntry(TGComboBox* cb, const char* name)
00031 {
00032    TGTextLBEntry* findEntry = static_cast<TGTextLBEntry*>( cb->FindEntry(name) );
00033    cb->Select(findEntry->EntryId());
00034 
00035    return findEntry->EntryId();
00036 }
00037 
00038 // Class to make the Unit Testing. It is important than the test
00039 // methods are inside the class as this in particular is defined as a
00040 // friend of the TFitEditor. This way, we can access the private
00041 // methods of TFitEditor to perform several types of tests.
00042 class FitEditorUnitTesting 
00043 {
00044 private:
00045    // Pointer to the current (and only one) TFitEditor opened.
00046    TFitEditor* f;
00047 
00048    // These two variables are here to redirect the standard output to
00049    // a file.
00050    int old_stdout;
00051    FILE *out;
00052 public:
00053 
00054    // Exception thrown when any of the pointers managed by the
00055    // FitEditorUnitTesting class are invalid
00056    class InvalidPointer: public std::exception 
00057    {
00058    private:
00059       const char* _exp;
00060    public:
00061       InvalidPointer(const char* exp): _exp(exp) {};
00062       const char* what() { return _exp; };
00063    };
00064 
00065    // Constructor: Receives the instance of the TFitEditor
00066    FitEditorUnitTesting() {
00067       // Redirect the stdout to a file outputUnitTesting.txt
00068       old_stdout = dup (fileno (stdout));
00069       (void) freopen ("outputUnitTesting.txt", "w", stdout);
00070       out = fdopen (old_stdout, "w");
00071 
00072       // Execute the initial script
00073       gROOT->ProcessLine(".x $ROOTSYS/tutorials/fit/FittingDemo.C+");
00074       
00075       // Get an instance of the TFitEditor
00076       TCanvas* c1 = static_cast<TCanvas*>( gROOT->FindObject("c1") );
00077       TH1*      h = static_cast<TH1*>    ( gROOT->FindObject("histo") );
00078       
00079       f = TFitEditor::GetInstance(c1,h);
00080    
00081       if ( f == 0 )
00082          throw InvalidPointer("In FitEditorUnitTesting constructor");
00083    }
00084 
00085    // The destructor will close the TFitEditor and terminate the
00086    // application. Unfortunately, the application must be run from
00087    // main, otherwise, the test will make a segmentation fault while
00088    // trying to retrieve the TFitEditor singleton. If the user wants
00089    // to play a bit with the fitpanel once the tests have finised,
00090    // then they should comment this method.
00091    ~FitEditorUnitTesting() {
00092       f->DoClose();
00093       gApplication->Terminate();
00094    }
00095 
00096    // This is a generic method to make the output of all the tests
00097    // consistent. T is a function pointer to one of the tests
00098    // function. It has been implemented through templates to permit
00099    // more test types than the originally designed.
00100    // @ str : Name of the test
00101    // @ func : Member function pointer to the real implementation of
00102    // the test.
00103    template <typename T>
00104    int MakeTest(const char* str,  T func )
00105    {
00106       fprintf(stdout, "\n***** %s *****\n", str);
00107       int status = (this->*func)();
00108 
00109       fprintf(stdout, "%s..........", str);
00110       fprintf(out, "%s..........", str);
00111       if ( status == 0 ) {
00112          fprintf(stdout, "OK\n");
00113          fprintf(out, "OK\n");
00114       }
00115       else {
00116          fprintf(stdout, "FAILED\n");
00117          fprintf(out, "FAILED\n");
00118       }
00119       return status;
00120    }
00121 
00122    // This is where all the tests are called. If the user wants to add
00123    // new tests or avoid executing one of the existing ones, it is
00124    // here where they should do it.
00125    int UnitTesting() {
00126       int result = 0;
00127 
00128       fprintf(out, "\n**STARTING TFitEditor Unit Tests**\n\n");
00129 
00130       result += MakeTest("TestHistogramFit...", &FitEditorUnitTesting::TestHistogramFit);
00131 
00132       result += MakeTest("TestGSLFit.........", &FitEditorUnitTesting::TestGSLFit);
00133 
00134       result += MakeTest("TestUpdate.........", &FitEditorUnitTesting::TestUpdate);
00135 
00136       result += MakeTest("TestGraph..........", &FitEditorUnitTesting::TestGraph);
00137 
00138       result += MakeTest("TestGraphError.....", &FitEditorUnitTesting::TestGraphError);
00139 
00140       result += MakeTest("TestGraph2D........", &FitEditorUnitTesting::TestGraph2D);
00141 
00142       result += MakeTest("TestGraph2DError...", &FitEditorUnitTesting::TestGraph2DError);
00143 
00144       result += MakeTest("TestUpdateTree.....", &FitEditorUnitTesting::TestUpdateTree);
00145 
00146       result += MakeTest("TestTree1D.........", &FitEditorUnitTesting::TestTree1D); 
00147 
00148       result += MakeTest("TestTree2D.........", &FitEditorUnitTesting::TestTree2D);
00149 
00150       result += MakeTest("TestTreeND.........", &FitEditorUnitTesting::TestTreeND); 
00151 
00152       fprintf(out, "\nRemember to also check outputUnitTesting.txt for "
00153               "more detailed information\n\n");
00154 
00155       return result;
00156    }
00157 
00158    // This is a debuggin method used to print the parameter values
00159    // stored in the fitpanel. This is useful when performing a fit, to
00160    // know against which values the test should be compare to.
00161    void PrintFuncPars()
00162    {
00163       static int counter = 0;
00164       fprintf(out, "Printing the Func Pars (%d)\n", ++counter);
00165       for ( unsigned int i = 0; i < f->fFuncPars.size(); ++i ) {
00166          fprintf(out, "%30.20f %30.20f %30.20f\n", f->fFuncPars[i][0], f->fFuncPars[i][1], f->fFuncPars[i][2]);
00167       }
00168    }
00169 
00170    // This function compares the parameters stored in the TFitEditor
00171    // with the ones passed by the test functions. Normally, if the
00172    // function return 0, it means all the parameters are equal up to a
00173    // certain limit, thus the test was succesful.
00174    int CompareFuncPars(std::vector<TFitEditor::FuncParamData_t>& pars)
00175    {
00176       int status = 0;
00177       for ( unsigned int i = 0; i < f->fFuncPars.size(); ++i ) {
00178          for ( unsigned int j = 0; j < 3; ++j) {
00179             int internalStatus = equals(pars[i][j], f->fFuncPars[i][j]);
00180             //fprintf(out, "i: %d, j: %d, e: %d\n", i, j, internalStatus);
00181             status += internalStatus;
00182          }
00183       }
00184 
00185       return status;
00186    }
00187 
00188    // From here, the implementation of the different tests. The names
00189    // of the test should be enough to know what they are testing, as
00190    // these tests are mean to be as simple as possible.
00191 
00192    int TestHistogramFit() {
00193       f->fTypeFit->Select(kFP_UFUNC, kTRUE);
00194       f->fFuncList->Select(kFP_ALTFUNC, kTRUE);
00195       f->DoFit();
00196 
00197       std::vector<TFitEditor::FuncParamData_t> pars(6);
00198       pars[0][0] = -0.86471376634076801970;  pars[0][1] = pars[0][2] = 0.0;
00199       pars[1][0] = 45.84337697060870908672;  pars[1][1] = pars[1][2] = 0.0;
00200       pars[2][0] = -13.32141783912906873866; pars[2][1] = pars[2][2] = 0.0;
00201       pars[3][0] = 13.80743352672578438955;  pars[3][1] = pars[3][2] = 0.0;
00202       pars[4][0] = 0.17230936727526752206;   pars[4][1] = pars[4][2] = 0.0;
00203       pars[5][0] = 0.98728095791845293938;   pars[5][1] = pars[5][2] = 0.0;
00204 
00205       return CompareFuncPars(pars);
00206    }
00207 
00208    int TestGSLFit() {
00209       f->fTypeFit->Select(kFP_PREVFIT, kTRUE);
00210       f->fLibGSL->Toggled(kTRUE);
00211       f->fMinMethodList->Select(kFP_BFGS2, kTRUE);
00212       f->DoFit();
00213 
00214       std::vector<TFitEditor::FuncParamData_t> pars(6);
00215       pars[0][0] = -0.86471376626133966692;  pars[0][1] = pars[0][2] = 0.0;
00216       pars[1][0] = 45.84337697042452219875;  pars[1][1] = pars[1][2] = 0.0;
00217       pars[2][0] = -13.32141783972060622432; pars[2][1] = pars[2][2] = 0.0;
00218       pars[3][0] = 13.80743352667312962012;  pars[3][1] = pars[3][2] = 0.0;
00219       pars[4][0] = 0.17230936776683797307;   pars[4][1] = pars[4][2] = 0.0;
00220       pars[5][0] = 0.98728095212777022827;   pars[5][1] = pars[5][2] = 0.0;
00221 
00222       return CompareFuncPars(pars);
00223    }
00224 
00225    int TestUpdate() {
00226       gROOT->ProcessLine(".x $ROOTSYS/tutorials/fit/ConfidenceIntervals.C+");
00227       f->DoUpdate();
00228 
00229       return 0;
00230    }
00231 
00232    int TestGraph() {
00233       SelectEntry(f->fDataSet, "TGraph::GraphNoError");
00234 
00235       f->fLibMinuit2->Toggled(kTRUE);
00236       f->fMinMethodList->Select(kFP_MIGRAD, kTRUE);
00237 
00238       f->fTypeFit->Select(kFP_UFUNC, kTRUE);
00239       SelectEntry(f->fFuncList, "fpol");
00240       f->DoFit();
00241 
00242       std::vector<TFitEditor::FuncParamData_t> pars(2);
00243       pars[0][0] = -1.07569876898511784802;  pars[0][1] = pars[0][2] = 0.0;
00244       pars[1][0] = 1.83337233651544084800;  pars[1][1] = pars[1][2] = 0.0;
00245 
00246       return CompareFuncPars(pars);
00247    }
00248 
00249     int TestGraphError() {
00250       SelectEntry(f->fDataSet, "TGraphErrors::Graph");
00251 
00252       f->fLibMinuit2->Toggled(kTRUE);
00253       f->fMinMethodList->Select(kFP_MIGRAD, kTRUE);
00254 
00255       f->fTypeFit->Select(kFP_UFUNC, kTRUE);
00256       SelectEntry(f->fFuncList, "fpol");
00257       f->DoFit();
00258 
00259       std::vector<TFitEditor::FuncParamData_t> pars(2);
00260       pars[0][0] = -1.07569876898508010044;  pars[0][1] = pars[0][2] = 0.0;
00261       pars[1][0] = 1.83337233651530895351;  pars[1][1] = pars[1][2] = 0.0;
00262 
00263       return CompareFuncPars(pars);
00264    }
00265 
00266    int TestGraph2D() {
00267       SelectEntry(f->fDataSet, "TGraph2D::Graph2DNoError");
00268 
00269       f->fLibMinuit2->Toggled(kTRUE);
00270       f->fMinMethodList->Select(kFP_MIGRAD, kTRUE);
00271 
00272       f->fTypeFit->Select(kFP_UFUNC, kTRUE);
00273       SelectEntry(f->fFuncList, "f2");
00274       
00275       // Set the parameters to the original ones in
00276       // ConfidenceIntervals.C. Otherwise it will be using those of
00277       // the last fit with fpol and will make an invalid fit.
00278       f->fFuncPars[0][0] = 0.5;
00279       f->fFuncPars[1][0] = 1.5;
00280 
00281       f->DoFit();
00282 
00283       std::vector<TFitEditor::FuncParamData_t> pars(2);
00284       pars[0][0] = 0.57910401391086918643;  pars[0][1] = pars[0][2] = 0.0;
00285       pars[1][0] = 1.73731204173242681499;  pars[1][1] = pars[1][2] = 0.0;
00286 
00287       return CompareFuncPars(pars);
00288    }
00289 
00290    int TestGraph2DError() {
00291       SelectEntry(f->fDataSet, "TGraph2DErrors::Graph2D");
00292 
00293       f->fLibMinuit2->Toggled(kTRUE);
00294       f->fMinMethodList->Select(kFP_MIGRAD, kTRUE);
00295 
00296       f->fTypeFit->Select(kFP_UFUNC, kTRUE);
00297       SelectEntry(f->fFuncList, "f2");
00298       
00299       // Set the parameters to the original ones in
00300       // ConfidenceIntervals.C. Otherwise it will be using those of
00301       // the last fit with f2 and the fit will make no sense.
00302       f->fFuncPars[0][0] = 0.5;
00303       f->fFuncPars[1][0] = 1.5;
00304 
00305       f->DoFit();
00306 
00307       std::vector<TFitEditor::FuncParamData_t> pars(2);
00308       pars[0][0] = 0.57911670684083915717;  pars[0][1] = pars[0][2] = 0.0;
00309       pars[1][0] = 1.73735012087486695442;  pars[1][1] = pars[1][2] = 0.0;
00310 
00311       return CompareFuncPars(pars);
00312    }
00313 
00314    int TestUpdateTree() {
00315       gROOT->ProcessLine(".x ~/tmp/fitpanel/createTree.C++");
00316       f->DoUpdate();
00317       return 0;
00318    }
00319 
00320    int TestTree1D() {
00321       TObject* objSelected = gROOT->FindObject("tree");
00322       if ( !objSelected ) 
00323          throw InvalidPointer("In TestUpdateTree");
00324 
00325       Int_t selected = kFP_NOSEL + 6;
00326 
00327       f->ProcessTreeInput(objSelected, selected, "x", "y>1");
00328       f->fTypeFit->Select(kFP_PRED1D, kTRUE);
00329       SelectEntry(f->fFuncList, "gausn");
00330 
00331       f->fFuncPars.resize(3);
00332       f->fFuncPars[0][0] = f->fFuncPars[0][1] = f->fFuncPars[0][2] = 1;
00333       f->fFuncPars[1][0] = 0;
00334       f->fFuncPars[2][0] = 1;
00335 
00336       f->DoFit();
00337 
00338       std::vector<TFitEditor::FuncParamData_t> pars(3);
00339       pars[0][0] = 1.0;  pars[0][1] = pars[0][2] = 1.0;
00340       pars[1][0] = 0.57616222565122654498;  pars[1][1] = pars[1][2] = 0.0;
00341       pars[2][0] = 0.90739764318839521984;  pars[2][1] = pars[2][2] = 0.0;
00342 
00343       return CompareFuncPars(pars);
00344    }
00345 
00346    int TestTree2D() {
00347       TObject* objSelected = gROOT->FindObject("tree");
00348       if ( !objSelected ) 
00349          throw InvalidPointer("In TestUpdateTree");
00350 
00351       Int_t selected = kFP_NOSEL + 6;
00352 
00353       f->ProcessTreeInput(objSelected, selected, "x:y", "");
00354       f->fTypeFit->Select(kFP_UFUNC, kTRUE);
00355       SelectEntry(f->fFuncList, "gaus2d");
00356 
00357       f->fFuncPars[0][0] = 1; f->fFuncPars[0][1] = f->fFuncPars[0][2] = 0;
00358       f->fFuncPars[1][0] = 1; f->fFuncPars[1][1] = f->fFuncPars[1][2] = 0;
00359       f->fFuncPars[2][0] = 0; f->fFuncPars[2][1] = f->fFuncPars[2][2] = 0;
00360 
00361       f->DoFit();
00362 
00363       std::vector<TFitEditor::FuncParamData_t> pars(3);
00364       pars[0][0] = 1.01009862846512765699;  pars[0][1] = pars[0][2] = 0.0;
00365       pars[1][0] = 2.00223267618221001385;  pars[1][1] = pars[1][2] = 0.0;
00366       pars[2][0] = 0.49143171847344568892;  pars[2][1] = pars[2][2] = 0.0;
00367 
00368       return CompareFuncPars(pars);
00369    }
00370 
00371    int TestTreeND() {
00372       TObject* objSelected = gROOT->FindObject("tree");
00373       if ( !objSelected ) 
00374          throw InvalidPointer("In TestUpdateTree");
00375 
00376       Int_t selected = kFP_NOSEL + 6;
00377 
00378       f->ProcessTreeInput(objSelected, selected, "x:y:z:u:v:w", "");
00379       f->fTypeFit->Select(kFP_UFUNC, kTRUE);
00380       SelectEntry(f->fFuncList, "gausND");
00381 
00382       f->fFuncPars[ 0][0] = 1.0; f->fFuncPars[ 0][1] = f->fFuncPars[ 0][2] = 0;
00383       f->fFuncPars[ 1][0] = 1.0; f->fFuncPars[ 1][1] = f->fFuncPars[ 1][2] = 0;
00384       f->fFuncPars[ 2][0] = 0.1; f->fFuncPars[ 2][1] = f->fFuncPars[ 2][2] = 0;
00385       f->fFuncPars[ 3][0] = 0.0; f->fFuncPars[ 3][1] = f->fFuncPars[ 3][2] = 0;
00386       f->fFuncPars[ 4][0] = 2.0; f->fFuncPars[ 4][1] = f->fFuncPars[ 4][2] = 0;
00387       f->fFuncPars[ 5][0] = 0.0; f->fFuncPars[ 5][1] = f->fFuncPars[ 5][2] = 0;
00388       f->fFuncPars[ 6][0] = 3.0; f->fFuncPars[ 6][1] = f->fFuncPars[ 6][2] = 0;
00389       f->fFuncPars[ 7][0] = 0.0; f->fFuncPars[ 7][1] = f->fFuncPars[ 7][2] = 0;
00390       f->fFuncPars[ 8][0] = 4.0; f->fFuncPars[ 8][1] = f->fFuncPars[ 8][2] = 0;
00391       f->fFuncPars[ 9][0] = 0.0; f->fFuncPars[ 9][1] = f->fFuncPars[ 9][2] = 0;
00392       f->fFuncPars[10][0] = 9.0; f->fFuncPars[10][1] = f->fFuncPars[10][2] = 0;
00393 
00394       f->DoFit();
00395 
00396       std::vector<TFitEditor::FuncParamData_t> pars(11);
00397       pars[ 0][0] = 1.01010130092504835098;  pars[ 0][1] = pars[ 0][2] = 0;
00398       pars[ 1][0] = 2.00223693541403102714;  pars[ 1][1] = pars[ 1][2] = 0;
00399       pars[ 2][0] = 0.49142981449519324011;  pars[ 2][1] = pars[ 2][2] = 0;
00400       pars[ 3][0] = 0.03058404503876750724;  pars[ 3][1] = pars[ 3][2] = 0;
00401       pars[ 4][0] = 2.98217423626109168211;  pars[ 4][1] = pars[ 4][2] = 0;
00402       pars[ 5][0] = 0.08458881936812148727;  pars[ 5][1] = pars[ 5][2] = 0;
00403       pars[ 6][0] = 3.97659923278031923743;  pars[ 6][1] = pars[ 6][2] = 0;
00404       pars[ 7][0] = -0.03584554242634782617; pars[ 7][1] = pars[ 7][2] = 0;
00405       pars[ 8][0] = 4.96478032328273499729;  pars[ 8][1] = pars[ 8][2] = 0;
00406       pars[ 9][0] = 0.89557700499129078153;  pars[ 9][1] = pars[ 9][2] = 0;
00407       pars[10][0] = 9.92938972972320499366;  pars[10][1] = pars[10][2] = 0;
00408 
00409 
00410       return CompareFuncPars(pars);
00411    }
00412 };
00413 
00414 // Runs the  basic script  and pops  out the fit  panel. Then  it will
00415 // initialize the  FitEditorUnitTesting class and make it  run all the
00416 // tests
00417 int UnitTesting()
00418 {
00419    FitEditorUnitTesting fUT;
00420 
00421    return fUT.UnitTesting();
00422 }
00423 
00424 // The main function. It is VERY important that it is run using the
00425 // TApplication.
00426 int main(int argc, char** argv)
00427 {
00428    TApplication* theApp = 0;
00429 
00430    theApp = new TApplication("App",&argc,argv);
00431 
00432    int ret =  UnitTesting();
00433 
00434    theApp->Run();
00435    delete theApp;
00436    theApp = 0;
00437 
00438    return ret;
00439 }

Generated on Tue Jul 5 14:19:23 2011 for ROOT_528-00b_version by  doxygen 1.5.1