stressGoFTest.cxx

Go to the documentation of this file.
00001 #include "TBenchmark.h"
00002 #include "Math/GoFTest.h"
00003 #include "Math/Functor.h"
00004 #include "TROOT.h"
00005 #include "TSystem.h"
00006 #include "TStopwatch.h"
00007 
00008 #include "Math/GSLRndmEngines.h"
00009 #if not defined(__CINT__)
00010 #include "Math/Random.h"
00011 #endif
00012 
00013 #include "TRandom3.h"
00014 
00015 #include <iostream>
00016 
00017 #include <cassert>
00018 
00019 /*N.B.: The tests' expected values (expectedDn and expectedA2) were computed on Pcphsft54.cern.ch i386 GNU/Linux computer (slc4_ia32_gcc34)
00020 */
00021 struct GoFTStress {
00022 
00023    static enum EDebugLevelTypes {
00024       kNoDebug,       // no test results printing
00025       kBasicDebug,    // prints either "OK" or "FAIL" test results
00026       kStandardDebug, // prints summarized test results
00027    } fgDebugLevel;
00028    
00029    Int_t RunTests() {
00030       Int_t result = 0;
00031       result += UnitTest1();
00032       result += UnitTest2();
00033       result += UnitTest3();
00034       result += UnitTest4();
00035       result += UnitTest5();
00036       result += UnitTest6();
00037       result += UnitTest7();
00038       return result;
00039    }
00040       
00041    void PrintBenchmark() {
00042       if (fgDebugLevel == kNoDebug) {
00043          return;
00044       }
00045          
00046          //Print table with results
00047       Bool_t UNIX = strcmp(gSystem->GetName(), "Unix") == 0;
00048       printf("******************************************************************\n");
00049       if (UNIX) {
00050          FILE *fp = gSystem->OpenPipe("uname -a", "r");
00051          Char_t line[60];
00052          fgets(line,60,fp); line[59] = 0;
00053          printf("*  SYS: %s\n",line);
00054          gSystem->ClosePipe(fp);
00055       } else {
00056          const Char_t *os = gSystem->Getenv("OS");
00057          if (!os) {
00058          printf("*  SYS: Windows 95\n");
00059          } else {
00060          printf("*  SYS: %s %s \n",os,gSystem->Getenv("PROCESSOR_IDENTIFIER"));
00061          }
00062       }
00063          
00064       printf("*****************************************************************************************\n");
00065       gBenchmark->Print("GoFTestStress");
00066 #ifdef __CINT__
00067       Double_t reftime = 0.02 ; // slc4rabacal interpreted (CPU time taken to run complete tests with ACLiC)
00068 #else
00069       Double_t reftime = 0.04; // slc4rabacal compiled (CPU time taken to run complete tests)
00070 #endif
00071       
00072       Double_t rootmarks = 800. * reftime / gBenchmark->GetCpuTime("GoFTestStress");
00073       
00074       printf("*****************************************************************************************\n");
00075       printf("*  ROOTMARKS = %6.1f   *  Root%-8s  %d/%d\n", rootmarks, gROOT->GetVersion(),
00076             gROOT->GetVersionDate(),gROOT->GetVersionTime());
00077       printf("*****************************************************************************************\n");
00078    }
00079    
00080    private:  
00081    
00082    Int_t UnitTest1() {
00083       std::cout << "UNIT TEST 1" << std::endl;
00084       
00085       UInt_t nsmps = 2;
00086       const UInt_t smpSize1 = 71;
00087       const UInt_t smpSize2 = 135;
00088    /*
00089       Data set adapted from the paper (1)
00090       "K-Sample Anderson-Darling Tests of Fit for continuous and discrete cases" by Scholz and Stephens
00091    */
00092       const Double_t smp1[smpSize1] = {194, 15, 41, 29, 33, 181, 413, 14, 58, 37, 100, 65, 9, 169, 447, 18, 4, 36, 201, 118, 34, 31, 18, 18, 67, 57, 62, 7, 22, 34, 90, 10, 60, 186, 61, 49, 14, 24, 56, 20, 79, 84, 44, 59, 29, 118, 25, 156, 310, 76, 26, 44, 23, 62, 130, 208, 70, 101, 208, 74, 57, 48, 29, 502, 12, 70, 21, 29, 386, 59, 27};
00093    
00094       const Double_t smp2[smpSize2] = {55, 320, 56, 104, 220, 239, 47, 246, 176, 182, 33, 23, 261, 87, 7, 120, 14, 62, 47, 225, 71, 246, 21, 42, 20, 5, 12, 120, 11, 3, 14, 71, 11, 14, 11, 16, 90, 1, 16, 52, 95, 97, 51, 11, 4, 141, 18, 142, 68, 77, 80, 1, 16, 106, 206, 82, 54, 31, 216, 46, 111, 39, 63, 18, 191, 18, 163, 24, 50, 44, 102, 72, 22, 39, 3, 15, 197, 188, 79, 88, 46, 5, 5, 36, 22, 139, 210, 97, 30, 23, 13, 14, 359, 9, 12, 270, 603, 3, 104, 2, 438, 50, 254, 5, 283, 35, 12, 487, 18, 100, 7, 98, 5, 85, 91, 43, 230, 3, 130, 102, 209, 14, 57, 54, 32, 67, 59, 134, 152, 27, 14, 230, 66, 61, 34};
00095    
00096       ROOT::Math::GoFTest* goft = new ROOT::Math::GoFTest( smpSize1, smp1, smpSize2, smp2 );
00097       
00098       Double_t A2 = goft->AndersonDarling2SamplesTest("t"); // standartized A2_akN
00099    //     Double_t pvalueAD = goft->AndersonDarling2SamplesTest();
00100       Double_t pvalueAD = (*goft)(ROOT::Math::GoFTest::kAD2s);
00101    
00102       Double_t expectedA2_akN = 1.58334 ; // A2_akN in (1)
00103    
00104       Double_t sigmaN = 0.754539;    // sigmaN in (1)
00105    
00106       Double_t zScore = 0.773108;    // zScore in (1)
00107    
00108       Int_t result = PrintResultAD2Samples(nsmps, A2, expectedA2_akN, sigmaN, zScore, pvalueAD);
00109    
00110    //     Double_t Dn = goft->KolmogorovSmirnov2SamplesTest("t"); // standartized A2_akN
00111       Double_t Dn = (*goft)(ROOT::Math::GoFTest::kKS2s, "t");
00112       Double_t pvalueKS = goft->KolmogorovSmirnov2SamplesTest();
00113    
00114       Double_t expectedDn = 0.139176;
00115    
00116       result += PrintResultKS(nsmps, Dn, expectedDn, pvalueKS);
00117    
00118       delete goft;
00119       return result;
00120    }
00121    
00122    Int_t UnitTest2() {
00123       std::cout << "UNIT TEST 2" << std::endl;
00124       
00125       const UInt_t nsmps = 2;
00126       const UInt_t smpSize = 16;
00127    /*
00128       Data sets adapted from the paper (1)
00129       "K-Sample Anderson-Darling Tests of Fit for continuous and discrete cases" by Scholz and Stephens
00130    */
00131       const Double_t smp1[smpSize] = {38.7, 41.5, 43.8, 44.5, 45.5, 46.0, 47.7, 58.0, 39.2, 39.3, 39.7, 41.4, 41.8, 42.9, 43.3, 45.8};
00132       const Double_t smp2[smpSize] = {34.0, 35.0, 39.0, 40.0, 43.0, 43.0, 44.0, 45.0, 34.0, 34.8, 34.8, 35.4, 37.2, 37.8, 41.2, 42.8};
00133    
00134       ROOT::Math::GoFTest* goft = new ROOT::Math::GoFTest( smpSize, smp1, smpSize, smp2 );
00135    
00136    //     Double_t A2 = goft->AndersonDarling2SamplesTest("t"); // standartized A2_akN
00137       Double_t A2 = (*goft)(ROOT::Math::GoFTest::kAD2s, "t");
00138       Double_t pvalueAD = goft->AndersonDarling2SamplesTest();
00139    
00140       Double_t expectedA2_akN = 4.5735; // unstandardized A2_akN in (1)
00141    
00142       Double_t sigmaN = 0.719388;   // sigmaN in (1)
00143    
00144       Double_t zScore = 4.96748;    // zScore in (1)
00145    
00146       Int_t result = PrintResultAD2Samples(nsmps, A2, expectedA2_akN, sigmaN, zScore, pvalueAD);
00147    
00148       Double_t Dn = goft->KolmogorovSmirnov2SamplesTest("t"); // standartized A2_akN
00149    //     Double_t pvalueKS = goft->KolmogorovSmirnov2SamplesTest();
00150       Double_t pvalueKS = (*goft)(ROOT::Math::GoFTest::kKS2s);
00151    
00152       Double_t expectedDn = 0.5;
00153    
00154       result += PrintResultKS(nsmps, Dn, expectedDn, pvalueKS);
00155    
00156       delete goft;
00157       return result;
00158    }
00159    
00160    Int_t UnitTest3() {
00161       std::cout << "UNIT TEST 3" << std::endl;
00162       
00163       UInt_t nEvents = 1000;
00164       UInt_t nsmps = 1;
00165          
00166       ROOT::Math::Random<ROOT::Math::GSLRngMT> r;
00167    
00168       Double_t* sample = new Double_t[nEvents];
00169    
00170       for (UInt_t i = 0; i < nEvents; ++i) { 
00171          Double_t data = r.LogNormal(5.0, 2.0);
00172          sample[i] = data;
00173          assert(sample[i] == data);
00174       }
00175       
00176       ROOT::Math::GoFTest* goft = new ROOT::Math::GoFTest(nEvents, sample, ROOT::Math::GoFTest::kLogNormal);
00177       
00178       if (GoFTStress::fgDebugLevel == GoFTStress::kStandardDebug)
00179          std::cout << "LogNormal fitting" << std::endl;
00180       
00181    //     Double_t A2 = goft->AndersonDarlingTest("t");
00182       Double_t A2 = goft->operator()(ROOT::Math::GoFTest::kAD, "t");
00183       Double_t pvalueAD = goft->AndersonDarlingTest();
00184    
00185       Double_t expectedA2 = 0.422771;
00186    
00187       Int_t result = PrintResultAD1Sample(A2, expectedA2, pvalueAD);
00188    
00189       Double_t Dn = goft->KolmogorovSmirnovTest("t");
00190    //     Double_t pvalueKS = goft->KolmogorovSmirnovTest();
00191       Double_t pvalueKS = goft->operator()(ROOT::Math::GoFTest::kKS);
00192    
00193       Double_t expectedDn = 0.0204916;
00194    
00195       result += PrintResultKS(nsmps, Dn, expectedDn, pvalueKS);
00196    
00197       delete goft;
00198       return result;
00199    }
00200    
00201    Int_t UnitTest4() {
00202       std::cout << "UNIT TEST 4" << std::endl;
00203       
00204       UInt_t nEvents = 1000;
00205       UInt_t nsmps = 1;
00206       
00207       TRandom3 r;
00208    
00209       Double_t* sample = new Double_t[nEvents];
00210    
00211       for (UInt_t i = 0; i < nEvents; ++i) { 
00212          Double_t data = r.Exp(1.54);
00213          sample[i] = data;
00214          assert(sample[i] == data);
00215       }
00216       
00217       ROOT::Math::GoFTest* goft = new ROOT::Math::GoFTest(nEvents, sample, ROOT::Math::GoFTest::kExponential);
00218    
00219       if (GoFTStress::fgDebugLevel == GoFTStress::kStandardDebug)
00220          std::cout << "**Exponential fitting**" << std::endl;
00221       
00222       Double_t A2 = goft->AndersonDarlingTest("t");
00223    //     Double_t pvalueAD = goft->AndersonDarlingTest();
00224       Double_t pvalueAD = goft->operator()();
00225    
00226       Double_t expectedA2 = 0.521153;
00227    
00228       Int_t result = PrintResultAD1Sample(A2, expectedA2, pvalueAD);
00229    
00230    //     Double_t Dn = goft->KolmogorovSmirnovTest("t");
00231       Double_t Dn = goft->operator()(ROOT::Math::GoFTest::kKS, "t");
00232       Double_t pvalueKS = goft->KolmogorovSmirnovTest();
00233    
00234       Double_t expectedDn = 0.0218148;
00235    
00236       result += PrintResultKS(nsmps, Dn, expectedDn, pvalueKS);
00237    
00238       delete goft;
00239       return result;
00240    }
00241    
00242    Int_t UnitTest5() {
00243       std::cout << "UNIT TEST 5" << std::endl;
00244       
00245       UInt_t nEvents = 1000;
00246       UInt_t nsmps = 1;
00247       
00248       TRandom3 r;
00249    
00250       Double_t* sample = new Double_t[nEvents];
00251    
00252       for (UInt_t i = 0; i < nEvents; ++i) { 
00253          Double_t data = r.Gaus(300, 50);
00254          sample[i] = data;
00255          assert(sample[i] == data);
00256       }
00257       
00258       ROOT::Math::GoFTest* goft = new ROOT::Math::GoFTest(nEvents, sample);
00259       goft->SetDistribution(ROOT::Math::GoFTest::kGaussian);
00260    
00261       if (GoFTStress::fgDebugLevel == GoFTStress::kStandardDebug)
00262          std::cout << "**Gaussian fitting**" << std::endl;
00263       
00264       Double_t A2 =  goft->AndersonDarlingTest("t");
00265       Double_t pvalueAD = goft->AndersonDarlingTest();
00266    
00267       Double_t expectedA2 = 0.441755;
00268    
00269       Int_t result = PrintResultAD1Sample(A2, expectedA2, pvalueAD);
00270    
00271       Double_t Dn = goft->KolmogorovSmirnovTest("t");
00272       Double_t pvalueKS = goft->KolmogorovSmirnovTest();
00273    
00274       Double_t expectedDn = 0.0282508;
00275    
00276       result += PrintResultKS(nsmps, Dn, expectedDn, pvalueKS);
00277       
00278       delete goft;
00279       return result;
00280    }
00281    
00282    Int_t UnitTest6() {
00283       std::cout << "UNIT TEST 6" << std::endl;
00284       UInt_t nEvents = 1000;
00285       UInt_t nsmps = 1;
00286       
00287       TRandom3 r;
00288    
00289       Double_t* sample = new Double_t[nEvents];
00290    
00291       for (UInt_t i = 0; i < nEvents; ++i) { 
00292          Double_t data = r.Landau();
00293          sample[i] = data;
00294          assert(sample[i] == data);
00295       }
00296       
00297       ROOT::Math::Functor1D userCdf(&TMath::LandauI);
00298       ROOT::Math::GoFTest* goft = new ROOT::Math::GoFTest(nEvents, sample, userCdf, ROOT::Math::GoFTest::kCDF);
00299          
00300       if (GoFTStress::fgDebugLevel == GoFTStress::kStandardDebug)
00301          std::cout << "**Landau fitting**" << std::endl;
00302       
00303       Double_t A2 =  goft->AndersonDarlingTest("t");
00304       Double_t pvalueAD = goft->AndersonDarlingTest();
00305    
00306       Double_t expectedA2 = 0.544658;
00307    
00308       Int_t result = PrintResultAD1Sample(A2, expectedA2, pvalueAD);
00309       
00310       Double_t Dn = goft->KolmogorovSmirnovTest("t");
00311       Double_t pvalueKS = goft->KolmogorovSmirnovTest();
00312    
00313       Double_t expectedDn = 0.0203432;
00314    
00315       result += PrintResultKS(nsmps, Dn, expectedDn, pvalueKS);
00316       
00317       delete goft;
00318       return result;
00319    }
00320    
00321    Int_t UnitTest7() {
00322       std::cout << "UNIT TEST 7" << std::endl;
00323       
00324       UInt_t nEvents = 1000;
00325       UInt_t nsmps = 1;
00326       
00327       TRandom3 r;
00328    
00329       Double_t* sample = new Double_t[nEvents];
00330    
00331       for (UInt_t i = 0; i < nEvents; ++i) { 
00332          Double_t data = r.Landau();
00333          sample[i] = data;
00334       }
00335       
00336       // need to specify min and max otherwise pdf does not converge
00337       ROOT::Math::GoFTest* goft = new ROOT::Math::GoFTest(nEvents, sample); 
00338 
00339       ROOT::Math::Functor1D userPdf(&TMath::Landau);
00340       // need to use a reasanble range for the Landau 
00341       // but must be bigger than xmin and xmax 
00342       double xmin = 3*TMath::MinElement(nEvents, sample);
00343       double xmax = 3*TMath::MaxElement(nEvents, sample);
00344          
00345       if (GoFTStress::fgDebugLevel == GoFTStress::kStandardDebug)
00346          std::cout << "**Landau fitting**" << " in [ " << xmin << " , " << xmax << " ]" << std::endl;
00347 
00348       goft->SetUserDistribution(userPdf,ROOT::Math::GoFTest::kPDF, xmin, xmax);
00349       
00350       Double_t A2 =  goft->AndersonDarlingTest("t");
00351       Double_t pvalueAD = goft->AndersonDarlingTest();
00352    
00353       Double_t expectedA2 =  0.544658;
00354    
00355       // use larger tolerance due to truncation error of Landau
00356       Int_t result = PrintResultAD1Sample(A2, expectedA2, pvalueAD,0.002);
00357       
00358       Double_t Dn = goft->KolmogorovSmirnovTest("t");
00359       Double_t pvalueKS = goft->KolmogorovSmirnovTest();
00360    
00361       Double_t expectedDn = 0.0203432;
00362    
00363       result += PrintResultKS(nsmps, Dn, expectedDn, pvalueKS,0.001);
00364       
00365       delete goft;
00366       return result;
00367    }
00368    
00369    Int_t PrintResultAD2Samples(UInt_t nsmps, Double_t A2, Double_t expectedA2_akN, Double_t sigmaN, Double_t zScore, Double_t pvalue, Double_t limit = 0.0001) {
00370    
00371       Double_t A2_akN = A2  * sigmaN + (nsmps - 1);
00372    
00373       if (GoFTStress::fgDebugLevel == GoFTStress::kStandardDebug) {
00374          std::cout << "Anderson-Darling 2-Samples Test" << std::endl;
00375    
00376          std::cout << "pvalue = " << pvalue << std::endl;
00377    
00378          std::cout << "zScore = " << zScore << std::endl;
00379       
00380          std::cout << "Expected A2 value = " << A2 << std::endl;
00381       
00382          std::cout << "A2_akN = " << A2_akN << std::endl;
00383       
00384          std::cout << "Expected A2_akN value = " << expectedA2_akN << std::endl;
00385       }
00386       if (TMath::Abs(A2_akN - expectedA2_akN) < limit * expectedA2_akN || TMath::Abs(A2 - zScore) < limit * zScore) {
00387          if (GoFTStress::fgDebugLevel >= GoFTStress::kBasicDebug) 
00388          std::cout << "+++++++ TEST OK +++++++ \n" << std::endl;
00389          return EXIT_SUCCESS;
00390       } else {
00391          if (GoFTStress::fgDebugLevel >= GoFTStress::kBasicDebug) 
00392          std::cout << "------- TEST FAIL ------- \n" << std::endl;
00393          return EXIT_FAILURE;
00394       }
00395    }
00396    
00397    Int_t PrintResultAD1Sample(Double_t A2, Double_t expectedA2, Double_t pvalue, Double_t limit = 0.0001) {
00398       
00399       if (GoFTStress::fgDebugLevel == GoFTStress::kStandardDebug) {  
00400          std::cout << "Anderson-Darling 1-Sample Test" << std::endl;
00401          
00402          std::cout << "pvalue = " << pvalue << std::endl;
00403       
00404          std::cout << "A2 value = " << A2 << std::endl;
00405       
00406          std::cout << "Expected A2 value = " << expectedA2 << std::endl;
00407       }
00408       if (TMath::Abs(A2 - expectedA2) < limit * expectedA2) {
00409          if (GoFTStress::fgDebugLevel >= GoFTStress::kBasicDebug) 
00410          std::cout << "+++++++ TEST OK +++++++ \n" << std::endl;
00411          return EXIT_SUCCESS;
00412       } else {
00413          if (GoFTStress::fgDebugLevel >= GoFTStress::kBasicDebug) 
00414          std::cout << "------- TEST FAIL ------- \n" << std::endl;
00415          return EXIT_FAILURE;
00416       }
00417    }
00418    
00419    Int_t PrintResultKS(UInt_t nsmps, Double_t Dn, Double_t expectedDn, Double_t pvalue, Double_t limit = 0.0001) {
00420    
00421       if (GoFTStress::fgDebugLevel == GoFTStress::kStandardDebug) {
00422          std::cout << "Kolmogorov-Smirnov "<< nsmps << "-Samples Test" << std::endl;
00423          
00424          std::cout << "pvalue = " << pvalue << std::endl;
00425       
00426          std::cout << "Dn value = " << Dn << std::endl;
00427       
00428          std::cout << "Expected Dn value = " << expectedDn << std::endl;
00429       }
00430       if (TMath::Abs(Dn - expectedDn) < limit * expectedDn) {
00431          if (GoFTStress::fgDebugLevel >= GoFTStress::kBasicDebug)
00432          std::cout << "+++++++ TEST OK +++++++ \n" << std::endl;
00433          return EXIT_SUCCESS;
00434       } else {
00435          if (GoFTStress::fgDebugLevel >= GoFTStress::kBasicDebug) 
00436          std::cout << "------- TEST FAIL ------- \n" << std::endl;
00437          return EXIT_FAILURE;
00438       }
00439    }
00440 };
00441    
00442 #ifdef __MAKECINT__
00443 #pragma link C++ class GoFTStress-;
00444 #endif
00445    
00446 GoFTStress::EDebugLevelTypes GoFTStress::fgDebugLevel;
00447 
00448 Int_t RunTests(Int_t argc, Char_t* argv[]) {
00449    Int_t result = 0;
00450    Bool_t validOption(kFALSE);
00451    
00452    if (argc == 1) {
00453       GoFTStress::fgDebugLevel = GoFTStress::kBasicDebug;
00454       validOption = kTRUE;
00455    } else if (argc == 3 && strcmp(argv[1], "--o") == 0) {
00456       if (strcmp(argv[2], "0") == 0 || strcmp(argv[2], "no-debug") == 0) {
00457          GoFTStress::fgDebugLevel = GoFTStress::kNoDebug;
00458          validOption = kTRUE;
00459       } else if (strcmp(argv[2], "1") == 0 || strcmp(argv[2], "basic-debug") == 0) {
00460          GoFTStress::fgDebugLevel = GoFTStress::kBasicDebug;
00461          validOption = kTRUE;
00462          std::cout << "Debug level: basic." << std::endl;
00463       } else if (strcmp(argv[2], "2") == 0 || strcmp(argv[2], "standard-debug") == 0) {
00464          GoFTStress::fgDebugLevel = GoFTStress::kStandardDebug;
00465          validOption = kTRUE;
00466          std::cout << "Debug level: standard." << std::endl;
00467       } else if (strcmp(argv[2], "help") == 0) {
00468          std::cout << "Showing help: " << std::endl;
00469       }
00470    }
00471    
00472    if (!validOption) {
00473       std::cout << "Please type just one of the following debug levels in either formats preceded by \"--o\":" << std::endl;
00474       std::cout << "a) no-debug(0) [no test results printing]" << std::endl;
00475       std::cout << "b) basic-debug(1) [prints either \"OK\" or \"FAIL\" test results]" << std::endl;
00476       std::cout << "c) standard-debug(2) [prints summarized test results]" << std::endl;
00477       return 0;
00478    }
00479    
00480    if (GoFTStress::fgDebugLevel >= GoFTStress::kBasicDebug) { 
00481       std::cout << "*****************************************************************************************" << std::endl;
00482       std::cout << "*                           Goodness of Fit Test STRESS suite                           *" <<std::endl;
00483       std::cout << "*****************************************************************************************" << std::endl;
00484 }
00485 
00486    gBenchmark = new TBenchmark();
00487    
00488    TStopwatch timer;
00489    timer.Start();
00490    
00491    gBenchmark->Start("GoFTestStress");
00492    
00493    GoFTStress* goftStressTest = new GoFTStress;
00494    
00495    result = goftStressTest->RunTests();
00496    
00497    gBenchmark->Stop("GoFTestStress");
00498    
00499    goftStressTest->PrintBenchmark();
00500    
00501    delete goftStressTest;
00502    
00503    delete gBenchmark;
00504    
00505    return result;
00506 }
00507 
00508 Int_t stressGoFTest(Int_t argc = 1 , Char_t* argv[] = 0) {
00509    return RunTests(argc, argv);
00510 }
00511    
00512 #if not defined(__CINT__) && not defined(__MAKECINT__)
00513 Int_t main(Int_t argc, Char_t* argv[]) {
00514    return RunTests(argc, argv);
00515 }
00516 #endif

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