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

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

#include "TMVA/Event.h"
#include "TMVA/Tools.h"
#include <iostream>
#include "assert.h"
#include <iomanip>
#include <cassert>
#include "TCut.h"

Bool_t TMVA::Event::fgIsTraining = kFALSE;
Bool_t TMVA::Event::fgIgnoreNegWeightsInTraining = kFALSE;

//____________________________________________________________
TMVA::Event::Event()
   : fValues(),
     fValuesDynamic(0),
     fTargets(),
     fSpectators(),
     fVariableArrangement(0),
     fClass(0),
     fWeight(1.0),
     fBoostWeight(1.0),
     fDynamic(kFALSE),
     fDoNotBoost(kFALSE)
{
   // copy constructor
}

//____________________________________________________________
TMVA::Event::Event( const std::vector<Float_t>& ev,
                    const std::vector<Float_t>& tg,
                    UInt_t cls,
                    Double_t weight,
                    Double_t boostweight )
   : fValues(ev),
     fValuesDynamic(0),
     fTargets(tg),
     fSpectators(0),
     fVariableArrangement(0),
     fClass(cls),
     fWeight(weight),
     fBoostWeight(boostweight),
     fDynamic(kFALSE),
     fDoNotBoost(kFALSE)
{
   // constructor
}

//____________________________________________________________
TMVA::Event::Event( const std::vector<Float_t>& ev,
                    const std::vector<Float_t>& tg,
                    const std::vector<Float_t>& vi,
                    UInt_t cls,
                    Double_t weight,
                    Double_t boostweight )
   : fValues(ev),
     fValuesDynamic(0),
     fTargets(tg),
     fSpectators(vi),
     fVariableArrangement(0),
     fClass(cls),
     fWeight(weight),
     fBoostWeight(boostweight),
     fDynamic(kFALSE),
     fDoNotBoost(kFALSE)
{
   // constructor
}

//____________________________________________________________
TMVA::Event::Event( const std::vector<Float_t>& ev,
                    UInt_t cls,
                    Double_t weight,
                    Double_t boostweight )
   : fValues(ev),
     fValuesDynamic(0),
     fTargets(0),
     fSpectators(0),
     fVariableArrangement(0),
     fClass(cls),
     fWeight(weight),
     fBoostWeight(boostweight),
     fDynamic(kFALSE),
     fDoNotBoost(kFALSE)
{
   // constructor
}

//____________________________________________________________
TMVA::Event::Event( const std::vector<Float_t*>*& evdyn, UInt_t nvar )
   : fValues(nvar),
     fValuesDynamic(0),
     fTargets(0),
     fSpectators(evdyn->size()-nvar),
     fVariableArrangement(0),
     fClass(0),
     fWeight(0),
     fBoostWeight(0),
     fDynamic(true),
     fDoNotBoost(kFALSE)
{
   // constructor for single events
   fValuesDynamic = (std::vector<Float_t*>*) evdyn;
}

//____________________________________________________________
TMVA::Event::Event( const Event& event ) 
   : fValues(event.fValues),
     fValuesDynamic(event.fValuesDynamic),
     fTargets(event.fTargets),
     fSpectators(event.fSpectators),
     fVariableArrangement(event.fVariableArrangement),
     fClass(event.fClass),
     fWeight(event.fWeight),
     fBoostWeight(event.fBoostWeight),
     fDynamic(event.fDynamic),
     fDoNotBoost(kFALSE)
{
   // copy constructor
   if (event.fDynamic){
      fValues.clear();
      UInt_t nvar = event.GetNVariables();
      UInt_t idx=0;
      std::vector<Float_t*>::iterator itDyn=event.fValuesDynamic->begin(), itDynEnd=event.fValuesDynamic->end();
      for (; itDyn!=itDynEnd && idx<nvar; ++itDyn){
         Float_t value=*(*itDyn);
         fValues.push_back( value );
         ++idx;
      }
      fSpectators.clear();
      for (; itDyn!=itDynEnd; ++itDyn){
         Float_t value=*(*itDyn);
         fSpectators.push_back( value );
         ++idx;
      }

      fDynamic=kFALSE;
      fValuesDynamic=NULL;
   }
}

//____________________________________________________________
TMVA::Event::~Event()
{
   // Event destructor
}
//____________________________________________________________
void TMVA::Event::SetVariableArrangement( std::vector<UInt_t>* const m ) const {
   // set the variable arrangement

   // mapping from global variable index (the position in the vector)
   // to the new index in the subset of variables used by the
   // composite classifier
   fVariableArrangement = m;
}


//____________________________________________________________
void TMVA::Event::CopyVarValues( const Event& other )
{
   // copies only the variable values
   fValues      = other.fValues;
   fTargets     = other.fTargets;
   fSpectators  = other.fSpectators;
   if (other.fDynamic){
      UInt_t nvar = other.GetNVariables();
      fValues.clear();
      UInt_t idx=0;
      std::vector<Float_t*>::iterator itDyn=other.fValuesDynamic->begin(), itDynEnd=other.fValuesDynamic->end();
      for (; itDyn!=itDynEnd && idx<nvar; ++itDyn){
         Float_t value=*(*itDyn);
         fValues.push_back( value );
         ++idx;
      }
      fSpectators.clear();
      for (; itDyn!=itDynEnd; ++itDyn){
         Float_t value=*(*itDyn);
         fSpectators.push_back( value );
         ++idx;
      }
   }
   fDynamic     = kFALSE;
   fValuesDynamic = NULL;

   fClass       = other.fClass;
   fWeight      = other.fWeight;
   fBoostWeight = other.fBoostWeight;
}

//____________________________________________________________
Float_t TMVA::Event::GetValue( UInt_t ivar ) const
{
   // return value of i'th variable
   Float_t retval;
   if (fVariableArrangement==0) {
      retval = fDynamic ? ( *((*fValuesDynamic).at(ivar)) ) : fValues.at(ivar); 
   } 
   else {
      UInt_t mapIdx = (*fVariableArrangement)[ivar];
      //   std::cout<< fDynamic ; 
      if (fDynamic){
         //     std::cout<< " " << (*fValuesDynamic).size() << " " << fValues.size() << std::endl;
         retval = *((*fValuesDynamic).at(mapIdx));
      }
      else{
         //retval = fValues.at(ivar);
         retval = ( mapIdx<fValues.size() ) ? fValues[mapIdx] : fSpectators[mapIdx-fValues.size()];
      }
   }

   return retval;
}

//____________________________________________________________
Float_t TMVA::Event::GetSpectator( UInt_t ivar) const 
{
   // return spectator content
   if (fDynamic) return *(fValuesDynamic->at(GetNVariables()+ivar));
   else          return fSpectators.at(ivar);
}

//____________________________________________________________
const std::vector<Float_t>& TMVA::Event::GetValues() const
{
   // return value vector
   if (fVariableArrangement==0) {

      if (fDynamic) {
         fValues.clear();
         for (std::vector<Float_t*>::const_iterator it = fValuesDynamic->begin(), itEnd=fValuesDynamic->end()-GetNSpectators(); 
              it != itEnd; ++it) { 
            Float_t val = *(*it); 
            fValues.push_back( val ); 
         }
      }
   }else{
      UInt_t mapIdx;
      if (fDynamic) {
         fValues.clear();
         for (UInt_t i=0; i< fVariableArrangement->size(); i++){
            mapIdx = (*fVariableArrangement)[i];
            fValues.push_back(*((*fValuesDynamic).at(mapIdx)));
         }
      } else {
         // hmm now you have a problem, as you do not want to mess with the original event variables
         // (change them permanently) ... guess the only way is to add a 'fValuesRearranged' array, 
         // and living with the fact that it 'doubles' the Event size :(
         fValuesRearranged.clear();
         for (UInt_t i=0; i< fVariableArrangement->size(); i++){
            mapIdx = (*fVariableArrangement)[i];
            fValuesRearranged.push_back(fValues.at(mapIdx));
         }
         return fValuesRearranged;
      }
   }
   return fValues;
}

//____________________________________________________________
UInt_t TMVA::Event::GetNVariables() const 
{
   // accessor to the number of variables 

   // if variables have to arranged (as it is the case for the
   // composite classifier) the number of the variables changes
   if (fVariableArrangement==0) return fValues.size();
   else                         return fVariableArrangement->size();
}

//____________________________________________________________
UInt_t TMVA::Event::GetNTargets() const 
{
   // accessor to the number of targets
   return fTargets.size();
}

//____________________________________________________________
UInt_t TMVA::Event::GetNSpectators() const 
{
   // accessor to the number of spectators 

   // if variables have to arranged (as it is the case for the
   // composite classifier) the number of the variables changes

   if (fVariableArrangement==0) return fSpectators.size();
   else                         return fValues.size()-fVariableArrangement->size();
}


//____________________________________________________________
void TMVA::Event::SetVal( UInt_t ivar, Float_t val ) 
{
   // set variable ivar to val
   if ((fDynamic ?( (*fValuesDynamic).size() ) : fValues.size())<=ivar)
      (fDynamic ?( (*fValuesDynamic).resize(ivar+1) ) : fValues.resize(ivar+1));

   (fDynamic ?( *(*fValuesDynamic)[ivar] ) : fValues[ivar])=val;
}

//____________________________________________________________
void TMVA::Event::Print( std::ostream& o ) const
{
   // print method
   o << *this << std::endl;
}

//_____________________________________________________________
void TMVA::Event::SetTarget( UInt_t itgt, Float_t value ) 
{ 
   // set the target value (dimension itgt) to value

   if (fTargets.size() <= itgt) fTargets.resize( itgt+1 );
   fTargets.at(itgt) = value;
}

//_____________________________________________________________
void TMVA::Event::SetSpectator( UInt_t ivar, Float_t value ) 
{ 
   // set spectator value (dimension ivar) to value

   if (fSpectators.size() <= ivar) fSpectators.resize( ivar+1 );
   fSpectators.at(ivar) = value;
}

//_____________________________________________________________
Double_t TMVA::Event::GetWeight() const 
{
   // return the event weight - depending on whether the flag 
   // *IgnoreNegWeightsInTraining* is or not. If it is set AND it is 
   // used for training, then negetive event weights are set to zero !
   // NOTE! For events used in Testing, the ORIGINAL possibly negative
   // event weight is used  no matter what 

   return (fgIgnoreNegWeightsInTraining && fgIsTraining && fWeight < 0) ? 0. : fWeight*fBoostWeight;
}

//_____________________________________________________________
void TMVA::Event::SetIsTraining(Bool_t b)
{
   // when this static function is called, it sets the flag whether 
   // events with negative event weight should be ignored in the 
   // training, or not.

   fgIsTraining=b;
}
//_____________________________________________________________
void TMVA::Event::SetIgnoreNegWeightsInTraining(Bool_t b)
{
   // when this static function is called, it sets the flag whether 
   // events with negative event weight should be ignored in the 
   // training, or not.

   fgIgnoreNegWeightsInTraining=b;
}

//_______________________________________________________________________
std::ostream& TMVA::operator << ( std::ostream& os, const TMVA::Event& event )
{ 
   // Outputs the data of an event
   os << "Variables [" << event.fValues.size() << "]:";
   for (UInt_t ivar=0; ivar<event.fValues.size(); ++ivar)
      os << " " << std::setw(10) << event.GetValue(ivar);
   os << ", targets [" << event.fTargets.size() << "]:";
   for (UInt_t ivar=0; ivar<event.fTargets.size(); ++ivar)
      os << " " << std::setw(10) << event.GetTarget(ivar);
   os << ", spectators ["<< event.fSpectators.size() << "]:";
   for (UInt_t ivar=0; ivar<event.fSpectators.size(); ++ivar)
      os << " " << std::setw(10) << event.GetSpectator(ivar);
   os << ", weight: " << event.GetWeight();
   os << ", class: " << event.GetClass();
   return os;
}
 Event.cxx:1
 Event.cxx:2
 Event.cxx:3
 Event.cxx:4
 Event.cxx:5
 Event.cxx:6
 Event.cxx:7
 Event.cxx:8
 Event.cxx:9
 Event.cxx:10
 Event.cxx:11
 Event.cxx:12
 Event.cxx:13
 Event.cxx:14
 Event.cxx:15
 Event.cxx:16
 Event.cxx:17
 Event.cxx:18
 Event.cxx:19
 Event.cxx:20
 Event.cxx:21
 Event.cxx:22
 Event.cxx:23
 Event.cxx:24
 Event.cxx:25
 Event.cxx:26
 Event.cxx:27
 Event.cxx:28
 Event.cxx:29
 Event.cxx:30
 Event.cxx:31
 Event.cxx:32
 Event.cxx:33
 Event.cxx:34
 Event.cxx:35
 Event.cxx:36
 Event.cxx:37
 Event.cxx:38
 Event.cxx:39
 Event.cxx:40
 Event.cxx:41
 Event.cxx:42
 Event.cxx:43
 Event.cxx:44
 Event.cxx:45
 Event.cxx:46
 Event.cxx:47
 Event.cxx:48
 Event.cxx:49
 Event.cxx:50
 Event.cxx:51
 Event.cxx:52
 Event.cxx:53
 Event.cxx:54
 Event.cxx:55
 Event.cxx:56
 Event.cxx:57
 Event.cxx:58
 Event.cxx:59
 Event.cxx:60
 Event.cxx:61
 Event.cxx:62
 Event.cxx:63
 Event.cxx:64
 Event.cxx:65
 Event.cxx:66
 Event.cxx:67
 Event.cxx:68
 Event.cxx:69
 Event.cxx:70
 Event.cxx:71
 Event.cxx:72
 Event.cxx:73
 Event.cxx:74
 Event.cxx:75
 Event.cxx:76
 Event.cxx:77
 Event.cxx:78
 Event.cxx:79
 Event.cxx:80
 Event.cxx:81
 Event.cxx:82
 Event.cxx:83
 Event.cxx:84
 Event.cxx:85
 Event.cxx:86
 Event.cxx:87
 Event.cxx:88
 Event.cxx:89
 Event.cxx:90
 Event.cxx:91
 Event.cxx:92
 Event.cxx:93
 Event.cxx:94
 Event.cxx:95
 Event.cxx:96
 Event.cxx:97
 Event.cxx:98
 Event.cxx:99
 Event.cxx:100
 Event.cxx:101
 Event.cxx:102
 Event.cxx:103
 Event.cxx:104
 Event.cxx:105
 Event.cxx:106
 Event.cxx:107
 Event.cxx:108
 Event.cxx:109
 Event.cxx:110
 Event.cxx:111
 Event.cxx:112
 Event.cxx:113
 Event.cxx:114
 Event.cxx:115
 Event.cxx:116
 Event.cxx:117
 Event.cxx:118
 Event.cxx:119
 Event.cxx:120
 Event.cxx:121
 Event.cxx:122
 Event.cxx:123
 Event.cxx:124
 Event.cxx:125
 Event.cxx:126
 Event.cxx:127
 Event.cxx:128
 Event.cxx:129
 Event.cxx:130
 Event.cxx:131
 Event.cxx:132
 Event.cxx:133
 Event.cxx:134
 Event.cxx:135
 Event.cxx:136
 Event.cxx:137
 Event.cxx:138
 Event.cxx:139
 Event.cxx:140
 Event.cxx:141
 Event.cxx:142
 Event.cxx:143
 Event.cxx:144
 Event.cxx:145
 Event.cxx:146
 Event.cxx:147
 Event.cxx:148
 Event.cxx:149
 Event.cxx:150
 Event.cxx:151
 Event.cxx:152
 Event.cxx:153
 Event.cxx:154
 Event.cxx:155
 Event.cxx:156
 Event.cxx:157
 Event.cxx:158
 Event.cxx:159
 Event.cxx:160
 Event.cxx:161
 Event.cxx:162
 Event.cxx:163
 Event.cxx:164
 Event.cxx:165
 Event.cxx:166
 Event.cxx:167
 Event.cxx:168
 Event.cxx:169
 Event.cxx:170
 Event.cxx:171
 Event.cxx:172
 Event.cxx:173
 Event.cxx:174
 Event.cxx:175
 Event.cxx:176
 Event.cxx:177
 Event.cxx:178
 Event.cxx:179
 Event.cxx:180
 Event.cxx:181
 Event.cxx:182
 Event.cxx:183
 Event.cxx:184
 Event.cxx:185
 Event.cxx:186
 Event.cxx:187
 Event.cxx:188
 Event.cxx:189
 Event.cxx:190
 Event.cxx:191
 Event.cxx:192
 Event.cxx:193
 Event.cxx:194
 Event.cxx:195
 Event.cxx:196
 Event.cxx:197
 Event.cxx:198
 Event.cxx:199
 Event.cxx:200
 Event.cxx:201
 Event.cxx:202
 Event.cxx:203
 Event.cxx:204
 Event.cxx:205
 Event.cxx:206
 Event.cxx:207
 Event.cxx:208
 Event.cxx:209
 Event.cxx:210
 Event.cxx:211
 Event.cxx:212
 Event.cxx:213
 Event.cxx:214
 Event.cxx:215
 Event.cxx:216
 Event.cxx:217
 Event.cxx:218
 Event.cxx:219
 Event.cxx:220
 Event.cxx:221
 Event.cxx:222
 Event.cxx:223
 Event.cxx:224
 Event.cxx:225
 Event.cxx:226
 Event.cxx:227
 Event.cxx:228
 Event.cxx:229
 Event.cxx:230
 Event.cxx:231
 Event.cxx:232
 Event.cxx:233
 Event.cxx:234
 Event.cxx:235
 Event.cxx:236
 Event.cxx:237
 Event.cxx:238
 Event.cxx:239
 Event.cxx:240
 Event.cxx:241
 Event.cxx:242
 Event.cxx:243
 Event.cxx:244
 Event.cxx:245
 Event.cxx:246
 Event.cxx:247
 Event.cxx:248
 Event.cxx:249
 Event.cxx:250
 Event.cxx:251
 Event.cxx:252
 Event.cxx:253
 Event.cxx:254
 Event.cxx:255
 Event.cxx:256
 Event.cxx:257
 Event.cxx:258
 Event.cxx:259
 Event.cxx:260
 Event.cxx:261
 Event.cxx:262
 Event.cxx:263
 Event.cxx:264
 Event.cxx:265
 Event.cxx:266
 Event.cxx:267
 Event.cxx:268
 Event.cxx:269
 Event.cxx:270
 Event.cxx:271
 Event.cxx:272
 Event.cxx:273
 Event.cxx:274
 Event.cxx:275
 Event.cxx:276
 Event.cxx:277
 Event.cxx:278
 Event.cxx:279
 Event.cxx:280
 Event.cxx:281
 Event.cxx:282
 Event.cxx:283
 Event.cxx:284
 Event.cxx:285
 Event.cxx:286
 Event.cxx:287
 Event.cxx:288
 Event.cxx:289
 Event.cxx:290
 Event.cxx:291
 Event.cxx:292
 Event.cxx:293
 Event.cxx:294
 Event.cxx:295
 Event.cxx:296
 Event.cxx:297
 Event.cxx:298
 Event.cxx:299
 Event.cxx:300
 Event.cxx:301
 Event.cxx:302
 Event.cxx:303
 Event.cxx:304
 Event.cxx:305
 Event.cxx:306
 Event.cxx:307
 Event.cxx:308
 Event.cxx:309
 Event.cxx:310
 Event.cxx:311
 Event.cxx:312
 Event.cxx:313
 Event.cxx:314
 Event.cxx:315
 Event.cxx:316
 Event.cxx:317
 Event.cxx:318
 Event.cxx:319
 Event.cxx:320
 Event.cxx:321
 Event.cxx:322
 Event.cxx:323
 Event.cxx:324
 Event.cxx:325
 Event.cxx:326
 Event.cxx:327
 Event.cxx:328
 Event.cxx:329
 Event.cxx:330
 Event.cxx:331
 Event.cxx:332
 Event.cxx:333
 Event.cxx:334
 Event.cxx:335
 Event.cxx:336
 Event.cxx:337
 Event.cxx:338
 Event.cxx:339
 Event.cxx:340
 Event.cxx:341
 Event.cxx:342
 Event.cxx:343
 Event.cxx:344
 Event.cxx:345
 Event.cxx:346
 Event.cxx:347
 Event.cxx:348
 Event.cxx:349
 Event.cxx:350
 Event.cxx:351
 Event.cxx:352
 Event.cxx:353
 Event.cxx:354
 Event.cxx:355
 Event.cxx:356
 Event.cxx:357
 Event.cxx:358
 Event.cxx:359
 Event.cxx:360
 Event.cxx:361
 Event.cxx:362
 Event.cxx:363
 Event.cxx:364
 Event.cxx:365
 Event.cxx:366
 Event.cxx:367
 Event.cxx:368
 Event.cxx:369
 Event.cxx:370
 Event.cxx:371
 Event.cxx:372
 Event.cxx:373
 Event.cxx:374
 Event.cxx:375
 Event.cxx:376
 Event.cxx:377
 Event.cxx:378
 Event.cxx:379
 Event.cxx:380
 Event.cxx:381
 Event.cxx:382
 Event.cxx:383
 Event.cxx:384
 Event.cxx:385
 Event.cxx:386
 Event.cxx:387
 Event.cxx:388
 Event.cxx:389
 Event.cxx:390
 Event.cxx:391
 Event.cxx:392
 Event.cxx:393
 Event.cxx:394
 Event.cxx:395
 Event.cxx:396
 Event.cxx:397
 Event.cxx:398
 Event.cxx:399
 Event.cxx:400
 Event.cxx:401