// @(#)root/tmva $Id$   
// Author: Andreas Hoecker, Joerg Stelzer, Helge Voss

/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : Timer                                                                 *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Implementation (see header file for description)                          *
 *                                                                                *
 * Authors (alphabetical):                                                        *
 *      Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland              *
 *      Joerg Stelzer   <Joerg.Stelzer@cern.ch>  - CERN, Switzerland              *
 *      Helge Voss      <Helge.Voss@cern.ch>     - MPI-K Heidelberg, Germany      *
 *      Kai Voss        <Kai.Voss@cern.ch>       - U. of Victoria, Canada         *
 *                                                                                *
 * Copyright (c) 2005:                                                            *
 *      CERN, Switzerland                                                         * 
 *      MPI-K Heidelberg, Germany                                                 * 
 *                                                                                *
 * Redistribution and use in source and binary forms, with or without             *
 * modification, are permitted according to the terms listed in LICENSE           *
 * (http://tmva.sourceforge.net/LICENSE)                                          *
 **********************************************************************************/

//_______________________________________________________________________
//                                                                      
// Timing information for training and evaluation of MVA methods  
// 
// Usage:
//
//    TMVA::Timer timer( Nloops, "MyClassName" ); 
//    for (Int_t i=0; i<Nloops; i++) {
//      ... // some code
//
//      // now, print progress bar:
//      timer.DrawProgressBar( i );
//
//      // **OR** text output of left time (never both !)
//      fLogger << " time left: " << timer.GetLeftTime( i ) << Endl;
//
//    } 
//    fLogger << "MyClassName" << ": elapsed time: " << timer.GetElapsedTime() 
//            << Endl;    
//
// Remark: in batch mode, the progress bar is quite ugly; you may 
//         want to use the text output then
//_______________________________________________________________________

#include <iomanip>

#include "TMVA/Timer.h"

#ifndef ROOT_TMVA_Config
#include "TMVA/Config.h"
#endif
#ifndef ROOT_TMVA_Tools
#include "TMVA/Tools.h"
#endif
#ifndef ROOT_TMVA_MsgLogger
#include "TMVA/MsgLogger.h"
#endif

const TString TMVA::Timer::fgClassName = "Timer";
const Int_t   TMVA::Timer::fgNbins     = 24;  

ClassImp(TMVA::Timer)

//_______________________________________________________________________
TMVA::Timer::Timer( const char* prefix, Bool_t colourfulOutput )
   : fNcounts        ( 0 ),
     fPrefix         ( strcmp(prefix,"")==0?Timer::fgClassName:TString(prefix) ),
     fColourfulOutput( colourfulOutput ),
     fLogger         ( new MsgLogger( fPrefix.Data() ) )
{
   // constructor
   Reset();
}

//_______________________________________________________________________
TMVA::Timer::Timer( Int_t ncounts, const char* prefix, Bool_t colourfulOutput  )
   : fNcounts        ( ncounts ),
     fPrefix         ( strcmp(prefix,"")==0?Timer::fgClassName:TString(prefix) ),
     fColourfulOutput( colourfulOutput ),
     fLogger         ( new MsgLogger( fPrefix.Data() ) )
{
   // standard constructor: ncounts gives the total number of counts that 
   // the loop will iterate through. At each call of the timer, the current
   // number of counts is provided by the user, so that the timer can obtain
   // the due time from linearly interpolating the spent time.
   Reset();
}

//_______________________________________________________________________
TMVA::Timer::~Timer( void )
{
   // destructor
   delete fLogger;
}

void TMVA::Timer::Init( Int_t ncounts )
{
   // timer initialisation
   fNcounts = ncounts;  
   Reset();
}

//_______________________________________________________________________
void TMVA::Timer::Reset( void )
{
   // resets timer
   TStopwatch::Start( kTRUE );
}

//_______________________________________________________________________
Double_t TMVA::Timer::ElapsedSeconds( void ) 
{
   // computes elapsed tim in seconds
   Double_t rt = TStopwatch::RealTime(); TStopwatch::Start( kFALSE );
   return rt;
}
//_______________________________________________________________________

TString TMVA::Timer::GetElapsedTime( Bool_t Scientific ) 
{
   // returns pretty string with elaplsed time
   return SecToText( ElapsedSeconds(), Scientific );
}

//_______________________________________________________________________
TString TMVA::Timer::GetLeftTime( Int_t icounts ) 
{
   // returns pretty string with time left
   Double_t leftTime = ( icounts <= 0 ? -1 :
                         icounts > fNcounts ? -1 :
                         Double_t(fNcounts - icounts)/Double_t(icounts)*ElapsedSeconds() );

   return SecToText( leftTime, kFALSE );
}

//_______________________________________________________________________
void TMVA::Timer::DrawProgressBar() 
{
   // draws the progressbar
   fNcounts++;
   if (fNcounts == 1) {
      std::clog << fLogger->GetPrintedSource();
      std::clog << "Please wait ";
   }

   std::clog << "." << std::flush;
}

//_______________________________________________________________________
void TMVA::Timer::DrawProgressBar( TString theString ) 
{
   // draws a string in the progress bar
   std::clog << fLogger->GetPrintedSource();

   std::clog << gTools().Color("white_on_green") << gTools().Color("dyellow") << "[" << gTools().Color("reset");

   std::clog << gTools().Color("white_on_green") << gTools().Color("dyellow") << theString << gTools().Color("reset");

   std::clog << gTools().Color("white_on_green") << gTools().Color("dyellow") << "]" << gTools().Color("reset");

   std::clog << "\r" << std::flush; 
}

//_______________________________________________________________________
void TMVA::Timer::DrawProgressBar( Int_t icounts, const TString& comment  ) 
{
   // draws progress bar in color or B&W
   // caution: 

   if (!gConfig().DrawProgressBar()) return;

   // sanity check:
   if (icounts > fNcounts-1) icounts = fNcounts-1;
   if (icounts < 0         ) icounts = 0;
   Int_t ic = Int_t(Float_t(icounts)/Float_t(fNcounts)*fgNbins);

   std::clog << fLogger->GetPrintedSource();
   if (fColourfulOutput) std::clog << gTools().Color("white_on_green") << gTools().Color("dyellow") << "[" << gTools().Color("reset");
   else                  std::clog << "[";
   for (Int_t i=0; i<ic; i++) {
      if (fColourfulOutput) std::clog << gTools().Color("white_on_green") << gTools().Color("dyellow") << ">" << gTools().Color("reset"); 
      else                  std::clog << ">";
   }
   for (Int_t i=ic+1; i<fgNbins; i++) {
      if (fColourfulOutput) std::clog << gTools().Color("white_on_green") << gTools().Color("dyellow") << "." << gTools().Color("reset"); 
      else                  std::clog << ".";
   }
   if (fColourfulOutput) std::clog << gTools().Color("white_on_green") << gTools().Color("dyellow") << "]" << gTools().Color("reset");
   else                  std::clog << "]" ;

   // timing information
   if (fColourfulOutput) {
      std::clog << gTools().Color("reset") << " " ;
      std::clog << "(" << gTools().Color("red") << Int_t((100*(icounts+1))/Float_t(fNcounts)) << "%" << gTools().Color("reset")
               << ", " 
               << "time left: "
               << this->GetLeftTime( icounts ) << gTools().Color("reset") << ") ";
   }
   else {
      std::clog << "] " ;
      std::clog << "(" << Int_t((100*(icounts+1))/Float_t(fNcounts)) << "%" 
               << ", " << "time left: " << this->GetLeftTime( icounts ) << ") ";
   }
   if (comment != "") {
      std::clog << "[" << comment << "]  ";
   }
   std::clog << "\r" << std::flush; 
}

//_______________________________________________________________________
TString TMVA::Timer::SecToText( Double_t seconds, Bool_t Scientific ) const
{
   // pretty string output
   TString out = "";
   if      (Scientific    ) out = Form( "%.3g sec", seconds );
   else if (seconds <  0  ) out = "unknown";
   else if (seconds <= 300) out = Form( "%i sec", Int_t(seconds) );
   else {
      if (seconds > 3600) {
         Int_t h = Int_t(seconds/3600);
         if (h <= 1) out = Form( "%i hr : ", h );
         else        out = Form( "%i hrs : ", h );
      
         seconds = Int_t(seconds)%3600;
      }
      Int_t m = Int_t(seconds/60);
      if (m <= 1) out += Form( "%i min", m );
      else        out += Form( "%i mins", m );
   }

   return (fColourfulOutput) ? gTools().Color("red") + out + gTools().Color("reset") : out;
}

 Timer.cxx:1
 Timer.cxx:2
 Timer.cxx:3
 Timer.cxx:4
 Timer.cxx:5
 Timer.cxx:6
 Timer.cxx:7
 Timer.cxx:8
 Timer.cxx:9
 Timer.cxx:10
 Timer.cxx:11
 Timer.cxx:12
 Timer.cxx:13
 Timer.cxx:14
 Timer.cxx:15
 Timer.cxx:16
 Timer.cxx:17
 Timer.cxx:18
 Timer.cxx:19
 Timer.cxx:20
 Timer.cxx:21
 Timer.cxx:22
 Timer.cxx:23
 Timer.cxx:24
 Timer.cxx:25
 Timer.cxx:26
 Timer.cxx:27
 Timer.cxx:28
 Timer.cxx:29
 Timer.cxx:30
 Timer.cxx:31
 Timer.cxx:32
 Timer.cxx:33
 Timer.cxx:34
 Timer.cxx:35
 Timer.cxx:36
 Timer.cxx:37
 Timer.cxx:38
 Timer.cxx:39
 Timer.cxx:40
 Timer.cxx:41
 Timer.cxx:42
 Timer.cxx:43
 Timer.cxx:44
 Timer.cxx:45
 Timer.cxx:46
 Timer.cxx:47
 Timer.cxx:48
 Timer.cxx:49
 Timer.cxx:50
 Timer.cxx:51
 Timer.cxx:52
 Timer.cxx:53
 Timer.cxx:54
 Timer.cxx:55
 Timer.cxx:56
 Timer.cxx:57
 Timer.cxx:58
 Timer.cxx:59
 Timer.cxx:60
 Timer.cxx:61
 Timer.cxx:62
 Timer.cxx:63
 Timer.cxx:64
 Timer.cxx:65
 Timer.cxx:66
 Timer.cxx:67
 Timer.cxx:68
 Timer.cxx:69
 Timer.cxx:70
 Timer.cxx:71
 Timer.cxx:72
 Timer.cxx:73
 Timer.cxx:74
 Timer.cxx:75
 Timer.cxx:76
 Timer.cxx:77
 Timer.cxx:78
 Timer.cxx:79
 Timer.cxx:80
 Timer.cxx:81
 Timer.cxx:82
 Timer.cxx:83
 Timer.cxx:84
 Timer.cxx:85
 Timer.cxx:86
 Timer.cxx:87
 Timer.cxx:88
 Timer.cxx:89
 Timer.cxx:90
 Timer.cxx:91
 Timer.cxx:92
 Timer.cxx:93
 Timer.cxx:94
 Timer.cxx:95
 Timer.cxx:96
 Timer.cxx:97
 Timer.cxx:98
 Timer.cxx:99
 Timer.cxx:100
 Timer.cxx:101
 Timer.cxx:102
 Timer.cxx:103
 Timer.cxx:104
 Timer.cxx:105
 Timer.cxx:106
 Timer.cxx:107
 Timer.cxx:108
 Timer.cxx:109
 Timer.cxx:110
 Timer.cxx:111
 Timer.cxx:112
 Timer.cxx:113
 Timer.cxx:114
 Timer.cxx:115
 Timer.cxx:116
 Timer.cxx:117
 Timer.cxx:118
 Timer.cxx:119
 Timer.cxx:120
 Timer.cxx:121
 Timer.cxx:122
 Timer.cxx:123
 Timer.cxx:124
 Timer.cxx:125
 Timer.cxx:126
 Timer.cxx:127
 Timer.cxx:128
 Timer.cxx:129
 Timer.cxx:130
 Timer.cxx:131
 Timer.cxx:132
 Timer.cxx:133
 Timer.cxx:134
 Timer.cxx:135
 Timer.cxx:136
 Timer.cxx:137
 Timer.cxx:138
 Timer.cxx:139
 Timer.cxx:140
 Timer.cxx:141
 Timer.cxx:142
 Timer.cxx:143
 Timer.cxx:144
 Timer.cxx:145
 Timer.cxx:146
 Timer.cxx:147
 Timer.cxx:148
 Timer.cxx:149
 Timer.cxx:150
 Timer.cxx:151
 Timer.cxx:152
 Timer.cxx:153
 Timer.cxx:154
 Timer.cxx:155
 Timer.cxx:156
 Timer.cxx:157
 Timer.cxx:158
 Timer.cxx:159
 Timer.cxx:160
 Timer.cxx:161
 Timer.cxx:162
 Timer.cxx:163
 Timer.cxx:164
 Timer.cxx:165
 Timer.cxx:166
 Timer.cxx:167
 Timer.cxx:168
 Timer.cxx:169
 Timer.cxx:170
 Timer.cxx:171
 Timer.cxx:172
 Timer.cxx:173
 Timer.cxx:174
 Timer.cxx:175
 Timer.cxx:176
 Timer.cxx:177
 Timer.cxx:178
 Timer.cxx:179
 Timer.cxx:180
 Timer.cxx:181
 Timer.cxx:182
 Timer.cxx:183
 Timer.cxx:184
 Timer.cxx:185
 Timer.cxx:186
 Timer.cxx:187
 Timer.cxx:188
 Timer.cxx:189
 Timer.cxx:190
 Timer.cxx:191
 Timer.cxx:192
 Timer.cxx:193
 Timer.cxx:194
 Timer.cxx:195
 Timer.cxx:196
 Timer.cxx:197
 Timer.cxx:198
 Timer.cxx:199
 Timer.cxx:200
 Timer.cxx:201
 Timer.cxx:202
 Timer.cxx:203
 Timer.cxx:204
 Timer.cxx:205
 Timer.cxx:206
 Timer.cxx:207
 Timer.cxx:208
 Timer.cxx:209
 Timer.cxx:210
 Timer.cxx:211
 Timer.cxx:212
 Timer.cxx:213
 Timer.cxx:214
 Timer.cxx:215
 Timer.cxx:216
 Timer.cxx:217
 Timer.cxx:218
 Timer.cxx:219
 Timer.cxx:220
 Timer.cxx:221
 Timer.cxx:222
 Timer.cxx:223
 Timer.cxx:224
 Timer.cxx:225
 Timer.cxx:226
 Timer.cxx:227
 Timer.cxx:228
 Timer.cxx:229
 Timer.cxx:230
 Timer.cxx:231
 Timer.cxx:232
 Timer.cxx:233
 Timer.cxx:234
 Timer.cxx:235
 Timer.cxx:236
 Timer.cxx:237
 Timer.cxx:238
 Timer.cxx:239
 Timer.cxx:240