#include <sstream>
#include "RVersion.h"
#if ROOT_VERSION_CODE < ROOT_VERSION(6,07,00)
#define private public
#define protected public
#include "TMVA/Factory.h"
#include "TMVA/DataSetInfo.h"
#undef private
#undef protected
#else
#define private public
#define protected public
#include "TMVA/Factory.h"
#include "TMVA/DataSetInfo.h"
#include "TMVA/DataLoader.h"
#undef private
#undef protected
#endif

#include "QFramework/TQMVA.h"
#include "QFramework/TQIterator.h"
#include "TFile.h"
#include "QFramework/TQUtils.h"

// #define _DEBUG_

#include "QFramework/TQLibrary.h"

////////////////////////////////////////////////////////////////////////////////////////////////
//
// TQMVA
//
// The TQMVA is a wrapper class providing an interface of the TQSampleFolder structure
// to a TMVA object.
//
// This class can be used as follows:
// 1. Instantiate an object of TQMVA, providing a TQSampleFolder
// either directly to the constructor or via setSampleFolder
// 2. Call the member function createFactory, providing the name of 
// the desired output file and the TMVA options to be passed through.
// You may also set the factory manually via setFactory instead.
// The factory may at any time be retrieved via getFactory.
// 3. Setup the TQMVA
// - Aquire or define an instance of TQCut and assign it
// to the TQMVA via the member function setBaseCut.
// You may instruct the TQMVA to use a derived cut by calling
// the TQMVA::useCut function on some cut name
// - Add the variables using TQMVA::bookVariable
// - Call the addSignal and addBackground functions to announce 
// paths under which signal/background trees may be found.
// This method is superior to adding the trees directly because
// the trees will automatically be obtained from the samples.
// 4. Call TQMVA::readSamples to propagate the setup to the TMVA::Factory
// and read the input samples. As an argument, you may pass an EventSelector,
// a simple class-type object that will sort your events into a 
// 'training' and a 'testing' category. By default, an even-odd-rule will 
// be used.
// 5. Call TQMVA::prepareTrees("XYZ") to replace TMVA::prepareTrainingAndTestTree,
// where the option string "XYZ" will be forwarded to the latter function.
// 6. Retrieve the TMVA::Factory via TQMVA::getFactory. 
// 7. Perform your analysis on the TMVA::Factory directly.
//
// Please note that after retrieving the TMVA::Factory, you may delete the TQMVA object.
// This will NOT delete your TMVA::Factory, which you can use for further analysis.
// It is the users responsibility to delete the TMVA::Factory and close and delete
// the output file. If the TMVA::Factory was created with TQMVA::createFactory, 
// this can be achieved by calling TQMVA::deleteFactory and TQMVA::closeOutputFile.
//
////////////////////////////////////////////////////////////////////////////////////////////////

ClassImp(TQMVA)

TQMVA::TQMVA() :
TQNamedTaggable("TQMVA")
{
  // default constructor
  init();
}

TQMVA::TQMVA(const TString& name_) : 
  TQNamedTaggable(TQStringUtils::replace(name_,"-","_"))
{
  // constructor taking a job name
  init();
}

TQMVA::TQMVA(TQSampleFolder* sf) : 
  TQNamedTaggable("TQMVA"),
  fSampleFolder(sf)
{
  // constructor taking a sample folder
  init();
}

TQMVA::TQMVA(const TString& name_, TQSampleFolder* sf) : 
  TQNamedTaggable(TQStringUtils::replace(name_,"-","_")),
  fSampleFolder(sf)
{
  // constructor taking a job name and sample folder
  init();
}

void TQMVA::init(){
  this->SetTitle("TQMVA");
  #ifndef LEGACY_INTERFACE_PRE_607
  this->fDataLoader = new TMVA::DataLoader("TQMVADataLoader");
  #endif
}

TQMVA::~TQMVA(){
  // default destructor
#ifndef LEGACY_INTERFACE_PRE_607
  delete this->fDataLoader;
#endif
}
 
void TQMVA::printListOfVariables() const {
  // print the list of currently booked variables
  for(size_t i=0; i<this->fNames.size(); i++){
    std::cout << this->fNames[i] << "\t" << this->fExpressions[i] << std::endl;
  }
}

TString TQMVA::getVariableExpression(const TString& var){
  // return the full expression for the variable with a given name
  for(size_t i=0; i<this->fExpressions.size(); i++){
    if(TQStringUtils::equal(var,this->fNames[i])){
      return this->fExpressions[i];
    }
  }
  return TQStringUtils::emptyString;
}

TString TQMVA::getVariableExpression(const char* var){
  // return the full expression for the variable with a given name
  return this->getVariableExpression((TString)(var));
}

void TQMVA::setBaseCut(TQCut* cut){
  // set the base cut
  this->fBaseCut = cut;
}

TQCut* TQMVA::getBaseCut(){
  // get the base cut
  return this->fBaseCut;
}

TQCut* TQMVA::useCut(const TString& name){
  // set and return the active cut (by name)
  this->fActiveCut = this->fBaseCut->getCut(name);
  return this->fActiveCut;
}

TMVA::Factory* TQMVA::getFactory(){
  // get the TMVA::Factory embedded in this class
  return this->fMVA;
}
void TQMVA::setFactory(TMVA::Factory* mva){
  // set the embedded TMVA::Factory
  this->fMVA = mva;
}
TQSampleFolder* TQMVA::getSampleFolder(){
  // get the TQSampleFolder embedded in this class
  return this->fSampleFolder;
}
void TQMVA::setSampleFolder(TQSampleFolder* sf){
  // set the embedded sample folder
  this->fSampleFolder = sf;
}

void TQMVA::deleteFactory(){
  // delete the TMVA::Factory embedded in this class
  if(this->fMVA) delete this->fMVA;
}
void TQMVA::closeOutputFile(){
  // close the output file of the TMVA::Factory
  // will only work as desired if the factory
  // was created with TQMVA::createFactory
  if(this->fOutputFile){
    this->fOutputFile->Close();
    delete this->fOutputFile;
    this->fOutputFile = NULL;
  }
}
bool TQMVA::createFactory(const TString& filename, const TString& options){
  // create an instance of TMVA::Factory
  // will open an output file in RECREATE mode
  // neither the TMVA nor the TFile will be deleted
  // when the TQMVA is deleted, they need to be
  // closed/deleted with closeOutputFile and deleteFactory
  if(!TQUtils::ensureDirectoryForFile(filename)){
    TQLibrary::ERRORclass("unable to access directory for file '%s'",filename.Data());
    return false;
  }
  this->fOutputFile = TFile::Open(filename,"RECREATE");
  if(!fOutputFile || !fOutputFile->IsOpen()){
    TQLibrary::ERRORclass("unable to open file '%s'",filename.Data());
    if(fOutputFile) delete fOutputFile;
    return false;
  }
  this->setTagString("outputFileName",filename);
  this->fMVA = new TMVA::Factory(this->GetName(),fOutputFile,options.Data());
  return true;
}

void TQMVA::addVariable(const TString& name, const TString& title, const TString& expression, const TString& unit, char vtype, double min, double max, bool spectator){
  // internal function mapping to the TMVA::Factory/DataLoader management functions
  if(!this->fMVA){
    throw std::runtime_error("unable to book variable without instance of TMVA!");
  }
#ifdef LEGACY_INTERFACE_PRE_607
  if(spectator) this->fMVA->AddSpectator(TString::Format("%s := %s",name.Data(),name.Data()),title,unit,min,max);
  else this->fMVA->AddVariable(TString::Format("%s := %s",name.Data(),name.Data()),title,unit,vtype,min,max);
  this->fNames.push_back(name);
  this->fExpressions.push_back(expression);
  std::vector<TMVA::VariableInfo>& variables = this->fMVA->DefaultDataSetInfo().GetVariableInfos();
  for(size_t i=0; i<this->fNames.size(); i++){
    if(TQStringUtils::equal(variables[i].GetInternalName(),name)){
      variables[i].SetLabel(expression);
    }
  }
#else
  if(spectator) this->fDataLoader->AddSpectator(TString::Format("%s := %s",name.Data(),name.Data()),title,unit,min,max);
  else this->fDataLoader->AddVariable(TString::Format("%s := %s",name.Data(),name.Data()),title,unit,vtype,min,max);
  this->fNames.push_back(name);
  this->fExpressions.push_back(expression);
  std::vector<TMVA::VariableInfo>& variables = this->fDataLoader->DefaultDataSetInfo().GetVariableInfos();
  for(size_t i=0; i<this->fNames.size(); i++){
    if(TQStringUtils::equal(variables[i].GetInternalName(),name)){
      variables[i].SetLabel(expression);
    }
  }
#endif
}

void TQMVA::printInternalVariables() const {
  // print the list of currently booked variables
  // this function accesses the internal variables of the TMVA::Factory
  #ifdef LEGACY_INTERFACE_PRE_607
  std::vector<TMVA::VariableInfo>& variables = this->fMVA->DefaultDataSetInfo().GetVariableInfos();
  for(size_t i=0; i<variables.size(); i++){
    std::cout << variables[i].GetInternalName() << ":" << variables[i].GetLabel() << ":" << variables[i].GetExpression() << " (" << variables[i].GetVarType() << "/" << variables[i].GetUnit() << ")" << std::endl;
  }
  #else 
  std::vector<TMVA::VariableInfo>& variables = this->fDataLoader->DefaultDataSetInfo().GetVariableInfos();
  for(size_t i=0; i<variables.size(); i++){
    std::cout << variables[i].GetInternalName() << ":" << variables[i].GetLabel() << ":" << variables[i].GetExpression() << " (" << variables[i].GetVarType() << "/" << variables[i].GetUnit() << ")" << std::endl;
  }
  #endif
}

void TQMVA::prepareTrees(const TString& options){
  // wrapper for TMVA::prepareTrainingAndTestTree (with empty cut)
  TCut cut;
#ifdef LEGACY_INTERFACE_PRE_607
  if(this->fMVA) this->fMVA->PrepareTrainingAndTestTree(cut,options);
# else 
  if(this->fDataLoader) this->fDataLoader->PrepareTrainingAndTestTree(cut,options);
#endif
}


void TQMVA::bookVariable(const TString& name_, const TString& expression_, double min, double max){
  // book a variable
  // will internally call TMVA::Factory::addVariable
  TString name = TQFolder::makeValidIdentifier(name_);
  TString expression(this->fAliases ? this->fAliases->replaceInText(expression_) : expression_);
  this->addVariable(name,name,expression,"",'F',min,max,false);
}

void TQMVA::bookVariable(const TString& name_, const TString& expression_, const TString& title, const TString& unit, double min, double max){
  // book a variable
  // will internally call TMVA::Factory::addVariable
  TString name = TQFolder::makeValidIdentifier(name_);
  TString expression(this->fAliases ? this->fAliases->replaceInText(expression_) : expression_);
  this->addVariable(name,title,expression,unit,'F',min,max,false);
}

void TQMVA::bookVariable(const TString& name_, const TString& expression_, const TString& title, double min, double max){
  // book a variable
  // will internally call TMVA::Factory::addVariable
  TString name = TQFolder::makeValidIdentifier(name_);
  TString expression(this->fAliases ? this->fAliases->replaceInText(expression_) : expression_);
  this->addVariable(name,title,expression,"",'F',min,max,false);
}

void TQMVA::bookVariable(const char* name_, const char* expression_, double min, double max){
  // book a variable
  // will internally call TMVA::Factory::addVariable
  TString name = TQFolder::makeValidIdentifier(name_);
  TString expression(this->fAliases ? this->fAliases->replaceInText(expression_).Data() : expression_);
  this->addVariable(name,name,expression,"",'F',min,max,false);
}

void TQMVA::bookVariable(const char* name_, const char* expression_, const char* title, const char* unit, double min, double max){
  // book a variable
  // will internally call TMVA::Factory::addVariable
  TString name = TQFolder::makeValidIdentifier(name_);
  TString expression(this->fAliases ? this->fAliases->replaceInText(expression_).Data() : expression_);
  this->addVariable(name,title,expression,unit,'F',min,max,false);
}

void TQMVA::bookVariable(const char* name_, const char* expression_, const char* title, double min, double max){
  // book a variable
  // will internally call TMVA::Factory::addVariable
  TString name = TQFolder::makeValidIdentifier(name_);
  TString expression = (this->fAliases ? this->fAliases->replaceInText(expression_).Data() : expression_);
  this->addVariable(name,title,expression,"",'F',min,max,false);
}

//--------------------------------------

void TQMVA::bookSpectator(const TString& name_, const TString& expression_, double min, double max){
  // book a variable
  // will internally call TMVA::Factory::addVariable
  TString name = TQFolder::makeValidIdentifier(name_);
  TString expression(this->fAliases ? this->fAliases->replaceInText(expression_) : expression_);
  this->addVariable(name,name,expression,"",'F',min,max,true);
}

void TQMVA::bookSpectator(const TString& name_, const TString& expression_, const TString& title, const TString& unit, double min, double max){
  // book a variable
  // will internally call TMVA::Factory::addVariable
  TString name = TQFolder::makeValidIdentifier(name_);
  TString expression(this->fAliases ? this->fAliases->replaceInText(expression_) : expression_);
  this->addVariable(name,title,expression,unit,'F',min,max,true);
}

void TQMVA::bookSpectator(const TString& name_, const TString& expression_, const TString& title, double min, double max){
  // book a variable
  // will internally call TMVA::Factory::addVariable
  TString name = TQFolder::makeValidIdentifier(name_);
  TString expression(this->fAliases ? this->fAliases->replaceInText(expression_) : expression_);
  this->addVariable(name,title,expression,"",'F',min,max,true);
}

void TQMVA::bookSpectator(const char* name_, const char* expression_, double min, double max){
  // book a variable
  // will internally call TMVA::Factory::addVariable
  TString name = TQFolder::makeValidIdentifier(name_);
  TString expression(this->fAliases ? this->fAliases->replaceInText(expression_).Data() : expression_);
  this->addVariable(name,name,expression,"",'F',min,max,true);
}

void TQMVA::bookSpectator(const char* name_, const char* expression_, const char* title, const char* unit, double min, double max){
  // book a variable
  // will internally call TMVA::Factory::addVariable
  TString name = TQFolder::makeValidIdentifier(name_);
  TString expression(this->fAliases ? this->fAliases->replaceInText(expression_).Data() : expression_);
  this->addVariable(name,title,expression,unit,'F',min,max,true);
}

void TQMVA::bookSpectator(const char* name_, const char* expression_, const char* title, double min, double max){
  // book a variable
  // will internally call TMVA::Factory::addVariable
  TString name = TQFolder::makeValidIdentifier(name_);
  TString expression = (this->fAliases ? this->fAliases->replaceInText(expression_).Data() : expression_);
  this->addVariable(name,title,expression,"",'F',min,max,true);
}

//-------------------------------------

void TQMVA::addSignal(const TString& path){
  // add a signal path
  this->fSigPaths.push_back(path);
}
void TQMVA::addBackground(const TString& path){
  // add a background path
  this->fBkgPaths.push_back(path);
}
void TQMVA::clearSignal(){
  // clear all signal paths
  this->fSigPaths.clear();
}
void TQMVA::clearBackground(){
  // clear all background paths
  this->fBkgPaths.clear();
}

int TQMVA::readSamples(){
  // initialize the TMVA::Factory instance
  // this will open all required files and access the trees
  // and return the number of successfully read events
  return this->readSamples(TQMVA::EvenOddEventSelector());
}

int TQMVA::readSamples(const TQMVA::EventSelector& evtsel){
  // initialize the TMVA::Factory instance
  // this will open all required files and access the trees
  // and return the number of successfully read events
  if(!this->fMVA){
    ERRORclass("cannot initialze - no TMVA::Factory assigned!");
    return 0;
  }
  if(!this->fBaseCut){
    ERRORclass("cannot initialze - no TQCut assigned!");
    return 0;
  }
 
  int retval = 0;
  retval += this->readSamplesOfType(TQMVA::Signal,evtsel);
  retval += this->readSamplesOfType(TQMVA::Background,evtsel);
 
  return retval;
}

int TQMVA::readSamplesOfType(TQMVA::SampleType type){
  // read all samples of the given type (Signal or Background), using the default (Even-Odd) event selector
  return this->readSamplesOfType(type,TQMVA::EvenOddEventSelector());
}

int TQMVA::readSamplesOfType(TQMVA::SampleType type, const TQMVA::EventSelector& sel){
  // read all samples of the given type (Signal or Background), using the
  // given event selector
  DEBUGclass("function called for '%s'",type == TQMVA::Signal ? "Signal" : "Background");
  TQSampleIterator sitr(this->getListOfSamples(type),true);
  int retval = 0;
  while(sitr.hasNext()){
    TQSample* s = sitr.readNext();
    this->readSample(s, type,sel);
    retval++;
  }
  return retval;
}

int TQMVA::readSample(TQSample* s, TQMVA::SampleType type, const TQMVA::EventSelector& sel){
  // read a specific sample, assigning it to the given type (Signal or
  // Background), using the given event selector
  if(fOutputFile) this->fOutputFile->cd();
  if(!fActiveCut) fActiveCut = fBaseCut;
  if(!s){
    ERRORclass("sample is NULL");
    return -1;
  }
  if(!fActiveCut){
    ERRORclass("cannot read sample '%s' without active cut, please use TQMVA::setBaseCut(...) to set a base cut");
    return -1;
  }

  DEBUGclass("reading sample '%s'",s->getPath().Data());

  std::vector<double> vars(this->fExpressions.size());

  TQToken* tok = s->getTreeToken();
  if(!tok){
    ERRORclass("unable to obtain tree token for sample '%s'",s->getPath().Data());
    return -1;
  }
  TTree* t = (TTree*)(tok->getContent());
 
  DEBUGclass("initializing cut '%s'",fBaseCut->GetName());
  this->fBaseCut->initialize(s);
  
  // the following two loops seem strangely chopped apart and they are indeed but for now this should make it work untill a better fix is available
  std::vector<TQObservable*> observables;
  for(size_t i=0; i<this->fExpressions.size(); i++){
    TQObservable* obs = TQObservable::getObservable(this->fExpressions[i],s);
    if (!obs->initialize(s)) {
      ERRORclass("Failed to initialize observable obtained from expression '%s' in TQMVA for sample '%s'",this->fExpressions[i].Data(),s->getPath().Data());
    }
    observables.push_back(obs);
  }
    
  t->SetBranchStatus("*", 0);

  for(size_t i=0; i<this->fExpressions.size(); i++){  
    TQObservable* obs = observables.at(i);
    DEBUGclass("activating branches for variable '%s'",this->fNames[i].Data());
    TObjArray* bNames = obs->getBranchNames();
    if (bNames) bNames->SetOwner(true);
#ifdef _DEBUG_
    DEBUGclass("enabling the following branches:");
    TQListUtils::printList(bNames);
#endif
    TQListUtils::setBranchStatus(t,bNames,1);
    delete bNames; 
  }

  {
    DEBUGclass("activating branches for cut '%s'",this->fBaseCut->GetName());
    TObjArray* branchNames = this->fBaseCut->getListOfBranches();
    branchNames->SetOwner(true);
#ifdef _DEBUG_
    DEBUGclass("enabling the following branches:");
    TQListUtils::printList(branchNames);
#endif
    TQListUtils::setBranchStatus(t,branchNames,1);
  }

  int nTrainEvent = 0;
  double sumWeightsTrain = 0;
  int nTestEvent = 0;
  double sumWeightsTest = 0;
  int nEvent = 0;
 
  DEBUGclass("entering event loop using cut '%s'",fActiveCut->GetName());
  
  if(this->fVerbose) TQLibrary::msgStream.startProcessInfo(TQMessageStream::INFO,80,"r",TString::Format("%s: %s",(type == TQMVA::Signal ? "sig" : "bkg"),s->getPath().Data()));
  
  TQCounter* cnt_train = NULL;
  TQCounter* cnt_test = NULL;
  TQCounter* cnt_total = NULL;
  
  //@tag: [makeCounters] If set to true, counters will be added to the cutflow counters, containing the number of training, testing and training+testing events  
  bool makeCounters = this->getTagBoolDefault("makeCounters",false);
  if(makeCounters){
    cnt_train = new TQCounter(TString::Format("TQMVA_%s_testing", this->GetName()),TString::Format("%s testing events", this->GetTitle()));
    cnt_test = new TQCounter(TString::Format("TQMVA_%s_training",this->GetName()),TString::Format("%s training events",this->GetTitle()));
    cnt_total = new TQCounter(TString::Format("TQMVA_%s_total", this->GetName()),TString::Format("%s testing+training events",this->GetTitle()));
  }

#ifndef _DEBUG_
  TQLibrary::redirect_stdout("/dev/null");
#endif
  Long64_t nEntries = t->GetEntriesFast();
  for(Long64_t iEvent = 0; iEvent < nEntries; ++iEvent){
    t->GetEntry(iEvent);
#ifdef _DEBUG_
    //if(this->fActiveCut) this->fActiveCut->printEvaluation();
    //else DEBUGclass("No active cut present");
#endif
    if(!this->fActiveCut->passedGlobally()){
      continue;
    }
    nEvent++;
 
    for(size_t i=0; i<observables.size(); ++i){
#ifdef _DEBUG_
      try {
#endif
        vars[i] = observables[i]->getValue();
#ifdef _DEBUG_  
      } catch(const std::exception& e){
        BREAK("ERROR in TQMVA: observable '%s' with expression '%s' encountered error '%s'",observables[i]->GetName(),observables[i]->getActiveExpression().Data(),e.what());
      }
#endif
    }
    double weight = this->fActiveCut->getGlobalWeight() * s->getNormalisation();
 
    if(sel.selectEvent(iEvent)){
#ifdef LEGACY_INTERFACE_PRE_607
      if(type==TQMVA::Signal) this->fMVA->AddSignalTrainingEvent(vars,weight);
      else this->fMVA->AddBackgroundTrainingEvent(vars,weight);
#else
      if(type==TQMVA::Signal) this->fDataLoader->AddSignalTrainingEvent(vars,weight);
      else this->fDataLoader->AddBackgroundTrainingEvent(vars,weight);
#endif
      if(makeCounters){
        cnt_train->add(weight);
        cnt_total->add(weight);
      }
      nTrainEvent++;
      sumWeightsTrain += weight;
    } else {
#ifdef LEGACY_INTERFACE_PRE_607
      if(type==TQMVA::Signal) this->fMVA->AddSignalTestEvent(vars,weight);
      else this->fMVA->AddBackgroundTestEvent(vars,weight);
#else
      if(type==TQMVA::Signal) this->fDataLoader->AddSignalTestEvent(vars,weight);
      else this->fDataLoader->AddBackgroundTestEvent(vars,weight);
#endif
      if(makeCounters){
        cnt_test->add(weight);
        cnt_total->add(weight);
      }
      nTestEvent++;
      sumWeightsTest += weight;
    }
  }
#ifndef _DEBUG_
  TQLibrary::restore_stdout();
#endif

  if(this->fVerbose){
    if(nTrainEvent == 0 || nTestEvent == 0 || nEvent == 0){
      TQLibrary::msgStream.endProcessInfo(TQMessageStream::WARN);
    } else {
      TQLibrary::msgStream.endProcessInfo(TQMessageStream::OK);
    } 
    if(nEntries == 0){
      WARNclass("this sample was empty (tree had no entries)");
    } else if(nEvent == 0){
      WARNclass("no events from this sample passed the cut '%s' (from a total of %lld events)!",this->fActiveCut->GetName(),nEntries);
#ifdef _DEBUG_
      DEBUGclass("cut expression is as follows:");
      this->fActiveCut->printActiveCutExpression();
#endif
    } else {
      if(nTrainEvent == 0){
        WARNclass("event selector did not select any training events (from a total of %d selected events)!",nEvent);
      } 
      if(nTestEvent == 0){
        WARNclass("event selector did not select any testing events (from a total of %d selected events)!",nEvent);
      }
    }
    if(this->fVerbose > 1){
      INFO("number of read events: %d training (%.1f weighted), %d test (%.1f weighted)",nTrainEvent,sumWeightsTrain,nTestEvent,sumWeightsTest);
    }
  }

  DEBUGclass("finalizing cut '%s'",fBaseCut->GetName());
  this->fBaseCut->finalize();
  for(size_t i=0; i<observables.size(); ++i){
    DEBUGclass("finalizing variable '%s'",this->fNames[i].Data());
    observables[i]->finalize();
  }

  if(makeCounters){
    TQFolder* counters = s->getFolder(".cutflow+");
    if(counters){
      counters->addObject(cnt_train);
      counters->addObject(cnt_test);
      counters->addObject(cnt_total);
    }
  }
  
  s->returnTreeToken(tok);
  return nEvent;
}

void TQMVA::printListOfSamples(TQMVA::SampleType type){
  // print the list of all samples of the given type (Signal or Background)
  std::vector<TString>* vec = (type == TQMVA::Signal ? &(this->fSigPaths) : &(this->fBkgPaths));
  std::cout << TQStringUtils::makeBoldBlue(this->GetName()) << TQStringUtils::makeBoldWhite(": samples of type '") << TQStringUtils::makeBoldBlue(type == TQMVA::Signal ? "Signal" : "Background") << TQStringUtils::makeBoldWhite("'") << std::endl;
  if(vec->size() < 1){
    std::cout << TQStringUtils::makeBoldRed("<no paths listed>") << std::endl;
    return;
  }
  for(size_t i=0; i<vec->size(); i++){
    TString path(vec->at(i));
    TQStringUtils::ensureTrailingText(path,"/*");
    std::cout << "\t" << TQStringUtils::makeBoldWhite(path) << std::endl;
    TList* l = this->fSampleFolder->getListOfSamples(path);
    if(l && l->GetEntries() > 0){
      TQSampleIterator itr(l,true);
      while(itr.hasNext()){
        std::cout << "\t\t";
        TQSample* s = itr.readNext();
        if(!s) std::cout << TQStringUtils::makeBoldRed("<NULL>");
        else std::cout << s->getPath();
        std::cout << std::endl;
      }
    } else {
      if(l) delete l;
      std::cout << "\t\t" << TQStringUtils::makeBoldRed("<no samples found under this path>" ) << std::endl;
    }
  }
}

TList* TQMVA::getListOfSamples(TQMVA::SampleType type){
  // get the list of all samples of the given type (Signal or Background)
  std::vector<TString>* vec = (type == TQMVA::Signal ? &(this->fSigPaths) : &(this->fBkgPaths));
  TList* retval = new TList();
  for(size_t i=0; i<vec->size(); i++){
    TString path(vec->at(i));
    TQStringUtils::ensureTrailingText(path,"/*");
    TQSampleIterator itr(this->fSampleFolder->getListOfSamples(path),true);
    while(itr.hasNext()) {
      TQSample* s = itr.readNext();
      if (s && !s->hasSubSamples()) retval->Add(s);
    }
  }
  return retval;
}

void TQMVA::setVerbose(int verbose){
  // control verbosity
  this->fVerbose = verbose;
}

TQTaggable* TQMVA::getAliases(){
  // retrieve a pointer to the alias container
  return this->fAliases;
}

void TQMVA::setAliases(TQTaggable* aliases){
  // set the alias container
  this->fAliases = aliases;
}

 TQMVA.cxx:1
 TQMVA.cxx:2
 TQMVA.cxx:3
 TQMVA.cxx:4
 TQMVA.cxx:5
 TQMVA.cxx:6
 TQMVA.cxx:7
 TQMVA.cxx:8
 TQMVA.cxx:9
 TQMVA.cxx:10
 TQMVA.cxx:11
 TQMVA.cxx:12
 TQMVA.cxx:13
 TQMVA.cxx:14
 TQMVA.cxx:15
 TQMVA.cxx:16
 TQMVA.cxx:17
 TQMVA.cxx:18
 TQMVA.cxx:19
 TQMVA.cxx:20
 TQMVA.cxx:21
 TQMVA.cxx:22
 TQMVA.cxx:23
 TQMVA.cxx:24
 TQMVA.cxx:25
 TQMVA.cxx:26
 TQMVA.cxx:27
 TQMVA.cxx:28
 TQMVA.cxx:29
 TQMVA.cxx:30
 TQMVA.cxx:31
 TQMVA.cxx:32
 TQMVA.cxx:33
 TQMVA.cxx:34
 TQMVA.cxx:35
 TQMVA.cxx:36
 TQMVA.cxx:37
 TQMVA.cxx:38
 TQMVA.cxx:39
 TQMVA.cxx:40
 TQMVA.cxx:41
 TQMVA.cxx:42
 TQMVA.cxx:43
 TQMVA.cxx:44
 TQMVA.cxx:45
 TQMVA.cxx:46
 TQMVA.cxx:47
 TQMVA.cxx:48
 TQMVA.cxx:49
 TQMVA.cxx:50
 TQMVA.cxx:51
 TQMVA.cxx:52
 TQMVA.cxx:53
 TQMVA.cxx:54
 TQMVA.cxx:55
 TQMVA.cxx:56
 TQMVA.cxx:57
 TQMVA.cxx:58
 TQMVA.cxx:59
 TQMVA.cxx:60
 TQMVA.cxx:61
 TQMVA.cxx:62
 TQMVA.cxx:63
 TQMVA.cxx:64
 TQMVA.cxx:65
 TQMVA.cxx:66
 TQMVA.cxx:67
 TQMVA.cxx:68
 TQMVA.cxx:69
 TQMVA.cxx:70
 TQMVA.cxx:71
 TQMVA.cxx:72
 TQMVA.cxx:73
 TQMVA.cxx:74
 TQMVA.cxx:75
 TQMVA.cxx:76
 TQMVA.cxx:77
 TQMVA.cxx:78
 TQMVA.cxx:79
 TQMVA.cxx:80
 TQMVA.cxx:81
 TQMVA.cxx:82
 TQMVA.cxx:83
 TQMVA.cxx:84
 TQMVA.cxx:85
 TQMVA.cxx:86
 TQMVA.cxx:87
 TQMVA.cxx:88
 TQMVA.cxx:89
 TQMVA.cxx:90
 TQMVA.cxx:91
 TQMVA.cxx:92
 TQMVA.cxx:93
 TQMVA.cxx:94
 TQMVA.cxx:95
 TQMVA.cxx:96
 TQMVA.cxx:97
 TQMVA.cxx:98
 TQMVA.cxx:99
 TQMVA.cxx:100
 TQMVA.cxx:101
 TQMVA.cxx:102
 TQMVA.cxx:103
 TQMVA.cxx:104
 TQMVA.cxx:105
 TQMVA.cxx:106
 TQMVA.cxx:107
 TQMVA.cxx:108
 TQMVA.cxx:109
 TQMVA.cxx:110
 TQMVA.cxx:111
 TQMVA.cxx:112
 TQMVA.cxx:113
 TQMVA.cxx:114
 TQMVA.cxx:115
 TQMVA.cxx:116
 TQMVA.cxx:117
 TQMVA.cxx:118
 TQMVA.cxx:119
 TQMVA.cxx:120
 TQMVA.cxx:121
 TQMVA.cxx:122
 TQMVA.cxx:123
 TQMVA.cxx:124
 TQMVA.cxx:125
 TQMVA.cxx:126
 TQMVA.cxx:127
 TQMVA.cxx:128
 TQMVA.cxx:129
 TQMVA.cxx:130
 TQMVA.cxx:131
 TQMVA.cxx:132
 TQMVA.cxx:133
 TQMVA.cxx:134
 TQMVA.cxx:135
 TQMVA.cxx:136
 TQMVA.cxx:137
 TQMVA.cxx:138
 TQMVA.cxx:139
 TQMVA.cxx:140
 TQMVA.cxx:141
 TQMVA.cxx:142
 TQMVA.cxx:143
 TQMVA.cxx:144
 TQMVA.cxx:145
 TQMVA.cxx:146
 TQMVA.cxx:147
 TQMVA.cxx:148
 TQMVA.cxx:149
 TQMVA.cxx:150
 TQMVA.cxx:151
 TQMVA.cxx:152
 TQMVA.cxx:153
 TQMVA.cxx:154
 TQMVA.cxx:155
 TQMVA.cxx:156
 TQMVA.cxx:157
 TQMVA.cxx:158
 TQMVA.cxx:159
 TQMVA.cxx:160
 TQMVA.cxx:161
 TQMVA.cxx:162
 TQMVA.cxx:163
 TQMVA.cxx:164
 TQMVA.cxx:165
 TQMVA.cxx:166
 TQMVA.cxx:167
 TQMVA.cxx:168
 TQMVA.cxx:169
 TQMVA.cxx:170
 TQMVA.cxx:171
 TQMVA.cxx:172
 TQMVA.cxx:173
 TQMVA.cxx:174
 TQMVA.cxx:175
 TQMVA.cxx:176
 TQMVA.cxx:177
 TQMVA.cxx:178
 TQMVA.cxx:179
 TQMVA.cxx:180
 TQMVA.cxx:181
 TQMVA.cxx:182
 TQMVA.cxx:183
 TQMVA.cxx:184
 TQMVA.cxx:185
 TQMVA.cxx:186
 TQMVA.cxx:187
 TQMVA.cxx:188
 TQMVA.cxx:189
 TQMVA.cxx:190
 TQMVA.cxx:191
 TQMVA.cxx:192
 TQMVA.cxx:193
 TQMVA.cxx:194
 TQMVA.cxx:195
 TQMVA.cxx:196
 TQMVA.cxx:197
 TQMVA.cxx:198
 TQMVA.cxx:199
 TQMVA.cxx:200
 TQMVA.cxx:201
 TQMVA.cxx:202
 TQMVA.cxx:203
 TQMVA.cxx:204
 TQMVA.cxx:205
 TQMVA.cxx:206
 TQMVA.cxx:207
 TQMVA.cxx:208
 TQMVA.cxx:209
 TQMVA.cxx:210
 TQMVA.cxx:211
 TQMVA.cxx:212
 TQMVA.cxx:213
 TQMVA.cxx:214
 TQMVA.cxx:215
 TQMVA.cxx:216
 TQMVA.cxx:217
 TQMVA.cxx:218
 TQMVA.cxx:219
 TQMVA.cxx:220
 TQMVA.cxx:221
 TQMVA.cxx:222
 TQMVA.cxx:223
 TQMVA.cxx:224
 TQMVA.cxx:225
 TQMVA.cxx:226
 TQMVA.cxx:227
 TQMVA.cxx:228
 TQMVA.cxx:229
 TQMVA.cxx:230
 TQMVA.cxx:231
 TQMVA.cxx:232
 TQMVA.cxx:233
 TQMVA.cxx:234
 TQMVA.cxx:235
 TQMVA.cxx:236
 TQMVA.cxx:237
 TQMVA.cxx:238
 TQMVA.cxx:239
 TQMVA.cxx:240
 TQMVA.cxx:241
 TQMVA.cxx:242
 TQMVA.cxx:243
 TQMVA.cxx:244
 TQMVA.cxx:245
 TQMVA.cxx:246
 TQMVA.cxx:247
 TQMVA.cxx:248
 TQMVA.cxx:249
 TQMVA.cxx:250
 TQMVA.cxx:251
 TQMVA.cxx:252
 TQMVA.cxx:253
 TQMVA.cxx:254
 TQMVA.cxx:255
 TQMVA.cxx:256
 TQMVA.cxx:257
 TQMVA.cxx:258
 TQMVA.cxx:259
 TQMVA.cxx:260
 TQMVA.cxx:261
 TQMVA.cxx:262
 TQMVA.cxx:263
 TQMVA.cxx:264
 TQMVA.cxx:265
 TQMVA.cxx:266
 TQMVA.cxx:267
 TQMVA.cxx:268
 TQMVA.cxx:269
 TQMVA.cxx:270
 TQMVA.cxx:271
 TQMVA.cxx:272
 TQMVA.cxx:273
 TQMVA.cxx:274
 TQMVA.cxx:275
 TQMVA.cxx:276
 TQMVA.cxx:277
 TQMVA.cxx:278
 TQMVA.cxx:279
 TQMVA.cxx:280
 TQMVA.cxx:281
 TQMVA.cxx:282
 TQMVA.cxx:283
 TQMVA.cxx:284
 TQMVA.cxx:285
 TQMVA.cxx:286
 TQMVA.cxx:287
 TQMVA.cxx:288
 TQMVA.cxx:289
 TQMVA.cxx:290
 TQMVA.cxx:291
 TQMVA.cxx:292
 TQMVA.cxx:293
 TQMVA.cxx:294
 TQMVA.cxx:295
 TQMVA.cxx:296
 TQMVA.cxx:297
 TQMVA.cxx:298
 TQMVA.cxx:299
 TQMVA.cxx:300
 TQMVA.cxx:301
 TQMVA.cxx:302
 TQMVA.cxx:303
 TQMVA.cxx:304
 TQMVA.cxx:305
 TQMVA.cxx:306
 TQMVA.cxx:307
 TQMVA.cxx:308
 TQMVA.cxx:309
 TQMVA.cxx:310
 TQMVA.cxx:311
 TQMVA.cxx:312
 TQMVA.cxx:313
 TQMVA.cxx:314
 TQMVA.cxx:315
 TQMVA.cxx:316
 TQMVA.cxx:317
 TQMVA.cxx:318
 TQMVA.cxx:319
 TQMVA.cxx:320
 TQMVA.cxx:321
 TQMVA.cxx:322
 TQMVA.cxx:323
 TQMVA.cxx:324
 TQMVA.cxx:325
 TQMVA.cxx:326
 TQMVA.cxx:327
 TQMVA.cxx:328
 TQMVA.cxx:329
 TQMVA.cxx:330
 TQMVA.cxx:331
 TQMVA.cxx:332
 TQMVA.cxx:333
 TQMVA.cxx:334
 TQMVA.cxx:335
 TQMVA.cxx:336
 TQMVA.cxx:337
 TQMVA.cxx:338
 TQMVA.cxx:339
 TQMVA.cxx:340
 TQMVA.cxx:341
 TQMVA.cxx:342
 TQMVA.cxx:343
 TQMVA.cxx:344
 TQMVA.cxx:345
 TQMVA.cxx:346
 TQMVA.cxx:347
 TQMVA.cxx:348
 TQMVA.cxx:349
 TQMVA.cxx:350
 TQMVA.cxx:351
 TQMVA.cxx:352
 TQMVA.cxx:353
 TQMVA.cxx:354
 TQMVA.cxx:355
 TQMVA.cxx:356
 TQMVA.cxx:357
 TQMVA.cxx:358
 TQMVA.cxx:359
 TQMVA.cxx:360
 TQMVA.cxx:361
 TQMVA.cxx:362
 TQMVA.cxx:363
 TQMVA.cxx:364
 TQMVA.cxx:365
 TQMVA.cxx:366
 TQMVA.cxx:367
 TQMVA.cxx:368
 TQMVA.cxx:369
 TQMVA.cxx:370
 TQMVA.cxx:371
 TQMVA.cxx:372
 TQMVA.cxx:373
 TQMVA.cxx:374
 TQMVA.cxx:375
 TQMVA.cxx:376
 TQMVA.cxx:377
 TQMVA.cxx:378
 TQMVA.cxx:379
 TQMVA.cxx:380
 TQMVA.cxx:381
 TQMVA.cxx:382
 TQMVA.cxx:383
 TQMVA.cxx:384
 TQMVA.cxx:385
 TQMVA.cxx:386
 TQMVA.cxx:387
 TQMVA.cxx:388
 TQMVA.cxx:389
 TQMVA.cxx:390
 TQMVA.cxx:391
 TQMVA.cxx:392
 TQMVA.cxx:393
 TQMVA.cxx:394
 TQMVA.cxx:395
 TQMVA.cxx:396
 TQMVA.cxx:397
 TQMVA.cxx:398
 TQMVA.cxx:399
 TQMVA.cxx:400
 TQMVA.cxx:401
 TQMVA.cxx:402
 TQMVA.cxx:403
 TQMVA.cxx:404
 TQMVA.cxx:405
 TQMVA.cxx:406
 TQMVA.cxx:407
 TQMVA.cxx:408
 TQMVA.cxx:409
 TQMVA.cxx:410
 TQMVA.cxx:411
 TQMVA.cxx:412
 TQMVA.cxx:413
 TQMVA.cxx:414
 TQMVA.cxx:415
 TQMVA.cxx:416
 TQMVA.cxx:417
 TQMVA.cxx:418
 TQMVA.cxx:419
 TQMVA.cxx:420
 TQMVA.cxx:421
 TQMVA.cxx:422
 TQMVA.cxx:423
 TQMVA.cxx:424
 TQMVA.cxx:425
 TQMVA.cxx:426
 TQMVA.cxx:427
 TQMVA.cxx:428
 TQMVA.cxx:429
 TQMVA.cxx:430
 TQMVA.cxx:431
 TQMVA.cxx:432
 TQMVA.cxx:433
 TQMVA.cxx:434
 TQMVA.cxx:435
 TQMVA.cxx:436
 TQMVA.cxx:437
 TQMVA.cxx:438
 TQMVA.cxx:439
 TQMVA.cxx:440
 TQMVA.cxx:441
 TQMVA.cxx:442
 TQMVA.cxx:443
 TQMVA.cxx:444
 TQMVA.cxx:445
 TQMVA.cxx:446
 TQMVA.cxx:447
 TQMVA.cxx:448
 TQMVA.cxx:449
 TQMVA.cxx:450
 TQMVA.cxx:451
 TQMVA.cxx:452
 TQMVA.cxx:453
 TQMVA.cxx:454
 TQMVA.cxx:455
 TQMVA.cxx:456
 TQMVA.cxx:457
 TQMVA.cxx:458
 TQMVA.cxx:459
 TQMVA.cxx:460
 TQMVA.cxx:461
 TQMVA.cxx:462
 TQMVA.cxx:463
 TQMVA.cxx:464
 TQMVA.cxx:465
 TQMVA.cxx:466
 TQMVA.cxx:467
 TQMVA.cxx:468
 TQMVA.cxx:469
 TQMVA.cxx:470
 TQMVA.cxx:471
 TQMVA.cxx:472
 TQMVA.cxx:473
 TQMVA.cxx:474
 TQMVA.cxx:475
 TQMVA.cxx:476
 TQMVA.cxx:477
 TQMVA.cxx:478
 TQMVA.cxx:479
 TQMVA.cxx:480
 TQMVA.cxx:481
 TQMVA.cxx:482
 TQMVA.cxx:483
 TQMVA.cxx:484
 TQMVA.cxx:485
 TQMVA.cxx:486
 TQMVA.cxx:487
 TQMVA.cxx:488
 TQMVA.cxx:489
 TQMVA.cxx:490
 TQMVA.cxx:491
 TQMVA.cxx:492
 TQMVA.cxx:493
 TQMVA.cxx:494
 TQMVA.cxx:495
 TQMVA.cxx:496
 TQMVA.cxx:497
 TQMVA.cxx:498
 TQMVA.cxx:499
 TQMVA.cxx:500
 TQMVA.cxx:501
 TQMVA.cxx:502
 TQMVA.cxx:503
 TQMVA.cxx:504
 TQMVA.cxx:505
 TQMVA.cxx:506
 TQMVA.cxx:507
 TQMVA.cxx:508
 TQMVA.cxx:509
 TQMVA.cxx:510
 TQMVA.cxx:511
 TQMVA.cxx:512
 TQMVA.cxx:513
 TQMVA.cxx:514
 TQMVA.cxx:515
 TQMVA.cxx:516
 TQMVA.cxx:517
 TQMVA.cxx:518
 TQMVA.cxx:519
 TQMVA.cxx:520
 TQMVA.cxx:521
 TQMVA.cxx:522
 TQMVA.cxx:523
 TQMVA.cxx:524
 TQMVA.cxx:525
 TQMVA.cxx:526
 TQMVA.cxx:527
 TQMVA.cxx:528
 TQMVA.cxx:529
 TQMVA.cxx:530
 TQMVA.cxx:531
 TQMVA.cxx:532
 TQMVA.cxx:533
 TQMVA.cxx:534
 TQMVA.cxx:535
 TQMVA.cxx:536
 TQMVA.cxx:537
 TQMVA.cxx:538
 TQMVA.cxx:539
 TQMVA.cxx:540
 TQMVA.cxx:541
 TQMVA.cxx:542
 TQMVA.cxx:543
 TQMVA.cxx:544
 TQMVA.cxx:545
 TQMVA.cxx:546
 TQMVA.cxx:547
 TQMVA.cxx:548
 TQMVA.cxx:549
 TQMVA.cxx:550
 TQMVA.cxx:551
 TQMVA.cxx:552
 TQMVA.cxx:553
 TQMVA.cxx:554
 TQMVA.cxx:555
 TQMVA.cxx:556
 TQMVA.cxx:557
 TQMVA.cxx:558
 TQMVA.cxx:559
 TQMVA.cxx:560
 TQMVA.cxx:561
 TQMVA.cxx:562
 TQMVA.cxx:563
 TQMVA.cxx:564
 TQMVA.cxx:565
 TQMVA.cxx:566
 TQMVA.cxx:567
 TQMVA.cxx:568
 TQMVA.cxx:569
 TQMVA.cxx:570
 TQMVA.cxx:571
 TQMVA.cxx:572
 TQMVA.cxx:573
 TQMVA.cxx:574
 TQMVA.cxx:575
 TQMVA.cxx:576
 TQMVA.cxx:577
 TQMVA.cxx:578
 TQMVA.cxx:579
 TQMVA.cxx:580
 TQMVA.cxx:581
 TQMVA.cxx:582
 TQMVA.cxx:583
 TQMVA.cxx:584
 TQMVA.cxx:585
 TQMVA.cxx:586
 TQMVA.cxx:587
 TQMVA.cxx:588
 TQMVA.cxx:589
 TQMVA.cxx:590
 TQMVA.cxx:591
 TQMVA.cxx:592
 TQMVA.cxx:593
 TQMVA.cxx:594
 TQMVA.cxx:595
 TQMVA.cxx:596
 TQMVA.cxx:597
 TQMVA.cxx:598
 TQMVA.cxx:599
 TQMVA.cxx:600
 TQMVA.cxx:601
 TQMVA.cxx:602
 TQMVA.cxx:603
 TQMVA.cxx:604
 TQMVA.cxx:605
 TQMVA.cxx:606
 TQMVA.cxx:607
 TQMVA.cxx:608
 TQMVA.cxx:609
 TQMVA.cxx:610
 TQMVA.cxx:611
 TQMVA.cxx:612
 TQMVA.cxx:613
 TQMVA.cxx:614
 TQMVA.cxx:615
 TQMVA.cxx:616
 TQMVA.cxx:617
 TQMVA.cxx:618
 TQMVA.cxx:619
 TQMVA.cxx:620
 TQMVA.cxx:621
 TQMVA.cxx:622
 TQMVA.cxx:623
 TQMVA.cxx:624
 TQMVA.cxx:625
 TQMVA.cxx:626
 TQMVA.cxx:627
 TQMVA.cxx:628
 TQMVA.cxx:629
 TQMVA.cxx:630
 TQMVA.cxx:631
 TQMVA.cxx:632
 TQMVA.cxx:633
 TQMVA.cxx:634
 TQMVA.cxx:635
 TQMVA.cxx:636
 TQMVA.cxx:637
 TQMVA.cxx:638
 TQMVA.cxx:639
 TQMVA.cxx:640
 TQMVA.cxx:641
 TQMVA.cxx:642
 TQMVA.cxx:643
 TQMVA.cxx:644
 TQMVA.cxx:645
 TQMVA.cxx:646
 TQMVA.cxx:647
 TQMVA.cxx:648
 TQMVA.cxx:649
 TQMVA.cxx:650
 TQMVA.cxx:651
 TQMVA.cxx:652
 TQMVA.cxx:653
 TQMVA.cxx:654
 TQMVA.cxx:655
 TQMVA.cxx:656
 TQMVA.cxx:657
 TQMVA.cxx:658
 TQMVA.cxx:659
 TQMVA.cxx:660
 TQMVA.cxx:661
 TQMVA.cxx:662
 TQMVA.cxx:663
 TQMVA.cxx:664
 TQMVA.cxx:665
 TQMVA.cxx:666
 TQMVA.cxx:667
 TQMVA.cxx:668
 TQMVA.cxx:669
 TQMVA.cxx:670
 TQMVA.cxx:671
 TQMVA.cxx:672
 TQMVA.cxx:673
 TQMVA.cxx:674
 TQMVA.cxx:675
 TQMVA.cxx:676
 TQMVA.cxx:677
 TQMVA.cxx:678
 TQMVA.cxx:679
 TQMVA.cxx:680
 TQMVA.cxx:681